From 623952ad31a13cdb8b4ea486517684eedc9b4a90 Mon Sep 17 00:00:00 2001 From: Julien Michel <julien.michel@c-s.fr> Date: Wed, 7 Mar 2007 13:27:33 +0000 Subject: [PATCH] Ajout de OSSIM dans l'arborescence. --- Utilities/CMakeLists.txt | 2 +- Utilities/OSSIM/.CMakeLists.txt.swp | Bin 0 -> 12288 bytes Utilities/OSSIM/CMakeLists.txt | 16 + Utilities/OSSIM/ossimConfig.h.in | 125 + Utilities/OSSIM/ossim_core/.cvsignore | 2 + Utilities/OSSIM/ossim_core/CMakeLists.txt | 72 + .../OSSIM/ossim_core/base/CMakeLists.txt | 6 + .../OSSIM/ossim_core/base/common/.cvsignore | 3 + .../ossim_core/base/common/events/.cvsignore | 1 + .../ossimConnectableDisplayListener.cpp | 179 + .../events/ossimConnectableDisplayListener.h | 109 + .../events/ossimConnectableObjectListener.cpp | 102 + .../events/ossimConnectableObjectListener.h | 75 + .../common/events/ossimConnectionEvent.cpp | 127 + .../base/common/events/ossimConnectionEvent.h | 76 + .../common/events/ossimContainerEvent.cpp | 38 + .../base/common/events/ossimContainerEvent.h | 41 + .../events/ossimDisplayEventListener.cpp | 62 + .../common/events/ossimDisplayEventListener.h | 43 + .../common/events/ossimDisplayListEvent.cpp | 44 + .../common/events/ossimDisplayListEvent.h | 32 + .../events/ossimDisplayRefreshEvent.cpp | 2 + .../common/events/ossimDisplayRefreshEvent.h | 16 + .../events/ossimElevationManagerEvent.cpp | 3 + .../events/ossimElevationManagerEvent.h | 28 + .../ossimElevationManagerEventListener.cpp | 31 + .../ossimElevationManagerEventListener.h | 18 + .../base/common/events/ossimEvent.cpp | 86 + .../base/common/events/ossimEvent.h | 64 + .../base/common/events/ossimEventIds.h | 86 + .../common/events/ossimImageAoiListener.cpp | 50 + .../common/events/ossimImageAoiListener.h | 43 + .../common/events/ossimImageGeometryEvent.cpp | 29 + .../common/events/ossimImageGeometryEvent.h | 82 + .../ossimImageGeometryEventListener.cpp | 45 + .../events/ossimImageGeometryEventListener.h | 43 + .../common/events/ossimImagePolygonEvent.h | 65 + .../common/events/ossimImageRectangleEvent.h | 57 + .../base/common/events/ossimListener.cpp | 51 + .../base/common/events/ossimListener.h | 51 + .../common/events/ossimListenerManager.cpp | 155 + .../base/common/events/ossimListenerManager.h | 138 + .../base/common/events/ossimMouseEvent.cpp | 27 + .../base/common/events/ossimMouseEvent.h | 97 + .../base/common/events/ossimMouseListener.cpp | 54 + .../base/common/events/ossimMouseListener.h | 44 + .../events/ossimObjectDestructingEvent.cpp | 3 + .../events/ossimObjectDestructingEvent.h | 18 + .../base/common/events/ossimObjectEvents.h | 10 + .../common/events/ossimProcessListener.cpp | 44 + .../base/common/events/ossimProcessListener.h | 28 + .../events/ossimProcessProgressEvent.cpp | 68 + .../common/events/ossimProcessProgressEvent.h | 51 + .../base/common/events/ossimPropertyEvent.h | 14 + .../base/common/events/ossimROIEvent.cpp | 124 + .../base/common/events/ossimROIEvent.h | 74 + .../common/events/ossimROIEventListener.cpp | 49 + .../common/events/ossimROIEventListener.h | 22 + .../base/common/events/ossimRefreshEvent.cpp | 27 + .../base/common/events/ossimRefreshEvent.h | 48 + .../common/events/ossimStateChangedEvent.cpp | 38 + .../common/events/ossimStateChangedEvent.h | 31 + .../base/common/events/ossimViewEvent.cpp | 27 + .../base/common/events/ossimViewEvent.h | 169 + .../base/common/events/ossimViewListener.cpp | 59 + .../base/common/events/ossimViewListener.h | 51 + .../base/common/ossimApplicationUsage.cpp | 206 + .../base/common/ossimApplicationUsage.h | 85 + .../base/common/ossimArgumentParser.cpp | 468 ++ .../base/common/ossimArgumentParser.h | 187 + .../ossim_core/base/common/ossimCommon.cpp | 325 + .../ossim_core/base/common/ossimCommon.h | 282 + .../base/common/ossimConnectableContainer.cpp | 772 +++ .../base/common/ossimConnectableContainer.h | 184 + .../ossimConnectableContainerInterface.cpp | 27 + .../ossimConnectableContainerInterface.h | 131 + .../base/common/ossimConnectableObject.cpp | 1903 ++++++ .../base/common/ossimConnectableObject.h | 470 ++ .../ossim_core/base/common/ossimConstants.h | 514 ++ .../ossim_core/base/common/ossimCplUtil.cpp | 297 + .../ossim_core/base/common/ossimCplUtil.h | 58 + .../base/common/ossimCustomEditorWindow.cpp | 26 + .../base/common/ossimCustomEditorWindow.h | 71 + .../base/common/ossimDataObject.cpp | 154 + .../ossim_core/base/common/ossimDataObject.h | 126 + .../ossim_core/base/common/ossimDate.cpp | 536 ++ .../OSSIM/ossim_core/base/common/ossimDate.h | 241 + .../base/common/ossimDisplayInterface.cpp | 31 + .../base/common/ossimDisplayInterface.h | 40 + .../base/common/ossimErrorCodes.cpp | 318 + .../ossim_core/base/common/ossimErrorCodes.h | 102 + .../base/common/ossimErrorStatusInterface.cpp | 79 + .../base/common/ossimErrorStatusInterface.h | 84 + .../base/common/ossimFactoryBaseTemplate.cpp | 34 + .../base/common/ossimFactoryBaseTemplate.h | 128 + .../base/common/ossimFontInformation.cpp | 221 + .../base/common/ossimFontInformation.h | 163 + .../ossim_core/base/common/ossimGzStream.cpp | 280 + .../ossim_core/base/common/ossimGzStream.h | 163 + .../base/common/ossimHistogramSource.cpp | 120 + .../base/common/ossimHistogramSource.h | 58 + .../OSSIM/ossim_core/base/common/ossimId.cpp | 3 + .../OSSIM/ossim_core/base/common/ossimId.h | 109 + .../ossim_core/base/common/ossimIdManager.cpp | 64 + .../ossim_core/base/common/ossimIdManager.h | 25 + .../ossim_core/base/common/ossimIoStream.cpp | 169 + .../ossim_core/base/common/ossimIoStream.h | 342 + .../base/common/ossimKeywordNames.cpp | 173 + .../base/common/ossimKeywordNames.h | 181 + .../base/common/ossimLeastSquaresBilin.cpp | 151 + .../base/common/ossimLeastSquaresBilin.h | 146 + .../ossim_core/base/common/ossimMutex.cpp | 54 + .../OSSIM/ossim_core/base/common/ossimMutex.h | 77 + .../base/common/ossimNBandLutDataObject.cpp | 342 + .../base/common/ossimNBandLutDataObject.h | 456 ++ .../ossim_core/base/common/ossimObject.cpp | 117 + .../ossim_core/base/common/ossimObject.h | 88 + .../base/common/ossimOutputSource.cpp | 15 + .../base/common/ossimOutputSource.h | 107 + .../OSSIM/ossim_core/base/common/ossimPool.h | 151 + .../ossim_core/base/common/ossimPoolObject.h | 49 + .../base/common/ossimPreferences.cpp | 241 + .../ossim_core/base/common/ossimPreferences.h | 116 + .../base/common/ossimProcessInterface.cpp | 143 + .../base/common/ossimProcessInterface.h | 88 + .../base/common/ossimPropertyInterface.cpp | 77 + .../base/common/ossimPropertyInterface.h | 40 + .../base/common/ossimProtocolStream.h | 32 + .../base/common/ossimQuadrilateralMap.cpp | 95 + .../base/common/ossimQuadrilateralMap.h | 55 + .../common/ossimRectilinearDataObject.cpp | 312 + .../base/common/ossimRectilinearDataObject.h | 156 + .../ossim_core/base/common/ossimRefPtr.h | 88 + .../base/common/ossimReferenced.cpp | 14 + .../ossim_core/base/common/ossimReferenced.h | 59 + .../base/common/ossimRgbLutDataObject.cpp | 279 + .../base/common/ossimRgbLutDataObject.h | 99 + .../ossim_core/base/common/ossimRtti.cpp | 134 + .../OSSIM/ossim_core/base/common/ossimRtti.h | 509 ++ .../ossim_core/base/common/ossimScopedLock.h | 40 + .../ossim_core/base/common/ossimSource.cpp | 167 + .../ossim_core/base/common/ossimSource.h | 83 + .../base/common/ossimStdOutProgress.cpp | 58 + .../base/common/ossimStdOutProgress.h | 33 + .../base/common/ossimStreamBase.cpp | 3 + .../ossim_core/base/common/ossimStreamBase.h | 29 + .../ossim_core/base/common/ossimTrace.cpp | 40 + .../OSSIM/ossim_core/base/common/ossimTrace.h | 72 + .../base/common/ossimTraceManager.cpp | 105 + .../base/common/ossimTraceManager.h | 69 + .../base/common/ossimViewController.cpp | 173 + .../base/common/ossimViewController.h | 65 + .../base/common/ossimViewInterface.cpp | 22 + .../base/common/ossimViewInterface.h | 59 + .../OSSIM/ossim_core/base/context/.cvsignore | 2 + .../base/context/ossimErrorContext.h | 31 + .../base/context/ossimNotifyContext.cpp | 403 ++ .../base/context/ossimNotifyContext.h | 119 + .../ossim_core/base/data_types/.cvsignore | 1 + .../base/data_types/color_space/.cvsignore | 1 + .../data_types/color_space/ossimCmyVector.cpp | 41 + .../data_types/color_space/ossimCmyVector.h | 68 + .../data_types/color_space/ossimHsiVector.cpp | 97 + .../data_types/color_space/ossimHsiVector.h | 84 + .../data_types/color_space/ossimHsvVector.cpp | 107 + .../data_types/color_space/ossimHsvVector.h | 86 + .../color_space/ossimJpegYCbCrVector.cpp | 37 + .../color_space/ossimJpegYCbCrVector.h | 84 + .../color_space/ossimNormRgbVector.cpp | 183 + .../color_space/ossimNormRgbVector.h | 109 + .../data_types/color_space/ossimRgbVector.cpp | 296 + .../data_types/color_space/ossimRgbVector.h | 123 + .../base/data_types/datum/.cvsignore | 1 + .../ossim_core/base/data_types/datum/datum.h | 528 ++ .../base/data_types/datum/ossimDatum.cpp | 124 + .../base/data_types/datum/ossimDatum.h | 160 + .../data_types/datum/ossimNadconGridDatum.cpp | 128 + .../data_types/datum/ossimNadconGridDatum.h | 44 + .../data_types/datum/ossimNadconGridFile.cpp | 100 + .../data_types/datum/ossimNadconGridFile.h | 54 + .../datum/ossimNadconGridHeader.cpp | 60 + .../data_types/datum/ossimNadconGridHeader.h | 89 + .../data_types/datum/ossimNadconNarDatum.cpp | 66 + .../data_types/datum/ossimNadconNarDatum.h | 21 + .../data_types/datum/ossimNadconNasDatum.cpp | 106 + .../data_types/datum/ossimNadconNasDatum.h | 19 + .../data_types/datum/ossimSevenParamDatum.cpp | 172 + .../data_types/datum/ossimSevenParamDatum.h | 91 + .../data_types/datum/ossimThreeParamDatum.cpp | 138 + .../data_types/datum/ossimThreeParamDatum.h | 81 + .../base/data_types/datum/ossimWgs72Datum.cpp | 223 + .../base/data_types/datum/ossimWgs72Datum.h | 45 + .../base/data_types/datum/ossimWgs84Datum.cpp | 79 + .../base/data_types/datum/ossimWgs84Datum.h | 48 + .../base/data_types/ellipse/.cvsignore | 1 + .../base/data_types/ellipse/ellips.dat | 23 + .../base/data_types/ellipse/ossimEllipse.c | 663 ++ .../base/data_types/ellipse/ossimEllipse.h | 308 + .../base/data_types/ellipse/ossimEllipse.hpp | 28 + .../data_types/ellipse/ossimEllipsoid.cpp | 453 ++ .../base/data_types/ellipse/ossimEllipsoid.h | 159 + .../base/data_types/geoid/.cvsignore | 3 + .../base/data_types/geoid/ossimGeoid.cpp | 42 + .../base/data_types/geoid/ossimGeoid.h | 61 + .../base/data_types/geoid/ossimGeoidEgm96.cpp | 328 + .../base/data_types/geoid/ossimGeoidEgm96.h | 78 + .../data_types/geoid/ossimGeoidManager.cpp | 239 + .../base/data_types/geoid/ossimGeoidManager.h | 101 + .../base/data_types/geoid/ossimGeoidNgs.cpp | 272 + .../base/data_types/geoid/ossimGeoidNgs.h | 70 + .../data_types/geoid/ossimGeoidNgsHeader.cpp | 173 + .../data_types/geoid/ossimGeoidNgsHeader.h | 97 + .../base/data_types/ossimActiveEdgeTable.cpp | 227 + .../base/data_types/ossimActiveEdgeTable.h | 146 + .../ossim_core/base/data_types/ossimAxes.h | 110 + .../base/data_types/ossimColumnVector3d.h | 258 + .../base/data_types/ossimColumnVector4d.h | 213 + .../base/data_types/ossimDblGrid.cpp | 1127 ++++ .../ossim_core/base/data_types/ossimDblGrid.h | 214 + .../base/data_types/ossimDirectory.cpp | 275 + .../base/data_types/ossimDirectory.h | 83 + .../base/data_types/ossimDirectoryData.cpp | 168 + .../base/data_types/ossimDirectoryData.h | 57 + .../base/data_types/ossimDirectoryTree.cpp | 169 + .../base/data_types/ossimDirectoryTree.h | 87 + .../ossim_core/base/data_types/ossimDms.cpp | 941 +++ .../ossim_core/base/data_types/ossimDms.h | 209 + .../ossim_core/base/data_types/ossimDpt.cpp | 232 + .../ossim_core/base/data_types/ossimDpt.h | 153 + .../ossim_core/base/data_types/ossimDpt3d.cpp | 26 + .../ossim_core/base/data_types/ossimDpt3d.h | 113 + .../ossim_core/base/data_types/ossimDrect.cpp | 736 +++ .../ossim_core/base/data_types/ossimDrect.h | 766 +++ .../base/data_types/ossimEcefPoint.cpp | 89 + .../base/data_types/ossimEcefPoint.h | 192 + .../base/data_types/ossimEcefRay.cpp | 108 + .../ossim_core/base/data_types/ossimEcefRay.h | 198 + .../base/data_types/ossimEcefVector.h | 300 + .../base/data_types/ossimFilename.cpp | 665 ++ .../base/data_types/ossimFilename.h | 179 + .../ossim_core/base/data_types/ossimFpt.cpp | 107 + .../ossim_core/base/data_types/ossimFpt.h | 100 + .../ossim_core/base/data_types/ossimFpt3d.cpp | 59 + .../ossim_core/base/data_types/ossimFpt3d.h | 63 + .../base/data_types/ossimGeoPolygon.cpp | 356 ++ .../base/data_types/ossimGeoPolygon.h | 170 + .../ossim_core/base/data_types/ossimGeocent.c | 384 ++ .../ossim_core/base/data_types/ossimGeocent.h | 162 + .../base/data_types/ossimGeoref.cpp | 375 ++ .../ossim_core/base/data_types/ossimGeoref.h | 70 + .../ossim_core/base/data_types/ossimGpt.cpp | 341 + .../ossim_core/base/data_types/ossimGpt.h | 259 + .../ossim_core/base/data_types/ossimGrect.cpp | 234 + .../ossim_core/base/data_types/ossimGrect.h | 329 + .../base/data_types/ossimHexString.cpp | 248 + .../base/data_types/ossimHexString.h | 152 + .../base/data_types/ossimHistogram.cpp | 1378 ++++ .../base/data_types/ossimHistogram.h | 206 + .../ossim_core/base/data_types/ossimIpt.cpp | 204 + .../ossim_core/base/data_types/ossimIpt.h | 142 + .../ossim_core/base/data_types/ossimIrect.cpp | 451 ++ .../ossim_core/base/data_types/ossimIrect.h | 684 ++ .../base/data_types/ossimKeyword.cpp | 136 + .../ossim_core/base/data_types/ossimKeyword.h | 64 + .../base/data_types/ossimKeywordlist.cpp | 1244 ++++ .../base/data_types/ossimKeywordlist.h | 387 ++ .../ossim_core/base/data_types/ossimLine.cpp | 176 + .../ossim_core/base/data_types/ossimLine.h | 94 + .../base/data_types/ossimLsrPoint.cpp | 124 + .../base/data_types/ossimLsrPoint.h | 194 + .../base/data_types/ossimLsrRay.cpp | 109 + .../ossim_core/base/data_types/ossimLsrRay.h | 169 + .../base/data_types/ossimLsrSpace.cpp | 236 + .../base/data_types/ossimLsrSpace.h | 147 + .../base/data_types/ossimLsrVector.cpp | 119 + .../base/data_types/ossimLsrVector.h | 303 + .../base/data_types/ossimMatrix3x3.cpp | 289 + .../base/data_types/ossimMatrix3x3.h | 96 + .../base/data_types/ossimMatrix4x4.cpp | 298 + .../base/data_types/ossimMatrix4x4.h | 283 + .../data_types/ossimMultiBandHistogram.cpp | 400 ++ .../base/data_types/ossimMultiBandHistogram.h | 101 + .../ossimMultiResLevelHistogram.cpp | 500 ++ .../data_types/ossimMultiResLevelHistogram.h | 115 + .../base/data_types/ossimPolyArea2d.cpp | 949 +++ .../base/data_types/ossimPolyArea2d.h | 196 + .../base/data_types/ossimPolyLine.cpp | 573 ++ .../base/data_types/ossimPolyLine.h | 257 + .../base/data_types/ossimPolygon.cpp | 992 +++ .../ossim_core/base/data_types/ossimPolygon.h | 209 + .../base/data_types/ossimRationalNumber.cpp | 233 + .../base/data_types/ossimRationalNumber.h | 210 + .../base/data_types/ossimRegExp.cpp | 1276 ++++ .../ossim_core/base/data_types/ossimRegExp.h | 223 + .../base/data_types/ossimString.cpp | 743 +++ .../ossim_core/base/data_types/ossimString.h | 307 + .../base/data_types/ossimTempFilename.cpp | 114 + .../base/data_types/ossimTempFilename.h | 42 + .../ossim_core/base/data_types/ossimVrect.cpp | 41 + .../ossim_core/base/data_types/ossimVrect.h | 162 + .../base/data_types/ossimXmlAttribute.cpp | 236 + .../base/data_types/ossimXmlAttribute.h | 52 + .../base/data_types/ossimXmlDocument.cpp | 409 ++ .../base/data_types/ossimXmlDocument.h | 74 + .../base/data_types/ossimXmlNode.cpp | 840 +++ .../ossim_core/base/data_types/ossimXmlNode.h | 103 + .../base/data_types/ossimXmlString.cpp | 72 + .../base/data_types/ossimXmlString.h | 79 + .../OSSIM/ossim_core/base/factory/.cvsignore | 1 + .../base/factory/ossimBaseObjectFactory.cpp | 74 + .../base/factory/ossimBaseObjectFactory.h | 49 + .../ossimCustomEditorWindowFactoryBase.cpp | 25 + .../ossimCustomEditorWindowFactoryBase.h | 52 + .../ossimCustomEditorWindowRegistry.cpp | 168 + .../factory/ossimCustomEditorWindowRegistry.h | 78 + .../base/factory/ossimDatumFactory.cpp | 340 + .../base/factory/ossimDatumFactory.h | 67 + .../base/factory/ossimDatumFactory.inc | 299 + .../base/factory/ossimEllipsoidFactory.cpp | 187 + .../base/factory/ossimEllipsoidFactory.h | 58 + .../base/factory/ossimObjectFactory.cpp | 4 + .../base/factory/ossimObjectFactory.h | 58 + .../factory/ossimObjectFactoryRegistry.cpp | 187 + .../base/factory/ossimObjectFactoryRegistry.h | 90 + .../factory/ossimPropertyInterfaceFactory.cpp | 5 + .../factory/ossimPropertyInterfaceFactory.h | 48 + .../ossimPropertyInterfaceRegistry.cpp | 112 + .../factory/ossimPropertyInterfaceRegistry.h | 62 + .../base/factory/ossimStreamFactory.cpp | 82 + .../base/factory/ossimStreamFactory.h | 35 + .../base/factory/ossimStreamFactoryBase.h | 32 + .../factory/ossimStreamFactoryRegistry.cpp | 71 + .../base/factory/ossimStreamFactoryRegistry.h | 38 + .../OSSIM/ossim_core/base/misc/.cvsignore | 1 + .../OSSIM/ossim_core/base/misc/FlexLexer.h | 188 + .../ossim_core/base/misc/hash/.cvsignore | 1 + .../base/misc/hash/ossimPointHash.h | 28 + .../base/misc/hash/ossimTileHash.cpp | 123 + .../ossim_core/base/misc/hash/ossimTileHash.h | 46 + .../base/misc/hash/ossimTiledImageHash.cpp | 140 + .../base/misc/hash/ossimTiledImageHash.h | 40 + .../base/misc/lookup_tables/.cvsignore | 1 + .../ossimGeoTiffCoordTransformsLut.cpp | 97 + .../ossimGeoTiffCoordTransformsLut.h | 81 + .../lookup_tables/ossimGeoTiffDatumLut.cpp | 116 + .../misc/lookup_tables/ossimGeoTiffDatumLut.h | 74 + .../misc/lookup_tables/ossimImageTypeLut.cpp | 68 + .../misc/lookup_tables/ossimImageTypeLut.h | 47 + .../lookup_tables/ossimInterleaveTypeLut.cpp | 50 + .../lookup_tables/ossimInterleaveTypeLut.h | 45 + .../misc/lookup_tables/ossimLookUpTable.cpp | 147 + .../misc/lookup_tables/ossimLookUpTable.h | 116 + .../misc/lookup_tables/ossimScalarTypeLut.cpp | 126 + .../misc/lookup_tables/ossimScalarTypeLut.h | 53 + .../misc/lookup_tables/ossimUnitTypeLut.cpp | 54 + .../misc/lookup_tables/ossimUnitTypeLut.h | 80 + .../base/misc/ossim2dLinearRegression.cpp | 73 + .../base/misc/ossim2dLinearRegression.h | 89 + .../base/misc/ossim2dTo2dTransform.cpp | 242 + .../base/misc/ossim2dTo2dTransform.h | 62 + .../misc/ossimAdjustableParameterInfo.cpp | 126 + .../base/misc/ossimAdjustableParameterInfo.h | 97 + .../ossimAdjustableParameterInterface.cpp | 617 ++ .../misc/ossimAdjustableParameterInterface.h | 121 + .../base/misc/ossimAdjustmentInfo.cpp | 188 + .../base/misc/ossimAdjustmentInfo.h | 62 + .../ossim_core/base/misc/ossimAdrData.cpp | 422 ++ .../OSSIM/ossim_core/base/misc/ossimAdrData.h | 63 + .../base/misc/ossimAffineTransform.cpp | 219 + .../base/misc/ossimAffineTransform.h | 110 + .../ossim_core/base/misc/ossimBilSplitter.cpp | 184 + .../ossim_core/base/misc/ossimBilSplitter.h | 74 + .../ossim_core/base/misc/ossimEndian.cpp | 213 + .../OSSIM/ossim_core/base/misc/ossimEndian.h | 77 + .../base/misc/ossimEquTokenDefines.h | 54 + .../base/misc/ossimEquTokenizer.cpp | 1795 ++++++ .../ossim_core/base/misc/ossimEquTokenizer.h | 9 + .../ossim_core/base/misc/ossimEquTokenizer.l | 179 + .../base/misc/ossimQuadTreeWarp.cpp | 1426 +++++ .../ossim_core/base/misc/ossimQuadTreeWarp.h | 461 ++ .../base/misc/ossimRectanglePartitioner.cpp | 248 + .../base/misc/ossimRectanglePartitioner.h | 147 + .../base/misc/ossimUnitConversionTool.cpp | 349 + .../base/misc/ossimUnitConversionTool.h | 93 + .../ossim_core/base/misc/ossimUsgsQuad.cpp | 730 +++ .../ossim_core/base/misc/ossimUsgsQuad.h | 118 + .../OSSIM/ossim_core/base/property/.cvsignore | 7 + .../base/property/ossimBooleanProperty.cpp | 82 + .../base/property/ossimBooleanProperty.h | 47 + .../base/property/ossimColorProperty.cpp | 128 + .../base/property/ossimColorProperty.h | 54 + .../base/property/ossimContainerProperty.cpp | 172 + .../base/property/ossimContainerProperty.h | 56 + .../base/property/ossimDateProperty.cpp | 142 + .../base/property/ossimDateProperty.h | 29 + .../base/property/ossimDoubleGridProperty.cpp | 159 + .../base/property/ossimDoubleGridProperty.h | 79 + .../base/property/ossimFilenameProperty.cpp | 168 + .../base/property/ossimFilenameProperty.h | 75 + .../base/property/ossimFontProperty.cpp | 103 + .../base/property/ossimFontProperty.h | 48 + .../base/property/ossimMatrixProperty.cpp | 331 + .../base/property/ossimMatrixProperty.h | 96 + .../base/property/ossimNumericProperty.cpp | 224 + .../base/property/ossimNumericProperty.h | 78 + .../base/property/ossimProperty.cpp | 168 + .../ossim_core/base/property/ossimProperty.h | 89 + .../base/property/ossimStringListProperty.cpp | 272 + .../base/property/ossimStringListProperty.h | 80 + .../base/property/ossimStringProperty.cpp | 127 + .../base/property/ossimStringProperty.h | 73 + .../base/property/ossimTextProperty.cpp | 76 + .../base/property/ossimTextProperty.h | 50 + Utilities/OSSIM/ossim_core/dll_main/Makefile | 10 + .../ossim_core/dll_main/ossimDllMain.cpp | 13 + .../OSSIM/ossim_core/dll_main/ossimDllMain.h | 7 + .../OSSIM/ossim_core/elevation/.cvsignore | 1 + .../OSSIM/ossim_core/elevation/CMakeLists.txt | 6 + .../ossim_core/elevation/formats/.cvsignore | 1 + .../elevation/formats/dted_cell/.cvsignore | 1 + .../formats/dted_cell/ossimDtedFactory.cpp | 168 + .../formats/dted_cell/ossimDtedFactory.h | 38 + .../formats/dted_cell/ossimDtedHandler.cpp | 460 ++ .../formats/dted_cell/ossimDtedHandler.h | 156 + .../formats/ossimElevCellHandler.cpp | 88 + .../elevation/formats/ossimElevCellHandler.h | 115 + .../formats/ossimElevCellHandlerFactory.cpp | 130 + .../formats/ossimElevCellHandlerFactory.h | 63 + .../elevation/formats/srtm/.cvsignore | 2 + .../formats/srtm/ossimSrtmFactory.cpp | 228 + .../elevation/formats/srtm/ossimSrtmFactory.h | 59 + .../formats/srtm/ossimSrtmHandler.cpp | 364 ++ .../elevation/formats/srtm/ossimSrtmHandler.h | 100 + .../ossim_core/elevation/ossimElevLess.h | 45 + .../ossim_core/elevation/ossimElevManager.cpp | 1538 +++++ .../ossim_core/elevation/ossimElevManager.h | 331 + .../ossim_core/elevation/ossimElevSource.cpp | 265 + .../ossim_core/elevation/ossimElevSource.h | 184 + .../elevation/ossimElevSourceFactory.cpp | 43 + .../elevation/ossimElevSourceFactory.h | 76 + .../elevation/ossimElevationShapeIdx.cpp | 274 + .../elevation/ossimElevationShapeIdx.h | 41 + Utilities/OSSIM/ossim_core/fonts/.cvsignore | 1 + .../OSSIM/ossim_core/fonts/CMakeLists.txt | 6 + .../OSSIM/ossim_core/fonts/factory/.cvsignore | 1 + .../fonts/factory/ossimFontFactoryBase.h | 41 + .../factory/ossimFontFactoryRegistry.cpp | 191 + .../fonts/factory/ossimFontFactoryRegistry.h | 82 + .../factory/ossimFreeTypeFontFactory.cpp | 237 + .../fonts/factory/ossimFreeTypeFontFactory.h | 64 + .../OSSIM/ossim_core/fonts/ossimFont.cpp | 83 + Utilities/OSSIM/ossim_core/fonts/ossimFont.h | 336 + .../ossim_core/fonts/ossimFreeTypeFont.cpp | 646 ++ .../ossim_core/fonts/ossimFreeTypeFont.h | 199 + .../ossim_core/fonts/ossimGdBitmapFont.cpp | 263 + .../ossim_core/fonts/ossimGdBitmapFont.h | 101 + .../ossim_core/fonts/ossimGdSansBold.inc | 4383 +++++++++++++ Utilities/OSSIM/ossim_core/imaging/.cvsignore | 1 + .../OSSIM/ossim_core/imaging/CMakeLists.txt | 6 + .../ossim_core/imaging/annotation/.cvsignore | 1 + .../ossim_core/imaging/annotation/gdfontg.inc | 4384 +++++++++++++ .../ossim_core/imaging/annotation/gdfontl.inc | 4641 ++++++++++++++ .../imaging/annotation/gdfontmb.inc | 3870 +++++++++++ .../ossim_core/imaging/annotation/gdfonts.inc | 3871 +++++++++++ .../ossim_core/imaging/annotation/gdfontt.inc | 2589 ++++++++ .../ossimAnnotationEllipseObject.cpp | 180 + .../annotation/ossimAnnotationEllipseObject.h | 75 + .../annotation/ossimAnnotationFontObject.cpp | 397 ++ .../annotation/ossimAnnotationFontObject.h | 85 + .../ossimAnnotationGdBitmapFont.cpp | 195 + .../annotation/ossimAnnotationGdBitmapFont.h | 137 + .../annotation/ossimAnnotationLineObject.cpp | 183 + .../annotation/ossimAnnotationLineObject.h | 76 + .../annotation/ossimAnnotationMapGridSource.h | 14 + .../ossimAnnotationMultiEllipseObject.cpp | 237 + .../ossimAnnotationMultiEllipseObject.h | 80 + .../ossimAnnotationMultiLineObject.cpp | 191 + .../ossimAnnotationMultiLineObject.h | 102 + .../ossimAnnotationMultiPolyLineObject.cpp | 268 + .../ossimAnnotationMultiPolyLineObject.h | 70 + .../ossimAnnotationMultiPolyObject.cpp | 322 + .../ossimAnnotationMultiPolyObject.h | 97 + .../annotation/ossimAnnotationObject.cpp | 161 + .../annotation/ossimAnnotationObject.h | 105 + .../annotation/ossimAnnotationPolyObject.cpp | 283 + .../annotation/ossimAnnotationPolyObject.h | 80 + .../annotation/ossimAnnotationSource.cpp | 457 ++ .../annotation/ossimAnnotationSource.h | 140 + .../annotation/ossimEsriShapeFileFilter.cpp | 813 +++ .../annotation/ossimEsriShapeFileFilter.h | 270 + .../imaging/annotation/ossimGdFont.h | 54 + .../imaging/annotation/ossimGdFontExterns.h | 33 + .../annotation/ossimGeoAnnotationBitmap.cpp | 168 + .../annotation/ossimGeoAnnotationBitmap.h | 71 + .../ossimGeoAnnotationEllipseObject.cpp | 307 + .../ossimGeoAnnotationEllipseObject.h | 86 + .../ossimGeoAnnotationFontObject.cpp | 290 + .../annotation/ossimGeoAnnotationFontObject.h | 128 + .../ossimGeoAnnotationGdBitmapFont.cpp | 139 + .../ossimGeoAnnotationGdBitmapFont.h | 74 + .../ossimGeoAnnotationLineObject.cpp | 141 + .../annotation/ossimGeoAnnotationLineObject.h | 65 + .../ossimGeoAnnotationMultiEllipseObject.cpp | 186 + .../ossimGeoAnnotationMultiEllipseObject.h | 83 + .../ossimGeoAnnotationMultiPolyLineObject.cpp | 354 ++ .../ossimGeoAnnotationMultiPolyLineObject.h | 90 + .../ossimGeoAnnotationMultiPolyObject.cpp | 199 + .../ossimGeoAnnotationMultiPolyObject.h | 118 + .../annotation/ossimGeoAnnotationObject.cpp | 46 + .../annotation/ossimGeoAnnotationObject.h | 51 + .../ossimGeoAnnotationPolyLineObject.cpp | 178 + .../ossimGeoAnnotationPolyLineObject.h | 69 + .../ossimGeoAnnotationPolyObject.cpp | 302 + .../annotation/ossimGeoAnnotationPolyObject.h | 88 + .../annotation/ossimGeoAnnotationSource.cpp | 207 + .../annotation/ossimGeoAnnotationSource.h | 75 + .../ossimGeographicAnnotationGrid.cpp | 283 + .../ossimGeographicAnnotationGrid.h | 52 + .../annotation/ossimMapCompositionSource.cpp | 4032 ++++++++++++ .../annotation/ossimMapCompositionSource.h | 339 + .../imaging/atmospheric_correction/.cvsignore | 5 + .../atmospheric_correction/ossimAOD.cpp | 238 + .../imaging/atmospheric_correction/ossimAOD.h | 66 + .../ossimAtCorrGridRemapper.cpp | 351 + .../ossimAtCorrGridRemapper.h | 154 + .../ossimAtCorrKeywords.h | 35 + .../ossimAtCorrRemapper.cpp | 729 +++ .../ossimAtCorrRemapper.h | 88 + .../ossimGammaRemapper.cpp | 433 ++ .../ossimGammaRemapper.h | 71 + .../OSSIM/ossim_core/imaging/cache/.cvsignore | 1 + .../imaging/cache/ossimAppFixedTileCache.cpp | 383 ++ .../imaging/cache/ossimAppFixedTileCache.h | 118 + .../imaging/cache/ossimAppTileCache.cpp | 307 + .../imaging/cache/ossimAppTileCache.h | 169 + .../imaging/cache/ossimFixedTileCache.cpp | 282 + .../imaging/cache/ossimFixedTileCache.h | 143 + .../imaging/cache/ossimTileCache.cpp | 189 + .../ossim_core/imaging/cache/ossimTileCache.h | 114 + .../ossim_core/imaging/elevation/.cvsignore | 2 + .../elevation/ossimElevImageSource.cpp | 821 +++ .../imaging/elevation/ossimElevImageSource.h | 146 + .../ossim_core/imaging/factory/.cvsignore | 2 + .../factory/ossimAnnotationObjectFactory.cpp | 102 + .../factory/ossimAnnotationObjectFactory.h | 57 + .../imaging/factory/ossimImageDataFactory.cpp | 254 + .../imaging/factory/ossimImageDataFactory.h | 62 + .../factory/ossimImageHandlerFactory.cpp | 633 ++ .../factory/ossimImageHandlerFactory.h | 76 + .../factory/ossimImageHandlerFactoryBase.cpp | 25 + .../factory/ossimImageHandlerFactoryBase.h | 44 + .../factory/ossimImageHandlerRegistry.cpp | 193 + .../factory/ossimImageHandlerRegistry.h | 98 + .../ossimImageMetaDataWriterFactory.cpp | 206 + .../factory/ossimImageMetaDataWriterFactory.h | 87 + .../ossimImageMetaDataWriterFactoryBase.cpp | 28 + .../ossimImageMetaDataWriterFactoryBase.h | 67 + .../ossimImageMetaDataWriterRegistry.cpp | 176 + .../ossimImageMetaDataWriterRegistry.h | 98 + .../ossimImageReconstructionFilterFactory.cpp | 86 + .../ossimImageReconstructionFilterFactory.h | 47 + ...ossimImageReconstructionFilterRegistry.cpp | 126 + .../ossimImageReconstructionFilterRegistry.h | 51 + .../factory/ossimImageSourceFactory.cpp | 551 ++ .../imaging/factory/ossimImageSourceFactory.h | 46 + .../factory/ossimImageSourceFactoryBase.cpp | 74 + .../factory/ossimImageSourceFactoryBase.h | 46 + .../ossimImageSourceFactoryRegistry.cpp | 144 + .../factory/ossimImageSourceFactoryRegistry.h | 55 + .../factory/ossimImageWriterFactory.cpp | 226 + .../imaging/factory/ossimImageWriterFactory.h | 59 + .../factory/ossimImageWriterFactoryBase.cpp | 26 + .../factory/ossimImageWriterFactoryBase.h | 55 + .../ossimImageWriterFactoryRegistry.cpp | 220 + .../factory/ossimImageWriterFactoryRegistry.h | 73 + .../ossim_core/imaging/filters/.cvsignore | 1 + .../filters/ossimDiscrete3x3HatFilter.cpp | 289 + .../filters/ossimDiscrete3x3HatFilter.h | 64 + .../ossimDiscreteConvolutionKernel.cpp | 557 ++ .../filters/ossimDiscreteConvolutionKernel.h | 151 + .../filters/ossimDiscreteNearestNeighbor.h | 123 + .../imaging/filters/ossimFilter.cpp | 333 + .../ossim_core/imaging/filters/ossimFilter.h | 486 ++ .../imaging/filters/ossimFilterTable.cpp | 149 + .../imaging/filters/ossimFilterTable.h | 97 + .../ossim_core/imaging/formats/.cvsignore | 1 + .../imaging/formats/adrg/.cvsignore | 1 + .../imaging/formats/adrg/ossimAdrgHeader.cpp | 499 ++ .../imaging/formats/adrg/ossimAdrgHeader.h | 130 + .../formats/adrg/ossimAdrgTileSource.cpp | 782 +++ .../formats/adrg/ossimAdrgTileSource.h | 175 + .../imaging/formats/adrg/ossimDdffield.cpp | 336 + .../formats/adrg/ossimDdffielddefn.cpp | 865 +++ .../imaging/formats/adrg/ossimDdfmodule.cpp | 709 +++ .../imaging/formats/adrg/ossimDdfrecord.cpp | 1850 ++++++ .../formats/adrg/ossimDdfsubfielddefn.cpp | 950 +++ .../imaging/formats/adrg/ossimDdfutils.cpp | 101 + .../imaging/formats/adrg/ossimIso8211.h | 527 ++ .../imaging/formats/aigrid/.cvsignore | 1 + .../formats/aigrid/ossimArcInfoGridWriter.cpp | 367 ++ .../formats/aigrid/ossimArcInfoGridWriter.h | 59 + .../ossim_core/imaging/formats/ccf/.cvsignore | 1 + .../imaging/formats/ccf/ossimCcfHead.cpp | 767 +++ .../imaging/formats/ccf/ossimCcfHead.h | 202 + .../formats/ccf/ossimCcfTileSource.cpp | 847 +++ .../imaging/formats/ccf/ossimCcfTileSource.h | 202 + .../imaging/formats/cibcadrg/.cvsignore | 1 + .../cibcadrg/ossimCibCadrgTileSource.cpp | 1423 +++++ .../cibcadrg/ossimCibCadrgTileSource.h | 574 ++ .../imaging/formats/doqq/.cvsignore | 1 + .../formats/doqq/ossimDoqqTileSource.cpp | 222 + .../formats/doqq/ossimDoqqTileSource.h | 43 + .../imaging/formats/dted/.cvsignore | 1 + .../dted/ossimDtedElevationImageSource.cpp | 719 +++ .../dted/ossimDtedElevationImageSource.h | 226 + .../formats/dted/ossimDtedTileSource.cpp | 739 +++ .../formats/dted/ossimDtedTileSource.h | 209 + .../formats/ers/ossimERSTileSource.cpp | 199 + .../imaging/formats/ers/ossimERSTileSource.h | 59 + .../imaging/formats/general_raster/.cvsignore | 1 + .../general_raster/ossimGeneralRasterInfo.cpp | 611 ++ .../general_raster/ossimGeneralRasterInfo.h | 367 ++ .../ossimGeneralRasterTileSource.cpp | 1192 ++++ .../ossimGeneralRasterTileSource.h | 168 + .../ossimGeneralRasterWriter.cpp | 829 +++ .../general_raster/ossimGeneralRasterWriter.h | 120 + .../imaging/formats/jpeg/.cvsignore | 1 + .../formats/jpeg/ossimJpegTileSource.cpp | 606 ++ .../formats/jpeg/ossimJpegTileSource.h | 198 + .../imaging/formats/jpeg/ossimJpegWriter.cpp | 469 ++ .../imaging/formats/jpeg/ossimJpegWriter.h | 110 + .../imaging/formats/landsat/.cvsignore | 1 + .../landsat/ossimLandsatTileSource.cpp | 450 ++ .../formats/landsat/ossimLandsatTileSource.h | 83 + .../imaging/formats/nitf/.cvsignore | 2 + .../formats/nitf/ossimNitfTileSource.cpp | 2175 +++++++ .../formats/nitf/ossimNitfTileSource.h | 416 ++ .../imaging/formats/nitf/ossimNitfWriter.cpp | 1045 +++ .../imaging/formats/nitf/ossimNitfWriter.h | 166 + .../nitf/ossimQuickbirdNitfTileSource.cpp | 187 + .../nitf/ossimQuickbirdNitfTileSource.h | 27 + .../imaging/formats/ossimImageFileWriter.cpp | 1123 ++++ .../imaging/formats/ossimImageFileWriter.h | 319 + .../imaging/formats/ossimImageHandler.cpp | 1228 ++++ .../imaging/formats/ossimImageHandler.h | 564 ++ .../formats/srtm/ossimSrtmTileSource.cpp | 145 + .../formats/srtm/ossimSrtmTileSource.h | 72 + .../imaging/formats/tiff/.cvsignore | 1 + .../tiff/ossimQuickbirdTiffTileSource.cpp | 88 + .../tiff/ossimQuickbirdTiffTileSource.h | 33 + .../formats/tiff/ossimTiffOverviewBuilder.cpp | 1580 +++++ .../formats/tiff/ossimTiffOverviewBuilder.h | 208 + .../formats/tiff/ossimTiffTileSource.cpp | 1825 ++++++ .../formats/tiff/ossimTiffTileSource.h | 268 + .../imaging/formats/tiff/ossimTiffWriter.cpp | 2316 +++++++ .../imaging/formats/tiff/ossimTiffWriter.h | 257 + .../imaging/formats/usgs_dem/.cvsignore | 1 + .../usgs_dem/ossimUsgsDemTileSource.cpp | 648 ++ .../formats/usgs_dem/ossimUsgsDemTileSource.h | 173 + .../ossim_core/imaging/formats/vpf/.cvsignore | 3 + .../vpf/ossimVpfAnnotationCoverageInfo.cpp | 217 + .../vpf/ossimVpfAnnotationCoverageInfo.h | 77 + .../vpf/ossimVpfAnnotationFeatureInfo.cpp | 1451 +++++ .../vpf/ossimVpfAnnotationFeatureInfo.h | 218 + .../vpf/ossimVpfAnnotationLibraryInfo.cpp | 260 + .../vpf/ossimVpfAnnotationLibraryInfo.h | 52 + .../formats/vpf/ossimVpfAnnotationSource.cpp | 267 + .../formats/vpf/ossimVpfAnnotationSource.h | 45 + .../formats/vpf/ossimVpfTileSource.cpp | 217 + .../imaging/formats/vpf/ossimVpfTileSource.h | 168 + .../ossim_core/imaging/histogram/.cvsignore | 1 + .../histogram/ossimHistogramWriter.cpp | 154 + .../imaging/histogram/ossimHistogramWriter.h | 178 + .../histogram/ossimImageHistogramSource.cpp | 373 ++ .../histogram/ossimImageHistogramSource.h | 101 + .../ossim_core/imaging/metadata/.cvsignore | 3 + .../metadata/ossimEnviHeaderFileWriter.cpp | 107 + .../metadata/ossimEnviHeaderFileWriter.h | 77 + .../imaging/metadata/ossimFgdcFileWriter.cpp | 972 +++ .../imaging/metadata/ossimFgdcFileWriter.h | 157 + .../imaging/metadata/ossimGeomFileWriter.cpp | 96 + .../imaging/metadata/ossimGeomFileWriter.h | 57 + .../metadata/ossimJpegWorldFileWriter.cpp | 119 + .../metadata/ossimJpegWorldFileWriter.h | 57 + .../metadata/ossimMetadataFileWriter.cpp | 240 + .../metadata/ossimMetadataFileWriter.h | 149 + .../metadata/ossimReadmeFileWriter.cpp | 476 ++ .../imaging/metadata/ossimReadmeFileWriter.h | 57 + .../metadata/ossimTiffWorldFileWriter.cpp | 121 + .../metadata/ossimTiffWorldFileWriter.h | 56 + .../OSSIM/ossim_core/imaging/misc/.cvsignore | 1 + .../imaging/misc/ossimPixelFlipper.cpp | 1216 ++++ .../imaging/misc/ossimPixelFlipper.h | 246 + .../imaging/misc/ossimVertexExtractor.cpp | 1962 ++++++ .../imaging/misc/ossimVertexExtractor.h | 173 + .../ossim_core/imaging/ossimIgenGenerator.cpp | 703 ++ .../ossim_core/imaging/ossimIgenGenerator.h | 319 + .../ossim_core/imaging/ossimImageChain.cpp | 1809 ++++++ .../ossim_core/imaging/ossimImageChain.h | 358 ++ .../ossim_core/imaging/ossimImageData.cpp | 5662 +++++++++++++++++ .../OSSIM/ossim_core/imaging/ossimImageData.h | 930 +++ .../imaging/ossimImageDataHelper.cpp | 604 ++ .../ossim_core/imaging/ossimImageDataHelper.h | 115 + .../imaging/ossimImageDisplayWriter.cpp | 52 + .../imaging/ossimImageDisplayWriter.h | 90 + .../ossim_core/imaging/ossimImageMetaData.cpp | 476 ++ .../ossim_core/imaging/ossimImageMetaData.h | 102 + .../imaging/ossimImageShapeFileIndex.cpp | 197 + .../imaging/ossimImageShapeFileIndex.h | 61 + .../ossim_core/imaging/ossimImageSource.cpp | 336 + .../ossim_core/imaging/ossimImageSource.h | 202 + .../imaging/ossimImageSourceInterface.cpp | 18 + .../imaging/ossimImageSourceInterface.h | 109 + .../imaging/ossimImageSourceSequencer.cpp | 424 ++ .../imaging/ossimImageSourceSequencer.h | 160 + .../imaging/ossimImageStatisticsSource.cpp | 180 + .../imaging/ossimImageStatisticsSource.h | 32 + .../ossim_core/imaging/ossimImageWriter.cpp | 81 + .../ossim_core/imaging/ossimImageWriter.h | 71 + .../ossim_core/imaging/ossimRgbImage.cpp | 1910 ++++++ .../OSSIM/ossim_core/imaging/ossimRgbImage.h | 370 ++ .../ossim_core/imaging/ossimS16ImageData.cpp | 716 +++ .../ossim_core/imaging/ossimS16ImageData.h | 195 + .../OSSIM/ossim_core/imaging/ossimTiling.cpp | 854 +++ .../OSSIM/ossim_core/imaging/ossimTiling.h | 161 + .../ossim_core/imaging/ossimU11ImageData.cpp | 724 +++ .../ossim_core/imaging/ossimU11ImageData.h | 204 + .../ossim_core/imaging/ossimU16ImageData.cpp | 695 ++ .../ossim_core/imaging/ossimU16ImageData.h | 208 + .../ossim_core/imaging/ossimU8ImageData.cpp | 738 +++ .../ossim_core/imaging/ossimU8ImageData.h | 189 + .../OSSIM/ossim_core/imaging/patch/.cvsignore | 1 + .../imaging/patch/ossimTilePatch.cpp | 518 ++ .../ossim_core/imaging/patch/ossimTilePatch.h | 135 + .../reconstruction/ossimMeanMedianFilter.cpp | 929 +++ .../reconstruction/ossimMeanMedianFilter.h | 129 + .../imaging/remap_tables/.cvsignore | 1 + .../ossimNormalizedRemapTable.cpp | 29 + .../remap_tables/ossimNormalizedRemapTable.h | 68 + .../ossimNormalizedU11RemapTable.cpp | 45 + .../ossimNormalizedU11RemapTable.h | 102 + .../ossimNormalizedU16RemapTable.cpp | 45 + .../ossimNormalizedU16RemapTable.h | 101 + .../ossimNormalizedU8RemapTable.cpp | 45 + .../ossimNormalizedU8RemapTable.h | 104 + .../ossim_core/imaging/resample/.cvsignore | 1 + .../imaging/resample/ossimFilterResampler.cpp | 921 +++ .../imaging/resample/ossimFilterResampler.h | 151 + .../imaging/resample/ossimResampler.cpp | 1259 ++++ .../imaging/resample/ossimResampler.h | 240 + .../imaging/tile_sources/.cvsignore | 1 + .../ossim3x3ConvolutionFilter.cpp | 632 ++ .../tile_sources/ossim3x3ConvolutionFilter.h | 97 + .../tile_sources/ossimBandAverageFilter.cpp | 394 ++ .../tile_sources/ossimBandAverageFilter.h | 109 + .../tile_sources/ossimBandClipFilter.cpp | 697 ++ .../tile_sources/ossimBandClipFilter.h | 92 + .../tile_sources/ossimBandMergeSource.cpp | 274 + .../tile_sources/ossimBandMergeSource.h | 62 + .../tile_sources/ossimBandSelector.cpp | 428 ++ .../imaging/tile_sources/ossimBandSelector.h | 119 + .../imaging/tile_sources/ossimBlendMosaic.cpp | 624 ++ .../imaging/tile_sources/ossimBlendMosaic.h | 78 + .../ossimBrightnessContrastSource.cpp | 314 + .../ossimBrightnessContrastSource.h | 132 + .../tile_sources/ossimBrightnessMatch.cpp | 247 + .../tile_sources/ossimBrightnessMatch.h | 56 + .../tile_sources/ossimBumpShadeTileSource.cpp | 507 ++ .../tile_sources/ossimBumpShadeTileSource.h | 271 + .../tile_sources/ossimCacheTileSource.cpp | 357 ++ .../tile_sources/ossimCacheTileSource.h | 75 + .../ossimCastTileSourceFilter.cpp | 688 ++ .../tile_sources/ossimCastTileSourceFilter.h | 93 + .../ossimClosestToCenterCombiner.cpp | 141 + .../ossimClosestToCenterCombiner.h | 60 + .../ossimColorNormalizedFusion.cpp | 144 + .../tile_sources/ossimColorNormalizedFusion.h | 32 + .../tile_sources/ossimConvolutionFilter1D.cpp | 638 ++ .../tile_sources/ossimConvolutionFilter1D.h | 102 + .../tile_sources/ossimConvolutionSource.cpp | 525 ++ .../tile_sources/ossimConvolutionSource.h | 72 + .../ossimEastingNorthingCutter.cpp | 209 + .../tile_sources/ossimEastingNorthingCutter.h | 45 + .../imaging/tile_sources/ossimEdgeFilter.cpp | 545 ++ .../imaging/tile_sources/ossimEdgeFilter.h | 77 + .../tile_sources/ossimEquationCombiner.cpp | 3555 +++++++++++ .../tile_sources/ossimEquationCombiner.h | 311 + .../tile_sources/ossimEsriShapeFileCutter.cpp | 323 + .../tile_sources/ossimEsriShapeFileCutter.h | 200 + .../tile_sources/ossimFeatherMosaic.cpp | 474 ++ .../imaging/tile_sources/ossimFeatherMosaic.h | 87 + .../imaging/tile_sources/ossimFftFilter.cpp | 472 ++ .../imaging/tile_sources/ossimFftFilter.h | 86 + .../tile_sources/ossimFusionCombiner.cpp | 191 + .../tile_sources/ossimFusionCombiner.h | 47 + .../tile_sources/ossimGeoPolyCutter.cpp | 353 + .../imaging/tile_sources/ossimGeoPolyCutter.h | 251 + .../tile_sources/ossimHistoMatchRemapper.cpp | 349 + .../tile_sources/ossimHistoMatchRemapper.h | 95 + .../ossimHistogramEqualization.cpp | 537 ++ .../tile_sources/ossimHistogramEqualization.h | 99 + .../ossimHistogramMatchFilter.cpp | 248 + .../tile_sources/ossimHistogramMatchFilter.h | 173 + .../tile_sources/ossimHistogramRemapper.cpp | 1694 +++++ .../tile_sources/ossimHistogramRemapper.h | 529 ++ .../ossimHistogramThreshholdFilter.cpp | 259 + .../ossimHistogramThreshholdFilter.h | 51 + .../imaging/tile_sources/ossimHsiRemapper.cpp | 2751 ++++++++ .../imaging/tile_sources/ossimHsiRemapper.h | 251 + .../tile_sources/ossimHsiToRgbSource.cpp | 147 + .../tile_sources/ossimHsiToRgbSource.h | 49 + .../tile_sources/ossimHsvToRgbSource.cpp | 159 + .../tile_sources/ossimHsvToRgbSource.h | 42 + .../tile_sources/ossimImageCombiner.cpp | 689 ++ .../imaging/tile_sources/ossimImageCombiner.h | 132 + .../tile_sources/ossimImageGaussianFilter.cpp | 198 + .../tile_sources/ossimImageGaussianFilter.h | 54 + .../imaging/tile_sources/ossimImageMosaic.cpp | 532 ++ .../imaging/tile_sources/ossimImageMosaic.h | 73 + .../tile_sources/ossimImageRenderer.cpp | 1866 ++++++ .../imaging/tile_sources/ossimImageRenderer.h | 402 ++ .../tile_sources/ossimImageSharpenFilter.cpp | 368 ++ .../tile_sources/ossimImageSharpenFilter.h | 60 + .../tile_sources/ossimImageSourceFilter.cpp | 340 + .../tile_sources/ossimImageSourceFilter.h | 115 + .../ossimImageSourceHistogramFilter.cpp | 238 + .../ossimImageSourceHistogramFilter.h | 65 + .../ossimImageToPlaneNormalFilter.cpp | 432 ++ .../ossimImageToPlaneNormalFilter.h | 67 + .../tile_sources/ossimIndexToRgbLutFilter.cpp | 626 ++ .../tile_sources/ossimIndexToRgbLutFilter.h | 205 + .../ossimIntensityAdjustmentFilter.cpp | 287 + .../ossimIntensityAdjustmentFilter.h | 74 + .../ossimJpegYCbCrToRgbSource.cpp | 114 + .../tile_sources/ossimJpegYCbCrToRgbSource.h | 37 + .../ossimLandsatTopoCorrectionFilter.cpp | 361 ++ .../ossimLandsatTopoCorrectionFilter.h | 54 + .../ossimLocalCorrelationFusion.cpp | 432 ++ .../ossimLocalCorrelationFusion.h | 88 + .../imaging/tile_sources/ossimMaskFilter.cpp | 798 +++ .../imaging/tile_sources/ossimMaskFilter.h | 234 + .../imaging/tile_sources/ossimMaxMosaic.cpp | 547 ++ .../imaging/tile_sources/ossimMaxMosaic.h | 79 + .../ossimMultiBandHistogramTileSource.cpp | 371 ++ .../ossimMultiBandHistogramTileSource.h | 103 + .../tile_sources/ossimNBandToIndexFilter.cpp | 551 ++ .../tile_sources/ossimNBandToIndexFilter.h | 129 + .../tile_sources/ossimOrthoImageMosaic.cpp | 416 ++ .../tile_sources/ossimOrthoImageMosaic.h | 65 + .../imaging/tile_sources/ossimPolyCutter.cpp | 373 ++ .../imaging/tile_sources/ossimPolyCutter.h | 96 + .../tile_sources/ossimRLevelFilter.cpp | 265 + .../imaging/tile_sources/ossimRLevelFilter.h | 84 + .../tile_sources/ossimRectangleCutFilter.cpp | 295 + .../tile_sources/ossimRectangleCutFilter.h | 57 + .../tile_sources/ossimRgbToGreyFilter.cpp | 249 + .../tile_sources/ossimRgbToGreyFilter.h | 70 + .../tile_sources/ossimRgbToHsiSource.cpp | 162 + .../tile_sources/ossimRgbToHsiSource.h | 47 + .../tile_sources/ossimRgbToHsvSource.cpp | 155 + .../tile_sources/ossimRgbToHsvSource.h | 47 + .../tile_sources/ossimRgbToIndexFilter.cpp | 227 + .../tile_sources/ossimRgbToIndexFilter.h | 96 + .../ossimRgbToJpegYCbCrSource.cpp | 93 + .../tile_sources/ossimRgbToJpegYCbCrSource.h | 32 + .../imaging/tile_sources/ossimSFIMFusion.cpp | 285 + .../imaging/tile_sources/ossimSFIMFusion.h | 76 + .../tile_sources/ossimScalarRemapper.cpp | 554 ++ .../tile_sources/ossimScalarRemapper.h | 108 + .../imaging/tile_sources/ossimScaleFilter.cpp | 908 +++ .../imaging/tile_sources/ossimScaleFilter.h | 179 + .../tile_sources/ossimSubImageTileSource.cpp | 224 + .../tile_sources/ossimSubImageTileSource.h | 89 + .../tile_sources/ossimTableRemapper.cpp | 610 ++ .../imaging/tile_sources/ossimTableRemapper.h | 154 + .../ossimTopographicCorrectionFilter.cpp | 1297 ++++ .../ossimTopographicCorrectionFilter.h | 225 + .../imaging/tile_sources/ossimTrimFilter.cpp | 352 + .../imaging/tile_sources/ossimTrimFilter.h | 70 + .../ossimValueAssignImageSourceFilter.cpp | 377 ++ .../ossimValueAssignImageSourceFilter.h | 102 + .../tile_sources/ossimVectorRenderer.cpp | 148 + .../tile_sources/ossimVectorRenderer.h | 133 + .../tile_sources/ossimWatermarkFilter.cpp | 1167 ++++ .../tile_sources/ossimWatermarkFilter.h | 351 + .../imaging/tonal_balance/.cvsignore | 1 + .../tonal_balance/ossimAtbController.cpp | 594 ++ .../tonal_balance/ossimAtbController.h | 162 + .../tonal_balance/ossimAtbMatchPoint.cpp | 169 + .../tonal_balance/ossimAtbMatchPoint.h | 104 + .../tonal_balance/ossimAtbPointSource.cpp | 206 + .../tonal_balance/ossimAtbPointSource.h | 108 + .../tonal_balance/ossimGridRemapEngine.cpp | 32 + .../tonal_balance/ossimGridRemapEngine.h | 69 + .../ossimGridRemapEngineFactory.cpp | 44 + .../ossimGridRemapEngineFactory.h | 53 + .../tonal_balance/ossimGridRemapSource.cpp | 368 ++ .../tonal_balance/ossimGridRemapSource.h | 144 + .../tonal_balance/ossimHsvGridRemapEngine.cpp | 276 + .../tonal_balance/ossimHsvGridRemapEngine.h | 54 + .../ossimMonoGridRemapEngine.cpp | 368 ++ .../tonal_balance/ossimMonoGridRemapEngine.h | 54 + .../tonal_balance/ossimRgbGridRemapEngine.cpp | 271 + .../tonal_balance/ossimRgbGridRemapEngine.h | 54 + Utilities/OSSIM/ossim_core/init/.cvsignore | 1 + .../OSSIM/ossim_core/init/CMakeLists.txt | 6 + Utilities/OSSIM/ossim_core/init/ossimInit.cpp | 551 ++ Utilities/OSSIM/ossim_core/init/ossimInit.h | 125 + .../OSSIM/ossim_core/libpolyclip/.cvsignore | 1 + .../ossim_core/libpolyclip/CMakeLists.txt | 6 + .../OSSIM/ossim_core/libpolyclip/polyarea.h | 336 + .../OSSIM/ossim_core/libpolyclip/polygon0.c | 1234 ++++ .../OSSIM/ossim_core/libpolyclip/polygon1.c | 1482 +++++ .../OSSIM/ossim_core/libpolyclip/polyio.c | 306 + .../OSSIM/ossim_core/libpolyclip/polyio.h | 40 + .../OSSIM/ossim_core/libpolyclip/vectmatr.c | 823 +++ .../OSSIM/ossim_core/libpolyclip/vectmatr.h | 190 + Utilities/OSSIM/ossim_core/matrix/.cvsignore | 1 + .../OSSIM/ossim_core/matrix/CMakeLists.txt | 6 + Utilities/OSSIM/ossim_core/matrix/bandmat.cpp | 569 ++ Utilities/OSSIM/ossim_core/matrix/bc.mak | 202 + Utilities/OSSIM/ossim_core/matrix/bc32.mak | 200 + Utilities/OSSIM/ossim_core/matrix/boolean.h | 40 + Utilities/OSSIM/ossim_core/matrix/cc.mak | 160 + .../OSSIM/ossim_core/matrix/cholesky.cpp | 280 + Utilities/OSSIM/ossim_core/matrix/controlw.h | 48 + Utilities/OSSIM/ossim_core/matrix/evalue.cpp | 297 + Utilities/OSSIM/ossim_core/matrix/example.txt | 123 + Utilities/OSSIM/ossim_core/matrix/fft.cpp | 474 ++ Utilities/OSSIM/ossim_core/matrix/gnu.mak | 154 + Utilities/OSSIM/ossim_core/matrix/hholder.cpp | 331 + Utilities/OSSIM/ossim_core/matrix/include.h | 313 + Utilities/OSSIM/ossim_core/matrix/jacobi.cpp | 123 + Utilities/OSSIM/ossim_core/matrix/ms.mak | 201 + Utilities/OSSIM/ossim_core/matrix/ms_nt.mak | 151 + .../OSSIM/ossim_core/matrix/myexcept.cpp | 485 ++ Utilities/OSSIM/ossim_core/matrix/myexcept.h | 433 ++ Utilities/OSSIM/ossim_core/matrix/newfft.cpp | 1059 +++ Utilities/OSSIM/ossim_core/matrix/newmat.h | 1805 ++++++ Utilities/OSSIM/ossim_core/matrix/newmat.txt | 3235 ++++++++++ Utilities/OSSIM/ossim_core/matrix/newmat1.cpp | 199 + Utilities/OSSIM/ossim_core/matrix/newmat2.cpp | 641 ++ Utilities/OSSIM/ossim_core/matrix/newmat3.cpp | 842 +++ Utilities/OSSIM/ossim_core/matrix/newmat4.cpp | 1027 +++ Utilities/OSSIM/ossim_core/matrix/newmat5.cpp | 485 ++ Utilities/OSSIM/ossim_core/matrix/newmat6.cpp | 884 +++ Utilities/OSSIM/ossim_core/matrix/newmat7.cpp | 1037 +++ Utilities/OSSIM/ossim_core/matrix/newmat8.cpp | 734 +++ Utilities/OSSIM/ossim_core/matrix/newmat9.cpp | 76 + Utilities/OSSIM/ossim_core/matrix/newmatap.h | 201 + .../OSSIM/ossim_core/matrix/newmatex.cpp | 313 + Utilities/OSSIM/ossim_core/matrix/newmatio.h | 61 + .../OSSIM/ossim_core/matrix/newmatnl.cpp | 260 + Utilities/OSSIM/ossim_core/matrix/newmatnl.h | 322 + Utilities/OSSIM/ossim_core/matrix/newmatrc.h | 171 + .../OSSIM/ossim_core/matrix/newmatrm.cpp | 216 + Utilities/OSSIM/ossim_core/matrix/newmatrm.h | 145 + Utilities/OSSIM/ossim_core/matrix/nl_ex.txt | 42 + Utilities/OSSIM/ossim_core/matrix/precisio.h | 241 + Utilities/OSSIM/ossim_core/matrix/sl_ex.txt | 21 + .../OSSIM/ossim_core/matrix/solution.cpp | 203 + Utilities/OSSIM/ossim_core/matrix/solution.h | 96 + Utilities/OSSIM/ossim_core/matrix/sort.cpp | 272 + Utilities/OSSIM/ossim_core/matrix/submat.cpp | 340 + Utilities/OSSIM/ossim_core/matrix/svd.cpp | 204 + .../OSSIM/ossim_core/matrix/test_exc.txt | 189 + .../OSSIM/ossim_core/matrix/watco_nt.mak | 205 + Utilities/OSSIM/ossim_core/matrix/watcom.mak | 200 + .../OSSIM/ossim_core/parallel/.cvsignore | 4 + .../OSSIM/ossim_core/parallel/CMakeLists.txt | 6 + .../OSSIM/ossim_core/parallel/ossimIgen.cpp | 805 +++ .../OSSIM/ossim_core/parallel/ossimIgen.h | 94 + ...ossimImageMpiMWriterSequenceConnection.cpp | 290 + .../ossimImageMpiMWriterSequenceConnection.h | 60 + ...ossimImageMpiSWriterSequenceConnection.cpp | 355 ++ .../ossimImageMpiSWriterSequenceConnection.h | 53 + .../OSSIM/ossim_core/parallel/ossimMpi.cpp | 175 + .../OSSIM/ossim_core/parallel/ossimMpi.h | 59 + .../ossim_core/parallel/ossimOrthoIgen.cpp | 1051 +++ .../ossim_core/parallel/ossimOrthoIgen.h | 144 + Utilities/OSSIM/ossim_core/plugin/.cvsignore | 1 + .../OSSIM/ossim_core/plugin/CMakeLists.txt | 6 + .../ossim_core/plugin/ossimDynamicLibrary.cpp | 118 + .../ossim_core/plugin/ossimDynamicLibrary.h | 69 + .../ossim_core/plugin/ossimPluginLibrary.cpp | 95 + .../ossim_core/plugin/ossimPluginLibrary.h | 45 + .../plugin/ossimSharedObjectBridge.cpp | 27 + .../plugin/ossimSharedObjectBridge.h | 54 + .../plugin/ossimSharedPluginRegistry.cpp | 181 + .../plugin/ossimSharedPluginRegistry.h | 36 + .../OSSIM/ossim_core/projections/.cvsignore | 3 + .../ossim_core/projections/CMakeLists.txt | 6 + .../ossim_core/projections/factory/.cvsignore | 3 + .../ossimImageViewTransformFactory.cpp | 69 + .../factory/ossimImageViewTransformFactory.h | 49 + .../factory/ossimMapProjectionFactory.cpp | 326 + .../factory/ossimMapProjectionFactory.h | 74 + .../factory/ossimMiscProjectionFactory.cpp | 190 + .../factory/ossimMiscProjectionFactory.h | 74 + .../factory/ossimNitfProjectionFactory.cpp | 874 +++ .../factory/ossimNitfProjectionFactory.h | 253 + .../factory/ossimPcsCodeProjectionFactory.cpp | 327 + .../factory/ossimPcsCodeProjectionFactory.h | 84 + .../factory/ossimProjectionFactoryBase.cpp | 90 + .../factory/ossimProjectionFactoryBase.h | 78 + .../ossimProjectionFactoryRegistry.cpp | 199 + .../factory/ossimProjectionFactoryRegistry.h | 71 + .../ossimProjectionViewControllerFactory.cpp | 90 + .../ossimProjectionViewControllerFactory.h | 54 + .../factory/ossimSensorModelFactory.cpp | 548 ++ .../factory/ossimSensorModelFactory.h | 73 + .../factory/ossimSrsProjectionFactory.cpp | 159 + .../factory/ossimSrsProjectionFactory.h | 68 + .../ossimStatePlaneProjectionFactory.cpp | 854 +++ .../ossimStatePlaneProjectionFactory.h | 57 + .../factory/ossimTiffProjectionFactory.cpp | 133 + .../factory/ossimTiffProjectionFactory.h | 75 + .../projections/map_projections/.cvsignore | 3 + .../map_projections/ossimAlbersProjection.cpp | 660 ++ .../map_projections/ossimAlbersProjection.h | 252 + .../ossimAzimEquDistProjection.cpp | 491 ++ .../ossimAzimEquDistProjection.h | 197 + .../map_projections/ossimBngProjection.cpp | 761 +++ .../map_projections/ossimBngProjection.h | 159 + .../map_projections/ossimBonneProjection.cpp | 541 ++ .../map_projections/ossimBonneProjection.h | 215 + .../map_projections/ossimCadrgProjection.cpp | 417 ++ .../map_projections/ossimCadrgProjection.h | 101 + .../ossimCassiniProjection.cpp | 546 ++ .../map_projections/ossimCassiniProjection.h | 208 + .../ossimCylEquAreaProjection.cpp | 467 ++ .../ossimCylEquAreaProjection.h | 211 + .../ossimEckert4Projection.cpp | 462 ++ .../map_projections/ossimEckert4Projection.h | 193 + .../ossimEckert6Projection.cpp | 445 ++ .../map_projections/ossimEckert6Projection.h | 193 + .../ossimEquDistCylProjection.cpp | 466 ++ .../ossimEquDistCylProjection.h | 209 + .../ossimGnomonicProjection.cpp | 459 ++ .../map_projections/ossimGnomonicProjection.h | 193 + .../ossimLambertConformalConicProjection.cpp | 647 ++ .../ossimLambertConformalConicProjection.h | 230 + .../map_projections/ossimLlxyProjection.cpp | 323 + .../map_projections/ossimLlxyProjection.h | 146 + .../map_projections/ossimMapProjection.cpp | 1054 +++ .../map_projections/ossimMapProjection.h | 295 + .../ossimMapProjectionInfo.cpp | 548 ++ .../map_projections/ossimMapProjectionInfo.h | 277 + .../ossimMercatorProjection.cpp | 462 ++ .../map_projections/ossimMercatorProjection.h | 224 + .../projections/map_projections/ossimMgrs.c | 1325 ++++ .../projections/map_projections/ossimMgrs.h | 252 + .../map_projections/ossimMillerProjection.cpp | 411 ++ .../map_projections/ossimMillerProjection.h | 186 + .../ossimMollweidProjection.cpp | 453 ++ .../map_projections/ossimMollweidProjection.h | 188 + .../ossimNewZealandMapGridProjection.cpp | 434 ++ .../ossimNewZealandMapGridProjection.h | 135 + .../ossimObliqueMercatorProjection.cpp | 734 +++ .../ossimObliqueMercatorProjection.h | 256 + .../ossimOrthoGraphicProjection.cpp | 501 ++ .../ossimOrthoGraphicProjection.h | 196 + .../ossimPolarStereoProjection.cpp | 562 ++ .../ossimPolarStereoProjection.h | 192 + .../map_projections/ossimPolarst.c | 505 ++ .../map_projections/ossimPolarst.h | 202 + .../ossimPolyconicProjection.cpp | 529 ++ .../ossimPolyconicProjection.h | 203 + .../map_projections/ossimSinusoid.c | 388 ++ .../map_projections/ossimSinusoid.h | 185 + .../ossimSinusoidalProjection.cpp | 455 ++ .../ossimSinusoidalProjection.h | 201 + .../ossimSpaceObliqueMercatorProjection.cpp | 408 ++ .../ossimSpaceObliqueMercatorProjection.h | 105 + .../ossimStereographicProjection.cpp | 511 ++ .../ossimStereographicProjection.h | 193 + .../map_projections/ossimTranmerc.c | 625 ++ .../map_projections/ossimTranmerc.h | 209 + .../ossimTransCylEquAreaProjection.cpp | 606 ++ .../ossimTransCylEquAreaProjection.h | 230 + .../ossimTransMercatorProjection.cpp | 743 +++ .../ossimTransMercatorProjection.h | 220 + .../projections/map_projections/ossimUps.c | 310 + .../projections/map_projections/ossimUps.h | 175 + .../map_projections/ossimUpsProjection.cpp | 335 + .../map_projections/ossimUpsProjection.h | 140 + .../map_projections/ossimUpspt.cpp | 67 + .../projections/map_projections/ossimUpspt.h | 56 + .../projections/map_projections/ossimUtm.c | 337 + .../projections/map_projections/ossimUtm.h | 178 + .../map_projections/ossimUtmProjection.cpp | 892 +++ .../map_projections/ossimUtmProjection.h | 209 + .../map_projections/ossimUtmpt.cpp | 88 + .../projections/map_projections/ossimUtmpt.h | 89 + .../ossimVanDerGrintenProjection.cpp | 529 ++ .../ossimVanDerGrintenProjection.h | 189 + .../projections/ossimAffineProjection.cpp | 287 + .../projections/ossimAffineProjection.h | 130 + .../projections/ossimBilinearProjection.cpp | 433 ++ .../projections/ossimBilinearProjection.h | 108 + .../ossimImageViewAffineTransform.cpp | 352 + .../ossimImageViewAffineTransform.h | 139 + .../ossimImageViewProjectionTransform.cpp | 476 ++ .../ossimImageViewProjectionTransform.h | 169 + .../projections/ossimImageViewTransform.cpp | 272 + .../projections/ossimImageViewTransform.h | 134 + .../projections/ossimMapViewController.cpp | 215 + .../projections/ossimMapViewController.h | 72 + .../projections/ossimProjection.cpp | 203 + .../ossim_core/projections/ossimProjection.h | 148 + .../projections/ossimQuadProjection.cpp | 543 ++ .../projections/ossimQuadProjection.h | 88 + .../projections/ossimRpcProjection.cpp | 788 +++ .../projections/ossimRpcProjection.h | 151 + .../ossim_core/projections/ossimRpcSolver.cpp | 792 +++ .../ossim_core/projections/ossimRpcSolver.h | 233 + .../ossimStatePlaneProjectionInfo.cpp | 306 + .../ossimStatePlaneProjectionInfo.h | 108 + .../projections/ossimWarpProjection.cpp | 343 + .../projections/ossimWarpProjection.h | 146 + .../projections/sensor_modeling/.cvsignore | 2 + .../sensor_modeling/coarse_grid/.cvsignore | 2 + .../coarse_grid/ossimCoarseGridModel.cpp | 1348 ++++ .../coarse_grid/ossimCoarseGridModel.h | 173 + .../sensor_modeling/fcsi/.cvsignore | 2 + .../fcsi/ossimApplanixEcefModel.cpp | 625 ++ .../fcsi/ossimApplanixEcefModel.h | 71 + .../fcsi/ossimApplanixUtmModel.cpp | 802 +++ .../fcsi/ossimApplanixUtmModel.h | 73 + .../sensor_modeling/fcsi/ossimFcsiModel.cpp | 1064 ++++ .../sensor_modeling/fcsi/ossimFcsiModel.h | 249 + .../sensor_modeling/landsat/.cvsignore | 2 + .../landsat/ossimLandSatModel.cpp | 1154 ++++ .../landsat/ossimLandSatModel.h | 191 + .../sensor_modeling/ossimAdjMapModel.cpp | 416 ++ .../sensor_modeling/ossimAdjMapModel.h | 132 + .../sensor_modeling/ossimLensDistortion.cpp | 48 + .../sensor_modeling/ossimLensDistortion.h | 52 + .../ossimMeanRadialLensDistortion.cpp | 267 + .../ossimMeanRadialLensDistortion.h | 120 + .../sensor_modeling/ossimNitfMapModel.cpp | 680 ++ .../sensor_modeling/ossimNitfMapModel.h | 90 + .../ossimRadialDecentLensDistortion.cpp | 207 + .../ossimRadialDecentLensDistortion.h | 174 + .../sensor_modeling/ossimSensorModel.cpp | 962 +++ .../sensor_modeling/ossimSensorModel.h | 234 + .../sensor_modeling/rpc/.cvsignore | 2 + .../rpc/ossimIkonosRpcModel.cpp | 601 ++ .../sensor_modeling/rpc/ossimIkonosRpcModel.h | 68 + .../sensor_modeling/rpc/ossimNitfRpcModel.cpp | 466 ++ .../sensor_modeling/rpc/ossimNitfRpcModel.h | 53 + .../rpc/ossimQuickbirdRpcModel.cpp | 534 ++ .../rpc/ossimQuickbirdRpcModel.h | 55 + .../sensor_modeling/rpc/ossimRpcModel.cpp | 1040 +++ .../sensor_modeling/rpc/ossimRpcModel.h | 193 + .../sensor_modeling/spot/.cvsignore | 2 + .../sensor_modeling/spot/ossimSpot5Model.cpp | 593 ++ .../sensor_modeling/spot/ossimSpot5Model.h | 163 + .../OSSIM/ossim_core/support_data/.cvsignore | 4 + .../ossim_core/support_data/CMakeLists.txt | 6 + .../support_data/doqq/ossimDoqq.cpp | 393 ++ .../ossim_core/support_data/doqq/ossimDoqq.h | 122 + .../ossim_core/support_data/dted/.cvsignore | 2 + .../support_data/dted/ossimDtedAcc.cpp | 248 + .../support_data/dted/ossimDtedAcc.h | 102 + .../support_data/dted/ossimDtedDsi.cpp | 553 ++ .../support_data/dted/ossimDtedDsi.h | 207 + .../support_data/dted/ossimDtedHdr.cpp | 234 + .../support_data/dted/ossimDtedHdr.h | 97 + .../support_data/dted/ossimDtedRecord.cpp | 323 + .../support_data/dted/ossimDtedRecord.h | 174 + .../support_data/dted/ossimDtedUhl.cpp | 298 + .../support_data/dted/ossimDtedUhl.h | 100 + .../support_data/dted/ossimDtedVol.cpp | 191 + .../support_data/dted/ossimDtedVol.h | 78 + .../ossim_core/support_data/envi/.cvsignore | 4 + .../support_data/envi/ossimEnviHeader.cpp | 974 +++ .../support_data/envi/ossimEnviHeader.h | 339 + .../ossim_core/support_data/ers/.cvsignore | 2 + .../ossim_core/support_data/ers/ossimERS.cpp | 603 ++ .../ossim_core/support_data/ers/ossimERS.h | 89 + .../ossim_core/support_data/esri/.cvsignore | 5 + .../support_data/esri/ossimAigBounds.cpp | 58 + .../support_data/esri/ossimAigBounds.h | 59 + .../esri/ossimAigDataFileHeader.cpp | 49 + .../esri/ossimAigDataFileHeader.h | 179 + .../support_data/esri/ossimAigHeader.cpp | 91 + .../support_data/esri/ossimAigHeader.h | 128 + .../esri/ossimAigIndexFileHeader.cpp | 46 + .../esri/ossimAigIndexFileHeader.h | 90 + .../support_data/esri/ossimAigStatistics.cpp | 58 + .../support_data/esri/ossimAigStatistics.h | 51 + .../ossim_core/support_data/fcsi/.cvsignore | 2 + .../support_data/fcsi/ossimApplanixEOFile.cpp | 690 ++ .../support_data/fcsi/ossimApplanixEOFile.h | 208 + .../ossim_core/support_data/ff_l7/.cvsignore | 3 + .../support_data/ff_l7/ossimFfL5.cpp | 183 + .../ossim_core/support_data/ff_l7/ossimFfL5.h | 54 + .../support_data/ff_l7/ossimFfL7.cpp | 564 ++ .../ossim_core/support_data/ff_l7/ossimFfL7.h | 152 + .../support_data/ff_revb/.cvsignore | 3 + .../support_data/ff_revb/ossimFfRevb.cpp | 1373 ++++ .../support_data/ff_revb/ossimFfRevb.h | 303 + .../support_data/ff_revc/.cvsignore | 3 + .../support_data/ff_revc/ossimFfRevc.cpp | 1956 ++++++ .../support_data/ff_revc/ossimFfRevc.h | 361 ++ .../ossim_core/support_data/ikonos/.cvsignore | 2 + .../ikonos/ossimIkonosMetaData.cpp | 46 + .../support_data/ikonos/ossimIkonosMetaData.h | 49 + .../ikonos/ossimSpaceImagingGeom.cpp | 286 + .../ikonos/ossimSpaceImagingGeom.h | 74 + .../ossim_core/support_data/nitf/.cvsignore | 5 + .../support_data/nitf/ossimNitfBlockaTag.cpp | 319 + .../support_data/nitf/ossimNitfBlockaTag.h | 341 + .../support_data/nitf/ossimNitfCommon.cpp | 213 + .../support_data/nitf/ossimNitfCommon.h | 106 + .../nitf/ossimNitfCompressionHeader.cpp | 13 + .../nitf/ossimNitfCompressionHeader.h | 24 + .../nitf/ossimNitfDataExtensionSegment.cpp | 34 + .../nitf/ossimNitfDataExtensionSegment.h | 44 + .../ossimNitfDataExtensionSegmentV2_0.cpp | 142 + .../nitf/ossimNitfDataExtensionSegmentV2_0.h | 83 + .../nitf/ossimNitfEmbeddedRpfDes.cpp | 49 + .../nitf/ossimNitfEmbeddedRpfDes.h | 48 + .../nitf/ossimNitfEmbeddedRpfHeader.cpp | 78 + .../nitf/ossimNitfEmbeddedRpfHeader.h | 57 + .../support_data/nitf/ossimNitfFile.cpp | 264 + .../support_data/nitf/ossimNitfFile.h | 72 + .../support_data/nitf/ossimNitfFileHeader.cpp | 140 + .../support_data/nitf/ossimNitfFileHeader.h | 179 + .../nitf/ossimNitfFileHeaderV2_0.cpp | 837 +++ .../nitf/ossimNitfFileHeaderV2_0.h | 591 ++ .../nitf/ossimNitfFileHeaderV2_1.cpp | 1852 ++++++ .../nitf/ossimNitfFileHeaderV2_1.h | 678 ++ .../nitf/ossimNitfGeoPositioningTag.cpp | 116 + .../nitf/ossimNitfGeoPositioningTag.h | 218 + .../support_data/nitf/ossimNitfImageBand.cpp | 43 + .../support_data/nitf/ossimNitfImageBand.h | 50 + .../nitf/ossimNitfImageBandV2_0.cpp | 154 + .../nitf/ossimNitfImageBandV2_0.h | 72 + .../nitf/ossimNitfImageBandV2_1.cpp | 47 + .../nitf/ossimNitfImageBandV2_1.h | 31 + .../nitf/ossimNitfImageHeader.cpp | 219 + .../support_data/nitf/ossimNitfImageHeader.h | 118 + .../nitf/ossimNitfImageHeaderV2_0.cpp | 760 +++ .../nitf/ossimNitfImageHeaderV2_0.h | 540 ++ .../nitf/ossimNitfImageHeaderV2_1.cpp | 2222 +++++++ .../nitf/ossimNitfImageHeaderV2_1.h | 1097 ++++ .../support_data/nitf/ossimNitfImageLut.cpp | 47 + .../support_data/nitf/ossimNitfImageLut.h | 48 + .../nitf/ossimNitfImageLutV2_0.cpp | 74 + .../support_data/nitf/ossimNitfImageLutV2_0.h | 48 + .../nitf/ossimNitfImageLutV2_1.cpp | 74 + .../support_data/nitf/ossimNitfImageLutV2_1.h | 41 + .../nitf/ossimNitfLabelHeader.cpp | 26 + .../support_data/nitf/ossimNitfLabelHeader.h | 44 + .../nitf/ossimNitfLabelHeaderV2_0.cpp | 164 + .../nitf/ossimNitfLabelHeaderV2_0.h | 173 + .../nitf/ossimNitfLocalCartographicTag.cpp | 146 + .../nitf/ossimNitfLocalCartographicTag.h | 92 + .../nitf/ossimNitfLocalGeographicTag.cpp | 119 + .../nitf/ossimNitfLocalGeographicTag.h | 82 + .../nitf/ossimNitfNameConversionTables.cpp | 161 + .../nitf/ossimNitfNameConversionTables.h | 28 + .../support_data/nitf/ossimNitfPackedBits.cpp | 58 + .../support_data/nitf/ossimNitfPackedBits.h | 41 + .../nitf/ossimNitfProjectionParameterTag.cpp | 188 + .../nitf/ossimNitfProjectionParameterTag.h | 324 + .../nitf/ossimNitfRegisteredTag.cpp | 27 + .../nitf/ossimNitfRegisteredTag.h | 51 + .../nitf/ossimNitfRegisteredTagFactory.cpp | 103 + .../nitf/ossimNitfRegisteredTagFactory.h | 29 + .../support_data/nitf/ossimNitfRpcATag.cpp | 28 + .../support_data/nitf/ossimNitfRpcATag.h | 38 + .../support_data/nitf/ossimNitfRpcBTag.cpp | 26 + .../support_data/nitf/ossimNitfRpcBTag.h | 33 + .../support_data/nitf/ossimNitfRpcBase.cpp | 741 +++ .../support_data/nitf/ossimNitfRpcBase.h | 546 ++ .../nitf/ossimNitfRpfTagFactory.cpp | 57 + .../nitf/ossimNitfRpfTagFactory.h | 39 + .../support_data/nitf/ossimNitfSensraTag.cpp | 414 ++ .../support_data/nitf/ossimNitfSensraTag.h | 259 + .../support_data/nitf/ossimNitfStdidcTag.cpp | 326 + .../support_data/nitf/ossimNitfStdidcTag.h | 189 + .../nitf/ossimNitfSymbolHeader.cpp | 26 + .../support_data/nitf/ossimNitfSymbolHeader.h | 44 + .../nitf/ossimNitfSymbolHeaderV2_0.cpp | 185 + .../nitf/ossimNitfSymbolHeaderV2_0.h | 236 + .../support_data/nitf/ossimNitfTagFactory.cpp | 35 + .../support_data/nitf/ossimNitfTagFactory.h | 36 + .../nitf/ossimNitfTagFactoryRegistry.cpp | 89 + .../nitf/ossimNitfTagFactoryRegistry.h | 57 + .../nitf/ossimNitfTagInformation.cpp | 158 + .../nitf/ossimNitfTagInformation.h | 100 + .../support_data/nitf/ossimNitfTextHeader.cpp | 26 + .../support_data/nitf/ossimNitfTextHeader.h | 41 + .../nitf/ossimNitfTextHeaderV2_0.cpp | 127 + .../nitf/ossimNitfTextHeaderV2_0.h | 155 + .../support_data/nitf/ossimNitfUse00aTag.cpp | 415 ++ .../support_data/nitf/ossimNitfUse00aTag.h | 260 + .../nitf/ossimNitfVqCompressionHeader.cpp | 267 + .../nitf/ossimNitfVqCompressionHeader.h | 69 + .../ossim_core/support_data/qb/.cvsignore | 2 + .../qb/ossimQuickbirdRpcHeader.cpp | 246 + .../support_data/qb/ossimQuickbirdRpcHeader.h | 55 + .../support_data/qb/ossimQuickbirdTile.cpp | 365 ++ .../support_data/qb/ossimQuickbirdTile.h | 135 + .../ossim_core/support_data/rpf/.cvsignore | 2 + .../rpf/ossimRpfAttributeOffsetRecord.cpp | 58 + .../rpf/ossimRpfAttributeOffsetRecord.h | 275 + .../rpf/ossimRpfAttributeSectionSubheader.cpp | 99 + .../rpf/ossimRpfAttributeSectionSubheader.h | 67 + .../support_data/rpf/ossimRpfAttributes.cpp | 157 + .../support_data/rpf/ossimRpfAttributes.h | 350 + .../rpf/ossimRpfBoundaryRectRecord.cpp | 93 + .../rpf/ossimRpfBoundaryRectRecord.h | 92 + .../ossimRpfBoundaryRectSectionSubheader.cpp | 81 + .../ossimRpfBoundaryRectSectionSubheader.h | 53 + .../rpf/ossimRpfBoundaryRectTable.cpp | 76 + .../rpf/ossimRpfBoundaryRectTable.h | 50 + .../ossimRpfColorConverterOffsetRecord.cpp | 60 + .../rpf/ossimRpfColorConverterOffsetRecord.h | 61 + .../rpf/ossimRpfColorConverterSubsection.cpp | 130 + .../rpf/ossimRpfColorConverterSubsection.h | 52 + .../rpf/ossimRpfColorConverterTable.cpp | 93 + .../rpf/ossimRpfColorConverterTable.h | 45 + .../ossimRpfColorGrayscaleOffsetRecord.cpp | 69 + .../rpf/ossimRpfColorGrayscaleOffsetRecord.h | 44 + .../rpf/ossimRpfColorGrayscaleSubheader.cpp | 59 + .../rpf/ossimRpfColorGrayscaleSubheader.h | 52 + .../rpf/ossimRpfColorGrayscaleTable.cpp | 152 + .../rpf/ossimRpfColorGrayscaleTable.h | 51 + .../ossimRpfCompressionLookupOffsetRecord.cpp | 64 + .../ossimRpfCompressionLookupOffsetRecord.h | 48 + .../rpf/ossimRpfCompressionSection.cpp | 202 + .../rpf/ossimRpfCompressionSection.h | 57 + .../ossimRpfCompressionSectionSubheader.cpp | 62 + .../rpf/ossimRpfCompressionSectionSubheader.h | 63 + .../support_data/rpf/ossimRpfConstants.h | 59 + .../rpf/ossimRpfCoverageSection.cpp | 115 + .../rpf/ossimRpfCoverageSection.h | 118 + .../support_data/rpf/ossimRpfFrame.cpp | 1022 +++ .../support_data/rpf/ossimRpfFrame.h | 176 + .../support_data/rpf/ossimRpfFrameEntry.cpp | 73 + .../support_data/rpf/ossimRpfFrameEntry.h | 59 + .../rpf/ossimRpfFrameFileIndexRecord.cpp | 106 + .../rpf/ossimRpfFrameFileIndexRecord.h | 78 + ...ossimRpfFrameFileIndexSectionSubheader.cpp | 85 + .../ossimRpfFrameFileIndexSectionSubheader.h | 57 + .../rpf/ossimRpfFrameFileIndexSubsection.cpp | 98 + .../rpf/ossimRpfFrameFileIndexSubsection.h | 54 + .../rpf/ossimRpfFrameFileReader.cpp | 140 + .../rpf/ossimRpfFrameFileReader.h | 39 + .../support_data/rpf/ossimRpfHeader.cpp | 641 ++ .../support_data/rpf/ossimRpfHeader.h | 121 + .../rpf/ossimRpfImageDescriptionSubheader.cpp | 111 + .../rpf/ossimRpfImageDescriptionSubheader.h | 126 + ...ossimRpfImageDisplayParameterSubheader.cpp | 81 + .../ossimRpfImageDisplayParameterSubheader.h | 74 + .../rpf/ossimRpfLocationSection.cpp | 185 + .../rpf/ossimRpfLocationSection.h | 115 + .../rpf/ossimRpfMaskSubheader.cpp | 90 + .../support_data/rpf/ossimRpfMaskSubheader.h | 39 + .../rpf/ossimRpfMaskSubsection.cpp | 56 + .../support_data/rpf/ossimRpfMaskSubsection.h | 51 + .../rpf/ossimRpfPathnameRecord.cpp | 81 + .../support_data/rpf/ossimRpfPathnameRecord.h | 49 + .../support_data/rpf/ossimRpfToc.cpp | 338 + .../ossim_core/support_data/rpf/ossimRpfToc.h | 81 + .../support_data/rpf/ossimRpfTocEntry.cpp | 133 + .../support_data/rpf/ossimRpfTocEntry.h | 83 + .../ossim_core/support_data/spot/.cvsignore | 2 + .../spot/ossimSpotDimapSupportData.cpp | 2073 ++++++ .../spot/ossimSpotDimapSupportData.h | 207 + .../ossim_core/support_data/srtm/.cvsignore | 2 + .../support_data/srtm/ossimSrtmFilename.cpp | 184 + .../support_data/srtm/ossimSrtmFilename.h | 25 + .../srtm/ossimSrtmSupportData.cpp | 807 +++ .../support_data/srtm/ossimSrtmSupportData.h | 191 + .../ossim_core/support_data/tiff/.cvsignore | 4 + .../support_data/tiff/ossimGeoTiff.cpp | 2146 +++++++ .../support_data/tiff/ossimGeoTiff.h | 272 + .../support_data/tiff/ossimTiffWorld.cpp | 200 + .../support_data/tiff/ossimTiffWorld.h | 66 + .../support_data/usgs_dem/.cvsignore | 2 + .../support_data/usgs_dem/ossimDemGrid.cpp | 235 + .../support_data/usgs_dem/ossimDemGrid.h | 110 + .../support_data/usgs_dem/ossimDemHeader.cpp | 699 ++ .../support_data/usgs_dem/ossimDemHeader.h | 356 ++ .../support_data/usgs_dem/ossimDemPoint.cpp | 16 + .../support_data/usgs_dem/ossimDemPoint.h | 111 + .../support_data/usgs_dem/ossimDemProfile.cpp | 158 + .../support_data/usgs_dem/ossimDemProfile.h | 96 + .../support_data/usgs_dem/ossimDemStats.cpp | 126 + .../support_data/usgs_dem/ossimDemStats.h | 88 + .../support_data/usgs_dem/ossimDemUtil.cpp | 80 + .../support_data/usgs_dem/ossimDemUtil.h | 57 + Utilities/OSSIM/ossim_core/vec/CMakeLists.txt | 6 + .../OSSIM/ossim_core/vec/shape/.cvsignore | 2 + .../OSSIM/ossim_core/vec/shape/dbfopen.c | 1549 +++++ .../vec/shape/ossimShapeDatabase.cpp | 265 + .../ossim_core/vec/shape/ossimShapeDatabase.h | 136 + .../ossim_core/vec/shape/ossimShapeFile.cpp | 232 + .../ossim_core/vec/shape/ossimShapeFile.h | 327 + .../OSSIM/ossim_core/vec/shape/shapefil.h | 528 ++ .../OSSIM/ossim_core/vec/shape/shpopen.c | 2018 ++++++ .../OSSIM/ossim_core/vec/shape/shptree.c | 983 +++ Utilities/OSSIM/ossim_core/vec/vpf/.cvsignore | 3 + .../vec/vpf/ossimVpfBoundingRecordTable.cpp | 105 + .../vec/vpf/ossimVpfBoundingRecordTable.h | 18 + .../ossim_core/vec/vpf/ossimVpfCoverage.cpp | 211 + .../ossim_core/vec/vpf/ossimVpfCoverage.h | 67 + .../ossim_core/vec/vpf/ossimVpfDatabase.cpp | 205 + .../ossim_core/vec/vpf/ossimVpfDatabase.h | 103 + .../vec/vpf/ossimVpfDatabaseHeader.cpp | 67 + .../vec/vpf/ossimVpfDatabaseHeader.h | 43 + .../ossimVpfDatabaseHeaderTableValidator.cpp | 132 + .../ossimVpfDatabaseHeaderTableValidator.h | 17 + .../ossim_core/vec/vpf/ossimVpfExtent.cpp | 95 + .../OSSIM/ossim_core/vec/vpf/ossimVpfExtent.h | 48 + .../vec/vpf/ossimVpfFeatureClass.cpp | 151 + .../ossim_core/vec/vpf/ossimVpfFeatureClass.h | 92 + .../vec/vpf/ossimVpfFeatureClassSchema.cpp | 148 + .../vec/vpf/ossimVpfFeatureClassSchema.h | 83 + .../ossim_core/vec/vpf/ossimVpfLibrary.cpp | 283 + .../ossim_core/vec/vpf/ossimVpfLibrary.h | 73 + ...ossimVpfLibraryAttributeTableValidator.cpp | 66 + .../ossimVpfLibraryAttributeTableValidator.h | 12 + .../ossim_core/vec/vpf/ossimVpfTable.cpp | 898 +++ .../OSSIM/ossim_core/vec/vpf/ossimVpfTable.h | 103 + .../vec/vpf/ossimVpfTableValidator.h | 18 + Utilities/OSSIM/ossim_core/vec/vpf/vpf.h | 34 + .../OSSIM/ossim_core/vpf_util/.cvsignore | 1 + .../OSSIM/ossim_core/vpf_util/CMakeLists.txt | 6 + .../OSSIM/ossim_core/vpf_util/bitarray.c | 1085 ++++ .../OSSIM/ossim_core/vpf_util/distance.c | 86 + .../OSSIM/ossim_core/vpf_util/linklist.c | 710 +++ .../OSSIM/ossim_core/vpf_util/linklist.h | 69 + Utilities/OSSIM/ossim_core/vpf_util/machine.h | 14 + .../OSSIM/ossim_core/vpf_util/mapgraph.h | 56 + Utilities/OSSIM/ossim_core/vpf_util/polygrf.c | 358 ++ Utilities/OSSIM/ossim_core/vpf_util/polygrf.h | 435 ++ .../OSSIM/ossim_core/vpf_util/projectn.h | 41 + .../OSSIM/ossim_core/vpf_util/protomas.h | 123 + Utilities/OSSIM/ossim_core/vpf_util/set.c | 1303 ++++ Utilities/OSSIM/ossim_core/vpf_util/set.h | 73 + Utilities/OSSIM/ossim_core/vpf_util/system.h | 59 + Utilities/OSSIM/ossim_core/vpf_util/values.h | 92 + Utilities/OSSIM/ossim_core/vpf_util/vpfclip.c | 285 + .../OSSIM/ossim_core/vpf_util/vpfcntnt.c | 510 ++ Utilities/OSSIM/ossim_core/vpf_util/vpfdict.c | 236 + Utilities/OSSIM/ossim_core/vpf_util/vpfdisp.c | 505 ++ Utilities/OSSIM/ossim_core/vpf_util/vpfdisp.h | 31 + Utilities/OSSIM/ossim_core/vpf_util/vpfdraw.c | 1620 +++++ Utilities/OSSIM/ossim_core/vpf_util/vpfdraw.h | 64 + Utilities/OSSIM/ossim_core/vpf_util/vpfinit.h | 44 + Utilities/OSSIM/ossim_core/vpf_util/vpfio.h | 203 + Utilities/OSSIM/ossim_core/vpf_util/vpfmisc.c | 1835 ++++++ Utilities/OSSIM/ossim_core/vpf_util/vpfmisc.h | 108 + Utilities/OSSIM/ossim_core/vpf_util/vpfnear.c | 350 + Utilities/OSSIM/ossim_core/vpf_util/vpfprim.c | 1135 ++++ Utilities/OSSIM/ossim_core/vpf_util/vpfprim.h | 122 + .../OSSIM/ossim_core/vpf_util/vpfptply.c | 499 ++ .../OSSIM/ossim_core/vpf_util/vpfquery.c | 970 +++ Utilities/OSSIM/ossim_core/vpf_util/vpfread.c | 1641 +++++ .../OSSIM/ossim_core/vpf_util/vpfrelat.c | 902 +++ .../OSSIM/ossim_core/vpf_util/vpfrelat.h | 58 + .../OSSIM/ossim_core/vpf_util/vpfselec.c | 1318 ++++ .../OSSIM/ossim_core/vpf_util/vpfselec.h | 41 + Utilities/OSSIM/ossim_core/vpf_util/vpfspx.c | 359 ++ .../OSSIM/ossim_core/vpf_util/vpftable.c | 1058 +++ .../OSSIM/ossim_core/vpf_util/vpftable.h | 320 + Utilities/OSSIM/ossim_core/vpf_util/vpftidx.c | 1959 ++++++ Utilities/OSSIM/ossim_core/vpf_util/vpftidx.h | 145 + Utilities/OSSIM/ossim_core/vpf_util/vpfview.h | 206 + .../OSSIM/ossim_core/vpf_util/vpfwrite.c | 835 +++ Utilities/OSSIM/ossim_core/vpf_util/xmemory.h | 37 + otbIncludeDirectories.cmake | 2 + 1478 files changed, 401765 insertions(+), 1 deletion(-) create mode 100644 Utilities/OSSIM/.CMakeLists.txt.swp create mode 100644 Utilities/OSSIM/CMakeLists.txt create mode 100644 Utilities/OSSIM/ossimConfig.h.in create mode 100644 Utilities/OSSIM/ossim_core/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/CMakeLists.txt create mode 100644 Utilities/OSSIM/ossim_core/base/CMakeLists.txt create mode 100644 Utilities/OSSIM/ossim_core/base/common/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimConnectableDisplayListener.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimConnectableDisplayListener.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimConnectableObjectListener.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimConnectableObjectListener.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimConnectionEvent.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimConnectionEvent.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimContainerEvent.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimContainerEvent.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimDisplayEventListener.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimDisplayEventListener.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimDisplayListEvent.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimDisplayListEvent.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimDisplayRefreshEvent.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimDisplayRefreshEvent.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimElevationManagerEvent.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimElevationManagerEvent.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimElevationManagerEventListener.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimElevationManagerEventListener.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimEvent.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimEvent.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimEventIds.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimImageAoiListener.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimImageAoiListener.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimImageGeometryEvent.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimImageGeometryEvent.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimImageGeometryEventListener.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimImageGeometryEventListener.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimImagePolygonEvent.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimImageRectangleEvent.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimListener.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimListener.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimListenerManager.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimListenerManager.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimMouseEvent.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimMouseEvent.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimMouseListener.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimMouseListener.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimObjectDestructingEvent.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimObjectDestructingEvent.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimObjectEvents.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimProcessListener.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimProcessListener.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimProcessProgressEvent.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimProcessProgressEvent.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimPropertyEvent.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimROIEvent.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimROIEvent.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimROIEventListener.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimROIEventListener.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimRefreshEvent.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimRefreshEvent.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimStateChangedEvent.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimStateChangedEvent.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimViewEvent.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimViewEvent.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimViewListener.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/events/ossimViewListener.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimApplicationUsage.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimApplicationUsage.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimArgumentParser.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimArgumentParser.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimCommon.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimCommon.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimConnectableContainer.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimConnectableContainer.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimConnectableContainerInterface.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimConnectableContainerInterface.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimConnectableObject.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimConnectableObject.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimConstants.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimCplUtil.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimCplUtil.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimCustomEditorWindow.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimCustomEditorWindow.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimDataObject.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimDataObject.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimDate.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimDate.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimDisplayInterface.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimDisplayInterface.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimErrorCodes.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimErrorCodes.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimErrorStatusInterface.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimErrorStatusInterface.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimFactoryBaseTemplate.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimFactoryBaseTemplate.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimFontInformation.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimFontInformation.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimGzStream.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimGzStream.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimHistogramSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimHistogramSource.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimId.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimId.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimIdManager.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimIdManager.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimIoStream.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimIoStream.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimKeywordNames.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimKeywordNames.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimLeastSquaresBilin.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimLeastSquaresBilin.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimMutex.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimMutex.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimNBandLutDataObject.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimNBandLutDataObject.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimObject.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimObject.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimOutputSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimOutputSource.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimPool.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimPoolObject.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimPreferences.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimPreferences.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimProcessInterface.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimProcessInterface.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimPropertyInterface.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimPropertyInterface.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimProtocolStream.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimQuadrilateralMap.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimQuadrilateralMap.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimRectilinearDataObject.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimRectilinearDataObject.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimRefPtr.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimReferenced.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimReferenced.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimRgbLutDataObject.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimRgbLutDataObject.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimRtti.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimRtti.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimScopedLock.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimSource.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimStdOutProgress.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimStdOutProgress.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimStreamBase.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimStreamBase.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimTrace.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimTrace.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimTraceManager.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimTraceManager.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimViewController.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimViewController.h create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimViewInterface.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/common/ossimViewInterface.h create mode 100644 Utilities/OSSIM/ossim_core/base/context/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/base/context/ossimErrorContext.h create mode 100644 Utilities/OSSIM/ossim_core/base/context/ossimNotifyContext.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/context/ossimNotifyContext.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/color_space/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimCmyVector.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimCmyVector.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimHsiVector.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimHsiVector.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimHsvVector.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimHsvVector.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimJpegYCbCrVector.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimJpegYCbCrVector.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimNormRgbVector.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimNormRgbVector.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimRgbVector.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimRgbVector.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/datum/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/datum/datum.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/datum/ossimDatum.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/datum/ossimDatum.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconGridDatum.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconGridDatum.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconGridFile.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconGridFile.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconGridHeader.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconGridHeader.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconNarDatum.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconNarDatum.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconNasDatum.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconNasDatum.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/datum/ossimSevenParamDatum.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/datum/ossimSevenParamDatum.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/datum/ossimThreeParamDatum.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/datum/ossimThreeParamDatum.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/datum/ossimWgs72Datum.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/datum/ossimWgs72Datum.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/datum/ossimWgs84Datum.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/datum/ossimWgs84Datum.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ellipse/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ellipse/ellips.dat create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ellipse/ossimEllipse.c create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ellipse/ossimEllipse.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ellipse/ossimEllipse.hpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ellipse/ossimEllipsoid.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ellipse/ossimEllipsoid.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/geoid/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoid.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoid.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidEgm96.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidEgm96.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidManager.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidManager.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidNgs.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidNgs.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidNgsHeader.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidNgsHeader.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimActiveEdgeTable.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimActiveEdgeTable.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimAxes.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimColumnVector3d.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimColumnVector4d.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimDblGrid.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimDblGrid.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimDirectory.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimDirectory.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimDirectoryData.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimDirectoryData.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimDirectoryTree.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimDirectoryTree.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimDms.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimDms.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimDpt.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimDpt.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimDpt3d.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimDpt3d.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimDrect.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimDrect.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimEcefPoint.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimEcefPoint.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimEcefRay.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimEcefRay.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimEcefVector.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimFilename.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimFilename.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimFpt.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimFpt.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimFpt3d.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimFpt3d.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimGeoPolygon.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimGeoPolygon.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimGeocent.c create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimGeocent.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimGeoref.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimGeoref.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimGpt.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimGpt.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimGrect.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimGrect.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimHexString.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimHexString.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimHistogram.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimHistogram.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimIpt.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimIpt.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimIrect.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimIrect.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimKeyword.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimKeyword.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimKeywordlist.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimKeywordlist.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimLine.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimLine.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimLsrPoint.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimLsrPoint.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimLsrRay.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimLsrRay.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimLsrSpace.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimLsrSpace.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimLsrVector.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimLsrVector.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimMatrix3x3.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimMatrix3x3.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimMatrix4x4.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimMatrix4x4.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimMultiBandHistogram.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimMultiBandHistogram.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimMultiResLevelHistogram.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimMultiResLevelHistogram.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimPolyArea2d.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimPolyArea2d.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimPolyLine.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimPolyLine.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimPolygon.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimPolygon.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimRationalNumber.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimRationalNumber.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimRegExp.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimRegExp.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimString.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimString.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimTempFilename.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimTempFilename.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimVrect.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimVrect.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimXmlAttribute.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimXmlAttribute.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimXmlDocument.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimXmlDocument.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimXmlNode.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimXmlNode.h create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimXmlString.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/data_types/ossimXmlString.h create mode 100644 Utilities/OSSIM/ossim_core/base/factory/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/base/factory/ossimBaseObjectFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/factory/ossimBaseObjectFactory.h create mode 100644 Utilities/OSSIM/ossim_core/base/factory/ossimCustomEditorWindowFactoryBase.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/factory/ossimCustomEditorWindowFactoryBase.h create mode 100644 Utilities/OSSIM/ossim_core/base/factory/ossimCustomEditorWindowRegistry.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/factory/ossimCustomEditorWindowRegistry.h create mode 100644 Utilities/OSSIM/ossim_core/base/factory/ossimDatumFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/factory/ossimDatumFactory.h create mode 100644 Utilities/OSSIM/ossim_core/base/factory/ossimDatumFactory.inc create mode 100644 Utilities/OSSIM/ossim_core/base/factory/ossimEllipsoidFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/factory/ossimEllipsoidFactory.h create mode 100644 Utilities/OSSIM/ossim_core/base/factory/ossimObjectFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/factory/ossimObjectFactory.h create mode 100644 Utilities/OSSIM/ossim_core/base/factory/ossimObjectFactoryRegistry.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/factory/ossimObjectFactoryRegistry.h create mode 100644 Utilities/OSSIM/ossim_core/base/factory/ossimPropertyInterfaceFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/factory/ossimPropertyInterfaceFactory.h create mode 100644 Utilities/OSSIM/ossim_core/base/factory/ossimPropertyInterfaceRegistry.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/factory/ossimPropertyInterfaceRegistry.h create mode 100644 Utilities/OSSIM/ossim_core/base/factory/ossimStreamFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/factory/ossimStreamFactory.h create mode 100644 Utilities/OSSIM/ossim_core/base/factory/ossimStreamFactoryBase.h create mode 100644 Utilities/OSSIM/ossim_core/base/factory/ossimStreamFactoryRegistry.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/factory/ossimStreamFactoryRegistry.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/base/misc/FlexLexer.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/hash/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/base/misc/hash/ossimPointHash.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/hash/ossimTileHash.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/misc/hash/ossimTileHash.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/hash/ossimTiledImageHash.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/misc/hash/ossimTiledImageHash.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/lookup_tables/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimGeoTiffCoordTransformsLut.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimGeoTiffCoordTransformsLut.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimGeoTiffDatumLut.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimGeoTiffDatumLut.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimImageTypeLut.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimImageTypeLut.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimInterleaveTypeLut.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimInterleaveTypeLut.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimLookUpTable.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimLookUpTable.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimScalarTypeLut.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimScalarTypeLut.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimUnitTypeLut.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimUnitTypeLut.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossim2dLinearRegression.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossim2dLinearRegression.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossim2dTo2dTransform.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossim2dTo2dTransform.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimAdjustableParameterInfo.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimAdjustableParameterInfo.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimAdjustableParameterInterface.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimAdjustableParameterInterface.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimAdjustmentInfo.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimAdjustmentInfo.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimAdrData.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimAdrData.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimAffineTransform.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimAffineTransform.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimBilSplitter.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimBilSplitter.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimEndian.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimEndian.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimEquTokenDefines.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimEquTokenizer.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimEquTokenizer.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimEquTokenizer.l create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimQuadTreeWarp.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimQuadTreeWarp.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimRectanglePartitioner.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimRectanglePartitioner.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimUnitConversionTool.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimUnitConversionTool.h create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimUsgsQuad.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/misc/ossimUsgsQuad.h create mode 100644 Utilities/OSSIM/ossim_core/base/property/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimBooleanProperty.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimBooleanProperty.h create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimColorProperty.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimColorProperty.h create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimContainerProperty.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimContainerProperty.h create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimDateProperty.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimDateProperty.h create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimDoubleGridProperty.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimDoubleGridProperty.h create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimFilenameProperty.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimFilenameProperty.h create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimFontProperty.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimFontProperty.h create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimMatrixProperty.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimMatrixProperty.h create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimNumericProperty.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimNumericProperty.h create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimProperty.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimProperty.h create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimStringListProperty.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimStringListProperty.h create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimStringProperty.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimStringProperty.h create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimTextProperty.cpp create mode 100644 Utilities/OSSIM/ossim_core/base/property/ossimTextProperty.h create mode 100644 Utilities/OSSIM/ossim_core/dll_main/Makefile create mode 100644 Utilities/OSSIM/ossim_core/dll_main/ossimDllMain.cpp create mode 100644 Utilities/OSSIM/ossim_core/dll_main/ossimDllMain.h create mode 100644 Utilities/OSSIM/ossim_core/elevation/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/elevation/CMakeLists.txt create mode 100644 Utilities/OSSIM/ossim_core/elevation/formats/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/elevation/formats/dted_cell/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/elevation/formats/dted_cell/ossimDtedFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/elevation/formats/dted_cell/ossimDtedFactory.h create mode 100644 Utilities/OSSIM/ossim_core/elevation/formats/dted_cell/ossimDtedHandler.cpp create mode 100644 Utilities/OSSIM/ossim_core/elevation/formats/dted_cell/ossimDtedHandler.h create mode 100644 Utilities/OSSIM/ossim_core/elevation/formats/ossimElevCellHandler.cpp create mode 100644 Utilities/OSSIM/ossim_core/elevation/formats/ossimElevCellHandler.h create mode 100644 Utilities/OSSIM/ossim_core/elevation/formats/ossimElevCellHandlerFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/elevation/formats/ossimElevCellHandlerFactory.h create mode 100644 Utilities/OSSIM/ossim_core/elevation/formats/srtm/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/elevation/formats/srtm/ossimSrtmFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/elevation/formats/srtm/ossimSrtmFactory.h create mode 100644 Utilities/OSSIM/ossim_core/elevation/formats/srtm/ossimSrtmHandler.cpp create mode 100644 Utilities/OSSIM/ossim_core/elevation/formats/srtm/ossimSrtmHandler.h create mode 100644 Utilities/OSSIM/ossim_core/elevation/ossimElevLess.h create mode 100644 Utilities/OSSIM/ossim_core/elevation/ossimElevManager.cpp create mode 100644 Utilities/OSSIM/ossim_core/elevation/ossimElevManager.h create mode 100644 Utilities/OSSIM/ossim_core/elevation/ossimElevSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/elevation/ossimElevSource.h create mode 100644 Utilities/OSSIM/ossim_core/elevation/ossimElevSourceFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/elevation/ossimElevSourceFactory.h create mode 100644 Utilities/OSSIM/ossim_core/elevation/ossimElevationShapeIdx.cpp create mode 100644 Utilities/OSSIM/ossim_core/elevation/ossimElevationShapeIdx.h create mode 100644 Utilities/OSSIM/ossim_core/fonts/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/fonts/CMakeLists.txt create mode 100644 Utilities/OSSIM/ossim_core/fonts/factory/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/fonts/factory/ossimFontFactoryBase.h create mode 100644 Utilities/OSSIM/ossim_core/fonts/factory/ossimFontFactoryRegistry.cpp create mode 100644 Utilities/OSSIM/ossim_core/fonts/factory/ossimFontFactoryRegistry.h create mode 100644 Utilities/OSSIM/ossim_core/fonts/factory/ossimFreeTypeFontFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/fonts/factory/ossimFreeTypeFontFactory.h create mode 100644 Utilities/OSSIM/ossim_core/fonts/ossimFont.cpp create mode 100644 Utilities/OSSIM/ossim_core/fonts/ossimFont.h create mode 100644 Utilities/OSSIM/ossim_core/fonts/ossimFreeTypeFont.cpp create mode 100644 Utilities/OSSIM/ossim_core/fonts/ossimFreeTypeFont.h create mode 100644 Utilities/OSSIM/ossim_core/fonts/ossimGdBitmapFont.cpp create mode 100644 Utilities/OSSIM/ossim_core/fonts/ossimGdBitmapFont.h create mode 100644 Utilities/OSSIM/ossim_core/fonts/ossimGdSansBold.inc create mode 100644 Utilities/OSSIM/ossim_core/imaging/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/CMakeLists.txt create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/gdfontg.inc create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/gdfontl.inc create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/gdfontmb.inc create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/gdfonts.inc create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/gdfontt.inc create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationEllipseObject.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationEllipseObject.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationFontObject.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationFontObject.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationGdBitmapFont.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationGdBitmapFont.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationLineObject.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationLineObject.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMapGridSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiEllipseObject.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiEllipseObject.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiLineObject.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiLineObject.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiPolyLineObject.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiPolyLineObject.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiPolyObject.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiPolyObject.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationObject.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationObject.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationPolyObject.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationPolyObject.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimEsriShapeFileFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimEsriShapeFileFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGdFont.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGdFontExterns.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationBitmap.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationBitmap.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationEllipseObject.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationEllipseObject.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationFontObject.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationFontObject.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationGdBitmapFont.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationGdBitmapFont.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationLineObject.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationLineObject.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationMultiEllipseObject.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationMultiEllipseObject.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationMultiPolyLineObject.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationMultiPolyLineObject.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationMultiPolyObject.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationMultiPolyObject.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationObject.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationObject.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationPolyLineObject.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationPolyLineObject.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationPolyObject.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationPolyObject.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeographicAnnotationGrid.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeographicAnnotationGrid.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimMapCompositionSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/annotation/ossimMapCompositionSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAOD.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAOD.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAtCorrGridRemapper.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAtCorrGridRemapper.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAtCorrKeywords.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAtCorrRemapper.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAtCorrRemapper.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimGammaRemapper.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimGammaRemapper.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/cache/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/cache/ossimAppFixedTileCache.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/cache/ossimAppFixedTileCache.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/cache/ossimAppTileCache.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/cache/ossimAppTileCache.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/cache/ossimFixedTileCache.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/cache/ossimFixedTileCache.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/cache/ossimTileCache.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/cache/ossimTileCache.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/elevation/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/elevation/ossimElevImageSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/elevation/ossimElevImageSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimAnnotationObjectFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimAnnotationObjectFactory.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageDataFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageDataFactory.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageHandlerFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageHandlerFactory.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageHandlerFactoryBase.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageHandlerFactoryBase.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageHandlerRegistry.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageHandlerRegistry.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageMetaDataWriterFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageMetaDataWriterFactory.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageMetaDataWriterFactoryBase.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageMetaDataWriterFactoryBase.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageMetaDataWriterRegistry.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageMetaDataWriterRegistry.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageReconstructionFilterFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageReconstructionFilterFactory.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageReconstructionFilterRegistry.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageReconstructionFilterRegistry.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageSourceFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageSourceFactory.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageSourceFactoryBase.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageSourceFactoryBase.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageSourceFactoryRegistry.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageSourceFactoryRegistry.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageWriterFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageWriterFactory.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageWriterFactoryBase.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageWriterFactoryBase.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageWriterFactoryRegistry.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/factory/ossimImageWriterFactoryRegistry.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/filters/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/filters/ossimDiscrete3x3HatFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/filters/ossimDiscrete3x3HatFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/filters/ossimDiscreteConvolutionKernel.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/filters/ossimDiscreteConvolutionKernel.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/filters/ossimDiscreteNearestNeighbor.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/filters/ossimFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/filters/ossimFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/filters/ossimFilterTable.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/filters/ossimFilterTable.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/adrg/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimAdrgHeader.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimAdrgHeader.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimAdrgTileSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimAdrgTileSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimDdffield.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimDdffielddefn.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimDdfmodule.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimDdfrecord.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimDdfsubfielddefn.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimDdfutils.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimIso8211.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/aigrid/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/aigrid/ossimArcInfoGridWriter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/aigrid/ossimArcInfoGridWriter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/ccf/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/ccf/ossimCcfHead.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/ccf/ossimCcfHead.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/ccf/ossimCcfTileSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/ccf/ossimCcfTileSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/cibcadrg/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/cibcadrg/ossimCibCadrgTileSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/cibcadrg/ossimCibCadrgTileSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/doqq/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/doqq/ossimDoqqTileSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/doqq/ossimDoqqTileSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/dted/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/dted/ossimDtedElevationImageSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/dted/ossimDtedElevationImageSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/dted/ossimDtedTileSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/dted/ossimDtedTileSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/ers/ossimERSTileSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/ers/ossimERSTileSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/general_raster/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/general_raster/ossimGeneralRasterInfo.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/general_raster/ossimGeneralRasterInfo.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/general_raster/ossimGeneralRasterTileSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/general_raster/ossimGeneralRasterTileSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/general_raster/ossimGeneralRasterWriter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/general_raster/ossimGeneralRasterWriter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/jpeg/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/jpeg/ossimJpegTileSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/jpeg/ossimJpegTileSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/jpeg/ossimJpegWriter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/jpeg/ossimJpegWriter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/landsat/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/landsat/ossimLandsatTileSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/landsat/ossimLandsatTileSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/nitf/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/nitf/ossimNitfTileSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/nitf/ossimNitfTileSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/nitf/ossimNitfWriter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/nitf/ossimNitfWriter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/nitf/ossimQuickbirdNitfTileSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/nitf/ossimQuickbirdNitfTileSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/ossimImageFileWriter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/ossimImageFileWriter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/ossimImageHandler.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/ossimImageHandler.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/srtm/ossimSrtmTileSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/srtm/ossimSrtmTileSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/tiff/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimQuickbirdTiffTileSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimQuickbirdTiffTileSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimTiffOverviewBuilder.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimTiffOverviewBuilder.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimTiffTileSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimTiffTileSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimTiffWriter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimTiffWriter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/usgs_dem/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/usgs_dem/ossimUsgsDemTileSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/usgs_dem/ossimUsgsDemTileSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/vpf/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationCoverageInfo.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationCoverageInfo.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationFeatureInfo.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationFeatureInfo.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationLibraryInfo.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationLibraryInfo.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfTileSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfTileSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/histogram/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/histogram/ossimHistogramWriter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/histogram/ossimHistogramWriter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/histogram/ossimImageHistogramSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/histogram/ossimImageHistogramSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/metadata/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/metadata/ossimEnviHeaderFileWriter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/metadata/ossimEnviHeaderFileWriter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/metadata/ossimFgdcFileWriter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/metadata/ossimFgdcFileWriter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/metadata/ossimGeomFileWriter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/metadata/ossimGeomFileWriter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/metadata/ossimJpegWorldFileWriter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/metadata/ossimJpegWorldFileWriter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/metadata/ossimMetadataFileWriter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/metadata/ossimMetadataFileWriter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/metadata/ossimReadmeFileWriter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/metadata/ossimReadmeFileWriter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/metadata/ossimTiffWorldFileWriter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/metadata/ossimTiffWorldFileWriter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/misc/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/misc/ossimPixelFlipper.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/misc/ossimPixelFlipper.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/misc/ossimVertexExtractor.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/misc/ossimVertexExtractor.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimIgenGenerator.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimIgenGenerator.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimImageChain.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimImageChain.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimImageData.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimImageData.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimImageDataHelper.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimImageDataHelper.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimImageDisplayWriter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimImageDisplayWriter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimImageMetaData.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimImageMetaData.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimImageShapeFileIndex.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimImageShapeFileIndex.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimImageSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimImageSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimImageSourceInterface.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimImageSourceInterface.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimImageSourceSequencer.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimImageSourceSequencer.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimImageStatisticsSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimImageStatisticsSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimImageWriter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimImageWriter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimRgbImage.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimRgbImage.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimS16ImageData.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimS16ImageData.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimTiling.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimTiling.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimU11ImageData.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimU11ImageData.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimU16ImageData.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimU16ImageData.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimU8ImageData.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/ossimU8ImageData.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/patch/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/patch/ossimTilePatch.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/patch/ossimTilePatch.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/reconstruction/ossimMeanMedianFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/reconstruction/ossimMeanMedianFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/remap_tables/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedRemapTable.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedRemapTable.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedU11RemapTable.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedU11RemapTable.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedU16RemapTable.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedU16RemapTable.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedU8RemapTable.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedU8RemapTable.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/resample/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/resample/ossimFilterResampler.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/resample/ossimFilterResampler.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/resample/ossimResampler.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/resample/ossimResampler.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossim3x3ConvolutionFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossim3x3ConvolutionFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandAverageFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandAverageFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandClipFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandClipFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandMergeSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandMergeSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandSelector.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandSelector.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBlendMosaic.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBlendMosaic.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBrightnessContrastSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBrightnessContrastSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBrightnessMatch.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBrightnessMatch.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBumpShadeTileSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBumpShadeTileSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimCacheTileSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimCacheTileSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimCastTileSourceFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimCastTileSourceFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimClosestToCenterCombiner.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimClosestToCenterCombiner.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimColorNormalizedFusion.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimColorNormalizedFusion.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimConvolutionFilter1D.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimConvolutionFilter1D.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimConvolutionSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimConvolutionSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEastingNorthingCutter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEastingNorthingCutter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEdgeFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEdgeFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEquationCombiner.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEquationCombiner.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEsriShapeFileCutter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEsriShapeFileCutter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimFeatherMosaic.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimFeatherMosaic.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimFftFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimFftFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimFusionCombiner.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimFusionCombiner.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimGeoPolyCutter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimGeoPolyCutter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistoMatchRemapper.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistoMatchRemapper.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramEqualization.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramEqualization.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramMatchFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramMatchFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramRemapper.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramRemapper.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramThreshholdFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramThreshholdFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHsiRemapper.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHsiRemapper.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHsiToRgbSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHsiToRgbSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHsvToRgbSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHsvToRgbSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageCombiner.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageCombiner.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageGaussianFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageGaussianFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageMosaic.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageMosaic.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageRenderer.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageRenderer.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageSharpenFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageSharpenFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageSourceFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageSourceFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageSourceHistogramFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageSourceHistogramFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageToPlaneNormalFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageToPlaneNormalFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimIndexToRgbLutFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimIndexToRgbLutFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimIntensityAdjustmentFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimIntensityAdjustmentFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimJpegYCbCrToRgbSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimJpegYCbCrToRgbSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimLandsatTopoCorrectionFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimLandsatTopoCorrectionFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimLocalCorrelationFusion.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimLocalCorrelationFusion.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimMaskFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimMaskFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimMaxMosaic.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimMaxMosaic.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimMultiBandHistogramTileSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimMultiBandHistogramTileSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimNBandToIndexFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimNBandToIndexFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimOrthoImageMosaic.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimOrthoImageMosaic.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimPolyCutter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimPolyCutter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRLevelFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRLevelFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRectangleCutFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRectangleCutFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToGreyFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToGreyFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToHsiSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToHsiSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToHsvSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToHsvSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToIndexFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToIndexFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToJpegYCbCrSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToJpegYCbCrSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimSFIMFusion.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimSFIMFusion.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimScalarRemapper.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimScalarRemapper.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimScaleFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimScaleFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimSubImageTileSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimSubImageTileSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimTableRemapper.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimTableRemapper.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimTopographicCorrectionFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimTopographicCorrectionFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimTrimFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimTrimFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimValueAssignImageSourceFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimValueAssignImageSourceFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimVectorRenderer.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimVectorRenderer.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimWatermarkFilter.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimWatermarkFilter.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tonal_balance/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimAtbController.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimAtbController.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimAtbMatchPoint.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimAtbMatchPoint.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimAtbPointSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimAtbPointSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimGridRemapEngine.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimGridRemapEngine.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimGridRemapEngineFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimGridRemapEngineFactory.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimGridRemapSource.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimGridRemapSource.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimHsvGridRemapEngine.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimHsvGridRemapEngine.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimMonoGridRemapEngine.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimMonoGridRemapEngine.h create mode 100644 Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimRgbGridRemapEngine.cpp create mode 100644 Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimRgbGridRemapEngine.h create mode 100644 Utilities/OSSIM/ossim_core/init/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/init/CMakeLists.txt create mode 100644 Utilities/OSSIM/ossim_core/init/ossimInit.cpp create mode 100644 Utilities/OSSIM/ossim_core/init/ossimInit.h create mode 100644 Utilities/OSSIM/ossim_core/libpolyclip/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/libpolyclip/CMakeLists.txt create mode 100644 Utilities/OSSIM/ossim_core/libpolyclip/polyarea.h create mode 100644 Utilities/OSSIM/ossim_core/libpolyclip/polygon0.c create mode 100644 Utilities/OSSIM/ossim_core/libpolyclip/polygon1.c create mode 100644 Utilities/OSSIM/ossim_core/libpolyclip/polyio.c create mode 100644 Utilities/OSSIM/ossim_core/libpolyclip/polyio.h create mode 100644 Utilities/OSSIM/ossim_core/libpolyclip/vectmatr.c create mode 100644 Utilities/OSSIM/ossim_core/libpolyclip/vectmatr.h create mode 100644 Utilities/OSSIM/ossim_core/matrix/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/matrix/CMakeLists.txt create mode 100644 Utilities/OSSIM/ossim_core/matrix/bandmat.cpp create mode 100644 Utilities/OSSIM/ossim_core/matrix/bc.mak create mode 100644 Utilities/OSSIM/ossim_core/matrix/bc32.mak create mode 100644 Utilities/OSSIM/ossim_core/matrix/boolean.h create mode 100644 Utilities/OSSIM/ossim_core/matrix/cc.mak create mode 100644 Utilities/OSSIM/ossim_core/matrix/cholesky.cpp create mode 100644 Utilities/OSSIM/ossim_core/matrix/controlw.h create mode 100644 Utilities/OSSIM/ossim_core/matrix/evalue.cpp create mode 100644 Utilities/OSSIM/ossim_core/matrix/example.txt create mode 100644 Utilities/OSSIM/ossim_core/matrix/fft.cpp create mode 100644 Utilities/OSSIM/ossim_core/matrix/gnu.mak create mode 100644 Utilities/OSSIM/ossim_core/matrix/hholder.cpp create mode 100644 Utilities/OSSIM/ossim_core/matrix/include.h create mode 100644 Utilities/OSSIM/ossim_core/matrix/jacobi.cpp create mode 100644 Utilities/OSSIM/ossim_core/matrix/ms.mak create mode 100644 Utilities/OSSIM/ossim_core/matrix/ms_nt.mak create mode 100644 Utilities/OSSIM/ossim_core/matrix/myexcept.cpp create mode 100644 Utilities/OSSIM/ossim_core/matrix/myexcept.h create mode 100644 Utilities/OSSIM/ossim_core/matrix/newfft.cpp create mode 100644 Utilities/OSSIM/ossim_core/matrix/newmat.h create mode 100644 Utilities/OSSIM/ossim_core/matrix/newmat.txt create mode 100644 Utilities/OSSIM/ossim_core/matrix/newmat1.cpp create mode 100644 Utilities/OSSIM/ossim_core/matrix/newmat2.cpp create mode 100644 Utilities/OSSIM/ossim_core/matrix/newmat3.cpp create mode 100644 Utilities/OSSIM/ossim_core/matrix/newmat4.cpp create mode 100644 Utilities/OSSIM/ossim_core/matrix/newmat5.cpp create mode 100644 Utilities/OSSIM/ossim_core/matrix/newmat6.cpp create mode 100644 Utilities/OSSIM/ossim_core/matrix/newmat7.cpp create mode 100644 Utilities/OSSIM/ossim_core/matrix/newmat8.cpp create mode 100644 Utilities/OSSIM/ossim_core/matrix/newmat9.cpp create mode 100644 Utilities/OSSIM/ossim_core/matrix/newmatap.h create mode 100644 Utilities/OSSIM/ossim_core/matrix/newmatex.cpp create mode 100644 Utilities/OSSIM/ossim_core/matrix/newmatio.h create mode 100644 Utilities/OSSIM/ossim_core/matrix/newmatnl.cpp create mode 100644 Utilities/OSSIM/ossim_core/matrix/newmatnl.h create mode 100644 Utilities/OSSIM/ossim_core/matrix/newmatrc.h create mode 100644 Utilities/OSSIM/ossim_core/matrix/newmatrm.cpp create mode 100644 Utilities/OSSIM/ossim_core/matrix/newmatrm.h create mode 100644 Utilities/OSSIM/ossim_core/matrix/nl_ex.txt create mode 100644 Utilities/OSSIM/ossim_core/matrix/precisio.h create mode 100644 Utilities/OSSIM/ossim_core/matrix/sl_ex.txt create mode 100644 Utilities/OSSIM/ossim_core/matrix/solution.cpp create mode 100644 Utilities/OSSIM/ossim_core/matrix/solution.h create mode 100644 Utilities/OSSIM/ossim_core/matrix/sort.cpp create mode 100644 Utilities/OSSIM/ossim_core/matrix/submat.cpp create mode 100644 Utilities/OSSIM/ossim_core/matrix/svd.cpp create mode 100644 Utilities/OSSIM/ossim_core/matrix/test_exc.txt create mode 100644 Utilities/OSSIM/ossim_core/matrix/watco_nt.mak create mode 100644 Utilities/OSSIM/ossim_core/matrix/watcom.mak create mode 100644 Utilities/OSSIM/ossim_core/parallel/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/parallel/CMakeLists.txt create mode 100644 Utilities/OSSIM/ossim_core/parallel/ossimIgen.cpp create mode 100644 Utilities/OSSIM/ossim_core/parallel/ossimIgen.h create mode 100644 Utilities/OSSIM/ossim_core/parallel/ossimImageMpiMWriterSequenceConnection.cpp create mode 100644 Utilities/OSSIM/ossim_core/parallel/ossimImageMpiMWriterSequenceConnection.h create mode 100644 Utilities/OSSIM/ossim_core/parallel/ossimImageMpiSWriterSequenceConnection.cpp create mode 100644 Utilities/OSSIM/ossim_core/parallel/ossimImageMpiSWriterSequenceConnection.h create mode 100644 Utilities/OSSIM/ossim_core/parallel/ossimMpi.cpp create mode 100644 Utilities/OSSIM/ossim_core/parallel/ossimMpi.h create mode 100644 Utilities/OSSIM/ossim_core/parallel/ossimOrthoIgen.cpp create mode 100644 Utilities/OSSIM/ossim_core/parallel/ossimOrthoIgen.h create mode 100644 Utilities/OSSIM/ossim_core/plugin/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/plugin/CMakeLists.txt create mode 100644 Utilities/OSSIM/ossim_core/plugin/ossimDynamicLibrary.cpp create mode 100644 Utilities/OSSIM/ossim_core/plugin/ossimDynamicLibrary.h create mode 100644 Utilities/OSSIM/ossim_core/plugin/ossimPluginLibrary.cpp create mode 100644 Utilities/OSSIM/ossim_core/plugin/ossimPluginLibrary.h create mode 100644 Utilities/OSSIM/ossim_core/plugin/ossimSharedObjectBridge.cpp create mode 100644 Utilities/OSSIM/ossim_core/plugin/ossimSharedObjectBridge.h create mode 100644 Utilities/OSSIM/ossim_core/plugin/ossimSharedPluginRegistry.cpp create mode 100644 Utilities/OSSIM/ossim_core/plugin/ossimSharedPluginRegistry.h create mode 100644 Utilities/OSSIM/ossim_core/projections/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/projections/CMakeLists.txt create mode 100644 Utilities/OSSIM/ossim_core/projections/factory/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/projections/factory/ossimImageViewTransformFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/factory/ossimImageViewTransformFactory.h create mode 100644 Utilities/OSSIM/ossim_core/projections/factory/ossimMapProjectionFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/factory/ossimMapProjectionFactory.h create mode 100644 Utilities/OSSIM/ossim_core/projections/factory/ossimMiscProjectionFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/factory/ossimMiscProjectionFactory.h create mode 100644 Utilities/OSSIM/ossim_core/projections/factory/ossimNitfProjectionFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/factory/ossimNitfProjectionFactory.h create mode 100644 Utilities/OSSIM/ossim_core/projections/factory/ossimPcsCodeProjectionFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/factory/ossimPcsCodeProjectionFactory.h create mode 100644 Utilities/OSSIM/ossim_core/projections/factory/ossimProjectionFactoryBase.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/factory/ossimProjectionFactoryBase.h create mode 100644 Utilities/OSSIM/ossim_core/projections/factory/ossimProjectionFactoryRegistry.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/factory/ossimProjectionFactoryRegistry.h create mode 100644 Utilities/OSSIM/ossim_core/projections/factory/ossimProjectionViewControllerFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/factory/ossimProjectionViewControllerFactory.h create mode 100644 Utilities/OSSIM/ossim_core/projections/factory/ossimSensorModelFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/factory/ossimSensorModelFactory.h create mode 100644 Utilities/OSSIM/ossim_core/projections/factory/ossimSrsProjectionFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/factory/ossimSrsProjectionFactory.h create mode 100644 Utilities/OSSIM/ossim_core/projections/factory/ossimStatePlaneProjectionFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/factory/ossimStatePlaneProjectionFactory.h create mode 100644 Utilities/OSSIM/ossim_core/projections/factory/ossimTiffProjectionFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/factory/ossimTiffProjectionFactory.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimAlbersProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimAlbersProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimAzimEquDistProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimAzimEquDistProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimBngProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimBngProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimBonneProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimBonneProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimCadrgProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimCadrgProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimCassiniProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimCassiniProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimCylEquAreaProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimCylEquAreaProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimEckert4Projection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimEckert4Projection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimEckert6Projection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimEckert6Projection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimEquDistCylProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimEquDistCylProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimGnomonicProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimGnomonicProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimLambertConformalConicProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimLambertConformalConicProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimLlxyProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimLlxyProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimMapProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimMapProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimMapProjectionInfo.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimMapProjectionInfo.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimMercatorProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimMercatorProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimMgrs.c create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimMgrs.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimMillerProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimMillerProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimMollweidProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimMollweidProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimNewZealandMapGridProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimNewZealandMapGridProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimObliqueMercatorProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimObliqueMercatorProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimOrthoGraphicProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimOrthoGraphicProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimPolarStereoProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimPolarStereoProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimPolarst.c create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimPolarst.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimPolyconicProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimPolyconicProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimSinusoid.c create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimSinusoid.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimSinusoidalProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimSinusoidalProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimSpaceObliqueMercatorProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimSpaceObliqueMercatorProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimStereographicProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimStereographicProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimTranmerc.c create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimTranmerc.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimTransCylEquAreaProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimTransCylEquAreaProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimTransMercatorProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimTransMercatorProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimUps.c create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimUps.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimUpsProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimUpsProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimUpspt.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimUpspt.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimUtm.c create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimUtm.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimUtmProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimUtmProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimUtmpt.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimUtmpt.h create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimVanDerGrintenProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/map_projections/ossimVanDerGrintenProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/ossimAffineProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/ossimAffineProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/ossimBilinearProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/ossimBilinearProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/ossimImageViewAffineTransform.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/ossimImageViewAffineTransform.h create mode 100644 Utilities/OSSIM/ossim_core/projections/ossimImageViewProjectionTransform.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/ossimImageViewProjectionTransform.h create mode 100644 Utilities/OSSIM/ossim_core/projections/ossimImageViewTransform.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/ossimImageViewTransform.h create mode 100644 Utilities/OSSIM/ossim_core/projections/ossimMapViewController.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/ossimMapViewController.h create mode 100644 Utilities/OSSIM/ossim_core/projections/ossimProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/ossimProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/ossimQuadProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/ossimQuadProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/ossimRpcProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/ossimRpcProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/ossimRpcSolver.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/ossimRpcSolver.h create mode 100644 Utilities/OSSIM/ossim_core/projections/ossimStatePlaneProjectionInfo.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/ossimStatePlaneProjectionInfo.h create mode 100644 Utilities/OSSIM/ossim_core/projections/ossimWarpProjection.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/ossimWarpProjection.h create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/coarse_grid/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/coarse_grid/ossimCoarseGridModel.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/coarse_grid/ossimCoarseGridModel.h create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/fcsi/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/fcsi/ossimApplanixEcefModel.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/fcsi/ossimApplanixEcefModel.h create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/fcsi/ossimApplanixUtmModel.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/fcsi/ossimApplanixUtmModel.h create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/fcsi/ossimFcsiModel.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/fcsi/ossimFcsiModel.h create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/landsat/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/landsat/ossimLandSatModel.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/landsat/ossimLandSatModel.h create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/ossimAdjMapModel.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/ossimAdjMapModel.h create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/ossimLensDistortion.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/ossimLensDistortion.h create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/ossimMeanRadialLensDistortion.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/ossimMeanRadialLensDistortion.h create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/ossimNitfMapModel.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/ossimNitfMapModel.h create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/ossimRadialDecentLensDistortion.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/ossimRadialDecentLensDistortion.h create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/ossimSensorModel.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/ossimSensorModel.h create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/rpc/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/rpc/ossimIkonosRpcModel.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/rpc/ossimIkonosRpcModel.h create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/rpc/ossimNitfRpcModel.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/rpc/ossimNitfRpcModel.h create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/rpc/ossimQuickbirdRpcModel.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/rpc/ossimQuickbirdRpcModel.h create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/rpc/ossimRpcModel.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/rpc/ossimRpcModel.h create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/spot/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/spot/ossimSpot5Model.cpp create mode 100644 Utilities/OSSIM/ossim_core/projections/sensor_modeling/spot/ossimSpot5Model.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/support_data/CMakeLists.txt create mode 100644 Utilities/OSSIM/ossim_core/support_data/doqq/ossimDoqq.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/doqq/ossimDoqq.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/dted/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/support_data/dted/ossimDtedAcc.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/dted/ossimDtedAcc.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/dted/ossimDtedDsi.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/dted/ossimDtedDsi.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/dted/ossimDtedHdr.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/dted/ossimDtedHdr.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/dted/ossimDtedRecord.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/dted/ossimDtedRecord.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/dted/ossimDtedUhl.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/dted/ossimDtedUhl.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/dted/ossimDtedVol.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/dted/ossimDtedVol.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/envi/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/support_data/envi/ossimEnviHeader.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/envi/ossimEnviHeader.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/ers/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/support_data/ers/ossimERS.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/ers/ossimERS.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/esri/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/support_data/esri/ossimAigBounds.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/esri/ossimAigBounds.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/esri/ossimAigDataFileHeader.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/esri/ossimAigDataFileHeader.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/esri/ossimAigHeader.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/esri/ossimAigHeader.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/esri/ossimAigIndexFileHeader.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/esri/ossimAigIndexFileHeader.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/esri/ossimAigStatistics.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/esri/ossimAigStatistics.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/fcsi/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/support_data/fcsi/ossimApplanixEOFile.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/fcsi/ossimApplanixEOFile.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/ff_l7/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/support_data/ff_l7/ossimFfL5.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/ff_l7/ossimFfL5.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/ff_l7/ossimFfL7.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/ff_l7/ossimFfL7.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/ff_revb/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/support_data/ff_revb/ossimFfRevb.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/ff_revb/ossimFfRevb.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/ff_revc/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/support_data/ff_revc/ossimFfRevc.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/ff_revc/ossimFfRevc.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/ikonos/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/support_data/ikonos/ossimIkonosMetaData.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/ikonos/ossimIkonosMetaData.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/ikonos/ossimSpaceImagingGeom.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/ikonos/ossimSpaceImagingGeom.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfBlockaTag.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfBlockaTag.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfCommon.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfCommon.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfCompressionHeader.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfCompressionHeader.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfDataExtensionSegment.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfDataExtensionSegment.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfDataExtensionSegmentV2_0.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfDataExtensionSegmentV2_0.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfEmbeddedRpfDes.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfEmbeddedRpfDes.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfEmbeddedRpfHeader.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfEmbeddedRpfHeader.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfFile.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfFile.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfFileHeader.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfFileHeader.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfFileHeaderV2_0.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfFileHeaderV2_0.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfFileHeaderV2_1.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfFileHeaderV2_1.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfGeoPositioningTag.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfGeoPositioningTag.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfImageBand.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfImageBand.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfImageBandV2_0.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfImageBandV2_0.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfImageBandV2_1.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfImageBandV2_1.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfImageHeader.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfImageHeader.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfImageHeaderV2_0.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfImageHeaderV2_0.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfImageHeaderV2_1.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfImageHeaderV2_1.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfImageLut.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfImageLut.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfImageLutV2_0.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfImageLutV2_0.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfImageLutV2_1.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfImageLutV2_1.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfLabelHeader.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfLabelHeader.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfLabelHeaderV2_0.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfLabelHeaderV2_0.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfLocalCartographicTag.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfLocalCartographicTag.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfLocalGeographicTag.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfLocalGeographicTag.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfNameConversionTables.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfNameConversionTables.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfPackedBits.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfPackedBits.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfProjectionParameterTag.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfProjectionParameterTag.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfRegisteredTag.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfRegisteredTag.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfRegisteredTagFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfRegisteredTagFactory.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfRpcATag.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfRpcATag.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfRpcBTag.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfRpcBTag.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfRpcBase.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfRpcBase.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfRpfTagFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfRpfTagFactory.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfSensraTag.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfSensraTag.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfStdidcTag.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfStdidcTag.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfSymbolHeader.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfSymbolHeader.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfSymbolHeaderV2_0.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfSymbolHeaderV2_0.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfTagFactory.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfTagFactory.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfTagFactoryRegistry.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfTagFactoryRegistry.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfTagInformation.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfTagInformation.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfTextHeader.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfTextHeader.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfTextHeaderV2_0.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfTextHeaderV2_0.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfUse00aTag.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfUse00aTag.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfVqCompressionHeader.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/nitf/ossimNitfVqCompressionHeader.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/qb/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/support_data/qb/ossimQuickbirdRpcHeader.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/qb/ossimQuickbirdRpcHeader.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/qb/ossimQuickbirdTile.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/qb/ossimQuickbirdTile.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfAttributeOffsetRecord.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfAttributeOffsetRecord.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfAttributeSectionSubheader.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfAttributeSectionSubheader.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfAttributes.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfAttributes.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfBoundaryRectRecord.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfBoundaryRectRecord.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfBoundaryRectSectionSubheader.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfBoundaryRectSectionSubheader.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfBoundaryRectTable.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfBoundaryRectTable.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfColorConverterOffsetRecord.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfColorConverterOffsetRecord.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfColorConverterSubsection.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfColorConverterSubsection.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfColorConverterTable.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfColorConverterTable.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfColorGrayscaleOffsetRecord.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfColorGrayscaleOffsetRecord.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfColorGrayscaleSubheader.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfColorGrayscaleSubheader.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfColorGrayscaleTable.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfColorGrayscaleTable.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfCompressionLookupOffsetRecord.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfCompressionLookupOffsetRecord.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfCompressionSection.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfCompressionSection.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfCompressionSectionSubheader.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfCompressionSectionSubheader.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfConstants.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfCoverageSection.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfCoverageSection.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfFrame.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfFrame.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfFrameEntry.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfFrameEntry.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfFrameFileIndexRecord.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfFrameFileIndexRecord.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfFrameFileIndexSectionSubheader.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfFrameFileIndexSectionSubheader.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfFrameFileIndexSubsection.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfFrameFileIndexSubsection.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfFrameFileReader.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfFrameFileReader.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfHeader.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfHeader.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfImageDescriptionSubheader.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfImageDescriptionSubheader.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfImageDisplayParameterSubheader.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfImageDisplayParameterSubheader.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfLocationSection.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfLocationSection.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfMaskSubheader.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfMaskSubheader.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfMaskSubsection.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfMaskSubsection.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfPathnameRecord.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfPathnameRecord.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfToc.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfToc.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfTocEntry.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/rpf/ossimRpfTocEntry.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/spot/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/support_data/spot/ossimSpotDimapSupportData.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/spot/ossimSpotDimapSupportData.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/srtm/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/support_data/srtm/ossimSrtmFilename.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/srtm/ossimSrtmFilename.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/srtm/ossimSrtmSupportData.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/srtm/ossimSrtmSupportData.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/tiff/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/support_data/tiff/ossimGeoTiff.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/tiff/ossimGeoTiff.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/tiff/ossimTiffWorld.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/tiff/ossimTiffWorld.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/usgs_dem/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/support_data/usgs_dem/ossimDemGrid.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/usgs_dem/ossimDemGrid.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/usgs_dem/ossimDemHeader.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/usgs_dem/ossimDemHeader.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/usgs_dem/ossimDemPoint.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/usgs_dem/ossimDemPoint.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/usgs_dem/ossimDemProfile.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/usgs_dem/ossimDemProfile.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/usgs_dem/ossimDemStats.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/usgs_dem/ossimDemStats.h create mode 100644 Utilities/OSSIM/ossim_core/support_data/usgs_dem/ossimDemUtil.cpp create mode 100644 Utilities/OSSIM/ossim_core/support_data/usgs_dem/ossimDemUtil.h create mode 100644 Utilities/OSSIM/ossim_core/vec/CMakeLists.txt create mode 100644 Utilities/OSSIM/ossim_core/vec/shape/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/vec/shape/dbfopen.c create mode 100644 Utilities/OSSIM/ossim_core/vec/shape/ossimShapeDatabase.cpp create mode 100644 Utilities/OSSIM/ossim_core/vec/shape/ossimShapeDatabase.h create mode 100644 Utilities/OSSIM/ossim_core/vec/shape/ossimShapeFile.cpp create mode 100644 Utilities/OSSIM/ossim_core/vec/shape/ossimShapeFile.h create mode 100644 Utilities/OSSIM/ossim_core/vec/shape/shapefil.h create mode 100644 Utilities/OSSIM/ossim_core/vec/shape/shpopen.c create mode 100644 Utilities/OSSIM/ossim_core/vec/shape/shptree.c create mode 100644 Utilities/OSSIM/ossim_core/vec/vpf/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/vec/vpf/ossimVpfBoundingRecordTable.cpp create mode 100644 Utilities/OSSIM/ossim_core/vec/vpf/ossimVpfBoundingRecordTable.h create mode 100644 Utilities/OSSIM/ossim_core/vec/vpf/ossimVpfCoverage.cpp create mode 100644 Utilities/OSSIM/ossim_core/vec/vpf/ossimVpfCoverage.h create mode 100644 Utilities/OSSIM/ossim_core/vec/vpf/ossimVpfDatabase.cpp create mode 100644 Utilities/OSSIM/ossim_core/vec/vpf/ossimVpfDatabase.h create mode 100644 Utilities/OSSIM/ossim_core/vec/vpf/ossimVpfDatabaseHeader.cpp create mode 100644 Utilities/OSSIM/ossim_core/vec/vpf/ossimVpfDatabaseHeader.h create mode 100644 Utilities/OSSIM/ossim_core/vec/vpf/ossimVpfDatabaseHeaderTableValidator.cpp create mode 100644 Utilities/OSSIM/ossim_core/vec/vpf/ossimVpfDatabaseHeaderTableValidator.h create mode 100644 Utilities/OSSIM/ossim_core/vec/vpf/ossimVpfExtent.cpp create mode 100644 Utilities/OSSIM/ossim_core/vec/vpf/ossimVpfExtent.h create mode 100644 Utilities/OSSIM/ossim_core/vec/vpf/ossimVpfFeatureClass.cpp create mode 100644 Utilities/OSSIM/ossim_core/vec/vpf/ossimVpfFeatureClass.h create mode 100644 Utilities/OSSIM/ossim_core/vec/vpf/ossimVpfFeatureClassSchema.cpp create mode 100644 Utilities/OSSIM/ossim_core/vec/vpf/ossimVpfFeatureClassSchema.h create mode 100644 Utilities/OSSIM/ossim_core/vec/vpf/ossimVpfLibrary.cpp create mode 100644 Utilities/OSSIM/ossim_core/vec/vpf/ossimVpfLibrary.h create mode 100644 Utilities/OSSIM/ossim_core/vec/vpf/ossimVpfLibraryAttributeTableValidator.cpp create mode 100644 Utilities/OSSIM/ossim_core/vec/vpf/ossimVpfLibraryAttributeTableValidator.h create mode 100644 Utilities/OSSIM/ossim_core/vec/vpf/ossimVpfTable.cpp create mode 100644 Utilities/OSSIM/ossim_core/vec/vpf/ossimVpfTable.h create mode 100644 Utilities/OSSIM/ossim_core/vec/vpf/ossimVpfTableValidator.h create mode 100644 Utilities/OSSIM/ossim_core/vec/vpf/vpf.h create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/.cvsignore create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/CMakeLists.txt create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/bitarray.c create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/distance.c create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/linklist.c create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/linklist.h create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/machine.h create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/mapgraph.h create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/polygrf.c create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/polygrf.h create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/projectn.h create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/protomas.h create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/set.c create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/set.h create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/system.h create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/values.h create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpfclip.c create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpfcntnt.c create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpfdict.c create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpfdisp.c create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpfdisp.h create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpfdraw.c create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpfdraw.h create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpfinit.h create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpfio.h create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpfmisc.c create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpfmisc.h create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpfnear.c create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpfprim.c create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpfprim.h create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpfptply.c create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpfquery.c create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpfread.c create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpfrelat.c create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpfrelat.h create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpfselec.c create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpfselec.h create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpfspx.c create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpftable.c create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpftable.h create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpftidx.c create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpftidx.h create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpfview.h create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/vpfwrite.c create mode 100644 Utilities/OSSIM/ossim_core/vpf_util/xmemory.h diff --git a/Utilities/CMakeLists.txt b/Utilities/CMakeLists.txt index 696564fbc9..fc5cf89183 100755 --- a/Utilities/CMakeLists.txt +++ b/Utilities/CMakeLists.txt @@ -4,7 +4,7 @@ IF(NOT OTB_USE_EXTERNAL_ITK) SUBDIRS( ITK ) ENDIF(NOT OTB_USE_EXTERNAL_ITK) -SUBDIRS( BGL otbsvm ) +SUBDIRS( BGL otbsvm OSSIM) IF(BUILD_TESTING) SUBDIRS( Dart ) diff --git a/Utilities/OSSIM/.CMakeLists.txt.swp b/Utilities/OSSIM/.CMakeLists.txt.swp new file mode 100644 index 0000000000000000000000000000000000000000..ab1e1d707a050a51dc937442d53ac7b12159fc25 GIT binary patch literal 12288 zcmeI2KX21O7{=c+(SbjLFJJ-^&OjWfgb-VDzBDGbFY?(DOjcsM&9#nQH5Um9ff)D( zEDTJ18@5h-3<N6+yiUS^+oa6Z`$~^2>)z*{^Ut@~x=DNFc*fJ#9$?)D`1<iXfB60v zjGh4;Epn9=)xh>DvRS#kV>SA2HK8Sf9v6>7A>6KbX_b0niLh%$TIEWsY;FlD9nWIk z_&9UbT+dtjwf>*^sfP#<fvp6hy(f>`_Z#<&yLY0kjWkFEhyW2F0z`la5CI}U1c<=Z zBcM-q;5R<jH57jS!_HcGp&|lAfCvx)B0vO)01+SpM1Tko0U|&It_Xo~3edg*@Bvl* z0I2=}{JaJ51N9B{1y!J)qpqXQZUTHp9ibFzfZ9c!q5so*9$n2vMFfZd5g-CYfCvx) zB0vO)01+Sp05a;@P9V*4K3B6isoj>RSrZ(exslCd?BgsHfy1Tw;0>OWj=PTE30_qL zZ_k~XZo;mys>^$q;jAnU)M0Dd1Sb5RvmXUK?l~@BXGswSY`KW@S^xN3ssPDDb9r<- z?ssG?hTM<Ce!x4nG}=u7*5_;x|9!41M4F8>KS+w!v|%u>GvH_(VVc`xe%!|;UF4XJ z^Sn%I7O&&Ff^GDqlM7vT_YxnjP3N^JTwCaFOghYTd7^8UeIANoxY4sH@Q{02^F+QQ tLwlnqRi{}|&#Cr`zsy-vHrX^wj-4XO7ird0IqoYM2I2+osMVWl!XL0Z@uL6$ literal 0 HcmV?d00001 diff --git a/Utilities/OSSIM/CMakeLists.txt b/Utilities/OSSIM/CMakeLists.txt new file mode 100644 index 0000000000..dd9b42f9e5 --- /dev/null +++ b/Utilities/OSSIM/CMakeLists.txt @@ -0,0 +1,16 @@ +PROJECT(OSSIM) + +INCLUDE(CheckIncludeFile) +CHECK_INCLUDE_FILES("dirent.h" CMAKE_HAVE_DIRENT_H) +CHECK_INCLUDE_FILES("unistd.h" CMAKE_HAVE_UNISTD_H) +CHECK_INCLUDE_FILES("getopt.h" CMAKE_HAVE_GETOPT_H) +CHECK_INCLUDE_FILES("fcntl.h" CMAKE_HAVE_FCNTL_H) +CHECK_INCLUDE_FILES("dbmalloc.h" CMAKE_HAVE_DBMALLOC_H) +CHECK_INCLUDE_FILES("malloc.h" CMAKE_HAVE_MALLOC_H) +CHECK_INCLUDE_FILES("dlfcn.h" CMAKE_HAVE_DLFCN_H) + +SET(OSSIM_HAS_OPEN_THREADS 0) +CONFIGURE_FILE(${OTB_SOURCE_DIR}/Utilities/OSSIM/ossimConfig.h.in + ${OTB_BINARY_DIR}/Utilities/OSSIM/ossimConfig.h) +INCLUDE_DIRECTORIES(${OTB_BINARY_DIR}/Utilities/OSSIM/) +SUBDIRS(ossim_core) diff --git a/Utilities/OSSIM/ossimConfig.h.in b/Utilities/OSSIM/ossimConfig.h.in new file mode 100644 index 0000000000..144748e4a5 --- /dev/null +++ b/Utilities/OSSIM/ossimConfig.h.in @@ -0,0 +1,125 @@ +/* $Id: ossimConfig.h.in,v 1.23 2005/11/09 19:30:09 gpotts Exp $ */ +#ifndef ossimConfig_HEADER +#define ossimConfig_HEADER + +/* Define if you have dirent.h. */ +#cmakedefine CMAKE_HAVE_DIRENT_H +#ifdef CMAKE_HAVE_DIRENT_H +#define HAVE_DIRENT_H 1 +#else +#define HAVE_DIRENT_H 0 +#endif + +/* Define as 1 if you have unistd.h. */ +#cmakedefine CMAKE_HAVE_UNISTD_H +#ifdef CMAKE_HAVE_UNISTD_H +#define HAVE_UNISTD_H 1 +#else +#define HAVE_UNISTD_H 0 +#endif + +/* Define as 1 if you have getopt.h. */ +#cmakedefine CMAKE_HAVE_GETOPT_H +#ifdef CMAKE_HAVE_GETOPT_H +#define HAVE_GETOPT_H 1 +#else +#define HAVE_GETOPT_H 0 +#endif + +/* Define as 1 if you have fcntl.h. */ +#cmakedefine CMAKE_HAVE_FCNTL_H +#ifdef CMAKE_HAVE_FCNTL_H +#define HAVE_FCNTL_H 1 +#else +#define HAVE_FCNTL_H 0 +#endif + +/* Define as 1 if you have dbmalloc.h. */ +#cmakedefine CMAKE_HAVE_DBMALLOC_H +#ifdef CMAKE_HAVE_DBMALLOC_H +#define HAVE_DBMALLOC_H 1 +#else +#define HAVE_DBMALLOC_H 0 +#endif + +/* Define as 1 if you have malloc.h. */ +#cmakedefine CMAKE_HAVE_MALLOC_H +#ifdef CMAKE_HAVE_MALLOC_H +#define HAVE_MALLOC_H 1 +#else +#define HAVE_MALLOC_H 0 + +#endif + +/* Define as 1 if you have dlfcn.h. */ +#cmakedefine CMAKE_HAVE_DLFCN_H +#ifdef CMAKE_HAVE_DLFCN_H +#define HAVE_DLFCN_H 1 +#else +#define HAVE_DLFCN_H 0 +#endif + +/* Define if you have support for large (64 bit size) files */ +#define HAVE_LARGEFILE_SUPPORT 0 + +/* Define to "1" if you have libz installed, "0" if not. */ +#define OSSIM_HAS_LIBZ 0 + +/* Define to "1" if you have MPI(lam/mpi), "0" if not. */ +#define OSSIM_HAS_MPI 0 + +/* Define to "1" if you have FREETYPE, "0" if not. */ +#define OSSIM_HAS_FREETYPE 0 + +/* Define to "1" if you have GEOTIFF, "0" if not. */ +#define OSSIM_HAS_GEOTIFF 0 + +/* Define to "1" if you have OpenThreads for mutex support, "0" if not. */ +#define OSSIM_HAS_OPEN_THREADS 0 + +/* Enable cvs id strings for use with "ident" application. */ +#define OSSIM_ID_ENABLED 1 + +/* Enable dynamic library support for plugins. + * Usually set to 0 for static applications. + */ +#define OSSIM_DYNAMIC_ENABLED 1 + +/* Define to the correct byte sizes. + * If not available define to 0 so OSSIM uses the defaults + */ +#define OSSIM_SIZEOF_FLOAT 0 +#define OSSIM_SIZEOF_DOUBLE 0 +#define OSSIM_SIZEOF_LONG_LONG 0 +#define OSSIM_SIZEOF_LONG_INT 0 +#define OSSIM_SIZEOF_INT 0 +#define OSSIM_SIZEOF_SHORT_INT 0 + +/* These are OS specific defines */ +#define __OSSIM_LINUX__ 0 +#define __OSSIM_DARWIN__ 0 +#define __OSSIM_ALPHA__ 0 +#define __OSSIM_SGI__ 0 +#define __OSSIM_SUN__ 0 +#define __OSSIM_SUNOS__ 0 +#define __OSSIM_SOLARIS__ 0 +#define __OSSIM_FREEBSD__ 0 +#define __OSSIM_BSD__ 0 +#define __OSSIM_OPENBSD__ 0 +#define __OSSIM_NETBSD__ 0 +#define __OSSIM_OSF__ 0 +#define __OSSIM_SYSV__ 0 +#define __OSSIM_AIX__ 0 +#define __OSSIM_DOS__ 0 +#define __OSSIM_POWERPC__ 0 +#define __OSSIM_BEOS__ 0 +#define __OSSIM_SVR4__ 0 +#define __OSSIM_EMX__ 0 +#define __OSSIM_CYGWIN__ 0 + +#define OSSIM_MAJOR_VERSION_NUMBER @OSSIM_MAJOR_VERSION_NUMBER@ +#define OSSIM_MINOR_VERSION_NUMBER @OSSIM_MINOR_VERSION_NUMBER@ +#define OSSIM_RELEASE_NUMBER @OSSIM_RELEASE_NUMBER@ +#define OSSIM_VERSION @OSSIM_VERSION@ + +#endif /* End of "#ifndef ossimConfig_HEADER" */ diff --git a/Utilities/OSSIM/ossim_core/.cvsignore b/Utilities/OSSIM/ossim_core/.cvsignore new file mode 100644 index 0000000000..7761c4d2a3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/.cvsignore @@ -0,0 +1,2 @@ +Makefile +ossimConfig.h diff --git a/Utilities/OSSIM/ossim_core/CMakeLists.txt b/Utilities/OSSIM/ossim_core/CMakeLists.txt new file mode 100644 index 0000000000..e99ceabf33 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/CMakeLists.txt @@ -0,0 +1,72 @@ +# Commented since we choosed to build one single library to compile ossim +#SUBDIRS(base elevation fonts imaging libpolyclip matrix parallel projections support_data vec vpf_util plugin init) + +FILE(GLOB_RECURSE ossim_base_SRCS "base/*.cpp" "base/*.c") +FILE(GLOB_RECURSE ossim_base_HDRS "base/*.h") + +FILE(GLOB_RECURSE ossim_elevation_SRCS "elevation/*.cpp" "elevation/*.c") +FILE(GLOB_RECURSE ossim_elevation_HDRS "elevation/*.h") + +FILE(GLOB_RECURSE ossim_fonts_SRCS "fonts/*.cpp" "fonts/*.c") +FILE(GLOB_RECURSE ossim_fonts_HDRS "fonts/*.h") + +FILE(GLOB_RECURSE ossim_imaging_SRCS "imaging/*.cpp" "imaging/*.c") +FILE(GLOB_RECURSE ossim_imaging_HDRS "imaging/*.h") + +FILE(GLOB_RECURSE ossim_libpolyclip_SRCS "libpolyclip/*.cpp" "libpolyclip/*.c") +FILE(GLOB_RECURSE ossim_libpolyclip_HDRS "libpolyclip/*.h") + +FILE(GLOB_RECURSE ossim_matrix_SRCS "matrix/*.cpp" "matrix/*.c") +FILE(GLOB_RECURSE ossim_matrix_HDRS "matrix/*.h") + +FILE(GLOB_RECURSE ossim_parallel_SRCS "parallel/*.cpp" "parallel/*.c") +FILE(GLOB_RECURSE ossim_parallel_HDRS "parallel/*.h") + +FILE(GLOB_RECURSE ossim_projections_SRCS "projections/*.cpp" "projections/*.c") +FILE(GLOB_RECURSE ossim_projections_HDRS "projections/*.h") + +FILE(GLOB_RECURSE ossim_support_data_SRCS "support_data/*.cpp" "support_data/*.c") +FILE(GLOB_RECURSE ossim_suport_data_HDRS "support_data/*.h") + +FILE(GLOB_RECURSE ossim_vec_SRCS "vec/*.cpp" "vec/*.c") +FILE(GLOB_RECURSE ossim_vec_HDRS "vec/*.h") + +FILE(GLOB_RECURSE ossim_vpf_util_SRCS "vpf_util/*.cpp" "vpf_util/*.c") +FILE(GLOB_RECURSE ossim_vpf_util_HDRS "vpf_util/*.h") + +FILE(GLOB_RECURSE ossim_plugin_SRCS "plugin/*.cpp" "plugin/*.c") +FILE(GLOB_RECURSE ossim_plugin_HDRS "plugin/*.h") + +FILE(GLOB_RECURSE ossim_init_SRCS "init/*.cpp" "init/*.c") +FILE(GLOB_RECURSE ossim_init_HDRS "init/*.h") + +ADD_LIBRARY(ossim +${ossim_base_SRCS} +${ossim_elevation_SRCS} +${ossim_fonts_SRCS} +${ossim_imaging_SRCS} +${ossim_libpolyclip_SRCS} +${ossim_matrix_SRCS} +${ossim_parallel_SRCS} +${ossim_projections_SRCS} +${ossim_support_data_SRCS} +${ossim_vec_SRCS} +${ossim_vpf_util_SRCS} +${ossim_plugin_SRCS} +${ossim_init_SRCS} +) + +INSTALL_TARGETS(/lib/otb/ ossim) +INSTALL_FILES(/include/otb/Utilities/OSSIM/ossim_core/ "\\.h$" ${ossim_base_HRDS}) +INSTALL_FILES(/include/otb/Utilities/OSSIM/ossim_core/ "\\.h$" ${ossim_elevation_HRDS}) +INSTALL_FILES(/include/otb/Utilities/OSSIM/ossim_core/ "\\.h$" ${ossim_fonts_HRDS}) +INSTALL_FILES(/include/otb/Utilities/OSSIM/ossim_core/ "\\.h$" ${ossim_imaging_HRDS}) +INSTALL_FILES(/include/otb/Utilities/OSSIM/ossim_core/ "\\.h$" ${ossim_libpolyclip_HRDS}) +INSTALL_FILES(/include/otb/Utilities/OSSIM/ossim_core/ "\\.h$" ${ossim_matrix_HRDS}) +INSTALL_FILES(/include/otb/Utilities/OSSIM/ossim_core/ "\\.h$" ${ossim_parallel_HRDS}) +INSTALL_FILES(/include/otb/Utilities/OSSIM/ossim_core/ "\\.h$" ${ossim_projections_HRDS}) +INSTALL_FILES(/include/otb/Utilities/OSSIM/ossim_core/ "\\.h$" ${ossim_support_data_HRDS}) +INSTALL_FILES(/include/otb/Utilities/OSSIM/ossim_core/ "\\.h$" ${ossim_vec_HRDS}) +INSTALL_FILES(/include/otb/Utilities/OSSIM/ossim_core/ "\\.h$" ${ossim_vpf_util_HRDS}) +INSTALL_FILES(/include/otb/Utilities/OSSIM/ossim_core/ "\\.h$" ${ossim_plugin_HRDS}) +INSTALL_FILES(/include/otb/Utilities/OSSIM/ossim_core/ "\\.h$" ${ossim_init_HRDS}) diff --git a/Utilities/OSSIM/ossim_core/base/CMakeLists.txt b/Utilities/OSSIM/ossim_core/base/CMakeLists.txt new file mode 100644 index 0000000000..631a7a4cf0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/CMakeLists.txt @@ -0,0 +1,6 @@ +FILE(GLOB_RECURSE ossim_base_SRCS "*.cpp") +FILE(GLOB_RECURSE ossim_base_HDRS "*.h") +ADD_LIBRARY(ossim_base ${ossim_base_SRCS}) + +INSTALL_TARGETS(/lib/otb/ ossim_base) +INSTALL_FILES(/include/otb/Utilities/OSSIM/ossim_core/ "\\.h$" ${ossim_base_HRDS}) diff --git a/Utilities/OSSIM/ossim_core/base/common/.cvsignore b/Utilities/OSSIM/ossim_core/base/common/.cvsignore new file mode 100644 index 0000000000..3c14b4e6ae --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.lo +.libs diff --git a/Utilities/OSSIM/ossim_core/base/common/events/.cvsignore b/Utilities/OSSIM/ossim_core/base/common/events/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimConnectableDisplayListener.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimConnectableDisplayListener.cpp new file mode 100644 index 0000000000..9ceeab39ba --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimConnectableDisplayListener.cpp @@ -0,0 +1,179 @@ + +//---------------------------------------------------------------------------- +// Copyright (c) 2004, David Burken, all rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +//---------------------------------------------------------------------------- +// $Id: ossimConnectableDisplayListener.cpp,v 1.1 2005/09/11 19:57:50 dburken Exp $ + +#include <base/common/events/ossimConnectableDisplayListener.h> +#include <base/common/ossimConnectableObject.h> +#include <base/common/events/ossimObjectEvents.h> +#include <base/common/events/ossimDisplayListEvent.h> +#include <base/common/events/ossimDisplayRefreshEvent.h> + +#include <base/context/ossimNotifyContext.h> + +RTTI_DEF1(ossimConnectableDisplayListener, + "ossimConnectableDisplayListener", + ossimListener); + +ossimConnectableDisplayListener::ossimConnectableDisplayListener() + : ossimListener() +{} + +void ossimConnectableDisplayListener::processEvent(ossimEvent& event) +{ + switch(event.getId()) + { + case OSSIM_EVENT_OBJECT_DESTRUCTING_ID: + { + ossimObjectDestructingEvent* eventCast = + static_cast<ossimObjectDestructingEvent*>(&event); + objectDestructingEvent(*eventCast); + + break; + } + case OSSIM_EVENT_CONNECTION_CONNECT_ID: + case OSSIM_EVENT_CONNECTION_DISCONNECT_ID: + { + ossimConnectionEvent* eventCast = + static_cast<ossimConnectionEvent*>(&event); + + connectionEvent(*eventCast); + if(event.getId() == OSSIM_EVENT_CONNECTION_DISCONNECT_ID) + { + if(eventCast->isInputDirection()) + { + disconnectInputEvent(*eventCast); + } + else if(eventCast->isOutputDirection()) + { + disconnectOutputEvent(*eventCast); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimConnectableDisplayListener::processEvent, Direction not set\n"; + } + } + else + { + ossimConnectionEvent* eventCast = static_cast<ossimConnectionEvent*>(&event); + + if(eventCast->isInputDirection()) + { + connectInputEvent(*eventCast); + } + else if(eventCast->isOutputDirection()) + { + connectOutputEvent(*eventCast); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) << "ossimConnectableDisplayListener::processEvent, Direction not set\n"; + } + } + break; + } + case OSSIM_EVENT_PROPERTY_ID: + { + ossimPropertyEvent* eventCast = static_cast<ossimPropertyEvent*>(&event); + propertyEvent(*eventCast); + break; + } + case OSSIM_EVENT_ADD_OBJECT_ID: + { + ossimContainerEvent* eventCast = static_cast<ossimContainerEvent*>(&event); + addObjectEvent(*eventCast); + break; + } + case OSSIM_EVENT_REMOVE_OBJECT_ID: + { + ossimContainerEvent* eventCast = static_cast<ossimContainerEvent*>(&event); + removeObjectEvent(*eventCast); + break; + } + case OSSIM_EVENT_REFRESH_ID: + { + ossimRefreshEvent* eventCast = static_cast<ossimRefreshEvent*>(&event); + refreshEvent(*eventCast); + break; + } + case OSSIM_EVENT_DISPLAY_LIST_ID: + { + ossimDisplayListEvent* eventCast = + static_cast<ossimDisplayListEvent*>(&event); + displayListEvent(*eventCast); + break; + } + case OSSIM_EVENT_DISPLAY_REFRESH_ID: + { + ossimDisplayRefreshEvent* eventCast = + static_cast<ossimDisplayRefreshEvent*>(&event); + displayRefreshEvent(*eventCast); + break; + } + default: + { + ossimListener::processEvent(event); + break; + } + } +} + +void ossimConnectableDisplayListener::objectDestructingEvent( + ossimObjectDestructingEvent& /*event*/) +{ +} + +void ossimConnectableDisplayListener::connectionEvent( + ossimConnectionEvent& /* event */) +{} + +void ossimConnectableDisplayListener::disconnectInputEvent( + ossimConnectionEvent& /* event */) +{} + +void ossimConnectableDisplayListener::disconnectOutputEvent( + ossimConnectionEvent& /* event */) +{} + +void ossimConnectableDisplayListener::connectInputEvent( + ossimConnectionEvent& /* event */) +{} + +void ossimConnectableDisplayListener::connectOutputEvent( + ossimConnectionEvent& /* event */) +{} + +void ossimConnectableDisplayListener::propertyEvent( + ossimPropertyEvent& /* event */) +{} + +void ossimConnectableDisplayListener::displayListEvent(ossimDisplayListEvent&) +{} + +void ossimConnectableDisplayListener::displayRefreshEvent( + ossimDisplayRefreshEvent&) +{} + +void ossimConnectableDisplayListener::addObjectEvent( + ossimContainerEvent& /* event */) +{} + +void ossimConnectableDisplayListener::removeObjectEvent( + ossimContainerEvent& /* event */) +{} + +void ossimConnectableDisplayListener::refreshEvent( + ossimRefreshEvent& /* event */) +{} + diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimConnectableDisplayListener.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimConnectableDisplayListener.h new file mode 100644 index 0000000000..a4c0741e31 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimConnectableDisplayListener.h @@ -0,0 +1,109 @@ +//---------------------------------------------------------------------------- +// Copyright (c) 2004, David Burken, all rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: ossimConnectableDisplayListener +// +// This class is intended for connectable displays that wants to be a +// ossimConnectableObjectListener and a ossimDisplayEventListener to avoid +// a triangle inheritance. +// +//---------------------------------------------------------------------------- +// $Id: ossimConnectableDisplayListener.h,v 1.1 2005/09/11 19:57:50 dburken Exp $ + +#ifndef ossimConnectableDisplayListener_HEADER +#define ossimConnectableDisplayListener_HEADER + +#include <base/common/events/ossimListener.h> + +class ossimConnectionEvent; +class ossimObjectDestructingEvent; +class ossimPropertyEvent; +class ossimContainerEvent; +class oossimDisplayListEvent; +class ossimRefreshEvent; +class ossimDisplayListEvent; +class ossimDisplayRefreshEvent; + +/** + * This class is intended for connectable displays that wants to be a + * ossimConnectableObjectListener and a ossimDisplayEventListener to avoid + * a triangle inheritance. + */ +class OSSIMDLLEXPORT ossimConnectableDisplayListener : public ossimListener +{ +public: + + /** default constructor */ + ossimConnectableDisplayListener(); + + /** + * Method called by listener managers. This will in turn call the correct + * xxxEvent method. + * + * @param event Event to handle. + */ + virtual void processEvent(ossimEvent& event); + + /** @param event Event to handle signifying an object destroying. */ + virtual void objectDestructingEvent(ossimObjectDestructingEvent& event); + + /** @param event Event to handle signifying an object connecting. */ + virtual void connectionEvent(ossimConnectionEvent& event); + + /** @param event Event to handle signifying a disconnect input event. */ + virtual void disconnectInputEvent(ossimConnectionEvent& event); + + /** @param event Event to handle signifying an output disconnect event. */ + virtual void disconnectOutputEvent(ossimConnectionEvent& event); + + /** @param event Event to handle signifying a connect input event. */ + virtual void connectInputEvent(ossimConnectionEvent& event); + + /** @param event Event to handle signifying a connect output event. */ + virtual void connectOutputEvent(ossimConnectionEvent& event); + + /** + * @param event Event to handle signifying a property has changed event. + */ + virtual void propertyEvent(ossimPropertyEvent& event); + + /** + * @param event Event to handle signifying a dislay list has changed + * event. + */ + virtual void displayListEvent(ossimDisplayListEvent&); + + /** + * @param event Event to handle signifying a dislay refresh + * is needed. + */ + virtual void displayRefreshEvent(ossimDisplayRefreshEvent&); + + /** + * @param event Event to handle signifying a refresh is needed. + */ + virtual void refreshEvent(ossimRefreshEvent& event); + + /** + * Container Events: + * Typically isued by objects that contain children. If anyone is + * interested, can latch on to this event. Other objects within the + * system might be interest in this event even + */ + + /** @param event Event signifying an object was added to a container. */ + virtual void addObjectEvent(ossimContainerEvent& event); + + /** @param event Event signifying an object was removed from a container. */ + virtual void removeObjectEvent(ossimContainerEvent& event); + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimConnectableObjectListener.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimConnectableObjectListener.cpp new file mode 100644 index 0000000000..073e94e1e0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimConnectableObjectListener.cpp @@ -0,0 +1,102 @@ +//******************************************************************* +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimConnectableObjectListener.cpp,v 1.15 2005/09/17 20:29:37 dburken Exp $ + +#include <base/common/events/ossimConnectableObjectListener.h> +#include <base/common/ossimConnectableObject.h> +#include <base/common/events/ossimObjectEvents.h> +#include <base/context/ossimNotifyContext.h> + +RTTI_DEF1(ossimConnectableObjectListener, + "ossimConnectableObjectListener", + ossimListener); + +void ossimConnectableObjectListener::processEvent(ossimEvent& event) +{ + switch(event.getId()) + { + case OSSIM_EVENT_OBJECT_DESTRUCTING_ID: + { + ossimObjectDestructingEvent* eventCast = static_cast<ossimObjectDestructingEvent*>(&event); + objectDestructingEvent(*eventCast); + + break; + } + case OSSIM_EVENT_CONNECTION_CONNECT_ID: + case OSSIM_EVENT_CONNECTION_DISCONNECT_ID: + { + ossimConnectionEvent* eventCast = static_cast<ossimConnectionEvent*>(&event); + + connectionEvent(*eventCast); + if(event.getId() == OSSIM_EVENT_CONNECTION_DISCONNECT_ID) + { + if(eventCast->isInputDirection()) + { + disconnectInputEvent(*eventCast); + } + else if(eventCast->isOutputDirection()) + { + disconnectOutputEvent(*eventCast); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) << "ossimConnectableObjectListener::processEvent, Direction not set\n"; + } + } + else + { + ossimConnectionEvent* eventCast = static_cast<ossimConnectionEvent*>(&event); + + if(eventCast->isInputDirection()) + { + connectInputEvent(*eventCast); + } + else if(eventCast->isOutputDirection()) + { + connectOutputEvent(*eventCast); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) << "ossimConnectableObjectListener::processEvent, Direction not set\n"; + } + } + break; + } + case OSSIM_EVENT_PROPERTY_ID: + { + ossimPropertyEvent* eventCast = static_cast<ossimPropertyEvent*>(&event); + propertyEvent(*eventCast); + break; + } + case OSSIM_EVENT_ADD_OBJECT_ID: + { + ossimContainerEvent* eventCast = static_cast<ossimContainerEvent*>(&event); + addObjectEvent(*eventCast); + break; + } + case OSSIM_EVENT_REMOVE_OBJECT_ID: + { + ossimContainerEvent* eventCast = static_cast<ossimContainerEvent*>(&event); + removeObjectEvent(*eventCast); + break; + } + case OSSIM_EVENT_REFRESH_ID: + { + ossimRefreshEvent* eventCast = static_cast<ossimRefreshEvent*>(&event); + refreshEvent(*eventCast); + break; + } + default: + { + ossimListener::processEvent(event); + break; + } + } +} diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimConnectableObjectListener.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimConnectableObjectListener.h new file mode 100644 index 0000000000..a6d2fc3767 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimConnectableObjectListener.h @@ -0,0 +1,75 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: A brief description of the contents of the file. +// +// +//************************************************************************* +// $Id: ossimConnectableObjectListener.h,v 1.19 2005/10/13 13:30:33 gpotts Exp $ +#ifndef ossimConnectableObjectListener_HEADER +#define ossimConnectableObjectListener_HEADER + +#include "ossimListener.h" +#include "ossimConnectionEvent.h" +#include "ossimObjectDestructingEvent.h" +#include "ossimPropertyEvent.h" +#include "ossimContainerEvent.h" +#include "ossimRefreshEvent.h" + +class OSSIMDLLEXPORT ossimConnectableObjectListener : public ossimListener +{ +public: + ossimConnectableObjectListener():ossimListener(){} + virtual ~ossimConnectableObjectListener(){} + + virtual void processEvent(ossimEvent& event); + + virtual void objectDestructingEvent(ossimObjectDestructingEvent& /*event*/) + {} + virtual void connectionEvent(ossimConnectionEvent& /* event */) + {} + virtual void disconnectInputEvent(ossimConnectionEvent& /* event */) + {} + virtual void disconnectOutputEvent(ossimConnectionEvent& /* event */) + {} + virtual void connectInputEvent(ossimConnectionEvent& /* event */) + {} + virtual void connectOutputEvent(ossimConnectionEvent& /* event */) + {} + + virtual void propertyEvent(ossimPropertyEvent& /* event */) + {} + + /*! + * Typically isued by objects that contain children. If anyone is + * interested, can latch on to this event. Other objects within the + * system might be interest in this event even + */ + virtual void addObjectEvent(ossimContainerEvent& /* event */) + {} + + virtual void removeObjectEvent(ossimContainerEvent& /* event */) + {} + + virtual void refreshEvent(ossimRefreshEvent& /* event */) + {} +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimConnectionEvent.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimConnectionEvent.cpp new file mode 100644 index 0000000000..edefd4986f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimConnectionEvent.cpp @@ -0,0 +1,127 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimConnectionEvent.cpp,v 1.3 2005/09/17 20:27:50 dburken Exp $ + +#include <base/common/events/ossimConnectionEvent.h> + +RTTI_DEF1(ossimConnectionEvent, "ossimConnectionEvent", ossimEvent); + +ossimConnectionEvent::ossimConnectionEvent(ossimObject* object, long id) + :ossimEvent(object, id), + theDirectionType(OSSIM_DIRECTION_UNKNOWN) +{ +} + +ossimConnectionEvent::ossimConnectionEvent( + ossimObject* object, + long id, + const vector<ossimConnectableObject*>& newList, + const vector<ossimConnectableObject*>& oldList, + ossimConnectionDirectionType whichDirection) + : ossimEvent(object, id), + theNewObjectList(newList), + theOldObjectList(oldList), + theDirectionType(whichDirection) +{ +} + +ossimConnectionEvent::ossimConnectionEvent( + ossimObject* object, + long id, + ossimConnectableObject* newConnectableObject, + ossimConnectableObject* oldConnectableObject, + ossimConnectionDirectionType whichDirection) + : ossimEvent(object, id), + theDirectionType(whichDirection) +{ + if(newConnectableObject) + { + theNewObjectList.push_back(newConnectableObject); + } + if(oldConnectableObject) + { + theOldObjectList.push_back(oldConnectableObject); + } +} + +ossimConnectionEvent::ossimConnectionEvent(const ossimConnectionEvent& rhs) + : ossimEvent(rhs), + theNewObjectList(rhs.theNewObjectList), + theOldObjectList(rhs.theOldObjectList), + theDirectionType(rhs.theDirectionType) +{ +} + +ossimObject* ossimConnectionEvent::dup()const +{ + return new ossimConnectionEvent(*this); +} + +void ossimConnectionEvent::setDirection( + ossimConnectionDirectionType direction) +{ + theDirectionType = direction; +} + +ossimConnectionEvent::ossimConnectionDirectionType ossimConnectionEvent::getDirection()const +{ + return theDirectionType; +} + +ossim_uint32 ossimConnectionEvent::getNumberOfNewObjects()const +{ + return theNewObjectList.size(); +} + +ossim_uint32 ossimConnectionEvent::getNumberOfOldObjects()const +{ + return theOldObjectList.size(); +} + +ossimConnectableObject* ossimConnectionEvent::getOldObject(ossim_uint32 i)const +{ + if(i < getNumberOfOldObjects()) + { + return theOldObjectList[i]; + } + + return (ossimConnectableObject*)NULL; +} + +ossimConnectableObject* ossimConnectionEvent::getNewObject(ossim_uint32 i)const +{ + if(i < getNumberOfNewObjects()) + { + return theNewObjectList[i]; + } + + return (ossimConnectableObject*)NULL; +} + +bool ossimConnectionEvent::isDisconnect()const +{ + return (getId()==OSSIM_EVENT_CONNECTION_DISCONNECT_ID); +} + +bool ossimConnectionEvent::isConnect()const +{ + return (getId()==OSSIM_EVENT_CONNECTION_CONNECT_ID); +} + +bool ossimConnectionEvent::isInputDirection()const +{ + return ((long)theDirectionType & (long)OSSIM_INPUT_DIRECTION); +} + +bool ossimConnectionEvent::isOutputDirection()const +{ + return ((long)theDirectionType & OSSIM_OUTPUT_DIRECTION); +} diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimConnectionEvent.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimConnectionEvent.h new file mode 100644 index 0000000000..6fedc269a1 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimConnectionEvent.h @@ -0,0 +1,76 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimConnectionEvent.h,v 1.12 2005/09/17 20:27:50 dburken Exp $ +#ifndef ossimConnectionEvent_HEADER +#define ossimConnectionEvent_HEADER +#include <base/common/events/ossimEventIds.h> +#include <base/common/events/ossimEvent.h> +#include <base/common/ossimConnectableObject.h> + +class OSSIMDLLEXPORT ossimConnectionEvent : public ossimEvent +{ +public: + enum ossimConnectionDirectionType + { + OSSIM_DIRECTION_UNKNOWN = 0, + OSSIM_INPUT_DIRECTION = 1, + OSSIM_OUTPUT_DIRECTION = 2, + OSSIM_INPUT_OUTPUT_DIRECTION = 3 + }; + + ossimConnectionEvent(ossimObject* object=NULL, + long id=OSSIM_EVENT_NULL_ID); + + ossimConnectionEvent(ossimObject* object, + long id, + const vector<ossimConnectableObject*>& newList, + const vector<ossimConnectableObject*>& oldList, + ossimConnectionDirectionType whichDirection); + + ossimConnectionEvent(ossimObject* object, + long id, + ossimConnectableObject* newConnectableObject, + ossimConnectableObject* oldConnectableObject, + ossimConnectionDirectionType whichDirection); + + ossimConnectionEvent(const ossimConnectionEvent& rhs); + + ossimObject* dup()const; + + virtual void setDirection(ossimConnectionDirectionType direction); + + virtual ossimConnectionDirectionType getDirection()const; + + virtual ossim_uint32 getNumberOfNewObjects()const; + + virtual ossim_uint32 getNumberOfOldObjects()const; + + virtual ossimConnectableObject* getOldObject(ossim_uint32 i=0)const; + + virtual ossimConnectableObject* getNewObject(ossim_uint32 i=0)const; + + virtual bool isDisconnect()const; + + virtual bool isConnect()const; + + virtual bool isInputDirection()const; + + virtual bool isOutputDirection()const; + +protected: + vector<ossimConnectableObject*> theNewObjectList; + vector<ossimConnectableObject*> theOldObjectList; + ossimConnectionDirectionType theDirectionType; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimContainerEvent.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimContainerEvent.cpp new file mode 100644 index 0000000000..90382ff8a3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimContainerEvent.cpp @@ -0,0 +1,38 @@ +//******************************************************************* +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimContainerEvent.cpp,v 1.1 2005/09/17 20:25:33 dburken Exp $ + +#include <base/common/events/ossimContainerEvent.h> + +RTTI_DEF1(ossimContainerEvent, "ossimContainerEvent", ossimEvent); + +ossimContainerEvent::ossimContainerEvent(ossimObject* obj1, + ossimObject* obj2, + long id) + : + ossimEvent(obj1, id), + theAssociatedObject(obj2) +{ +} + +ossimObject* ossimContainerEvent::getAssociatedObject() +{ + return theAssociatedObject; +} + +const ossimObject* ossimContainerEvent::getAssociatedObject()const +{ + return theAssociatedObject; +} + +void ossimContainerEvent::setAssociatedObject(ossimObject* obj) +{ + theAssociatedObject = obj; +} diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimContainerEvent.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimContainerEvent.h new file mode 100644 index 0000000000..fb6fc2f503 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimContainerEvent.h @@ -0,0 +1,41 @@ +//******************************************************************* +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimContainerEvent.h,v 1.3 2005/09/17 20:25:13 dburken Exp $ +#ifndef ossimContainerEvent_HEADER +#define ossimContainerEvent_HEADER +#include <base/common/events/ossimEvent.h> +#include <base/common/events/ossimEventIds.h> + +class OSSIMDLLEXPORT ossimContainerEvent : public ossimEvent +{ +public: + + /** constuctor */ + ossimContainerEvent(ossimObject* obj1,// the object theEvent was sent to. + ossimObject* obj2, // the object associated + long id); + + ossimObject* getAssociatedObject(); + const ossimObject* getAssociatedObject()const; + void setAssociatedObject(ossimObject* obj); + +protected: + + /*! + * This is the object associated with the container event. + * if this was an add then it s the object added to the + * container. + */ + ossimObject* theAssociatedObject; + +TYPE_DATA +}; + +#endif /* end of: "#ifndef ossimContainerEvent_HEADER" */ diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimDisplayEventListener.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimDisplayEventListener.cpp new file mode 100644 index 0000000000..80059e1dc1 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimDisplayEventListener.cpp @@ -0,0 +1,62 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id + +#include "ossimDisplayEventListener.h" +#include "ossimDisplayListEvent.h" +#include "ossimDisplayRefreshEvent.h" + +RTTI_DEF1(ossimDisplayEventListener, "ossimDisplayEventListener", ossimListener); + +ossimDisplayEventListener::ossimDisplayEventListener() + : ossimListener() +{ +} + +ossimDisplayEventListener::~ossimDisplayEventListener() +{ +} + +void ossimDisplayEventListener::processEvent(ossimEvent& event) +{ + ossimDisplayListEvent* displayListEvtPtr = PTR_CAST(ossimDisplayListEvent, &event); + + if(displayListEvtPtr) + { + displayListEvent(*displayListEvtPtr); + } + + ossimDisplayRefreshEvent* displayRefreshEvt = PTR_CAST(ossimDisplayRefreshEvent, &event); + if(displayRefreshEvt) + { + displayRefreshEvent(*displayRefreshEvt); + } + +} + +void ossimDisplayEventListener::displayListEvent(ossimDisplayListEvent&) +{ +} + +void ossimDisplayEventListener::displayRefreshEvent(ossimDisplayRefreshEvent&) +{ +} diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimDisplayEventListener.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimDisplayEventListener.h new file mode 100644 index 0000000000..6a6ea630f0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimDisplayEventListener.h @@ -0,0 +1,43 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id +#ifndef ossimDisplayEventListener_HEADER +#define ossimDisplayEventListener_HEADER + +#include "ossimListener.h" + +class ossimDisplayListEvent; +class ossimDisplayRefreshEvent; + +class OSSIMDLLEXPORT ossimDisplayEventListener : public ossimListener +{ +public: + ossimDisplayEventListener(); + virtual ~ossimDisplayEventListener(); + virtual void processEvent(ossimEvent& event); + virtual void displayListEvent(ossimDisplayListEvent&); + virtual void displayRefreshEvent(ossimDisplayRefreshEvent&); + +TYPE_DATA +}; + +#endif /* End of "#ifndef ossimDisplayEventListener_HEADER". */ diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimDisplayListEvent.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimDisplayListEvent.cpp new file mode 100644 index 0000000000..416e517149 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimDisplayListEvent.cpp @@ -0,0 +1,44 @@ +#include "ossimDisplayListEvent.h" + +RTTI_DEF1(ossimDisplayListEvent, "ossimDisplayListEvent", ossimEvent); + +void ossimDisplayListEvent::addDisplay(void* display) +{ + std::map<void*, void*>::iterator iter = theDisplayMap.find(display); + + if(iter == theDisplayMap.end()) + { + theDisplayMap.insert(std::make_pair(display, display)); + } +} + +void* ossimDisplayListEvent::firstDisplay() +{ + theDisplayIterator = theDisplayMap.begin(); + + if(theDisplayIterator != theDisplayMap.end()) + { + return (*theDisplayIterator).first; + } + + return NULL; +} + +void* ossimDisplayListEvent::nextDisplay() +{ + ++theDisplayIterator; + + if(theDisplayIterator != theDisplayMap.end()) + { + return (*theDisplayIterator).first; + } + + return NULL; +} + +void ossimDisplayListEvent::clearList() +{ + theDisplayMap.clear(); + theDisplayIterator = theDisplayMap.end(); +} + diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimDisplayListEvent.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimDisplayListEvent.h new file mode 100644 index 0000000000..2d5290ca1f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimDisplayListEvent.h @@ -0,0 +1,32 @@ +#ifndef ossimDisplayListEvent_HEADER +#define ossimDisplayListEvent_HEADER +#include "ossimEvent.h" +#include <map> + +class OSSIMDLLEXPORT ossimDisplayListEvent : public ossimEvent +{ +public: + ossimDisplayListEvent(ossimObject* obj = NULL) + :ossimEvent(obj, OSSIM_EVENT_DISPLAY_LIST_ID) + { + theDisplayIterator = theDisplayMap.end(); + } + void addDisplay(void* display); + virtual ossimObject* dup()const + { + return new ossimDisplayListEvent(*this); + } + + void* firstDisplay(); + void* nextDisplay(); + void clearList(); + +protected: + std::map<void*, void*> theDisplayMap; + std::map<void*, void*>::iterator theDisplayIterator; + + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimDisplayRefreshEvent.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimDisplayRefreshEvent.cpp new file mode 100644 index 0000000000..b0e75ce497 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimDisplayRefreshEvent.cpp @@ -0,0 +1,2 @@ +#include "ossimDisplayRefreshEvent.h" +RTTI_DEF1(ossimDisplayRefreshEvent, "ossimDisplayRefreshEvent", ossimEvent); diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimDisplayRefreshEvent.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimDisplayRefreshEvent.h new file mode 100644 index 0000000000..acd3c165a3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimDisplayRefreshEvent.h @@ -0,0 +1,16 @@ +#ifndef ossimDisplayRefreshEvent_HEADER +#define ossimDisplayRefreshEvent_HEADER +#include "ossimEvent.h" +#include <map> + +class OSSIMDLLEXPORT ossimDisplayRefreshEvent : public ossimEvent +{ +public: + ossimDisplayRefreshEvent(ossimObject* obj = NULL) + :ossimEvent(obj, OSSIM_EVENT_DISPLAY_REFRESH_ID) + {} + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimElevationManagerEvent.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimElevationManagerEvent.cpp new file mode 100644 index 0000000000..f675f7e7ae --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimElevationManagerEvent.cpp @@ -0,0 +1,3 @@ +#include "ossimElevationManagerEvent.h" + +RTTI_DEF1(ossimElevationManagerEvent, "ossimROIEvent", ossimEvent); diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimElevationManagerEvent.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimElevationManagerEvent.h new file mode 100644 index 0000000000..1c4ddaded1 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimElevationManagerEvent.h @@ -0,0 +1,28 @@ +#ifndef ossimElevationManagerEvent_HEADER +#define ossimElevationManagerEvent_HEADER + +#include "base/common/events/ossimEvent.h" + +class ossimObject; + +class OSSIMDLLEXPORT ossimElevationManagerEvent : public ossimEvent +{ + public: + ossimElevationManagerEvent( ossimObject* object=NULL, + long id=OSSIM_EVENT_NULL_ID ) + : ossimEvent( object, id ) + { + } + ossimElevationManagerEvent( const ossimElevationManagerEvent& rhs ) + : ossimEvent( rhs ) + { + } + virtual ossimObject* dup() const + { + return new ossimElevationManagerEvent( *this ); + } + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimElevationManagerEventListener.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimElevationManagerEventListener.cpp new file mode 100644 index 0000000000..1f522f9d46 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimElevationManagerEventListener.cpp @@ -0,0 +1,31 @@ +#include "ossimElevationManagerEventListener.h" +#include "ossimElevationManagerEvent.h" + +RTTI_DEF1(ossimElevationManagerEventListener, "ossimElevationManagerEventListener", + ossimListener); + +ossimElevationManagerEventListener::ossimElevationManagerEventListener() + : ossimListener() +{ +} + + +ossimElevationManagerEventListener::~ossimElevationManagerEventListener() +{ +} + +void ossimElevationManagerEventListener::processEvent( ossimEvent& event ) +{ + ossimElevationManagerEvent* elevationManagerEvent = + PTR_CAST( ossimElevationManagerEvent, &event ); + + if ( elevationManagerEvent ) + { + processEvent( *elevationManagerEvent ); + } +} + +void ossimElevationManagerEventListener::processEvent( ossimElevationManagerEvent& event ) +{ + +} diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimElevationManagerEventListener.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimElevationManagerEventListener.h new file mode 100644 index 0000000000..dbdaf252fa --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimElevationManagerEventListener.h @@ -0,0 +1,18 @@ +#ifndef ossimElevationManagerEventListener_HEADER +#define ossmiElevationManagerEventListener_HEADER + +#include "base/common/events/ossimListener.h" +#include "base/common/events/ossimElevationManagerEvent.h" + +class OSSIMDLLEXPORT ossimElevationManagerEventListener : public ossimListener +{ + public: + ossimElevationManagerEventListener(); + virtual ~ossimElevationManagerEventListener(); + virtual void processEvent( ossimEvent& event ); + virtual void processEvent( ossimElevationManagerEvent& event ); + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimEvent.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimEvent.cpp new file mode 100644 index 0000000000..d74ab2e130 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimEvent.cpp @@ -0,0 +1,86 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: A brief description of the contents of the file. +// +// +//************************************************************************* +// $Id: ossimEvent.cpp,v 1.3 2004/06/10 17:57:10 dburken Exp $ +#include "ossimEvent.h" + +RTTI_DEF1(ossimEvent, "ossimEvent", ossimObject); + + +ossimEvent::ossimEvent(ossimObject* object, long id) + : + ossimObject(), + theObject(object), + theId(id), + theIsConsumedFlag(false) +{ +} + +ossimEvent::ossimEvent(const ossimEvent& rhs) + : + ossimObject(), + theObject(rhs.theObject), + theId(rhs.theId), + theIsConsumedFlag(rhs.theIsConsumedFlag) +{ +} + +long ossimEvent::getId() const +{ + return theId; +} + +void ossimEvent::setId(long id) +{ + theId = id; +} + +bool ossimEvent::isConsumed() const +{ + return theIsConsumedFlag; +} + +void ossimEvent::setConsumedFlag(bool flag) +{ + theIsConsumedFlag = flag; +} + +void ossimEvent::consume() +{ + setConsumedFlag(true); +} + +const ossimObject* ossimEvent::getObject() const +{ + return theObject; +} + +ossimObject* ossimEvent::getObject() +{ + return theObject; +} + +void ossimEvent::setObject(ossimObject* object) +{ + theObject = object; +} diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimEvent.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimEvent.h new file mode 100644 index 0000000000..abc4404239 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimEvent.h @@ -0,0 +1,64 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: A brief description of the contents of the file. +// +// +//************************************************************************* +// $Id: ossimEvent.h,v 1.10 2005/09/09 19:23:58 gpotts Exp $ +#ifndef ossimEvent_HEADER +#define ossimEvent_HEADER +#include "ossimEventIds.h" +#include "base/common/ossimObject.h" + +class OSSIMDLLEXPORT ossimEvent : public ossimObject +{ +public: + + /** + * @param object The object associated with the event if any. + * + * @param id The event id. + */ + ossimEvent(ossimObject* object=NULL, + long id=OSSIM_EVENT_NULL_ID); + + ossimEvent(const ossimEvent& rhs); + + long getId()const; + void setId(long id); + + bool isConsumed()const; + void setConsumedFlag(bool flag=true); + void consume(); + + const ossimObject* getObject()const; + ossimObject* getObject(); + + void setObject(ossimObject* object); + +protected: + ossimObject* theObject; + long theId; + bool theIsConsumedFlag; + +TYPE_DATA +}; + +#endif /* #ifndef ossimEvent_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimEventIds.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimEventIds.h new file mode 100644 index 0000000000..52b5f33bba --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimEventIds.h @@ -0,0 +1,86 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: A brief description of the contents of the file. +// +// +//************************************************************************* +// $Id: ossimEventIds.h,v 1.16 2003/12/03 13:57:16 gpotts Exp $ +#ifndef ossimEventIds_HEADER +#define ossimEventIds_HEADER + +#define OSSIM_EVENT_NULL_ID -1 + + +// destruction event +#define OSSIM_EVENT_OBJECT_DESTRUCTING_ID 1 + +// connection events +#define OSSIM_EVENT_CONNECTION_DISCONNECT_ID 3 +#define OSSIM_EVENT_CONNECTION_CONNECT_ID 4 + +#define OSSIM_EVENT_REFRESH_ID 5 +#define OSSIM_EVENT_PROCESS_PROGRESS_ID 20 + +#define OSSIM_EVENT_ADD_OBJECT_ID 40 +#define OSSIM_EVENT_REMOVE_OBJECT_ID 41 + + +#define OSSIM_EVENT_PROPERTY_ID 80 +#define OSSIM_EVENT_STATE_CHANGED_ID 90 + + +#define OSSIM_EVENT_AOI_RECTANGLE_ID 200 +#define OSSIM_EVENT_AOI_POLYGON_ID 201 + + +#define OSSIM_MOUSE_EVENT_ID 400 +#define OSSIM_MOUSE_EVENT_LEAVE_WINDOW_ID 401 +#define OSSIM_MOUSE_EVENT_MOTION_ID 402 +#define OSSIM_MOUSE_EVENT_LEFT_DOWN_ID 403 +#define OSSIM_MOUSE_EVENT_RIGHT_DOWN_ID 404 +#define OSSIM_MOUSE_EVENT_MIDDLE_DOWN_ID 405 +#define OSSIM_MOUSE_EVENT_LEFT_UP_ID 406 +#define OSSIM_MOUSE_EVENT_RIGHT_UP_ID 407 +#define OSSIM_MOUSE_EVENT_MIDDLE_UP_ID 408 + +#define OSSIM_MOUSE_EVENT_LEFT_DCLICK_ID 409 +#define OSSIM_MOUSE_EVENT_RIGHT_DCLICK_ID 410 +#define OSSIM_MOUSE_EVENT_MIDDLE_DCLICK_ID 411 +#define OSSIM_MOUSE_EVENT_ENTER_WINDOW_ID 412 + +#define OSSIM + +#define OSSIM_KEYBOARD_EVENT_ID 500 + +#define OSSIM_EVENT_VIEW_ID 600 + + +#define OSSIM_EVENT_DISPLAY_LIST_ID 700 +#define OSSIM_EVENT_DISPLAY_REFRESH_ID 701 + +#define OSSIM_EVENT_IMAGE_GEOMETRY_ID 800 + +// this is the first user defined id. If users want to add +// additional id's they need to start at this id. That way +// we have no conflicts. +// +#define OSSIM_FIRST_USER_DEFINED_EVENT_ID 1000000 + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimImageAoiListener.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimImageAoiListener.cpp new file mode 100644 index 0000000000..161e92f755 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimImageAoiListener.cpp @@ -0,0 +1,50 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossimImageAoiListener.cpp,v 1.2 2002/04/09 21:20:03 gpotts Exp $ +#include "ossimImageAoiListener.h" +#include "ossimEventIds.h" +#include "ossimImageRectangleEvent.h" +#include "ossimImagePolygonEvent.h" + +void ossimImageAoiListener::processEvent(ossimEvent& event) +{ + switch(event.getId()) + { + case OSSIM_EVENT_AOI_RECTANGLE_ID: + { + ossimImageRectangleEvent* eventCast = static_cast<ossimImageRectangleEvent*>(&event); + imageRectangleEvent(*eventCast); + break; + } + case OSSIM_EVENT_AOI_POLYGON_ID: + { + ossimImagePolygonEvent* eventCast = static_cast<ossimImagePolygonEvent*>(&event); + imagePolygonEvent(*eventCast); + break; + } + default: + { + ossimListener::processEvent(event); + break; + } + } +} diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimImageAoiListener.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimImageAoiListener.h new file mode 100644 index 0000000000..3d58d4933f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimImageAoiListener.h @@ -0,0 +1,43 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossimImageAoiListener.h,v 1.3 2002/11/25 18:49:10 gpotts Exp $ +#ifndef ossimImageAoiListener_HEADER +#define ossimImageAoiListener_HEADER +#include "ossimListener.h" + +class OSSIMDLLEXPORT ossimImageRectangleEvent; +class OSSIMDLLEXPORT ossimImagePolygonEvent; + +class OSSIMDLLEXPORT ossimImageAoiListener : public ossimListener +{ +public: + ossimImageAoiListener():ossimListener(){} + virtual ~ossimImageAoiListener(){} + + virtual void processEvent(ossimEvent& event); + + virtual void imageRectangleEvent(ossimImageRectangleEvent& event) + {} + virtual void imagePolygonEvent(ossimImagePolygonEvent& event) + {} +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimImageGeometryEvent.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimImageGeometryEvent.cpp new file mode 100644 index 0000000000..6987926c6c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimImageGeometryEvent.cpp @@ -0,0 +1,29 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: A brief description of the contents of the file. +// +// +//************************************************************************* +// $Id: ossimImageGeometryEvent.cpp,v 1.1 2003/12/03 13:57:46 gpotts Exp $ +#include "ossimImageGeometryEvent.h" + +RTTI_DEF1(ossimImageGeometryEvent, "ossimImageGeometryEvent", ossimEvent); + + diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimImageGeometryEvent.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimImageGeometryEvent.h new file mode 100644 index 0000000000..03e2bc8ace --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimImageGeometryEvent.h @@ -0,0 +1,82 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: A brief description of the contents of the file. +// +// +//************************************************************************* +// $Id: ossimImageGeometryEvent.h,v 1.1 2003/12/03 13:57:46 gpotts Exp $ +#ifndef ossimImageGeometryEvent_HEADER +#define ossimImageGeometryEvent_HEADER +#include "ossimEvent.h" +#include "base/data_types/ossimKeywordlist.h" + +class ossimImageGeometryEvent : public ossimEvent +{ +public: + ossimImageGeometryEvent(ossimObject* object=0, + long id=OSSIM_EVENT_IMAGE_GEOMETRY_ID) + :ossimEvent(object, id) + { + } + + ossimImageGeometryEvent(const ossimKeywordlist& geomKwl, + ossimObject* object=NULL, + long id=OSSIM_EVENT_IMAGE_GEOMETRY_ID) + :ossimEvent(object, id), + theGeomKwl(geomKwl) + { + } + ossimImageGeometryEvent(const ossimImageGeometryEvent& rhs) + :ossimEvent(rhs), + theGeomKwl(rhs.theGeomKwl) + { + } + virtual ~ossimImageGeometryEvent(){} + virtual ossimObject* dup()const + { + return new ossimImageGeometryEvent(*this); + } + void setGeometry(const ossimKeywordlist& geomKwl) + { + theGeomKwl = geomKwl; + } + void getGeometry(ossimKeywordlist& geomKwl)const + { + geomKwl = theGeomKwl; + } + const ossimKeywordlist& getGeometry()const + { + return theGeomKwl; + } + bool isGeometrySet()const + { + return (theGeomKwl.getSize() != 0); + } + void clearGeometry() + { + theGeomKwl.clear(); + } +protected: + ossimKeywordlist theGeomKwl; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimImageGeometryEventListener.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimImageGeometryEventListener.cpp new file mode 100644 index 0000000000..80ab1cd8d0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimImageGeometryEventListener.cpp @@ -0,0 +1,45 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: A brief description of the contents of the file. +// +// +//************************************************************************* +// $Id: ossimImageGeometryEventListener.cpp,v 1.1 2003/12/03 13:57:46 gpotts Exp $ +#include "ossimImageGeometryEventListener.h" + +RTTI_DEF1(ossimImageGeometryEventListener, "ossimImageGeometryEventListener", ossimListener); + +void ossimImageGeometryEventListener::processEvent(ossimEvent& event) +{ + switch(event.getId()) + { + case OSSIM_EVENT_IMAGE_GEOMETRY_ID: + { + ossimImageGeometryEvent* tempCast = (ossimImageGeometryEvent*)(&event); + imageGeometryEvent(*tempCast); + + break; + } + default: + { + ossimListener::processEvent(event); + } + } +} diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimImageGeometryEventListener.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimImageGeometryEventListener.h new file mode 100644 index 0000000000..2a1a3a66b7 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimImageGeometryEventListener.h @@ -0,0 +1,43 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: A brief description of the contents of the file. +// +// +//************************************************************************* +// $Id: ossimImageGeometryEventListener.h,v 1.1 2003/12/03 13:57:46 gpotts Exp $ +#ifndef ossimImageGeometryEventListener_HEADER +#define ossimImageGeometryEventListener_HEADER +#include "ossimListener.h" +#include "ossimImageGeometryEvent.h" + +class ossimImageGeometryEventListener : public ossimListener +{ +public: + ossimImageGeometryEventListener():ossimListener(){} + virtual ~ossimImageGeometryEventListener(){} + virtual void processEvent(ossimEvent& event); + + virtual void imageGeometryEvent(ossimImageGeometryEvent& /* event */) + {} + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimImagePolygonEvent.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimImagePolygonEvent.h new file mode 100644 index 0000000000..b6f5b1bdd3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimImagePolygonEvent.h @@ -0,0 +1,65 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossimImagePolygonEvent.h,v 1.4 2005/12/16 14:27:52 dburken Exp $ +#ifndef ossimImagePolygonEvent_HEADER +#define ossimImagePolygonEvent_HEADER +#include <vector> +#include <base/common/events/ossimEvent.h> +#include <base/common/events/ossimEventIds.h> +#include <base/data_types/ossimIpt.h> +#include <base/data_types/ossimDpt.h> + + +class OSSIMDLLEXPORT ossimImagePolygonEvent : public ossimEvent +{ +public: + ossimImagePolygonEvent(const std::vector<ossimIpt>& polygon, + ossimObject* obj=NULL) + : ossimEvent(obj,OSSIM_EVENT_AOI_POLYGON_ID) , + thePolygon(polygon) + { + } + ossimImagePolygonEvent(const std::vector<ossimDpt>& polygon, + ossimObject* obj=NULL) + : ossimEvent(obj,OSSIM_EVENT_AOI_POLYGON_ID) , + thePolygon(polygon.begin(), + polygon.end()) + { + } + virtual ossimObject* dup()const + { + return new ossimImagePolygonEvent(*this); + } + + const std::vector<ossimIpt>& getpolygon()const + { + return thePolygon; + } + const std::vector<ossimIpt>& getPolygon()const + { + return thePolygon; + } + void setPolygon(const std::vector<ossimIpt>& polygon) + { + thePolygon = polygon; + } + void setPolygon(const std::vector<ossimDpt>& polygon) + { + thePolygon.clear(); + thePolygon.insert(thePolygon.begin(), + polygon.begin(), + polygon.end()); + } + +protected: + std::vector<ossimIpt> thePolygon; + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimImageRectangleEvent.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimImageRectangleEvent.h new file mode 100644 index 0000000000..289d4e92cb --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimImageRectangleEvent.h @@ -0,0 +1,57 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossimImageRectangleEvent.h,v 1.3 2003/01/06 19:01:05 gpotts Exp $ +#ifndef ossimImageRectangleEvent_HEADER +#define ossimImageRectangleEvent_HEADER +#include "ossimEvent.h" +#include "ossimEventIds.h" +#include "base/data_types/ossimIrect.h" + +class OSSIMDLLEXPORT ossimImageRectangleEvent : public ossimEvent +{ +public: + ossimImageRectangleEvent(const ossimIrect& rect, + ossimObject* obj=NULL) + : ossimEvent(obj,OSSIM_EVENT_AOI_RECTANGLE_ID) , + theRectangle(rect) + { + } + virtual ossimObject* dup()const + { + return new ossimImageRectangleEvent(*this); + } + + const ossimIrect& getRectangle()const + { + return theRectangle; + } + void setRectangle(const ossimIrect& rect) + { + theRectangle = rect; + } + +protected: + ossimIrect theRectangle; + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimListener.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimListener.cpp new file mode 100644 index 0000000000..22950b6f29 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimListener.cpp @@ -0,0 +1,51 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimListener.cpp,v 1.5 2005/07/15 20:43:51 dburken Exp $ +#include <base/common/events/ossimListener.h> + +RTTI_DEF(ossimListener, "ossimListener"); + +ossimListener::ossimListener() + :theListenerEnableFlag(true) +{} + +ossimListener::~ossimListener() +{ +} + +void ossimListener::processEvent(ossimEvent& /* event */) +{ +} + +void ossimListener::enableListener() +{ + theListenerEnableFlag = true; +} + +void ossimListener::disableListener() +{ + theListenerEnableFlag = false; +} + +void ossimListener::setListenerEnableFlag(bool flag) +{ + theListenerEnableFlag = flag; +} + +bool ossimListener::isListenerEnabled()const +{ + return theListenerEnableFlag; +} + +bool ossimListener::getListenerEnableFlag()const +{ + return theListenerEnableFlag; +} diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimListener.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimListener.h new file mode 100644 index 0000000000..face43d540 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimListener.h @@ -0,0 +1,51 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimListener.h,v 1.7 2005/07/15 18:57:49 dburken Exp $ +#ifndef ossimListener_HEADER +#define ossimListener_HEADER +#include <base/common/ossimObject.h> + +class OSSIMDLLEXPORT ossimEvent; + +/*! + * Base class for all listners. Listners nned to derive from this + * class and override the processEvent method. + */ +class OSSIMDLLEXPORT ossimListener +{ +public: + + ossimListener(); + + virtual ~ossimListener(); + + /** + * ProcessEvent. The defaul is to do nothing. Derived + * classes need to override this class. + */ + virtual void processEvent(ossimEvent& event); + + void enableListener(); + + void disableListener(); + + void setListenerEnableFlag(bool flag); + + bool isListenerEnabled() const; + + bool getListenerEnableFlag() const; + +protected: + bool theListenerEnableFlag; +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimListenerManager.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimListenerManager.cpp new file mode 100644 index 0000000000..7e4a921626 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimListenerManager.cpp @@ -0,0 +1,155 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See LICENSE.txt file in the top level directory. +// +// Author: Garrett Potts +// +// Description: A brief description of the contents of the file. +// +//************************************************************************* +// $Id: ossimListenerManager.cpp,v 1.21 2005/12/01 16:39:14 dburken Exp $ + +#include <algorithm> +#include <base/common/events/ossimListenerManager.h> +#include <base/common/events/ossimEvent.h> +#include <base/common/events/ossimListener.h> + +RTTI_DEF(ossimListenerManager, "ossimListenerManager"); + +ossimListenerManager::ossimListenerManager() +{ + theFireEventFlag = false; +} + +ossimListenerManager::ossimListenerManager(const ossimListenerManager& rhs) +{ +// replaceListeners(rhs.getListeners()); +} + +ossimListenerManager::~ossimListenerManager() +{ + theListenerList.clear(); +} + +void ossimListenerManager::fireEvent(ossimEvent& event) +{ + // only process the event if it has not been consumed. + if(event.isConsumed()) + { + return; + } + theFireEventFlag = true; + + std::list<ossimListener*>::iterator currentIterator = theListenerList.begin(); + + while(currentIterator != theListenerList.end()) + { + // only fire if the event is not consumed + if(!event.isConsumed()) + { + if(*currentIterator) + { + if(theDelayedRemove.end()==std::find(theDelayedRemove.begin(), + theDelayedRemove.end(), + (*currentIterator))) + { + if((*currentIterator)->isListenerEnabled()) + { + (*currentIterator)->processEvent(event); + } + } + } + } + else + { + // the event is now consumed so stop propagating. + // + theFireEventFlag = false; + break; + } + ++currentIterator; + } + + theFireEventFlag = false; + + if(theDelayedAdd.size()) + { + for(std::list<ossimListener*>::iterator current = theDelayedAdd.begin(); + current != theDelayedAdd.end();++current) + { + addListener(*current); + } + theDelayedAdd.clear(); + } + + if(theDelayedRemove.size()) + { + for(std::list<ossimListener*>::iterator current = theDelayedRemove.begin(); + current != theDelayedRemove.end();++current) + { + removeListener(*current); + } + theDelayedRemove.clear(); + } +} + +bool ossimListenerManager::addListener(ossimListener* listener) +{ + if(theFireEventFlag) + { + theDelayedAdd.push_back(listener); + } + else + { + + if(!findListener(listener)) + { + theListenerList.push_back(listener); + } + } + + return true; +} + +bool ossimListenerManager::removeListener(ossimListener* listener) +{ + + if(theFireEventFlag) + { + theDelayedRemove.push_back(listener); + return true; + } + + std::list<ossimListener*>::iterator current=theListenerList.begin(); + while(current!=theListenerList.end()) + { + if( (*current) == listener) + { + current = theListenerList.erase(current); + break; // Should only be in list once... (drb) + } + else + { + ++current; + } + } + + return true; +} + +bool ossimListenerManager::findListener(ossimListener* listener) +{ + bool result = false; + + if(listener) + { + std::list<ossimListener*>::iterator currentIter = + std::find(theListenerList.begin(), + theListenerList.end(), + listener); + result = (currentIter != theListenerList.end()); + } + + return result; +} diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimListenerManager.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimListenerManager.h new file mode 100644 index 0000000000..17f9404ffd --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimListenerManager.h @@ -0,0 +1,138 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: A brief description of the contents of the file. +// +// +//************************************************************************* +// $Id: ossimListenerManager.h,v 1.16 2005/09/14 15:05:03 gpotts Exp $ +#ifndef ossimListenerManager_HEADER +#define ossimListenerManager_HEADER +#include "base/common/ossimConstants.h" +#include <list> +#include "base/common/ossimRtti.h" + +class OSSIMDLLEXPORT ossimListener; +class OSSIMDLLEXPORT ossimEvent; + +class OSSIMDLLEXPORT ossimListenerManager +{ +public: + /*! + * Default constructor and needs no initialization. + */ + ossimListenerManager(); + + /*! + * Default destructor. Note the Manager doesn't own the listeners + * and will not delete them + */ + virtual ~ossimListenerManager(); + + /*! + * Traverses through all listeners and fires an event to them. + * if any listener sets the consumed flag on the event it + * will stop traversing the list. + */ + virtual void fireEvent(ossimEvent& event); + + /*! + * Appends the listener onto the list. + */ + virtual bool addListener(ossimListener* listener); + + /*! + * Will push the lister to the front of the list. + */ + // virtual bool insertFrontListener(ossimListener* listener); + + /*! + * Finds and removes the listener. + */ + virtual bool removeListener(ossimListener* listener); + + + /*! + * Will find the listener passed in as the first argument + * and insert the passed in listener before it. If not + * found then it will default to a push to front. + */ +// virtual bool insertBeforeListener(ossimListener* listenerSearchKey, +// ossimListener* listener); + + /*! + * Will find the listener passed in as the first argument + * and insert the passed in listener after it. If not + * found then it will default to an append. + */ +// virtual bool insertAfterListener(ossimListener* listenerSearchKey, +// ossimListener* listener); + + /*! + * Will insert the listener before the specified + * listener. If the index is invalid it defaults + * to a push to front. An invalid index is any + * index < 0 or larger than the number of items + * currently in the list. + */ +// virtual bool insertBeforeListener(ossimListener* listener, +// long index); + + /*! + * Will insert the listener after the specified + * listener. If the index is invalid it defaults + * to an addListener. An invalid index is any + * index < 0 or larger than the number of items + * currently in the list. + */ +// virtual bool insertAfterListener(ossimListener* listener, +// long index); + + /*! + * Searches the list and sees if a listener is found + */ + virtual bool findListener(ossimListener* listener); + + /*! + * Will search the list and return the index if found else + * returns a negative value. + */ + // virtual long getIndexOfListener(ossimListener* listener); + + // const std::vector<ossimListener*>& getListeners()const{return theListenerList;} + + +protected: + ossimListenerManager(const ossimListenerManager& rhs); + + /*! + * Holds the list of listeners. + */ + std::list<ossimListener*> theListenerList; + bool theEnabledFlag; + mutable std::list<ossimListener*> theDelayedAdd; + mutable std::list<ossimListener*> theDelayedRemove; + mutable bool theFireEventFlag; +// mutable std::list<ossimListener*>::iterator theCurrentIterator; + + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimMouseEvent.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimMouseEvent.cpp new file mode 100644 index 0000000000..a815133c61 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimMouseEvent.cpp @@ -0,0 +1,27 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: A brief description of the contents of the file. +// +// +//************************************************************************* +// $Id: ossimMouseEvent.cpp,v 1.2 2002/06/25 12:30:17 gpotts Exp $ +#include "ossimMouseEvent.h" + +RTTI_DEF1(ossimMouseEvent, "ossimMouseEvent", ossimEvent); diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimMouseEvent.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimMouseEvent.h new file mode 100644 index 0000000000..3fb2c1a8b9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimMouseEvent.h @@ -0,0 +1,97 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimMouseEvent.h,v 1.11 2003/01/06 19:01:24 gpotts Exp $ + +#ifndef ossimMouseEvent_HEADER +#define ossimMouseEvent_HEADER +#include "ossimEvent.h" +#include "base/data_types/ossimIpt.h" + +class OSSIMDLLEXPORT ossimMouseEvent : public ossimEvent +{ +public: + ossimMouseEvent(const ossimDpt& scenePoint=ossimDpt(0,0), + const ossimDpt& relViewPoint=ossimDpt(0,0), + ossimObject* object = NULL, + long id = OSSIM_MOUSE_EVENT_ID, + long mouseType = 0) + :ossimEvent(object, id), + theScenePoint(scenePoint), + theRelViewPoint(relViewPoint), + theMouseType(mouseType) + { + } + + virtual ossimObject* dup()const{return new ossimMouseEvent(*this);} + + bool controlDown() const { return theControlKeyDown; } + bool altDown() const { return theAltKeyDown; } + bool shiftDown() const { return theShiftKeyDown; } + + // Find which event was just generated + bool leftDown() const{ return (theMouseType == OSSIM_MOUSE_EVENT_LEFT_DOWN_ID); } + bool middleDown() const{ return (theMouseType == OSSIM_MOUSE_EVENT_MIDDLE_DOWN_ID); } + bool rightDown() const{ return (theMouseType == OSSIM_MOUSE_EVENT_RIGHT_DOWN_ID); } + bool leftUp() const{ return (theMouseType == OSSIM_MOUSE_EVENT_LEFT_UP_ID); } + bool middleUp() const{ return (theMouseType == OSSIM_MOUSE_EVENT_MIDDLE_UP_ID); } + bool rightUp() const{ return (theMouseType == OSSIM_MOUSE_EVENT_RIGHT_UP_ID); } + + bool leftDClick() const { return (theMouseType == OSSIM_MOUSE_EVENT_LEFT_DCLICK_ID); } + bool middleDClick() const { return (theMouseType == OSSIM_MOUSE_EVENT_MIDDLE_DCLICK_ID); } + bool rightDClick() const { return (theMouseType == OSSIM_MOUSE_EVENT_RIGHT_DCLICK_ID); } + + // Find the current state of the mouse buttons (regardless + // of current event type) + bool leftIsDown() const { return theLeftDown; } + bool middleIsDown() const { return theMiddleDown; } + bool rightIsDown() const { return theRightDown; } + + // True if a button is down and the mouse is moving + bool dragging() const + { + return (moving() && + (leftIsDown() || middleIsDown() || rightIsDown())); + } + + // True if the mouse is moving, and no button is down + bool moving() const { return (theMouseType == OSSIM_MOUSE_EVENT_MOTION_ID); } + + // True if the mouse is just entering the window + bool entering() const { return (theMouseType == OSSIM_MOUSE_EVENT_ENTER_WINDOW_ID); } + + // True if the mouse is just leaving the window + bool leaving() const { return (theMouseType == OSSIM_MOUSE_EVENT_LEAVE_WINDOW_ID); } + + ossimDpt theScenePoint; + ossimDpt theRelViewPoint; + int theMouseType; + bool theAltKeyDown; + bool theControlKeyDown; + bool theShiftKeyDown; + bool theLeftDown; + bool theRightDown; + bool theMiddleDown; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimMouseListener.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimMouseListener.cpp new file mode 100644 index 0000000000..be0f88e683 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimMouseListener.cpp @@ -0,0 +1,54 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossimMouseListener.cpp,v 1.4 2002/09/25 12:01:18 gpotts Exp $ + +#include "base/common/events/ossimMouseListener.h" +#include "base/common/events/ossimMouseEvent.h" + +RTTI_DEF1(ossimMouseListener,"ossimMouseListener",ossimListener); + +void ossimMouseListener::processEvent(ossimEvent& event) +{ + ossimMouseEvent* mEvent = PTR_CAST(ossimMouseEvent, &event); + + if(mEvent) + { + mouseEvent(*mEvent); + } + else + { + ossimListener::processEvent(event); + } +// switch(event.getId()) +// { +// case OSSIM_MOUSE_EVENT_ID: +// { +// = static_cast<ossimMouseEvent*>(&event); +// mouseEvent(*mEvent); +// break; +// } +// default: +// { +// ossimListener::processEvent(event); +// } +// } +} diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimMouseListener.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimMouseListener.h new file mode 100644 index 0000000000..9de007c7be --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimMouseListener.h @@ -0,0 +1,44 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossimMouseListener.h,v 1.2 2002/11/25 18:49:10 gpotts Exp $ +#ifndef ossimMouseListener_HEADER +#define ossimMouseListener_HEADER +#include "ossimListener.h" +#include "ossimMouseEvent.h" + +class OSSIMDLLEXPORT ossimMouseListener : public ossimListener +{ +public: + ossimMouseListener():ossimListener(){} + virtual ~ossimMouseListener(){} + + virtual void processEvent(ossimEvent& event); + + /*! + * processes all mouse events + */ + virtual void mouseEvent(ossimMouseEvent& event) + {} + +TYPE_DATA +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimObjectDestructingEvent.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimObjectDestructingEvent.cpp new file mode 100644 index 0000000000..74fcd05c43 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimObjectDestructingEvent.cpp @@ -0,0 +1,3 @@ +#include "ossimObjectDestructingEvent.h" + +RTTI_DEF1(ossimObjectDestructingEvent,"ossimObjectDestructingEvent",ossimEvent) diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimObjectDestructingEvent.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimObjectDestructingEvent.h new file mode 100644 index 0000000000..333fd1d7ef --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimObjectDestructingEvent.h @@ -0,0 +1,18 @@ +#ifndef ossimObjectDestructingEvent_HEADER +#define ossimObjectDestructingEvent_HEADER + +#include "ossimEvent.h" +#include "ossimEventIds.h" + +class OSSIMDLLEXPORT ossimObject; +class OSSIMDLLEXPORT ossimObjectDestructingEvent : public ossimEvent +{ +public: + ossimObjectDestructingEvent(ossimObject* objectDestructing=NULL) + :ossimEvent(objectDestructing, OSSIM_EVENT_OBJECT_DESTRUCTING_ID) + {} + virtual ossimObject* dup()const{return new ossimObjectDestructingEvent(*this);} + +TYPE_DATA +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimObjectEvents.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimObjectEvents.h new file mode 100644 index 0000000000..357c6dd19a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimObjectEvents.h @@ -0,0 +1,10 @@ +#ifndef ossimObjectEvents_HEADER +#define ossimObjectEvents_HEADER + +#include "base/common/events/ossimObjectDestructingEvent.h" +#include "base/common/events/ossimConnectionEvent.h" +#include "base/common/events/ossimPropertyEvent.h" +#include "base/common/events/ossimContainerEvent.h" +#include "base/common/events/ossimRefreshEvent.h" + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimProcessListener.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimProcessListener.cpp new file mode 100644 index 0000000000..00dd7fadcf --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimProcessListener.cpp @@ -0,0 +1,44 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// $Id: ossimProcessListener.cpp,v 1.4 2004/08/17 16:49:03 dburken Exp $ +//---------------------------------------------------------------------------- + +#include "ossimProcessListener.h" +#include "ossimProcessProgressEvent.h" + +RTTI_DEF1(ossimProcessListener, "ossimProcessListener", ossimListener); + +ossimProcessListener::ossimProcessListener() + : ossimListener() +{} + +ossimProcessListener::~ossimProcessListener() +{} + +void ossimProcessListener::processEvent(ossimEvent& event) +{ + switch(event.getId()) + { + case OSSIM_EVENT_PROCESS_PROGRESS_ID: + { + ossimProcessProgressEvent* eventCast = static_cast<ossimProcessProgressEvent*>(&event); + processProgressEvent(*eventCast); + break; + } + default: + { + ossimListener::processEvent(event); + break; + } + } +} + +void ossimProcessListener::processProgressEvent(ossimProcessProgressEvent& /* event */ ) +{} diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimProcessListener.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimProcessListener.h new file mode 100644 index 0000000000..c32ac68a61 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimProcessListener.h @@ -0,0 +1,28 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// $Id: ossimProcessListener.h,v 1.5 2004/08/17 16:49:03 dburken Exp $ +//---------------------------------------------------------------------------- +#ifndef ossimProcessListener_HEADER +#define ossimProcessListener_HEADER +#include "ossimListener.h" +class OSSIMDLLEXPORT ossimProcessProgressEvent; + +class OSSIMDLLEXPORT ossimProcessListener : public ossimListener +{ +public: + ossimProcessListener(); + virtual ~ossimProcessListener(); + virtual void processEvent(ossimEvent& event); + virtual void processProgressEvent(ossimProcessProgressEvent& event); + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimProcessProgressEvent.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimProcessProgressEvent.cpp new file mode 100644 index 0000000000..1e2c84a9ac --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimProcessProgressEvent.cpp @@ -0,0 +1,68 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: Event for process progress. +// +// $Id: ossimProcessProgressEvent.cpp,v 1.3 2005/09/09 19:23:58 gpotts Exp $ +//---------------------------------------------------------------------------- +#include <base/common/events/ossimProcessProgressEvent.h> + +RTTI_DEF1(ossimProcessProgressEvent, "ossimProcessProgressEvent", ossimEvent); + +ossimProcessProgressEvent::ossimProcessProgressEvent(ossimObject* owner, + double percentComplete, + const ossimString message, + bool outputMessageFlag) + : + ossimEvent(owner, OSSIM_EVENT_PROCESS_PROGRESS_ID), + thePercentComplete(percentComplete), + theMessage(message), + theOutputMessageFlag(outputMessageFlag) +{ +} + +ossimObject* ossimProcessProgressEvent::dup()const +{ + return new ossimProcessProgressEvent(*this); +} + +double ossimProcessProgressEvent::getPercentComplete()const +{ + return thePercentComplete; +} + +ossimString ossimProcessProgressEvent::getMessage()const +{ + return theMessage; +} + +void ossimProcessProgressEvent::getMessage(ossimString& message)const +{ + message = theMessage; +} + +void ossimProcessProgressEvent::setPercentComplete(double percentComplete) +{ + thePercentComplete = percentComplete; +} + +void ossimProcessProgressEvent::setMessage(const ossimString& message) +{ + theMessage = message; +} + +void ossimProcessProgressEvent::setOutputMessageFlag(bool flag) +{ + theOutputMessageFlag = flag; +} + +bool ossimProcessProgressEvent::getOutputMessageFlag() const +{ + return theOutputMessageFlag; +} diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimProcessProgressEvent.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimProcessProgressEvent.h new file mode 100644 index 0000000000..800c825d52 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimProcessProgressEvent.h @@ -0,0 +1,51 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: Event for process progress. +// +// $Id: ossimProcessProgressEvent.h,v 1.8 2005/09/09 19:23:58 gpotts Exp $ +//---------------------------------------------------------------------------- +#ifndef ossimProcessProgressEvent_HEADER +#define ossimProcessProgressEvent_HEADER + +#include <base/common/events/ossimEvent.h> +#include <base/data_types/ossimString.h> + +class OSSIMDLLEXPORT ossimProcessProgressEvent : public ossimEvent +{ +public: + ossimProcessProgressEvent(ossimObject* owner=NULL, + double percentComplete=0.0, + const ossimString message="", + bool outputMessageFlag=false); + + virtual ossimObject* dup()const; + + double getPercentComplete()const; + + ossimString getMessage()const; + + void getMessage(ossimString& message)const; + + void setPercentComplete(double percentComplete); + + void setMessage(const ossimString& message); + + void setOutputMessageFlag(bool flag); + + bool getOutputMessageFlag() const; + +protected: + double thePercentComplete; + ossimString theMessage; + bool theOutputMessageFlag; + +TYPE_DATA +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimPropertyEvent.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimPropertyEvent.h new file mode 100644 index 0000000000..70d09e0e31 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimPropertyEvent.h @@ -0,0 +1,14 @@ +#ifndef ossimPropertyEvent_HEADER +#define ossimPropertyEvent_HEADER +#include "base/common/events/ossimEvent.h" + +class OSSIMDLLEXPORT ossimPropertyEvent : public ossimEvent +{ +public: + ossimPropertyEvent(ossimObject* object) // the event id + :ossimEvent(object, OSSIM_EVENT_PROPERTY_ID) + {} + virtual ossimObject* dup()const{return new ossimPropertyEvent(*this);} +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimROIEvent.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimROIEvent.cpp new file mode 100644 index 0000000000..46c898b26f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimROIEvent.cpp @@ -0,0 +1,124 @@ +//---------------------------------------------------------------------------- +// +// License: See top level LICENSE.txt file. +// +// Author: Scott Bortman +// +// Description: Region Of Interest (ROI) Event +// +// $Id: ossimROIEvent.cpp,v 1.5 2006/01/04 15:48:56 dburken Exp $ +//---------------------------------------------------------------------------- +#include <base/common/events/ossimROIEvent.h> +#include <base/data_types/ossimPolygon.h> +#include <base/data_types/ossimPolyLine.h> +#include <base/data_types/ossimIrect.h> + +RTTI_DEF1(ossimROIEvent, "ossimROIEvent", ossimEvent); + +ossimROIEvent::ossimROIEvent(ossimObject* object, + long id) + : ossimEvent( object, id ), + theType(OSSIM_RECTANGLE_ROI), + theMovingFlag(false) + +{ +} + +ossimROIEvent::ossimROIEvent( const ossimROIEvent& rhs ) + : ossimEvent ( rhs ), + theType ( rhs.theType ), + theMovingFlag ( rhs.theMovingFlag) +{ +} + +ossimObject* ossimROIEvent::dup() const +{ + return new ossimROIEvent( *this ); +} + +const vector<ossimIpt>& ossimROIEvent::getPoints()const +{ + return thePoints; +} + +void ossimROIEvent::getPoint(vector<ossimIpt>& points)const +{ + points = thePoints; +} + +void ossimROIEvent::setPoints( const vector<ossimIpt>& points ) +{ + thePoints = points; +} + +void ossimROIEvent::setRect(const ossimIrect& rect) +{ + thePoints.clear(); + thePoints.push_back(rect.ul()); + thePoints.push_back(rect.lr()); +} + +void ossimROIEvent::setEventType( ossimRegionType eventType ) +{ + theType = eventType; +} + +ossimROIEvent::ossimRegionType ossimROIEvent::getEventType()const +{ + return theType; +} + +void ossimROIEvent::setTypeToPolygon() +{ + theType = OSSIM_POLYGON_ROI; +} + +void ossimROIEvent::setTypeToRectangle() +{ + theType = OSSIM_RECTANGLE_ROI; +} + +void ossimROIEvent::setTypeToPolyline() +{ + theType = OSSIM_POLYLINE_ROI; +} + +bool ossimROIEvent::isRectangleRegion()const +{ + return (theType == OSSIM_RECTANGLE_ROI); +} + +bool ossimROIEvent::isPolygonRegion()const +{ + return (theType == OSSIM_POLYGON_ROI); +} + +bool ossimROIEvent::isPolylineRegion()const +{ + return (theType == OSSIM_POLYLINE_ROI); +} + +void ossimROIEvent::getRect(ossimIrect& rect)const +{ + rect = ossimIrect(thePoints); +} + +void ossimROIEvent::getPolygon(ossimPolygon& polygon)const +{ + polygon = ossimPolygon(thePoints); +} + +void ossimROIEvent::getPolyLine(ossimPolyLine& polyline)const +{ + polyline = ossimPolyLine(thePoints); +} + +void ossimROIEvent::setMovingFlag(bool flag) +{ + theMovingFlag = flag; +} + +bool ossimROIEvent::getMovingFlag() const +{ + return theMovingFlag; +} diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimROIEvent.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimROIEvent.h new file mode 100644 index 0000000000..380c331a33 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimROIEvent.h @@ -0,0 +1,74 @@ +//---------------------------------------------------------------------------- +// +// License: See top level LICENSE.txt file. +// +// Author: Scott Bortman +// +// Description: Region Of Interest (ROI) Event +// +// $Id: ossimROIEvent.h,v 1.14 2006/01/04 15:48:56 dburken Exp $ +//---------------------------------------------------------------------------- +#ifndef ossimROIEvent_HEADER +#define ossimROIEvent_HEADER + +#include <base/common/events/ossimEvent.h> +#include <base/data_types/ossimIpt.h> +#include <vector> + +class ossimPolygon; +class ossimPolyLine; +class ossimIrect; +class OSSIMDLLEXPORT ossimROIEvent : public ossimEvent +{ +public: + ossimROIEvent( ossimObject* object=NULL, + long id=OSSIM_EVENT_NULL_ID ); + ossimROIEvent( const ossimROIEvent& rhs ); + virtual ossimObject* dup() const; + + enum ossimRegionType + { + OSSIM_RECTANGLE_ROI = 0, + OSSIM_POLYGON_ROI = 1, + OSSIM_POLYLINE_ROI = 2 + }; + + const std::vector<ossimIpt>& getPoints()const; + void getPoint(std::vector<ossimIpt>& points)const ; + void setPoints( const std::vector<ossimIpt>& points ); + void setRect(const ossimIrect& rect); + void setEventType( ossimRegionType eventType ); + ossimRegionType getEventType()const; + void setTypeToPolygon(); + void setTypeToRectangle(); + void setTypeToPolyline(); + bool isRectangleRegion()const; + bool isPolygonRegion()const; + bool isPolylineRegion()const; + void getRect(ossimIrect& rect)const; + void getPolygon(ossimPolygon& polygon)const; + void getPolyLine(ossimPolyLine& polyline)const; + + /** + * @param flag If true indicates region of interest is moving and size is + * not to change. + */ + void setMovingFlag(bool flag); + + /** + * @return Returns theMoving flag. If true indicates region of interest + * is moving and size is not to change. + */ + bool getMovingFlag() const; + + protected: + std::vector<ossimIpt> thePoints; + ossimRegionType theType; + + // Indicates moving so keep the same size on a redraw. + bool theMovingFlag; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimROIEventListener.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimROIEventListener.cpp new file mode 100644 index 0000000000..6d5b9ec9a3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimROIEventListener.cpp @@ -0,0 +1,49 @@ +#include "ossimROIEventListener.h" +#include "ossimROIEvent.h" + + +RTTI_DEF1(ossimROIEventListener, "ossimROIEventListener", ossimListener); + +void ossimROIEventListener::processEvent(ossimEvent& event) +{ + if(event.isConsumed()) return; + + ossimROIEvent* roiEvent = PTR_CAST(ossimROIEvent, + &event); + + if(roiEvent) + { + const int type = roiEvent->getEventType(); + + switch ( type ) + { + case ossimROIEvent::OSSIM_RECTANGLE_ROI: + handleRectangleROIEvent( *roiEvent ); + break; + + case ossimROIEvent::OSSIM_POLYGON_ROI: + handlePolygonROIEvent( *roiEvent ); + break; + + + case ossimROIEvent::OSSIM_POLYLINE_ROI: + handlePolylineROIEvent( *roiEvent ); + break; + + default: + break; + } + } +} + +void ossimROIEventListener::handleRectangleROIEvent( ossimROIEvent& event ) +{ +} + +void ossimROIEventListener::handlePolygonROIEvent( ossimROIEvent& event ) +{ +} + +void ossimROIEventListener::handlePolylineROIEvent( ossimROIEvent& event ) +{ +} diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimROIEventListener.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimROIEventListener.h new file mode 100644 index 0000000000..813f2385b5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimROIEventListener.h @@ -0,0 +1,22 @@ +#ifndef ossimROIEventListener_HEADER +#define ossimROIEventListener_HEADER + +#include "base/common/events/ossimListener.h" +//#include "gui/wx/events/ossimROIEvent.h" +#include "ossimROIEvent.h" + +class OSSIMDLLEXPORT ossimROIEventListener : public ossimListener +{ +public: + ossimROIEventListener() + { + } + virtual void processEvent(ossimEvent& event); + virtual void handleRectangleROIEvent( ossimROIEvent& event ); + virtual void handlePolygonROIEvent( ossimROIEvent& event ); + virtual void handlePolylineROIEvent( ossimROIEvent& event ); + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimRefreshEvent.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimRefreshEvent.cpp new file mode 100644 index 0000000000..28831bfb06 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimRefreshEvent.cpp @@ -0,0 +1,27 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// Description: A brief description of the contents of the file. +// +// +//************************************************************************* +// $Id: ossimRefreshEvent.cpp,v 1.1 2002/11/14 17:49:47 gpotts Exp $ +#include "ossimRefreshEvent.h" + +RTTI_DEF1(ossimRefreshEvent, "ossimRefreshEvent", ossimEvent); diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimRefreshEvent.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimRefreshEvent.h new file mode 100644 index 0000000000..13bcf9bfd2 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimRefreshEvent.h @@ -0,0 +1,48 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// Description: A brief description of the contents of the file. +// +// +//************************************************************************* +// $Id: ossimRefreshEvent.h,v 1.2 2003/01/06 19:02:30 gpotts Exp $ +#ifndef ossimRefreshEvent_HEADER +#define ossimRefreshEvent_HEADER +#include "ossimEvent.h" + +class OSSIMDLLEXPORT ossimRefreshEvent : public ossimEvent +{ +public: + + ossimRefreshEvent(ossimObject* object=NULL) // the object associated with the event if any + :ossimEvent(object, OSSIM_EVENT_REFRESH_ID) + {} + ossimRefreshEvent(const ossimRefreshEvent& rhs) + :ossimEvent(rhs) + { + } + virtual ossimObject* dup()const + { + return new ossimRefreshEvent(*this); + } + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimStateChangedEvent.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimStateChangedEvent.cpp new file mode 100644 index 0000000000..77210e79fe --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimStateChangedEvent.cpp @@ -0,0 +1,38 @@ +#include "ossimStateChangedEvent.h" + +ossimStateChangedEvent::ossimStateChangedEvent( ossimObject* object, + long id ) + : ossimEvent( object, id ) +{ +} + +void ossimStateChangedEvent::setNewKeywordlist( ossimKeywordlist kwl ) +{ + theNewKeywordlist = kwl; +} + +ossimKeywordlist ossimStateChangedEvent::getNewKeywordlist() +{ + return theNewKeywordlist; +} + + +void ossimStateChangedEvent::setOldKeywordlist( ossimKeywordlist kwl ) +{ + theOldKeywordlist = kwl; +} + +ossimKeywordlist ossimStateChangedEvent::getOldKeywordlist() +{ + return theOldKeywordlist; +} + +void ossimStateChangedEvent::setObjId( string objId ) +{ + theObjId = objId; +} + +string ossimStateChangedEvent::getObjId() +{ + return theObjId; +} diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimStateChangedEvent.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimStateChangedEvent.h new file mode 100644 index 0000000000..6bb3c8c759 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimStateChangedEvent.h @@ -0,0 +1,31 @@ +#ifndef ossimStateChangedEvent_HEADER +#define ossimStateChangedEvent_HEADER + +#include "ossimEvent.h" +#include "ossimEventIds.h" +#include "base/data_types/ossimKeywordlist.h" + +class OSSIMDLLEXPORT ossimStateChangedEvent : public ossimEvent +{ +public: + ossimStateChangedEvent( ossimObject* object=NULL, + long id=OSSIM_EVENT_STATE_CHANGED_ID ); + + void setObjId( string objId ); + void setNewKeywordlist( ossimKeywordlist kwl ); + void setOldKeywordlist( ossimKeywordlist kwl ); + + string getObjId(); + ossimKeywordlist getNewKeywordlist(); + ossimKeywordlist getOldKeywordlist(); + + // HACK - Need to set keywordlists too!!! + virtual ossimObject* dup()const{return new ossimStateChangedEvent(*this);} + +private: + string theObjId; + ossimKeywordlist theNewKeywordlist; + ossimKeywordlist theOldKeywordlist; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimViewEvent.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimViewEvent.cpp new file mode 100644 index 0000000000..fc66403160 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimViewEvent.cpp @@ -0,0 +1,27 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// Description: A brief description of the contents of the file. +// +// +//************************************************************************* +// $Id: ossimViewEvent.cpp,v 1.1 2002/12/09 14:38:36 gpotts Exp $ +#include "ossimViewEvent.h" + +RTTI_DEF1(ossimViewEvent, "ossimViewEvent", ossimEvent); diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimViewEvent.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimViewEvent.h new file mode 100644 index 0000000000..118887633d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimViewEvent.h @@ -0,0 +1,169 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// Description: A brief description of the contents of the file. +// +// +//************************************************************************* +// $Id: ossimViewEvent.h,v 1.8 2003/01/06 19:03:02 gpotts Exp $ +#ifndef ossimViewEvent_HEADER +#define ossimViewEvent_HEADER +#include "ossimEvent.h" +#include "base/data_types/ossimGpt.h" + +class OSSIMDLLEXPORT ossimViewEvent : public ossimEvent +{ +public: + enum ossimViewEventType + { + OSSIM_VIEW_EVENT_TYPE_GENERIC = 0, + OSSIM_VIEW_EVENT_SCALE_CHANGE, + OSSIM_VIEW_EVENT_TRANSFORM_CHANGE, + OSSIM_VIEW_EVENT_VIEW_TYPE_CHANGE + }; + enum ossimViewPropagateType + { + OSSIM_VIEW_EVENT_PROPAGATE_NONE = 0, + OSSIM_VIEW_EVENT_PROPAGATE_ALL_DISPLAYS = 1, + OSSIM_VIEW_EVENT_PROPAGATE_ALL_CHAINS = 2, + }; + + ossimViewEvent(ossimObject* view, + ossimGpt centerPt, + ossimViewPropagateType propagateType = OSSIM_VIEW_EVENT_PROPAGATE_NONE, + ossimViewEventType eventType = OSSIM_VIEW_EVENT_TYPE_GENERIC, + ossimObject* object=NULL) + :ossimEvent(object, OSSIM_EVENT_VIEW_ID), + theView(view), + theCenterPoint(centerPt), + theEventType(eventType), + thePropagateType(propagateType), + theUpdateInputViewFlag(true), + theRefreshDisplayFlag(true) + { + } + ossimViewEvent(const ossimViewEvent& rhs) + :ossimEvent(rhs), + theView(rhs.theView), + theCenterPoint(rhs.theCenterPoint), + theEventType(rhs.theEventType), + thePropagateType(rhs.thePropagateType), + theUpdateInputViewFlag(rhs.theUpdateInputViewFlag), + theRefreshDisplayFlag(rhs.theRefreshDisplayFlag) + { + } + virtual ossimObject* dup()const + { + return new ossimViewEvent(*this); + } + virtual void setView(ossimObject* view) + { + theView = view; + } + virtual ossimObject* getView() + { + return theView; + } + void disablePropagation() + { + thePropagateType = OSSIM_VIEW_EVENT_PROPAGATE_NONE; + } + void setPropagateType(ossimViewPropagateType type) + { + thePropagateType = type; + } + void setViewEventType(ossimViewEventType eventType) + { + theEventType = eventType; + } + void setEventTypeViewTypeChange() + { + theEventType = OSSIM_VIEW_EVENT_VIEW_TYPE_CHANGE; + } + void setEventTypeTransformChange() + { + theEventType = OSSIM_VIEW_EVENT_TRANSFORM_CHANGE; + } + void setEventTypeGeneric() + { + theEventType = OSSIM_VIEW_EVENT_TYPE_GENERIC; + } + void setCenterGroundPoint(const ossimGpt& gpt) + { + theCenterPoint = gpt; + } + const ossimGpt& getCenterGroundPoint()const + { + return theCenterPoint; + } + ossimViewEventType getViewEventType()const + { + return theEventType; + } + bool isViewChange()const + { + return (theEventType == OSSIM_VIEW_EVENT_VIEW_TYPE_CHANGE); + } + bool isTransformChange()const + { + return (theEventType == OSSIM_VIEW_EVENT_TRANSFORM_CHANGE); + } + bool isScaleChange()const + { + return (theEventType == OSSIM_VIEW_EVENT_SCALE_CHANGE); + + } + bool isPropagateEnabled()const + { + return (thePropagateType != OSSIM_VIEW_EVENT_PROPAGATE_NONE); + } + bool isPropagateToDisplays()const + { + return (thePropagateType & OSSIM_VIEW_EVENT_PROPAGATE_ALL_DISPLAYS); + } + bool isPropagateToChains()const + { + return (thePropagateType & OSSIM_VIEW_EVENT_PROPAGATE_ALL_CHAINS); + } + void setUpdateInputViewFlag(bool flag) + { + theUpdateInputViewFlag = flag; + } + bool getUpdateInputViewFlag()const + { + return theUpdateInputViewFlag; + } + void setRefreshDisplayFlag(bool flag) + { + theRefreshDisplayFlag = flag; + } + bool getRefreshDisplayFlag()const + { + return theRefreshDisplayFlag; + } +protected: + ossimObject* theView; + ossimGpt theCenterPoint; + ossimViewEventType theEventType; + ossimViewPropagateType thePropagateType; + bool theUpdateInputViewFlag; + bool theRefreshDisplayFlag; +TYPE_DATA +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimViewListener.cpp b/Utilities/OSSIM/ossim_core/base/common/events/ossimViewListener.cpp new file mode 100644 index 0000000000..bad5f3409b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimViewListener.cpp @@ -0,0 +1,59 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// Description: A brief description of the contents of the file. +// +// +//************************************************************************* +// $Id: ossimViewListener.cpp,v 1.3 2002/12/20 15:14:44 gpotts Exp $ +#include "ossimViewListener.h" + +RTTI_DEF1(ossimViewListener, "ossimViewListener", ossimListener); +void ossimViewListener::processEvent(ossimEvent& event) +{ + ossimViewEvent* evt = PTR_CAST(ossimViewEvent, &event); + + if(evt) + { + switch(evt->getViewEventType()) + { + case ossimViewEvent::OSSIM_VIEW_EVENT_SCALE_CHANGE: + { + viewScaleChangeEvent(*evt); + break; + } + case ossimViewEvent::OSSIM_VIEW_EVENT_TYPE_GENERIC: + { + viewEvent(*evt); + break; + } + case ossimViewEvent::OSSIM_VIEW_EVENT_TRANSFORM_CHANGE: + { + viewTransformChangeEvent(*evt); + break; + } + case ossimViewEvent::OSSIM_VIEW_EVENT_VIEW_TYPE_CHANGE: + { + viewTypeChangeEvent(*evt); + break; + } + } + allViewEvents(*evt); + } +} diff --git a/Utilities/OSSIM/ossim_core/base/common/events/ossimViewListener.h b/Utilities/OSSIM/ossim_core/base/common/events/ossimViewListener.h new file mode 100644 index 0000000000..5dba34d20b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/events/ossimViewListener.h @@ -0,0 +1,51 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// Description: A brief description of the contents of the file. +// +// +//************************************************************************* +// $Id: ossimViewListener.h,v 1.3 2002/12/20 15:14:38 gpotts Exp $ +#ifndef ossimViewListener_HEADER +#define ossimViewListener_HEADER +#include "ossimListener.h" +#include "ossimViewEvent.h" + +class OSSIMDLLEXPORT ossimViewListener : public ossimListener +{ +public: + ossimViewListener():ossimListener(){} + virtual ~ossimViewListener(){} + + virtual void processEvent(ossimEvent& event); + virtual void viewScaleChangeEvent(ossimViewEvent& event) + {} + virtual void viewTypeChangeEvent(ossimViewEvent& event) + {} + virtual void viewEvent(ossimViewEvent& event) + {} + virtual void viewTransformChangeEvent(ossimViewEvent& event) + {} + + virtual void allViewEvents(ossimViewEvent& event) + {} +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimApplicationUsage.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimApplicationUsage.cpp new file mode 100644 index 0000000000..a3b622c238 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimApplicationUsage.cpp @@ -0,0 +1,206 @@ +//------------------------------------------------------------------------- +// +// This code was taken from Open Scene Graph and incorporated from into +// OSSIM. +// +//------------------------------------------------------------------------- +// $Id: ossimApplicationUsage.cpp,v 1.4 2005/09/08 11:01:02 gpotts Exp $ +#include <base/common/ossimApplicationUsage.h> +#include <base/common/ossimCommon.h> + +ossimApplicationUsage::ossimApplicationUsage(const ossimString& commandLineUsage): + theCommandLineUsage(commandLineUsage) +{ +} + +ossimApplicationUsage* ossimApplicationUsage::instance() +{ + static ossimApplicationUsage theApplicationUsage; + return &theApplicationUsage; +} +void ossimApplicationUsage::setApplicationName(const ossimString& name) +{ + theApplicationName = name; +} + +const ossimString& ossimApplicationUsage::getApplicationName() const +{ + return theApplicationName; +} +void ossimApplicationUsage::setDescription(const ossimString& desc) +{ + theDescription = desc; +} + +const ossimString& ossimApplicationUsage::getDescription() const +{ + return theDescription; +} + +void ossimApplicationUsage::addUsageExplanation(Type type,const ossimString& option,const ossimString& explanation) +{ + switch(type) + { + case(OSSIM_COMMAND_LINE_OPTION): + addCommandLineOption(option,explanation); + break; + case(OSSIM_ENVIRONMENTAL_VARIABLE): + addEnvironmentalVariable(option,explanation); + break; + } +} +void ossimApplicationUsage::setCommandLineUsage(const ossimString& explanation) +{ + theCommandLineUsage=explanation; +} + +const ossimString& ossimApplicationUsage::getCommandLineUsage() const +{ + return theCommandLineUsage; +} + +void ossimApplicationUsage::addCommandLineOption(const ossimString& option,const ossimString& explanation) +{ + theCommandLineOptions[option]=explanation; +} + +const ossimApplicationUsage::UsageMap& ossimApplicationUsage::getCommandLineOptions() const +{ + return theCommandLineOptions; +} + +void ossimApplicationUsage::addEnvironmentalVariable(const ossimString& option,const ossimString& explanation) +{ + theEnvironmentalVariables[option]=explanation; +} +const ossimApplicationUsage::UsageMap& ossimApplicationUsage::getEnvironmentalVariables() const +{ + return theEnvironmentalVariables; +} + +void ossimApplicationUsage::getFormatedString(ossimString& str, const UsageMap& um,unsigned int widthOfOutput) +{ + + unsigned int maxNumCharsInOptions = 0; + ossimApplicationUsage::UsageMap::const_iterator citr; + for(citr=um.begin(); + citr!=um.end(); + ++citr) + { + maxNumCharsInOptions = ossimMax(maxNumCharsInOptions,(unsigned int)citr->first.length()); + } + + unsigned int fullWidth = widthOfOutput; + unsigned int optionPos = 2; + unsigned int explanationPos = 2+maxNumCharsInOptions+2; + unsigned int explanationWidth = fullWidth-explanationPos; + + ossimString line; + + for(citr=um.begin(); + citr!=um.end(); + ++citr) + { + line.assign(fullWidth,' '); + line.replace(optionPos,citr->first.length(),citr->first); + + const ossimString& explanation = citr->second; + ossimString::size_type pos = 0; + ossimString::size_type offset = 0; + bool firstInLine = true; + while (pos<explanation.length()) + { + if (firstInLine) offset = 0; + + // skip any leading white space. + while (pos<explanation.length() && *(explanation.begin()+pos)==' ') + { + if (firstInLine) ++offset; + ++pos; + } + + firstInLine = false; + + ossimString::size_type width = ossimMin((ossimString::size_type)(explanation.length()-pos),(ossimString::size_type)(explanationWidth-offset)); + ossimString::size_type slashn_pos = explanation.find('\n',pos); + + unsigned int extraSkip = 0; + bool concatinated = false; + if (slashn_pos!=ossimString::npos) + { + if (slashn_pos<pos+width) + { + width = slashn_pos-pos; + ++extraSkip; + firstInLine = true; + } + else if (slashn_pos==pos+width) + { + ++extraSkip; + firstInLine = true; + } + } + + if (pos+width<explanation.length()) + { + // now reduce width until we get a space or a return + // so that we ensure that whole words are printed. + while (width>0 && + *(explanation.begin()+(pos+width))!=' ' && + *(explanation.begin()+(pos+width))!='\n') --width; + + if (width==0) + { + // word must be longer than a whole line so will need + // to concatinate it. + width = explanationWidth-1; + concatinated = true; + } + } + + line.replace(explanationPos+offset,explanationWidth, explanation, pos, width); + + if (concatinated) { str += line; str += "-\n"; } + else { str += line; str += "\n"; } + + // move to the next line of output. + line.assign(fullWidth,' '); + + pos += width+extraSkip; + + + } + + } +} + +void ossimApplicationUsage::write(std::ostream& output, const ossimApplicationUsage::UsageMap& um,unsigned int widthOfOutput) +{ + ossimString str; + getFormatedString(str, um, widthOfOutput); + output << str << std::endl; +} + +void ossimApplicationUsage::write(std::ostream& output, unsigned int type, unsigned int widthOfOutput) +{ + + output << "Usage: "<<getCommandLineUsage()<<std::endl; + bool needspace = false; + if ((type&OSSIM_COMMAND_LINE_OPTION) && !getCommandLineOptions().empty()) + { + if (needspace) output << std::endl; + output << "Options:"<<std::endl; + write(output,getCommandLineOptions(),widthOfOutput); + needspace = true; + } + + if ((type&OSSIM_ENVIRONMENTAL_VARIABLE) && !getEnvironmentalVariables().empty()) + { + if (needspace) output << std::endl; + output << "Environmental Variables:"<<std::endl; + write(output,getEnvironmentalVariables(),widthOfOutput); + needspace = true; + } + +} + diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimApplicationUsage.h b/Utilities/OSSIM/ossim_core/base/common/ossimApplicationUsage.h new file mode 100644 index 0000000000..a5f68a6e09 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimApplicationUsage.h @@ -0,0 +1,85 @@ +//------------------------------------------------------------------------- +// +// This code was taken from Open Scene Graph and incorporated from into +// OSSIM. +// +//------------------------------------------------------------------------- +// $Id: ossimApplicationUsage.h,v 1.3 2005/08/18 14:31:44 gpotts Exp $ +#ifndef ossimApplicationUsage_HEADER +#define ossimApplicationUsage_HEADER 1 + +#include <base/common/ossimConstants.h> +#include <base/data_types/ossimString.h> +#include <map> +#include <string> +#include <iostream> + +class OSSIMDLLEXPORT ossimApplicationUsage +{ + public: + + static ossimApplicationUsage* instance(); + + ossimApplicationUsage() {} + + ossimApplicationUsage(const ossimString& commandLineUsage); + + typedef std::map<ossimString,ossimString> UsageMap; + + + void setApplicationName(const ossimString& name); + const ossimString& getApplicationName() const; + + void setDescription(const ossimString& desc); + const ossimString& getDescription() const; + + enum Type + { + OSSIM_COMMAND_LINE_OPTION = 0x1, + OSSIM_ENVIRONMENTAL_VARIABLE = 0x2 + }; + + void addUsageExplanation(Type type,const ossimString& option,const ossimString& explanation); + + void setCommandLineUsage(const ossimString& explanation); + + const ossimString& getCommandLineUsage() const; + + + void addCommandLineOption(const ossimString& option,const ossimString& explanation); + + const UsageMap& getCommandLineOptions() const; + + + void addEnvironmentalVariable(const ossimString& option,const ossimString& explanation); + + const UsageMap& getEnvironmentalVariables() const; + + void getFormatedString(ossimString& str, const UsageMap& um,unsigned int widthOfOutput=80); + + void write(std::ostream& output,const UsageMap& um,unsigned int widthOfOutput=80); + + void write(std::ostream& output,unsigned int type=OSSIM_COMMAND_LINE_OPTION|OSSIM_ENVIRONMENTAL_VARIABLE, unsigned int widthOfOutput=80); + + protected: + + ossimString theApplicationName; + ossimString theDescription; + ossimString theCommandLineUsage; + UsageMap theCommandLineOptions; + UsageMap theEnvironmentalVariables; +}; + +class ApplicationUsageProxy +{ + public: + + /** register an explanation of commandline/evironmentalvaraible/keyboard mouse usage.*/ + ApplicationUsageProxy(ossimApplicationUsage::Type type,const ossimString& option,const ossimString& explanation) + { + ossimApplicationUsage::instance()->addUsageExplanation(type,option,explanation); + } +}; + + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimArgumentParser.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimArgumentParser.cpp new file mode 100644 index 0000000000..c1adbdc360 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimArgumentParser.cpp @@ -0,0 +1,468 @@ +//------------------------------------------------------------------------- +// +// This code was taken from Open Scene Graph and incorporated from into +// OSSIM. +// +//------------------------------------------------------------------------- +// $Id: ossimArgumentParser.cpp,v 1.4 2005/04/01 20:39:25 dburken Exp $ +#include <base/common/ossimArgumentParser.h> +#include <base/common/ossimApplicationUsage.h> +#include <set> +#include <iostream> +#include <base/data_types/ossimString.h> + +bool ossimArgumentParser::isOption(const char* str) +{ + return str && str[0]=='-'; +} + +bool ossimArgumentParser::isString(const char* str) +{ + if (!str) return false; + + return true; +// return !isOption(str); +} + +bool ossimArgumentParser::isNumber(const char* str) +{ + if (!str) return false; + + bool hadPlusMinus = false; + bool hadDecimalPlace = false; + bool hadExponent = false; + bool couldBeInt = true; + bool couldBeFloat = true; + int noZeroToNine = 0; + + const char* ptr = str; + + // check if could be a hex number. + if (strncmp(ptr,"0x",2)==0) + { + // skip over leading 0x, and then go through rest of string + // checking to make sure all values are 0...9 or a..f. + ptr+=2; + while ( + *ptr!=0 && + ((*ptr>='0' && *ptr<='9') || + (*ptr>='a' && *ptr<='f') || + (*ptr>='A' && *ptr<='F')) + ) + { + ++ptr; + } + + // got to end of string without failure, therefore must be a hex integer. + if (*ptr==0) return true; + } + + ptr = str; + + // check if a float or an int. + while (*ptr!=0 && couldBeFloat) + { + if (*ptr=='+' || *ptr=='-') + { + if (hadPlusMinus) + { + couldBeInt = false; + couldBeFloat = false; + } + else + { + hadPlusMinus = true; + } + } + else if (*ptr>='0' && *ptr<='9') + { + noZeroToNine++; + } + else if (*ptr=='.') + { + if (hadDecimalPlace) + { + couldBeInt = false; + couldBeFloat = false; + } + else + { + hadDecimalPlace = true; + couldBeInt = false; + } + } + else if (*ptr=='e' || *ptr=='E') + { + if (hadExponent || noZeroToNine==0) + { + couldBeInt = false; + couldBeFloat = false; + } + else + { + hadExponent = true; + couldBeInt = false; + hadDecimalPlace = false; + hadPlusMinus = false; + noZeroToNine=0; + } + } + else + { + couldBeInt = false; + couldBeFloat = false; + } + ++ptr; + } + + if (couldBeInt && noZeroToNine>0) return true; + if (couldBeFloat && noZeroToNine>0) return true; + + return false; + +} + +bool ossimArgumentParser::ossimParameter::valid(const char* str) const +{ + switch(theType) + { + case ossimParameter::OSSIM_FLOAT_PARAMETER: return isNumber(str); + case ossimParameter::OSSIM_DOUBLE_PARAMETER: return isNumber(str); + case ossimParameter::OSSIM_INT_PARAMETER: return isNumber(str); + case ossimParameter::OSSIM_UNSIGNED_INT_PARAMETER: return isNumber(str); + case ossimParameter::OSSIM_STRING_PARAMETER: return isString(str); + } + return false; +} + +bool ossimArgumentParser::ossimParameter::assign(const char* str) +{ + if (valid(str)) + { + switch(theType) + { + case ossimParameter::OSSIM_FLOAT_PARAMETER: *theValue.theFloat = (float)ossimString(str).toDouble(); break; + case ossimParameter::OSSIM_DOUBLE_PARAMETER: *theValue.theDouble = ossimString(str).toDouble(); break; + case ossimParameter::OSSIM_INT_PARAMETER: *theValue.theInt = ossimString(str).toInt(); break; + case ossimParameter::OSSIM_UNSIGNED_INT_PARAMETER: *theValue.theUint = ossimString(str).toUInt32(); break; + case ossimParameter::OSSIM_STRING_PARAMETER: *theValue.theString = str; break; + } + return true; + } + else + { + return false; + } +} + + + +ossimArgumentParser::ossimArgumentParser(int* argc,char **argv): + theArgc(argc), + theArgv(argv), + theUsage(ossimApplicationUsage::instance()) +{ +} + +ossimArgumentParser::~ossimArgumentParser() +{ +} + +std::string ossimArgumentParser::getApplicationName() const +{ + if (theArgc && *theArgc>0 ) return std::string(theArgv[0]); + return ""; +} + + +bool ossimArgumentParser::isOption(int pos) const +{ + return pos<*theArgc && isOption(theArgv[pos]); +} + +bool ossimArgumentParser::isString(int pos) const +{ + return pos < *theArgc && isString(theArgv[pos]); +} + +bool ossimArgumentParser::isNumber(int pos) const +{ + return pos < *theArgc && isNumber(theArgv[pos]); +} + + +int ossimArgumentParser::find(const std::string& str) const +{ + for(int pos=1;pos<*theArgc;++pos) + { + if (str==theArgv[pos]) + { + return pos; + } + } + return 0; +} + +bool ossimArgumentParser::match(int pos, const std::string& str) const +{ + return pos<*theArgc && str==theArgv[pos]; +} + + +bool ossimArgumentParser::containsOptions() const +{ + for(int pos=1;pos<*theArgc;++pos) + { + if (isOption(pos)) return true; + } + return false; +} + + +void ossimArgumentParser::remove(int pos,int num) +{ + if (num==0) return; + + for(;pos+num<*theArgc;++pos) + { + theArgv[pos]=theArgv[pos+num]; + } + for(;pos<*theArgc;++pos) + { + theArgv[pos]=0; + } + *theArgc-=num; +} + +bool ossimArgumentParser::read(const std::string& str) +{ + int pos=find(str); + if (pos<=0) return false; + remove(pos); + return true; +} + +bool ossimArgumentParser::read(const std::string& str, ossimParameter value1) +{ + int pos=find(str); + if (pos<=0) return false; + if (!value1.valid(theArgv[pos+1])) + { + reportError("argument to `"+str+"` is missing"); + return false; + } + value1.assign(theArgv[pos+1]); + remove(pos,2); + return true; +} + +bool ossimArgumentParser::read(const std::string& str, ossimParameter value1, ossimParameter value2) +{ + int pos=find(str); + if (pos<=0) return false; + if (!value1.valid(theArgv[pos+1]) || + !value2.valid(theArgv[pos+2])) + { + reportError("argument to `"+str+"` is missing"); + return false; + } + value1.assign(theArgv[pos+1]); + value2.assign(theArgv[pos+2]); + remove(pos,3); + return true; +} + +bool ossimArgumentParser::read(const std::string& str, ossimParameter value1, ossimParameter value2, ossimParameter value3) +{ + int pos=find(str); + if (pos<=0) return false; + if (!value1.valid(theArgv[pos+1]) || + !value2.valid(theArgv[pos+2]) || + !value2.valid(theArgv[pos+3])) + { + reportError("argument to `"+str+"` is missing"); + return false; + } + value1.assign(theArgv[pos+1]); + value2.assign(theArgv[pos+2]); + value3.assign(theArgv[pos+3]); + remove(pos,4); + return true; +} + +bool ossimArgumentParser::read(const std::string& str, ossimParameter value1, ossimParameter value2, ossimParameter value3, ossimParameter value4) +{ + int pos=find(str); + if (pos<=0) return false; + if (!value1.valid(theArgv[pos+1]) || + !value2.valid(theArgv[pos+2]) || + !value2.valid(theArgv[pos+3]) || + !value3.valid(theArgv[pos+4])) + { + reportError("argument to `"+str+"` is missing"); + return false; + } + value1.assign(theArgv[pos+1]); + value2.assign(theArgv[pos+2]); + value3.assign(theArgv[pos+3]); + value4.assign(theArgv[pos+4]); + remove(pos,5); + return true; +} + + +/** if the argument value at the psotion pos matches specified string, and subsequent + * paramters are also matched then set the paramter values and remove the from the list of arguments.*/ +bool ossimArgumentParser::read(int pos, const std::string& str) +{ + if (match(pos,str)) + { + remove(pos,1); + return true; + } + else + { + return false; + } +} + +bool ossimArgumentParser::read(int pos, const std::string& str, ossimParameter value1) +{ + if (match(pos,str) && + value1.valid(theArgv[pos+1])) + { + value1.assign(theArgv[pos+1]); + remove(pos,2); + return true; + } + else + { + return false; + } +} + +bool ossimArgumentParser::read(int pos, const std::string& str, ossimParameter value1, ossimParameter value2) +{ + if (match(pos,str) && + value1.valid(theArgv[pos+1]) && + value2.valid(theArgv[pos+2])) + { + value1.assign(theArgv[pos+1]); + value2.assign(theArgv[pos+2]); + remove(pos,3); + return true; + } + else + { + return false; + } +} + +bool ossimArgumentParser::read(int pos, const std::string& str, ossimParameter value1, ossimParameter value2, ossimParameter value3) +{ + if (match(pos,str) && + value1.valid(theArgv[pos+1]) && + value2.valid(theArgv[pos+2]) && + value3.valid(theArgv[pos+3])) + { + value1.assign(theArgv[pos+1]); + value2.assign(theArgv[pos+2]); + value3.assign(theArgv[pos+3]); + remove(pos,4); + return true; + } + else + { + return false; + } +} + +bool ossimArgumentParser::read(int pos, const std::string& str, ossimParameter value1, ossimParameter value2, ossimParameter value3, ossimParameter value4) +{ + if (match(pos,str) && + value1.valid(theArgv[pos+1]) && + value2.valid(theArgv[pos+2]) && + value3.valid(theArgv[pos+3]) && + value4.valid(theArgv[pos+4])) + { + value1.assign(theArgv[pos+1]); + value2.assign(theArgv[pos+2]); + value3.assign(theArgv[pos+3]); + value4.assign(theArgv[pos+4]); + remove(pos,5); + return true; + } + else + { + return false; + } +} + + + +bool ossimArgumentParser::errors(ossimErrorSeverity severity) const +{ + for(ossimErrorMessageMap::const_iterator itr=theErrorMessageMap.begin(); + itr!=theErrorMessageMap.end(); + ++itr) + { + if (itr->second>=severity) return true; + } + return false; +} + +void ossimArgumentParser::reportError(const std::string& message, ossimErrorSeverity severity) +{ + theErrorMessageMap[message]=severity; +} + +void ossimArgumentParser::reportRemainingOptionsAsUnrecognized(ossimErrorSeverity severity) +{ + std::set<std::string> options; + if (theUsage) + { + // parse the usage options to get all the option that the application can potential handle. + for(ossimApplicationUsage::UsageMap::const_iterator itr=theUsage->getCommandLineOptions().begin(); + itr!=theUsage->getCommandLineOptions().end(); + ++itr) + { + const std::string& option = itr->first; + std::string::size_type prevpos = 0, pos = 0; + while ((pos=option.find(' ',prevpos))!=std::string::npos) + { + if (option[prevpos]=='-') + { + options.insert(std::string(option,prevpos,pos-prevpos)); + } + prevpos=pos+1; + } + if (option[prevpos]=='-') + { + + options.insert(std::string(option,prevpos,std::string::npos)); + } + } + + } + + for(int pos=1;pos<argc();++pos) + { + // if an option and havn't been previous querried for report as unrecognized. + if (isOption(pos) && options.find(theArgv[pos])==options.end()) + { + reportError(getApplicationName() +": unrecognized option "+theArgv[pos],severity); + } + } +} +void ossimArgumentParser::writeErrorMessages(std::ostream& output, ossimErrorSeverity severity) +{ + for(ossimErrorMessageMap::iterator itr=theErrorMessageMap.begin(); + itr!=theErrorMessageMap.end(); + ++itr) + { + if (itr->second>=severity) + { + output<< getApplicationName() << ": " << itr->first << std::endl; + } + } +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimArgumentParser.h b/Utilities/OSSIM/ossim_core/base/common/ossimArgumentParser.h new file mode 100644 index 0000000000..92fa48f7b1 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimArgumentParser.h @@ -0,0 +1,187 @@ +//------------------------------------------------------------------------- +// +// This code was taken from Open Scene Graph and incorporated from into +// OSSIM. +// +//------------------------------------------------------------------------- +// $Id: ossimArgumentParser.h,v 1.3 2005/04/01 20:39:25 dburken Exp $ +#ifndef ossimArgumentParser_HEADER +#define ossimArgumentParser_HEADER 1 +#include <base/common/ossimConstants.h> +#include <map> +#include <string> +#include <iostream> + +class ossimApplicationUsage; + +class OSSIMDLLEXPORT ossimArgumentParser +{ +public: + + class ossimParameter + { + public: + enum ossimParameterType + { + OSSIM_FLOAT_PARAMETER, + OSSIM_DOUBLE_PARAMETER, + OSSIM_INT_PARAMETER, + OSSIM_UNSIGNED_INT_PARAMETER, + OSSIM_STRING_PARAMETER, + }; + + union ossimValueUnion + { + float* theFloat; + double* theDouble; + int* theInt; + unsigned int* theUint; + std::string* theString; + }; + + ossimParameter(float& value) + { + theType = OSSIM_FLOAT_PARAMETER; theValue.theFloat = &value; + } + + ossimParameter(double& value) + { + theType = OSSIM_DOUBLE_PARAMETER; theValue.theDouble = &value; + } + + ossimParameter(int& value) + { + theType = OSSIM_INT_PARAMETER; theValue.theInt = &value; + } + + ossimParameter(unsigned int& value) + { + theType = OSSIM_UNSIGNED_INT_PARAMETER; theValue.theUint = &value; + } + + ossimParameter(std::string& value) + { + theType = OSSIM_STRING_PARAMETER; theValue.theString = &value; + } + + bool valid(const char* str) const; + bool assign(const char* str); + + protected: + + ossimParameterType theType; + ossimValueUnion theValue; + }; + + /** return return true if specified string is an option in the form of + * -option or --option . + */ + static bool isOption(const char* str); + + /** return return true if string is any other string apart from an option.*/ + static bool isString(const char* str); + + /** return return true if specified parameter is an number.*/ + static bool isNumber(const char* str); + +public: + + ossimArgumentParser(int* argc,char **argv); + + ~ossimArgumentParser(); + + void setApplicationUsage(ossimApplicationUsage* usage) { theUsage = usage; } + ossimApplicationUsage* getApplicationUsage() { return theUsage; } + const ossimApplicationUsage* getApplicationUsage() const { return theUsage; } + + /** return the argument count.*/ + int& argc() { return *theArgc; } + + /** return the argument array.*/ + char** argv() { return theArgv; } + + /** return char* argument at specificed position.*/ + char* operator [] (int pos) { return theArgv[pos]; } + + /** return const char* argument at specificed position.*/ + const char* operator [] (int pos) const { return theArgv[pos]; } + + /** return the application name, as specified by argv[0] */ + std::string getApplicationName() const; + + /** return the position of an occurance of a string in the argument list. + * return -1 when no string is found.*/ + int find(const std::string& str) const; + + /** return return true if specified parameter is an option in the form of -option or --option .*/ + bool isOption(int pos) const; + + /** return return true if specified parameter is an string, which can be any other string apart from an option.*/ + bool isString(int pos) const; + + /** return return true if specified parameter is an number.*/ + bool isNumber(int pos) const; + + bool containsOptions() const; + + /** remove one or more arguments from the argv argument list, and decrement the argc respectively.*/ + void remove(int pos,int num=1); + + /** return true if specified argument matches string.*/ + bool match(int pos, const std::string& str) const; + + /** search for an occurance of a string in the argument list, on sucess + * remove that occurance from the list and return true, otherwise return false.*/ + bool read(const std::string& str); + bool read(const std::string& str, ossimParameter value1); + bool read(const std::string& str, ossimParameter value1, ossimParameter value2); + bool read(const std::string& str, ossimParameter value1, ossimParameter value2, ossimParameter value3); + bool read(const std::string& str, ossimParameter value1, ossimParameter value2, ossimParameter value3, ossimParameter value4); + + + /** if the argument value at the position pos matches specified string, and subsequent + * paramters are also matched then set the paramter values and remove the from the list of arguments.*/ + bool read(int pos, const std::string& str); + bool read(int pos, const std::string& str, ossimParameter value1); + bool read(int pos, const std::string& str, ossimParameter value1, ossimParameter value2); + bool read(int pos, const std::string& str, ossimParameter value1, ossimParameter value2, ossimParameter value3); + bool read(int pos, const std::string& str, ossimParameter value1, ossimParameter value2, ossimParameter value3, ossimParameter value4); + + + enum ossimErrorSeverity + { + OSSIM_BENIGN = 0, + OSSIM_CRITICAL = 1 + }; + + typedef std::map<std::string,ossimErrorSeverity> ossimErrorMessageMap; + + /** return the error flag, true if an error has occured when reading arguments.*/ + bool errors(ossimErrorSeverity severity=OSSIM_BENIGN) const; + + /** report an error message by adding to the ErrorMessageMap.*/ + void reportError(const std::string& message,ossimErrorSeverity severity=OSSIM_CRITICAL); + + /** for each remaining option report it as an unrecongnized.*/ + void reportRemainingOptionsAsUnrecognized(ossimErrorSeverity severity=OSSIM_BENIGN); + + /** return the error message, if any has occured.*/ + ossimErrorMessageMap& getErrorMessageMap() { return theErrorMessageMap; } + + /** return the error message, if any has occured.*/ + const ossimErrorMessageMap& getErrorMessageMap() const { return theErrorMessageMap; } + + /** write out error messages at an above specified .*/ + void writeErrorMessages(std::ostream& output,ossimErrorSeverity sevrity=OSSIM_BENIGN); + + +protected: + + int* theArgc; + char** theArgv; + ossimErrorMessageMap theErrorMessageMap; + ossimApplicationUsage* theUsage; + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimCommon.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimCommon.cpp new file mode 100644 index 0000000000..42350b5204 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimCommon.cpp @@ -0,0 +1,325 @@ +//******************************************************************* +// Copyright (C) 2004 Intelligence Data Systems, Inc. All rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: Common file for global functions. +// +//************************************************************************* +// $Id: ossimCommon.cpp,v 1.9 2006/01/10 21:04:02 gpotts Exp $ + +#include <base/common/ossimCommon.h> +#include <base/common/ossimConstants.h> +#include <base/common/ossimPreferences.h> +#include <base/common/ossimTrace.h> +#include <base/context/ossimNotifyContext.h> +#include <base/data_types/ossimIpt.h> +#include <sstream> + +ossimMutex theCriticalSectionMutex; + +static ossimTrace traceDebug("ossimCommon:debug"); + +ossimByteOrder ossimGetByteOrder() +{ + union + { + short s; + char c[sizeof(short)]; + } un; + + un.s = 0x0102; + if (un.c[0] == 2 && un.c[1] == 1) + { + return OSSIM_LITTLE_ENDIAN; + } + else + { + return OSSIM_BIG_ENDIAN; + } +} + +double ossimGetDefaultMin(ossimScalarType scalarType) +{ + switch(scalarType) + { + case OSSIM_UINT8: + { + return OSSIM_DEFAULT_MIN_PIX_UCHAR; + } + case OSSIM_SINT8: + { + return OSSIM_DEFAULT_MIN_PIX_SINT8; + } + case OSSIM_UINT16: + { + return OSSIM_DEFAULT_MIN_PIX_UINT16; + } + case OSSIM_SINT16: + { + return OSSIM_DEFAULT_MIN_PIX_SINT16; + } + case OSSIM_USHORT11: + { + return OSSIM_DEFAULT_MIN_PIX_UINT11; + } + case OSSIM_UINT32: + { + return OSSIM_DEFAULT_MIN_PIX_UINT32; + } + case OSSIM_SINT32: + { + return OSSIM_DEFAULT_MIN_PIX_SINT32; + } + case OSSIM_FLOAT32: + { + return OSSIM_DEFAULT_MIN_PIX_FLOAT; + } + case OSSIM_NORMALIZED_FLOAT: + { + return OSSIM_DEFAULT_MIN_PIX_NORM_FLOAT; + } + case OSSIM_FLOAT64: + { + return OSSIM_DEFAULT_MIN_PIX_DOUBLE; + } + case OSSIM_NORMALIZED_DOUBLE: + { + return OSSIM_DEFAULT_MIN_PIX_NORM_DOUBLE; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << __FILE__ << ":" << __LINE__ + << "\nUnhandled scalar type: " << scalarType << endl; + } + break; + } + } + + return OSSIM_DBL_NAN; +} + +double ossimGetDefaultMax(ossimScalarType scalarType) +{ + switch(scalarType) + { + case OSSIM_UINT8: + { + return OSSIM_DEFAULT_MAX_PIX_UCHAR; + } + case OSSIM_SINT8: + { + return OSSIM_DEFAULT_MAX_PIX_SINT8; + } + case OSSIM_UINT16: + { + return OSSIM_DEFAULT_MAX_PIX_UINT16; + } + case OSSIM_SINT16: + { + return OSSIM_DEFAULT_MAX_PIX_SINT16; + } + case OSSIM_USHORT11: + { + return OSSIM_DEFAULT_MAX_PIX_UINT11; + } + case OSSIM_UINT32: + { + return OSSIM_DEFAULT_MAX_PIX_UINT32; + } + case OSSIM_SINT32: + { + return OSSIM_DEFAULT_MAX_PIX_SINT32; + } + case OSSIM_FLOAT32: + { + return OSSIM_DEFAULT_MAX_PIX_FLOAT; + } + case OSSIM_NORMALIZED_FLOAT: + { + return OSSIM_DEFAULT_MAX_PIX_NORM_FLOAT; + } + case OSSIM_FLOAT64: + { + return OSSIM_DEFAULT_MAX_PIX_DOUBLE; + } + case OSSIM_NORMALIZED_DOUBLE: + { + return OSSIM_DEFAULT_MAX_PIX_NORM_DOUBLE; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_WARN) + << __FILE__ << ":" << __LINE__ + << "\nUnhandled scalar type: " << scalarType << endl; + } + break; + } + } + return OSSIM_DBL_NAN; +} + +double ossimGetDefaultNull(ossimScalarType scalarType) +{ + switch(scalarType) + { + case OSSIM_UINT8: + { + return 0; + } + case OSSIM_SINT8: + { + return OSSIM_DEFAULT_MIN_PIX_SINT8-10; + } + case OSSIM_UINT16: + { + return 0; + } + case OSSIM_SINT16: + { + return OSSIM_SSHORT_NAN; + } + case OSSIM_USHORT11: + { + return 0; + } + case OSSIM_UINT32: + { + return 0; + } + case OSSIM_SINT32: + { + return OSSIM_INT_NAN; + } + case OSSIM_FLOAT32: + { + return OSSIM_FLT_NAN; + } + case OSSIM_NORMALIZED_FLOAT: + { + return 0.0; + } + case OSSIM_FLOAT64: + { + return OSSIM_DBL_NAN; + } + case OSSIM_NORMALIZED_DOUBLE: + { + return 0.0; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << __FILE__ << ":" << __LINE__ + << "\nUnhandled scalar type: " << scalarType << endl; + } + break; + } + } + + return OSSIM_DBL_NAN; +} + +ossim_uint32 ossimGetScalarSizeInBytes(ossimScalarType scalarType) +{ + switch(scalarType) + { + case OSSIM_UINT8: + { + return sizeof(ossim_uint8); + } + case OSSIM_SINT8: + { + return sizeof(ossim_sint8); + } + case OSSIM_UINT16: + case OSSIM_USHORT11: + { + return sizeof(ossim_uint16); + } + case OSSIM_SINT16: + { + return sizeof(ossim_sint16); + } + case OSSIM_UINT32: + { + return sizeof(ossim_uint32); + } + case OSSIM_SINT32: + { + return sizeof(ossim_sint32); + } + case OSSIM_FLOAT32: + case OSSIM_NORMALIZED_FLOAT: + { + return sizeof(ossim_float32); + } + case OSSIM_FLOAT64: + case OSSIM_NORMALIZED_DOUBLE: + { + return sizeof(ossim_float64); + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << __FILE__ << ":" << __LINE__ + << "\nUnhandled scalar type: " << scalarType << endl; + } + break; + } + } + + return 1; +} + +void ossimGetDefaultTileSize(ossimIpt& tileSize) +{ + const char* tileSizeKw = ossimPreferences::instance()-> + findPreference("tile_size"); + + if(tileSizeKw) + { + std::istringstream in(tileSizeKw); + bool hasX = true; + in >> tileSize.x >> tileSize.y; + + if(tileSize.x < 1) + { + tileSize.x = OSSIM_DEFAULT_TILE_WIDTH; + hasX = false; + } + if(tileSize.y < 1) + { + if(!hasX) + { + tileSize.y = OSSIM_DEFAULT_TILE_HEIGHT; + } + else + { + tileSize.y = tileSize.x; + } + } + } + else + { + tileSize.x = OSSIM_DEFAULT_TILE_WIDTH; + tileSize.y = OSSIM_DEFAULT_TILE_HEIGHT; + } +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimCommon.h b/Utilities/OSSIM/ossim_core/base/common/ossimCommon.h new file mode 100644 index 0000000000..648817f79c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimCommon.h @@ -0,0 +1,282 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// LICENSE: LGPL +// +// Author: Garrett Potts +// Description: Common file for global functions. +// +//************************************************************************* +// $Id: ossimCommon.h,v 1.24 2005/06/17 21:42:59 dburken Exp $ +#ifndef COMMON_H +#define COMMON_H + + +#include <cmath> +#include <base/common/ossimMutex.h> +#include <base/common/ossimConstants.h> +#include <base/common/ossimRtti.h> + +class ossimIpt; + +/** + * Mutex for lock/unlocking. + */ +extern ossimMutex theCriticalSectionMutex; + +//*** +// Common math functions +//*** +inline double cosd(double X) {return std::cos(X*RAD_PER_DEG);} +inline double sind(double X) {return std::sin(X*RAD_PER_DEG);} +inline double tand(double X) {return std::tan(X*RAD_PER_DEG);} +inline double acosd(double X) {return DEG_PER_RAD * std::acos(X);} +inline double asind(double X) {return DEG_PER_RAD * std::asin(X);} +inline double atand(double X) {return DEG_PER_RAD * std::atan(X);} +inline double atan2d(double Y, double X) +{ + return DEG_PER_RAD * std::atan2(Y,X); +} + +// Note: We use n and m as temporaries in this function, so there is no value +// in using const IntType& as we would only need to make a copy anyway... +template <typename IntType> +IntType ossimGcd(IntType n, IntType m) +{ + // Avoid repeated construction + IntType zero(0); + + // This is abs() - given the existence of broken compilers with Koenig + // lookup issues and other problems, I code this explicitly. (Remember, + // IntType may be a user-defined type). + if (n < zero) + n = -n; + if (m < zero) + m = -m; + + // As n and m are now positive, we can be sure that %= returns a + // positive value (the standard guarantees this for built-in types, + // and we require it of user-defined types). + for(;;) { + if(m == zero) + return n; + n %= m; + if(n == zero) + return m; + m %= n; + } +} + +template<class T> inline T ossimAbs(T val) +{ + return ( (val<0) ? ( val * ( (T)-1) ) : val ); +} + +template <typename IntType> +IntType ossimLcm(IntType n, IntType m) +{ + // Avoid repeated construction + IntType zero(0); + + if (n == zero || m == zero) + return zero; + + n /= gcd(n, m); + n *= m; + + if (n < zero) + n = -n; + return n; +} + +inline bool ossimIsNan(double val) +{ + return (val == OSSIM_DBL_NAN); +} + +inline bool ossimIsNan(float val) +{ + return (val == OSSIM_FLT_NAN); +} + +inline bool ossimIsNan(int val) +{ + return (val == OSSIM_INT_NAN); +} + +inline bool ossimIsNan(long val) +{ + return (val == OSSIM_INT_NAN); +} + +inline bool ossimIsNan(unsigned long val) +{ + return (val == OSSIM_ULONG_NAN); +} + +inline bool ossimIsNan(unsigned int val) +{ + return (val == OSSIM_UINT_NAN); +} + +inline double sinc(double x) +{ + x *= M_PI; + if(x != 0) + return std::sin(x)/x; + else + return 1.0; +} +inline int ossimGetSign(double value) +{ + return (value < 0?-1:1); +} + +#ifndef MAX +# define MAX(x,y) ((x)>(y)?(x):(y)) +# define MIN(x,y) ((x)>(y)?(y):(x)) +#endif + +#ifndef ABS +# define ABS(x) ((x)>0?(x):-(x)) +#endif + +#ifndef SIGN +# define SIGN(x) ((x)<0?(-1):(1)) +#endif + +template<class T> +T ossimClamp(const T& value, + const T& minValue, + const T& maxValue) +{ + if(value < minValue) return minValue; + if(value > maxValue) return maxValue; + return value; +} + +template<class T> +T ossimMax(T leftValue, T rightValue) +{ + if(leftValue < rightValue) + { + return rightValue; + } + return leftValue; +} + +template<class T> +T ossimMin(T leftValue, T rightValue) +{ + if(rightValue < leftValue) + { + return rightValue; + } + return leftValue; +} + + +template<class Type> inline Type SQ(Type &x) {return (x * x);} + +inline double square(double x) +{ + return x*x; +} + +inline long square(long x) +{ + return x*x; +} + +inline bool equals(double x, double y) +{ + return (ossimAbs(x-y) <= DBL_EPSILON); +} + +inline bool equals(float x, float y) +{ + return (ossimAbs(x-y) <= FLT_EPSILON); +} + +inline int factorial(int n) +{ + if(n == 0) return 1; + return (n * factorial(n - 1)); +} + +// Round a double to an int correctly. +//inline int irint(double d) { return int(floor(d + 0.5)); } +inline int irint(double d) +{ + return (int) ((d < 0) ? (d-.5):(d+.5)); +} + +// Round a double to an int correctly. +//inline long irlong(double d) { return long(floor(d + 0.5)); } +inline int irlong(double d) +{ + return (long) ((d < 0) ? (d-.5):(d+.5)); +} + +// Round a double to an int correctly. +//inline int irint(double d) { return int(floor(d + 0.5)); } +inline int irint(float d) +{ + return (int) ((d < 0) ? (d-.5):(d+.5)); +} + +// Round a double to an int correctly. +//inline long irlong(double d) { return long(floor(d + 0.5)); } +inline int irlong(float d) +{ + return (long) ((d < 0) ? (d-.5):(d+.5)); +} + +// Round a float to an int correctly. +//inline int irint(f32 f) { return int(floor(f + 0.5)); } + +// Round a double to an int correctly. +//inline long irlong(f32 f) { return long(floor(f + 0.5)); } + +// greatest common divisors of two integers +inline int gcd(int m, int n) +{ + if(n == 0) return m; + return gcd(n, m % n); +} + +//*** +// Common conversion functions +//*** +inline double ft2mtrs(double feet) +{ + return (feet * MTRS_PER_FT); +} + +inline double usft2mtrs(double feet) +{ + return (feet * US_METERS_PER_FT); +} + +inline double mtrs2ft(double meters) +{ + return (meters / MTRS_PER_FT); +} + +inline double mtrs2usft(double meters) +{ + return (meters / US_METERS_PER_FT); +} + +ossimByteOrder ossimGetByteOrder(); + +OSSIM_DLL double ossimGetDefaultMin(ossimScalarType scalarType); +OSSIM_DLL double ossimGetDefaultMax(ossimScalarType scalarType); +OSSIM_DLL double ossimGetDefaultNull(ossimScalarType scalarType); + +OSSIM_DLL ossim_uint32 ossimGetScalarSizeInBytes(ossimScalarType scalarType); + + +OSSIM_DLL void ossimGetDefaultTileSize(ossimIpt& tileSize); + +#endif /* #ifndef COMMON_H */ diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimConnectableContainer.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimConnectableContainer.cpp new file mode 100644 index 0000000000..e81a530592 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimConnectableContainer.cpp @@ -0,0 +1,772 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimConnectableContainer.cpp,v 1.48 2005/11/22 19:40:35 dburken Exp $ +#include <algorithm> +#include <base/common/ossimConnectableContainer.h> +#include <base/common/ossimIdManager.h> +#include <base/common/events/ossimObjectDestructingEvent.h> +#include <base/common/events/ossimPropertyEvent.h> +#include <base/common/events/ossimConnectionEvent.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/factory/ossimObjectFactoryRegistry.h> +#include <base/common/ossimTrace.h> +#include <base/context/ossimNotifyContext.h> + +#include <stack> +using namespace std; + +static ossimTrace traceDebug("ossimConnectableContainer:debug"); + +RTTI_DEF2(ossimConnectableContainer, "ossimConnectableContainer", ossimConnectableObject, ossimConnectableContainerInterface); + +class ossimConnectableContainerChildListener : public ossimConnectableObjectListener +{ +public: + ossimConnectableContainerChildListener(ossimConnectableContainer* container) + :theContainer(container), + theEnabledFlag(true) + {} + void enableListener(){theEnabledFlag = true;} + void disableListener(){theEnabledFlag = false;} + + virtual void objectDestructingEvent(ossimObjectDestructingEvent& event) + { + ossimConnectableObject* object = PTR_CAST(ossimConnectableObject, event.getObject()); + if(object&&theContainer) + { + if(theContainer->removeChild(object)) + { + object->removeListener((ossimConnectableObjectListener*) this); + } + } + propagatePropertyEvent(event); + + } + virtual void disconnectInputEvent(ossimConnectionEvent& event) + { + propagatePropertyEvent(event); + } + virtual void connectInputEvent(ossimConnectionEvent& event) + { + propagatePropertyEvent(event); + } + + void propagatePropertyEvent(ossimEvent& event) + { + if(theEnabledFlag) + { + if(event.getObject()) + { + ossimConnectableObject* connectable = PTR_CAST(ossimConnectableObject, + event.getObject()); + if(connectable) + { + ossimPropertyEvent evt(event.getObject()); + connectable->propagateEventToOutputs(evt); + } + } + } + } + ossimConnectableContainer* theContainer; + bool theEnabledFlag; + +}; + +ossimConnectableContainer::ossimConnectableContainer(ossimConnectableObject* owner) + :ossimConnectableObject(owner, 0, 0, true, true), + ossimConnectableContainerInterface(NULL) +{ + ossimConnectableContainerInterface::theBaseObject = this; + theChildListener = new ossimConnectableContainerChildListener(this); +} + +ossimConnectableContainer::~ossimConnectableContainer() +{ + // will need to destory and detach all children + // + deleteAllChildren(); + + if(theChildListener) + { + delete theChildListener; + theChildListener = NULL; + } +} + +ossimConnectableObject* ossimConnectableContainer::findFirstObjectOfType(const RTTItypeid& typeInfo, + bool recurse) +{ + ossimConnectableObject* result = NULL; + connectablObjectMapType::iterator current; + + current = theObjectMap.begin(); + while(current != theObjectMap.end()) + { + if(((*current).second)->canCastTo(typeInfo)) + { + return (*current).second; + } + ++current; + } + + if(recurse) + { + current = theObjectMap.begin(); + while(current != theObjectMap.end()) + { + ossimConnectableContainerInterface* child=PTR_CAST(ossimConnectableContainerInterface, (*current).second); + + if(child) + { + result = child->findFirstObjectOfType(typeInfo); + if(result) + { + return result; + } + } + ++current; + } + } + + return result; +} + +ossimConnectableObject* ossimConnectableContainer::findFirstObjectOfType(const ossimString& className, + bool recurse) +{ + ossimConnectableObject* result = NULL; + connectablObjectMapType::iterator current; + + current = theObjectMap.begin(); + while(current != theObjectMap.end()) + { + if( ((*current).second)->canCastTo(className) ) + { + return (*current).second; + } + ++current; + } + + if(recurse) + { + current = theObjectMap.begin(); + while(current != theObjectMap.end()) + { + ossimConnectableContainerInterface* child=PTR_CAST(ossimConnectableContainerInterface, (*current).second); + + if(child) + { + result = child->findFirstObjectOfType(className); + if(result) + { + return result; + } + } + ++current; + } + } + + return result; +} + +std::vector<ossimConnectableObject*> ossimConnectableContainer::findAllObjectsOfType(const RTTItypeid& typeInfo, + bool recurse) +{ + std::vector<ossimConnectableObject*> result; + + connectablObjectMapType::iterator current; + + current = theObjectMap.begin(); + while(current != theObjectMap.end()) + { + if(((*current).second)->canCastTo(typeInfo)) + { + result.push_back( (*current).second); + } + ++current; + } + + if(recurse) + { + current = theObjectMap.begin(); + while(current != theObjectMap.end()) + { + ossimConnectableContainerInterface* child=PTR_CAST(ossimConnectableContainerInterface, (*current).second); + + if(child) + { + vector<ossimConnectableObject*> temp; + temp = child->findAllObjectsOfType(typeInfo, recurse); + for(long index=0; index < (long)temp.size();++index) + { + result.push_back(temp[index]); + } + } + ++current; + } + } + return result; +} + +std::vector<ossimConnectableObject*> ossimConnectableContainer::findAllObjectsOfType(const ossimString& className, + bool recurse) +{ + std::vector<ossimConnectableObject*> result; + + connectablObjectMapType::iterator current; + + current = theObjectMap.begin(); + while(current != theObjectMap.end()) + { + if(((*current).second)->canCastTo(className)) + { + result.push_back( (*current).second); + } + ++current; + } + + if(recurse) + { + current = theObjectMap.begin(); + while(current != theObjectMap.end()) + { + ossimConnectableContainerInterface* child=PTR_CAST(ossimConnectableContainerInterface, (*current).second); + + if(child) + { + vector<ossimConnectableObject*> temp; + temp = child->findAllObjectsOfType(className, true); + for(long index=0; index < (long)temp.size();++index) + { + result.push_back(temp[index]); + } + } + ++current; + } + } + return result; +} + +ossimConnectableObject* ossimConnectableContainer::findObject(const ossimId& id, + bool recurse) +{ + connectablObjectMapType::iterator current; + + current = theObjectMap.begin(); + + while(current != theObjectMap.end()) + { + if((*current).second && ((*current).second->getId()==id)) + { + return (*current).second; + } + ++current; + } + + if(recurse) + { + current = theObjectMap.begin(); + + while(current != theObjectMap.end()) + { + ossimConnectableContainerInterface* child=PTR_CAST(ossimConnectableContainerInterface, (*current).second); + + if(child) + { + ossimConnectableObject* object = child->findObject(id, true); + + if(object) return object; + } + ++current; + } + } + return NULL; +} + +ossimConnectableObject* ossimConnectableContainer::findObject(const ossimConnectableObject* obj, + bool recurse) +{ + connectablObjectMapType::iterator current; + + current = theObjectMap.begin(); + + while(current != theObjectMap.end()) + { + if((*current).second && ((*current).second==obj)) + { + return (*current).second; + } + ++current; + } + + if(recurse) + { + current = theObjectMap.begin(); + + while(current != theObjectMap.end()) + { + ossimConnectableContainerInterface* child=PTR_CAST(ossimConnectableContainerInterface, (*current).second); + + if(child) + { + ossimConnectableObject* object = child->findObject(obj, true); + + if(object) return object; + } + ++current; + } + } + + return NULL; +} + +void ossimConnectableContainer::makeUniqueIds() +{ + connectablObjectMapType::iterator current; + vector<ossimConnectableObject*> objectList; + + + current = theObjectMap.begin(); + + setId(ossimIdManager::instance()->generateId()); + while(current != theObjectMap.end()) + { + objectList.push_back((*current).second); + ++current; + } + theObjectMap.clear(); + + for(long index = 0; index < (long)objectList.size(); ++index) + { + ossimConnectableContainerInterface* container = PTR_CAST(ossimConnectableContainerInterface, + objectList[index]); + if(container) + { + container->makeUniqueIds(); + theObjectMap.insert(make_pair(objectList[index]->getId().getId(), + objectList[index])); + } + else + { + objectList[index]->setId(ossimIdManager::instance()->generateId()); + theObjectMap.insert(make_pair(objectList[index]->getId().getId(), + objectList[index])); + } + } +} + +ossim_uint32 ossimConnectableContainer::getNumberOfObjects(bool recurse)const +{ + ossim_uint32 result = 0; + + connectablObjectMapType::const_iterator current; + + current = theObjectMap.begin(); + + while(current != theObjectMap.end()) + { + ++result; + + if(recurse) + { + ossimConnectableContainerInterface* child=PTR_CAST(ossimConnectableContainerInterface, (*current).second); + if(child) + { + result += child->getNumberOfObjects(true); + } + } + ++current; + } + + return result; +} + +bool ossimConnectableContainer::addChild(ossimConnectableObject* object) +{ + if(object) + { + // if it's not already a child + if(!findObject(object->getId())) + { + object->changeOwner(this); + theObjectMap.insert(make_pair(object->getId().getId(), object)); +// object->addListener((ossimConnectableObjectListener*)this); + object->addListener(theChildListener); + } + + return true; + } + + return false; +} + +bool ossimConnectableContainer::removeChild(ossimConnectableObject* object) +{ + ossimConnectableObject* result = NULL; + + if(object) + { + connectablObjectMapType::iterator childIter = theObjectMap.find(object->getId().getId()); + if(childIter != theObjectMap.end()) + { + result = (*childIter).second; + if(result->getOwner() == this) + { + result->changeOwner(NULL); + result->removeListener(theChildListener); +// result->removeListener(this); + } + theObjectMap.erase(childIter); + } + } + + return (result!=NULL); +} + +bool ossimConnectableContainer::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + static const char* MODULE = "ossimConnectableContainer::loadState(kwl, prefix)"; + + ossimString copyPrefix = prefix; + bool result = ossimConnectableObject::loadState(kwl, copyPrefix.c_str()); + + map<ossimId, vector<ossimId> > idMapping; + result = addAllObjects(idMapping, kwl, prefix); + if(!result) + { + ossimNotify(ossimNotifyLevel_FATAL) << MODULE << " error: " << "problems adding sources" << endl; + } + result = connectAllObjects(idMapping); + if(!result) + { + ossimNotify(ossimNotifyLevel_FATAL) << MODULE << " error: " << "problems connecting sources\n"; + } + + return result; +} + +bool ossimConnectableContainer::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + bool result = true; + connectablObjectMapType::const_iterator current; + + ossim_int32 childIndex = 1; + current = theObjectMap.begin(); + while(current != theObjectMap.end()) + { + ossimString newPrefix = ( (ossimString(prefix) + + ossimString("object") + + ossimString::toString(childIndex) + ".")); + if((*current).second) + { + bool test = ((*current).second)->saveState(kwl, newPrefix); + if(!test) + { + result = false; + } + } + ++childIndex; + ++current; + } + if(result) + { + result = ossimConnectableObject::saveState(kwl, prefix); + } + + return result; +} + +void ossimConnectableContainer::getChildren(vector<ossimConnectableObject*>& children, + bool immediateChildrenOnlyFlag) +{ + connectablObjectMapType::iterator current; + current = theObjectMap.begin(); + vector<ossimConnectableObject*> temp; + + while(current != theObjectMap.end()) + { + temp.push_back((*current).second); + } + ossim_uint32 i; + for(i = 0; i < temp.size();++i) + { + + if(!immediateChildrenOnlyFlag) + { + ossimConnectableContainerInterface* inter = PTR_CAST(ossimConnectableContainerInterface, + (*current).second); + if(!inter) + { + children.push_back(temp[i]); + } + } + else + { + children.push_back(temp[i]); + } + } + + if(!immediateChildrenOnlyFlag) + { + for(i = 0; i < temp.size(); ++i) + { + ossimConnectableContainerInterface* inter = PTR_CAST(ossimConnectableContainerInterface, + (*current).second); + + if(inter) + { + inter->getChildren(children, + immediateChildrenOnlyFlag); + } + } + } +} + +void ossimConnectableContainer::deleteAllChildren() +{ + connectablObjectMapType::iterator current; + ossimConnectableObject* temp; + current = theObjectMap.begin(); + removeAllListeners(); + + while(theObjectMap.size()) + { + current = theObjectMap.begin(); + temp = (*current).second; + if(temp) + { +// temp->removeListener((ossimConnectableObjectListener*) this); + temp->removeListener(theChildListener); + (*current).second = NULL; + } + theObjectMap.erase(current); + if(temp) + { + delete temp; + } + } +} + +void ossimConnectableContainer::removeAllListeners() +{ + connectablObjectMapType::iterator current; + ossimConnectableObject* temp; + current = theObjectMap.begin(); + + while(current != theObjectMap.end()) + { + temp = (*current).second; + if(temp) + { + temp->removeListener(theChildListener); +// temp->removeListener((ossimConnectableObjectListener*) this); + } + ++current; + } +} + +bool ossimConnectableContainer::addAllObjects(map<ossimId, + vector<ossimId> >& idMapping, + const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimString copyPrefix = prefix; + + vector<ossimId> inputConnectionIds; + + ossimString regExpression = ossimString("^(") + copyPrefix + "object[0-9]+.)"; + vector<ossimString> keys = + kwl.getSubstringKeyList( regExpression ); + long numberOfSources = keys.size(); + + int offset = (copyPrefix+"object").size(); + int idx = 0; + std::vector<int> theNumberList(numberOfSources); + for(idx = 0; idx < (int)theNumberList.size();++idx) + { + ossimString numberStr(keys[idx].begin() + offset, + keys[idx].end()); + theNumberList[idx] = numberStr.toInt(); + } + std::sort(theNumberList.begin(), theNumberList.end()); + for(idx=0;idx < (int)theNumberList.size();++idx) + { + ossimString newPrefix = copyPrefix; + newPrefix += ossimString("object"); + newPrefix += ossimString::toString(theNumberList[idx]); + newPrefix += ossimString("."); + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "trying to create source with prefix: " << newPrefix << "\n"; + } + ossimObject* object = ossimObjectFactoryRegistry::instance()->createObject(kwl, + newPrefix.c_str()); + if(object) + { + ossimConnectableObject* connectable = PTR_CAST(ossimConnectableObject, object); + if(connectable) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "Created source with prefix: " << newPrefix << "\n"; + } + // we did find a source so include it in the count + ossimId id = connectable->getId(); + inputConnectionIds.clear(); + + findInputConnectionIds(inputConnectionIds, + kwl, + newPrefix); + + if(inputConnectionIds.size() != 0) + { + idMapping.insert(std::make_pair(id, inputConnectionIds)); + } + addChild(connectable); + } + else + { + delete object; + object = NULL; + } + } + } + + return true; +} + +void ossimConnectableContainer::findInputConnectionIds(vector<ossimId>& result, + const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimString newPrefix = prefix; + long counter = 0; + + long numberOfMatches = 0; + + ossimString regExpression = ossimString("^") + newPrefix + "input_connection[0-9]+"; + long numberOfKeys = kwl.getNumberOfSubstringKeys( regExpression); + vector<ossimString> l = kwl.getSubstringKeyList(regExpression); + if(numberOfKeys > 0) + { + newPrefix += "input_connection"; + + while(numberOfMatches < numberOfKeys) + { + const char* lookup = kwl.find(newPrefix, + ossimString::toString(counter)); + if(lookup) + { + ++numberOfMatches; + long id = ossimString(lookup).toLong(); + if(id != ossimId::INVALID_ID) + { + result.push_back(ossimId(id)); + } + } + ++counter; + } + } +} + +bool ossimConnectableContainer::connectAllObjects(const map<ossimId, vector<ossimId> >& idMapping) +{ + if(idMapping.size()) + { + map<ossimId, vector<ossimId> >::const_iterator iter = idMapping.begin(); + + while(iter != idMapping.end()) + { + ossimConnectableObject* currentObject = findObject((*iter).first); + + if(currentObject) + { + long upperBound = (*iter).second.size(); + for(long index = 0; index < upperBound; ++index) + { + ossimConnectableObject* inputObject = findObject((*iter).second[index]); + + currentObject->connectMyInputTo(index, inputObject); + } + } + else + { + ossimNotify(ossimNotifyLevel_FATAL) << "ossimConnectableContainer::connectAllObjects, Could not find " << (*iter).first << " for source: \n"; + return false; + } + ++iter; + } + } + return true; +} + +ossimObject* ossimConnectableContainer::getObject() +{ + return this; +} + +const ossimObject* ossimConnectableContainer::getObject()const +{ + return this; +} + +ossimConnectableObject* ossimConnectableContainer::getConnectableObject( + ossim_uint32 index) +{ + ossimConnectableObject* result = NULL; + + if (index > theObjectMap.size()) + { + return result; + } + + connectablObjectMapType::iterator current; + current = theObjectMap.begin(); + ossim_uint32 i = 0; + while(current != theObjectMap.end()) + { + if (i == index) + { + return (*current).second; + } + ++current; + ++i; + } + + return result; +} + +bool ossimConnectableContainer::canConnectMyInputTo(ossim_int32, + const ossimConnectableObject*) const +{ + return false; +} + +bool ossimConnectableContainer::canConnectMyOutputTo(ossim_int32, + const ossimConnectableObject*) const +{ + return false; +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimConnectableContainer.h b/Utilities/OSSIM/ossim_core/base/common/ossimConnectableContainer.h new file mode 100644 index 0000000000..6e95777114 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimConnectableContainer.h @@ -0,0 +1,184 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: A brief description of the contents of the file. +// +//************************************************************************* +// $Id: ossimConnectableContainer.h,v 1.28 2005/11/22 19:40:35 dburken Exp $ + +#ifndef ossimConnectableContainer_HEADER +#define ossimConnectableContainer_HEADER +#include <map> + +#include "ossimConnectableObject.h" +#include "base/common/events/ossimConnectableObjectListener.h" +#include "ossimConnectableContainerInterface.h" + +class OSSIMDLLEXPORT ossimConnectableContainerChildListener; + +class OSSIMDLLEXPORT ossimConnectableContainer : public ossimConnectableObject, + public ossimConnectableContainerInterface, + public ossimConnectableObjectListener +{ +public: + typedef std::map<long, ossimConnectableObject*> connectablObjectMapType; + + ossimConnectableContainer(ossimConnectableObject* owner=NULL); + virtual ~ossimConnectableContainer(); + + virtual ossimObject* getObject(); + + virtual const ossimObject* getObject()const; + + /** + * @param index Index of object to get. + * + * @see getNumberOfObjects(false) to get the number of objects inside + * the container. + * + * @return Container's object at that index or NULL if out of range. + * + * @note This does not recurse into other containers. + */ + virtual ossimConnectableObject* getConnectableObject(ossim_uint32 index); + + + /*! + * Will find all objects of the past in type. Use the RTTI type info. + * An optional recurse flag will say if there is another container then + * recurse it to find the type you are looking for else it just looks + * within its immediate children. + * + * Example: passing STATIC_TYPE_INFO(ossimImageRenderer) as an argument will + * look for all ossimImageRenderer's and return the list. + */ + virtual std::vector<ossimConnectableObject*> findAllObjectsOfType(const RTTItypeid& typeInfo, + bool recurse=true); + virtual std::vector<ossimConnectableObject*> findAllObjectsOfType(const ossimString& className, + bool recurse=true); + + /*! + * Will find the firt object of the past in type. Use the RTTI type info. + * An optional recurse flag will say if there is another container then + * recurse it to find the type you are looking for else it just looks + * within its immediate children. + * + * Example: passing STATIC_TYPE_INFO(ossimImageRenderer) as an argument will + * look for the first ossimImageRenderer and return that object. + */ + virtual ossimConnectableObject* findFirstObjectOfType(const RTTItypeid& typeInfo, + bool recurse=true); + + virtual ossimConnectableObject* findFirstObjectOfType(const ossimString& className, + bool recurse=true); + + /*! + * will search for the object given an id. If recurse is true it will + * recurse + * to other containers. + */ + ossimConnectableObject* findObject(const ossimId& id, + bool recurse=true); + + ossimConnectableObject* findObject(const ossimConnectableObject* obj, + bool recurse=true); + + /*! + * Will cycle through all sources setting their ids. the idLast wlil be + * updated + * so we can recurse into other containers. + */ + void makeUniqueIds(); + + /*! + * Returns the number of objects within this container and all child + * containers. + */ + ossim_uint32 getNumberOfObjects(bool recurse=true)const; + + /*! + * Will add an object to the container and then set the added objects owner + * to this. + */ + virtual bool addChild(ossimConnectableObject* attachableObject); + + + virtual bool removeChild(ossimConnectableObject* object); + + virtual bool canConnectMyInputTo(ossim_int32 index, + const ossimConnectableObject* obj) const; + + virtual bool canConnectMyOutputTo(ossim_int32 index, + const ossimConnectableObject* obj) const; + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=NULL); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=NULL)const; + + //____________________PLACE ALL EVENT HANDLING STUFF HERE_____________ +// virtual void objectDestructingEvent(ossimObjectDestructingEvent& event); +// virtual void propertyEvent(ossimPropertyEvent& event); + +// virtual void disconnectInputEvent(ossimConnectionEvent& event); +// virtual void connectInputEvent(ossimConnectionEvent& event); + +// virtual void disconnectOutputEvent(ossimConnectionEvent& event); +// virtual void connectOutputEvent(ossimConnectionEvent& event); + + + virtual void getChildren(vector<ossimConnectableObject*>& children, + bool immediateChildrenOnlyFlag); + void deleteAllChildren(); + +// void propagateEventToOutputs(ossimEvent& event, +// ossimConnectableObject* start); +// void propagateEventToInputs(ossimEvent& event, +// ossimConnectableObject* start); + +protected: + ossimConnectableContainer(const ossimConnectableContainer& rhs); + + void removeAllListeners(); + bool addAllObjects(map<ossimId, vector<ossimId> >& idMapping, + const ossimKeywordlist& kwl, + const char* prefix); + + bool connectAllObjects(const map<ossimId, vector<ossimId> >& idMapping); + + void findInputConnectionIds(vector<ossimId>& result, + const ossimKeywordlist& kwl, + const char* prefix); + + /*! + * Every object added must have a unique id. We will sort them in a easy to + * query form. Since the container can have hundreds of objects we will use a + * more efficient map that allows us to do binary searches of the objects. + * + * map<key, value> The key will be the objectsUnique id and the value + * is a pointer to the attachable object. + */ + connectablObjectMapType theObjectMap; + + ossimConnectableContainerChildListener* theChildListener; +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimConnectableContainerInterface.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimConnectableContainerInterface.cpp new file mode 100644 index 0000000000..0e4997a411 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimConnectableContainerInterface.cpp @@ -0,0 +1,27 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: A brief description of the contents of the file. +// +// +//************************************************************************* +// $Id: ossimConnectableContainerInterface.cpp,v 1.1 2002/01/15 19:45:47 gpotts Exp $ +#include "ossimConnectableContainerInterface.h" + +RTTI_DEF(ossimConnectableContainerInterface, "ossimConnectableContainerInterface"); diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimConnectableContainerInterface.h b/Utilities/OSSIM/ossim_core/base/common/ossimConnectableContainerInterface.h new file mode 100644 index 0000000000..2ffae8df60 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimConnectableContainerInterface.h @@ -0,0 +1,131 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: A brief description of the contents of the file. +// +// +//************************************************************************* +// $Id: ossimConnectableContainerInterface.h,v 1.12 2005/11/22 19:39:11 dburken Exp $ +#ifndef ossimConnectableContainerInterface_HEADER +#define ossimConnectableContainerInterface_HEADER +#include "base/common/ossimConstants.h" +#include "base/common/ossimRtti.h" +#include "base/common/ossimId.h" +#include <vector> + +class OSSIMDLLEXPORT ossimObject; +class OSSIMDLLEXPORT ossimConnectableObject; +class OSSIMDLLEXPORT ossimString; + +class OSSIMDLLEXPORT ossimConnectableContainerInterface +{ +public: + ossimConnectableContainerInterface(ossimObject* obj):theBaseObject(obj){} + virtual ~ossimConnectableContainerInterface(){theBaseObject=NULL;} + + /*! + * Will find all objects of the past in type. Use the RTTI type info. An optional + * recurse flag will say if there is another container then recurse it to + * find the type you are looking for else it just looks within its immediate + * children + * + * Example: passing STATIC_TYPE_INFO(ossimImageRenderer) as an argument will + * look for all ossimImageRenderer's and return the list. + */ + virtual std::vector<ossimConnectableObject*> findAllObjectsOfType(const RTTItypeid& typeInfo, + bool recurse=true)=0; + virtual std::vector<ossimConnectableObject*> findAllObjectsOfType(const ossimString& className, + bool recurse=true)=0; + + /*! + * Will find the firt object of the past in type. Use the RTTI type info.An optional + * recurse flag will say if there is another container then recurse it to + * find the type you are looking for else it just looks within its immediate + * children + * + * Example: passing STATIC_TYPE_INFO(ossimImageRenderer) as an argument will + * look for the first ossimImageRenderer and return that object. + */ + virtual ossimConnectableObject* findFirstObjectOfType(const RTTItypeid& typeInfo, + bool recurse=true)=0; + + virtual ossimConnectableObject* findFirstObjectOfType(const ossimString& className, + bool recurse=true)=0; + + /*! + * will search for the object given an id. If recurse is true it will recurse + * to other containers. + */ + virtual ossimConnectableObject* findObject(const ossimId& id, + bool recurse=true)=0; + + virtual ossimConnectableObject* findObject(const ossimConnectableObject* obj, + bool recurse=true)=0; + /*! + * Will cycle through all sources setting their ids. the idLast wlil be updated + * so we can recurse into other containers. + */ + virtual void makeUniqueIds()=0; + + /*! + * Returns the number of objects within this container and all child containers. + */ + virtual ossim_uint32 getNumberOfObjects(bool recurse=true)const=0; + + + /*! + * Will add an object to the container and then set the added objects owner + * to this. + */ + virtual bool addChild(ossimConnectableObject* attachableObject)=0; + + /*! + * Will remove the child from the container. Changes the owner of the + * child to be NULL; + */ + virtual bool removeChild(ossimConnectableObject* object)=0; + + /*! + * Gives access to the this point of the base object that everyone derives + * from. + */ + ossimObject* getObject(){return theBaseObject;} + const ossimObject* getObject()const{return theBaseObject;} + + /** + * @param index Index of object to get. + * + * @see getNumberOfObjects(false) to get the number of objects inside + * the container. + * + * @return Container's object at that index or NULL if out of range. + * + * @note This does not recurse into other containers. + */ + virtual ossimConnectableObject* getConnectableObject(ossim_uint32 index)=0; + + void deleteAllChildren(); + virtual void getChildren(vector<ossimConnectableObject*>& children, + bool immediateChildrenOnlyFlag)=0; +protected: + ossimObject* theBaseObject; +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimConnectableObject.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimConnectableObject.cpp new file mode 100644 index 0000000000..faa4a665a6 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimConnectableObject.cpp @@ -0,0 +1,1903 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// Description: A brief description of the contents of the file. +// +//************************************************************************* +// $Id: ossimConnectableObject.cpp,v 1.92 2006/01/03 20:31:16 dburken Exp $ +#include <base/common/ossimConnectableObject.h> +#include <base/common/ossimIdManager.h> +#include <base/common/ossimKeywordNames.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/common/events/ossimObjectEvents.h> +#include <base/common/events/ossimObjectEvents.h> +#include <base/common/ossimConnectableContainerInterface.h> +#include <base/property/ossimTextProperty.h> +#include <base/context/ossimNotifyContext.h> +#include <algorithm> + +RTTI_DEF3(ossimConnectableObject, + "ossimConnectableObject", + ossimObject, + ossimListenerManager, + ossimPropertyInterface); + +const char* CONNECTABLE_INPUT_LIST_FIXED_KW = "input_list_fixed"; +const char* CONNECTABLE_OUTPUT_LIST_FIXED_KW = "output_list_fixed"; + +ossimConnectableObject::ossimConnectableObject(ossimObject* owner) + :ossimObject(), + ossimListenerManager(), + theInputListIsFixedFlag(false), + theOutputListIsFixedFlag(false) +{ + theId = ossimIdManager::instance()->generateId(); + theOwner = owner; +} + +ossimConnectableObject::ossimConnectableObject(ossimObject* owner, + long inputListSize, + long outputListSize, + bool inputListIsFixedFlag, + bool outputListIsFixedFlag) + :ossimObject(), + ossimListenerManager(), + theInputListIsFixedFlag(inputListIsFixedFlag), + theOutputListIsFixedFlag(outputListIsFixedFlag) +{ + theId = ossimIdManager::instance()->generateId(); + theOwner = owner; + + setNumberOfInputs(inputListSize); + setNumberOfOutputs(outputListSize); +} + +ossimConnectableObject::~ossimConnectableObject() +{ + + // tell the immediate listeners that we are destructing. + ossimObjectDestructingEvent event(this); + +// if(theOwner) +// { +// ossimListenerManager* manager = PTR_CAST(ossimListenerManager, theOwner); + +// if(manager) +// { +// // notify the owner that you are destructing +// // +// manager->fireEvent(event); +// } +// } + + // notify all other listeners that you are destructing + // + fireEvent(event); + + ossimIdManager::instance()->releaseId(theId); + + // next we need to make sure that we are detached. + // + disconnect(this); + +} + +void ossimConnectableObject::changeOwner(ossimObject* owner) +{ + theOwner = owner; +} + +void ossimConnectableObject::setDescription(const ossimString& description) +{ + theDescription = description; +} + +ossimString ossimConnectableObject::getDescription()const +{ + return theDescription; +} + +bool ossimConnectableObject::isConnected(ossimConnectableObjectDirectionType direction)const +{ + if(direction & CONNECTABLE_DIRECTION_INPUT) + { + if(getNumberOfInputs()) + { + std::vector<ossimConnectableObject*>::const_iterator current = theInputObjectList.begin(); + + while(current != theInputObjectList.end()) + { + if(! (*current)) + { + return false; + } + + ++current; + } + } + else if(!theInputListIsFixedFlag) + { + return false; + } + } + + if(direction & CONNECTABLE_DIRECTION_OUTPUT) + { + std::vector<ossimConnectableObject*>::const_iterator current = theOutputObjectList.begin(); + current = theOutputObjectList.begin(); + + while(current != theOutputObjectList.end()) + { + if(! (*current)) + { + return false; + } + + ++current; + } + } + + return true; +} + +ossimConnectableObject* ossimConnectableObject::findConnectableObject(const ossimId& id) +{ + std::vector<ossimConnectableObject*>::iterator current; + + current = theInputObjectList.begin(); + while(current != theInputObjectList.end()) + { + ossimConnectableObject* temp = *current; + + if(temp->getId() == id) + { + return temp; + } + + ++current; + } + + // go through the outputs + current = theOutputObjectList.begin(); + while(current != theOutputObjectList.end()) + { + ossimConnectableObject* temp = *current; + + if(temp->getId() == id) + { + return temp; + } + + ++current; + } + + return NULL; +} + +ossimConnectableObject* ossimConnectableObject::findObjectOfType(RTTItypeid typeId, + ossimConnectableObjectDirectionType directionType, + bool recurse) +{ + vector<ossimConnectableObject*> *connectableList = &theInputObjectList; + + if(directionType == CONNECTABLE_DIRECTION_NONE) + { + return NULL; + } + + if(directionType == CONNECTABLE_DIRECTION_OUTPUT) + { + connectableList = &theOutputObjectList; + + } + + + // see if it is in the immediate list + for(ossim_uint32 index = 0; index < connectableList->size(); ++index) + { + if((*connectableList)[index]) + { + if((*connectableList)[index]->canCastTo(typeId))//typeId.can_cast(TYPE_INFO(theInputObjectList[index]))) + { + return (*connectableList)[index]; + } + } + } + + if(recurse) + { + ossimConnectableContainerInterface* inter = PTR_CAST(ossimConnectableContainerInterface, + this); + if(inter) + { + ossimConnectableObject* tempObj = inter->findFirstObjectOfType(typeId); + if(tempObj) + { + return tempObj; + } + } + + for(ossim_uint32 index = 0; index < connectableList->size(); ++index) + { + inter = PTR_CAST(ossimConnectableContainerInterface, + (*connectableList)[index]); + if(inter) + { + ossimConnectableObject* tempObj = inter->findFirstObjectOfType(typeId); + if(tempObj) + { + return tempObj; + } + } + if((*connectableList)[index]) + { + ossimConnectableObject* result = (*connectableList)[index]->findObjectOfType(typeId, + directionType, + recurse); + if(result) + { + return result; + } + } + } + } + + ossimConnectableObject* result = NULL; + for(ossim_uint32 index = 0; (index < connectableList->size())&&!result; ++index) + { + if((*connectableList)[index]) + { + result = ((*connectableList)[index])->findObjectOfType(typeId, + directionType, + recurse); + } + } + + return result; +} + +ossimConnectableObject* ossimConnectableObject::findObjectOfType( + const ossimString& className, + ossimConnectableObjectDirectionType directionType, + bool recurse) +{ + vector<ossimConnectableObject*> *connectableList = &theInputObjectList; + + if(directionType == CONNECTABLE_DIRECTION_NONE) + { + return NULL; + } + + if(directionType == CONNECTABLE_DIRECTION_OUTPUT) + { + connectableList = &theOutputObjectList; + + } + + // see if it is in the immediate list + for(ossim_uint32 index = 0; index < connectableList->size(); ++index) + { + if((*connectableList)[index]) + { + if((*connectableList)[index]->canCastTo(className))//typeId.can_cast(TYPE_INFO(theInputObjectList[index]))) + { + return (*connectableList)[index]; + } + } + } + + if(recurse) + { + ossimConnectableContainerInterface* inter = PTR_CAST(ossimConnectableContainerInterface, + this); + if(inter) + { + ossimConnectableObject* tempObj = inter->findFirstObjectOfType(className); + if(tempObj) + { + return tempObj; + } + } + for(ossim_uint32 index = 0; index < connectableList->size(); ++index) + { + inter = PTR_CAST(ossimConnectableContainerInterface, + (*connectableList)[index]); + if(inter) + { + ossimConnectableObject* tempObj = inter->findFirstObjectOfType(className); + if(tempObj) + { + return tempObj; + } + } + if((*connectableList)[index]) + { + ossimConnectableObject* result = (*connectableList)[index]->findObjectOfType(className, + directionType, + recurse); + if(result) + { + return result; + } + } + } + } + ossimConnectableObject* result = NULL; + for(ossim_uint32 index = 0; (index < connectableList->size())&&!result; ++index) + { + if((*connectableList)[index]) + { + result = ((*connectableList)[index])->findObjectOfType(className, + directionType, + recurse); + // Return ... + } + } + + return result; +} + +ossimConnectableObject* ossimConnectableObject::findInputObjectOfType( + const ossimString& className) +{ + // See if we are of class type. + if (canCastTo(className)) + { + return this; + } + + // If we are a container, look inside for type. + ossimConnectableContainerInterface* container = + PTR_CAST(ossimConnectableContainerInterface, this); + if (container) + { + const ossim_uint32 NUMBER_OF_OBJECTS = + container->getNumberOfObjects(false); + if (NUMBER_OF_OBJECTS) + { + for (ossim_uint32 idx = NUMBER_OF_OBJECTS; idx > 0; --idx) + { + ossimConnectableObject* result = + container->getConnectableObject(idx-1); + if (result) + { + if (result->canCastTo(className)) + { + return result; + } + } + } + } + } + + if ( getInputListIsFixedFlag() && (theInputObjectList.size() == 1) ) + { + // Look at the input connection. + ossimConnectableObject* input = theInputObjectList[0]; + + if(input) + { + // See if the input can cast to type. + if(input->canCastTo(className)) + { + return input; + } + + // Look inside the input connection. + ossimConnectableObject* result = + input->findInputObjectOfType(className); + if(result) + { + return result; + } + } + + } // End of "Must have fixed input of one." + + return (ossimConnectableObject*)NULL; +} + +ossim_int32 ossimConnectableObject::findInputIndex(const ossimConnectableObject* object) +{ + ossim_int32 i = 0; + for(i = 0; i < (ossim_int32)theInputObjectList.size(); ++i) + { + if(theInputObjectList[i] == object) + { + return i; + } + } + + return -1; +} + +ossim_int32 ossimConnectableObject::findInputIndex(const ossimId& id) +{ + ossim_int32 i = 0; + for(i = 0; i < (ossim_int32)theInputObjectList.size(); ++i) + { + if(theInputObjectList[i] && + (theInputObjectList[i]->getId() == id)) + { + return i; + } + } + + return -1; +} + +ossim_int32 ossimConnectableObject::findOutputIndex(const ossimConnectableObject* object) +{ + ossim_int32 i = 0; + for(i = 0; i < (ossim_int32)theOutputObjectList.size(); ++i) + { + if(theOutputObjectList[i] == object) + { + return i; + } + } + + return -1; +} + +ossim_int32 ossimConnectableObject::findOutputIndex(const ossimId& id) +{ + ossim_int32 i = 0; + for(i = 0; i < (ossim_int32)theOutputObjectList.size(); ++i) + { + if(theOutputObjectList[i] && + (theOutputObjectList[i]->getId() == id)) + { + return i; + } + } + + return -1; +} + +ossim_int32 ossimConnectableObject::getMyInputIndexToConnectTo(ossimConnectableObject* object)const +{ + std::vector<ossimConnectableObject*>::const_iterator current; + + ossim_int32 index = 0; + current = theInputObjectList.begin(); + while(current != theInputObjectList.end()) + { + if(!(*current)) + { + if(canConnectMyInputTo(index, object)) + { + return index; + } + } + ++current; + ++index; + } + if(!theInputListIsFixedFlag) + { + if(canConnectMyInputTo((ossim_int32)theInputObjectList.size(), + object)) + { + return (ossim_int32)theInputObjectList.size(); + } + } + return -1; +} + +ossim_int32 ossimConnectableObject::getMyOutputIndexToConnectTo(ossimConnectableObject* object)const +{ + std::vector<ossimConnectableObject*>::const_iterator current; + + ossim_int32 index = 0; + current = theOutputObjectList.begin(); + while(current != theOutputObjectList.end()) + { + if(!(*current)) + { + if(canConnectMyOutputTo(index, object)) + { + return index; + } + } + ++current; + ++index; + } + if(!theOutputListIsFixedFlag) + { + if(canConnectMyOutputTo((ossim_int32)theOutputObjectList.size(), + object)) + { + return (ossim_int32)theOutputObjectList.size(); + } + } + // default to return the size. This will force an append. + // + return -1; +} + +void ossimConnectableObject::disconnect(ossimConnectableObject* object) +{ + if( (object==this) || (object==(ossimConnectableObject*)NULL)) + { + disconnectAllInputs(); + disconnectAllOutputs(); + } + else + { + ossim_int32 index = findInputIndex(object); + if(index > -1) + { + disconnectMyInput(index); + } + else + { + index = findOutputIndex(object); + disconnectMyOutput(index, object); + } + } +} + +void ossimConnectableObject::disconnect(const ossimId& id) +{ + if(id == theId) + { + disconnect(this); + } + else + { + ossimConnectableObject* object = findConnectableObject(id); + disconnect(object); + } +} + +ossimConnectableObject* ossimConnectableObject::disconnectMyInput(ossim_int32 inputIndex, + bool disconnectOutputFlag, + bool createEventFlag) +{ + if(theInputObjectList.size() == 0) + { + return (ossimConnectableObject*)NULL; + } + + std::vector<ossimConnectableObject*>::iterator current; + ossimConnectableObject* result = NULL; + + if( (inputIndex > -1)&& + (inputIndex < (ossim_int32)theInputObjectList.size())) + { + current = (theInputObjectList.begin()+inputIndex); + result = *current; + + ossim_int32 index = inputIndex; + if(!theInputListIsFixedFlag) + { + current = theInputObjectList.erase(current); + index = -1; + } + else + { + *current = NULL; + } + if(createEventFlag&&result) + { + ossimConnectionEvent event(this, // owner of message + OSSIM_EVENT_CONNECTION_DISCONNECT_ID, + NULL, // new object + result,// old object + ossimConnectionEvent::OSSIM_INPUT_DIRECTION); + + // send event to all listeners. + // + fireEvent(event); + } + + if(disconnectOutputFlag&&result) + { + result->disconnectMyOutput(this, false, createEventFlag); + } + } + return result; +} + + +void ossimConnectableObject::disconnectMyInput(ossimConnectableObject* input, + bool disconnectOutputFlag, + bool createEventFlag) +{ + disconnectMyInput(findInputIndex(input), + disconnectOutputFlag, + createEventFlag); +} + +void ossimConnectableObject::disconnectMyInputs(std::vector<ossimConnectableObject*>& inputList, + bool disconnectOutputFlag, + bool createEventFlag) +{ + if(theInputObjectList.size() == 0) return; + vector<ossimConnectableObject*> oldInputs; + vector<ossimConnectableObject*> newInputs; + ossim_int32 i = 0; + + for(i = 0; i < (ossim_int32)inputList.size(); ++i) + { + if(findInputIndex(inputList[i]) >= 0) + { + disconnectMyInput(inputList[i], disconnectOutputFlag, false); + oldInputs.push_back(inputList[i]); + } + } + if(createEventFlag && oldInputs.size()) + { + ossimConnectionEvent event(this, + OSSIM_EVENT_CONNECTION_DISCONNECT_ID, + newInputs, + oldInputs, + ossimConnectionEvent::OSSIM_INPUT_DIRECTION); + fireEvent(event); + } +} + +ossimConnectableObject* ossimConnectableObject::disconnectMyOutput(ossim_int32 outputIndex, + bool disconnectInputFlag, + bool createEvent) +{ + if(theOutputObjectList.size() == 0) + { + return (ossimConnectableObject*)NULL; + } + + std::vector<ossimConnectableObject*>::iterator current; + ossimConnectableObject* result = NULL; + if( (outputIndex > -1)&& + (outputIndex < (ossim_int32)theOutputObjectList.size())) + { + current = (theOutputObjectList.begin()+outputIndex); + result = *current; + ossim_int32 index = outputIndex; + if(!theOutputListIsFixedFlag) + { + current = theOutputObjectList.erase(current); + index = -1; + } + else + { + *current = NULL; + } + if(createEvent) + { + ossimConnectionEvent event(this, // owner of message + OSSIM_EVENT_CONNECTION_DISCONNECT_ID, + NULL, // new object + result,// old object + ossimConnectionEvent::OSSIM_OUTPUT_DIRECTION); + + // send event to all listeners. + // + fireEvent(event); + } + + if(disconnectInputFlag&&result) + { + result->disconnectMyInput(this, false, createEvent); + } + } + return result; +} + +void ossimConnectableObject::disconnectMyOutput(ossimConnectableObject* output, + bool disconnectInputFlag, + bool createEventFlag) +{ + disconnectMyOutput(findOutputIndex(output), disconnectInputFlag, createEventFlag); +} + +void ossimConnectableObject::disconnectMyOutputs(std::vector<ossimConnectableObject*>& outputList, + bool disconnectInputFlag, + bool createEventFlag) +{ + if(theOutputObjectList.size() == 0) return; + + if(theOutputObjectList.size() == 1) + { + disconnectMyOutput((ossim_int32)0); + return; + } + vector<ossimConnectableObject*> oldOutputs; + vector<ossimConnectableObject*> newOutputs; + ossim_int32 i = 0; + for(i = 0; i < (ossim_int32)outputList.size(); ++i) + { + if(findOutputIndex(outputList[i]) >= 0) + { + disconnectMyOutput(outputList[i], disconnectInputFlag, false); + oldOutputs.push_back(outputList[i]); + } + } + if(createEventFlag && oldOutputs.size()) + { + ossimConnectionEvent event(this, + OSSIM_EVENT_CONNECTION_DISCONNECT_ID, + newOutputs, + oldOutputs, + ossimConnectionEvent::OSSIM_OUTPUT_DIRECTION); + fireEvent(event); + } +} + +void ossimConnectableObject::disconnectAllInputs() +{ + if(theInputObjectList.size() == 0) return; + if(theInputObjectList.size() == 1) + { +// ossimConnectableObject* obj = disconnectMyInput((ossim_int32)0, false); + disconnectMyInput((ossim_int32)0); +// if(obj) +// { +// obj->disconnectMyOutput(this, false); +// } + return; + } + std::vector<ossimConnectableObject*>::iterator current; + std::vector<ossimConnectableObject*> oldInputs = theInputObjectList; + std::vector<ossimConnectableObject*> newInputs; + + + current = theInputObjectList.begin(); + while(current != theInputObjectList.end()) + { + if(!theInputListIsFixedFlag) + { + current = theInputObjectList.erase(current); + } + else + { + *current = NULL; + ++current; + } + } + ossimConnectionEvent event(this, + OSSIM_EVENT_CONNECTION_DISCONNECT_ID, + newInputs, + oldInputs, + ossimConnectionEvent::OSSIM_INPUT_DIRECTION); + fireEvent(event); + + for(ossim_uint32 index = 0; index < oldInputs.size(); ++index) + { + if(oldInputs[index]) + { + oldInputs[index]->disconnectMyOutput(this, false); + } + } +} + +void ossimConnectableObject::disconnectAllOutputs() +{ + if(theOutputObjectList.size() == 0) return; + if(theOutputObjectList.size() == 1) + { +// ossimConnectableObject* obj = disconnectMyOutput((ossim_int32)0, false); + disconnectMyOutput((ossim_int32)0); +// if(obj) +// { +// obj->disconnectMyInput(this, +// false); +// } + return; + } + std::vector<ossimConnectableObject*>::iterator current; + + std::vector<ossimConnectableObject*> oldOutputs = theOutputObjectList; + std::vector<ossimConnectableObject*> newOutputs; + + current = theOutputObjectList.begin(); + while(current != theOutputObjectList.end()) + { + if(!theOutputListIsFixedFlag) + { + current = theOutputObjectList.erase(current); + } + else + { + *current = NULL; + ++current; + } + } + ossimConnectionEvent event(this, + OSSIM_EVENT_CONNECTION_DISCONNECT_ID, + newOutputs, + oldOutputs, + ossimConnectionEvent::OSSIM_OUTPUT_DIRECTION); + fireEvent(event); + + for(ossim_uint32 index = 0; index < oldOutputs.size(); ++index) + { + if(oldOutputs[index]) + { + oldOutputs[index]->disconnectMyInput(this, false); + } + } +} + +ossim_int32 ossimConnectableObject::connectMyInputTo(ossimConnectableObject* object, + bool makeOutputConnection, + bool createEventFlag) +{ + if(!object) return false; + + ossim_int32 index = findInputIndex(object); + if(index >= 0) return index; + + index = getMyInputIndexToConnectTo(object); + + if(index>-1) + { + if(index >= (ossim_int32)theInputObjectList.size()) + { + if(theInputListIsFixedFlag) return -1; + + index = (ossim_int32)theInputObjectList.size(); + theInputObjectList.push_back(object); + } + else + { + if(!theInputObjectList[index]) + { + theInputObjectList[index] = object; + } + else + { + ossimNotify(ossimNotifyLevel_WARN) << "Must issue a detach first!! trying to attach object " << object->getClassName() + << "\n to input index " << index << " in " << getClassName() << "\n"; + + return -1; + } + } + if(createEventFlag) + { + ossimConnectionEvent event(this, // owner of message + OSSIM_EVENT_CONNECTION_CONNECT_ID, + theInputObjectList[index], // new object + NULL,// old object + ossimConnectionEvent::OSSIM_INPUT_DIRECTION); + // send event to any listener. + // + fireEvent(event); + } + + if(makeOutputConnection&&object) + { + // make sure we tell the input not to connect + // back to us or infinite loop + // + object->connectMyOutputTo(this, false, createEventFlag); + } + } + else + { + return index; + } + + return index; +} + +ossim_int32 ossimConnectableObject::connectMyInputTo(ossim_int32 inputIndex, + ossimConnectableObject* inputObject, + bool makeOutputConnection, + bool createEventFlag) +{ + if(!inputObject) + { + if(inputIndex < (ossim_int32)theInputObjectList.size()) + { + ossimConnectableObject* oldObject = theInputObjectList[inputIndex]; + if(theInputListIsFixedFlag) + { + theInputObjectList[inputIndex] = (ossimConnectableObject*)NULL; + } + else + { + theInputObjectList.erase(theInputObjectList.begin() + inputIndex); + } + if(createEventFlag) + { + ossimConnectionEvent event(this, // owner of message + OSSIM_EVENT_CONNECTION_CONNECT_ID, + NULL, // new object + oldObject,// old object + ossimConnectionEvent::OSSIM_INPUT_DIRECTION); + // send event to any listener. + // + fireEvent(event); + } + return -1; + } + return -1; + } + + ossim_int32 index = findInputIndex(inputObject); + + if((index >= 0)&&!inputObject) return index; + if(!inputObject) return -1; + + if(canConnectMyInputTo(inputIndex, inputObject)) + { + if(inputIndex>-1) + { + ossimConnectableObject* oldObject=NULL; + if(inputIndex >= (ossim_int32)theInputObjectList.size()) + { + if(theInputListIsFixedFlag) return -1; + + inputIndex = (ossim_int32)theInputObjectList.size(); + theInputObjectList.push_back(inputObject); + } + else + { + oldObject = theInputObjectList[inputIndex]; + theInputObjectList[inputIndex] = inputObject; + if(oldObject) + { + oldObject->disconnectMyOutput(this, false); + } + } + + if(createEventFlag) + { + ossimConnectionEvent event(this, // owner of message + OSSIM_EVENT_CONNECTION_CONNECT_ID, + theInputObjectList[inputIndex], // new object + oldObject,// old object + ossimConnectionEvent::OSSIM_INPUT_DIRECTION); + // send event to any listener. + // + fireEvent(event); + } + + if(makeOutputConnection&&inputObject) + { + // make sure we tell the input not to connect + // back to us or infinite loop + // + inputObject->connectMyOutputTo(this, false, createEventFlag); + } + } + else + { + return inputIndex; + } + + return inputIndex; + } + + return -1; +} + +bool ossimConnectableObject::connectMyInputTo(vector<ossimConnectableObject*>& inputList, + bool makeOutputConnection, + bool createEventFlag) +{ + bool result = true; + vector<ossimConnectableObject*> oldInputs; + vector<ossimConnectableObject*> newInputs; + + if(inputList.size() == 1) + { + if(inputList[0]) + { + return (connectMyInputTo(inputList[0], makeOutputConnection, createEventFlag) >= 0); + } + else + { + if(theInputListIsFixedFlag) + { + theInputObjectList[0] = NULL; + } + else + { + theInputObjectList.clear(); + } + if(createEventFlag) + { + ossimConnectionEvent event(this, + OSSIM_EVENT_CONNECTION_CONNECT_ID, + (ossimConnectableObject*)NULL, + theInputObjectList[0], + ossimConnectionEvent::OSSIM_INPUT_DIRECTION); + fireEvent(event); + } + + return true; + } + } + ossim_int32 i = 0; + for(i = 0; i < (ossim_int32)inputList.size(); ++i) + { + if(inputList[i]) + { + if(connectMyInputTo(inputList[i], makeOutputConnection, false)<0) + { + result = false; + } + else + { + newInputs.push_back(inputList[i]); + } + } + else + { + newInputs.push_back((ossimConnectableObject*)NULL); + } + } + if(createEventFlag) + { + ossimConnectionEvent event(this, + OSSIM_EVENT_CONNECTION_CONNECT_ID, + newInputs, + oldInputs, + ossimConnectionEvent::OSSIM_INPUT_DIRECTION); + fireEvent(event); + } + return result; +} + +ossim_int32 ossimConnectableObject::connectMyOutputTo(ossimConnectableObject* output, + bool makeInputConnection, + bool createEventFlag) +{ + ossim_int32 index = findOutputIndex(output); + if(index >= 0) return index; + + index = getMyOutputIndexToConnectTo(output); + + if(index > -1) + { + if((index >= (ossim_int32)theOutputObjectList.size())&& + !theOutputListIsFixedFlag) + { + index = (ossim_int32)theOutputObjectList.size(); + theOutputObjectList.push_back(output); + } + else + { + if(!theOutputObjectList[index]) + { + theOutputObjectList[index] = output; + } + else + { + ossimNotify(ossimNotifyLevel_WARN) << "Must issue a disconnect first!! trying to connect object " << output->getClassName() + << "\n to output index " << index << " in " << getClassName() << "\n"; + + return -1; + } + } + if(createEventFlag) + { + ossimConnectionEvent event(this, // owner of message + OSSIM_EVENT_CONNECTION_CONNECT_ID, + theOutputObjectList[index], // new object + NULL,// old object + ossimConnectionEvent::OSSIM_OUTPUT_DIRECTION); + // send event to any listener. + // + fireEvent(event); + } + if(makeInputConnection&&output) + { + // tell the output object not to connect back + // to us since this is already done. + // + output->connectMyInputTo(this, false, createEventFlag); + } + } + else + { + return index; + } + + return index; +} + +bool ossimConnectableObject::connectMyOutputTo(vector<ossimConnectableObject*>& outputList, + bool makeInputConnection, + bool createEventFlag) +{ + bool result = true; + vector<ossimConnectableObject*> oldOutputs; + vector<ossimConnectableObject*> newOutputs; + + if(outputList.size() == 0) + { + disconnectAllOutputs(); + return true; + } + if((outputList.size() == 1)&&outputList[0]) + { + if(outputList[0]) + { + return (connectMyOutputTo(outputList[0], makeInputConnection, createEventFlag) >= 0); + } + else + { + disconnectAllOutputs(); + } + } + + ossim_int32 i = 0; + for(i = 0; i < (ossim_int32)outputList.size(); ++i) + { + if((connectMyOutputTo(outputList[i], makeInputConnection, false)<0)&&outputList[i]) + { + newOutputs.push_back(outputList[i]); + result = false; + } + } + if(createEventFlag&&newOutputs.size()) + { + ossimConnectionEvent event(this, + OSSIM_EVENT_CONNECTION_CONNECT_ID, + newOutputs, + oldOutputs, + ossimConnectionEvent::OSSIM_OUTPUT_DIRECTION); + fireEvent(event); + } + + return result; +} + +ossimConnectableObject* ossimConnectableObject::getInput(ossim_uint32 index) +{ + if( (index >= 0) && (index < theInputObjectList.size())) + { + return theInputObjectList[index]; + } + + return NULL; +} + +const ossimConnectableObject* ossimConnectableObject::getInput(ossim_uint32 index)const +{ + if( (index >= 0) && (index < theInputObjectList.size())) + { + return theInputObjectList[index]; + } + + return NULL; +} + +ossimConnectableObject* ossimConnectableObject::getOutput(ossim_uint32 index) +{ + if( (index >= 0) && (index < theOutputObjectList.size())) + { + return theOutputObjectList[index]; + } + + return NULL; +} + +bool ossimConnectableObject::connectInputList(std::vector<ossimConnectableObject*>& inputList) +{ + bool result = true; + ossim_uint32 i = 0; + vector<ossimConnectableObject*> oldInputs = theInputObjectList; + vector<ossimConnectableObject*> newInputs; + vector<ossimConnectableObject*>::const_iterator currentInput = inputList.begin(); + vector<ossimConnectableObject*> tempOld; + if(theInputObjectList.size()) + { + for(i = 0; i < theInputObjectList.size(); ++i) + { + if(oldInputs[i]) + { + tempOld.push_back(oldInputs[i]); + } + theInputObjectList[i] = NULL; + } + } + if(theInputListIsFixedFlag && (theInputObjectList.size()==0)) + { + return false; + } + + if(!theInputListIsFixedFlag) + { + theInputObjectList.clear(); + } + if(tempOld.size()) + { + for(i = 0; i < tempOld.size(); ++ i) + { + tempOld[i]->disconnectMyOutput(this, false); + } + } + // disconnectAllInputs(); + + if(inputList.size() == 1) + { + return (connectMyInputTo(inputList[0])>=0); + } + i = 0; + while(currentInput != inputList.end()) + { + if(!canConnectMyInputTo(i, *currentInput)) + { + result = false; + } + ++i; + ++currentInput; + } + + if(!result) + { + return false; + } + // now connect the new outputs + // + currentInput = inputList.begin(); + while(currentInput != inputList.end()) + { + if(*currentInput) + { + (*currentInput)->connectMyOutputTo(this, false); + } + ++currentInput; + } + ossimConnectionEvent event(this, + OSSIM_EVENT_CONNECTION_DISCONNECT_ID, + newInputs, + oldInputs, + ossimConnectionEvent::OSSIM_INPUT_DIRECTION); + + if(theInputObjectList.size()) + { + theInputObjectList = inputList; + fireEvent(event); + } + else + { + theInputObjectList = inputList; + } + + newInputs = theInputObjectList; + + + + event = ossimConnectionEvent(this, + OSSIM_EVENT_CONNECTION_CONNECT_ID, + newInputs, + oldInputs, + ossimConnectionEvent::OSSIM_INPUT_DIRECTION); + fireEvent(event); + + return result; +} + +bool ossimConnectableObject::connectOutputList(std::vector<ossimConnectableObject*>& outputList) +{ + bool result = true; + ossim_int32 index = 0; + vector<ossimConnectableObject*> oldOutputs = theOutputObjectList; + vector<ossimConnectableObject*> newOutputs; + vector<ossimConnectableObject*>::const_iterator currentOutput = outputList.begin(); + + disconnectAllOutputs(); + + if(outputList.size() == 1) + { + return (connectMyOutputTo(outputList[0])>=0); + } + while(currentOutput != outputList.end()) + { + if(!canConnectMyOutputTo(index, *currentOutput)) + { + result = false; + } + ++currentOutput; + } + + if(!result) + { + return false; + } + + theOutputObjectList = outputList; + newOutputs = theOutputObjectList; + + ossimConnectionEvent event(this, + OSSIM_EVENT_CONNECTION_CONNECT_ID, + newOutputs, + oldOutputs, + ossimConnectionEvent::OSSIM_OUTPUT_DIRECTION); + fireEvent(event); + + return result; +} + +void ossimConnectableObject::setNumberOfInputs(ossim_int32 numberOfInputs) +{ + if((ossim_int32)theInputObjectList.size() == numberOfInputs) + { + return; + } + ossim_int32 i = 0; + if(numberOfInputs < (ossim_int32)theInputObjectList.size()) + { + vector<ossimConnectableObject*> v(theInputObjectList.begin(), + theInputObjectList.begin()+numberOfInputs); + vector<ossimConnectableObject*> disconnectList; + + for(i = numberOfInputs; + i < (ossim_int32)theInputObjectList.size(); + ++i) + { + if(theInputObjectList[i]) + { + disconnectList.push_back(theInputObjectList[i]); + } + } + disconnectMyInputs(disconnectList); + + theInputObjectList.clear(); + theInputObjectList = v; + } + else + { + for(i = (ossim_int32)theInputObjectList.size(); + i < numberOfInputs; + ++i) + { + theInputObjectList.push_back((ossimConnectableObject*)NULL); + } + } +} + +void ossimConnectableObject::setNumberOfOutputs(ossim_int32 numberOfOutputs) +{ + if((ossim_int32)theOutputObjectList.size() == numberOfOutputs) + { + return; + } + ossim_int32 i = 0; + if(numberOfOutputs < (ossim_int32)theOutputObjectList.size()) + { + vector<ossimConnectableObject*> v(theOutputObjectList.begin(), + theOutputObjectList.begin()+numberOfOutputs); + vector<ossimConnectableObject*> disconnectList; + for(i = numberOfOutputs; + i < (ossim_int32)theOutputObjectList.size(); + ++i) + { + if(theOutputObjectList[i]) + { + disconnectList.push_back(theOutputObjectList[i]); + } + } + disconnectMyOutputs(disconnectList); + + theOutputObjectList.clear(); + theOutputObjectList = v; + } + else + { + for(i = (ossim_int32)theOutputObjectList.size(); + i < numberOfOutputs; + ++i) + { + theOutputObjectList.push_back((ossimConnectableObject*)NULL); + } + } +} + + +const ossimConnectableObject* ossimConnectableObject::getOutput(ossim_uint32 index)const +{ + if( (index >= 0) && (index < theOutputObjectList.size())) + { + return theOutputObjectList[index]; + } + + return NULL; +} + +void ossimConnectableObject::findAllInputsOfType(vector<ossimConnectableObject*>& result, + const RTTItypeid& typeInfo, + bool propagateToInputs, + bool recurseChildren) +{ + int i; + int j; + // go through children first + // + ossimConnectableContainerInterface* inter = PTR_CAST(ossimConnectableContainerInterface, + this); + if(inter&&recurseChildren) + { + vector<ossimConnectableObject*> tempList = inter->findAllObjectsOfType(typeInfo, + true); + + for(j = 0; j < (int)tempList.size(); ++j) + { + std::vector<ossimConnectableObject*>::iterator iter = std::find(result.begin(), result.end(), tempList[j]); + if(iter == result.end()) + { + result.push_back(tempList[j]); + } + } + } + + for(i = 0; i < (int)getNumberOfInputs(); ++i) + { + ossimConnectableObject* current = getInput(i); + if(current&&(current->canCastTo(typeInfo))) + { + vector<ossimConnectableObject*>::iterator position = std::find(result.begin(), result.end(), current); + + if(position == result.end()) + { + result.push_back(current); + } + } + inter = PTR_CAST(ossimConnectableContainerInterface, current); + if(inter) + { + vector<ossimConnectableObject*> tempList = inter->findAllObjectsOfType(typeInfo, true); + for(j = 0; j < (int)tempList.size(); ++j) + { + std::vector<ossimConnectableObject*>::iterator iter = std::find(result.begin(), result.end(), tempList[j]); + if(iter == result.end()) + { + result.push_back(tempList[j]); + } + } + } + + if(propagateToInputs&¤t) + { + current->findAllInputsOfType(result, + typeInfo, + true, + recurseChildren); + } + } +} + +void ossimConnectableObject::findAllInputsOfType(vector<ossimConnectableObject*>& result, + const ossimString& className, + bool propagateToInputs, + bool recurseChildren) +{ + int j; + // go through children first + // + ossimConnectableContainerInterface* inter = PTR_CAST(ossimConnectableContainerInterface, + this); + if(inter&&recurseChildren) + { + vector<ossimConnectableObject*> tempList = inter->findAllObjectsOfType(className, + true); + + for(j = 0; j < (int)tempList.size(); ++j) + { + std::vector<ossimConnectableObject*>::iterator iter = std::find(result.begin(), result.end(), tempList[j]); + if(iter == result.end()) + { + result.push_back(tempList[j]); + } + } + } + for(ossim_uint32 i = 0; i < getNumberOfInputs(); ++i) + { + ossimConnectableObject* current = getInput(i); + if(current&&(current->canCastTo(className))) + { + std::vector<ossimConnectableObject*>::iterator iter = std::find(result.begin(), result.end(), current); + if(iter == result.end()) + { + result.push_back(current); + } + } + ossimConnectableContainerInterface* inter = PTR_CAST(ossimConnectableContainerInterface, + current); + if(inter) + { + vector<ossimConnectableObject*> tempList = inter->findAllObjectsOfType(className, true); + for(j = 0; j < (int)tempList.size(); ++j) + { + std::vector<ossimConnectableObject*>::iterator iter = std::find(result.begin(), result.end(), tempList[j]); + if(iter == result.end()) + { + result.push_back(tempList[j]); + } + } + } + + if(propagateToInputs&¤t) + { + current->findAllInputsOfType(result, + className, + true, + recurseChildren); + } + } +} + +void ossimConnectableObject::findAllOutputsOfType(vector<ossimConnectableObject*>& result, + const RTTItypeid& typeInfo, + bool propagateToOutputs, + bool recurseChildren) +{ + int j; + // go through children first + // + ossimConnectableContainerInterface* inter = PTR_CAST(ossimConnectableContainerInterface, + this); + if(inter&&recurseChildren) + { + vector<ossimConnectableObject*> tempList = inter->findAllObjectsOfType(typeInfo, + true); + + for(j = 0; j < (int)tempList.size(); ++j) + { + std::vector<ossimConnectableObject*>::iterator iter = std::find(result.begin(), result.end(), tempList[j]); + if(iter == result.end()) + { + result.push_back(tempList[j]); + } + } + } + for(ossim_uint32 i = 0; i < getNumberOfOutputs(); ++i) + { + ossimConnectableObject* current = getOutput(i); + if(current&&(current->canCastTo(typeInfo))) + { + result.push_back(current); + } + ossimConnectableContainerInterface* inter = PTR_CAST(ossimConnectableContainerInterface, + current); + if(inter) + { + vector<ossimConnectableObject*> tempList = inter->findAllObjectsOfType(typeInfo, true); + for(j = 0; j < (int)tempList.size(); ++j) + { + std::vector<ossimConnectableObject*>::iterator iter = std::find(result.begin(), result.end(), tempList[j]); + if(iter == result.end()) + { + result.push_back(tempList[j]); + } + } + } + + if(propagateToOutputs&¤t) + { + current->findAllOutputsOfType(result, + typeInfo, + true, + recurseChildren); + } + } +} + +void ossimConnectableObject::findAllOutputsOfType(vector<ossimConnectableObject*>& result, + const ossimString& className, + bool propagateToOutputs, + bool recurseChildren) +{ + int j; + // go through children first + // + ossimConnectableContainerInterface* inter = PTR_CAST(ossimConnectableContainerInterface, + this); + if(inter&&recurseChildren) + { + vector<ossimConnectableObject*> tempList = inter->findAllObjectsOfType(className, + true); + + for(j = 0; j < (int)tempList.size(); ++j) + { + std::vector<ossimConnectableObject*>::iterator iter = std::find(result.begin(), result.end(), tempList[j]); + if(iter == result.end()) + { + result.push_back(tempList[j]); + } + } + } + for(ossim_uint32 i = 0; i < getNumberOfOutputs(); ++i) + { + ossimConnectableObject* current = getOutput(i); + if(current&&(current->canCastTo(className))) + { + std::vector<ossimConnectableObject*>::iterator iter = std::find(result.begin(), result.end(), current); + if(iter == result.end()) + { + result.push_back(current); + } + } + ossimConnectableContainerInterface* inter = PTR_CAST(ossimConnectableContainerInterface, + current); + if(inter) + { + vector<ossimConnectableObject*> tempList = inter->findAllObjectsOfType(className, + true); + for(j = 0; j < (int)tempList.size(); ++j) + { + std::vector<ossimConnectableObject*>::iterator iter = std::find(result.begin(), result.end(), tempList[j]); + if(iter == result.end()) + { + result.push_back(tempList[j]); + } + } + } + + if(propagateToOutputs&¤t) + { + current->findAllOutputsOfType(result, + className, + true, + recurseChildren); + } + } +} + + +void ossimConnectableObject::propagateEventToOutputs(ossimEvent& event) +{ + ossim_uint32 i; + + for(i = 0; i <getNumberOfOutputs(); ++i) + { + ossimConnectableObject* obj = getOutput(i); + if(obj) + { + obj->fireEvent(event); + obj->propagateEventToOutputs(event); + } + } +} + +void ossimConnectableObject::propagateEventToInputs(ossimEvent& event) +{ + ossim_uint32 i; + + for(i = 0; i <getNumberOfInputs(); ++i) + { + ossimConnectableObject* obj = getInput(i); + if(obj) + { + obj->fireEvent(event); + obj->propagateEventToInputs(event); + } + } +} + +void ossimConnectableObject::setProperty(ossimRefPtr<ossimProperty> property) +{ + if(!property.valid()) return; + if(property->getName() == "Description") + { + property->valueToString(theDescription); + } +} + +ossimRefPtr<ossimProperty> ossimConnectableObject::getProperty(const ossimString& name)const +{ + if(name == "Description") + { + return new ossimTextProperty(name, theDescription); + } + else if(name == "Class name") + { + ossimProperty* prop = new ossimTextProperty(name, + getClassName()); + prop->setReadOnlyFlag(true); + + return prop; + } + return (ossimProperty*)NULL; +} + +void ossimConnectableObject::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + propertyNames.push_back("Class name"); + propertyNames.push_back("Description"); +} + +bool ossimConnectableObject::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* lookup = kwl.find(prefix, + ossimKeywordNames::ID_KW); + + // disconnect(this); + + if(lookup) + { + theId = ossimId(ossimString(lookup).toLong()); + } + + lookup = kwl.find(prefix, CONNECTABLE_INPUT_LIST_FIXED_KW); + if(lookup) + { + theInputListIsFixedFlag = ossimString(lookup).toBool(); + } + + lookup = kwl.find(prefix, CONNECTABLE_OUTPUT_LIST_FIXED_KW); + if(lookup) + { + theOutputListIsFixedFlag = ossimString(lookup).toBool(); + } + + ossim_int32 numberInputs = 0; + ossim_int32 numberOutputs = 0; + + ossimString regExpression; + lookup = kwl.find(prefix, ossimKeywordNames::NUMBER_INPUTS_KW); + if(lookup) + { + numberInputs = ossimString(lookup).toLong(); + } + else + { + regExpression = ossimString("^(") + ossimString(prefix) + "input_connection[0-9]+)"; + numberInputs = kwl.getNumberOfSubstringKeys(regExpression); + } + + lookup = kwl.find(prefix, ossimKeywordNames::NUMBER_OUTPUTS_KW); + if(lookup) + { + numberOutputs = ossimString(lookup).toLong(); + } + else + { + regExpression = ossimString("^(") + ossimString(prefix) + "output_connection[0-9]+)"; + numberOutputs = kwl.getNumberOfSubstringKeys(regExpression); + } + theDescription = kwl.find(prefix, ossimKeywordNames::DESCRIPTION_KW); + + setNumberOfInputs(numberInputs); + setNumberOfOutputs(numberOutputs); + + return ossimObject::loadState(kwl, prefix); +} + +bool ossimConnectableObject::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimObject::saveState(kwl, prefix); + + kwl.add(prefix, + ossimKeywordNames::ID_KW, + theId.getId(), + true); + + kwl.add(prefix, + ossimKeywordNames::DESCRIPTION_KW, + theDescription, + true); + + kwl.add(prefix, + CONNECTABLE_INPUT_LIST_FIXED_KW, + (long)theInputListIsFixedFlag, + true); + + kwl.add(prefix, + CONNECTABLE_OUTPUT_LIST_FIXED_KW, + (long)theOutputListIsFixedFlag, + true); + + kwl.add(prefix, + ossimKeywordNames::NUMBER_INPUTS_KW, + (long)theInputObjectList.size(), + true); + + kwl.add(prefix, + ossimKeywordNames::NUMBER_OUTPUTS_KW, + (long)theOutputObjectList.size(), + true); + + ossim_int32 i = 0; + for(i = 1; i <= (ossim_int32)theInputObjectList.size(); ++i) + { + ossimString value = "input_connection" + ossimString::toString(i); + + long id; + + if(theInputObjectList[i-1]) + { + id = theInputObjectList[i-1]->getId().getId(); + } + else + { + id = -1; + } + kwl.add(prefix, + value.c_str(), + id, + true); + } + + for(i = 1; i <= (ossim_int32)theOutputObjectList.size(); ++i) + { + ossimString value = "output_connection" + ossimString::toString(i); + + long id; + + if(theOutputObjectList[i-1]) + { + id = theOutputObjectList[i-1]->getId().getId(); + } + else + { + id = -1; + } + kwl.add(prefix, + value.c_str(), + id, + true); + } + + return true; +} + +ossim_uint32 ossimConnectableObject::saveStateOfAllInputs( + ossimKeywordlist& kwl, + bool saveThisStateFlag, + ossim_uint32 objectIndex, + const char* prefix) const +{ + ossim_uint32 index = objectIndex; + + const ossim_uint32 NUMBER_OF_INPUTS = getNumberOfInputs(); + if (NUMBER_OF_INPUTS) + { + // Save all the inputs. + for(ossim_uint32 i = 0; i < NUMBER_OF_INPUTS; ++i) + { + const ossimConnectableObject* input = getInput(i); + if(input) + { + index = input->saveStateOfAllInputs(kwl, + true, + index, + prefix); + } + } + } + + if (saveThisStateFlag) + { + ossimString myPrefix; + if (prefix) + { + myPrefix = prefix; + } + + myPrefix += "object"; + myPrefix += ossimString::toString(index); + myPrefix += "."; + + // Save the state of this object. + saveState(kwl, myPrefix.c_str()); + ++index; + } + + return index; +} + +bool ossimConnectableObject::canConnectMyOutputTo(ossim_int32 myOutputIndex, + const ossimConnectableObject* /* object */ ) const +{ + if(theOutputListIsFixedFlag) + { + return ((myOutputIndex >= 0) && + (myOutputIndex < (ossim_int32)theOutputObjectList.size())); + } + + return ((myOutputIndex >= 0) && + (myOutputIndex <= (ossim_int32)theOutputObjectList.size())); +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimConnectableObject.h b/Utilities/OSSIM/ossim_core/base/common/ossimConnectableObject.h new file mode 100644 index 0000000000..9976f518a0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimConnectableObject.h @@ -0,0 +1,470 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: Garrett Potts +// +// Description: +// +// Contains class declaration for ossimConnectableObject the base class for +// all connectable objects. +// +//************************************************************************* +// $Id: ossimConnectableObject.h,v 1.54 2005/12/27 15:47:49 dburken Exp $ + +#ifndef ossimConnectableObject_HEADER +#define ossimConnectableObject_HEADER + +#include <vector> + +#include <base/common/ossimObject.h> +#include <base/common/ossimId.h> +#include <base/common/ossimConstants.h> +#include <base/common/events/ossimListenerManager.h> +#include <base/common/ossimPropertyInterface.h> + +/** + * This class is the base of all connectable objects. It will manage + * firing any attachment events (changing, adding and removing, etc. + * This allows us to perform automatic notification to nodes + * to the input's or output's. + * + * The only methods that the derived classes should override are the + * canConnect methods. + */ +class OSSIMDLLEXPORT ossimConnectableObject : public ossimObject, + public ossimListenerManager, + public ossimPropertyInterface +{ +public: + enum ossimConnectableObjectDirectionType + { + CONNECTABLE_DIRECTION_NONE = 0, + CONNECTABLE_DIRECTION_INPUT = 1, + CONNECTABLE_DIRECTION_OUTPUT = 2 + }; + /** + * Base constructor of this object. + */ + ossimConnectableObject(ossimObject* owner=0); + ossimConnectableObject(ossimObject* owner, + long inputListSize, + long outputListSize, + bool inputListIsFixedFlag=true, + bool outputListIsFixedFlag=true); + + virtual ~ossimConnectableObject(); + + /** + * All connectable objects will have id's. This allows us to + * set the id of this object. + */ + void setId(const ossimId& id){theId = id;} + + /** + * Will allow us to get this object's id. + */ + const ossimId& getId()const{return theId;} + + /** + * Fetches the current owner, most likely a container but not limited to one. + */ + const ossimObject* getOwner() const { return theOwner; } + + /** + * Permits changing the object's owner. + */ + virtual void changeOwner(ossimObject* owner); + + virtual void setDescription(const ossimString& description); + virtual ossimString getDescription()const; + + /** + * will check the direction specified to see if all slots are full. + * If any slot is null then false is returned. + * If a filter requires options testing they + * need to override this method. The argument can be ored together. If you + * want both checked then pass + * CONNECTABLE_DIRECTION_INPUT | CONNECTABLE_DIRECTION_OUTPUT + */ + virtual bool isConnected(ossimConnectableObjectDirectionType direction = CONNECTABLE_DIRECTION_INPUT)const; + + + /** + * + * Searches the input list and the output list for the + * passed in id. Returns NULL if it wasn't found. + * + */ + virtual ossimConnectableObject* findConnectableObject(const ossimId& id); + + /** + * Will search for a given object of the passed in RTTI type. + */ + virtual ossimConnectableObject* findObjectOfType(RTTItypeid typeId, + ossimConnectableObjectDirectionType directionType, + bool recurse = true); + + virtual ossimConnectableObject* findObjectOfType(const ossimString& obj, + ossimConnectableObjectDirectionType directionType, + bool recurse = true); + + /** + * @param className Class name of object to look for. + * + * @return object of the passed in RTTI type or NULL if not found. + * + * @note This method does NOT traverse beyond any objects the do not have + * a fixed input of one connection. + */ + virtual ossimConnectableObject* findInputObjectOfType( + const ossimString& className); + + /** + * Return a valid index of the input list if the passed in object + * is found else return -1. + */ + virtual ossim_int32 findInputIndex(const ossimConnectableObject* object); + + /** + * Return a valid index of the input list if the passed id + * is found else return -1. + */ + virtual ossim_int32 findInputIndex(const ossimId& id); + + /** + * Return a valid index of the output list if the passed in object + * is found else return -1. + */ + virtual ossim_int32 findOutputIndex(const ossimConnectableObject* object); + + /** + * Return a valid index of the output list if the passed in object + * is found else return -1. + */ + virtual ossim_int32 findOutputIndex(const ossimId& id); + + /** + * Should return the first available index to connect to. The connectMyInputTo + * that just takes another ossimConnectableObject as input and not an index + * will call this method. By default this method will find the first open + * slot (not null) or append o the list if it's dynamic. if the list is + * dynamic it calls conConnectMyInputTo(index, object) on an index = to listSize. + * + */ + virtual ossim_int32 getMyInputIndexToConnectTo(ossimConnectableObject* object)const; + + + /** + * Should return the first available index to connect to. The connectMyOutputTo + * that just takes another ossimConnectableObject as input and not an index + * will call this method. By default this method will find the first open + * slot (not null) or append to the list if it's dynamic. if the list is + * dynamic it calls canConnectMyOutputTo(index, object) on an index = to listSize. + * + */ + virtual ossim_int32 getMyOutputIndexToConnectTo(ossimConnectableObject* object)const; + + /** + * required to be overriden by derived classes + */ + virtual bool canConnectMyInputTo(ossim_int32 myInputIndex, + const ossimConnectableObject* object)const=0; + + /** + * default implementation is to allow anyone to connect to us. + */ + virtual bool canConnectMyOutputTo(ossim_int32 myOutputIndex, + const ossimConnectableObject* object)const; + + /** + * Will disconnect the object passed in. + */ + virtual void disconnect(ossimConnectableObject* object=0); + + /** + * Will disconnect the object passed in. + */ + virtual void disconnect(const ossimId& id); + + /** + * Will disconnect the object at the given input index and generate + * a connection event. + */ + virtual ossimConnectableObject* disconnectMyInput(ossim_int32 inputIndex, + bool disconnectOutputFlag=true, + bool createEventFlag = true); + + /** + * Finds the index of the passed in input and calls + * disconnectMyInput(inputIndex, disconnectOutputFlag, createEventFlag); + */ + virtual void disconnectMyInput(ossimConnectableObject* input, + bool disconnectOutputFlag=true, + bool createEventFlag = true); + /** + * + */ + virtual void disconnectMyInputs(std::vector<ossimConnectableObject*>& inputList, + bool disconnectOutputFlag=true, + bool createEventFlag=true); + + /** + * Will disconnect the object at the given output index and generate + * a connection event. If there is no object at that index then no + * event is generated and NULL is returned. The disconnectOutputFlag + * says do you want this method to disconnect the output pointer to + * this object. + */ + virtual ossimConnectableObject* disconnectMyOutput(ossim_int32 outputIndex, + bool disconnectInputFlag=true, + bool createEventFlag = true); + + /** + * Will disconnect the output object. It will get the index of + * the object and call disconnectMyOutput(index, disconnectOutputFlag). + */ + virtual void disconnectMyOutput(ossimConnectableObject* output, + bool disconnectInputFlag=true, + bool createEventFlag=true); + + virtual void disconnectMyOutputs(std::vector<ossimConnectableObject*>& outputList, + bool disconnectOutputFlag=true, + bool createEventFlag=true); + /** + * Will disconnect all of the input objects. + */ + virtual void disconnectAllInputs(); + + /** + * Will disconnect all of the output objects. + */ + virtual void disconnectAllOutputs(); + + /** + * Will try to connect this objects input to the passed in object. + * It will return a valid index >= 0 if successful. Will use the + * getMyInputIndexToConnectTo method to implement the connection + */ + virtual ossim_int32 connectMyInputTo(ossimConnectableObject* inputObject, + bool makeOutputConnection=true, + bool createEventFlag=true); + + /** + * Will connect the specified input to the passed in object + */ + virtual ossim_int32 connectMyInputTo(ossim_int32 inputIndex, + ossimConnectableObject* inputObject, + bool makeOutputConnection=true, + bool createEventFlag=true); + + virtual bool connectMyInputTo(std::vector<ossimConnectableObject*>& inputList, + bool makeOutputConnection=true, + bool createEventFlag = true); + + /** + * Will try to connect this objects output to the passed in object. + * It will return a valid index >= 0 if successful. It will in turn call + * the passed in objects connect input command if makeInputConnection + * is set to true. + * + * Will use the getMyOutputIndexToConnectTo to implement this method + */ + virtual ossim_int32 connectMyOutputTo(ossimConnectableObject* outputObject, + bool makeInputConnection=true, + bool createEventFlag=true); + + virtual bool connectMyOutputTo(std::vector<ossimConnectableObject*>& outputList, + bool makeInputConnection=true, + bool createEventFlag=true); + + /** + * Will disconnect itself from all inputs and reset to the passed in + * input list. It will return true if all objects were successfully + * added. + */ + virtual bool connectInputList(std::vector<ossimConnectableObject*>& inputList); + + /** + * Will disconnect itself from all outputs and reset to the passed in + * output list. It will return true if all objects were successfully + * added. + */ + virtual bool connectOutputList(std::vector<ossimConnectableObject*>& outputList); + + /** + * Returns the number of input objects. + */ + virtual ossim_uint32 getNumberOfInputs()const + { + return (ossim_uint32)theInputObjectList.size(); + } + + /** + * Return the number of output objects + */ + virtual ossim_uint32 getNumberOfOutputs()const + { + return (ossim_uint32)theOutputObjectList.size(); + } + + /** + * returns the object at the specified index. + * if the index is not valid then NULL is + * returned + */ + ossimConnectableObject* getInput(ossim_uint32 index=0); + + /** + * returns the object at the specified index. + * if the index is not valid then NULL is + * returned + */ + const ossimConnectableObject* getInput(ossim_uint32 index=0)const; + + /** + * returns the object at the specified index. + * if the index is not valid then NULL is + * returned + */ + ossimConnectableObject* getOutput(ossim_uint32 index=0); + + /** + * returns the object at the specified index. + * if the index is not valid then NULL is + * returned + */ + const ossimConnectableObject* getOutput(ossim_uint32 index=0)const; + + /** + * Will set the number of inputs. This will expand the list if the number + * of inputs is larger than the current number of inputs. Will shrink + * the list if the current number of inputs is larger than the passed in + * inputs. + */ + virtual void setNumberOfInputs(ossim_int32 numberOfInputs); + + virtual bool getInputListIsFixedFlag()const + { + return theInputListIsFixedFlag; + } + + virtual bool getOutputListIsFixedFlag()const + { + return theOutputListIsFixedFlag; + } + /** + * Will set the number of outputs. This will expand the list if the + * number of outputs is larger than the current number of outputs. + * Will shrink the list if the current number of outputs is larger than + * the passed in outputs. + */ + virtual void setNumberOfOutputs(ossim_int32 numberOfInputs); + + const std::vector<ossimConnectableObject*>& getInputList()const + { + return theInputObjectList; + } + const std::vector<ossimConnectableObject*>& getOutputList()const + { + return theOutputObjectList; + } + std::vector<ossimConnectableObject*>& getInputList() + { + return theInputObjectList; + } + std::vector<ossimConnectableObject*>& getOutputList() + { + return theOutputObjectList; + } + + virtual void findAllInputsOfType(vector<ossimConnectableObject*>& result, + const RTTItypeid& typeInfo, + bool propagateToInputs=true, + bool recurseChildren=false); + virtual void findAllInputsOfType(vector<ossimConnectableObject*>& result, + const ossimString& className, + bool propagateToInputs=true, + bool recurseChildren=false); + virtual void findAllOutputsOfType(vector<ossimConnectableObject*>& result, + const ossimString& className, + bool propagateToOutputs=true, + bool recurseChildren=false); + virtual void findAllOutputsOfType(vector<ossimConnectableObject*>& result, + const RTTItypeid& typeInfo, + bool propagateToOutputs=true, + bool recurseChildren=false); + + virtual void propagateEventToOutputs(ossimEvent& event); + virtual void propagateEventToInputs(ossimEvent& event); + + /* ------------------- PROPERTY INTERFACE -------------------- */ + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + /* ------------------ PROPERTY INTERFACE END ------------------- */ + + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix = (const char*)NULL); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix = (const char*)NULL)const; + + /** + * Save the state of all inputs to a keyword list. This will do a + * recursive call through all inputs and save their state to a + * keyword list. + * + * @param kwl Keyword list to save state to. + * + * @param saveThisStateFlag If the true the state of this object will be + * saved as well as all inputs. Default = true. + * + * @param objectIndex Index to be used for prefix. So if + * objectIndex = 1, the first object will have a prefix of: "object1." + * Default = 1. + * + * @param prefix Prefix to tack onto keyword. If prefix = "myChain." and + * objectIndex = 1, then the first keyword would be + * "myChain.object1.some_keyword". + * + * @return Returns the next object index. This is the last index used + * plus one. Used internally to keep track of index to use for prefix. + */ + virtual ossim_uint32 saveStateOfAllInputs(ossimKeywordlist& kwl, + bool saveThisStateFlag=true, + ossim_uint32 objectIndex=1, + const char* prefix=NULL) const; + +protected: + ossimId theId; + ossimString theDescription; + ossimObject* theOwner; + + /** + * Indicates whether the theInputObjectList is fixed + */ + bool theInputListIsFixedFlag; + + /** + * Indicates whether the theOutputObjectList is fixed + */ + bool theOutputListIsFixedFlag; + + /** + * Holds a list of input objects. + */ + std::vector<ossimConnectableObject*> theInputObjectList; + + /** + * Holds a list of output objects. + */ + std::vector<ossimConnectableObject*> theOutputObjectList; + +private: +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimConstants.h b/Utilities/OSSIM/ossim_core/base/common/ossimConstants.h new file mode 100644 index 0000000000..d257b2af14 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimConstants.h @@ -0,0 +1,514 @@ +/******************************************************************** + * Copyright (C) 2000 ImageLinks Inc. + * + * License: LGPL + * + * See LICENSE.txt file in the top level directory for more details. + * + * Author: Ken Melero + * + * Description: Common file for global constants. + * + ************************************************************************** + * $Id: ossimConstants.h,v 1.69 2005/06/30 18:32:51 gpotts Exp $ + */ +#ifndef ossimConstants_HEADER +#define ossimConstants_HEADER + +#ifdef __cplusplus +extern "C" { +#endif + +#include <float.h> +#include <ossimConfig.h> + + +/** + * WARNINGS SECTION: + */ +#ifdef _MSC_VER /* Quiet a bunch of MSVC warnings... */ +# pragma warning(disable:4786) /* visual c6.0 compiler */ +# pragma warning(disable:4251)/* for std:: member variable to have dll interface */ +# pragma warning(disable:4275) /* for std:: base class to have dll interface */ +# pragma warning(disable:4800) /* int forcing value to bool */ +# pragma warning(disable:4244) /* conversion, possible loss of data */ +#endif + +/** + * DLL IMPORT/EXORT SECTION + */ +#if defined(__MINGW32__) || defined(__CYGWIN__) || defined(_MSC_VER) || defined(__VISUALC__) || defined(__BORLANDC__) || defined(__WATCOMC__) +# define OSSIMEXPORT __declspec(dllexport) +# define OSSIMIMPORT __declspec(dllimport) +# ifdef OSSIMMAKINGDLL +# define OSSIMDLLEXPORT OSSIMEXPORT +# define OSSIM_DLL OSSIMEXPORT +# define OSSIMDLLEXPORT_DATA(type) OSSIMEXPORT type +# define OSSIM_DLL_DATA(type) OSSIMEXPORT type +# define OSSIMDLLEXPORT_CTORFN +# else +# define OSSIMDLLEXPORT OSSIMIMPORT +# define OSSIM_DLL OSSIMIMPORT +# define OSSIMDLLEXPORT_DATA(type) OSSIMIMPORT type +# define OSSIM_DLL_DATA(type) OSSIMIMPORT type +# define OSSIMDLLEXPORT_CTORFN +# endif +#else /* not #if defined(_MSC_VER) */ +# define OSSIMEXPORT +# define OSSIMIMPORT +# define OSSIMDLLEXPORT +# define OSSIM_DLL +# define OSSIMDLLEXPORT_DATA +# define OSSIM_DLL_DATA +# define OSSIMDLLEXPORT_CTORFN +#endif /* #if defined(_MSC_VER) */ + +/** + * Previous DLL import export section. Commented out, but left just in case. + */ +#if 0 /* Comment out ALL this mess! */ +#if defined(_MSC_VER) || defined(__VISUALC__) || defined(__BORLANDC__) || defined(__GNUC__) || defined(__WATCOMC__) +# if (_MSC_VER >= 1300) /* MSVC .NET 2003 version */ +# define OSSIMEXPORT __declspec(dllexport) +# define OSSIMIMPORT __declspec(dllimport) +# else +# define OSSIMEXPORT __declspec(dllexport) +# define OSSIMIMPORT __declspec(dllimport) +# endif +#else /* compiler doesn't support __declspec() */ +# define OSSIMEXPORT +# define OSSIMIMPORT +#endif + +#if defined(__WXPM__) +# if defined (__WATCOMC__) +# define OSSIMEXPORT __declspec(dllexport) + /* + __declspec(dllimport) prepends __imp to imported symbols. We do NOT + want that! + */ +# define OSSIMIMPORT +# elif (!(defined(__VISAGECPP__) && (__IBMCPP__ < 400 || __IBMC__ < 400 ))) +# define OSSIMEXPORT _Export +# define OSSIMIMPORT _Export +# endif +#elif defined(__OSSIMMAC__) +# ifdef __MWERKS__ +# define OSSIMEXPORT __declspec(export) +# define OSSIMIMPORT __declspec(import) +# endif +#endif + +#if defined(_MSC_VER) +# pragma warning(disable:4786) /* visual c6.0 compiler */ +# pragma warning(disable:4251) /* for std:: member variable to have dll interface */ +# pragma warning(disable:4275) /* for std:: base class to have dll interface */ +# pragma warning(disable:4800) /* int forcing value to bool */ +# pragma warning(disable:4244) /* conversion, possible loss of data */ + +# ifdef OSSIMSINGLEDLL /* one gigantic dll, all declared export */ +# ifdef EXPORT_OSMMATRIX +# define EXPORT_OSMMATRIX OSSIMEXPORT +# endif +# ifndef OSSIMDLLEXPORT +# define OSSIMDLLEXPORT OSSIMEXPORT +# endif +# ifdef EXPORT_OSMELEV +# define EXPORT_OSMELEV OSSIMEXPORT +# endif +# ifdef EXPORT_OSMSPTDATA +# define EXPORT_OSMSPTDATA OSSIMEXPORT +# endif +# ifdef EXPORT_ISO8211 +# define EXPORT_ISO8211 OSSIMEXPORT +# endif +# ifdef EXPORT_OSMPROJ +# define EXPORT_OSMPROJ OSSIMEXPORT +# endif +# ifndef EXPORT_OSMIMAGING +# define EXPORT_OSMIMAGING OSSIMEXPORT +# endif +# else /* individual dlls, each with their own import/export symbols */ +# ifndef EXPORT_OSMMATRIX +# ifdef OSMMATRIX_EXPORTS +# define EXPORT_OSMMATRIX OSSIMEXPORT +# else +# define EXPORT_OSMMATRIX OSSIMIMPORT +# endif +# endif +# ifndef OSSIMDLLEXPORT +# ifdef OSMBASE_EXPORTS +# define OSSIMDLLEXPORT OSSIMEXPORT +# else +# define OSSIMDLLEXPORT OSSIMIMPORT +# endif +# endif +# ifndef EXPORT_OSMELEV +# ifdef OSMELEV_EXPORTS +# define EXPORT_OSMELEV OSSIMEXPORT +# else +# define EXPORT_OSMELEV OSSIMIMPORT +# endif +# endif +# ifndef EXPORT_OSMSPTDATA +# ifdef OSMSPTDATA_EXPORTS +# define EXPORT_OSMSPTDATA OSSIMEXPORT +# else +# define EXPORT_OSMSPTDATA OSSIMIMPORT +# endif +# endif +# ifndef EXPORT_OSMPROJ +# ifdef OSMPROJ_EXPORTS +# define EXPORT_OSMPROJ OSSIMEXPORT +# else +# define EXPORT_OSMPROJ OSSIMIMPORT +# endif +# endif +# ifndef EXPORT_ISO8211 +# ifdef ISO8211_EXPORTS +# define EXPORT_ISO8211 OSSIMEXPORT +# else +# define EXPORT_ISO8211 OSSIMIMPORT +# endif +# endif +# ifndef EXPORT_OSMIMAGING +# ifdef OSMIMAGING_EXPORTS +# define EXPORT_OSMIMAGING OSSIMEXPORT +# else +# define EXPORT_OSMIMAGING OSSIMIMPORT +# endif +# endif +# endif +#else /* defined(_MSC_VER) */ +# ifdef OSSIMMAKINGDLL +# define OSSIMDLLEXPORT OSSIMEXPORT +# define OSSIM_DLL OSSIMEXPORT +# define OSSIMDLLEXPORT_DATA(type) OSSIMEXPORT type +# define OSSIM_DLL_DATA(type) OSSIMEXPORT type +# define OSSIMDLLEXPORT_CTORFN +# elif defined(OSSIMUSINGDLL) +# define OSSIMDLLEXPORT OSSIMIMPORT +# define OSSIM_DLL OSSIMIMPORT +# define OSSIMDLLEXPORT_DATA(type) OSSIMIMPORT type +# define OSSIM_DLL_DATA(type) OSSIMIMPORT type +# define OSSIMDLLEXPORT_CTORFN +# else /* not making nor using DLL */ +# define OSSIMDLLEXPORT +# define OSSIM_DLL +# define OSSIM_DLL_DATA(type) type +# define OSSIMDLLEXPORT_DATA(type) type +# define OSSIMDLLEXPORT_CTORFN +# endif +# define EXPORT_OSMMATRIX OSSIMDLLEXPORT +# define EXPORT_OSMELEV OSSIMDLLEXPORT +# define EXPORT_OSMSPTDATA OSSIMDLLEXPORT +# define EXPORT_OSMPROJ OSSIMDLLEXPORT +# define EXPORT_OSMIMAGING OSSIMDLLEXPORT +#endif +#endif /* End of commented out "#if 0" old DLL import/export section. */ + +/* + we know that if this is defined all other types are defined + since its included from ossimConfig.h +*/ +typedef char ossim_int8; +typedef unsigned char ossim_uint8; +typedef signed char ossim_sint8; + +typedef short ossim_int16; +typedef unsigned short ossim_uint16; +typedef signed short ossim_sint16; + +typedef int ossim_int32; +typedef unsigned int ossim_uint32; +typedef signed int ossim_sint32; + +typedef float ossim_float32; +typedef double ossim_float64; + +/* + these are in ossimConfig.h. For platforms that dont have a configure + you just copy the ossimConfig.h.in to ossimConfig.h found in src directory + and make modifications based on your platform +*/ +#ifdef OSSIM_SIZEOF_LONG_INT + +# if OSSIM_SIZEOF_LONG_INT == 8 +typedef long int ossim_int64; +typedef unsigned long int ossim_uint64; +typedef signed long int ossim_sint64; +# elif OSSIM_SIZEOF_LONG_LONG == 8 +typedef long long ossim_int64; +typedef unsigned long long ossim_uint64; +typedef signed long long ossim_sint64; +# else +typedef long int ossim_int64; +typedef unsigned long int ossim_uint64; +typedef signed long int ossim_sint64; +# endif + +#else +typedef long int ossim_int64; +typedef unsigned long int ossim_uint64; +typedef signed long int ossim_sint64; +#endif + + +typedef ossim_int32 ossimErrorCode; + +enum ossimVertexOrdering +{ + OSSIM_VERTEX_ORDER_UNKNOWN = 0, + OSSIM_CLOCKWISE_ORDER = 1, + OSSIM_COUNTERCLOCKWISE_ORDER = 2 +}; + + +/* + Corner coordinates are relative to center (0) of pixel + or relative to the upper left of pixel (1). +*/ +enum ossimPixelType +{ + OSSIM_PIXEL_IS_POINT = 0, + OSSIM_PIXEL_IS_AREA = 1 +}; + +/* + Definitions for scalar type identification. +*/ +enum ossimScalarType +{ + OSSIM_SCALAR_UNKNOWN = 0, + OSSIM_UINT8 = 1, /**< 8 bit unsigned integer */ + OSSIM_SINT8 = 2, /**< 8 bit signed integer */ + OSSIM_UINT16 = 3, /**< 16 bit unsigned integer */ + OSSIM_SINT16 = 4, /**< 16 bit signed integer */ + OSSIM_UINT32 = 5, /**< 32 bit unsigned integer */ + OSSIM_SINT32 = 6, /**< 32 bit signed integer */ + OSSIM_FLOAT32 = 7, /**< 32 bit floating point */ + OSSIM_FLOAT64 = 8, /**< 64 bit floating point */ + OSSIM_CINT16 = 9, /**< 16 bit complex integer */ + OSSIM_CINT32 = 10, /**< 32 bit complex integer */ + OSSIM_CFLOAT32 = 11, /**< 32 bit complex floating point */ + OSSIM_CFLOAT64 = 12, /**< 64 bit complex floating point */ + + //--- + // Below for backward compatibility only. Please use above enums in + // conjunction with null, min, max settings to determine bit depth. + //--- + OSSIM_UCHAR = 1, /**< 8 bit unsigned iteger */ + OSSIM_USHORT16 = 3, /**< 16 bit unsigned iteger */ + OSSIM_SSHORT16 = 4, /**< 16 bit signed integer */ + OSSIM_USHORT11 = 13, /**< 16 bit unsigned integer (11 bits used) */ + OSSIM_FLOAT = 7, /**< 32 bit floating point */ + OSSIM_NORMALIZED_FLOAT = 18, /**< normalized floating point 32 bit */ + OSSIM_DOUBLE = 8, /**< double 64 bit */ + OSSIM_NORMALIZED_DOUBLE = 20 /**< Normalized double 64 bit */ +}; + +/* + Definitions for interleave type identification. +*/ +enum ossimInterleaveType +{ + OSSIM_INTERLEAVE_UNKNOWN = 0, + OSSIM_BIL = 1, /* band interleaved by line */ + OSSIM_BIP = 2, /* band interleaved by pixel */ + OSSIM_BSQ = 3, /* band sequential */ + OSSIM_BSQ_MULTI_FILE = 4 /* band sequential in separate files */ +}; + +/* + Definitions for origin location. +*/ +enum ossimOriginLocationType +{ + OSSIM_ORIGIN_LOCATION_UNKNOWN = 0, + OSSIM_CENTER = 1, + OSSIM_UPPER_LEFT = 2, + OSSIM_UPPER_LEFT_CENTER = 3, + OSSIM_LOWER_LEFT = 4, + OSSIM_LOWER_LEFT_CENTER = 5 +}; + +/* + Definitions for coordinate system type. +*/ +enum ossimCoordinateSystemType +{ + OSSIM_COORDINATE_SYSTEM_UNKNOWN = 0, + OSSIM_IMAGE_SPACE = 1, + OSSIM_GEOGRAPHIC_SPACE = 2, + OSSIM_PROJECTED_SPACE = 3, + OSSIM_GEOCENTRIC_SPACE = 4 +}; + +/* + Definitions for coordinate system orientation mode . +*/ +enum ossimCoordSysOrientMode +{ + OSSIM_LEFT_HANDED = 0, + OSSIM_RIGHT_HANDED = 1 +}; + + + +/* + Definitions for unit type. +*/ +enum ossimUnitType +{ + OSSIM_UNIT_UNKNOWN = 0, + OSSIM_METERS = 1, + OSSIM_FEET = 2, + OSSIM_US_SURVEY_FEET = 3, + OSSIM_DEGREES = 4, + OSSIM_RADIANS = 5, + OSSIM_NAUTICAL_MILES = 6, + OSSIM_SECONDS = 7, + OSSIM_MINUTES = 8, + OSSIM_PIXEL = 9, + OSSIM_MILES = 10, + OSSIM_MILLIMETERS = 11, + OSSIM_MICRONS = 12 +}; + +/* + Definitions for data object status. +*/ +enum ossimDataObjectStatus +{ + OSSIM_STATUS_UNKNOWN = 0, + OSSIM_NULL = 1, + OSSIM_EMPTY = 2, + OSSIM_PARTIAL = 3, + OSSIM_FULL = 4 +}; + +/** Definitions for image type identification. */ +enum ossimImageType +{ + OSSIM_IMAGE_TYPE_UNKNOWN = 0, + OSSIM_TIFF_STRIP = 1, + OSSIM_TIFF_STRIP_BAND_SEPARATE = 2, + OSSIM_TIFF_TILED = 3, + OSSIM_TIFF_TILED_BAND_SEPARATE = 4, + OSSIM_GENERAL_RASTER_BIP = 5, + OSSIM_GENERAL_RASTER_BIL = 6, + OSSIM_GENERAL_RASTER_BSQ = 7, + OSSIM_JPEG = 8 +}; + +/** Definitions for metadata type identification. */ +enum ossimMetadataType +{ + OSSIM_META_UNKNOWN = 0, + OSSIM_META_TFW = 1, + OSSIM_META_JGW = 2, + OSSIM_META_GEOM = 3, + OSSIM_META_README = 4, + OSSIM_META_FGDC = 5, + OSSIM_META_ENVI = 6 +}; + +enum ossimByteOrder +{ + OSSIM_LITTLE_ENDIAN = 0, + OSSIM_BIG_ENDIAN = 1 +}; + +#ifndef M_PI +# define M_PI ((ossim_float64)3.141592653589793238462643) +#endif +#ifndef TWO_PI +# define TWO_PI ((ossim_float64)(2.0 * M_PI)) +#endif +#ifndef DEG_PER_RAD +# define DEG_PER_RAD ((ossim_float64)(180.0/M_PI)) +#endif +#ifndef SEC_PER_RAD +# define SEC_PER_RAD ((ossim_float64)206264.8062471) +#endif +#ifndef RAD_PER_DEG +# define RAD_PER_DEG ((ossim_float64)(M_PI/180.0)) +#endif +#ifndef MTRS_PER_FT +# define MTRS_PER_FT ((ossim_float64)0.3048) +#endif +#ifndef FT_PER_MTRS +# define FT_PER_MTRS ((ossim_float64)3.280839895013122) +#endif +#ifndef FT_PER_MILE +# define FT_PER_MILE ((ossim_float64)5280.0) +#endif +#ifndef SQRT_TWO_PI +# define SQRT_TWO_PI ((ossim_float64)2.50662827463100050242) +#endif +#ifndef SQRT_TWO_PI_DIV2 +# define SQRT_TWO_PI_DIV2 ((ossim_float64)7.07106781186547524401E-1) +#endif + +#define OSSIM_DEFAULT_TILE_HEIGHT ((ossim_int32)64) +#define OSSIM_DEFAULT_TILE_WIDTH ((ossim_int32)64) + +/* + NOTE Reference for U.S. feet value: + U.S.G.S. "Map Projections - A Working Manual" + USGS Professional paper 1395 page 51 +*/ +#ifndef US_METERS_PER_FT +# define US_METERS_PER_FT ((ossim_float64)0.3048006096) +#endif + +#define OSSIM_DBL_NAN ((ossim_float64)-1.0/DBL_EPSILON) +#define OSSIM_FLT_NAN ((ossim_float32)-1.0/FLT_EPSILON) +#define OSSIM_LONG_NAN ((ossim_sint32)0x80000000) +#define OSSIM_INT_NAN ((ossim_sint32)0x80000000) +#define OSSIM_ULONG_NAN ((ossim_uint32)0x0) +#define OSSIM_UINT_NAN ((ossim_uint32)0x0) +#define OSSIM_SSHORT_NAN ((ossim_sint16)0x8000) +#define OSSIM_USHORT_NAN ((ossim_uint16)0) + +#define OSSIM_DEFAULT_MIN_PIX_UCHAR ((ossim_uint8)1) +#define OSSIM_DEFAULT_MAX_PIX_UCHAR ((ossim_uint8)255) +#define OSSIM_DEFAULT_MIN_PIX_UINT8 ((ossim_uint8)1) +#define OSSIM_DEFAULT_MAX_PIX_UINT8 ((ossim_uint8)255) +#define OSSIM_DEFAULT_MIN_PIX_SINT8 ((ossim_sint8)0x81) +#define OSSIM_DEFAULT_MAX_PIX_SINT8 ((ossim_sint8)0x7F) +#define OSSIM_DEFAULT_MIN_PIX_SINT16 ((ossim_sint16)0x8001) +#define OSSIM_DEFAULT_MAX_PIX_SINT16 ((ossim_sint16)0x7FFF) +#define OSSIM_DEFAULT_MIN_PIX_UINT16 ((ossim_uint16)1) +#define OSSIM_DEFAULT_MAX_PIX_UINT16 ((ossim_uint16)0xFFFF) +#define OSSIM_DEFAULT_MIN_PIX_SINT32 ((ossim_sint32)0x80000001) +#define OSSIM_DEFAULT_MAX_PIX_SINT32 ((ossim_sint32)0x7FFFFFFF) +#define OSSIM_DEFAULT_MIN_PIX_UINT32 ((ossim_uint32)1) +#define OSSIM_DEFAULT_MAX_PIX_UINT32 ((ossim_uint32)0xFFFFFFFF) +#define OSSIM_DEFAULT_MIN_PIX_UINT11 ((ossim_uint16)1) +#define OSSIM_DEFAULT_MAX_PIX_UINT11 ((ossim_uint16)0x07FF) +#define OSSIM_DEFAULT_MIN_PIX_FLOAT ((ossim_float32)((-1.0/FLT_EPSILON) + 1)) +#define OSSIM_DEFAULT_MAX_PIX_FLOAT ((ossim_float32)((1.0/FLT_EPSILON))) +#define OSSIM_DEFAULT_MIN_PIX_NORM_FLOAT ((ossim_float32)((2*FLT_EPSILON))) +#define OSSIM_DEFAULT_MAX_PIX_NORM_FLOAT ((ossim_float32)1.0) +#define OSSIM_DEFAULT_MIN_PIX_DOUBLE ((ossim_float64)((-1.0/DBL_EPSILON) + 1)) +#define OSSIM_DEFAULT_MAX_PIX_DOUBLE ((ossim_float64)((1.0/DBL_EPSILON))) +#define OSSIM_DEFAULT_MIN_PIX_NORM_DOUBLE ((ossim_float64)((2*DBL_EPSILON))) +#define OSSIM_DEFAULT_MAX_PIX_NORM_DOUBLE ((ossim_float64)(1.0)) + + +/* + *OSSIM Numerical Limits + */ +#ifndef _OSSIM_LIMITS_ +#define _OSSIM_LIMITS_ +#define OSSIM_INFINITY ((ossim_float64)((1.0 / DBL_EPSILON) - 1.0)) +#define OSSIM_NAN ((ossim_float64)(-(1.0 / DBL_EPSILON))) +#define OSSIM_EPSILON ((ossim_float64)(DBL_EPSILON)) +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimCplUtil.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimCplUtil.cpp new file mode 100644 index 0000000000..6ac6f2531e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimCplUtil.cpp @@ -0,0 +1,297 @@ +/* + * Copied from "gdal" project. See licence below. + * + * Global functions for gdal code compatibility. + * + * Project: ISO 8211 Access + * Purpose: Main declarations for ISO 8211. + * Author: Frank Warmerdam, warmerdam@pobox.com + * + ****************************************************************************** + * Copyright (c) 1999, Frank Warmerdam <warmerdam@pobox.com> + * + * 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 above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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. + ****************************************************************************** + * $Id& + */ + +#include <base/common/ossimCplUtil.h> +#include <base/data_types/ossimString.h> + +#ifndef OSSIM_CSLT_HONOURSTRINGS +# define OSSIM_CSLT_HONOURSTRINGS 0x0001 +#endif +#ifndef OSSIM_CSLT_ALLOWEMPTYTOKENS +# define OSSIM_CSLT_ALLOWEMPTYTOKENS 0x0002 +#endif +#ifndef OSSIM_CSLT_PRESERVEQUOTES +# define OSSIM_CSLT_PRESERVEQUOTES 0x0004 +#endif +#ifndef OSSIM_CSLT_PRESERVEESCAPES +# define OSSIM_CSLT_PRESERVEESCAPES 0x0008 +#endif + +/************************************************************************/ +/* ossimCSLFindString() */ +/* */ +/* Find a string within a string list. The string must match */ +/* the full length, but the comparison is case insensitive. */ +/* Return -1 on failure. */ +/************************************************************************/ + +int ossimCSLFindString( char ** papszList, const char * pszTarget ) + +{ + int i; + + if( papszList == NULL ) + return -1; + + for( i = 0; papszList[i] != NULL; i++ ) + { + ossimString s = papszList[i]; + if( s == pszTarget) + return i; + } + + return -1; +} + +/********************************************************************** + * ossimCSLTokenizeString() + * + * Tokenizes a string and returns a StringList with one string for + * each token. + **********************************************************************/ + +char **ossimCSLTokenizeString( const char *pszString ) +{ + return ossimCSLTokenizeString2( pszString, " ", OSSIM_CSLT_HONOURSTRINGS ); +} + +/************************************************************************/ +/* ossimCSLTokenizeStringComplex() */ +/* */ +/* Obsolete tokenizing api. */ +/************************************************************************/ + +char ** ossimCSLTokenizeStringComplex( const char * pszString, + const char * pszDelimiters, + int bHonourStrings, + int bAllowEmptyTokens ) + +{ + int nFlags = 0; + + if( bHonourStrings ) + nFlags |= OSSIM_CSLT_HONOURSTRINGS; + if( bAllowEmptyTokens ) + nFlags |= OSSIM_CSLT_ALLOWEMPTYTOKENS; + + return ossimCSLTokenizeString2( pszString, pszDelimiters, nFlags ); +} + +/************************************************************************/ +/* ossimCSLTokenizeString2() */ +/* */ +/* The ultimate tokenizer? */ +/************************************************************************/ + +char ** ossimCSLTokenizeString2( const char * pszString, + const char * pszDelimiters, + int nCSLTFlags ) + +{ + char **papszRetList = NULL; + int nRetMax = 0, nRetLen = 0; + char *pszToken; + int nTokenMax, nTokenLen; + int bHonourStrings = (nCSLTFlags & OSSIM_CSLT_HONOURSTRINGS); + int bAllowEmptyTokens = (nCSLTFlags & OSSIM_CSLT_ALLOWEMPTYTOKENS); + + pszToken = (char *) calloc(10,1); + nTokenMax = 10; + + while( pszString != NULL && *pszString != '\0' ) + { + int bInString = false; + + nTokenLen = 0; + + /* Try to find the next delimeter, marking end of token */ + for( ; *pszString != '\0'; pszString++ ) + { + + /* End if this is a delimeter skip it and break. */ + if( !bInString && strchr(pszDelimiters, *pszString) != NULL ) + { + pszString++; + break; + } + + /* If this is a quote, and we are honouring constant + strings, then process the constant strings, with out delim + but don't copy over the quotes */ + if( bHonourStrings && *pszString == '"' ) + { + if( nCSLTFlags & OSSIM_CSLT_PRESERVEQUOTES ) + { + pszToken[nTokenLen] = *pszString; + nTokenLen++; + } + + if( bInString ) + { + bInString = false; + continue; + } + else + { + bInString = true; + continue; + } + } + + /* Within string constants we allow for escaped quotes, but + in processing them we will unescape the quotes */ + if( bInString && pszString[0] == '\\' && pszString[1] == '"' ) + { + if( nCSLTFlags & OSSIM_CSLT_PRESERVEESCAPES ) + { + pszToken[nTokenLen] = *pszString; + nTokenLen++; + } + + pszString++; + } + + /* Within string constants a \\ sequence reduces to \ */ + else if( bInString + && pszString[0] == '\\' && pszString[1] == '\\' ) + { + if( nCSLTFlags & OSSIM_CSLT_PRESERVEESCAPES ) + { + pszToken[nTokenLen] = *pszString; + nTokenLen++; + } + pszString++; + } + + if( nTokenLen >= nTokenMax-3 ) + { + nTokenMax = nTokenMax * 2 + 10; + pszToken = (char *) ossimCPLRealloc( pszToken, nTokenMax ); + } + + pszToken[nTokenLen] = *pszString; + nTokenLen++; + } + + pszToken[nTokenLen] = '\0'; + + /* + * If the last token is an empty token, then we have to catch + * it now, otherwise we won't reenter the loop and it will be lost. + */ + + if( (pszToken[0] != '\0' || bAllowEmptyTokens) + || (*pszString == '\0' && bAllowEmptyTokens + && strchr(pszDelimiters, *(pszString-1)) ) ) + { + if( nRetLen >= nRetMax - 1 ) + { + nRetMax = nRetMax * 2 + 10; + papszRetList = (char **) + ossimCPLRealloc(papszRetList, sizeof(char*) * nRetMax ); + } + + papszRetList[nRetLen++] = strdup( pszToken ); + papszRetList[nRetLen] = NULL; + } + } + + if( papszRetList == NULL ) + papszRetList = (char **) calloc(sizeof(char *),1); + + free( pszToken ); + + return papszRetList; +} + +/********************************************************************** + * ossimCSLCount() + * + * Return the number of lines in a Stringlist. + **********************************************************************/ +int ossimCSLCount(char **papszStrList) +{ + int nItems=0; + + if (papszStrList) + { + while(*papszStrList != NULL) + { + nItems++; + papszStrList++; + } + } + + return nItems; +} + +/********************************************************************** + * ossimCSLDestroy() + * + * Free all memory used by a StringList. + **********************************************************************/ +void ossimCSLDestroy(char **papszStrList) +{ + char **papszPtr; + + if (papszStrList) + { + papszPtr = papszStrList; + while(*papszPtr != NULL) + { + free(*papszPtr); + papszPtr++; + } + + free(papszStrList); + } +} + +void * ossimCPLRealloc( void * pData, size_t nNewSize ) + +{ + void *pReturn; + + if ( nNewSize == 0 ) + { + free(pData); + return NULL; + } + + if( pData == NULL ) + pReturn = malloc( nNewSize ); + else + pReturn = realloc( pData, nNewSize ); + + return pReturn; +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimCplUtil.h b/Utilities/OSSIM/ossim_core/base/common/ossimCplUtil.h new file mode 100644 index 0000000000..d3e8bc0582 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimCplUtil.h @@ -0,0 +1,58 @@ +/* + * Copied from "gdal" project. See licence below. + * + * Global functions for gdal code compatibility. + * + * Project: ISO 8211 Access + * Purpose: Main declarations for ISO 8211. + * Author: Frank Warmerdam, warmerdam@pobox.com + * + ****************************************************************************** + * Copyright (c) 1999, Frank Warmerdam <warmerdam@pobox.com> + * + * 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 above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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. + ****************************************************************************** + * $Id& + */ + +#ifndef ossimCplUtil_HEADER +#define ossimCplUtil_HEADER + +#include <cstdio> /* to pick up "size_t" */ +#include <base/common/ossimConstants.h> /* for dll export */ + + +OSSIMDLLEXPORT char** ossimCSLTokenizeString(const char *pszString ); + +OSSIMDLLEXPORT char** ossimCSLTokenizeStringComplex(const char *pszString, + const char *pszDelimiter, + int bHonourStrings, + int bAllowEmptyTokens ); + +OSSIMDLLEXPORT char** ossimCSLTokenizeString2( const char *pszString, + const char *pszDelimeter, + int nCSLTFlags ); + +OSSIMDLLEXPORT int ossimCSLCount(char **papszStrList); + +OSSIMDLLEXPORT void ossimCSLDestroy(char **papszStrList); + +OSSIMDLLEXPORT void* ossimCPLRealloc( void * pData, size_t nNewSize ); + +#endif /* ossimCplUtil_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimCustomEditorWindow.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimCustomEditorWindow.cpp new file mode 100644 index 0000000000..476f56d98a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimCustomEditorWindow.cpp @@ -0,0 +1,26 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimCustomEditorWindow.cpp,v 1.1 2002/04/02 17:18:03 gpotts Exp $ +#include "ossimCustomEditorWindow.h" +RTTI_DEF1(ossimCustomEditorWindow, "ossimCustomEditorWindow", ossimObject); + diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimCustomEditorWindow.h b/Utilities/OSSIM/ossim_core/base/common/ossimCustomEditorWindow.h new file mode 100644 index 0000000000..717381e3cd --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimCustomEditorWindow.h @@ -0,0 +1,71 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimCustomEditorWindow.h,v 1.7 2002/11/25 18:45:47 gpotts Exp $ +#ifndef ossimCustomEditorWindow_HEADER +#define ossimCustomEditorWindow_HEADER +#include "base/common/ossimObject.h" + +class OSSIMDLLEXPORT ossimCustomEditorWindow : public ossimObject +{ +public: + /*! + * Returns the system dependent window. If you are in wx it + * will probalby be some type of wxWindow*. + */ + virtual void* getWindow()=0; + + /*! + * This is the parent window. If the parent can be + * set by the derived classes it will return true. + */ + virtual void setParent(void* parent)=0; + + /*! + * Will return the parent of the managed wxWindow + */ + virtual void* getParent()=0; + + /*! + * WIll set the object to edit. If this editor does not know + * anything about the passed in obj it will return false. + */ + virtual bool setObjectToEdit(ossimObject* obj)=0; + + /*! + * Just asks if I can edit the passed in object. + */ + virtual bool canEdit(ossimObject* obj)const=0; + + /*! + * Returns the object we are editing. + */ + virtual ossimObject* getObject()=0; + +protected: + ossimCustomEditorWindow(){} + ossimCustomEditorWindow(const ossimCustomEditorWindow&){} + void operator =(const ossimCustomEditorWindow& rhs){} + +TYPE_DATA +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimDataObject.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimDataObject.cpp new file mode 100644 index 0000000000..88281b8959 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimDataObject.cpp @@ -0,0 +1,154 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimDataObject.cpp,v 1.10 2005/04/20 15:10:28 dburken Exp $ +#include "ossimDataObject.h" +#include "base/common/ossimSource.h" +#include "base/misc/lookup_tables/ossimScalarTypeLut.h" + +RTTI_DEF1(ossimDataObject, "ossimDataObject", ossimObject) + +ossimDataObject::ossimDataObject(ossimSource* source, + ossimDataObjectStatus status) + : + theOwner(source), + theDataObjectStatus(status) +{ +} + +ossimDataObject::ossimDataObject(const ossimDataObject& rhs) + : ossimObject(), + theOwner(NULL), + theDataObjectStatus(rhs.theDataObjectStatus) +{ +} + +ossimDataObject::~ossimDataObject() +{ +} + +void ossimDataObject::setOwner(ossimSource* aSource) +{ + theOwner = aSource; +} + +ossimSource* ossimDataObject::getOwner() +{ + return theOwner; +} + +const ossimSource* ossimDataObject::getOwner() const +{ + return theOwner; +} + +void ossimDataObject::setDataObjectStatus(ossimDataObjectStatus status) const +{ + theDataObjectStatus = status; +} + +ossimDataObjectStatus ossimDataObject::getDataObjectStatus()const +{ + return theDataObjectStatus; +} + +ossimString ossimDataObject::getDataObjectStatusString() const +{ + ossimString s; + + switch (theDataObjectStatus) + { + case OSSIM_NULL: + s = "OSSIM_NULL"; + break; + + case OSSIM_EMPTY: + s = "OSSIM_EMPTY"; + break; + + case OSSIM_PARTIAL: + s = "OSSIM_PARTIAL"; + break; + + case OSSIM_FULL: + s = "OSSIM_FULL"; + break; + + case OSSIM_STATUS_UNKNOWN: + default: + s = "OSSIM_STATUS_UNKNOWN"; + break; + } + + return s; +} + +ossim_uint32 ossimDataObject::getObjectSizeInBytes()const +{ + return sizeof(theOwner); +} + +bool ossimDataObject::isInitialize()const +{ + return (getDataObjectStatus()!=OSSIM_NULL); +} + +bool ossimDataObject::operator!=(const ossimDataObject& rhs) const +{ + return ( theOwner != rhs.theOwner || + theDataObjectStatus != rhs.theDataObjectStatus ); +} + +bool ossimDataObject::operator==(const ossimDataObject& rhs) const +{ + return (theOwner == rhs.theOwner && + theDataObjectStatus == rhs.theDataObjectStatus); +} + +void ossimDataObject::assign(const ossimDataObject* rhs) +{ + if(rhs != this) + { + theOwner = rhs->theOwner; + theDataObjectStatus = rhs->theDataObjectStatus; + } +} + +const ossimDataObject* ossimDataObject::operator=(const ossimDataObject* rhs) +{ + assign(rhs); + return this; +} + +const ossimDataObject& ossimDataObject::operator=(const ossimDataObject& rhs) +{ + assign(&rhs); + return *this; +} + +std::ostream& ossimDataObject::print(ostream& out) const +{ + out << "ossimDataObject::print:"; + + if (theOwner) + { + out << "\ntheOwner->getClassName(): " + << theOwner->getClassName()<<endl; + } + else + { + out << "\ntheOwner is null" + <<endl; + } + out << "theDataObjectStatus: " << getDataObjectStatusString() + << endl; + + return out; +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimDataObject.h b/Utilities/OSSIM/ossim_core/base/common/ossimDataObject.h new file mode 100644 index 0000000000..d2e2f3cac6 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimDataObject.h @@ -0,0 +1,126 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimDataObject.h,v 1.19 2005/04/20 15:10:28 dburken Exp $ + +#ifndef ossimDataObject_HEADER +#define ossimDataObject_HEADER + +#include "ossimObject.h" +#include "base/common/ossimConstants.h" +#include "base/data_types/ossimDpt3d.h" + +class OSSIMDLLEXPORT ossimSource; + +class OSSIMDLLEXPORT ossimDataObject : public ossimObject +{ +public: + ossimDataObject(ossimSource* source=0, + ossimDataObjectStatus status=OSSIM_STATUS_UNKNOWN); + + ossimDataObject(const ossimDataObject& rhs); + + virtual ~ossimDataObject(); + + + virtual ossim_uint32 getHashId()const=0; + + /** + * Sets the owner of this Data object. + */ + virtual void setOwner(ossimSource* aSource); + + virtual ossimSource* getOwner(); + + virtual const ossimSource* getOwner() const; + + /** + * Full list found in ossimConstants.h + * + * OSSIM_STATUS_UNKNOWN + * OSSIM_NULL Null data. The buffers are never allocated + * OSSIM_EMPTY Allocated data but its empty. Most of the + * time this will be the default for an initialized + * data object. + * OSSIM_PARTIAL Says that some of the object is empty and is only + * partially full + * OSSIM_FULL This data is completey full + */ + virtual void setDataObjectStatus(ossimDataObjectStatus status) const; + + /** + * @return Returns enumerated status: + * OSSIM_STATUS_UNKNOWN = 0 + * OSSIM_NULL = 1 + * OSSIM_EMPTY = 2 + * OSSIM_PARTIAL = 3 + * OSSIM_FULL = 4 + */ + virtual ossimDataObjectStatus getDataObjectStatus() const; + + /** + * @return Returns the status as a string, like "OSSIM_NULL". + */ + virtual ossimString getDataObjectStatusString() const; + + virtual ossim_uint32 getObjectSizeInBytes()const; + + virtual ossim_uint32 getDataSizeInBytes()const=0; + + /** + * This is to be overriden in the derived classes so they can check + * If their data is null. + */ + virtual bool isInitialize() const; + + /** + * Will allow derived classes to initialize their buffers. This class + * does nothing with this and reset any internal attributes. + */ + virtual void initialize()=0; + + virtual void assign(const ossimDataObject* rhs); + + /** + * Derived classes should implement this method. For data objects + * there is usually 2 types of tests a shallow and a deep test. If + * deepTest is false then a shallow test is performed. I shallow test + * just doesn't compare the data but instead compares the fields that + * describes the data. For example if it were an ossimImageData then a + * shallow compare will just compare the origin, scale, width, height, + * number of bands, min, max, null, and scalar type. If + * it were a deep compare it will also test the actual data to one another. + */ + virtual bool isEqualTo(const ossimDataObject& rhs, + bool deepTest=false)const=0; + + virtual const ossimDataObject* operator =(const ossimDataObject* rhs); + + virtual const ossimDataObject& operator=(const ossimDataObject& rhs); + + virtual bool operator==(const ossimDataObject& rhs) const; + virtual bool operator!=(const ossimDataObject& rhs) const; + + virtual std::ostream& print(std::ostream& out) const; + +protected: + + //*** + // Note: This object is not responsible for deletion of the ossimSource* + // "theSource". It is simply a hook to his owner for things + // like unregister and so forth... + //*** + ossimSource* theOwner; + mutable ossimDataObjectStatus theDataObjectStatus; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimDate.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimDate.cpp new file mode 100644 index 0000000000..445263b11c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimDate.cpp @@ -0,0 +1,536 @@ +#include <base/common/ossimDate.h> +#include <iomanip> +#include <sstream> + + +std::ostream& operator<< (std::ostream& out, const ossimDate& src) +{ + return src.print(out); +} + +std::ostream& operator<< (std::ostream & os, ossimLocalTm const & t) +{ + return t.print(os); +} + +int operator== (ossimLocalTm const & t1, ossimLocalTm const & t2) +{ + return int(t1.compare(t2) == 0); +} + +int operator!= (ossimLocalTm const & t1, ossimLocalTm const & t2) +{ + return int(t1.compare(t2) != 0); +} + +int operator< (ossimLocalTm const & t1, ossimLocalTm const & t2) +{ + return int(t1.compare(t2) < 0); +} + +int operator<= (ossimLocalTm const & t1, ossimLocalTm const & t2) +{ + return int(t1.compare(t2) <= 0); +} + +int operator> (ossimLocalTm const & t1, ossimLocalTm const & t2) +{ + return int(t1.compare(t2) > 0); +} + +int operator>= (ossimLocalTm const & t1, ossimLocalTm const & t2) +{ + return int(t1.compare(t2) >= 0); +} + +char ossimLocalTm::timech = ':'; +char ossimLocalTm::datech = '/'; + +int ossimLocalTm::datefmt = ossimLocalTm::ossimLocalTmFormatIntlShort; +int ossimLocalTm::timefmt = ossimLocalTm::ossimTimeFormatInternational; + + +ossimLocalTm::ossimLocalTm (time_t t) +{ + if (t == 0) + t = time(0); + *(tm *)this = *localtime(&t); +} + +ossimLocalTm::ossimLocalTm (tm const & t) +{ + *((tm *)this) = t; +} + +ossimLocalTm& ossimLocalTm::operator= (tm const & t) +{ + *((tm *)this) = t; + return *this; +} + +int ossimLocalTm::compare (ossimLocalTm const & t) const +{ + return compare ((time_t)t); +} + +int ossimLocalTm::compare (time_t const tt) const +{ + time_t tx = (time_t)*this; + return (tx == tt) ? 0 : (tx > tt) ? 1 : -1; +} + +ossimLocalTm::operator time_t (void) const +{ + return mktime ((tm *)this); +} + +int ossimLocalTm::isValid (void) const +{ + static int maxd[] = + { + 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 + }; + + return (tm_year > 0 && + tm_mon >= 0 && tm_mon < 12 && + tm_mday > 0 && tm_mday <= maxd[tm_mon] && + tm_wday < 7 && tm_yday < 367 && + tm_sec < 60 && tm_min < 60 && tm_hour < 24); +} + +void ossimLocalTm::dSfx (std::ostream & os, int fmt) const +{ + if (fmt & ossimLocalTmFormatSepChar) + os << datech; + if (fmt & ossimLocalTmFormatSepSpace) + os << ' '; +} + +void ossimLocalTm::pYear (std::ostream & os, int fmt) const +{ + if (fmt & ossimLocalTmFormatYear) + { + int year = tm_year; + int dig; + if (fmt & ossimLocalTmFormatYearShort) + { + dig = 2; + year %= 100; + } + else + { + dig = 4; + if (year < 200) + year += 1900; + } + os << std::setw((fmt & ossimLocalTmFormatPadYear) ? dig : 0); + os << std::setfill((fmt & ossimLocalTmFormatZeroYear) ? '0' : ' '); + os << year; + if ((fmt & ossimLocalTmFormatYearFirst)) + { + fmt &= (ossimLocalTmFormatSepChar|ossimLocalTmFormatSepSpace); + dSfx (os, fmt); + } + } +} + +void ossimLocalTm::pMonth (std::ostream & os, int fmt) const +{ + + static const char * _months[] = + { + "January", "February", "March", "April", + "May", "June", "July", "August", "September", + "October", "November", "December" + }; + + if (fmt & ossimLocalTmFormatMonth) + { + int mon = (tm_mon % 12); + if (fmt & ossimLocalTmFormatMonText) + { + char const * tmon = _months[mon]; + if (!(fmt & ossimLocalTmFormatPadMon)) + os << tmon; + else + for (int x = 0; x < 3; ++x) + os << tmon[x]; + } + else + { + ++mon; + os << std::setw((fmt & ossimLocalTmFormatPadMon) ? 2 : 0); + os << std::setfill((fmt & ossimLocalTmFormatZeroMon) ? '0' : ' '); + os << mon; + } + if (((fmt & ossimLocalTmFormatYear) && !(fmt & ossimLocalTmFormatYearFirst)) || + ((fmt & ossimLocalTmFormatDay) && (fmt & ossimLocalTmFormatMonFirst))) + { + fmt &= (ossimLocalTmFormatSepChar|ossimLocalTmFormatSepSpace); + dSfx (os, fmt); + } + } +} + + +void ossimLocalTm::pDate (std::ostream & os, int fmt) const +{ + if (fmt & ossimLocalTmFormatDay) + { + int day = tm_mday; + os << std::setw((fmt & ossimLocalTmFormatPadDay) ? 2 : 0); + os << std::setfill((fmt & ossimLocalTmFormatZeroDay) ? '0' : ' '); + os << day; + if (!(fmt & ossimLocalTmFormatYearFirst) || !(fmt & ossimLocalTmFormatMonFirst)) + { + fmt &= (ossimLocalTmFormatSepChar|ossimLocalTmFormatSepSpace); + dSfx (os, fmt); + } + } +} + +std::ostream& ossimLocalTm::print(std::ostream & os, + int df, + int tf) const +{ + std::ostringstream pTmp; + printDate (pTmp, df); + pTmp << ' '; + printTime (pTmp, tf); + + return os << pTmp.str(); +} + +std::ostream& ossimLocalTm::printDate (std::ostream & os, int fmt) const +{ + std::ostringstream pTmp; + + static const char * _days[] = + { + "Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday" + }; + + if (fmt & ossimLocalTmFormatDayOfWeek) + { + int day = tm_wday % 7; + char const * p = _days[day]; + if (fmt & ossimLocalTmFormatPadDay) + for (int x = 0; x < 3; ++x) + pTmp << p[x]; + else + { + pTmp << p; + if (fmt & ossimLocalTmFormatDMY) + pTmp << ','; + } + if ((fmt & ossimLocalTmFormatDMY) && fmt & ossimLocalTmFormatSepSpace) + pTmp << ' '; + } + if (fmt & ossimLocalTmFormatYearFirst) + pYear (pTmp, fmt); + if (fmt & ossimLocalTmFormatMonFirst) + pMonth (pTmp, fmt); + pDate (pTmp, fmt); + if (!(fmt & ossimLocalTmFormatMonFirst)) + pMonth (pTmp, fmt); + if (!(fmt & ossimLocalTmFormatYearFirst)) + pYear (pTmp, fmt); + + return os << pTmp.str(); +} +void ossimLocalTm::tSfx (std::ostream & os, int fmt, char ch) const +{ + if (fmt & ossimTimeFormatSepAbbrev) + os << ch; + if (fmt & ossimTimeFormatSepChar) + os << timech; + if (fmt & ossimTimeFormatSepSpace) + os << ' '; +} + +void ossimLocalTm::pHour (std::ostream & os, int fmt) const +{ + if (fmt & ossimTimeFormatHour) + { + int hour = tm_hour; + if (!(fmt & ossimTimeFormat24hour)) + { + if (hour > 12) + hour -= 12; + else if (!hour && (fmt & ossimTimeFormatAmPm)) + hour += 12; + } + os << std::setw((fmt & ossimTimeFormatPadHour) ? 2 : 0); + os << std::setfill((fmt & ossimTimeFormatZeroHour) ? '0' : ' '); + os << hour; + if (!(fmt & ossimTimeFormatMins)) + fmt &= ossimTimeFormatSepAbbrev; + tSfx (os, fmt, 'h'); + } +} + +void ossimLocalTm::pMins (std::ostream & os, int fmt) const +{ + if (fmt & ossimTimeFormatMins) + { + int min = tm_min; + int dig = 2; + if (!(fmt & ossimTimeFormatHour)) + { + min += (tm_hour * 60); + dig += 2; + } + os << std::setw((fmt & ossimTimeFormatPadMins) ? dig : 0); + os << std::setfill((fmt & ossimTimeFormatZeroMins) ? '0' : ' '); + os << min; + if (!(fmt & ossimTimeFormatSecs)) + fmt &= ossimTimeFormatSepAbbrev; + tSfx (os, fmt, 'm'); + } +} + +void ossimLocalTm::pSecs (std::ostream & os, int fmt) const +{ + if (fmt & ossimTimeFormatSecs) + { + int sec = tm_sec; + int dig = 2; + if (!(fmt & (ossimTimeFormatHour|ossimTimeFormatMins))) + { + sec += ((tm_hour * 60) + tm_min) + 60; + dig += 3; + } + os << std::setw((fmt & ossimTimeFormatPadSecs) ? dig : 0); + os << std::setfill((fmt & ossimTimeFormatZeroSecs) ? '0' : ' '); + os << sec; + if (fmt & ossimTimeFormatAmPm) + fmt &= ~ossimTimeFormatSepChar; + else + fmt &= (ossimTimeFormatSepAbbrev|ossimTimeFormatSepSpace); + tSfx (os, fmt, 's'); + } +} + +std::ostream &ossimLocalTm::printTime (std::ostream & os, int fmt) const +{ + std::ostringstream pTmp; + pHour (pTmp, fmt); + pMins (pTmp, fmt); + pSecs (pTmp, fmt); + if (fmt & ossimTimeFormatAmPm) + { + pTmp << (tm_hour > 11 ? "pm" : "am"); + } + + return os << pTmp.str(); +} + + +int ossimLocalTm::getYear()const +{ + int result = tm_year; + if (result < 200) + { + result += 1900; + } + return result; +} + +int ossimLocalTm::getShortYear()const +{ + return (getYear()%100); +} + +int ossimLocalTm::getMonth()const +{ + return ((tm_mon % 12)+1); +} + +int ossimLocalTm::getDay()const +{ + return tm_mday; +} + +double ossimLocalTm::getJulian()const +{ + int J = getMonth(); + int K = getDay(); + int I = getYear(); + + return K-32075+1461*(I+4800+(J-14)/12)/4+367*(J-2-(J-14)/12*12) + /12-3*((I+4900+(J-14)/12)/100)/4+ + (getHour()/24.0)+ + (getMin()/1440.0)+ + (getSec()/86400.0); +} + +double ossimLocalTm::getModifiedJulian()const +{ + return getJulian() - 2400000.5; +} + +ossimLocalTm& ossimLocalTm::setDay(int day) +{ + tm_mday = day; + + return *this; +} + +ossimLocalTm& ossimLocalTm::setMonth(int month) +{ + tm_mon = month - 1; + + return *this; +} + +ossimLocalTm& ossimLocalTm::setYear(int year) +{ + if(year < 2099) + { + tm_year = year - 1900; + } + else + { + tm_year = year; + } + + return *this; +} + +ossimLocalTm& ossimLocalTm::setDateFromJulian(double jd) +{ + double fractional = jd - (long)jd; + long l; + long n; + long i; + long j; + long k; + + + l= (long)(jd+68569); + n= 4*l/146097; + l= l-(146097*n+3)/4; + i= 4000*(l+1)/1461001; + l= l-1461*i/4+31l; + j= 80*l/2447; + k= l-2447*j/80; + l= j/11; + j= j+2-12*l; + i= 100*(n-49)+i+l; + setDay(k); + setMonth(j); + setYear(i); + + setFractionalDay(fractional); + + return *this; +} + +ossimLocalTm& ossimLocalTm::setDateFromModifiedJulian(double mjd) +{ + setDateFromJulian(mjd + 2400000.5); + + return *this; +} + +void ossimLocalTm::setFractionalDay(double fractionalDay) +{ + int h, m, s; + extractHmsFromFractionalDay(fractionalDay, h, m, s); + + setHour(h); + setMin(m); + setSec(s); +} + +void ossimLocalTm::extractHmsFromFractionalDay(double fractionalDay, + int &h, + int &m, + int &s) +{ + fractionalDay *=24; + h = (int)fractionalDay; + fractionalDay = fractionalDay-h; + fractionalDay*=60; + m = (int)fractionalDay; + fractionalDay = fractionalDay-m; + fractionalDay*=60; + s = (int)fractionalDay; +} + +int ossimLocalTm::getHour()const +{ + return tm_hour; +} + +int ossimLocalTm::getMin()const +{ + return tm_min; +} + +int ossimLocalTm::getSec()const +{ + return tm_sec; +} + +ossimLocalTm& ossimLocalTm::setHour(int h) +{ + tm_hour = h; + + return *this; +} + +ossimLocalTm& ossimLocalTm::setMin(int m) +{ + tm_min = m; + + return *this; +} + +ossimLocalTm& ossimLocalTm::setSec(int s) +{ + tm_sec = s; + + return *this; +} + +std::ostream& ossimDate::print (std::ostream & os) const +{ + return printDate (os, _fmt); +} + + +std::ostream& operator <<(std::ostream& out, const ossimTime& src) +{ + return src.print(out); +} +ossimTime::ossimTime(int tmfmt) + : ossimLocalTm(0), _fmt(tmfmt) +{ +} +ossimTime::ossimTime(ossimTime const & t, + int tmfmt) + : ossimLocalTm (t), _fmt(tmfmt) +{ +} + +ossimTime::ossimTime(time_t t, int tmfmt) + : ossimLocalTm (t), _fmt(tmfmt) +{ +} + +int ossimTime::fmt(int f) +{ + return _fmt = f; +} + +int ossimTime::fmt(void) const +{ + return _fmt; +} + +std::ostream& ossimTime::print (std::ostream & os) const +{ + return printTime(os, _fmt); +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimDate.h b/Utilities/OSSIM/ossim_core/base/common/ossimDate.h new file mode 100644 index 0000000000..63f283dd9d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimDate.h @@ -0,0 +1,241 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossimDate.h,v 1.12 2005/07/13 12:31:06 gpotts Exp $ +#ifndef ossimDate_HEADER +#define ossimDate_HEADER +#include <iostream> +#include <ctime> +#include <base/common/ossimConstants.h> + +class OSSIMDLLEXPORT ossimLocalTm : public std::tm +{ +public: + friend std::ostream& operator<< (std::ostream& out, const ossimLocalTm& src); + friend int operator== (const ossimLocalTm& t1, const ossimLocalTm& src); + friend int operator!= (const ossimLocalTm& t1, const ossimLocalTm& src); + friend int operator< (const ossimLocalTm& t1, const ossimLocalTm& src); + friend int operator<= (const ossimLocalTm& t1, const ossimLocalTm& src); + friend int operator> (const ossimLocalTm& t1, const ossimLocalTm& src); + friend int operator>= (const ossimLocalTm& t1, const ossimLocalTm& src); + + ossimLocalTm (time_t t=0); // Set to time, 0 is magic for 'now' + ossimLocalTm (tm const & t); // Copy constructor + + ossimLocalTm & operator= (tm const & t); // Assignment + operator time_t (void) const; // Conversion operator + + int isValid (void) const; // Test for validity + + int compare (ossimLocalTm const & t) const; // Compare times + int compare (std::time_t const tt) const; // Compare times + + enum ossimLocalTmFormat // Date format flags + { + ossimLocalTmFormatYear = (int)0x0001, // Print year + ossimLocalTmFormatYearShort = (int)0x0002, // Print last two digits + ossimLocalTmFormatPadYear = (int)0x0004, // Pad year to 2 or 4 + ossimLocalTmFormatZeroYear = (int)0x0008, // Zero fill year + ossimLocalTmFormatMonth = (int)0x0010, // Print month + ossimLocalTmFormatMonText = (int)0x0020, // Print month in text + ossimLocalTmFormatPadMon = (int)0x0040, // Pad to 2 (trunc to 3) + ossimLocalTmFormatZeroMon = (int)0x0080, // Zero fill month + ossimLocalTmFormatDay = (int)0x0100, // Print date + ossimLocalTmFormatDayOfWeek = (int)0x0200, // Print day of week + ossimLocalTmFormatPadDay = (int)0x0400, // Pad date to 2 + ossimLocalTmFormatZeroDay = (int)0x0800, // Zero fill day + ossimLocalTmFormatDMY = (int)0x0111, // Print date, mth, year + ossimLocalTmFormatPadDMY = (int)0x0444, // Pad all three + ossimLocalTmFormatZeroDMY = (int)0x0888, // Zero fill all three + ossimLocalTmFormatYearFirst = (int)0x1000, // Print year first + ossimLocalTmFormatMonFirst = (int)0x2000, // Print month first + ossimLocalTmFormatSepChar = (int)0x4000,// Separate fields datech + ossimLocalTmFormatSepSpace = (int)0x8000, // Separate fields space + ossimLocalTmFormatInternational = (int)(ossimLocalTmFormatDMY|ossimLocalTmFormatMonText|ossimLocalTmFormatPadMon| + ossimLocalTmFormatSepSpace), + ossimLocalTmFormatIntlShort = (int)(ossimLocalTmFormatDMY|ossimLocalTmFormatMonText|ossimLocalTmFormatPadMon| + ossimLocalTmFormatSepSpace|ossimLocalTmFormatYearShort), + ossimLocalTmFormatUsa = (int)(ossimLocalTmFormatDMY|ossimLocalTmFormatMonFirst|ossimLocalTmFormatPadDMY| + ossimLocalTmFormatZeroDMY|ossimLocalTmFormatYearShort|ossimLocalTmFormatSepChar), + ossimLocalTmFormatEnglish = (int)(ossimLocalTmFormatDMY|ossimLocalTmFormatYearShort|ossimLocalTmFormatPadDMY| + ossimLocalTmFormatZeroDMY|ossimLocalTmFormatSepChar), + ossimLocalTmFormatJapanese = (int)(ossimLocalTmFormatDMY|ossimLocalTmFormatYearFirst|ossimLocalTmFormatPadDMY| + ossimLocalTmFormatZeroDMY|ossimLocalTmFormatYearShort|ossimLocalTmFormatMonFirst| + ossimLocalTmFormatSepChar), + ossimLocalTmFormatFull = (int)(ossimLocalTmFormatDMY|ossimLocalTmFormatDayOfWeek|ossimLocalTmFormatMonText| + ossimLocalTmFormatSepSpace) + }; + + enum ossimTimeFormat // Time format (nb: time zones not implemented) + { + ossimTimeFormatSecs = (int)0x0001, // Print seconds + ossimTimeFormatZeroSecs = (int)0x0002, // Zero fill seconds + ossimTimeFormatPadSecs = (int)0x0004, // Pad seconds to 2 + ossimTimeFormatSecsAll = (int)0x0007, + ossimTimeFormatTimeZone = (int)0x0008, // Print timezone + ossimTimeFormatMins = (int)0x0010, // Print minutes + ossimTimeFormatZeroMins = (int)0x0020, // Zero fill minutes + ossimTimeFormatPadMins = (int)0x0040, // Pad minutes to 2 + ossimTimeFormatMinsAll = (int)0x0070, + ossimTimeFormatTZNumeric = (int)0x0080, // Print numeric TZ + ossimTimeFormatHour = (int)0x0100, // Print hour + ossimTimeFormatZeroHour = (int)0x0200, // Zero fill hour + ossimTimeFormatPadHour = (int)0x0400, // Pad hour to 2 digits + ossimTimeFormatHourAll = (int)0x0700, + ossimTimeFormat24hour = (int)0x0800, // 24hour clock + ossimTimeFormatSepChar = (int)0x1000, // Separate field timech + ossimTimeFormatSepSpace = (int)0x2000, // Separate fields space + ossimTimeFormatSepAbbrev = (int)0x4000, // Add abbreviations + ossimTimeFormatAmPm = (int)0x8000, // Add 'am' or 'pm' + ossimTimeFormatInternational = (int)(ossimTimeFormatHourAll|ossimTimeFormatMinsAll|ossimTimeFormatSecsAll| + ossimTimeFormat24hour|ossimTimeFormatSepChar), + ossimTimeFormatShortTime = (int)(ossimTimeFormatHourAll|ossimTimeFormatMinsAll|ossimTimeFormat24hour| + ossimTimeFormatSepChar), + ossimTimeFormatClockTime = (int)(ossimTimeFormatHour|ossimTimeFormatPadHour|ossimTimeFormatMinsAll| + ossimTimeFormatAmPm|ossimTimeFormatSepChar), + ossimTimeFormatLongTime = (int)(ossimTimeFormatHour|ossimTimeFormatPadHour|ossimTimeFormatMinsAll| + ossimTimeFormatSecsAll|ossimTimeFormatSepAbbrev|ossimTimeFormatSepSpace), + ossimTimeFormatMillitary = (int)(ossimTimeFormatHourAll|ossimTimeFormatMinsAll|ossimTimeFormat24hour) + }; + + + static char timech; // Character used for time separator + static char datech; // Character used for date separator + static int datefmt; // Default date format + static int timefmt; // Default time format + + // Output methods + std::ostream& print(std::ostream & os, + int df =datefmt, + int tf =timefmt) const; + std::ostream& printTime(std::ostream & os, int f =timefmt) const; + std::ostream& printDate(std::ostream & os, int f =datefmt) const; + + + int getYear()const; + + int getShortYear()const; + + /*! + * This is one based i.e. values are returned between 1-12 + */ + int getMonth()const; + + /*! + * returns the day 1-31 + */ + int getDay()const; + double getJulian()const; + double getModifiedJulian()const; + + ossimLocalTm& setDay(int day); + /*! + * The month is a number bewteen 1 and 12. We will shift it to the internal + * representation + */ + ossimLocalTm& setMonth(int month); + ossimLocalTm& setYear(int year); + ossimLocalTm& setDateFromJulian(double jd); + ossimLocalTm& setDateFromModifiedJulian(double mjd); + + void setFractionalDay(double fractionalDay); + static void extractHmsFromFractionalDay(double fractionalDay, + int &h, + int &m, + int &s); + int getHour()const; + int getMin()const; + int getSec()const; + ossimLocalTm& setHour(int h); + ossimLocalTm& setMin(int m); + ossimLocalTm& setSec(int s); + + + + protected: + // Time suffix + void tSfx(std::ostream & os, int fmt, char ch) const; + // Time field formatters + void pHour(std::ostream & os, int fmt) const; + void pMins(std::ostream & os, int fmt) const; + void pSecs(std::ostream & os, int fmt) const; + // Date suffix + void dSfx(std::ostream & os, int fmt) const; + // Date field formatters + void pDate(std::ostream & os, int fmt) const; + void pMonth(std::ostream & os, int fmt) const; + void pYear(std::ostream & os, int fmt) const; + +}; + + +class OSSIMDLLEXPORT ossimDate : public ossimLocalTm +{ + public: + friend std::ostream& operator<<(std::ostream& out, const ossimDate& src); + + ossimDate(int datefmt =ossimLocalTm::datefmt) + :ossimLocalTm(0), _fmt(datefmt) + {} + ossimDate (ossimLocalTm const & t, + int dtfmt =ossimLocalTm::datefmt) + : ossimLocalTm (t), _fmt(dtfmt) + {} + ossimDate (time_t t, int dtfmt =ossimLocalTm::datefmt) + : ossimLocalTm (t), _fmt(dtfmt) + {} + ossimDate(int month, int day, int year,int dtfmt=ossimLocalTm::datefmt) + :ossimLocalTm (0), _fmt(dtfmt) + { + setMonth(month); + setDay(day); + setYear(year); + } + int fmt(int f) { return _fmt = f; } + int fmt(void) const { return _fmt; } + + std::ostream & print (std::ostream & os) const; + + + private: + + int _fmt; + +}; + +class OSSIMDLLEXPORT ossimTime :public ossimLocalTm +{ + public: + friend std::ostream& operator <<(std::ostream& out, const ossimTime& src); + ossimTime(int tmfmt =ossimLocalTm::timefmt); + ossimTime (ossimTime const & t, + int tmfmt =ossimLocalTm::timefmt); + ossimTime (time_t t, int tmfmt =ossimLocalTm::timefmt); + + int fmt (int f); + int fmt (void) const; + + std::ostream& print (std::ostream & os) const; + +private: + int _fmt; +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimDisplayInterface.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimDisplayInterface.cpp new file mode 100644 index 0000000000..428e8e6292 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimDisplayInterface.cpp @@ -0,0 +1,31 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimDisplayInterface.cpp,v 1.2 2005/07/15 19:04:28 dburken Exp $ +#include <base/common/ossimDisplayInterface.h> + +RTTI_DEF(ossimDisplayInterface, "ossimDisplayInterface"); + +ossimDisplayInterface::ossimDisplayInterface() +{ +} + +ossimDisplayInterface::~ossimDisplayInterface() +{ +} + +ossimString ossimDisplayInterface::getTitle()const +{ + ossimString result; + + getTitle(result); + + return result; +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimDisplayInterface.h b/Utilities/OSSIM/ossim_core/base/common/ossimDisplayInterface.h new file mode 100644 index 0000000000..4933cdb168 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimDisplayInterface.h @@ -0,0 +1,40 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimDisplayInterface.h,v 1.3 2005/07/15 19:04:28 dburken Exp $ +#ifndef ossimDisplayInterface_HEADER +#define ossimDisplayInterface_HEADER +#include <base/common/ossimRtti.h> +#include <base/data_types/ossimString.h> + +class OSSIMDLLEXPORT ossimDisplayInterface +{ +public: + ossimDisplayInterface(); + + virtual ~ossimDisplayInterface(); + + /*! + * Returns the display back to the caller + */ + virtual void* getDisplayDevice()=0; + + virtual void setTitle(const ossimString& title)=0; + virtual void getTitle(ossimString& title)const=0; + virtual ossimString getTitle()const; + virtual void close()=0; + virtual bool isOpen() const=0; + virtual bool open()=0; + virtual bool isMinimized()const=0; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimErrorCodes.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimErrorCodes.cpp new file mode 100644 index 0000000000..1c5484d5f7 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimErrorCodes.cpp @@ -0,0 +1,318 @@ +//******************************************************************* +// Copyright (C) 2002 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// +// Description: +// +// Contains class definition with common error codes and methods to go +// from code to string and string to code. +// +//************************************************************************* +// $Id: ossimErrorCodes.cpp,v 1.6 2004/05/17 13:57:23 dburken Exp $ + +#include "ossimErrorCodes.h" +#include "base/data_types/ossimString.h" + +const ossimErrorCode ossimErrorCodes::OSSIM_OK = 0; +const ossimErrorCode ossimErrorCodes::OSSIM_NO_ERROR = 0; +const ossimErrorCode ossimErrorCodes::OSSIM_WARNING = -1; +const ossimErrorCode ossimErrorCodes::OSSIM_ERROR = 1; +const ossimErrorCode ossimErrorCodes::OSSIM_ERROR_STD_PARALLEL_1 = 2; +const ossimErrorCode ossimErrorCodes::OSSIM_LAT_ERROR = 3; +const ossimErrorCode ossimErrorCodes::OSSIM_LON_ERROR = 4; +const ossimErrorCode ossimErrorCodes::OSSIM_NORTHING_ERROR = 5; +const ossimErrorCode ossimErrorCodes::OSSIM_ORIGIN_LAT_ERROR = 6; +const ossimErrorCode ossimErrorCodes::OSSIM_CENT_MER_ERROR = 7; +const ossimErrorCode ossimErrorCodes::OSSIM_A_ERROR = 8; +const ossimErrorCode ossimErrorCodes::OSSIM_B_ERROR = 9; +const ossimErrorCode ossimErrorCodes::OSSIM_A_LESS_B_ERROR = 10; +const ossimErrorCode ossimErrorCodes::OSSIM_FIRST_STDP_ERROR = 11; +const ossimErrorCode ossimErrorCodes::OSSIM_SEC_STDP_ERROR = 12; +const ossimErrorCode ossimErrorCodes::OSSIM_FIRST_SECOND_ERROR = 13; +const ossimErrorCode ossimErrorCodes::OSSIM_HEMISPHERE_ERROR = 14; +const ossimErrorCode ossimErrorCodes::OSSIM_EASTING_ERROR = 15; +const ossimErrorCode ossimErrorCodes::OSSIM_RADIUS_ERROR = 16; +const ossimErrorCode ossimErrorCodes::OSSIM_ORIGIN_LON_ERROR = 17; +const ossimErrorCode ossimErrorCodes::OSSIM_ORIENTATION_ERROR = 18; +const ossimErrorCode ossimErrorCodes::OSSIM_SCALE_FACTOR_ERROR = 19; +const ossimErrorCode ossimErrorCodes::OSSIM_ZONE_ERROR = 20; +const ossimErrorCode ossimErrorCodes::OSSIM_ZONE_OVERRIDE_ERROR = 21; +const ossimErrorCode ossimErrorCodes::OSSIM_INVALID_FILE_ERROR = 22; +const ossimErrorCode ossimErrorCodes::OSSIM_OPEN_FILE_ERROR = 23; +const ossimErrorCode ossimErrorCodes::OSSIM_WRITE_FILE_ERROR = 24; +const ossimErrorCode ossimErrorCodes::OSSIM_ERROR_UNKNOWN = OSSIM_INT_NAN; + +ossimErrorCodes* ossimErrorCodes::theInstance = NULL; + +ossimErrorCodes::ossimErrorCodes() +{ +} + +ossimErrorCodes::ossimErrorCodes(const ossimErrorCodes& /* rhs */ ) +{ +} + +const ossimErrorCodes& ossimErrorCodes::operator=(const ossimErrorCodes&) +{ + return *this; +} + +ossimErrorCodes::~ossimErrorCodes() +{ + if (theInstance) + { + delete theInstance; + theInstance = NULL; + } +} + +ossimErrorCodes* ossimErrorCodes::instance() +{ + if (!theInstance) + { + theInstance = new ossimErrorCodes(); + } + + return theInstance; +} + +ossimErrorCode ossimErrorCodes::getErrorCode(const ossimString& error_string) const +{ + // Upcase... + ossimString str; + str = str.upcase(error_string); + + if (str == "OSSIM_OK") + { + return ossimErrorCodes::OSSIM_OK; + } + else if (str == "OSSIM_NO_ERROR") + { + return ossimErrorCodes::OSSIM_NO_ERROR; + } + else if (str == "OSSIM_WARNING") + { + return ossimErrorCodes::OSSIM_WARNING; + } + else if (str == "OSSIM_ERROR") + { + return ossimErrorCodes::OSSIM_ERROR; + } + else if (str == "OSSIM_ERROR_STD_PARALLEL_1") + { + return ossimErrorCodes::OSSIM_ERROR_STD_PARALLEL_1; + } + else if (str == "OSSIM_LAT_ERROR") + { + return ossimErrorCodes::OSSIM_LAT_ERROR; + } + else if (str == "OSSIM_LON_ERROR") + { + return ossimErrorCodes::OSSIM_LON_ERROR; + } + else if (str == "OSSIM_NORTHING_ERROR") + { + return ossimErrorCodes::OSSIM_NORTHING_ERROR; + } + else if (str == "OSSIM_ORIGIN_LAT_ERROR") + { + return ossimErrorCodes::OSSIM_ORIGIN_LAT_ERROR; + } + else if (str == "OSSIM_CENT_MER_ERROR") + { + return ossimErrorCodes::OSSIM_CENT_MER_ERROR; + } + else if (str == "OSSIM_A_ERROR") + { + return ossimErrorCodes::OSSIM_B_ERROR; + } + else if (str == "OSSIM_A_LESS_B_ERROR") + { + return ossimErrorCodes::OSSIM_A_LESS_B_ERROR; + } + else if (str == "OSSIM_FIRST_STDP_ERROR") + { + return ossimErrorCodes::OSSIM_FIRST_STDP_ERROR; + } + else if (str == "OSSIM_SEC_STDP_ERROR") + { + return ossimErrorCodes::OSSIM_SEC_STDP_ERROR; + } + else if (str == "OSSIM_FIRST_SECOND_ERROR") + { + return ossimErrorCodes::OSSIM_FIRST_SECOND_ERROR; + } + else if (str == "OSSIM_HEMISPHERE_ERROR") + { + return ossimErrorCodes::OSSIM_HEMISPHERE_ERROR; + } + else if (str == "OSSIM_EASTING_ERROR") + { + return ossimErrorCodes::OSSIM_EASTING_ERROR; + } + else if (str == "OSSIM_RADIUS_ERROR") + { + return ossimErrorCodes::OSSIM_RADIUS_ERROR; + } + else if (str == "OSSIM_ORIGIN_LON_ERROR") + { + return ossimErrorCodes::OSSIM_ORIGIN_LON_ERROR; + } + else if (str == "OSSIM_ORIENTATION_ERROR") + { + return ossimErrorCodes::OSSIM_ORIENTATION_ERROR; + } + else if (str == "OSSIM_SCALE_FACTOR_ERROR") + { + return ossimErrorCodes::OSSIM_SCALE_FACTOR_ERROR; + } + else if (str == "OSSIM_ZONE_ERROR") + { + return ossimErrorCodes::OSSIM_ZONE_ERROR; + } + else if (str == "OSSIM_ZONE_OVERRIDE_ERROR") + { + return ossimErrorCodes::OSSIM_ZONE_OVERRIDE_ERROR; + } + else if (str == "OSSIM_INVALID_FILE_ERROR") + { + return ossimErrorCodes::OSSIM_INVALID_FILE_ERROR; + } + else if (str == "OSSIM_OPEN_FILE_ERROR") + { + return ossimErrorCodes::OSSIM_OPEN_FILE_ERROR; + } + else if (str == "OSSIM_WRITE_FILE_ERROR") + { + return ossimErrorCodes::OSSIM_WRITE_FILE_ERROR; + } + + return OSSIM_ERROR_UNKNOWN; +} + +ossimString ossimErrorCodes::getErrorString(ossimErrorCode error_code) const +{ + if(error_code == OSSIM_OK) + { + // No difference between OSSIM_NO_ERROR and OSSIM_OK. + return ossimString("OSSIM_OK"); + } + if(error_code == OSSIM_WARNING) + { + return ossimString("OSSIM_WARNING"); + } + if(error_code == OSSIM_ERROR) + { + return ossimString("OSSIM_ERROR"); + } + if(error_code == OSSIM_ERROR_STD_PARALLEL_1) + { + return ossimString("OSSIM_ERROR_STD_PARALLEL_1"); + } + if(error_code == OSSIM_LAT_ERROR) + { + return ossimString("OSSIM_LAT_ERROR"); + } + if(error_code == OSSIM_LON_ERROR) + { + return ossimString("OSSIM_LON_ERROR"); + } + if(error_code == OSSIM_NORTHING_ERROR) + { + return ossimString("OSSIM_NORTHING_ERROR"); + } + if(error_code == OSSIM_ORIGIN_LAT_ERROR) + { + return ossimString("OSSIM_ORIGIN_LAT_ERROR"); + } + if(error_code == OSSIM_CENT_MER_ERROR) + { + return ossimString("OSSIM_CENT_MER_ERROR"); + } + if(error_code == OSSIM_A_ERROR) + { + return ossimString("OSSIM_A_ERROR"); + } + if(error_code == OSSIM_B_ERROR) + { + return ossimString("OSSIM_B_ERROR"); + } + if(error_code == OSSIM_A_LESS_B_ERROR) + { + return ossimString("OSSIM_A_LESS_B_ERROR"); + } + if(error_code == OSSIM_FIRST_STDP_ERROR) + { + return ossimString("OSSIM_FIRST_STDP_ERROR"); + } + if(error_code == OSSIM_SEC_STDP_ERROR) + { + return ossimString("OSSIM_SEC_STDP_ERROR"); + } + if(error_code == OSSIM_FIRST_SECOND_ERROR) + { + return ossimString("OSSIM_FIRST_SECOND_ERROR"); + } + if(error_code == OSSIM_HEMISPHERE_ERROR) + { + return ossimString("OSSIM_HEMISPHERE_ERROR"); + } + if(error_code == OSSIM_EASTING_ERROR) + { + return ossimString("OSSIM_EASTING_ERROR"); + } + if(error_code == OSSIM_RADIUS_ERROR) + { + return ossimString("OSSIM_RADIUS_ERROR"); + } + if(error_code == OSSIM_ORIGIN_LON_ERROR) + { + return ossimString("OSSIM_ORIGIN_LON_ERROR"); + } + if(error_code == OSSIM_ORIENTATION_ERROR) + { + return ossimString("OSSIM_ORIENTATION_ERROR"); + } + if(error_code == OSSIM_SCALE_FACTOR_ERROR) + { + return ossimString("OSSIM_SCALE_FACTOR_ERROR"); + } + if(error_code == OSSIM_ZONE_ERROR) + { + return ossimString("OSSIM_ZONE_ERROR"); + } + if(error_code == OSSIM_ZONE_OVERRIDE_ERROR) + { + return ossimString("OSSIM_ZONE_OVERRIDE_ERROR"); + } + if(error_code == OSSIM_INVALID_FILE_ERROR) + { + return ossimString("OSSIM_INVALID_FILE_ERROR"); + } + if(error_code == OSSIM_OPEN_FILE_ERROR) + { + return ossimString("OSSIM_OPEN_FILE_ERROR"); + } + if(error_code == OSSIM_WRITE_FILE_ERROR) + { + return ossimString("OSSIM_WRITE_FILE_ERROR"); + } + + return ossimString("OSSIM_ERROR_UNKNOWN"); +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimErrorCodes.h b/Utilities/OSSIM/ossim_core/base/common/ossimErrorCodes.h new file mode 100644 index 0000000000..e129f50dcd --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimErrorCodes.h @@ -0,0 +1,102 @@ +//******************************************************************* +// Copyright (C) 2002 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// +// Description: +// +// Contains class declaration with common error codes and methods to go +// from code to string and string to code. +// +//************************************************************************* +// $Id: ossimErrorCodes.h,v 1.5 2004/05/17 13:57:22 dburken Exp $ + +#ifndef ossimErrorCodes_HEADER +#define ossimErrorCodes_HEADER + +#include "ossimConstants.h" + +class OSSIMDLLEXPORT ossimString; + +/*! + * class ossimErrorCodes + * Contains class declaration with common error codes and methods to go + * from code to string and string to code. + */ +class OSSIMDLLEXPORT ossimErrorCodes +{ +public: + + ~ossimErrorCodes(); + + /*! + * Returns a pointer to "theInstance". + */ + static ossimErrorCodes* instance(); + + /*! + * Returns the error code from a string. Returns OSSIM_ERROR_UNKNOWN if + * the string does not match. + */ + ossimErrorCode getErrorCode(const ossimString& error_string) const; + + /*! + * Returns the string matching the error code. + * Returns "OSSIM_ERROR_UNKNOWN" if code is not valid. + */ + ossimString getErrorString(ossimErrorCode error_code) const; + + static const ossimErrorCode OSSIM_OK; + static const ossimErrorCode OSSIM_NO_ERROR; + static const ossimErrorCode OSSIM_WARNING; + static const ossimErrorCode OSSIM_ERROR; + static const ossimErrorCode OSSIM_ERROR_STD_PARALLEL_1; + static const ossimErrorCode OSSIM_LAT_ERROR; + static const ossimErrorCode OSSIM_LON_ERROR; + static const ossimErrorCode OSSIM_NORTHING_ERROR; + static const ossimErrorCode OSSIM_ORIGIN_LAT_ERROR; + static const ossimErrorCode OSSIM_CENT_MER_ERROR; + static const ossimErrorCode OSSIM_A_ERROR; + static const ossimErrorCode OSSIM_B_ERROR; + static const ossimErrorCode OSSIM_A_LESS_B_ERROR; + static const ossimErrorCode OSSIM_FIRST_STDP_ERROR; + static const ossimErrorCode OSSIM_SEC_STDP_ERROR; + static const ossimErrorCode OSSIM_FIRST_SECOND_ERROR; + static const ossimErrorCode OSSIM_HEMISPHERE_ERROR; + static const ossimErrorCode OSSIM_EASTING_ERROR; + static const ossimErrorCode OSSIM_RADIUS_ERROR; + static const ossimErrorCode OSSIM_ORIGIN_LON_ERROR; + static const ossimErrorCode OSSIM_ORIENTATION_ERROR; + static const ossimErrorCode OSSIM_SCALE_FACTOR_ERROR; + static const ossimErrorCode OSSIM_ZONE_ERROR; + static const ossimErrorCode OSSIM_ZONE_OVERRIDE_ERROR; + static const ossimErrorCode OSSIM_INVALID_FILE_ERROR; + static const ossimErrorCode OSSIM_OPEN_FILE_ERROR; + static const ossimErrorCode OSSIM_WRITE_FILE_ERROR; + static const ossimErrorCode OSSIM_ERROR_UNKNOWN; + +protected: + // Only allow instantiation through the "instance()" method. + ossimErrorCodes(); + ossimErrorCodes(const ossimErrorCodes& rhs); + const ossimErrorCodes& operator=(const ossimErrorCodes &rhs); + + static ossimErrorCodes* theInstance; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimErrorStatusInterface.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimErrorStatusInterface.cpp new file mode 100644 index 0000000000..f00d35ae19 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimErrorStatusInterface.cpp @@ -0,0 +1,79 @@ +//******************************************************************* +// Copyright (C) 2002 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// +// Description: +// +// Contains class definition for common error interfaces. +// +//************************************************************************* +// $Id: ossimErrorStatusInterface.cpp,v 1.3 2005/10/17 18:37:16 gpotts Exp $ + +#include "ossimErrorStatusInterface.h" +#include "base/data_types/ossimString.h" + +RTTI_DEF(ossimErrorStatusInterface, "ossimErrorStatusInterface"); + +ossimErrorStatusInterface::ossimErrorStatusInterface() + : + theErrorStatus(ossimErrorCodes::OSSIM_OK) +{} + +ossimErrorStatusInterface::~ossimErrorStatusInterface() +{} + +ossimErrorCode ossimErrorStatusInterface::getErrorStatus() const +{ + return theErrorStatus; +} + +ossimString ossimErrorStatusInterface::getErrorStatusString() const +{ + return ossimErrorCodes::instance()->getErrorString(theErrorStatus); +} + +void ossimErrorStatusInterface::setErrorStatus(ossimErrorCode error_status) const +{ + theErrorStatus = error_status; +} + +void ossimErrorStatusInterface::setErrorStatus() const +{ + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; +} + +void ossimErrorStatusInterface::clearErrorStatus() const +{ + theErrorStatus = ossimErrorCodes::OSSIM_OK; +} + +std::ostream& ossimErrorStatusInterface::print(std::ostream& out) const +{ + out << "ossimErrorStatusInterface::print" + << "\ntheErrorStatus: " << theErrorStatus + << "\ntheErrorStatus string: " << getErrorStatusString() + << std::endl; + return out; +} + +std::ostream& operator<<(std::ostream& out, + const ossimErrorStatusInterface& obj) +{ + return obj.print(out); +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimErrorStatusInterface.h b/Utilities/OSSIM/ossim_core/base/common/ossimErrorStatusInterface.h new file mode 100644 index 0000000000..abb35b661c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimErrorStatusInterface.h @@ -0,0 +1,84 @@ +//******************************************************************* +// Copyright (C) 2002 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// +// Description: +// +// Contains class declaration for common error interfaces. +// +//************************************************************************* +// $Id: ossimErrorStatusInterface.h,v 1.7 2004/05/21 21:49:19 dburken Exp $ + +#ifndef ossimErrorStatusInterface_HEADER +#define ossimErrorStatusInterface_HEADER + +#include <iostream> + +#include "ossimConstants.h" +#include "base/common/ossimRtti.h" +#include "base/common/ossimErrorCodes.h" + +/*! + * class ossimErrorStatusInterface + * Provides common interfaces for error handling. + * + * Note: For error codes and associated strings use the ossimErrorCodes class. + */ +class OSSIMDLLEXPORT ossimErrorStatusInterface +{ +public: + ossimErrorStatusInterface(); + + virtual ~ossimErrorStatusInterface(); + + /*! return theErrorStatus */ + virtual ossimErrorCode getErrorStatus() const; + + /*! return theErrorStatus as an ossimString */ + virtual ossimString getErrorStatusString() const; + + /*! Sets theErrorStatus to error_status. */ + virtual void setErrorStatus(ossimErrorCode error_status) const; + + /*! Set theErrorStatus to ossimErrorCodes::OSSIM_ERROR. */ + virtual void setErrorStatus() const; + + /*! Clears theErrorStatus by setting to ossimErrorCodes::OSSIM_OK or 0. */ + virtual void clearErrorStatus() const; + + /** + * Outputs theErrorStatus as an ossimErrorCode and an ossimString. + * + * @return std::ostream& + * + * @note Derived classes should only have to implement a virtual print, + * not an operator<< funtion as it's implemented here. + */ + virtual std::ostream& print(std::ostream& out) const; + + friend OSSIMDLLEXPORT std::ostream& operator<<(std::ostream& out, + const ossimErrorStatusInterface& obj); + +protected: + mutable ossimErrorCode theErrorStatus; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimFactoryBaseTemplate.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimFactoryBaseTemplate.cpp new file mode 100644 index 0000000000..73068cdbe5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimFactoryBaseTemplate.cpp @@ -0,0 +1,34 @@ +//***************************************************************************** +// FILE: ossimFactoryBaseTemplate.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// DESCRIPTION: +// Contains implementation of class ossimFactoryBaseTemplate. +// +// SOFTWARE HISTORY: +//> +// ddmmm2001 Oscar Kramer (okramer@imagelinks.com) +// Initial coding. +//< +//***************************************************************************** +// $Id: ossimFactoryBaseTemplate.cpp,v 1.3 2001/07/12 13:21:46 gpotts Exp $ + +#include "ossimFactoryBaseTemplate.h" + + diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimFactoryBaseTemplate.h b/Utilities/OSSIM/ossim_core/base/common/ossimFactoryBaseTemplate.h new file mode 100644 index 0000000000..f8e5789224 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimFactoryBaseTemplate.h @@ -0,0 +1,128 @@ +//***************************************************************************** +// FILE: ossimFactoryBaseTemplate.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// DESCRIPTION: +// Contains declaration of template class ossimFactory. This is the base +// type for all factories. +// +// SOFTWARE HISTORY: +//> +// 14Jun2001 Oscar Kramer (okramer@imagelinks.com) +// Initial coding. +//< +//***************************************************************************** +// $Id: ossimFactoryBaseTemplate.h,v 1.5 2002/11/25 18:45:47 gpotts Exp $ + +#ifndef ossimFactory_HEADER +#define ossimFactory_HEADER +#include "ossimConstants.h" +#include <list> +using namespace std; +class OSSIMDLLEXPORT ossimKeywordlist; +class OSSIMDLLEXPORT ossimString; + +/*!**************************************************************************** + * + * TEMPLATE: ossimFactoryBase + * + * NOTE: This is primarily intended as an interface template only to insure + * that all factories prescribe to a common type. Concrete classes shall + * be derived from an instance of this template as: + * + * class MyFactory : public ossimFactoryBase<MyProductClass> + * + * where MyProductClass is the class type being produced. + * + * This template is applicable to "Registry" type factories that have + * one or more sub-factories. Thus, a common interface is provided + * without the client distinguishing between registries and factories. + * + * EXAMPLE: Refer to the projection factories for a working example of the + * use of this base class template. Specifically, refer to the files: + * - ../ossim_core/projections/factory/ossimProjectionFactory.h + * - ../ossim_core/projections/factory/ossimMapProjectionFactory.h + * - ../ossim_core/projections/factory/ossimSensorModelFactory.h + * + *****************************************************************************/ +template <class Product> class OSSIMDLLEXPORT ossimFactoryBase +{ +public: + /*! + * METHOD: instance() + * For accessing static singleton instance of concrete factory. The derived + * class implementation of this method invokes the factory's private + * constructor. MUST BE PROVIDED BY CONCRETE DERIVED CLASS as follows: + * + static <ossimFactoryBase-derived class>* instance(); + */ + + /*! + * PURE VIRTUAL METHODS: create(string), create(keywordlist, prefix) + * + * Attempts to create an instance of the Product given a string or + * keywordlist. It is up to the concrete factory implementation to decide + * how to interpret string. It could conceivably represent a "magic + * number" specification of a product (such as the class name). Or, it could + * be a filename that the factory must open to decide which product + * to instantiate. The derived factory can also define other create methods + * following the model used here. + * + * Returns successfully constructed product or NULL. + */ + virtual Product* create(const ossimString&) const = 0; + virtual Product* create(const ossimKeywordlist& kwl, + const char* prefix) const = 0; + + /*! + * PURE VIRTUAL METHOD: getList() + * Returns name list of all products represented by this factory: + */ + virtual list<ossimString> getList() const = 0; + + /*! + * METHOD: registerFactory() + * Adds sub-factories to this one. Relevant for the case where the + * derived factory maintains a registry of sub-factories. + */ + void registerFactory(ossimFactoryBase<Product>* new_factory) + { if(new_factory) theRegistry.push_back(new_factory); } + +protected: + /*! + * PROTECTED DEFAULT CONSTRUCTOR + * Gives concrete class the opportunity to perform initialization + * tasks since this is called once with first instance() call. If the + * derived factory is to serve as a sub-factory registry, then have the + * derived class' constructor call registerFactory() for all of the default + * sub-factories involved. + */ + ossimFactoryBase() {}; + + virtual ~ossimFactoryBase() {} + + /*! + * Member contains list of sub-factories associated with this factory: + */ + list<ossimFactoryBase<Product>*> theRegistry; + +}; + +#endif + diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimFontInformation.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimFontInformation.cpp new file mode 100644 index 0000000000..722e74044a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimFontInformation.cpp @@ -0,0 +1,221 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: Garrett Potts +// +//******************************************************************** +// $Id: ossimFontInformation.cpp,v 1.3 2005/12/16 14:27:02 dburken Exp $ + +#include <sstream> +#include <base/common/ossimFontInformation.h> +#include <base/data_types/ossimKeywordlist.h> + +const char* ossimFontInformation::FAMILY_NAME_KW = "family_name"; +const char* ossimFontInformation::STYLE_NAME_KW = "style_name"; +const char* ossimFontInformation::POINT_SIZE_KW = "point_size"; +const char* ossimFontInformation::POINT_SIZE_X_KW = "point_size_x"; +const char* ossimFontInformation::POINT_SIZE_Y_KW = "point_size_y"; +const char* ossimFontInformation::FIXED_FLAG_KW = "fixed_flag"; +const char* ossimFontInformation::SHEAR_KW = "shear"; +const char* ossimFontInformation::SHEAR_X_KW = "shear_x"; +const char* ossimFontInformation::SHEAR_Y_KW = "shear_y"; +const char* ossimFontInformation::SCALE_KW = "scale"; +const char* ossimFontInformation::SCALE_X_KW = "scale_x"; +const char* ossimFontInformation::SCALE_Y_KW = "scale_y"; +const char* ossimFontInformation::ROTATION_KW = "rotation"; + + +bool ossimFontInformation::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + FAMILY_NAME_KW, + theFamilyName, + true); + kwl.add(prefix, + STYLE_NAME_KW, + theStyleName, + true); + + kwl.add(prefix, + POINT_SIZE_KW, + thePointSize.toString().c_str(), + true); + + kwl.add(prefix, + SHEAR_KW, + theShear.toString().c_str(), + true); + + kwl.add(prefix, + SCALE_KW, + theScale.toString().c_str(), + true); + +#if 0 + kwl.add(prefix, + POINT_SIZE_X_KW, + thePointSize.x, + true); + kwl.add(prefix, + POINT_SIZE_Y_KW, + thePointSize.y, + true); + kwl.add(prefix, + SHEAR_Y_KW, + theShear.y, + true); + kwl.add(prefix, + SCALE_X_KW, + theScale.x, + true); + kwl.add(prefix, + SCALE_X_KW, + theScale.x, + true); + kwl.add(prefix, + SCALE_Y_KW, + theScale.y, + true); +#endif + + kwl.add(prefix, + FIXED_FLAG_KW, + (int)theFixedFlag, + true); + kwl.add(prefix, + ROTATION_KW, + theRotation, + true); + + + return true; +} + +bool ossimFontInformation::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + bool result = true; + + const char* family_name = kwl.find(prefix, FAMILY_NAME_KW); + const char* style_name = kwl.find(prefix, STYLE_NAME_KW); + const char* fixed = kwl.find(prefix, FIXED_FLAG_KW); + const char* rotation = kwl.find(prefix, ROTATION_KW); + + if(family_name) + { + theFamilyName = family_name; + } + else + { + result = false; + } + + if(style_name) + { + theStyleName = style_name; + } + else + { + result = false; + } + + // Look for point_size: + const char* lookup; + lookup = kwl.find(prefix, POINT_SIZE_KW); + if (lookup) + { + std::istringstream is(lookup); + is >> thePointSize; + } + else // backwards compat... + { + const char* point_x = kwl.find(prefix, POINT_SIZE_X_KW); + const char* point_y = kwl.find(prefix, POINT_SIZE_Y_KW); + if((point_x)&&(point_y)) + { + thePointSize = ossimIpt(ossimString(point_x).toLong(), + ossimString(point_y).toLong()); + } + else + { + result = false; + } + } + + // Look for shear: + lookup = kwl.find(prefix, SHEAR_KW); + if (lookup) + { + std::istringstream is(lookup); + is >> theShear; + } + else + { + const char* shear_x = kwl.find(prefix, SHEAR_X_KW); + if(shear_x) + { + theShear.x = ossimString(shear_x).toDouble(); + } + else + { + result = false; + } + const char* shear_y = kwl.find(prefix, SHEAR_Y_KW); + if(shear_y) + { + theShear.y = ossimString(shear_y).toDouble(); + } + else + { + result = false; + } + } + + // Look for scale: + lookup = kwl.find(prefix, SCALE_KW); + if (lookup) + { + std::istringstream is(lookup); + is >> theScale; + } + else + { + const char* scale_x = kwl.find(prefix, SCALE_X_KW); + if(scale_x) + { + theScale.x = ossimString(scale_x).toDouble(); + } + else + { + result = false; + } + const char* scale_y = kwl.find(prefix, SCALE_Y_KW); + if(scale_y) + { + theScale.y = ossimString(scale_y).toDouble(); + } + else + { + result = false; + } + } + + if(fixed) + { + theFixedFlag = ossimString(fixed).toBool(); + } + + if(rotation) + { + theRotation = ossimString(rotation).toDouble(); + } + else + { + result = false; + } + + return result; +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimFontInformation.h b/Utilities/OSSIM/ossim_core/base/common/ossimFontInformation.h new file mode 100644 index 0000000000..ef00a043e9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimFontInformation.h @@ -0,0 +1,163 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt. +// +// Author: Garrett Potts +// +//******************************************************************** +// $Id: ossimFontInformation.h,v 1.4 2005/12/16 14:27:02 dburken Exp $ +#ifndef ossimFontInformation_HEADER +#define ossimFontInformation_HEADER +#include <iostream> +#include <base/data_types/ossimString.h> +#include <base/data_types/ossimIpt.h> + +class ossimKeywordlist; + +class OSSIMDLLEXPORT ossimFontInformation +{ +public: + friend std::ostream& operator << (std::ostream& out, + const ossimFontInformation& rhs) + { + out << "Family name: " << rhs.theFamilyName + << "\nStyle name: " << rhs.theStyleName + << "\nPoint size: " << rhs.thePointSize + << "\nFixed flag: " << (rhs.theFixedFlag?"true":"false") + << std::endl; + + return out; + } + ossimFontInformation() + :theFamilyName(""), + theStyleName(""), + thePointSize(0,0), + theFixedFlag(false), + theScale(1.0,1.0), + theRotation(0.0), + theShear(0.0,0.0) + { + } + ossimFontInformation(const ossimString& family, + const ossimString& style, + const ossimIpt& pointSize, + bool fixedFlag, + const ossimDpt& scale=ossimDpt(1.0,1.0), + double rotation = 0.0, + const ossimDpt& shear=ossimDpt(0.0, 0.0)) + :theFamilyName(family), + theStyleName(style), + thePointSize(pointSize), + theFixedFlag(fixedFlag), + theScale(scale), + theRotation(rotation), + theShear(shear) + {} + ossimFontInformation(const ossimFontInformation& rhs) + : theFamilyName(rhs.theFamilyName), + theStyleName(rhs.theStyleName), + thePointSize(rhs.thePointSize), + theFixedFlag(rhs.theFixedFlag), + theScale(rhs.theScale), + theRotation(rhs.theRotation), + theShear(rhs.theShear) + { + } + bool isFixed()const + { + return theFixedFlag; + } + + /** + * Saves the current state of this object. + * + * For keywords see loadState: + */ + bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + * + * Keywords: + * + * family_name: + * style_name: + * fixed_flag: + * point_size: ( x, y ) + * scale: ( x, y ) + * shear: ( x, y ) + * rotation: + * + * point_size_x: (deprecated) + * point_size_y: (deprecated) + * scale_x: (deprecated) + * scale_y: (deprecated) + * shear_x: (deprecated) + * shear_y: (deprecated) + */ + bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + bool operator ==(const ossimFontInformation& rhs)const + { + return ( (theFamilyName == rhs.theFamilyName)&& + (theStyleName == rhs.theStyleName)&& + (thePointSize == rhs.thePointSize)&& + (theFixedFlag == rhs.theFixedFlag)&& + (theScale == rhs.theScale)&& + (theRotation == rhs.theRotation)&& + (theShear == rhs.theShear)); + } + + bool operator !=(const ossimFontInformation& rhs)const + { + return ( (theFamilyName != rhs.theFamilyName)|| + (theStyleName != rhs.theStyleName)|| + (thePointSize != rhs.thePointSize)|| + (theFixedFlag != rhs.theFixedFlag)|| + (theScale != rhs.theScale)|| + (theRotation != rhs.theRotation)|| + (theShear != rhs.theShear)); + } + + const ossimFontInformation& operator =(const ossimFontInformation& rhs) + { + theFamilyName = rhs.theFamilyName; + theStyleName = rhs.theStyleName; + thePointSize = rhs.thePointSize; + theFixedFlag = rhs.theFixedFlag; + theScale = rhs.theScale; + theRotation = rhs.theRotation; + theShear = rhs.theShear; + + return *this; + } + + static const char* FAMILY_NAME_KW; + static const char* STYLE_NAME_KW; + static const char* POINT_SIZE_KW; // point_size: ( x, y ) + static const char* POINT_SIZE_X_KW; // deprecated + static const char* POINT_SIZE_Y_KW; // deprecated + static const char* FIXED_FLAG_KW; + static const char* SHEAR_KW; // shear: ( x, y ) + static const char* SHEAR_X_KW; // deprecated + static const char* SHEAR_Y_KW; // deprecated + static const char* SCALE_KW; // scale: ( x, y ) + static const char* SCALE_X_KW; // deprecated + static const char* SCALE_Y_KW; // deprecated + static const char* ROTATION_KW; + + + ossimString theFamilyName; + ossimString theStyleName; + ossimIpt thePointSize; + bool theFixedFlag; + ossimDpt theScale; + double theRotation; + ossimDpt theShear; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimGzStream.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimGzStream.cpp new file mode 100644 index 0000000000..d5683faeda --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimGzStream.cpp @@ -0,0 +1,280 @@ +// ============================================================================ +// gzstream, C++ iostream classes wrapping the zlib compression library. +// Copyright (C) 2001 Deepak Bandyopadhyay, Lutz Kettner +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser 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 +// ============================================================================ +// +// File : gzstream.C +// Revision : $Revision: 1.2 $ +// Revision_date : $Date: 2005/11/10 14:13:25 $ +// Author(s) : Deepak Bandyopadhyay, Lutz Kettner +// +// Standard streambuf implementation following Nicolai Josuttis, "The +// Standard C++ Library". +// ============================================================================ + +#include "ossimGzStream.h" + +#if OSSIM_HAS_LIBZ + +#include <iostream> +#include <fstream> +#include <string.h> // for memcpy + + +RTTI_DEF1(ossimIgzStream, "ossimIgzStream", ossimIStream); +RTTI_DEF1(ossimOgzStream, "ossimOgzStream", ossimOStream); + +// ---------------------------------------------------------------------------- +// Internal classes to implement gzstream. See header file for user classes. +// ---------------------------------------------------------------------------- + +// -------------------------------------- +// class ossimGzStreamBuf: +// -------------------------------------- + +ossimGzStreamBuf* ossimGzStreamBuf::open( const char* name, int open_mode) +{ + if ( is_open()) + { + return (ossimGzStreamBuf*)0; + } + mode = open_mode; + // no append nor read/write mode + if ((mode & std::ios::ate) || (mode & std::ios::app) + || ((mode & std::ios::in) && (mode & std::ios::out))) + { + return (ossimGzStreamBuf*)0; + } + + char fmode[10]; + char* fmodeptr = fmode; + if ( mode & std::ios::in) + { + *fmodeptr++ = 'r'; + } + else if ( mode & std::ios::out) + { + *fmodeptr++ = 'w'; + } + *fmodeptr++ = 'b'; + *fmodeptr = '\0'; + file = gzopen( name, fmode); + if (file == 0) + { + return (ossimGzStreamBuf*)0; + } + opened = true; + return this; +} + +ossimGzStreamBuf * ossimGzStreamBuf::close() +{ + if ( is_open()) + { + sync(); + opened = false; + if ( gzclose( file) == Z_OK) + { + return this; + } + } + return (ossimGzStreamBuf*)0; +} + +std::streamsize ossimGzStreamBuf::xsgetn(char_type* __s, + std::streamsize n) +{ + int num = gzread( file, __s, n); + + if (num <= 0) // ERROR or EOF + return EOF; + + return num; +} + +#if 0 +// int ossimGzStreamBuf::underflow() +// { +// // used for input buffer only +// if ( gptr() && ( gptr() < egptr())) +// return * reinterpret_cast<unsigned char *>( gptr()); + +// if ( ! (mode & std::ios::in) || ! opened) +// return EOF; +// // Josuttis' implementation of inbuf +// int n_putback = gptr() - eback(); +// if ( n_putback > 4) +// n_putback = 4; +// memcpy( buffer + (4 - n_putback), gptr() - n_putback, n_putback); + +// int num = gzread( file, buffer+4, bufferSize-4); +// if (num <= 0) // ERROR or EOF +// return EOF; + +// // reset buffer pointers +// setg( buffer + (4 - n_putback), // beginning of putback area +// buffer + 4, // read position +// buffer + 4 + num); // end of buffer + +// // return next character +// return * reinterpret_cast<unsigned char *>( gptr()); +// } +#endif + +int ossimGzStreamBuf::flush_buffer() +{ + // Separate the writing of the buffer from overflow() and + // sync() operation. + int w = pptr() - pbase(); + if ( gzwrite( file, pbase(), w) != w) + return EOF; + pbump( -w); + return w; +} + +int ossimGzStreamBuf::overflow( int c) { // used for output buffer only + if ( ! ( mode & std::ios::out) || ! opened) + return EOF; + if (c != EOF) { + *pptr() = c; + pbump(1); + } + if ( flush_buffer() == EOF) + return EOF; + return c; +} + +int ossimGzStreamBuf::sync() { + // Changed to use flush_buffer() instead of overflow( EOF) + // which caused improper behavior with std::endl and flush(), + // bug reported by Vincent Ricard. + if ( pptr() && pptr() > pbase()) { + if ( flush_buffer() == EOF) + return -1; + } + return 0; +} + +ossimGzStreamBuf::pos_type ossimGzStreamBuf::seekoff(off_type t, + std::ios_base::seekdir dir, + std::ios_base::openmode omode) +{ + int whence = 0; + switch(dir) + { + case std::ios::beg: + { + whence = SEEK_SET; + break; + } + case std::ios::end: + { + whence = SEEK_END; + break; + } + case std::ios::cur: + { + whence = SEEK_CUR; + break; + } + default: + { + whence = SEEK_CUR; + break; + } + } + + return gzseek(file, t, whence); +} + +// ossimGzStreamBuf::pos_type ossimGzStreamBuf::seekpos(pos_type posType, +// std::ios_base::openmode) +// { +// std::cout << "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW" << std::endl; +// int whence = 0; +// switch(dir) +// { +// case std::ios::beg: +// { +// whence = SEEK_SET; +// break; +// } +// case std::ios::end: +// { +// whence = SEEK_END; +// break; +// } +// case std::ios::cur: +// { +// whence = SEEK_CUR; +// break; +// } +// default: +// { +// whence = SEEK_CUR; +// break; +// } +// } + +// return gzseek(file, t, whence); +//} + +// -------------------------------------- +// class ossimGzStreamBase: +// -------------------------------------- + +void ossimIgzStream::open( const char* name, int open_mode) +{ + if ( ! buf.open( name, open_mode)) + { + clear( rdstate() | std::ios::badbit); + } +} + +void ossimOgzStream::open( const char* name, int open_mode) +{ + if ( ! buf.open( name, open_mode)) + { + clear( rdstate() | std::ios::badbit); + } +} + +void ossimIgzStream::close() +{ + if ( buf.is_open()) + { + if ( !buf.close()) + { + clear( rdstate() | std::ios::badbit); + } + } +} + +void ossimOgzStream::close() +{ + if ( buf.is_open()) + { + if ( !buf.close()) + { + clear( rdstate() | std::ios::badbit); + } + } +} + +// ============================================================================ +// EOF // +#endif // OSSIM_HAS_LIBZ diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimGzStream.h b/Utilities/OSSIM/ossim_core/base/common/ossimGzStream.h new file mode 100644 index 0000000000..4869a51078 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimGzStream.h @@ -0,0 +1,163 @@ +// ============================================================================ +// gzstream, C++ iostream classes wrapping the zlib compression library. +// Copyright (C) 2001 Deepak Bandyopadhyay, Lutz Kettner +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser 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 +// ============================================================================ +// +// File : gzstream.h +// Revision : $Revision: 1.4 $ +// Revision_date : $Date: 2005/11/10 19:51:41 $ +// Author(s) : Deepak Bandyopadhyay, Lutz Kettner +// +// Standard streambuf implementation following Nicolai Josuttis, "The +// Standard C++ Library". +// ============================================================================ + +#ifndef ossimGzStream_HEADER +#define ossimGzStream_HEADER 1 + +// standard C++ with new header file names and std:: namespace +#include <base/common/ossimReferenced.h> +#include <base/common/ossimConstants.h> +#include <ossimConfig.h> +#include <iostream> +#include <fstream> +#include "ossimIoStream.h" + +#if OSSIM_HAS_LIBZ +#include <zlib.h> +// ---------------------------------------------------------------------------- +// Internal classes to implement gzstream. See below for user classes. +// ---------------------------------------------------------------------------- + +class OSSIM_DLL ossimGzStreamBuf : public std::streambuf { +private: + static const int bufferSize = 47+256; // size of data buff + // totals 512 bytes under g++ for igzstream at the end. + + gzFile file; // file handle for compressed file + char buffer[bufferSize]; // data buffer + bool opened; // open/close state of stream + int mode; // I/O mode + + int flush_buffer(); +public: + ossimGzStreamBuf() : opened(false) { + setp( buffer, buffer + (bufferSize-1)); + setg( buffer + 4, // beginning of putback area + buffer + 4, // read position + buffer + 4); // end position + // ASSERT: both input & output capabilities will not be used together + } + bool is_open()const { return opened; } + ossimGzStreamBuf* open( const char* name, int open_mode); + ossimGzStreamBuf* close(); + ~ossimGzStreamBuf() { close(); } + + virtual int overflow( int c = EOF); + + // will not use buffer for get. + virtual std::streamsize xsgetn(char_type* __s, + std::streamsize n); +// virtual int underflow(); + virtual int sync(); + virtual pos_type seekoff(off_type t, std::ios_base::seekdir dir, + std::ios_base::openmode omode = std::ios_base::in | + std::ios_base::out); +/* virtual pos_type seekpos(pos_type posType, */ +/* std::ios_base::openmode __mode = std::ios_base::in | */ +/* std::ios_base::out); */ +}; + +/* class OSSIM_DLL ossimGzStreamBase : virtual public ossimProtocolStream */ +/* { */ +/* protected: */ +/* ossimGzStreamBuf buf; */ + +/* public: */ +/* ossimGzStreamBase():ossimProtocolStream(&buf) { } */ +/* ossimGzStreamBase( const char* name, int open_mode); */ +/* virtual ~ossimGzStreamBase(); */ +/* virtual void open( const char* name, int open_mode); */ +/* virtual void close(); */ +/* ossimGzStreamBuf* rdbuf() { return &buf; } */ + +/* TYPE_DATA */ +/* }; */ + +//class OSSIM_DLL ossimIgzStream : public ossimGzStreamBase, public std::istream +class OSSIM_DLL ossimIgzStream : public ossimIStream +{ +protected: + ossimGzStreamBuf buf; + +public: + ossimIgzStream() :ossimIStream(&buf){} + ossimIgzStream( const char* name, int openMode = std::ios::in) + : ossimIStream(&buf) + { + open(name, openMode); + } + virtual ~ossimIgzStream() + { + buf.close(); + } + ossimGzStreamBuf* rdbuf() { return &buf; } + + virtual void open( const char* name, int open_mode = std::ios::in); + virtual void close(); + virtual bool is_open()const + { + return buf.is_open(); + } + virtual bool isCompressed()const + { + return true; + } +TYPE_DATA +}; + +class OSSIM_DLL ossimOgzStream : public ossimOStream +{ +protected: + ossimGzStreamBuf buf; + +public: + ossimOgzStream(){init(&buf);} + ossimOgzStream( const char* name, int mode = std::ios::out) + : ossimOStream(&buf) {} + virtual ~ossimOgzStream() + { + buf.close(); + } + ossimGzStreamBuf* rdbuf() { return &buf; } + void open( const char* name, int openMode = std::ios::out); + virtual void close(); + virtual bool is_open()const + { + return buf.is_open(); + } + virtual bool isCompressed()const + { + return true; + } +TYPE_DATA +}; + +#endif + +#endif // GZSTREAM_H + diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimHistogramSource.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimHistogramSource.cpp new file mode 100644 index 0000000000..0024783382 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimHistogramSource.cpp @@ -0,0 +1,120 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimHistogramSource.cpp,v 1.5 2005/10/06 13:44:05 dburken Exp $ + +#include <base/common/ossimHistogramSource.h> +#include <base/common/ossimKeywordNames.h> +#include <base/data_types/ossimMultiResLevelHistogram.h> + +RTTI_DEF1(ossimHistogramSource, "ossimHistogramSource", ossimSource); + + +ossimHistogramSource::ossimHistogramSource(ossimObject* owner, + ossim_uint32 numberOfInputs, + ossim_uint32 numberOfOutputs, + bool inputListFixedFlag, + bool outputListFixedFlag) + : ossimSource(owner, + numberOfInputs, + numberOfOutputs, + inputListFixedFlag, + outputListFixedFlag), + theHistogram(NULL), + theFilename() +{ +} + +ossimHistogramSource::~ossimHistogramSource() +{ + if (theHistogram) + { + delete theHistogram; + theHistogram = NULL; + } +} + +ossimMultiResLevelHistogram* ossimHistogramSource::getHistogram() +{ + return theHistogram; +} + +bool ossimHistogramSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + if(theHistogram) + { + delete theHistogram; + theHistogram = NULL; + } + + const char* externalFile = kwl.find(prefix, + ossimKeywordNames::FILENAME_KW); + + theHistogram = new ossimMultiResLevelHistogram; + if(externalFile) + { + if(!theHistogram->importHistogram(ossimFilename(externalFile))) + { + delete theHistogram; + theHistogram = NULL; + theFilename = ""; + } + theFilename = externalFile; + } + else + { + ossimString newPrefix = ossimString(prefix) + "histogram."; + if(!theHistogram->loadState(kwl, newPrefix)) + { + delete theHistogram; + theHistogram = NULL; + } + } + + return ossimSource::loadState(kwl, prefix); +} + +bool ossimHistogramSource::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + if(theHistogram) + { + if( (theFilename != "")&& + theHistogram) + { + ossimKeywordlist kwl2; + + if(theHistogram->saveState(kwl2)) + { + kwl2.write(theFilename.c_str()); + kwl.add(prefix, + ossimKeywordNames::FILENAME_KW, + theFilename.c_str(), + true); + } + } + else + { + ossimString newPrefix = ossimString(prefix) + "histogram."; + theHistogram->saveState(kwl, newPrefix); + } + } + + return ossimSource::saveState(kwl, prefix); +} + +// Hidden from use. +ossimHistogramSource::ossimHistogramSource(const ossimHistogramSource&) + : + theHistogram(NULL), + theFilename() +{ +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimHistogramSource.h b/Utilities/OSSIM/ossim_core/base/common/ossimHistogramSource.h new file mode 100644 index 0000000000..79f289552e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimHistogramSource.h @@ -0,0 +1,58 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimHistogramSource.h,v 1.11 2005/10/06 13:44:05 dburken Exp $ +#ifndef ossimHistogramSource_HEADER +#define ossimHistogramSource_HEADER + +#include <base/common/ossimSource.h> +#include <base/data_types/ossimFilename.h> + +class OSSIMDLLEXPORT ossimMultiResLevelHistogram; + +class OSSIMDLLEXPORT ossimHistogramSource : public ossimSource +{ +public: + + virtual ~ossimHistogramSource(); + + virtual ossimMultiResLevelHistogram* getHistogram(); + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; +protected: + ossimHistogramSource(ossimObject* owner=NULL, + ossim_uint32 numberOfInputs=0, + ossim_uint32 numberOfOutputs=0, + bool inputListFixedFlag=true, + bool outputListFixedFlag=true); + + ossimMultiResLevelHistogram* theHistogram; + + /*! + * if the filename is not "" then it will use + * this to store the histogram outside the keywordlist. + * + * it will set the filename keyword to the filename and + * during a save state will save it out to the file + * instead of inline to the keyword list. + */ + ossimFilename theFilename; + +private: + /** Hidden from use copy constructor. */ + ossimHistogramSource(const ossimHistogramSource&); + +TYPE_DATA +}; + +#endif /* End of "#ifndef ossimHistogramSource_HEADER" */ diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimId.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimId.cpp new file mode 100644 index 0000000000..de8dddbb17 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimId.cpp @@ -0,0 +1,3 @@ +#include "ossimId.h" + +const long ossimId::INVALID_ID = -1; diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimId.h b/Utilities/OSSIM/ossim_core/base/common/ossimId.h new file mode 100644 index 0000000000..8b798022e4 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimId.h @@ -0,0 +1,109 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimId.h,v 1.5 2002/11/25 18:45:47 gpotts Exp $ +#ifndef ossimId_HEADER +#define ossimId_HEADER +#include <iostream> +using namespace std; +#include "ossimConstants.h" + +class OSSIMDLLEXPORT ossimId +{ +public: + friend ostream& operator <<(ostream &out, + const ossimId& data) + { + data.print(out); + return out; + } + + explicit ossimId(long id = 0) + :theId(id) + {} + virtual ~ossimId(){} + + virtual void print(ostream& out)const + { + out << "id: " << theId; + } + void setId(long id){theId = id;} + long getId()const{return theId;} + + bool operator ==(const ossimId& rhs)const + { + return (theId == rhs.theId); + } + bool operator !=(const ossimId& rhs)const + { + return (theId != rhs.theId); + } + + bool operator == (int rhs) + { + return (theId == rhs); + } + bool operator != (int rhs) + { + return (theId != rhs); + } + + bool operator <(const ossimId& rhs)const + { + return (theId < rhs.theId); + } + bool operator <=(const ossimId& rhs)const + { + return (theId <= rhs.theId); + } + bool operator >(const ossimId& rhs)const + { + return (theId > rhs.theId); + } + bool operator >=(const ossimId& rhs)const + { + return (theId >= rhs.theId); + } + + bool operator <(int rhs)const + { + return (theId < rhs); + } + bool operator >(int rhs)const + { + return (theId > rhs); + } + bool operator <=(int rhs)const + { + return (theId <= rhs); + } + bool operator >=(int rhs)const + { + return (theId >= rhs); + } + + static const long INVALID_ID; +protected: + long theId; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimIdManager.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimIdManager.cpp new file mode 100644 index 0000000000..1fa4548a67 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimIdManager.cpp @@ -0,0 +1,64 @@ +#include "ossimIdManager.h" +#include <time.h> +#ifndef NULL +#include <stddef.h> +#endif + + +long ossimIdManager::theCurrentId = ossimId::INVALID_ID; +ossimIdManager* ossimIdManager::theInstance = NULL; + +ossimIdManager::ossimIdManager() +{ + theCurrentId=ossimId::INVALID_ID; +} + +ossimIdManager::ossimIdManager(const ossimIdManager& /* rhs */) +{ + theCurrentId=ossimId::INVALID_ID; +} + +ossimIdManager::~ossimIdManager() +{ + theCurrentId=ossimId::INVALID_ID; +} + +ossimIdManager* ossimIdManager::instance() +{ + if(!theInstance) + { + theInstance = new ossimIdManager; + theCurrentId = -1; + } + + return theInstance; +} + +ossimId ossimIdManager::generateId() +{ + return ossimId(++theCurrentId); +} + +ossimId ossimIdManager::generateId(long customId) +{ + if(customId <= theCurrentId) + { + return ossimId(++theCurrentId); + } + theCurrentId = customId; + return ossimId(theCurrentId); +} + +void ossimIdManager::setCurrentId(long currentId) +{ + theCurrentId = (currentId >=0) ? currentId: theCurrentId; +} + +void ossimIdManager::releaseId(const ossimId& idToRelease) +{ + // currently doesn't do anything but we will later + // store id's and make sure that they are unique. + // +} +void ossimIdManager::operator=(const ossimIdManager& /* rhs */) +{} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimIdManager.h b/Utilities/OSSIM/ossim_core/base/common/ossimIdManager.h new file mode 100644 index 0000000000..40818fc35f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimIdManager.h @@ -0,0 +1,25 @@ +#ifndef ossimIdManager_HEADER +#define ossimIdManager_HEADER + +#include "ossimId.h" + +class OSSIMDLLEXPORT ossimIdManager +{ +public: + static ossimIdManager* instance(); + ossimId generateId(); + ossimId generateId(long customId); + void releaseId(const ossimId& idToRelease); + void setCurrentId(long customId); + +protected: + ossimIdManager(); // make sure this can't be constructed outside + ossimIdManager(const ossimIdManager& rhs); + ~ossimIdManager(); + void operator =(const ossimIdManager& rhs); + + static ossimIdManager* theInstance; + static long theCurrentId; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimIoStream.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimIoStream.cpp new file mode 100644 index 0000000000..5c90ed8187 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimIoStream.cpp @@ -0,0 +1,169 @@ +#include "ossimIoStream.h" + +RTTI_DEF1(ossimIStream, "ossimIProtocolStream", ossimProtocolStream); +RTTI_DEF1(ossimOStream, "ossimOProtocolStream", ossimProtocolStream); +RTTI_DEF1(ossimIOStream, "ossimOProtocolStream", ossimProtocolStream); + +RTTI_DEF1(ossimIFStream, "ossimIFStream", ossimIStream); +RTTI_DEF1(ossimOFStream, "ossimOFStream", ossimOStream); +RTTI_DEF1(ossimIOFStream, "ossimIOFStream", ossimIOStream); + +void operator >> (ossimIStream& in,ossimOStream& out) +{ + char buf[1024]; + bool done = false; + + while(!done&&!in.fail()) + { + in.read(buf, 1024); + if(in.gcount() < 1024) + { + done = true; + } + if(in.gcount() > 0) + { + out.write(buf, in.gcount()); + } + } +} + +ossimIOStream& operator >> (ossimIStream& in,ossimIOStream& out) +{ + char buf[1024]; + bool done = false; + + while(!done&&!in.fail()) + { + in.read(buf, 1024); + if(in.gcount() < 1024) + { + done = true; + } + if(in.gcount() > 0) + { + out.write(buf, in.gcount()); + } + } + + return out; +} + +void operator >> (ossimIOStream& in,ossimOStream& out) +{ + char buf[1024]; + bool done = false; + + while(!done&&!in.fail()) + { + in.read(buf, 1024); + if(in.gcount() < 1024) + { + done = true; + } + if(in.gcount() > 0) + { + out.write(buf, in.gcount()); + } + } +} + +ossimIOStream& operator >> (ossimIOStream& in,ossimIOStream& out) +{ + char buf[1024]; + bool done = false; + + while(!done&&!in.fail()) + { + in.read(buf, 1024); + if(in.gcount() < 1024) + { + done = true; + } + if(in.gcount() > 0) + { + out.write(buf, in.gcount()); + } + } + + return out; +} + +void operator << (ossimOStream& out, ossimIStream& in) +{ + char buf[1024]; + bool done = false; + + while(!done&&!in.fail()) + { + in.read(buf, 1024); + if(in.gcount() < 1024) + { + done = true; + } + if(in.gcount() > 0) + { + out.write(buf, in.gcount()); + } + } +} + +void operator << (ossimOStream& out, ossimIOStream& in) +{ + char buf[1024]; + bool done = false; + + while(!done&&!in.fail()) + { + in.read(buf, 1024); + if(in.gcount() < 1024) + { + done = true; + } + if(in.gcount() > 0) + { + out.write(buf, in.gcount()); + } + } +} + +ossimIOStream& operator << (ossimIOStream& out, ossimIStream& in) +{ + char buf[1024]; + bool done = false; + + while(!done&&!in.fail()) + { + in.read(buf, 1024); + if(in.gcount() < 1024) + { + done = true; + } + if(in.gcount() > 0) + { + out.write(buf, in.gcount()); + } + } + + return out; +} + +ossimIOStream& operator << (ossimIOStream& out, ossimIOStream& in) +{ + char buf[1024]; + bool done = false; + + while(!done&&!in.fail()) + { + in.read(buf, 1024); + if(in.gcount() < 1024) + { + done = true; + } + if(in.gcount() > 0) + { + out.write(buf, in.gcount()); + } + } + + return out; +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimIoStream.h b/Utilities/OSSIM/ossim_core/base/common/ossimIoStream.h new file mode 100644 index 0000000000..498c0f6f22 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimIoStream.h @@ -0,0 +1,342 @@ +#ifndef ossimIoStream_HEADER +#define ossimIoStream_HEADER +#include "ossimProtocolStream.h" +#include <iostream> +#include <fstream> +#include <sstream> + + +class OSSIM_DLL ossimIStream : public ossimProtocolStream, public std::istream +{ +public: + ossimIStream():std::istream((std::streambuf*)0){} + ossimIStream(std::streambuf* buf):ossimProtocolStream(buf),std::istream(buf) + {} + void init(std::streambuf* buf) + { + ossimProtocolStream::init(buf); + std::istream::init(buf); + } +TYPE_DATA +}; + +class OSSIM_DLL ossimOStream : public ossimProtocolStream, public std::ostream +{ +public: + ossimOStream():std::ostream((std::streambuf*)0){} + ossimOStream(std::streambuf* buf):ossimProtocolStream(buf),std::ostream(buf) + {} + void init(std::streambuf* buf) + { + ossimProtocolStream::init(buf); + std::ostream::init(buf); + } + +TYPE_DATA +}; + +class OSSIM_DLL ossimIOStream : public ossimProtocolStream, public std::iostream +{ +public: + ossimIOStream():ossimProtocolStream((std::streambuf*)0),std::iostream((std::streambuf*)0){} + ossimIOStream(std::streambuf* buf):ossimProtocolStream(buf),std::iostream(buf) + {} + void init(std::streambuf* buf) + { + ossimProtocolStream::init(buf); + std::iostream::init(buf); + } + +TYPE_DATA +}; + +class OSSIM_DLL ossimIOMemoryStream : public ossimIOStream +{ +protected: + std::stringbuf theBuf; + +public: + ossimIOMemoryStream() + :theBuf(std::ios::in|std::ios::out) + { + ossimIOStream::init(&theBuf); + } + bool is_open()const + { + return true; + } + virtual void open(const char* protocolString, + int openMode) + { + } + ossimString str() + { + return theBuf.str(); + } + virtual void close() + {} + + ossim_uint32 size()const + { + ossimIOMemoryStream* thisPtr = const_cast<ossimIOMemoryStream*>(this); + std::streampos pos = thisPtr->tellg(); + thisPtr->seekg(0, std::ios::end); + std::streampos endPos = thisPtr->tellg(); + thisPtr->seekg(pos, std::ios::beg); + + return (ossim_uint32)(endPos); + } + virtual bool isCompressed()const + { + return false; + } +}; + +class OSSIM_DLL ossimIMemoryStream : public ossimIStream +{ +protected: + std::stringbuf theBuf; + +public: + ossimIMemoryStream(const ossimString& inputBuf) + :theBuf(inputBuf.c_str(), + std::ios::in) + { + ossimIStream::init(&theBuf); + } + bool is_open()const + { + return true; + } + ossim_uint32 size()const + { + ossimIMemoryStream* thisPtr = const_cast<ossimIMemoryStream*>(this); + std::streampos pos = thisPtr->tellg(); + thisPtr->seekg(0, std::ios::end); + std::streampos endPos = thisPtr->tellg(); + thisPtr->seekg(pos, std::ios::beg); + return (ossim_uint32)(endPos); + } + virtual void open(const char* protocolString, + int openMode) + { + } + virtual void close(){} + ossimString str() + { + return theBuf.str(); + } + virtual bool isCompressed()const + { + return false; + } +}; + +class OSSIM_DLL ossimOMemoryStream : public ossimOStream +{ +protected: + std::stringbuf theBuf; + +public: + ossimOMemoryStream() + :theBuf(std::ios::out) + { + ossimOStream::init(&theBuf); + } + bool is_open()const + { + return true; + } + ossim_uint32 size()const + { + ossimOMemoryStream* thisPtr = const_cast<ossimOMemoryStream*>(this); + std::streampos pos = thisPtr->tellp(); + thisPtr->seekp(0, std::ios::end); + std::streampos endPos = thisPtr->tellp(); + thisPtr->seekp(pos, std::ios::beg); + return (ossim_uint32)(endPos); + } + virtual void open(const char* protocolString, + int openMode) + { + } + virtual void close() + {} + + ossimString str() + { + return theBuf.str(); + } + virtual bool isCompressed()const + { + return false; + } +}; + +class OSSIM_DLL ossimIOFStream : public ossimIOStream +{ +protected: + std::filebuf theBuf; + +public: + ossimIOFStream() + { + ossimIOStream::init(&theBuf); + } + ossimIOFStream(const char* name, + int openMode=std::ios::in|std::ios::out|std::ios::binary) + { + ossimIOStream::init(&theBuf); + open(name, openMode); + } + virtual ~ossimIOFStream() + { + if(is_open()) + { + close(); + } + } + + std::filebuf* rdbuf() + { + return &theBuf; + } + + virtual void open(const char* name, + int openMode=std::ios::in|std::ios::out|std::ios::binary) + { + if(!theBuf.open(name, (std::ios::openmode)openMode)) + { + this->setstate(std::ios::failbit); + } + } + virtual void close() + { + if(!theBuf.close()) + { + this->setstate(std::ios::failbit); + } + } + virtual bool is_open()const + { + return theBuf.is_open(); + } + virtual bool isCompressed()const + { + return false; + } +TYPE_DATA +}; + +class OSSIM_DLL ossimIFStream : public ossimIStream +{ +protected: + std::filebuf theBuf; + +public: + ossimIFStream() + { + ossimIStream::init(&theBuf); + } + ossimIFStream(const char* name, + int openMode=std::ios::in|std::ios::binary) + { + ossimIStream::init(&theBuf); + open(name, openMode); + } + virtual ~ossimIFStream() + { + if(is_open()) + { + close(); + } + } + + std::filebuf* rdbuf() { return &theBuf; } + virtual void open(const char* name, + int openMode = std::ios::in|std::ios::binary) + { + if(!theBuf.open(name, (std::ios::openmode)openMode)) + { + this->setstate(std::ios::failbit); + } + } + virtual void close() + { + if(!theBuf.close()) + { + this->setstate(std::ios::failbit); + } + } + virtual bool is_open()const + { + return theBuf.is_open(); + } + virtual bool isCompressed()const + { + return false; + } +TYPE_DATA +}; + +class OSSIM_DLL ossimOFStream : public ossimOStream +{ +protected: + std::filebuf theBuf; + +public: + ossimOFStream() + { + ossimOStream::init(&theBuf); + } + ossimOFStream(const char* name, + int openMode=std::ios::out) + { + ossimOStream::init(&theBuf); + open(name, openMode); + } + virtual ~ossimOFStream() + { + if(is_open()) + { + close(); + } + } + std::filebuf* rdbuf() { return &theBuf; } + virtual void open(const char* name, + int openMode = std::ios::out) + { + if(!theBuf.open(name, (std::ios::openmode)openMode)) + { + this->setstate(std::ios::failbit); + } + } + virtual void close() + { + if(!theBuf.close()) + { + this->setstate(std::ios::failbit); + } + } + virtual bool is_open()const + { + return theBuf.is_open(); + } + virtual bool isCompressed()const + { + return false; + } +TYPE_DATA +}; + +OSSIM_DLL void operator >> (ossimIStream& in,ossimOStream& out); +OSSIM_DLL ossimIOStream& operator >> (ossimIStream& in,ossimIOStream& out); +OSSIM_DLL void operator >> (ossimIOStream& in,ossimOStream& out); +OSSIM_DLL ossimIOStream& operator >> (ossimIOStream& in,ossimIOStream& out); +OSSIM_DLL void operator << (ossimOStream& out, ossimIStream& in); +OSSIM_DLL void operator << (ossimOStream& out, ossimIOStream& in); +OSSIM_DLL ossimIOStream& operator << (ossimIOStream& out, ossimIStream& in); +OSSIM_DLL ossimIOStream& operator << (ossimIOStream& out, ossimIOStream& in); + + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimKeywordNames.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimKeywordNames.cpp new file mode 100644 index 0000000000..4078a58dd8 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimKeywordNames.cpp @@ -0,0 +1,173 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Ken Melero (kmelero@remotesensing.org) +// Description: Common file for global Keywords. +// +//************************************************************************* +// $Id: ossimKeywordNames.cpp,v 1.40 2005/11/16 17:44:11 dburken Exp $ + +#include "ossimKeywordNames.h" + +const char* ossimKeywordNames::AZIMUTH_ANGLE_KW = "azimuth_angle"; +const char* ossimKeywordNames::BAND_KW = "band"; +const char* ossimKeywordNames::BORDER_SIZE_KW = "border_size"; +const char* ossimKeywordNames::BRUSH_COLOR_KW = "brush_color"; +const char* ossimKeywordNames::BYTE_ORDER_KW = "byte_order"; +const char* ossimKeywordNames::CENTRAL_MERIDIAN_KW = "central_meridian"; +const char* ossimKeywordNames::CENTRAL_POINT1_LAT_KW = "central_point1_lat"; +const char* ossimKeywordNames::CENTRAL_POINT1_LON_KW = "central_point1_lon"; +const char* ossimKeywordNames::CENTRAL_POINT2_LAT_KW = "central_point2_lat"; +const char* ossimKeywordNames::CENTRAL_POINT2_LON_KW = "central_point2_lon"; +const char* ossimKeywordNames::CENTER_PIXEL_X_KW = "center_pixel_x"; +const char* ossimKeywordNames::CENTER_PIXEL_Y_KW = "center_pixel_y"; +const char* ossimKeywordNames::COMPRESS_KW = "compress"; +const char* ossimKeywordNames::COMPRESSION_QUALITY_KW = "compression_quality"; +const char* ossimKeywordNames::COMPRESSION_TYPE_KW = "compression_type"; +const char* ossimKeywordNames::CONVERGENCE_THRESHOLD_KW = "convergence_threshold"; +const char* ossimKeywordNames::CREATE_EXTERNAL_GEOMETRY_KW = "create_external_geometry"; +const char* ossimKeywordNames::CREATE_IMAGE_KW = "create_image"; +const char* ossimKeywordNames::CREATE_HISTOGRAM_KW = "create_histogram"; +const char* ossimKeywordNames::CREATE_OVERVIEW_KW = "create_overview"; +const char* ossimKeywordNames::DATA_FILE_KW = "data_file"; +const char* ossimKeywordNames::DATE_KW = "date"; +const char* ossimKeywordNames::DATUM_KW = "datum"; +const char* ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LAT = "decimal_degrees_per_pixel_lat"; +const char* ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LON = "decimal_degrees_per_pixel_lon"; +const char* ossimKeywordNames::DESCRIPTION_KW = "description"; +const char* ossimKeywordNames::ELEVATION_ANGLE_KW = "elevation_angle"; +const char* ossimKeywordNames::ELEVATION_CELL_KW = "elevation_cell"; +const char* ossimKeywordNames::ELEVATION_SOURCE_KW = "elevation_source"; +const char* ossimKeywordNames::ELLIPSE_CODE_KW = "ellipse_code"; +const char* ossimKeywordNames::ELLIPSE_NAME_KW = "ellipse_name"; +const char* ossimKeywordNames::ENABLED_KW = "enabled"; +const char* ossimKeywordNames::ENABLE_CACHE_KW = "enable_cache"; +const char* ossimKeywordNames::ENTRY_KW = "entry"; +const char* ossimKeywordNames::FALSE_EASTING_KW = "false_easting"; +const char* ossimKeywordNames::FALSE_NORTHING_KW = "false_northing"; +const char* ossimKeywordNames::FEATURE_NAME_KW = "feature_name"; +const char* ossimKeywordNames::FILENAME_KW = "filename"; +const char* ossimKeywordNames::FILEPATH_KW = "filepath"; +const char* ossimKeywordNames::FILL_FLAG_KW = "fill_flag"; +const char* ossimKeywordNames::GEOM_FILE_KW = "geom_file"; +const char* ossimKeywordNames::HEMISPHERE_KW = "hemisphere"; +const char* ossimKeywordNames::HORIZONTAL_SIZE_KW = "horizontal_size"; +const char* ossimKeywordNames::ID_KW ="id"; +const char* ossimKeywordNames::IMAGE_FILE_KW = "image_file"; +const char* ossimKeywordNames::IMAGE_PATH_KW = "image_path"; +const char* ossimKeywordNames::IMAGE_TYPE_KW = "image_type"; +const char* ossimKeywordNames::IMAGE_DATE_KW = "image_date"; +const char* ossimKeywordNames::IMAGE_FILE_SIZE_KW = "image_file_size"; +const char* ossimKeywordNames::INPUT_RR_LEVEL_KW = "input_rr_level"; +const char* ossimKeywordNames::INTERLEAVE_TYPE_KW = "interleave_type"; +const char* ossimKeywordNames::JULIAN_DAY_KW = "julian_day"; +const char* ossimKeywordNames::LAT_INCREMENT_KW = "lat_increment"; +const char* ossimKeywordNames::LL_LAT_KW = "ll_lat"; +const char* ossimKeywordNames::LL_LON_KW = "ll_lon"; +const char* ossimKeywordNames::LR_LAT_KW = "lr_lat"; +const char* ossimKeywordNames::LR_LON_KW = "lr_lon"; +const char* ossimKeywordNames::LL_X_KW = "ll_x"; +const char* ossimKeywordNames::LL_Y_KW = "ll_y"; +const char* ossimKeywordNames::LR_X_KW = "lr_x"; +const char* ossimKeywordNames::LR_Y_KW = "lr_y"; +const char* ossimKeywordNames::LON_INCREMENT_KW = "lon_increment"; +const char* ossimKeywordNames::MAJOR_AXIS_KW = "major_axis"; +const char* ossimKeywordNames::MAX_VALUE_KW = "max_value"; +const char* ossimKeywordNames::MAX_ITERATIONS_KW = "max_iterations"; +const char* ossimKeywordNames::MAX_QUADTREE_LEVELS_KW = "max_quadtree_levels"; +const char* ossimKeywordNames::METADATA_TYPE_KW = "metadata_type"; +const char* ossimKeywordNames::METERS_PER_PIXEL_X_KW = "meters_per_pixel_x"; +const char* ossimKeywordNames::METERS_PER_PIXEL_Y_KW = "meters_per_pixel_y"; +const char* ossimKeywordNames::MINOR_AXIS_KW = "minor_axis"; +const char* ossimKeywordNames::MIN_VALUE_KW = "min_value"; +const char* ossimKeywordNames::NULL_VALUE_KW = "null_value"; +const char* ossimKeywordNames::NUMBER_BANDS_KW = "number_bands"; +const char* ossimKeywordNames::NUMBER_ENTRIES_KW = "number_entries"; +const char* ossimKeywordNames::NUMBER_INPUT_BANDS_KW = "number_input_bands"; +const char* ossimKeywordNames::NUMBER_INPUTS_KW = "number_inputs"; +const char* ossimKeywordNames::NUMBER_OUTPUTS_KW = "number_outputs"; +const char* ossimKeywordNames::NUMBER_OUTPUT_BANDS_KW = "number_output_bands"; +const char* ossimKeywordNames::NUMBER_LINES_KW = "number_lines"; +const char* ossimKeywordNames::NUMBER_REDUCED_RES_SETS_KW = "number_reduced_res_sets"; +const char* ossimKeywordNames::NUMBER_SAMPLES_KW = "number_samples"; +const char* ossimKeywordNames::ORIGIN_X_KW = "origin_x"; +const char* ossimKeywordNames::ORIGIN_Y_KW = "origin_y"; +const char* ossimKeywordNames::ORIGIN_LATITUDE_KW = "origin_latitude"; +const char* ossimKeywordNames::OUTPUT_FILE_KW = "output_file"; +const char* ossimKeywordNames::OUTPUT_FILE_PREFIX_KW = "output_file_prefix"; +const char* ossimKeywordNames::OUTPUT_FILE_EXTENSION_KW = "output_file_extension"; +const char* ossimKeywordNames::OVERVIEW_COMPRESSION_QUALITY_KW = "overview_compression_quality"; +const char* ossimKeywordNames::OVERVIEW_COMPRESSION_TYPE_KW = "overview_compression_type"; +const char* ossimKeywordNames::OVERVIEW_FILE_KW = "overview_file"; +const char* ossimKeywordNames::PCS_CODE_KW = "pcs_code"; +const char* ossimKeywordNames::PEN_COLOR_KW = "pen_color"; +const char* ossimKeywordNames::PHOTOMETRIC_KW = "photometric"; +const char* ossimKeywordNames::PIXEL_TYPE_KW = "pixel_type"; +const char* ossimKeywordNames::PLANAR_CONFIG_KW = "planar_config"; +const char* ossimKeywordNames::POINT_WIDTH_HEIGHT_KW = "point_width_height"; +const char* ossimKeywordNames::PROJECTION_KW = "projection"; +const char* ossimKeywordNames::QUALITY_KW = "quality"; +const char* ossimKeywordNames::RADIOMETRY_KW = "radiometry"; +const char* ossimKeywordNames::REDUCED_RES_LEVEL_KW = "reduced_res_level"; +const char* ossimKeywordNames::ROTATION_KW = "rotation"; +const char* ossimKeywordNames::SCALE_PER_PIXEL_X_KW = "scale_per_pixel_x"; +const char* ossimKeywordNames::SCALE_PER_PIXEL_Y_KW = "scale_per_pixel_y"; +const char* ossimKeywordNames::SCALAR_TYPE_KW = "scalar_type"; +const char* ossimKeywordNames::SCALE_FACTOR_KW = "scale_factor"; +const char* ossimKeywordNames::SCALE_FACTOR_X_KW = "scale_factor_x"; +const char* ossimKeywordNames::SCALE_FACTOR_Y_KW = "scale_factor_y"; +const char* ossimKeywordNames::SCALE_X_KW = "scale_x"; +const char* ossimKeywordNames::SCALE_Y_KW = "scale_y"; +const char* ossimKeywordNames::STD_PARALLEL_1_KW = "std_parallel_1"; +const char* ossimKeywordNames::STD_PARALLEL_2_KW = "std_parallel_2"; +const char* ossimKeywordNames::THICKNESS_KW = "thickness"; +const char* ossimKeywordNames::TIE_POINT_EASTING_KW = "tie_point_easting"; // ???? +const char* ossimKeywordNames::TIE_POINT_NORTHING_KW = "tie_point_northing"; // ???? +const char* ossimKeywordNames::TIE_POINT_X_KW = "tie_point_x"; // ???? +const char* ossimKeywordNames::TIE_POINT_Y_KW = "tie_point_y"; // ???? +const char* ossimKeywordNames::TIE_POINT_LAT_KW = "tie_point_lat"; +const char* ossimKeywordNames::TIE_POINT_LON_KW = "tie_point_lon"; +const char* ossimKeywordNames::TILE_SIZE_X_KW = "tile_size_x"; +const char* ossimKeywordNames::TILE_SIZE_Y_KW = "tile_size_y"; +const char* ossimKeywordNames::TILE_SOURCE_KW = "tile_source"; +const char* ossimKeywordNames::TILE_TYPE_KW = "tile_type"; +const char* ossimKeywordNames::TRANSLATION_X_KW = "translation_x"; +const char* ossimKeywordNames::TRANSLATION_Y_KW = "translation_y"; +const char* ossimKeywordNames::TYPE_KW = "type"; +const char* ossimKeywordNames::UL_LAT_KW = "ul_lat"; +const char* ossimKeywordNames::UL_LON_KW = "ul_lon"; +const char* ossimKeywordNames::UNITS_KW = "units"; +const char* ossimKeywordNames::UR_LAT_KW = "ur_lat"; +const char* ossimKeywordNames::UR_LON_KW = "ur_lon"; +const char* ossimKeywordNames::UL_X_KW = "ul_x"; +const char* ossimKeywordNames::UL_Y_KW = "ul_y"; +const char* ossimKeywordNames::UR_X_KW = "ur_x"; +const char* ossimKeywordNames::UR_Y_KW = "ur_y"; +const char* ossimKeywordNames::VERTICAL_SIZE_KW = "vertical_size"; +const char* ossimKeywordNames::ZONE_KW = "zone"; + +ossimKeywordNames::ossimKeywordNames() +{} + +ossimKeywordNames::ossimKeywordNames(const ossimKeywordNames& /* rhs */) +{} + +const ossimKeywordNames& ossimKeywordNames::operator=(const ossimKeywordNames& /* rhs */) +{ + return *this; +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimKeywordNames.h b/Utilities/OSSIM/ossim_core/base/common/ossimKeywordNames.h new file mode 100644 index 0000000000..0ebeb8f6f2 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimKeywordNames.h @@ -0,0 +1,181 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Ken Melero (kmelero@remotesensing.org) +// Description: Common file for global Keywors. +// +//************************************************************************* +// $Id: ossimKeywordNames.h,v 1.41 2005/11/16 17:44:11 dburken Exp $ + +#ifndef ossimKeywordNames_HEADER +#define ossimKeywordNames_HEADER +#include "ossimConstants.h" + +class OSSIMDLLEXPORT ossimKeywordNames +{ +public: + //*** + // NOTE: List keyword in alphabetical order. + //*** + static const char* AZIMUTH_ANGLE_KW; + static const char* BAND_KW; + static const char* BORDER_SIZE_KW; + static const char* BRUSH_COLOR_KW; + static const char* BYTE_ORDER_KW; + static const char* CENTER_PIXEL_X_KW; + static const char* CENTER_PIXEL_Y_KW; + static const char* CENTRAL_MERIDIAN_KW; + static const char* CENTRAL_POINT1_LAT_KW; + static const char* CENTRAL_POINT1_LON_KW; + static const char* CENTRAL_POINT2_LAT_KW; + static const char* CENTRAL_POINT2_LON_KW; + static const char* COMPRESS_KW; + static const char* COMPRESSION_QUALITY_KW; + static const char* COMPRESSION_TYPE_KW; + static const char* CONVERGENCE_THRESHOLD_KW; + static const char* CREATE_EX_KW; + static const char* CREATE_EXTERNAL_GEOMETRY_KW; + static const char* CREATE_IMAGE_KW; + static const char* CREATE_HISTOGRAM_KW; + static const char* CREATE_OVERVIEW_KW; + static const char* DATA_FILE_KW; + static const char* DATE_KW; + static const char* DATUM_KW; + static const char* DECIMAL_DEGREES_PER_PIXEL_LAT; + static const char* DECIMAL_DEGREES_PER_PIXEL_LON; + static const char* DESCRIPTION_KW; + static const char* ELEVATION_ANGLE_KW; + static const char* ELEVATION_CELL_KW; + static const char* ELEVATION_SOURCE_KW; + static const char* ELLIPSE_CODE_KW; + static const char* ELLIPSE_NAME_KW; + static const char* ENABLED_KW; + static const char* ENABLE_CACHE_KW; + static const char* ENTRY_KW; + static const char* FALSE_EASTING_KW; + static const char* FALSE_NORTHING_KW; + static const char* FEATURE_NAME_KW; + static const char* FILENAME_KW; + static const char* FILEPATH_KW; + static const char* FILL_FLAG_KW; + static const char* GEOM_FILE_KW; + static const char* HEMISPHERE_KW; + static const char* HORIZONTAL_SIZE_KW; + static const char* ID_KW; + static const char* IMAGE_FILE_KW; + static const char* IMAGE_PATH_KW; + static const char* IMAGE_TYPE_KW; + static const char* IMAGE_DATE_KW; + static const char* IMAGE_FILE_SIZE_KW; + static const char* INPUT_RR_LEVEL_KW; + static const char* INTERLEAVE_TYPE_KW; + static const char* JULIAN_DAY_KW; + static const char* LAT_INCREMENT_KW; + static const char* LL_LAT_KW; + static const char* LL_LON_KW; + static const char* LR_LAT_KW; + static const char* LR_LON_KW; + static const char* LL_X_KW; + static const char* LL_Y_KW; + static const char* LR_X_KW; + static const char* LR_Y_KW; + static const char* LON_INCREMENT_KW; + static const char* MAJOR_AXIS_KW; + static const char* MAX_VALUE_KW; + static const char* MAX_ITERATIONS_KW; + static const char* MAX_QUADTREE_LEVELS_KW; + static const char* METADATA_TYPE_KW; + static const char* METERS_PER_PIXEL_X_KW; + static const char* METERS_PER_PIXEL_Y_KW; + static const char* MINOR_AXIS_KW; + static const char* MIN_VALUE_KW; + static const char* NULL_VALUE_KW; + static const char* NUMBER_BANDS_KW; + static const char* NUMBER_ENTRIES_KW; + static const char* NUMBER_INPUT_BANDS_KW; + static const char* NUMBER_INPUTS_KW; + static const char* NUMBER_OUTPUTS_KW; + static const char* NUMBER_OUTPUT_BANDS_KW; + static const char* NUMBER_LINES_KW; + static const char* NUMBER_REDUCED_RES_SETS_KW; + static const char* NUMBER_SAMPLES_KW; + static const char* ORIGIN_LATITUDE_KW; + static const char* ORIGIN_X_KW; + static const char* ORIGIN_Y_KW; + static const char* OUTPUT_FILE_KW; + static const char* OUTPUT_FILE_PREFIX_KW; + static const char* OUTPUT_FILE_EXTENSION_KW; + static const char* OVERVIEW_COMPRESSION_QUALITY_KW; + static const char* OVERVIEW_COMPRESSION_TYPE_KW; + static const char* OVERVIEW_FILE_KW; + static const char* PCS_CODE_KW; + static const char* PEN_COLOR_KW; + static const char* PHOTOMETRIC_KW; + static const char* PIXEL_TYPE_KW; + static const char* PLANAR_CONFIG_KW; + static const char* POINT_WIDTH_HEIGHT_KW; + static const char* PROJECTION_KW; + static const char* QUALITY_KW; + static const char* RADIOMETRY_KW; + static const char* REDUCED_RES_LEVEL_KW; + static const char* ROTATION_KW; + static const char* SCALAR_TYPE_KW; + static const char* SCALE_PER_PIXEL_X_KW; + static const char* SCALE_PER_PIXEL_Y_KW; + static const char* SCALE_FACTOR_KW; + static const char* SCALE_X_KW; + static const char* SCALE_Y_KW; + static const char* SCALE_FACTOR_X_KW; + static const char* SCALE_FACTOR_Y_KW; + static const char* STD_PARALLEL_1_KW; + static const char* STD_PARALLEL_2_KW; + static const char* THICKNESS_KW; + static const char* TIE_POINT_EASTING_KW; + static const char* TIE_POINT_NORTHING_KW; + static const char* TIE_POINT_X_KW; + static const char* TIE_POINT_Y_KW; + static const char* TIE_POINT_LAT_KW; + static const char* TIE_POINT_LON_KW; + static const char* TILE_SOURCE_KW; + static const char* TILE_TYPE_KW; + static const char* TILE_SIZE_X_KW; + static const char* TILE_SIZE_Y_KW; + static const char* TRANSLATION_X_KW; + static const char* TRANSLATION_Y_KW; + static const char* TYPE_KW; + static const char* UL_LAT_KW; + static const char* UL_LON_KW; + static const char* UNITS_KW; + + static const char* UR_LAT_KW; + static const char* UR_LON_KW; + static const char* UL_X_KW; + static const char* UL_Y_KW; + static const char* UR_X_KW; + static const char* UR_Y_KW; + static const char* VERTICAL_SIZE_KW; + static const char* ZONE_KW; + + +protected: + ossimKeywordNames(); + ossimKeywordNames(const ossimKeywordNames& rhs); + const ossimKeywordNames& operator =(const ossimKeywordNames &rhs); +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimLeastSquaresBilin.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimLeastSquaresBilin.cpp new file mode 100644 index 0000000000..b4d1095f56 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimLeastSquaresBilin.cpp @@ -0,0 +1,151 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com +// +// Description: Source code produced by Dave Knopp +// +//******************************************************************* +// $Id: ossimLeastSquaresBilin.cpp,v 1.4 2004/04/02 13:51:14 gpotts Exp $ +#include <iostream> // for debugging +using namespace std; +#include <base/common/ossimLeastSquaresBilin.h> +#include <base/context/ossimNotifyContext.h> + +ossimLeastSquaresBilin::ossimLeastSquaresBilin() + : bl_a(0.0) + , bl_b(0.0) + , bl_c(0.0) + , bl_d(0.0) + , AtA(NULL) + , Atb(NULL) +{ + // allocate normal system accumulation matrices + AtA = new NEWMAT::Matrix(4,4); + Atb = new NEWMAT::Matrix(4,1); + + // ensure initilization to zero + *AtA = 0.0; + *Atb = 0.0; + + return; +} +ossimLeastSquaresBilin::ossimLeastSquaresBilin(const ossimLeastSquaresBilin &rhs) +{ + // allocate normal system accumulation matrices + AtA = new NEWMAT::Matrix(4,4); + Atb = new NEWMAT::Matrix(4,1); + + bl_a = rhs.bl_a; + bl_b = rhs.bl_b; + bl_c = rhs.bl_c; + bl_d = rhs.bl_d; + + *AtA = *rhs.AtA; + *Atb = *rhs.Atb; +} + +ossimLeastSquaresBilin::~ossimLeastSquaresBilin() +{ + if(AtA) + { + delete AtA; + AtA = NULL; + } + if(Atb) + { + delete Atb; + Atb = NULL; + } +} +ossimLeastSquaresBilin & ossimLeastSquaresBilin::operator = (const ossimLeastSquaresBilin &rhs) +{ + bl_a = rhs.bl_a; + bl_b = rhs.bl_b; + bl_c = rhs.bl_c; + bl_d = rhs.bl_d; + + *AtA = *rhs.AtA; + *Atb = *rhs.Atb; + + return *this; +} + +void ossimLeastSquaresBilin::clear() +{ + *AtA = 0.0; + *Atb = 0.0; + bl_a = 0.0; + bl_b = 0.0; + bl_c = 0.0; + bl_d = 0.0; +} + +void ossimLeastSquaresBilin::addSample(double xx, double yy, double zmea) +{ + // form normal system layer + NEWMAT::Matrix AtA_layer(4,1); + AtA_layer(1,1) = 1.0; + AtA_layer(2,1) = xx; + AtA_layer(3,1) = yy; + AtA_layer(4,1) = xx*yy; + + // accumulate layer into normal system + *AtA += AtA_layer * AtA_layer.t(); + *Atb += AtA_layer * zmea; + +} + +bool ossimLeastSquaresBilin::solveLS() +{ + NEWMAT::Matrix Soln(4,1); + Soln = AtA->i() * (*Atb); + bl_a = Soln(1,1); + bl_b = Soln(2,1); + bl_c = Soln(3,1); + bl_d = Soln(4,1); + + + return true; +} + +bool ossimLeastSquaresBilin::getLSParms(double& pa, + double& pb_x, + double& pc_y, + double& pd_xy)const +{ + pa = bl_a; + pb_x = bl_b; + pc_y = bl_c; + pd_xy = bl_d; + + return true; +} + +void ossimLeastSquaresBilin::setLSParams(double pa, + double pb_x, + double pc_y, + double pd_xy) +{ + bl_a = pa; + bl_b = pb_x; + bl_c = pc_y; + bl_d = pd_xy; +} + + diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimLeastSquaresBilin.h b/Utilities/OSSIM/ossim_core/base/common/ossimLeastSquaresBilin.h new file mode 100644 index 0000000000..51866ce154 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimLeastSquaresBilin.h @@ -0,0 +1,146 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com +// +// Description: Source code produced by Dave Knopp +// +//******************************************************************* +// $Id: ossimLeastSquaresBilin.h,v 1.4 2004/04/02 13:49:19 gpotts Exp $ +#ifndef ossimLeastSquaresBilin_INCLUDE +#define ossimLeastSquaresBilin_INCLUDE +#include <base/common/ossimConstants.h> +#include <matrix/newmat.h> + +/** + * @brief Provide 2D Least Squares Bilinear model fitting + * The math model is that of a bilinear surface of the form: +@code +z(x,y) = a + b*x + c*y + d*x*y +@endcode + * The getLSParms() method returns parameter values which are the least + * squares solution associated with the samples added via addSample(). Note + * that it is necessary to add at least four sample to obtain a solution. + */ + +class OSSIMDLLEXPORT ossimLeastSquaresBilin +{ +public: + + ossimLeastSquaresBilin(const ossimLeastSquaresBilin &); + /** + * Instantiate as zero surface. + */ + ossimLeastSquaresBilin(); + + ossimLeastSquaresBilin & operator = (const ossimLeastSquaresBilin &); + + /** + * Free internal storage. + */ + virtual ~ossimLeastSquaresBilin(); + + + /** + * Will clear everything and set it up to + * for another solve. Just add points + * and call the solve method. + */ + virtual void clear(); + + /** + * add a single data sample. + * + * @param xx "x" coordinate of sample location. + * @param yy "y" "y" coordinate of sample location. + * @param zmea sample value measured at (xx,yy) + */ + virtual void addSample(double x, double yy, double zmea); + + /** + * return LS solution parameters. + * + * @param pa set to constant coefficient. + * @param pb_x set to linear coefficient of "x" + * @param pc_y set to linear coefficient of "y" + * @param pd_xy set to cross coefficient of "x*y" + */ + virtual bool getLSParms(double& pa, double& pb_x, double& pc_y, double& pd_xy)const; + + /** + * @param pa set to constant coefficient. + * @param pb_x set to linear coefficient of "x" + * @param pc_y set to linear coefficient of "y" + * @param pd_xy set to cross coefficient of "x*y" + */ + virtual void setLSParams(double pa, //constant + double pb_x, // linear coefficient of x, + double pc_y, // linear coefficient of y + double pd_xy); // coefficient of x*y + + /** + * interpolate LS-fit value at location (xx,yy) - returns z(xx,yy). + * + * @param xx "x" coordinate at which to interpolate. + * @param yy "y" "y" coordinate at which to interpolate. + * + */ + virtual inline double lsFitValue(double xx, double yy) const + { + return (bl_a + bl_b*xx + bl_c*yy + bl_d*xx*yy); + } + + /** + * compute least squares parameter solution - true if succesfull. + */ + bool solveLS(); + +private: + /** + * constant term. + */ + double bl_a; + + /** + * linear-X term. + */ + double bl_b; + + /** + * linear-Y term. + */ + double bl_c; + + /** + * cross-XY term + */ + double bl_d; + + /** + * Normal system coefficient matrix. + */ + NEWMAT::Matrix* AtA; + + /** + * Normal system RHS vector + */ + NEWMAT::Matrix* Atb; +}; + +#endif // LeastSquaresBilinilin_INCL_ + diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimMutex.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimMutex.cpp new file mode 100644 index 0000000000..c067345436 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimMutex.cpp @@ -0,0 +1,54 @@ +//************************************************************************* +// Copyright (C) 2004 Intelligence Data Sytems, Inc. All rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +//************************************************************************** +// $Id: ossimMutex.cpp,v 1.3 2005/11/07 22:06:07 dburken Exp $ + +#include <base/common/ossimMutex.h> + +ossimMutex::ossimMutex() +#ifdef OSSIM_HAS_OPEN_THREADS +# if OSSIM_HAS_OPEN_THREADS + : theMutex() +# endif +#endif +{} + +ossimMutex::~ossimMutex() +{} + +int ossimMutex::lock() +{ +#ifdef OSSIM_HAS_OPEN_THREADS +# if OSSIM_HAS_OPEN_THREADS + return theMutex.lock(); +# endif +#endif + return 0; +} + +int ossimMutex::unlock() +{ +#ifdef OSSIM_HAS_OPEN_THREADS +# if OSSIM_HAS_OPEN_THREADS + return theMutex.unlock(); +# endif +#endif + return 0; +} + +int ossimMutex::trylock() +{ +#ifdef OSSIM_HAS_OPEN_THREADS +# if OSSIM_HAS_OPEN_THREADS + return theMutex.trylock(); +# endif +#endif + return 0; +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimMutex.h b/Utilities/OSSIM/ossim_core/base/common/ossimMutex.h new file mode 100644 index 0000000000..132e7c3101 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimMutex.h @@ -0,0 +1,77 @@ +//************************************************************************* +// Copyright (C) 2004 Intelligence Data Sytems, Inc. All rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +//************************************************************************** +// $Id: ossimMutex.h,v 1.5 2005/11/07 22:06:07 dburken Exp $ +#ifndef ossimMutex_HEADER +#define ossimMutex_HEADER + +#include <ossimConfig.h> /* to pick up platform defines */ +#include <base/common/ossimReferenced.h> + +#ifdef OSSIM_HAS_OPEN_THREADS +# if OSSIM_HAS_OPEN_THREADS +# include <OpenThreads/Mutex> +# endif +#endif + +/** + * ossimMutex is a wrapper around OpenThreads::Mutex to allow for builds with + * or without the package. + */ +class ossimMutex : public ossimReferenced +{ +public: + + /** + * Constructor + */ + ossimMutex(); + + /** + * Destructor + */ + ~ossimMutex(); + + /** + * Lock the mutex + * + * @return 0 if normal, -1 if errno set, errno code otherwise. + * + * @note If #ifdef OSSIM_HAS_OPEN_THREADS is not set, always returns 0. + */ + int lock(); + + /** + * Unlock the mutex + * + * @return 0 if normal, -1 if errno set, errno code otherwise. + * + * @note If #ifdef OSSIM_HAS_OPEN_THREADS is not set, always returns 0. + */ + int unlock(); + + /** + * Test if mutex can be locked. + * + * @return 0 if normal, -1 if errno set, errno code otherwise. + * + * @note If #ifdef OSSIM_HAS_OPEN_THREADS is not set, always returns 0. + */ + int trylock(); + +private: +#ifdef OSSIM_HAS_OPEN_THREADS +# if OSSIM_HAS_OPEN_THREADS + OpenThreads::Mutex theMutex; +# endif +#endif + +}; +#endif /* ossimMutex_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimNBandLutDataObject.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimNBandLutDataObject.cpp new file mode 100644 index 0000000000..de2f3c7907 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimNBandLutDataObject.cpp @@ -0,0 +1,342 @@ +//******************************************************************* +// Copyright (C) 2005 Garrett Potts +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +// Contains class declaration for TiffWriter. +// +//******************************************************************* +// $Id: ossimNBandLutDataObject.cpp,v 1.7 2005/11/14 11:58:06 gpotts Exp $ +#include <sstream> +#include <base/misc/lookup_tables/ossimScalarTypeLut.h> +#include <base/common/ossimNBandLutDataObject.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/common/ossimKeywordNames.h> +#include <base/data_types/ossimFilename.h> +#include <base/context/ossimNotifyContext.h> + +RTTI_DEF1(ossimNBandLutDataObject, "ossimNBandLutDataObject", ossimObject); + +ostream& operator <<(ostream& out, + const ossimNBandLutDataObject& lut) +{ + if(lut.theLut) + { + out << ossimKeywordNames::NUMBER_ENTRIES_KW << ": " << lut.theNumberOfEntries << std::endl; + out << ossimKeywordNames::NUMBER_BANDS_KW << ": " << lut.theNumberOfBands << std::endl; + out << "null_pixel_index: " << lut.theNullPixelIndex << std::endl; + for(ossim_uint32 idx = 0; idx < lut.theNumberOfEntries; ++idx) + { + const ossimNBandLutDataObject::LUT_ENTRY_TYPE *bandPtr =lut[idx]; + ossim_uint32 bandIdx = 0; + out << ossimKeywordNames::ENTRY_KW << idx << ": "; + for(bandIdx = 0; bandIdx < lut.theNumberOfBands; ++bandIdx) + { + out << bandPtr[bandIdx] << " "; + } + if(idx < (lut.theNumberOfEntries-1)) + { + out << std::endl; + } + } + } + return out; +} + +ossimNBandLutDataObject::ossimNBandLutDataObject(ossim_uint32 numberOfEntries, + ossim_uint32 numberOfBands, + ossimScalarType bandScalarType, + ossim_int32 nullPixelIndex) + :theLut(0), + theNumberOfEntries(0), + theNumberOfBands(0), + theBandScalarType(bandScalarType), + theNullPixelIndex(nullPixelIndex) +{ + create(numberOfEntries, numberOfBands); +} + +ossimNBandLutDataObject::ossimNBandLutDataObject(const ossimNBandLutDataObject& lut) + :theLut(0), + theNumberOfEntries(lut.theNumberOfEntries), + theNumberOfBands(lut.theNumberOfBands), + theBandScalarType(lut.theBandScalarType), + theNullPixelIndex(lut.theNullPixelIndex) +{ + *this = lut; + +} + +ossimNBandLutDataObject::~ossimNBandLutDataObject() +{ + if(theLut) + { + delete [] theLut; + theLut = 0; + } + theNumberOfEntries = 0; + theNumberOfBands = 0; +} + +void ossimNBandLutDataObject::create(ossim_uint32 numberOfEntries, + ossim_uint32 numberOfBands) +{ + if(theLut) + { + delete [] theLut; + theLut = 0; + } + if(numberOfEntries&&numberOfBands) + { + theLut = new ossimNBandLutDataObject::LUT_ENTRY_TYPE[numberOfEntries*numberOfBands]; + theNumberOfEntries = numberOfEntries; + theNumberOfBands = numberOfBands; + } + else + { + theNumberOfEntries = 0; + theNumberOfBands = 0; + } +} + +ossim_uint32 ossimNBandLutDataObject::findIndex(ossimNBandLutDataObject::LUT_ENTRY_TYPE* bandValues)const +{ + ossim_float64 distance = 1.0/DBL_EPSILON; + ossim_uint32 result = 0; + + if(theNumberOfEntries > 0) + { + ossim_uint32 idx = 0; + ossim_uint32 bandIdx = 0; + ossimNBandLutDataObject::LUT_ENTRY_TYPE* lutPtr = theLut; + for(idx = 0; idx < theNumberOfEntries; ++idx,lutPtr+=theNumberOfBands) + { + ossim_float64 sumSquare = 0.0; + + for(bandIdx = 0; bandIdx < theNumberOfBands; ++bandIdx) + { + ossim_int64 delta = lutPtr[bandIdx] - bandValues[bandIdx]; + sumSquare += (delta*delta); + } + if((ossimNBandLutDataObject::LUT_ENTRY_TYPE)sumSquare == 0) + { + return idx; + } + else if( sumSquare < distance) + { + result = idx; + distance = sumSquare; + } + } + } + + return result; +} + +void ossimNBandLutDataObject::clearLut() +{ + if(theLut) + { + memset(theLut, '\0', theNumberOfEntries*theNumberOfBands*sizeof(ossimNBandLutDataObject::LUT_ENTRY_TYPE)); + } +} + +void ossimNBandLutDataObject::getMinMax(ossim_uint32 band, + ossimNBandLutDataObject::LUT_ENTRY_TYPE& minValue, + ossimNBandLutDataObject::LUT_ENTRY_TYPE& maxValue) +{ + minValue = 0; + maxValue = 0; + ossim_uint32 idx = 0; + LUT_ENTRY_TYPE *bandPtr = theLut+theNumberOfBands; + if((band < theNumberOfBands)&& + (theNumberOfEntries > 0)) + { + minValue = theLut[band]; + maxValue = theLut[band]; + + for(idx = 1; idx < theNumberOfEntries; ++idx,bandPtr+=theNumberOfBands) + { + if((ossim_int32)idx != theNullPixelIndex) + { + if(bandPtr[band] < minValue) + { + minValue = bandPtr[band]; + } + if(bandPtr[band] > maxValue) + { + maxValue = bandPtr[band]; + } + } + } + } +} + +const ossimNBandLutDataObject& ossimNBandLutDataObject::operator =(const ossimNBandLutDataObject& lut) +{ + if(theNumberOfEntries != lut.theNumberOfEntries) + { + delete [] theLut; + theLut = 0; + } + + theNullPixelIndex = lut.theNullPixelIndex; + theBandScalarType = lut.theBandScalarType; + create(lut.theNumberOfEntries, + lut.theNumberOfBands); + + if(theLut) + { + memcpy(theLut, lut.theLut, (theNumberOfEntries*theNumberOfBands)*sizeof(ossimNBandLutDataObject::LUT_ENTRY_TYPE)); + } + + return *this; +} + +bool ossimNBandLutDataObject::operator ==(const ossimNBandLutDataObject& lut)const +{ + if(theNumberOfEntries != lut.theNumberOfEntries) + { + return false; + } + + if(!theLut && !lut.theLut) return true; + if(theNullPixelIndex != lut.theNullPixelIndex) return false; + if(theBandScalarType != lut.theBandScalarType) return false; + + if(theLut&&lut.theLut) + { + return (memcmp(theLut, lut.theLut, theNumberOfEntries*theNumberOfBands*sizeof(ossimNBandLutDataObject::LUT_ENTRY_TYPE)) == 0); + } + return false; +} + +bool ossimNBandLutDataObject::saveState(ossimKeywordlist& kwl, const char* prefix)const +{ + kwl.add(prefix, + ossimKeywordNames::TYPE_KW, + getClassName(), + true); + kwl.add(prefix, + ossimKeywordNames::NUMBER_ENTRIES_KW, + ossimString::toString(theNumberOfEntries).c_str(), + true); + kwl.add(prefix, + ossimKeywordNames::NUMBER_BANDS_KW, + theNumberOfBands, + true); + kwl.add(prefix, + ossimKeywordNames::NULL_VALUE_KW, + theNullPixelIndex, + true); + kwl.add(prefix, + ossimKeywordNames::SCALAR_TYPE_KW, + ossimScalarTypeLut::instance()->getEntryString(theBandScalarType), + true); + + ossimNBandLutDataObject::LUT_ENTRY_TYPE* lutPtr = theLut; + for(ossim_uint32 idx = 0; idx < theNumberOfEntries; ++idx, lutPtr+=theNumberOfBands) + { + ossimString newPrefix = ossimKeywordNames::ENTRY_KW; + newPrefix += ossimString::toString(idx); + std::ostringstream ostr; + ossim_uint32 bandIdx = 0; + for(bandIdx = 0; bandIdx < theNumberOfBands; ++bandIdx) + { + ostr << lutPtr[bandIdx] + << " "; + } + kwl.add(prefix, + newPrefix, + ostr.str().c_str(), + true); + } + + return true; +} + +bool ossimNBandLutDataObject::open(const ossimFilename& lutFile) +{ + ossimKeywordlist kwl; + kwl.addFile(lutFile); + + return loadState(kwl); +} + +bool ossimNBandLutDataObject::loadState(const ossimKeywordlist& kwl, const char* prefix) +{ + const char* nullPixelIndex = kwl.find(prefix, ossimKeywordNames::NULL_VALUE_KW); + const char* lutFile = kwl.find(prefix, ossimKeywordNames::FILENAME_KW); + ossimKeywordlist fileLut; + const ossimKeywordlist* tempKwl = &kwl; + ossimString tempPrefix = prefix; + + // check to see if we should open an external file + // if so point the fileLut to the one that we use + if(lutFile) + { + ossimFilename filename(lutFile); + if(filename.exists()) + { + fileLut.addFile(filename.c_str()); + tempKwl = &fileLut; + tempPrefix = ""; + } + } + + if(nullPixelIndex) + { + theNullPixelIndex = ossimString(nullPixelIndex).toInt32(); + } + else + { + theNullPixelIndex = -1; + } + int scalar = ossimScalarTypeLut::instance()->getEntryNumber(kwl, prefix); + + if (scalar != ossimLookUpTable::NOT_FOUND) + { + theBandScalarType = static_cast<ossimScalarType>(scalar); + } + const char* numberOfBands = tempKwl->find(tempPrefix, ossimKeywordNames::NUMBER_BANDS_KW); + const char* numberOfEntries = tempKwl->find(tempPrefix, ossimKeywordNames::NUMBER_ENTRIES_KW); + + create(ossimString(numberOfEntries).toUInt32(), + ossimString(numberOfBands).toUInt32()); + clearLut(); + ossimNBandLutDataObject::LUT_ENTRY_TYPE* lutPtr = theLut; + + if(lutPtr) + { + ossim_uint32 entryIdx; + ossim_uint32 bandIdx; + for(entryIdx = 0; entryIdx < theNumberOfEntries; ++entryIdx) + { + ossimString newPrefix = "entry"; + newPrefix += ossimString::toString(entryIdx); + ossimString v = tempKwl->find(tempPrefix, newPrefix.c_str()); + v = v.trim(); + if(v != "") + { + std::istringstream istr(v); + + for(bandIdx = 0; bandIdx < theNumberOfBands; ++bandIdx) + { + if(!istr.fail()) + { + istr >> lutPtr[bandIdx]; + } + } + } + lutPtr += theNumberOfBands; + } + } + + return true; +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimNBandLutDataObject.h b/Utilities/OSSIM/ossim_core/base/common/ossimNBandLutDataObject.h new file mode 100644 index 0000000000..c4fc70999c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimNBandLutDataObject.h @@ -0,0 +1,456 @@ +//******************************************************************* +// Copyright (C) 2005 Garrett Potts +// +// LICENSE: LGPL See top level license file. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimNBandLutDataObject.h,v 1.5 2005/09/06 16:23:41 gpotts Exp $ +#ifndef ossimNBandLutDataObject_HEADER +#define ossimNBandLutDataObject_HEADER +#include "base/common/ossimObject.h" +#include "base/data_types/ossimFilename.h" +#include <iostream> + +/** + * class ossimNBandLutDataObject + * + * Sample CADRG LUT taken from an arbitrary CADRG image entry. This is a keywordlist + * support by the loadstate of this class. + * + * <pre> + * entry0: 25 39 116 + * entry1: 245 242 242 + * entry10: 92 89 115 + * entry100: 74 55 85 + * entry101: 233 165 53 + * entry102: 75 2 4 + * entry103: 162 118 42 + * entry104: 233 159 130 + * entry105: 189 129 40 + * entry106: 154 109 66 + * entry107: 145 97 85 + * entry108: 121 86 31 + * entry109: 238 151 118 + * entry11: 52 31 76 + * entry110: 239 167 42 + * entry111: 236 137 100 + * entry112: 179 112 88 + * entry113: 92 37 33 + * entry114: 121 66 24 + * entry115: 120 133 151 + * entry116: 76 92 192 + * entry117: 36 50 117 + * entry118: 57 75 191 + * entry119: 125 45 50 + * entry12: 235 217 204 + * entry120: 102 65 81 + * entry121: 172 148 199 + * entry122: 204 145 95 + * entry123: 81 19 5 + * entry124: 91 4 1 + * entry125: 109 54 31 + * entry126: 137 114 118 + * entry127: 230 150 52 + * entry128: 82 38 87 + * entry129: 190 120 76 + * entry13: 244 218 172 + * entry130: 170 109 45 + * entry131: 95 20 22 + * entry132: 150 80 61 + * entry133: 225 122 82 + * entry134: 122 37 16 + * entry135: 146 88 49 + * entry136: 122 94 122 + * entry137: 230 135 63 + * entry138: 137 73 75 + * entry139: 119 46 29 + * entry14: 189 167 141 + * entry140: 190 142 128 + * entry141: 242 216 187 + * entry142: 176 125 95 + * entry143: 193 117 143 + * entry144: 19 0 0 + * entry145: 12 1 42 + * entry146: 24 4 26 + * entry147: 38 40 52 + * entry148: 8 24 175 + * entry149: 40 23 45 + * entry15: 245 213 142 + * entry150: 39 11 58 + * entry151: 10 0 22 + * entry152: 236 148 41 + * entry153: 101 41 11 + * entry154: 230 113 67 + * entry155: 148 44 46 + * entry156: 225 144 133 + * entry157: 115 2 13 + * entry158: 159 79 49 + * entry159: 164 95 33 + * entry16: 246 241 205 + * entry160: 97 6 22 + * entry161: 175 90 133 + * entry162: 112 23 20 + * entry163: 105 22 6 + * entry164: 148 59 33 + * entry165: 215 118 104 + * entry166: 211 122 41 + * entry167: 233 129 34 + * entry168: 153 73 25 + * entry169: 208 102 39 + * entry17: 240 215 89 + * entry170: 206 101 133 + * entry171: 229 113 96 + * entry172: 127 16 25 + * entry173: 224 104 28 + * entry174: 171 76 74 + * entry175: 221 94 78 + * entry176: 229 86 94 + * entry177: 213 80 57 + * entry178: 161 44 36 + * entry179: 155 54 19 + * entry18: 115 92 157 + * entry180: 130 25 5 + * entry181: 150 29 24 + * entry182: 198 54 34 + * entry183: 224 61 70 + * entry184: 213 82 37 + * entry185: 186 28 31 + * entry186: 200 64 15 + * entry187: 110 2 2 + * entry188: 195 38 12 + * entry189: 151 6 8 + * entry19: 160 163 37 + * entry190: 193 13 10 + * entry191: 205 1 3 + * entry192: 44 62 193 + * entry193: 35 14 16 + * entry194: 15 30 118 + * entry195: 28 47 189 + * entry196: 25 3 80 + * entry197: 7 16 118 + * entry198: 33 10 6 + * entry199: 39 24 95 + * entry2: 216 212 237 + * entry20: 38 29 21 + * entry200: 82 58 159 + * entry201: 55 29 142 + * entry202: 33 4 23 + * entry203: 17 14 36 + * entry204: 58 26 41 + * entry205: 11 13 14 + * entry206: 74 87 85 + * entry207: 50 60 41 + * entry208: 119 123 98 + * entry209: 193 187 172 + * entry21: 208 202 156 + * entry210: 124 126 128 + * entry211: 47 68 84 + * entry212: 110 119 60 + * entry213: 63 145 121 + * entry214: 154 166 147 + * entry215: 107 156 104 + * entry22: 242 202 152 + * entry23: 168 148 140 + * entry24: 31 22 25 + * entry25: 245 205 114 + * entry26: 245 191 137 + * entry27: 175 161 172 + * entry28: 17 6 11 + * entry29: 172 170 137 + * entry3: 247 230 113 + * entry30: 51 27 20 + * entry31: 239 210 73 + * entry32: 185 176 129 + * entry33: 35 2 13 + * entry34: 60 52 51 + * entry35: 101 78 70 + * entry36: 141 124 101 + * entry37: 206 184 107 + * entry38: 244 174 106 + * entry39: 82 98 136 + * entry4: 246 231 132 + * entry40: 190 191 239 + * entry41: 241 188 161 + * entry42: 67 51 38 + * entry43: 244 184 122 + * entry44: 211 201 142 + * entry45: 61 27 16 + * entry46: 182 182 82 + * entry47: 243 188 87 + * entry48: 86 83 60 + * entry49: 61 40 43 + * entry5: 204 198 166 + * entry50: 146 141 93 + * entry51: 44 4 4 + * entry52: 231 210 51 + * entry53: 85 74 39 + * entry54: 197 169 127 + * entry55: 182 151 60 + * entry56: 121 98 73 + * entry57: 243 182 145 + * entry58: 58 18 21 + * entry59: 241 157 91 + * entry6: 2 0 2 + * entry60: 59 4 1 + * entry61: 155 162 223 + * entry62: 154 133 80 + * entry63: 73 21 16 + * entry64: 195 183 116 + * entry65: 76 51 29 + * entry66: 234 181 63 + * entry67: 58 59 98 + * entry68: 42 22 79 + * entry69: 134 143 219 + * entry7: 204 204 239 + * entry70: 106 117 205 + * entry71: 48 65 117 + * entry72: 63 54 117 + * entry73: 125 93 62 + * entry74: 137 138 41 + * entry75: 104 68 59 + * entry76: 113 99 41 + * entry77: 76 30 11 + * entry78: 239 184 48 + * entry79: 161 129 98 + * entry8: 31 4 66 + * entry80: 241 170 126 + * entry81: 145 109 105 + * entry82: 207 163 116 + * entry83: 79 41 40 + * entry84: 175 138 41 + * entry85: 10 0 56 + * entry86: 180 151 77 + * entry87: 72 12 24 + * entry88: 242 154 105 + * entry89: 91 26 15 + * entry9: 246 238 162 + * entry90: 160 118 53 + * entry91: 228 166 141 + * entry92: 231 160 69 + * entry93: 61 2 11 + * entry94: 132 83 60 + * entry95: 86 46 24 + * entry96: 243 143 86 + * entry97: 108 60 46 + * entry98: 109 76 38 + * entry99: 96 86 84 + * null_value: -1 + * number_bands: 3 + * number_entries: 216 + * scalar_type: ossim_uint8 + * type: ossimNBandLutDataObject + * + * + * NOTES: + * + * - The null_value keyword above is the index in the lut that correspnds to an invalid pixel value. + * - Each entry will have number_bands. SO if number of bands is 3 then there will be 3 values + * Where the first value is for band 1, ... etc. + * - scalar_type is a hint as to the scalar type of the entries. Is the resulting lut for 8 bit, 16 bit , etc data. + * - You should always use the LUT_ENTRY_TYPE when getting values from the lut. This value could change to an + * ossim_float32 precision and if you use the LUT_ENTRY_TYPE then your code will not have to change. + * + * </pre> + */ +class OSSIM_DLL ossimNBandLutDataObject : public ossimObject +{ +public: + + typedef ossim_int32 LUT_ENTRY_TYPE; + + friend std::ostream& operator <<(std::ostream& out, + const ossimNBandLutDataObject& lut); + /*! + * Will allocate 256 values for the color table + */ + ossimNBandLutDataObject(ossim_uint32 numberOfEntries=0, + ossim_uint32 numberOfBands=0, + ossimScalarType bandScalarType = OSSIM_UINT8, + ossim_int32 nullPixelIndex=-1); + ossimNBandLutDataObject(const ossimNBandLutDataObject& lut); + virtual ~ossimNBandLutDataObject(); + void create(ossim_uint32 numberOfEntries, + ossim_uint32 numberOfBands=3); + const LUT_ENTRY_TYPE* operator[](ossim_uint32 idx)const + { + if(theLut) + { + return &theLut[idx*theNumberOfBands]; + } + + return 0; + } + LUT_ENTRY_TYPE* operator[](ossim_uint32 idx) + { + if(theLut) + { + return &theLut[idx*theNumberOfBands]; + } + + return 0; + } + const LUT_ENTRY_TYPE* operator[](ossim_int32 idx)const + { + if(theLut) + { + return &theLut[idx*theNumberOfBands]; + } + + return 0; + } + LUT_ENTRY_TYPE* operator[](ossim_int32 idx) + { + if(theLut) + { + return &theLut[idx*theNumberOfBands]; + } + + return 0; + } + const LUT_ENTRY_TYPE* operator[](double normalizedIndex)const + { + int idx = int(normalizedIndex*theNumberOfEntries); + if (idx < 0) + { + idx = 0; + } + return (*this)[idx]; + } + + /** + * @param normalizedIndex If a double precision value is passed in then it is + * assumed to be in normalized space where the value ranges from 0.0 to 1.0 + * @return the starting address of the band values. + */ + LUT_ENTRY_TYPE* operator[](double normalizedIndex) + { + ossim_uint32 idx = int(normalizedIndex*(theNumberOfEntries-1)); + if (idx >= theNumberOfEntries) + { + idx = theNumberOfEntries-1; + } + return (*this)[idx]; + } + + bool hasNullPixelIndex()const + { + return (theNullPixelIndex >= 0); + } + /** + * Will return the min max value for a given band + * + * @param band band number to query. This is 0 based so the first band + * is indicated by the value of 0. + * @param minValue is the minimum value returned for the passed in band + * @param maxValue is the maximum value returned for the passed in band + */ + void getMinMax(ossim_uint32 band, + LUT_ENTRY_TYPE& minValue, + LUT_ENTRY_TYPE& maxValue); + + /** + * Allows you to specify which entry is to be designated as an invalid + * entry. Note: setting this to -1 indicates no null entry is set. + * + * @param idx is the entry number that will be used for the null value + */ + void setNullPixelIndex(ossim_int32 idx){theNullPixelIndex = idx;} + + /** + * @return Return either a positive value indicating the entry designated for + * a null pixel value or a -1 to say no null pixel has been designated + * yet. + */ + ossim_int32 getNullPixelIndex()const{return theNullPixelIndex;} + + /** + * @return Return the number of bands this lut is indexed for. + */ + ossim_uint32 getNumberOfBands()const{return theNumberOfBands;} + + /** + * @return Return the number of entries in the lut. + */ + ossim_uint32 getNumberOfEntries()const{return theNumberOfEntries;} + + /** + * This method gives you a way to find an entry index closest to the passed in + * band values. + * + * @param values Is an array of band values. This array must be equal to the number + * of bands for the lut. + * @return Returns the nearest index to the passed in value. + */ + ossim_uint32 findIndex(ossim_int32* values)const; + + /** + * Will do a simple memset to '\0' all + */ + void clearLut(); + /** + * does a deep copy from the passed in lut to the object. + * + * @param lut The lut to copy. + */ + const ossimNBandLutDataObject& operator =(const ossimNBandLutDataObject& lut); + + /** + * Determines if the state of this lut is identical to the passed in lut + * + * @param lut Checks equality of the this object to the lut parameter. + * @return True if equal and false otherwise + */ + bool operator ==(const ossimNBandLutDataObject& lut)const; + + /** + * Reads in an external lut file. The external file is in a keywordlist format specified by the saveState. + */ + bool open(const ossimFilename& lutFile); + + /** + * <pre> + * + * Keywords: + * + * entry0: + * entry1: + * : + * entry<number_entries-1>: + * null_value: -1 + * number_bands: 3 + * number_entries: 216 + * scalar_type: ossim_uint8 + * type: ossimNBandLutDataObject + * + * Where entry<idx> is repeasted for each entry number where idx start from 0 and goes to number_entries-1 + * each entry must have number_bands values. + * </pre> + * + * @param kwl The keyword list to store the keywords to. Each keyword could be prefixed by an optional + * prefix parameter. + * @param prefix The optional prefix parameter used to prefix each keyword. + * + */ + virtual bool saveState(ossimKeywordlist& kwl, const char* prefix=0)const; + + + /** + * Loads the state of the object by reading in the keywords listed in the save state. + * + * @param kwl The keywordlist to extract the classes keywords from to restore its state. + * @param prefix Optional prefix value used to prefix each keyword. + */ + virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix=0); +protected: + LUT_ENTRY_TYPE *theLut; + ossim_uint32 theNumberOfEntries; + ossim_uint32 theNumberOfBands; + ossimScalarType theBandScalarType; + ossim_int32 theNullPixelIndex; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimObject.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimObject.cpp new file mode 100644 index 0000000000..7c17800421 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimObject.cpp @@ -0,0 +1,117 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimObject.cpp,v 1.18 2005/10/14 13:26:01 dburken Exp $ +#include <base/common/ossimObject.h> +#include <base/common/ossimKeywordNames.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/factory/ossimObjectFactoryRegistry.h> +#include <base/context/ossimNotifyContext.h> + +RTTI_DEF(ossimObject, "ossimObject") + +ossimObject::ossimObject() +{} + +ossimObject::~ossimObject() +{ +} + +ossimObject* ossimObject::dup()const +{ + ossimObject* result = NULL; + ossimKeywordlist kwl; + + saveState(kwl); + + result = ossimObjectFactoryRegistry::instance()->createObject(kwl); + + if(!result) + { + ossimNotify(ossimNotifyLevel_WARN) + << "dup() not implemented for object = " + << getClassName() << ". Please implement!\n"; + } + + return result; +} + +ossimString ossimObject::getShortName()const +{ + return getClassName(); +} + +ossimString ossimObject::getLongName()const +{ + return getClassName(); +} + +ossimString ossimObject::getDescription()const +{ + return getLongName(); +} + + +ossimString ossimObject::getClassName()const +{ + return TYPE_NAME(this); +} + +RTTItypeid ossimObject::getType()const +{ + return TYPE_INFO(this); +} + +bool ossimObject::canCastTo(ossimObject* obj)const +{ + if(obj) + { + return obj->getType().can_cast(this->getType()); + } + + return false; +} + +bool ossimObject::canCastTo(const ossimString& parentClassName)const +{ + return (getType().find_baseclass(parentClassName.c_str()) != + getType().null_type()); +} + +bool ossimObject::canCastTo(const RTTItypeid& id)const +{ + return id.can_cast(this->getType()); +} + +bool ossimObject::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + ossimKeywordNames::TYPE_KW, + getClassName(), + true); + + return true; +} + +bool ossimObject::loadState(const ossimKeywordlist&, const char*) +{ + return true; +} + +std::ostream& ossimObject::print(std::ostream& out) const +{ + return out; +} + +std::ostream& operator<<(std::ostream& out, const ossimObject& obj) +{ + return obj.print(out); +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimObject.h b/Utilities/OSSIM/ossim_core/base/common/ossimObject.h new file mode 100644 index 0000000000..f72445e372 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimObject.h @@ -0,0 +1,88 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: Base class for ossim objects. +// +//************************************************************************* +// $Id: ossimObject.h,v 1.25 2005/06/07 17:57:04 dburken Exp $ + +#ifndef ossimObject_HEADER +#define ossimObject_HEADER + +#include <base/common/ossimConstants.h> +#include <base/common/ossimReferenced.h> +#include <base/data_types/ossimString.h> +#include <base/common/ossimRtti.h> +#include <iostream> + +class ossimKeywordlist; + +class OSSIMDLLEXPORT ossimObject : public ossimReferenced +{ +public: + ossimObject(); + virtual ~ossimObject(); + + virtual ossimObject* dup() const; + + virtual ossimString getShortName() const; + virtual ossimString getLongName() const; + virtual ossimString getDescription() const; + virtual ossimString getClassName() const; + + /*! + * Will return the type of this class in an RTTI format. + */ + virtual RTTItypeid getType() const; + + virtual bool canCastTo(ossimObject* obj) const; + + virtual bool canCastTo(const RTTItypeid& id) const; + + /*! + * Will use RTTI to search the derived classes to see if it derives from + * the passed in type. If so then this object can be casted to the + * passed in class name. + */ + virtual bool canCastTo(const ossimString& parentClassName) const; + + /*! + * Method to save the state of the object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0) const; + + /*! + * Method to the load (recreate) the state of the object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * Generic print method. Derived classes should re-implement as they see + * fit. + * + * @return std::ostream& + */ + virtual std::ostream& print(std::ostream& out) const; + + /** + * @note Since the print method is virtual, derived classes only need + * to implement that, not an addition operator<<. + */ + friend OSSIMDLLEXPORT std::ostream& operator<<(std::ostream& out, + const ossimObject& obj); + + protected: +TYPE_DATA +}; + +#endif /* #ifndef ossimObject_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimOutputSource.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimOutputSource.cpp new file mode 100644 index 0000000000..337bd27b19 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimOutputSource.cpp @@ -0,0 +1,15 @@ +#include "ossimOutputSource.h" + +RTTI_DEF1(ossimOutputSource, "ossimOutputSource", ossimSource); + +bool ossimOutputSource::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + return ossimSource::saveState(kwl, prefix); +} + +bool ossimOutputSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + return ossimSource::loadState(kwl, prefix); +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimOutputSource.h b/Utilities/OSSIM/ossim_core/base/common/ossimOutputSource.h new file mode 100644 index 0000000000..edb83e0206 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimOutputSource.h @@ -0,0 +1,107 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Contains class declaration for ossimImageWriter +//******************************************************************* +// $Id: ossimOutputSource.h,v 1.11 2003/05/13 11:31:01 dburken Exp $ +// +#ifndef ossimOutputSource_HEADER +#define ossimOutputSource_HEADER +#include "base/common/ossimConstants.h" +#include "base/common/ossimSource.h" +#include "base/common/ossimCommon.h" + +class OSSIMDLLEXPORT ossimOutputSource : public ossimSource +{ +public: + ossimOutputSource(ossimObject* owner=NULL) + :ossimSource(owner) + {} + ossimOutputSource(ossimObject* owner, + ossim_uint32 inputListSize, + ossim_uint32 outputListSize, + bool inputListIsFixedFlag=true, + bool outputListIsFixedFlag=true) + :ossimSource(owner, + inputListSize, + outputListSize, + inputListIsFixedFlag, + outputListIsFixedFlag) + { + } + + virtual ~ossimOutputSource(){} + + virtual bool isOpen()const = 0; + + /*! + * Allows a generic interface to open a consumer for writing. If + * you are a display writer then you would probably show the window or + * init the device context for writing. + */ + virtual bool open()=0; + + /*! + * Will set the output name and open the output device. + */ + virtual bool open(const ossimString& outputName) + { + setOutputName(outputName); + return open(); + } + + /*! + * This is a generic interface to allow one to set the output name of + * the writer. If its a Visual display this could be used to + * set the title. If this is a file output then this could be a + * directory or a file name. + */ + virtual void setOutputName(const ossimString& outputName) + { + theOutputName = outputName; + } + + virtual const ossimString& getOutputName() + { + return theOutputName; + } + /*! + * Generic interface to allow one to close a consumer. For displays + * this might minimize the window and free up internal pointers for + * file writers it will make sure the file stream is closed and flushed. + */ + virtual void close()=0; + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +protected: + ossimString theOutputName; + + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimPool.h b/Utilities/OSSIM/ossim_core/base/common/ossimPool.h new file mode 100644 index 0000000000..8c3ee640c3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimPool.h @@ -0,0 +1,151 @@ +//******************************************************************** +// Copyright (C) 2004 Intelligence-data, Inc. All rights reserved. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts +// +//********************************************************************** +// $Id: ossimPool.h,v 1.2 2004/04/20 21:26:05 dburken Exp $ +#ifndef ossimPool_HEADER +#define ossimPool_HEADER +#include <iostream> +#include <vector> +#include <exception> +#include <stdexcept> +#include <base/common/ossimCommon.h> +#include <base/common/ossimConstants.h> +#include <base/common/ossimPoolObject.h> +#include <base/context/ossimNotifyContext.h> + +#define OSSIM_DEFAULT_POOL_SIZE (ossim_uint32)10 + +/** + * Container pool to be used for things like threads. + */ +template <class T> +class ossimPool +{ + public: + /** + * Contructor + * @param n Number of pooled objects to create. + */ + ossimPool(ossim_uint32 n=OSSIM_DEFAULT_POOL_SIZE) throw(std::bad_alloc) + : thePool(n) + { + for(ossim_uint32 idx = 0; idx < n; ++idx) + { + try + { + ossimPoolObject<T>* poolObject = new ossimPoolObject<T>(); + poolObject->theAvailableFlag = true; + poolObject->theObjectPtr = new T(); + thePool[idx] = poolObject; + } + catch(std::bad_alloc) + { + ossimNotify(ossimNotifyLevel_FATAL) + << "FATAL ossimPool::ossimPool(): Bad allocation" << endl; + } + } + } + + /** + * Destructor + */ + ~ossimPool() + { + thePool.clear(); + } + + /** + * @return A pooled object of type T*. Will return null if the pool is + * used up or pool size is zero. + */ + T* checkout() + { + T* t = NULL; + + theCriticalSectionMutex.lock(); + for (ossim_uint32 idx = 0; idx < thePool.size(); ++idx) + { + if (thePool[idx]->theAvailableFlag == true) + { + thePool[idx]->theAvailableFlag = false; + t = thePool[idx]->theObjectPtr; + break; + } + } + theCriticalSectionMutex.unlock(); + return t; + } + + /** + * Resets and eturns object to the pool. + * @param obj Object to be returned to the pool. + * + * @note The object is required to have a "reset()" method. + * + * @return Returns void unless object was not from pool then throws + * a std::out_of_range error. + */ + void checkin(T* obj) throw(std::out_of_range) + { + theCriticalSectionMutex.lock(); + for (ossim_uint32 idx = 0; idx < thePool.size(); ++idx) + { + if (obj == thePool[idx]->theObjectPtr) + { + obj->reset(); + thePool[idx]->theAvailableFlag = true; + theCriticalSectionMutex.unlock(); + return; + } + } + + theCriticalSectionMutex.unlock(); + throw std::out_of_range(string("ossimPool<T>::checkin Error Object not managed by this pool!")); + } + + /** + * Outputs object addresses and theAvailableFlag. + */ + std::ostream& print(std::ostream& out) const + { + for (ossim_uint32 idx = 0; idx < thePool.size(); ++idx) + { + out << "obj address: " << (hex) << thePool[idx]->theObjectPtr + << " is " + << (thePool[idx]->theAvailableFlag ? "available":"unavailable") + << endl; + } + return out; + } + + template <class C> friend std::ostream& operator<<(std::ostream& out, + const ossimPool<C>& obj) + { + return obj.print(out); + } + +protected: + + std::vector<ossimPoolObject<T>*> thePool; +}; + +#endif /* #ifndef ossimPool_HEADER */ + diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimPoolObject.h b/Utilities/OSSIM/ossim_core/base/common/ossimPoolObject.h new file mode 100644 index 0000000000..2fce19ab62 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimPoolObject.h @@ -0,0 +1,49 @@ +//******************************************************************** +// Copyright (C) 2004 Intelligence-data, Inc. All rights reserved. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken +// +//********************************************************************** +// $Id: ossimPoolObject.h,v 1.1 2004/04/20 21:26:05 dburken Exp $ +#ifndef ossimPoolObject_HEADER +#define ossimPoolObject_HEADER + + +/** + * Templated container for an object pointer and a flag. + */ +template <class T> +class ossimPoolObject +{ + public: + ~ossimPoolObject() + { + if(theObjectPtr) + { + cout << "deleting obj: " << (hex) << theObjectPtr << endl; + delete theObjectPtr; + theObjectPtr = NULL; + } + theAvailableFlag = false; + } + + + bool theAvailableFlag; + T* theObjectPtr; +}; +#endif /* #ifndef ossimPoolObject_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimPreferences.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimPreferences.cpp new file mode 100644 index 0000000000..81d332871b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimPreferences.cpp @@ -0,0 +1,241 @@ +//***************************************************************************** +// FILE: ossimPreferences.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// DESCRIPTION: +// Contains implementation of class ossimPreferences. This class provides +// a static keywordlist for global preferences. Objects needing access to +// application-wide global parameters shall do so through this class. +// +// SOFTWARE HISTORY: +//> +// 23Apr2001 Oscar Kramer (okramer@imagelinks.com) +// Initial coding. +//< +//***************************************************************************** + +#include <stdlib.h> +#include <iostream> +using namespace std; + +#include <base/common/ossimPreferences.h> +#include <base/context/ossimNotifyContext.h> + +//RTTI_DEF1(ossimPreferences, "ossimPreferences", ossimObject) + +//*** +// Define Trace flags for use within this file: +//*** +#include "base/common/ossimTrace.h" +static ossimTrace traceExec ("ossimPreferences:exec"); +static ossimTrace traceDebug ("ossimPreferences:debug"); + +static const char* PREF_FILE_ENV_VAR_NAME = "OSSIM_PREFS_FILE"; + +ossimPreferences* ossimPreferences::theInstance = NULL; + +ossimPreferences::ossimPreferences() +{ + loadPreferences(); +} + +ossimPreferences::~ossimPreferences() +{ + theInstance = NULL; +} + +/*!**************************************************************************** + * METHOD: ossimPreferences::instance() + * + * This is the method by which run-time objects access this singleton instance + * + *****************************************************************************/ +ossimPreferences* ossimPreferences::instance() +{ + /*! + * Simply return the instance if already created: + */ + if (theInstance) + return theInstance; + + /*! + * Create the static instance of this class: + */ + theInstance = new ossimPreferences(); + + return theInstance; +} + +/*!**************************************************************************** + * METHOD: loadPreferences() + * + * Loads the preferences file specified in the runtime environment. + * + *****************************************************************************/ +bool ossimPreferences::loadPreferences() +{ + static const char MODULE[] = "ossimPreferences::loadPreferences()"; + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG: " << MODULE << " entering...\n"; + + bool parsed_ok = false; + + /*! + * Fetch preferences file name from environment: + */ + char* pref_filename = getenv(PREF_FILE_ENV_VAR_NAME); + + if (pref_filename) + { + /*! + * Load the preferences file into the static keywordlist object: + */ + thePrefFilename = pref_filename; + parsed_ok = theKWL.addFile(pref_filename); + + /*! + * Check for error opening KWL: + */ + if (!parsed_ok) + { + ossimNotify(ossimNotifyLevel_WARN) << "WARNING: " << MODULE << ", an error was encountered loading the prefererences " + << "file at \"" << thePrefFilename << "\" as specified by the " + << "environment variable \"" << PREF_FILE_ENV_VAR_NAME << "\"." + << "Preferences were not loaded.\n"; + } + } + + else + { +// if (traceDebug()) +// { +// // No ENV var found. Print warning: +// CLOG << "WARNING: the preferences file environment variable \"" +// << PREF_FILE_ENV_VAR_NAME << "\" is not defined. No preferences " +// << "were loaded. The environment variable should be set to " +// << "the full path to the preferences keywordlist file desired." +// << endl; +// } + } + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG: " << MODULE << "returning...\n"; + return parsed_ok; +} + +/*!**************************************************************************** + * METHOD: loadPreferences(filename) + * + * Loads the preferences file specified in the arg. + * + *****************************************************************************/ +bool ossimPreferences::loadPreferences(const ossimFilename& pathname) +{ + static const char MODULE[] = "ossimPreferences::loadPreferences(filename)"; + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG: " << MODULE << ", entering...\n"; + + bool parsed_ok; + + /*! + * First clear the existing KWL: + */ + theKWL.clear(); + theInstanceIsModified = true; + + /*! + * Load the preferences file into the static keywordlist object: + */ + thePrefFilename = pathname; + parsed_ok = theKWL.addFile(pathname); + + /*! + * Check for error opening KWL: + */ + if (!parsed_ok) + { + ossimNotify(ossimNotifyLevel_WARN) << "WARNING: " << MODULE << ", an error was encountered loading the prefererences " + << "file at \"" << pathname << "\". Preferences were not " + << "loaded.\n"; + } + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG: " << MODULE<< ", returning...\n"; + return parsed_ok; +} + +/*!**************************************************************************** + * METHOD: ossimPreferences::savePreferences() + * + * Saves KWL to the current filename. + * + *****************************************************************************/ +bool ossimPreferences::savePreferences() const +{ + static const char MODULE[] = "ossimPreferences::savePreferences()"; + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG: " << MODULE << ", entering...\n"; + + bool success = true; + + /*! + * Save the file to current preferences filename: + */ + if (theInstanceIsModified) + { + theKWL.write(thePrefFilename); + theInstanceIsModified = false; + } + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:" << MODULE << ", returning...\n"; + return success; +} + +/*!**************************************************************************** + * METHOD: ossimPreferences::savePreferences(filename) + * + * Saves KWL to the specified filename. + * + *****************************************************************************/ +bool ossimPreferences::savePreferences(const ossimFilename& pathname) +{ + static const char MODULE[] = "ossimPreferences::savePreferences()"; + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG: "<< MODULE << ", entering...\n"; + + bool success = true; + + /*! + * Save the file to the specified preferences filename: + */ + theKWL.write(pathname); + + thePrefFilename = pathname; + theInstanceIsModified = false; + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG: " << MODULE << ", returning...\n"; + return success; +} + +void ossimPreferences::addPreference(const char* key, const char* value) +{ + theKWL.add(key, value, true); + theInstanceIsModified = true; +} + +void ossimPreferences::addPreferences(const ossimKeywordlist& kwl, + const char* prefix, + bool stripPrefix) +{ + theKWL.add(kwl, prefix, stripPrefix); +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimPreferences.h b/Utilities/OSSIM/ossim_core/base/common/ossimPreferences.h new file mode 100644 index 0000000000..359286998d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimPreferences.h @@ -0,0 +1,116 @@ +//***************************************************************************** +// FILE: ossimPreferences.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// DESCRIPTION: +// Contains declaration of class ossimPreferences. This class provides +// a static keywordlist for global preferences. Objects needing access to +// application-wide global parameters shall do so through this class. +// +// SOFTWARE HISTORY: +//> +// 23Apr2001 Oscar Kramer (okramer@imagelinks.com) +// Initial coding. +//< +//***************************************************************************** + +#ifndef ossimPreferences_HEADER +#define ossimPreferences_HEADER + +#include "base/data_types/ossimFilename.h" +#include "base/data_types/ossimKeywordlist.h" +#include "base/common/ossimObject.h" + + + +/*!**************************************************************************** + * + * CLASS: ossimPreferences + * + *****************************************************************************/ +class OSSIMDLLEXPORT ossimPreferences +{ +public: + /*! + * METHOD: instance() + * The static singleton instance of this object is accessed via this method: + */ + static ossimPreferences* instance(); + + /*! + * METHOD: loadPreferences() + * These methods clear the current preferences and load either the default + * preferences file or the specified file. Returns TRUE if loaded properly: + */ + bool loadPreferences(); + bool loadPreferences(const ossimFilename& pathname); + + /*! + * METHOD: savePrefences() + * This method permits saving the preferences file to the default location + * or to a specified location: + */ + bool savePreferences() const; + bool savePreferences(const ossimFilename& pathname); + + /*! + * METHOD: findPreference() + * Performs a lookup for the specified keyword in the preferences KWL: + */ + const char* findPreference(const char* key) const {return theKWL.find(key);} + + + /*! + * METHOD: addPreference() + * Inserts keyword/value pair into the in-memory preferences KWL. It does + * save to disk. App must do a savePreferences() for changes to be saved. + */ + void addPreference(const char* key, + const char* value); + + /*! + * METHOD: preferencesKWL() + * An alternative to utilizing findPreference(), for objects derived from + * ossimObject, is to access the preferences KWL with this method + * (typically during construction) and provide it to the object's + * loadState() method. + */ + const ossimKeywordlist& preferencesKWL() const { return theKWL; } + + void addPreferences(const ossimKeywordlist& kwl, + const char* prefix=0, + bool stripPrefix=true); + +protected: + /*! + * Override the compiler default constructors: + */ + ossimPreferences(); + ossimPreferences(const ossimPreferences&) {} + + ~ossimPreferences(); + void operator = (const ossimPreferences&) const {} + + static ossimPreferences* theInstance; + ossimKeywordlist theKWL; + ossimFilename thePrefFilename; + mutable bool theInstanceIsModified; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimProcessInterface.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimProcessInterface.cpp new file mode 100644 index 0000000000..ee23dabf6b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimProcessInterface.cpp @@ -0,0 +1,143 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimProcessInterface.cpp,v 1.8 2004/10/06 15:33:40 dburken Exp $ +#include "ossimProcessInterface.h" +#include "base/common/events/ossimListenerManager.h" + +using namespace std; + +RTTI_DEF(ossimProcessInterface, "ossimProcessInterface"); + +ossimProcessInterface::ossimProcessInterface() + :thePercentComplete(0.0), + theProcessStatus(PROCESS_STATUS_NOT_EXECUTING), + theMessage(""), + theEventFlag(true) +{ +} + +ossimProcessInterface::~ossimProcessInterface() +{ +} + +void ossimProcessInterface::abort() +{ + if(theProcessStatus == PROCESS_STATUS_EXECUTING) + { + theProcessStatus = PROCESS_STATUS_ABORT_REQUEST; + } +} + +bool ossimProcessInterface::needsAborting() const +{ + return ( isAborted()|| isAbortRequested() ); +} + +bool ossimProcessInterface::isAbortRequested()const +{ + return (theProcessStatus == PROCESS_STATUS_ABORT_REQUEST); +} + +bool ossimProcessInterface::isAborted()const +{ + return (theProcessStatus==PROCESS_STATUS_ABORTED); +} + +bool ossimProcessInterface::isExecuting()const +{ + return ((theProcessStatus==PROCESS_STATUS_EXECUTING)|| + (theProcessStatus==PROCESS_STATUS_ABORT_REQUEST)); +} + +ossimProcessInterface::ossimProcessStatus ossimProcessInterface::getProcessStatus()const +{ + return theProcessStatus; +} + +void ossimProcessInterface::setProcessStatus(ossimProcessStatus processStatus) +{ + theProcessStatus = processStatus; +} + +double ossimProcessInterface::getPercentComplete()const +{ + return thePercentComplete; +} + +void ossimProcessInterface::setPercentComplete(double percentComplete) +{ + thePercentComplete = percentComplete; + + ossimListenerManager* manager = getManager(); + if(theEventFlag&&manager) + { + ossimProcessProgressEvent event(getObject(), + thePercentComplete, + theMessage, + false); + manager->fireEvent(event); + } +} + +ossimListenerManager* ossimProcessInterface::getManager() +{ + return PTR_CAST(ossimListenerManager, getObject()); +} + +void ossimProcessInterface::enableEvents() +{ + theEventFlag = true; +} + +void ossimProcessInterface::disableEvents() +{ + theEventFlag = false; +} + +void ossimProcessInterface::setCurrentMessage(const ossimString& message) +{ + theMessage = message; + + ossimListenerManager* manager = getManager(); + if(theEventFlag&&manager) + { + ossimProcessProgressEvent event(getObject(), + thePercentComplete, + theMessage, + true); + manager->fireEvent(event); + } +} + +ostream& ossimProcessInterface::print(ostream& out) const +{ + out << "process status: "; + if(theProcessStatus == PROCESS_STATUS_EXECUTING) + { + out << "executing" << endl; + } + else if(theProcessStatus == PROCESS_STATUS_ABORTED) + { + out << "aborted" << endl; + } + else if(theProcessStatus == PROCESS_STATUS_NOT_EXECUTING) + { + out << "not executing" << endl; + } + out << "percent_complete: " << thePercentComplete; + + return out; +} + +ostream& operator<<(ostream& out, const ossimProcessInterface& data) +{ + return data.print(out); +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimProcessInterface.h b/Utilities/OSSIM/ossim_core/base/common/ossimProcessInterface.h new file mode 100644 index 0000000000..78a1bae135 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimProcessInterface.h @@ -0,0 +1,88 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimProcessInterface.h,v 1.13 2004/10/06 15:32:02 dburken Exp $ +#ifndef ossimProcessInterface_HEADER +#define ossimProcessInterface_HEADER +#include <iostream> +#include "base/common/ossimRtti.h" +#include "base/data_types/ossimString.h" +#include "base/common/events/ossimProcessProgressEvent.h" +#include "base/common/events/ossimListenerManager.h" + +class OSSIMDLLEXPORT ossimObject; +class OSSIMDLLEXPORT ossimListenerManager; + +class OSSIMDLLEXPORT ossimProcessInterface +{ +public: + + enum ossimProcessStatus + { + PROCESS_STATUS_UNKNOWN = 0, + PROCESS_STATUS_EXECUTING = 1, + PROCESS_STATUS_ABORTED = 2, + PROCESS_STATUS_ABORT_REQUEST = 3, + PROCESS_STATUS_NOT_EXECUTING = 4 + }; + + ossimProcessInterface(); + + virtual ~ossimProcessInterface(); + + virtual ossimObject* getObject()=0; + virtual const ossimObject* getObject()const=0; + virtual bool execute()=0; + + virtual void abort(); + + bool needsAborting()const; + + bool isAbortRequested()const; + + bool isAborted()const; + + bool isExecuting()const; + + ossimProcessStatus getProcessStatus()const; + + virtual void setProcessStatus(ossimProcessStatus processStatus); + + virtual double getPercentComplete()const; + + virtual void setPercentComplete(double percentComplete); + + virtual ossimListenerManager* getManager(); + + void enableEvents(); + + void disableEvents(); + + void setCurrentMessage(const ossimString& message); + + /*! + * Called by friend operator<< function, derived classes should override + * if something different is desired. + */ + virtual std::ostream& print(std::ostream& out) const; + + friend std::ostream& operator<<(std::ostream& out, + const ossimProcessInterface& data); + +protected: + double thePercentComplete; + ossimProcessStatus theProcessStatus; + ossimString theMessage; + bool theEventFlag; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimPropertyInterface.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimPropertyInterface.cpp new file mode 100644 index 0000000000..a817c750ca --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimPropertyInterface.cpp @@ -0,0 +1,77 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossimPropertyInterface.cpp,v 1.10 2004/12/21 14:06:21 gpotts Exp $ +#include "ossimPropertyInterface.h" +#include <base/property/ossimStringProperty.h> + +RTTI_DEF(ossimPropertyInterface, "ossimPropertyInterface"); + +void ossimPropertyInterface::setProperty(const ossimString& name, + const ossimString& value) +{ + ossimRefPtr<ossimProperty> property = new ossimStringProperty(name, value); + + setProperty(property); +} + +void ossimPropertyInterface::setProperty(ossimRefPtr<ossimProperty> property) +{ +} + +ossimRefPtr<ossimProperty> ossimPropertyInterface::getProperty(const ossimString& name)const +{ + return (ossimProperty*)0; +} + +void ossimPropertyInterface::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ +} + + +void ossimPropertyInterface::getPropertyList(std::vector<ossimRefPtr<ossimProperty> >& propertyList)const +{ + std::vector<ossimString> propertyNames; + int idx = 0; + getPropertyNames(propertyNames); + + for(idx = 0; idx < (int)propertyNames.size();++idx) + { + ossimRefPtr<ossimProperty> prop = getProperty(propertyNames[idx]); + if(prop.valid()) + { + propertyList.push_back(prop); + } + } +} + +void ossimPropertyInterface::setProperties(std::vector<ossimRefPtr<ossimProperty> >& propertyList) +{ + ossim_uint32 idx = 0; + + for(idx = 0; idx < propertyList.size(); ++idx) + { + if(propertyList[idx].valid()) + { + setProperty(propertyList[idx]); + } + } +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimPropertyInterface.h b/Utilities/OSSIM/ossim_core/base/common/ossimPropertyInterface.h new file mode 100644 index 0000000000..eb12cb1985 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimPropertyInterface.h @@ -0,0 +1,40 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// LICENSE: LGPL see top level license.txt +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossimPropertyInterface.h,v 1.13 2004/12/21 14:06:21 gpotts Exp $ +#ifndef ossimPropertyInterface_HEADER +#define ossimPropertyInterface_HEADER +#include "base/data_types/ossimKeywordlist.h" +#include "base/common/ossimObject.h" +#include <base/common/ossimRefPtr.h> +#include <base/property/ossimProperty.h> + + +class OSSIM_DLL ossimPropertyInterface +{ +public: + ossimPropertyInterface() + {} + + virtual ~ossimPropertyInterface() + {} + + virtual void setProperty(const ossimString& name, + const ossimString& value); + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + void getPropertyList(std::vector<ossimRefPtr<ossimProperty> >& propertyList)const; + void setProperties(std::vector<ossimRefPtr<ossimProperty> >& propertyList); + +protected: + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimProtocolStream.h b/Utilities/OSSIM/ossim_core/base/common/ossimProtocolStream.h new file mode 100644 index 0000000000..a8f6d7dffd --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimProtocolStream.h @@ -0,0 +1,32 @@ +#ifndef ossimProtocolStream_HEADER +#define ossimProtocolStream_HEADER +#include "ossimStreamBase.h" + +class ossimProtocolStream : public ossimStreamBase +{ +public: + ossimProtocolStream(){} + ossimProtocolStream(std::streambuf* buf):ossimStreamBase(buf) + { + } + + /** + * This is a generic interface to any stream for opening and closing + * If supported this could be an interface to not only file streams + * but also http, https, ftp, ... etc + */ + virtual void open(const char* protocolString, + int openMode=0)=0; + + /** + * Closes the stream + */ + virtual void close()=0; + + + virtual bool is_open()const=0; + + virtual bool isCompressed()const=0; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimQuadrilateralMap.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimQuadrilateralMap.cpp new file mode 100644 index 0000000000..21484819f3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimQuadrilateralMap.cpp @@ -0,0 +1,95 @@ +#include "ossimQuadrilateralMap.h" +#include <iostream> +using namespace std; + +#include "matrix/newmat.h" +#include "matrix/newmatio.h" +#include "matrix/newmatap.h" + +ossimQuadrilateralMap::ossimQuadrilateralMap() + : a(0.0), + b(0.0), + c(0.0), + d(0.0), + e(0.0), + f(0.0), + g(0.0), + h(0.0) +{ +} +ossimQuadrilateralMap::ossimQuadrilateralMap(const ossimDpt& sourceP1, + const ossimDpt& sourceP2, + const ossimDpt& sourceP3, + const ossimDpt& sourceP4, + const ossimDpt& destP1, + const ossimDpt& destP2, + const ossimDpt& destP3, + const ossimDpt& destP4) +{ + solveCoefficients(sourceP1, sourceP2, sourceP3, sourceP4, + destP1, destP2, destP3, destP4); +} + +ossimQuadrilateralMap::ossimQuadrilateralMap(const ossimQuadrilateralMap& rhs) + :a(rhs.a), + b(rhs.b), + c(rhs.c), + d(rhs.d), + e(rhs.e), + f(rhs.f), + g(rhs.g) +{ +} + +void ossimQuadrilateralMap::solveCoefficients(const ossimDpt& sourceP1, + const ossimDpt& sourceP2, + const ossimDpt& sourceP3, + const ossimDpt& sourceP4, + const ossimDpt& destP1, + const ossimDpt& destP2, + const ossimDpt& destP3, + const ossimDpt& destP4) +{ + NEWMAT::Matrix m(8,8); + + m << sourceP1.x << sourceP1.y << 1.0 << 0.0 << 0.0 << 0.0 << -sourceP1.x*destP1.x << -sourceP1.y*destP1.x + << sourceP2.x << sourceP2.y << 1.0 << 0.0 << 0.0 << 0.0 << -sourceP2.x*destP2.x << -sourceP2.y*destP2.x + << sourceP3.x << sourceP3.y << 1.0 << 0.0 << 0.0 << 0.0 << -sourceP3.x*destP3.x << -sourceP3.y*destP3.x + << sourceP4.x << sourceP4.y << 1.0 << 0.0 << 0.0 << 0.0 << -sourceP4.x*destP4.x << -sourceP4.y*destP4.x + << 0.0 << 0.0 << 0.0 << sourceP1.x << sourceP1.y << 1.0 << -sourceP1.x*destP1.y << -sourceP1.y*destP1.y + << 0.0 << 0.0 << 0.0 << sourceP2.x << sourceP2.y << 1.0 << -sourceP2.x*destP2.y << -sourceP2.y*destP2.y + << 0.0 << 0.0 << 0.0 << sourceP3.x << sourceP3.y << 1.0 << -sourceP3.x*destP3.y << -sourceP3.y*destP3.y + << 0.0 << 0.0 << 0.0 << sourceP4.x << sourceP4.y << 1.0 << -sourceP4.x*destP4.y << -sourceP4.y*destP4.y; + + NEWMAT::Matrix A = m.i(); + NEWMAT::ColumnVector b(8); + b << destP1.x << destP2.x << destP3.x << destP4.x << destP1.y << destP2.y << destP3.y << destP4.y; + NEWMAT::ColumnVector y = A * b; + + a = y[0]; + b = y[1]; + c = y[2]; + d = y[3]; + e = y[4]; + f = y[5]; + g = y[6]; + h = y[7]; +} + +void ossimQuadrilateralMap::map(const ossimDpt& source, ossimDpt& dest)const +{ + double numerator; + double denominator; + + //solve x first + numerator = a*source.x + b*source.y + c; + denominator = g*source.x + h*source.y + 1; + + dest.x = numerator/denominator; + + //solve y + numerator = d*source.x + e*source.y + f; + denominator = g*source.x + h*source.y + 1; + + dest.y = numerator/denominator; +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimQuadrilateralMap.h b/Utilities/OSSIM/ossim_core/base/common/ossimQuadrilateralMap.h new file mode 100644 index 0000000000..669e3add43 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimQuadrilateralMap.h @@ -0,0 +1,55 @@ +#ifndef ossimQuadrilateralMap_HEADER +#define ossimQuadrilateralMap_HEADER +#include "base/data_types/ossimDpt.h" + +class OSSIMDLLEXPORT ossimQuadrilateralMap +{ +public: + ossimQuadrilateralMap(const ossimDpt& sourceP1, + const ossimDpt& sourceP2, + const ossimDpt& sourceP3, + const ossimDpt& sourceP4, + const ossimDpt& destP1, + const ossimDpt& destP2, + const ossimDpt& destP3, + const ossimDpt& destP4); + ossimQuadrilateralMap(); + + ossimQuadrilateralMap(const ossimQuadrilateralMap& rhs); + /*! + * Uses a standard form of quadrilateral to quadrilateral + * mapping: + * + * X = (a*U + b*V + c) / (g*U + h*V + 1) + * Y = (d*U + e*V+f)/(g*U + h*V + 1) + * + * where: + * X and Y are the mapped destination point. + * U and V are the source point to warp + * a, b, c, d, e, f, g, h are coefficients sovled by + * the points passed to the constructor. + */ + void map(const ossimDpt& source, ossimDpt& dest)const; + + void solveCoefficients(const ossimDpt& sourceP1, + const ossimDpt& sourceP2, + const ossimDpt& sourceP3, + const ossimDpt& sourceP4, + const ossimDpt& destP1, + const ossimDpt& destP2, + const ossimDpt& destP3, + const ossimDpt& destP4); + +protected: + double a; + double b; + double c; + double d; + double e; + double f; + double g; + double h; + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimRectilinearDataObject.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimRectilinearDataObject.cpp new file mode 100644 index 0000000000..d17919fdbe --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimRectilinearDataObject.cpp @@ -0,0 +1,312 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimRectilinearDataObject.cpp,v 1.12 2005/05/09 12:39:38 dburken Exp $ + +#include <base/common/ossimRectilinearDataObject.h> +#include <base/misc/lookup_tables/ossimScalarTypeLut.h> + +RTTI_DEF1(ossimRectilinearDataObject, "ossimRectilinearDataObject", ossimDataObject); + +ossimRectilinearDataObject::ossimRectilinearDataObject(const ossimRectilinearDataObject& rhs) + : ossimDataObject(rhs), + theNumberOfDataComponents(rhs.theNumberOfDataComponents), + theNumberOfSpatialComponents(rhs.theNumberOfSpatialComponents), + theScalarType(rhs.theScalarType), + theDataBuffer(NULL), + theSpatialExtents(NULL) +{ + if(rhs.theDataBuffer) + { + theDataBuffer = new ossim_uint8[rhs.getDataSizeInBytes()]; + if(theDataBuffer) + { + memcpy(theDataBuffer, rhs.theDataBuffer, rhs.getDataSizeInBytes()); + } + } + if(rhs.theSpatialExtents) + { + theSpatialExtents = new ossim_uint32[rhs.theNumberOfSpatialComponents]; + memcpy(theSpatialExtents, rhs.theSpatialExtents, sizeof(ossim_uint32)*theNumberOfSpatialComponents); + } +} + +ossimRectilinearDataObject::ossimRectilinearDataObject(ossim_uint32 numberOfSpatialComponents, + ossimSource* owner, + ossim_uint32 numberOfDataComponents, + ossimScalarType scalarType, + ossimDataObjectStatus status) + :ossimDataObject(owner, OSSIM_NULL), + theNumberOfDataComponents(numberOfDataComponents), + theNumberOfSpatialComponents(numberOfSpatialComponents), + theScalarType(scalarType), + theDataBuffer(NULL), + theSpatialExtents(NULL) +{ + if(theNumberOfSpatialComponents) + { + theSpatialExtents = new ossim_uint32[theNumberOfSpatialComponents]; + memset(theSpatialExtents, 1, theNumberOfSpatialComponents); + } +} + +ossimRectilinearDataObject::ossimRectilinearDataObject(ossimSource* owner, + ossim_uint32 numberOfDataComponents, + ossim_uint32 length, + ossimScalarType scalarType, + ossimDataObjectStatus status) + :ossimDataObject(owner, OSSIM_NULL), + theNumberOfDataComponents(numberOfDataComponents), + theNumberOfSpatialComponents(1), + theScalarType(scalarType), + theDataBuffer(NULL), + theSpatialExtents(NULL) +{ + + theSpatialExtents = new ossim_uint32[1]; + theSpatialExtents[0] = length; +} + +ossimRectilinearDataObject::ossimRectilinearDataObject(ossimSource* owner, + ossim_uint32 numberOfDataComponents, + ossim_uint32 width, + ossim_uint32 height, + ossimScalarType scalarType, + ossimDataObjectStatus status) + :ossimDataObject(owner, OSSIM_NULL), + theNumberOfDataComponents(numberOfDataComponents), + theNumberOfSpatialComponents(2), + theScalarType(scalarType), + theDataBuffer(NULL), + theSpatialExtents(NULL) +{ + + theSpatialExtents = new ossim_uint32[2]; + theSpatialExtents[0] = width; + theSpatialExtents[1] = height; +} + +ossimRectilinearDataObject::ossimRectilinearDataObject(ossimSource* owner, + ossim_uint32 numberOfDataComponents, + ossim_uint32 width, + ossim_uint32 height, + ossim_uint32 depth, + ossimScalarType scalarType, + ossimDataObjectStatus status) + :ossimDataObject(owner, OSSIM_NULL), + theNumberOfDataComponents(numberOfDataComponents), + theNumberOfSpatialComponents(3), + theScalarType(scalarType), + theDataBuffer(NULL), + theSpatialExtents(NULL) +{ + + theSpatialExtents = new ossim_uint32[3]; + theSpatialExtents[0] = width; + theSpatialExtents[1] = height; + theSpatialExtents[2] = depth; +} + +ossimRectilinearDataObject::~ossimRectilinearDataObject() +{ + if(theDataBuffer) + { + delete [] theDataBuffer; + theDataBuffer = NULL; + } + if(theSpatialExtents) + { + delete [] theSpatialExtents; + theSpatialExtents = NULL; + } + theNumberOfDataComponents = 0; + theNumberOfSpatialComponents = 0; +} + +ossim_uint32 ossimRectilinearDataObject::computeSpatialProduct()const +{ + if(!theSpatialExtents) return 0; + ossim_uint32 spatialProduct = 1; + for(ossim_uint32 index = 0; index < theNumberOfSpatialComponents; ++index) + { + spatialProduct *= theSpatialExtents[index]; + } + + return spatialProduct; +} + +void ossimRectilinearDataObject::setNumberOfDataComponents(ossim_uint32 n) +{ + theNumberOfDataComponents = n; +} + +void ossimRectilinearDataObject::setSpatialExtents(ossim_uint32* extents, + ossim_uint32 size) +{ + if(!extents) return; + if((size != theNumberOfSpatialComponents)&&size) + { + if(theSpatialExtents) + { + delete [] theSpatialExtents; + theSpatialExtents = NULL; + } + theSpatialExtents = new ossim_uint32[size]; + } + int i = 0; + for(i =0; i < (int)size; ++i) + { + theSpatialExtents[i] = extents[i]; + } + theNumberOfSpatialComponents = size; +} + +void ossimRectilinearDataObject::setScalarType(ossimScalarType type) +{ + theScalarType = type; +} + +ossim_uint32 ossimRectilinearDataObject::getNumberOfDataComponents() const +{ + return theNumberOfDataComponents; +} + +ossim_uint32 ossimRectilinearDataObject::getNumberOfSpatialComponents() const +{ + return theNumberOfSpatialComponents; +} + +const ossim_uint32* ossimRectilinearDataObject::getSpatialExtents()const +{ + return theSpatialExtents; +} + +ossimScalarType ossimRectilinearDataObject::getScalarType() const +{ + return theScalarType; +} + +ossim_uint32 ossimRectilinearDataObject::getScalarSizeInBytes() const +{ + return ossimGetScalarSizeInBytes(getScalarType()); +} + +void* ossimRectilinearDataObject::getBuf() +{ + return static_cast<void*>(theDataBuffer); +} + +const void* ossimRectilinearDataObject::getBuf()const +{ + return static_cast<const void*>(theDataBuffer); +} + +void ossimRectilinearDataObject::assign(const ossimRectilinearDataObject* data) +{ + if(!data) return; + ossimDataObject::assign(data); + ossim_uint32 savedSize = getDataSizeInBytes(); + //*** + // This method assumes contiguous buffer for "theData". Override if + // needed. + //*** + + if(theNumberOfSpatialComponents != data->theNumberOfSpatialComponents) + { + delete [] theSpatialExtents; + if(data->theNumberOfSpatialComponents) + { + theSpatialExtents = new ossim_uint32[data->theNumberOfSpatialComponents]; + } + else + { + theSpatialExtents = NULL; + } + } + for(ossim_uint32 index = 0; index < theNumberOfSpatialComponents; ++index) + { + theSpatialExtents[index] = data->theSpatialExtents[index]; + } + + theNumberOfSpatialComponents = data->theNumberOfSpatialComponents; + theNumberOfDataComponents = data->theNumberOfDataComponents; + theScalarType = data->theScalarType; + //*** + // First copy the buffer if there is one. + //*** + if(data->theDataBuffer) + { + //*** + // Make sure this buffer is the same size; if not, delete. + // This could be left alone if bigger than the data buffer; + // however, deleting for now... + //*** + ossim_uint32 source_size = data->getDataSizeInBytes(); + ossim_uint32 newSize = getDataSizeInBytes(); + if(!theDataBuffer) + { + theDataBuffer = new ossim_uint8[source_size]; + } + else if(savedSize != newSize) + { + if(theDataBuffer) + { + delete [] theDataBuffer; + theDataBuffer = NULL; + theDataBuffer = new ossim_uint8[newSize]; + } + } + + // Copy the image data... + memcpy(theDataBuffer, data->theDataBuffer, source_size); + } + if(!theDataBuffer) setDataObjectStatus(OSSIM_NULL); +} + +void ossimRectilinearDataObject::initialize() +{ + deInitialize(); + + ossim_uint32 size = getDataSizeInBytes(); + if(size) + { + theDataBuffer = new ossim_uint8[size]; + } +} + +void ossimRectilinearDataObject::deInitialize() +{ + if(theDataBuffer) + { + delete [] theDataBuffer; + theDataBuffer = NULL; + setDataObjectStatus(OSSIM_NULL); + } +} + +ossim_uint32 ossimRectilinearDataObject::getDataSizeInBytes()const +{ + return (ossim_uint32)(getScalarSizeInBytes()* + computeSpatialProduct()* + theNumberOfDataComponents); +} + +std::ostream& ossimRectilinearDataObject::print(std::ostream& out) const +{ + out << "ossimRectilinearDataObject::print:" + << "\ntheNumberOfDataComponents: " << theNumberOfDataComponents + << "\ntheNumberOfSpatialComponents: " << theNumberOfSpatialComponents; + + out << "\ntheScalarType: " + << (ossimScalarTypeLut::instance()->getEntryString(theScalarType)) + << endl; + + return ossimDataObject::print(out); +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimRectilinearDataObject.h b/Utilities/OSSIM/ossim_core/base/common/ossimRectilinearDataObject.h new file mode 100644 index 0000000000..0eedb60534 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimRectilinearDataObject.h @@ -0,0 +1,156 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossimRectilinearDataObject.h,v 1.9 2004/04/07 23:54:47 dburken Exp $ +#ifndef ossimRectilinearDataObject_HEADER +#define ossimRectilinearDataObject_HEADER +#include "ossimDataObject.h" + +class OSSIMDLLEXPORT ossimRectilinearDataObject : public ossimDataObject +{ +public: + ossimRectilinearDataObject(const ossimRectilinearDataObject&rhs); + + ossimRectilinearDataObject(ossim_uint32 numberOfSpatialComponents, + ossimSource* owner, + ossim_uint32 numberOfDataComponents, + ossimScalarType scalarType=OSSIM_SCALAR_UNKNOWN, + ossimDataObjectStatus status=OSSIM_NULL); + + /** + * This is a helper constructor that allows one to instantiate a one + * dimensional Spatial component with N number of data components. + * It will internally allocate theSpatialExtent to 1 and set the + * contents equal to the value passed in to length. + */ + ossimRectilinearDataObject(ossimSource* owner, + ossim_uint32 numberOfDataComponents, + ossim_uint32 length, + ossimScalarType scalarType=OSSIM_SCALAR_UNKNOWN, + ossimDataObjectStatus status=OSSIM_NULL); + + /** + * This is a helper constructor that allows one to instantiate a two + * dimensional Spatial component (WidthxHeight) with N number of + * data components. It will internally allocate theSpatialExtent + * to 2 and set the contents equal to the value passed in to width, and + * height. + */ + ossimRectilinearDataObject(ossimSource* owner, + ossim_uint32 numberOfDataComponents, + ossim_uint32 width, + ossim_uint32 height, + ossimScalarType scalarType=OSSIM_SCALAR_UNKNOWN, + ossimDataObjectStatus status=OSSIM_NULL); + + /** + * This is a helper constructor that allows one to instantiate a two + * dimensional Spatial component (WidthxHeightxDepth) with N number of + * data components. It will internally allocate theSpatialExtent + * to 3 and set the contents equal to the value passed in to width, + * height, and depth. + */ + ossimRectilinearDataObject(ossimSource* owner, + ossim_uint32 numberOfDataComponents, + ossim_uint32 width, + ossim_uint32 height, + ossim_uint32 depth, + ossimScalarType scalarType=OSSIM_SCALAR_UNKNOWN, + ossimDataObjectStatus status=OSSIM_NULL); + + virtual ~ossimRectilinearDataObject(); + + /** + * How many components make up this data object. For + * example: If this were an RGB image data object then + * the number of components would be set to 3 and the + * RGB would be seen as a single data object being + * passed through. + */ + virtual void setNumberOfDataComponents(ossim_uint32 n); + + virtual void setSpatialExtents(ossim_uint32* extents, ossim_uint32 size); + + /** + * See ossimScalarType in ossimConstants for a full list + * + * OSSIM_SCALAR_UNKNOWN + * OSSIM_UCHAR Unsigned char + * OSSIM_USHORT16 16bit unsigned short + * OSSIM_SSHORT16 16bit signed short + * OSSIM_USHORT11 11bit unsigned short + * OSSIM_FLOAT float + * OSSIM_NORMALIZED_DOUBLE normalized 0 to 1 data + */ + virtual void setScalarType(ossimScalarType type); + + virtual ossim_uint32 getNumberOfDataComponents() const; + + virtual ossim_uint32 getNumberOfSpatialComponents() const; + + virtual const ossim_uint32* getSpatialExtents() const; + + virtual ossimScalarType getScalarType() const; + + virtual ossim_uint32 getScalarSizeInBytes()const; + + virtual void* getBuf(); + + virtual const void* getBuf() const; + + virtual void assign(const ossimRectilinearDataObject* data); + + /** + * Calls deInitialize() which deletes theDataBuffer and sets object status + * to OSSIM_NULL, then initializes theDataBuffer. + * + * @see deInitialize + * + * @note This method is destructive in that if the buffer existed of + * the correct size it will delete it, then reallocate. + */ + virtual void initialize(); + + /** + * If theDataBuffer exist if will delete it then set object status to + * OSSIM_NULL. + * + * @see setDataObjectStatus + */ + virtual void deInitialize(); + + virtual ossim_uint32 computeSpatialProduct()const; + + virtual ossim_uint32 getDataSizeInBytes()const; + + virtual std::ostream& print(std::ostream& out) const; + +protected: + ossim_uint32 theNumberOfDataComponents; + ossim_uint32 theNumberOfSpatialComponents; + ossimScalarType theScalarType; + ossim_uint8* theDataBuffer; + ossim_uint32* theSpatialExtents; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimRefPtr.h b/Utilities/OSSIM/ossim_core/base/common/ossimRefPtr.h new file mode 100644 index 0000000000..1a99324129 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimRefPtr.h @@ -0,0 +1,88 @@ +/* -*-c++-*- ossim - Copyright (C) since 2004 Garrett Potts + * + * This was taken directly from OpenSceneGraph and will retain OSGGPL license. + * This is basically an LGPL. + * +*/ +#ifndef ossimRefPtr_HEADER +#define ossimRefPtr_HEADER +#include <base/common/ossimConstants.h> + +template<class T> class ossimRefPtr +{ + public: + typedef T element_type; + + ossimRefPtr() :thePtr(0) {} + ossimRefPtr(T* t):thePtr(t) { if (thePtr) thePtr->ref(); } + ossimRefPtr(const ossimRefPtr& rp):thePtr(rp.thePtr) { if (thePtr) thePtr->ref(); } + ~ossimRefPtr() { if (thePtr) thePtr->unref(); thePtr=0; } + + inline ossimRefPtr& operator = (const ossimRefPtr& rp) + { + if (thePtr==rp.thePtr) return *this; + T* tmpPtr = thePtr; + thePtr = rp.thePtr; + if (thePtr) thePtr->ref(); + // unref second to prevent any deletion of any object which might + // be referenced by the other object. i.e rp is child of the + // original _ptr. + if (tmpPtr) tmpPtr->unref(); + return *this; + } + + inline ossimRefPtr& operator = (T* ptr) + { + if (thePtr==ptr) return *this; + T* tmpPtr = thePtr; + thePtr = ptr; + if (thePtr) thePtr->ref(); + // unref second to prevent any deletion of any object which might + // be referenced by the other object. i.e rp is child of the + // original thePtr. + if (tmpPtr) tmpPtr->unref(); + return *this; + } + + // comparison operators for ossimRefPtr. + inline bool operator == (const ossimRefPtr& rp) const { return (thePtr==rp.thePtr); } + inline bool operator != (const ossimRefPtr& rp) const { return (thePtr!=rp.thePtr); } + inline bool operator < (const ossimRefPtr& rp) const { return (thePtr<rp.thePtr); } + inline bool operator > (const ossimRefPtr& rp) const { return (thePtr>rp.thePtr); } + + // comparion operator for const T*. + inline bool operator == (const T* ptr) const { return (thePtr==ptr); } + inline bool operator != (const T* ptr) const { return (thePtr!=ptr); } + inline bool operator < (const T* ptr) const { return (thePtr<ptr); } + inline bool operator > (const T* ptr) const { return (thePtr>ptr); } + + + inline T& operator*() { return *thePtr; } + + inline const T& operator*() const { return *thePtr; } + + inline T* operator->() { return thePtr; } + + inline const T* operator->() const { return thePtr; } + + inline bool operator!() const { return thePtr==0L; } + + inline bool valid() const { return thePtr!=0L; } + + inline T* get() { return thePtr; } + + inline const T* get() const { return thePtr; } + + /** take control over the object pointed to by ref_ptr, unreference but do not delete even if ref count goes to 0, + * return the pointer to the object. + * Note, do not use this unless you are 100% sure your code handles the deletion of the object correctly, and + * only use when absolutely required.*/ + inline T* take() { return release();} + + inline T* release() { T* tmp=thePtr; if (thePtr) thePtr->unref_nodelete(); thePtr=0; return tmp;} + + private: + T* thePtr; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimReferenced.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimReferenced.cpp new file mode 100644 index 0000000000..4a8ccf95d2 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimReferenced.cpp @@ -0,0 +1,14 @@ +/* -*-c++-*- libwms - Copyright (C) since 2004 Garrett Potts +*/ +#include <base/common/ossimReferenced.h> +#include <base/context/ossimNotifyContext.h> + +ossimReferenced::~ossimReferenced() +{ + if (theRefCount>0) + { + ossimNotify(ossimNotifyLevel_WARN)<<"Warning: deleting still referenced object "<<this<<std::endl; + ossimNotify(ossimNotifyLevel_WARN)<<" the final reference count was "<<theRefCount + <<", memory corruption possible."<<std::endl; + } +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimReferenced.h b/Utilities/OSSIM/ossim_core/base/common/ossimReferenced.h new file mode 100644 index 0000000000..09a707a5a9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimReferenced.h @@ -0,0 +1,59 @@ +/* -*-c++-*- libossim - Copyright (C) since 2004 Garrett Potts + * LICENSE: LGPL + * Author: Garrett Potts +*/ +#ifndef ossimReferenced_HEADER +#define ossimReferenced_HEADER +#include <base/common/ossimConstants.h> + +class OSSIMDLLEXPORT ossimReferenced +{ + public: + ossimReferenced() + : theRefCount(0) + {} + + ossimReferenced(const ossimReferenced&) + : theRefCount(0) + {} + + inline ossimReferenced& operator = (const ossimReferenced&) { return *this; } + + + /*! increment the reference count by one, indicating that + this object has another pointer which is referencing it.*/ + inline void ref() const { ++theRefCount; } + + /*! decrement the reference count by one, indicating that + a pointer to this object is referencing it. If the + reference count goes to zero, it is assumed that this object + is no longer referenced and is automatically deleted.*/ + inline void unref() const; + + /*! decrement the reference count by one, indicating that + a pointer to this object is referencing it. However, do + not delete it, even if ref count goes to 0. Warning, unref_nodelete() + should only be called if the user knows exactly who will + be resonsible for, one should prefer unref() over unref_nodelete() + as the later can lead to memory leaks.*/ + inline void unref_nodelete() const { --theRefCount; } + + /*! return the number pointers currently referencing this object. */ + inline int referenceCount() const { return theRefCount; } + + + protected: + virtual ~ossimReferenced(); + mutable int theRefCount; +}; + +inline void ossimReferenced::unref() const +{ + --theRefCount; + if (theRefCount==0) + { + delete this; + } +} + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimRgbLutDataObject.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimRgbLutDataObject.cpp new file mode 100644 index 0000000000..9102689b6a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimRgbLutDataObject.cpp @@ -0,0 +1,279 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimRgbLutDataObject.cpp,v 1.17 2005/05/10 16:57:20 dburken Exp $ +#include <base/common/ossimRgbLutDataObject.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimFilename.h> +#include <base/data_types/ossimColumnVector3d.h> +#include <base/context/ossimNotifyContext.h> + +#include <sstream> +using namespace std; + +RTTI_DEF1(ossimRgbLutDataObject, "ossimRgbLutDataObject", ossimObject); + +ostream& operator <<(ostream& out, + const ossimRgbLutDataObject& lut) +{ + for(ossim_uint32 index = 0; index < lut.theNumberOfEntries; ++index) + { + out << "entry" << index << " " << lut[index] << endl; + } + + return out; +} + +ossimRgbLutDataObject::ossimRgbLutDataObject(unsigned long numberOfEntries) + : + theLut(NULL), + theNumberOfEntries(numberOfEntries) +{ + if(theNumberOfEntries > 0) + { + // allocate 256 entries for the data object; + theLut = new ossimRgbVector[theNumberOfEntries]; + } + +} + +ossimRgbLutDataObject::ossimRgbLutDataObject(const ossimRgbLutDataObject& lut) + : + theLut(NULL), + theNumberOfEntries(0) +{ + theNumberOfEntries = lut.theNumberOfEntries; + if(theNumberOfEntries > 0) + { + theLut = new ossimRgbVector[theNumberOfEntries]; + for(ossim_uint32 index = 0; index < theNumberOfEntries; ++index) + { + theLut[index] = lut.theLut[index]; + } + } +} + +ossimRgbLutDataObject::~ossimRgbLutDataObject() +{ + if(theLut) + { + delete [] theLut; + theLut = NULL; + } + theNumberOfEntries = 0; +} + +int ossimRgbLutDataObject::findIndex(ossim_uint8 r, ossim_uint8 g, ossim_uint8 b) +{ + ossim_uint32 distance = 0x7FFFFFFF; // max 4 byte signed + ossim_int32 result = 0; + + if(theNumberOfEntries > 0) + { + for(ossim_uint32 i = 0; i < theNumberOfEntries; ++i) + { + ossim_uint32 rDelta = r - theLut[i].getR(); + ossim_uint32 gDelta = g - theLut[i].getG(); + ossim_uint32 bDelta = b - theLut[i].getB(); + + ossim_uint32 deltaSumSquare = (rDelta*rDelta + + gDelta*gDelta + + bDelta*bDelta); + if(deltaSumSquare == 0) + { + return static_cast<int>(i); + } + else if( deltaSumSquare < distance) + { + result = static_cast<int>(i); + distance = deltaSumSquare; + } + } + } + + return result; +} + +ossimRgbLutDataObject ossimRgbLutDataObject::rotate(long numberOfElements)const +{ + if(numberOfElements < 0) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL: Negative rotation is not supported yet in ossimRgbLutDataObject::rotate" << endl; + return *this; + } + ossimRgbLutDataObject lut; + for(ossim_uint32 index = 0; index < theNumberOfEntries; ++index) + { + int adjustedDestinationIndex = (index+numberOfElements)%theNumberOfEntries; + lut[adjustedDestinationIndex] = theLut[index] ; + } + + return lut; +} + +ossimRgbLutDataObject& ossimRgbLutDataObject::rotate(long numberOfElements) +{ + if(numberOfElements < 0) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL: Negative rotation is not supported yet in ossimRgbLutDataObject::rotate" << endl; + return *this; + } + const ossimRgbLutDataObject* temp = this; + + *this = temp->rotate(numberOfElements); + + return *this; +} + +const ossimRgbLutDataObject& ossimRgbLutDataObject::operator =(const ossimRgbLutDataObject& lut) +{ + if(theNumberOfEntries != lut.theNumberOfEntries) + { + delete [] theLut; + theLut = NULL; + } + + theNumberOfEntries = lut.theNumberOfEntries; + if(!theLut&&(theNumberOfEntries > 0)) + { + theLut = new ossimRgbVector[theNumberOfEntries]; + } + for(unsigned long index = 0; index < theNumberOfEntries; ++index) + { + theLut[index] = lut.theLut[index]; + } + + return *this; +} + +bool ossimRgbLutDataObject::operator ==(const ossimRgbLutDataObject& lut)const +{ + if(theNumberOfEntries != lut.theNumberOfEntries) + { + return false; + } + for(unsigned long index = 0; index < theNumberOfEntries; ++index) + { + if(theLut[index] != lut.theLut[index]) + { + return false; + } + } + return true; +} + +bool ossimRgbLutDataObject::saveState(ossimKeywordlist& kwl, const char* prefix)const +{ + kwl.add(prefix, + "type", + getClassName(), + true); + kwl.add(prefix, + "number_of_entries", + ossimString::toString(theNumberOfEntries).c_str(), + true); + for(unsigned long index = 0; index < theNumberOfEntries; ++index) + { + ossimString newPrefix = "entry"; + newPrefix += ossimString::toString(index); + ostringstream ostr; + ostr << (int)(theLut[index].getR()) + << " " << (int)(theLut[index].getG()) + << " " << (int)(theLut[index].getB()); + kwl.add(prefix, + newPrefix, + ostr.str().c_str(), + true); + } + + return true; +} + +bool ossimRgbLutDataObject::loadState(const ossimKeywordlist& kwl, const char* prefix) +{ + const char* lutFile = kwl.find(prefix, "lut_file"); + ossimKeywordlist fileLut; + ossimKeywordlist* tempKwl = (const_cast<ossimKeywordlist*>(&kwl)); + ossimString tempPrefix = prefix; + + // this should have been used instead of lut_file. We will still look + // for lut_file for backward compatibility. + // + if(!lutFile) + { + lutFile = kwl.find(prefix, "filename"); + } + // check to see if we should open an external file + // if so point the fileLut to the one that we use + if(lutFile) + { + ossimFilename filename(lutFile); + if(filename.exists()) + { + fileLut.addFile(filename.c_str()); + tempKwl = &fileLut; + tempPrefix = ""; + } + } + + const char* numberOfEntries = tempKwl->find(tempPrefix, "number_of_entries"); + if(!numberOfEntries) + { + numberOfEntries = tempKwl->find(tempPrefix, "number_entries"); + } + if(!numberOfEntries) return false; + theNumberOfEntries = ossimString(numberOfEntries).toULong(); + + delete [] theLut; + theLut = new ossimRgbVector[theNumberOfEntries]; + + if(tempKwl->find(tempPrefix, "entry0")) + { + for(long index = 0; index < (long)theNumberOfEntries; ++index) + { + ossimString newPrefix = "entry"; + newPrefix += ossimString::toString(index); + ossimString v = tempKwl->find(tempPrefix, newPrefix.c_str()); + istringstream istr(v); + + int r, g, b; + istr >> r >> g >> b; + theLut[index].setR((unsigned char)r); + theLut[index].setG((unsigned char)g); + theLut[index].setB((unsigned char)b); + } + } + else + { + for(long index = 0; index < (long)theNumberOfEntries; ++index) + { + ossimString newPrefix = "entry"; + newPrefix += ossimString::toString(index); + + const char* r = tempKwl->find(tempPrefix, (newPrefix+".r").c_str()); + const char* g = tempKwl->find(tempPrefix, (newPrefix+".g").c_str()); + const char* b = tempKwl->find(tempPrefix, (newPrefix+".b").c_str()); + + if(r) + { + theLut[index].setR((unsigned char)ossimString(r).toLong()); + } + if(g) + { + theLut[index].setG((unsigned char)ossimString(g).toLong()); + } + if(b) + { + theLut[index].setB((unsigned char)ossimString(b).toLong()); + } + } + } + return true; +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimRgbLutDataObject.h b/Utilities/OSSIM/ossim_core/base/common/ossimRgbLutDataObject.h new file mode 100644 index 0000000000..a750ac5332 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimRgbLutDataObject.h @@ -0,0 +1,99 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: A brief description of the contents of the file. +// +//************************************************************************* +// $Id: ossimRgbLutDataObject.h,v 1.12 2004/08/07 20:40:02 dburken Exp $ +#ifndef ossimRgbLutDataObject_HEADER +#define ossimRgbLutDataObject_HEADER +#include "base/data_types/color_space/ossimRgbVector.h" +#include "base/common/ossimObject.h" +#include <iostream> +class OSSIMDLLEXPORT ossimKeywordlist; + +class OSSIMDLLEXPORT ossimRgbLutDataObject : public ossimObject +{ +public: + friend std::ostream& operator <<(std::ostream& out, + const ossimRgbLutDataObject& lut); + /*! + * Will allocate 256 values for the color table + */ + ossimRgbLutDataObject(unsigned long numberOfEntries=0); + ossimRgbLutDataObject(const ossimRgbLutDataObject& lut); + virtual ~ossimRgbLutDataObject(); + const ossimRgbVector& operator[](unsigned int index)const + { + return index<theNumberOfEntries?theLut[index]:theLut[theNumberOfEntries-1]; + } + ossimRgbVector& operator[](unsigned int index) + { + return index<theNumberOfEntries?theLut[index]:theLut[theNumberOfEntries-1]; + } + const ossimRgbVector& operator[](int index)const + { + return index<(long)theNumberOfEntries?theLut[index]:theLut[theNumberOfEntries-1]; + } + ossimRgbVector& operator[](int index) + { + return index<(long)theNumberOfEntries?theLut[index]:theLut[theNumberOfEntries-1]; + } + const ossimRgbVector& operator[](double normalizedIndex)const + { + int index = int(normalizedIndex*theNumberOfEntries+.5); + if (index < 0) + { + index = 0; + } + return (*this)[index]; + } + ossimRgbVector& operator[](double normalizedIndex) + { + int index = int(normalizedIndex*theNumberOfEntries+.5); + if (index < 0) + { + index = 0; + } + return (*this)[index]; + } + long getNumberOfEntries()const{return theNumberOfEntries;} + int findIndex(const ossimRgbVector& rgb) + { + return findIndex(rgb.getR(), + rgb.getG(), + rgb.getB()); + } + int findIndex(ossim_uint8 r, ossim_uint8 g, ossim_uint8 b); + ossimRgbLutDataObject& rotate(long numberOfElements=1); + ossimRgbLutDataObject rotate(long numberOfElements=1)const; + + const ossimRgbLutDataObject& operator =(const ossimRgbLutDataObject& lut); + bool operator ==(const ossimRgbLutDataObject& lut)const; + + virtual bool saveState(ossimKeywordlist& kwl, const char* prefix=0)const; + virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix=0); +protected: + ossimRgbVector *theLut; + ossim_uint32 theNumberOfEntries; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimRtti.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimRtti.cpp new file mode 100644 index 0000000000..e9e1fb2edc --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimRtti.cpp @@ -0,0 +1,134 @@ +#include "ossimRtti.h" +#include <iostream> +#include <string.h> +using namespace std; + +static const RTTITypeinfo* RTTI_base_null_type[] = { 0 }; + +const RTTITypeinfo* RTTIdyntypeid::a[] = { 0 }; + +const RTTITypeinfo RTTITypeinfo::null_type = RTTITypeinfo("NULL", RTTI_base_null_type,0,0); + +void RTTITypeinfo::add_subtype(const RTTITypeinfo* t) //Adds t as last RTTITypeinfo in the +{ //'subtypes' list. For this, the + const RTTITypeinfo** ptr = new const RTTITypeinfo*[ns+1]; //list is realloc'd with one extra entry. + int i; for(i=0;i<ns;i++) ptr[i] = subtypes[i]; + ptr[i] = t; + ns++; + delete[] subtypes; + subtypes = ptr; +} + +void RTTITypeinfo::del_subtype(const RTTITypeinfo* 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]; +} + +RTTITypeinfo::RTTITypeinfo(const char* name, + const RTTITypeinfo* bb[], + void* (*f1)(int,void*), + void* (*f2)()) +{ + n = strdup(name); + b = bb; //ns = 0; subtypes = 0; //Create default RTTITypeinfo + cast = f1; //Attach casting func + new_obj = f2; //Attach creation func + int i = 0; + for(i=0;b[i];i++) //Add this as subtype to all its basetypes + ((RTTITypeinfo**)b)[i]->add_subtype(this); //REMARK: Harmless const castaway +} + +const char* RTTITypeinfo::getname() const +{ + return n; +} + + +RTTITypeinfo::~RTTITypeinfo() +{ + if(n) + { + free(n); + n = NULL; + } + int i = 0; + for(i=0;b[i];i++) + { + //Del this subtype from all its basetypes + ((RTTITypeinfo**)b)[i]->del_subtype(this); //REMARK: Harmless const castaway + } +} + +int RTTITypeinfo::has_base(const RTTITypeinfo* p) const +{ + int i = 0; + for(i=0;b[i];i++) //for all bases of this... + if (p->same(b[i]) || b[i]->has_base(p)) return 1; //match found, return 1 or no match, search deeper + return 0; //no match at all, return 0 +} + +void* RTTITypeinfo::create(const RTTITypeinfo* bt, const char* c) const //Tries to create an obj of type-name +{ //given by char*. Searches for this type in the + void* p = 0; int i; //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. + if (!strcmp(c,n)) //Want to create an obj of this type ? + p = (new_obj)? new_obj() : 0; //Yes, do it if this type is instantiable. + 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 for(i=0;b[i] && b[i]!=bt;i++); //Search to which base of this we should cast + //Found: cast to ith base of this + return cast(i,p); //Cast to ith base of to this, return as void* +} + +RTTItypeid RTTItypeid::find_baseclass(const char* name)const +{ + if(strcmp(name, getname())==0) + { + return *this; + } + else if(num_baseclasses() == 0) + { + if(strcmp(name, getname()) == 0) + { + return *this; + } + return null_type(); + } + else + { + int index = 0; + + while(index < num_baseclasses()) + { + RTTItypeid typeId = baseclass(index); + if(typeId == *this) + { + return *this;//null_type(); + } + if(strcmp(name, typeId.getname()) == 0) + { + return *this; + } + ++index; + } + index = 0; + while(index < num_baseclasses()) + { + RTTItypeid typeId = baseclass(index); + if(typeId.find_baseclass(name) == typeId.null_type()) + { + ++index; + } + else + { + return typeId; + } + } + } + return null_type(); +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimRtti.h b/Utilities/OSSIM/ossim_core/base/common/ossimRtti.h new file mode 100644 index 0000000000..fe2110605c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimRtti.h @@ -0,0 +1,509 @@ +#ifndef RTTI_H +#define RTTI_H + +#include <string.h> + + +///////////////////////////////////////////////////////////////////////////////////////// +/* + RTTI_H: 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 TYPE_DATA (without ';') as the last item in the class-decl. + 2) in the .C file where the class's implementation resides, insert the following (without';'): + + RTTI_DEF(classname,"RT classname") if the class has no bases with RTTI + RTTI_DEFn(classname,"RT classname",b1,...bn) if the class has bases b1,...bn with RTTI + + Use RTTI_DEF_INST instead of 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 RTTItypeid. A typeid describes a type of a class. typeids can be compared + with operator== and operator!= and can be retrieved from classes/pointers. They should provide all necessary + support for any kind of RTTI/casting, as described by the macros below (by RTTI-class we mean a class having RTTI, + as described above). The 'return type' of the macros is listed between quotes: + + 'RTTItypeid' + STATIC_TYPE_INFO(T) T=RTTI-class name. Returns a RTTItypeid with T's type. if T hasn't RTTI, a + compile-time error occurs. + 'RTTItypeid' + TYPE_INFO(p) p=ptr to a RTTI-class. + Returns the RTTItypeid of the class-obj p is really pointing at. + If *p hasn't RTTI, a compile-time error occurs. + If p==NULL, a special typeid for the NULL pointer is returned. + This typeid has the name (const char*) "NULL". + 'T*' + 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 separate + branches of a class hierarchy is also supported, as long as all classes + have RTTI. Therefore PTR_CAST is a fully general and safe operator. + If p==NULL, the operator returns NULL. + + Some other macros. Not essential, provided mostly for convenience: + ================= + const char* + STATIC_TYPE_NAME(T) T=RTTI-class name. Returns the name (const char*) of T's type. + Provided for convenience. Compile-time error if T hasn't RTTI. + const char* + TYPE_NAME(p) p=RTTI-class ptr. Returns the class name (char*) of real *p. + Provided for convenience. Compile-time error if *p hasn't RTTI. + int If p==NULL, "NULL" is returned. + DYN_CAST(t,p) t=RTTItypeid. p=RTTI-class ptr. + Returns 1 if p can indeed be cast to t, else returns 0. + Compile-time error if *p hasn't RTTI. + If p==NULL, 1 is returned (NULL can be cast to anything). + This operator is useful when we just want to check that a pointer can be cast to + a RTTItypeid variable (which can be created/selected at run-time). For creating a RTTItypeid, + construct a subclass of RTTItypeid called RTTIdyntypeid which allows construction from a const char*, i.e. from + a user specification and pass it to DYN_CAST. + DYN_TYPE can't return a typed pointer (since t is a RTTItypeid var and C++ has no 'real' type variables), + but returns a 1/0 indicating whether the cast is possible or not. + void* + UPTR_CAST(t,p) t=RTTItypeid. p=RTTI-class ptr. + Returns p cast to a void* if cast succeeds, else returns NULL. + Again, p can point to virtual-bases and casts between separate branches of a class dag + are supported. this operator is practically the 'untyped' version of PTR_CAST, offering + the extra feature that the type is expressed by a run-time type variable (RTTItypeid). + Compile-time error if *p hasn't RTTI. + + + Obsolete macros: This set of macros is based on Stroustrup. They are not general and safe + =============== (e.g. virtual-base to derived casts are trapped as compile-time errors and casts + between separate class-dag branches are incorrectly done without any warnings). + The above macros are including ALL functionality of these macros, which are + provided only for completeness: + + OLD_PTR_CAST(T,p) Like PTR_CAST(T,p), but without accepting p=ptr to virtual bases and performing + incorrect casts between separate branches of a class-dag. + OLD_UPTR_CAST(t,p) Like UPTR_CAST(t,p), but with same problems as above. + OLD_DYN_CAST(t,p) Like DYN_CAST(t,p), but with same problems as above. + + + RT Object Creation: This feature enables the user to create objects of a RT-selected type in a generic manner. + ================== Typically, we create/obtain a RT type (via a RTTItypeid t1). Then, having another RTTItypeid t2 + (typically from the (STATIC_)TYPE_INFO of some ROOT class / ROOT* ptr, we call: + + ROOT* new_obj = (ROOT*)t2.create(t1); + + create() searches for t1 in the class DAG rooted at t2. If found, it creates a new obj of type + t1 and returns it as a '(void*)(t2*)'. For example, we know above that we get a ROOT* since + t2 is ROOT's RTTItypeid, so we can _safely_ cast the void* to ROOT. If create() can't make the t1 + object (there's no such type or the type is not declared via RTTI_DEF_INST), it returns NULL. + This gives a fully generic typeid-based factory method for RT obj creation. + + REMARK: RTTI support adds some additional info, both static+virtual, to a class. The current implementation + ======= adds a static object and some static functions and 2 virtual functions to each class desiring RTTI. + This may of course cause potential name-clash problems. In order to avoid this, all added identifiers + in the RTTI system are prefixed with RTTI_ (see the TYPE_DATA macro). + + REMARK_2: There are two classes related to RTTI: RTTItypeid and RTTITypeinfo. A RTTItypeid is, as it says, an 'id for a type' + ======== It actually wraps a RTTITypeinfo*, where a RTTITypeinfo contains the actual encoding of a class type. + You can freely create/copy/destroy/manipulate RTTItypeid's, but you should NEVER deal directly + with RTTITypeinfo. A RTTITypeinfo should actually be created ONLY by the TYPE_DATA macros, as part of a class definition, + since the RTTITypeinfo encodes a type info for an EXISTING class. All type-related stuff should be therefore + handled via RTTItypeid's. If you really want to dynamically create a dummy typeid, use RTTIdyntypeid class. + + REMARK 3: All names introduced by this RTTI implementation (RTTItypeid,RTTIdyntypeid,RTTITypeinfo,etc) + ========= are prefixed by RTTI, to make this system easily acceptable by e.g. C++ environments which happen to + already support typeids. + +*/ + + +////////////////////////////////////////////////////////////// + +#include <stdlib.h> // for free +#include <string.h> // for strdup,strcmp +#include "ossimConstants.h" +///////////////////////////////////////////////////////////// + +class OSSIMDLLEXPORT RTTITypeinfo; + +class OSSIMDLLEXPORT RTTItypeid + { // Main class for RTTI interface. + public: + + RTTItypeid(const RTTITypeinfo* p): id(p) {} + RTTItypeid(); + int operator==(RTTItypeid) const; + int operator!=(RTTItypeid) const; + const RTTITypeinfo* get_info() const { return id; } + int can_cast(RTTItypeid) const; // 1 if the arg can be cast to this, else 0 + const char* getname() const; + int num_subclasses() const; // Return # subclasses of this + RTTItypeid subclass(int) const; // Return ith subclass of this + int num_baseclasses() const; // Return # baseclasses of this + RTTItypeid baseclass(int) const; // Return ith baseclass of this + void* create(RTTItypeid) const; // Tries to create an instance of a subclass of this + // having of type given by the RTTItypeid arg. If ok, it returns it + // casted to the class-type of this and then to void* + int can_create() const; // Return 1 if this type is instantiable, else 0 + RTTItypeid find_baseclass(const char* name)const;// + static RTTItypeid + null_type(); // the RTTItypeid for NULL ptrs + + protected: + + const RTTITypeinfo* id; // RTTItypeid implementation (the only data-member) + }; + + +class OSSIMDLLEXPORT RTTIdyntypeid : public RTTItypeid //Class for dynamic type creation from user strings. + { //Useful for creating typeids at RT for comparison + public: //purposes. + RTTIdyntypeid(const char*); + ~RTTIdyntypeid(); + private: + static const RTTITypeinfo* a[]; + }; + +/////////////////////////////////////////////////////////////////// + +class OSSIMDLLEXPORT RTTITypeinfo { //Implementation of type-related info + public: + + RTTITypeinfo(const char* name, const RTTITypeinfo* bb[], + void* (*)(int,void*),void* (*)()); + ~RTTITypeinfo(); + const char* getname() const; //Returns name of this RTTITypeinfo + int same(const RTTITypeinfo*) const; //Compares 2 RTTITypeinfo objs + int can_cast(const RTTITypeinfo*) const; //1 if the arg can be cast to this, else 0 + int has_base(const RTTITypeinfo*) const; //1 if this has the arg as some base, else 0 + + + const RTTITypeinfo* + subclass(int=0) const; //get i-th subclass of this, if any, else NULL + int num_subclasses() const; //get # subclasses of this + void* create(const RTTITypeinfo*,const char*) const; //search for a subclass named char*, + //create obj of it and return it cast to + //the RTTITypeinfo* type, which is either + //this or a direct base of this. + int can_create() const; //Returns 1 if this type has a default ctor, else 0 + + private: + + char* n; //type name + const RTTITypeinfo** b; //base types (NULL-ended array of RTTITypeinfo's for this's direct bases) + int ns; //#subtypes of this type + const RTTITypeinfo** subtypes; //types derived from this type + static const RTTITypeinfo null_type; //convenience type info for a '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 + + void add_subtype(const RTTITypeinfo*);//adds a subtype to this's subtypes[] + void del_subtype(const RTTITypeinfo*);//dels a subtype from this's subtypes[] + + friend class RTTItypeid; //for null_type + }; + + + + +inline int RTTITypeinfo::num_subclasses() const //Return # subclasses of this +{ + return ns; +} + +inline const RTTITypeinfo* RTTITypeinfo::subclass(int i) const //Return ith subclass of this, else NULL; +{ + return (i>=0 && i<ns)? subtypes[i]: 0; +} + +inline int RTTITypeinfo::same(const RTTITypeinfo* p) const //Compare 2 RTTITypeinfo's: +{ //First, try to see if it's the same + return this==p || !strcmp(n,p->n); //'physical' RTTITypeinfo (which should be the case, +} //since we create them per-class and not per-obj). + //If this fails, still do a textual name comaprison. + +inline int RTTITypeinfo::can_cast(const RTTITypeinfo* p) const +{ + return same(p) || p->has_base(this); +} + +inline int RTTITypeinfo::can_create() const +{ + return new_obj!=0; +} + +///////////////////////////////////////////////////////////////// +// +// RTTItypeid methods: +// + +inline RTTItypeid RTTItypeid::null_type() +{ + return &(RTTITypeinfo::null_type); +} + +inline RTTItypeid::RTTItypeid(): id(null_type().id) +{ +} + +inline int RTTItypeid::operator==(RTTItypeid i) const +{ + return id->same(i.id); +} + +inline int RTTItypeid::operator!=(RTTItypeid i) const +{ + return !(id->same(i.id)); +} + +inline int RTTItypeid::can_cast(RTTItypeid i) const +{ + return id->can_cast(i.id); +} + + +inline const char* RTTItypeid::getname() const +{ + return id->getname(); +} + +inline int RTTItypeid::num_subclasses() const +{ + return id->num_subclasses(); +} + +inline RTTItypeid RTTItypeid::subclass(int i) const +{ + return id->subclass(i); +} + +inline int RTTItypeid::num_baseclasses() const +{ + int i; for(i=0;id->b[i];i++); + return i; +} + +inline RTTItypeid RTTItypeid::baseclass(int i) const +{ + return id->b[i]; +} + +inline void* RTTItypeid::create(RTTItypeid t) const +{ + return id->create(id,t.getname()); +} + +inline int RTTItypeid::can_create() const +{ + return id->can_create(); +} + +//////////////////////////////////////////////////////////////////////////////// + + +inline RTTIdyntypeid::RTTIdyntypeid(const char* c) : RTTItypeid(new RTTITypeinfo(c,a,0,0)) { } //create a dummy RTTITypeinfo +inline RTTIdyntypeid::~RTTIdyntypeid() +{ + if(id) + { + delete id; + id = 0; + } +} //delete the dummy RTTITypeinfo + + +///////////////////////////////////////////////////////////////////////////////////// + +// 1. Main operators +#define STATIC_TYPE_INFO(T) T::RTTI_sinfo() +#define TYPE_INFO(p) ((p)? (p)->RTTI_vinfo() : RTTItypeid::null_type() ) +#define PTR_CAST(T,p) ((p)? (T*)((p)->RTTI_cast(STATIC_TYPE_INFO(T))) : 0) + + +// 2. Convenience operators +#define STATIC_TYPE_NAME(T) (STATIC_TYPE_INFO(T).getname()) +#define TYPE_NAME(p) ((p)? ((p)->RTTI_vinfo().getname()) : RTTItypeid::null_type().getname()) +#define DYN_CAST(t,p) ((p)? ((p)->RTTI_cast((t))!=0) : 1) +#define UPTR_CAST(t,p) ((p)? ((p)->RTTI_cast((t))) : 0) + +// 3. Unsafe operators (see Stroustrup) +#define OLD_PTR_CAST(T,p) ((p)? ((STATIC_TYPE_INFO(T).can_cast((p)->RTTI_vinfo()))? (T*)p : 0) : 0) +#define OLD_UPTR_CAST(t,p) ((p)? ((t).can_cast((p)->RTTI_vinfo())? (void*)p : 0) : 0) +#define OLD_DYN_CAST(t,p) ((p)? ((t).can_cast((p)->RTTI_vinfo())? 1 : 0) : 1) + + +// Definition of TYPE_DATA for a RTTI-class: introduces one static RTTITypeinfo data-member +// and a couple of virtuals. + +#define TYPE_DATA \ + protected: \ + static const RTTITypeinfo RTTI_obj; \ + static void* RTTI_scast(int,void*); \ + static void* RTTI_new(); \ + public: \ + virtual RTTItypeid RTTI_vinfo() const { return &RTTI_obj; }\ + static RTTItypeid RTTI_sinfo() { return &RTTI_obj; }\ + virtual void* RTTI_cast(RTTItypeid);\ + virtual const void* RTTI_cast(RTTItypeid)const; + + + +// Definition of auxiliary data-structs supporting RTTI for a class: defines the static RTTITypeinfo +// object of that class and its associated virtuals. + +// Auxiliary definition of the construction method: +#define RTTI_NEW(cls,name) void* cls::RTTI_new() { return new cls; } \ + const RTTITypeinfo cls::RTTI_obj = RTTITypeinfo(name,RTTI_base_##cls,cls::RTTI_scast,cls::RTTI_new); + +#define RTTI_NO_NEW(cls,name) const RTTITypeinfo cls::RTTI_obj = RTTITypeinfo(name,RTTI_base_##cls,cls::RTTI_scast,0); + + + +////////////////////////////////////////////////////////////////// +// +// Top-level macros: +// + +#define RTTI_DEF_BASE(cls,name) \ + static const RTTITypeinfo* RTTI_base_##cls [] = { 0 };\ + void* cls::RTTI_cast(RTTItypeid t) \ + { \ + if (t == &RTTI_obj) return this; \ + return 0; \ + } \ + const void* cls::RTTI_cast(RTTItypeid t)const \ + { \ + if (t == &RTTI_obj) return this; \ + return 0; \ + } \ + void* cls::RTTI_scast(int i,void* p) \ + { cls* ptr = (cls*)p; return ptr; } + + +#define RTTI_DEF1_BASE(cls,name,b1) \ + static const RTTITypeinfo* RTTI_base_##cls [] = \ + { STATIC_TYPE_INFO(b1).get_info(),0 }; \ + void* cls::RTTI_cast(RTTItypeid t) \ + { \ + if (t == &RTTI_obj) return this; \ + void* ptr; \ + if ((ptr=b1::RTTI_cast(t))) return ptr; \ + return 0; \ + } \ + const void* cls::RTTI_cast(RTTItypeid t)const \ + { \ + if (t == &RTTI_obj) return this; \ + const void* ptr; \ + if ((ptr=b1::RTTI_cast(t))) return ptr; \ + return 0; \ + } \ + void* cls::RTTI_scast(int i,void* p) \ + { cls* ptr = (cls*)p; \ + switch(i) \ + { case 0: return (b1*)ptr; } \ + return ptr; \ + } + + +#define RTTI_DEF2_BASE(cls,name,b1,b2) \ + static const RTTITypeinfo* RTTI_base_##cls [] = \ + { STATIC_TYPE_INFO(b1).get_info(), \ + STATIC_TYPE_INFO(b2).get_info(),0 }; \ + void* cls::RTTI_cast(RTTItypeid t) \ + { \ + if (t == &RTTI_obj) return this; \ + void* ptr; \ + if ((ptr=b1::RTTI_cast(t))) return ptr; \ + if ((ptr=b2::RTTI_cast(t))) return ptr; \ + return 0; \ + } \ + const void* cls::RTTI_cast(RTTItypeid t)const \ + { \ + if (t == &RTTI_obj) return this; \ + const void* ptr; \ + if ((ptr=b1::RTTI_cast(t))) return ptr; \ + if ((ptr=b2::RTTI_cast(t))) return ptr; \ + return 0; \ + } \ + 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 RTTI_DEF3_BASE(cls,name,b1,b2,b3) \ + static const RTTITypeinfo* RTTI_base_##cls [] = \ + { STATIC_TYPE_INFO(b1).get_info(), \ + STATIC_TYPE_INFO(b2).get_info(), \ + STATIC_TYPE_INFO(b3).get_info(), 0 }; \ + void* cls::RTTI_cast(RTTItypeid t) \ + { \ + if (t == &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 0; \ + } \ + const void* cls::RTTI_cast(RTTItypeid t)const \ + { \ + if (t == &RTTI_obj) return this; \ + const 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 0; \ + } \ + 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 RTTI_DEF_INST(cls,name) \ + RTTI_DEF_BASE(cls,name) \ + RTTI_NEW(cls,name) + +#define RTTI_DEF(cls,name) \ + RTTI_DEF_BASE(cls,name) \ + RTTI_NO_NEW(cls,name) + +#define RTTI_DEF1_INST(cls,name,b1) \ + RTTI_DEF1_BASE(cls,name,b1) \ + RTTI_NEW(cls,name) + +#define RTTI_DEF1(cls,name,b1) \ + RTTI_DEF1_BASE(cls,name,b1) \ + RTTI_NO_NEW(cls,name) + +#define RTTI_DEF2_INST(cls,name,b1,b2) \ + RTTI_DEF2_BASE(cls,name,b1,b2) \ + RTTI_NEW(cls,name) + +#define RTTI_DEF2(cls,name,b1,b2) \ + RTTI_DEF2_BASE(cls,name,b1,b2) \ + RTTI_NO_NEW(cls,name) + +#define RTTI_DEF3_INST(cls,name,b1,b2,b3) \ + RTTI_DEF3_BASE(cls,name,b1,b2,b3) \ + RTTI_NEW(cls,name) + +#define RTTI_DEF3(cls,name,b1,b2,b3) \ + RTTI_DEF3_BASE(cls,name,b1,b2,b3) \ + RTTI_NO_NEW(cls,name) + + +#endif + + + + + diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimScopedLock.h b/Utilities/OSSIM/ossim_core/base/common/ossimScopedLock.h new file mode 100644 index 0000000000..58b9aab4c4 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimScopedLock.h @@ -0,0 +1,40 @@ +//************************************************************************* +// Copyright (C) 2004 Intelligence Data Sytems, Inc. All rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// NOTES: This was taken from OpenThreads::ScopedLock +// +// +//************************************************************************** +// $Id: ossimScopedLock.h,v 1.2 2005/07/15 11:05:10 gpotts Exp $ +#ifndef ossimScopedLock_HEADER +#define ossimScopedLock_HEADER + +template <class T> class ossimScopedLock +{ + private: + T& theLock; + ossimScopedLock(const ossimScopedLock&); // prevent copy + ossimScopedLock& operator=(const ossimScopedLock&); // prevent assign + public: + explicit ossimScopedLock(T& m):theLock(m) {theLock.lock();} + ~ossimScopedLock(){theLock.unlock();} +}; + +template <class T> class ossimReverseScopedLock +{ + private: + T& theLock; + ossimReverseScopedLock(const ossimReverseScopedLock&); // prevent copy + ossimReverseScopedLock& operator=(const ossimReverseScopedLock&); // prevent assign + public: + explicit ossimReverseScopedLock(T& m):theLock(m) {theLock.unlock();} + ~ossimReverseScopedLock(){theLock.lock();} +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimSource.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimSource.cpp new file mode 100644 index 0000000000..cfcc361a88 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimSource.cpp @@ -0,0 +1,167 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimSource.cpp,v 1.45 2005/12/08 13:50:20 gpotts Exp $ +#include <base/common/ossimSource.h> +#include <base/common/ossimDataObject.h> +#include <base/common/ossimIdManager.h> +#include <base/common/ossimKeywordNames.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/property/ossimBooleanProperty.h> + +RTTI_DEF2(ossimSource, "ossimSource", + ossimConnectableObject, ossimErrorStatusInterface) + + +ossimSource::ossimSource(ossimObject* owner) + : + ossimConnectableObject(owner), + theEnableFlag(true), + theInitializedFlag(false) +{ +} + +ossimSource::ossimSource(const ossimSource &rhs) + : + ossimConnectableObject(rhs), + theEnableFlag(rhs.theEnableFlag), + theInitializedFlag(rhs.theInitializedFlag) +{ +} + +ossimSource::ossimSource(ossimObject* owner, + ossim_uint32 inputListSize, + ossim_uint32 outputListSize, + bool inputListIsFixedFlag, + bool outputListIsFixedFlag) + : + ossimConnectableObject(owner, inputListSize, outputListSize, + inputListIsFixedFlag, outputListIsFixedFlag), + theEnableFlag(true), + theInitializedFlag(false) +{} + +ossimSource::~ossimSource() +{ +} + +bool ossimSource::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + ossimKeywordNames::ENABLED_KW, + (int)theEnableFlag, + true); + + return ossimConnectableObject::saveState(kwl, prefix); +} + +bool ossimSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* lookup = kwl.find(prefix, + ossimKeywordNames::ENABLED_KW); + if(lookup) + { + theEnableFlag = ossimString(lookup).toBool(); + } + + return ossimConnectableObject::loadState(kwl, prefix); +} + +bool ossimSource::isSourceEnabled()const +{ + return theEnableFlag; +} + +void ossimSource::enableSource() +{ + setEnableFlag(true); +} + +void ossimSource::disableSource() +{ + setEnableFlag(false); +} + +bool ossimSource::getEnableFlag() const +{ + return theEnableFlag; +} + +void ossimSource::setEnableFlag(bool flag) +{ + theEnableFlag = flag; +} + +bool ossimSource::isInitialized() const +{ + return theInitializedFlag; +} + +void ossimSource::setInitializedFlag(bool flag) +{ + theInitializedFlag = flag; +} + +void ossimSource::initialize() +{ +} + +void ossimSource::setProperty(ossimRefPtr<ossimProperty> property) +{ + if(!property.valid()) return; + + ossimString name = property->getName(); + name = name.downcase(); + + if(name == ossimKeywordNames::ENABLED_KW) + { + ossimString value; + + property->valueToString(value); + setEnableFlag(value.toBool()); + } + else + { + ossimConnectableObject::setProperty(property); + } +} + +ossimRefPtr<ossimProperty> ossimSource::getProperty(const ossimString& name)const +{ + if( (name == "Enabled") || (name == ossimKeywordNames::ENABLED_KW) ) + { + return new ossimBooleanProperty(ossimKeywordNames::ENABLED_KW,theEnableFlag); + } + return ossimConnectableObject::getProperty(name); +} + +void ossimSource::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + ossimConnectableObject::getPropertyNames(propertyNames); + + propertyNames.push_back(ossimKeywordNames::ENABLED_KW); +} + +const ossimSource& ossimSource::operator=(const ossimSource &rhs) +{ + return *this; +} + +std::ostream& ossimSource::print(std::ostream& out) const +{ + out << "ossimSource::print:\n" + << "theEnableFlag: " << theEnableFlag + << "\ntheInitializedFlag: " << theInitializedFlag + << endl; + + return ossimErrorStatusInterface::print(out); +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimSource.h b/Utilities/OSSIM/ossim_core/base/common/ossimSource.h new file mode 100644 index 0000000000..66d22bbb2b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimSource.h @@ -0,0 +1,83 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// Base class for any object that can be a source. Derives from +// ossimConnectableObject since all source's should be connectable +// +//************************************************************************* +// $Id: ossimSource.h,v 1.41 2004/11/11 20:17:25 gpotts Exp $ + +#ifndef ossimSource_HEADER +#define ossimSource_HEADER + +#include "base/common/ossimConnectableObject.h" +#include "base/common/ossimErrorStatusInterface.h" +#include "base/common/ossimConstants.h" + +class OSSIMDLLEXPORT ossimDataObject; + +class OSSIMDLLEXPORT ossimSource : public ossimConnectableObject, + public ossimErrorStatusInterface +{ +public: + ossimSource(ossimObject* owner=0); + ossimSource(ossimObject* owner, + ossim_uint32 inputListSize, + ossim_uint32 outputListSize, + bool inputListIsFixedFlag=true, + bool outputListIsFixedFlag=true); + + virtual ~ossimSource(); + + virtual bool isSourceEnabled()const; + virtual void enableSource(); + virtual void disableSource(); + virtual bool getEnableFlag() const; + virtual void setEnableFlag(bool flag); + + virtual bool isInitialized() const; + virtual void setInitializedFlag(bool flag); + virtual void initialize(); + + /*---------------------- PROPERTY INTERFACE ---------------------------*/ + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + /*--------------------- PROPERTY INTERFACE END ------------------------*/ + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual std::ostream& print(std::ostream& out) const; + +protected: + ossimSource(const ossimSource &rhs); + const ossimSource& operator=(const ossimSource &rhs); + + bool theEnableFlag; + bool theInitializedFlag; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimStdOutProgress.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimStdOutProgress.cpp new file mode 100644 index 0000000000..c5e12d2eae --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimStdOutProgress.cpp @@ -0,0 +1,58 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimStdOutProgress.cpp,v 1.5 2005/10/17 18:37:16 gpotts Exp $ +#include "ossimStdOutProgress.h" + +RTTI_DEF1(ossimStdOutProgress, "ossimStdOutProgress", ossimProcessListener); + +ossimStdOutProgress theStdOutProgress; + +ossimStdOutProgress::ossimStdOutProgress(long precision, bool flushStream) + : + ossimProcessListener(), + thePrecision(precision), + theFlushStreamFlag(flushStream) +{ +} + +void ossimStdOutProgress::processProgressEvent(ossimProcessProgressEvent& event) +{ + if (event.getOutputMessageFlag()) + { + ossimString s; + event.getMessage(s); + if (!s.empty()) + { + ossimNotify(ossimNotifyLevel_NOTICE) << s.c_str() << std::endl; + } + return; // Don't output percentage on a message update. + } + + + double p = event.getPercentComplete(); + ossimNotify(ossimNotifyLevel_NOTICE) + << std::setiosflags(std::ios::fixed) + << std::setprecision(thePrecision) + << p << "%\r"; + + if(theFlushStreamFlag) + { + (p != 100.0) ? + ossimNotify(ossimNotifyLevel_NOTICE).flush() : + ossimNotify(ossimNotifyLevel_NOTICE) << "\n"; + } +} + +void ossimStdOutProgress::setFlushStreamFlag(bool flag) +{ + theFlushStreamFlag = flag; +} + diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimStdOutProgress.h b/Utilities/OSSIM/ossim_core/base/common/ossimStdOutProgress.h new file mode 100644 index 0000000000..5183dd6923 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimStdOutProgress.h @@ -0,0 +1,33 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimStdOutProgress.h,v 1.16 2004/10/06 15:35:17 dburken Exp $ +#ifndef ossimStdOutProgress_HEADER +#define ossimStdOutProgress_HEADER +#include <iostream> +#include <base/common/events/ossimProcessListener.h> +#include <base/common/events/ossimProcessProgressEvent.h> +#include <base/context/ossimNotifyContext.h> +class OSSIMDLLEXPORT ossimStdOutProgress : public ossimProcessListener +{ +public: + ossimStdOutProgress(long precision = 0, bool flushStream=false); + + virtual void processProgressEvent(ossimProcessProgressEvent& event); + + virtual void setFlushStreamFlag(bool flag); + +protected: + long thePrecision; + bool theFlushStreamFlag; +TYPE_DATA +}; +OSSIMDLLEXPORT extern ossimStdOutProgress theStdOutProgress; +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimStreamBase.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimStreamBase.cpp new file mode 100644 index 0000000000..d4b829dbfe --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimStreamBase.cpp @@ -0,0 +1,3 @@ +#include "ossimStreamBase.h" + +RTTI_DEF1(ossimStreamBase, "ossimStreamBase", ossimObject); diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimStreamBase.h b/Utilities/OSSIM/ossim_core/base/common/ossimStreamBase.h new file mode 100644 index 0000000000..58671dc4a9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimStreamBase.h @@ -0,0 +1,29 @@ +//******************************************************************* +// Copyright (C) 2005 Garrett Potts +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// +//******************************************************************* +// $Id: ossimStreamBase.h,v 1.3 2005/11/14 13:58:51 gpotts Exp $ +// +#ifndef ossimStreamBase_HEADER +#define ossimStreamBase_HEADER +#include <iostream> +#include "ossimObject.h" + +class OSSIM_DLL ossimStreamBase : public ossimObject, virtual public std::ios +{ +public: + ossimStreamBase(){} + ossimStreamBase(std::streambuf* buf) + { + init(buf); + } +TYPE_DATA +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimTrace.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimTrace.cpp new file mode 100644 index 0000000000..0af738e37c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimTrace.cpp @@ -0,0 +1,40 @@ +//***************************************************************************** +// FILE: ossimTrace.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// DESCRIPTION: +// Contains implementation of class ossimTrace +// +// SOFTWARE HISTORY: +//> +// 24Apr2001 Oscar Kramer +// Initial coding. +//< +//***************************************************************************** +// $Id: ossimTrace.cpp,v 1.7 2005/04/18 20:46:13 dburken Exp $ + +#include <base/common/ossimTrace.h> +#include <base/common/ossimTraceManager.h> +#include <base/common/ossimCommon.h> +//***************************************************************************** +// CONSTRUCTOR: ossimTrace +// +//***************************************************************************** +ossimTrace::ossimTrace(const ossimString& trace_name) + : + theTraceName (trace_name), + theEnabledFlag (false) +{ + ossimTraceManager::instance()->addTrace(this); +} + +ossimTrace::~ossimTrace() +{ + ossimTraceManager::instance()->removeTrace(this); +} + diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimTrace.h b/Utilities/OSSIM/ossim_core/base/common/ossimTrace.h new file mode 100644 index 0000000000..ffef22f05d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimTrace.h @@ -0,0 +1,72 @@ +//***************************************************************************** +// FILE: ossimTrace.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// DESCRIPTION: +// Contains declaration of class ossimTrace. Used for tracing code execution. +// Implemented as a singluy linked list of ossimTrace objects. +// +// SOFTWARE HISTORY: +// 24Apr2001 Oscar Kramer +// Initial coding. +//***************************************************************************** +// $Id: ossimTrace.h,v 1.12 2005/04/18 20:46:13 dburken Exp $ + +#ifndef ossimTrace_HEADER +#define ossimTrace_HEADER + +#include <iostream> // for "clog" +#include <base/data_types/ossimString.h> +#include <base/context/ossimNotifyContext.h> + +// Macro for use with trace... +#define CLOG ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " (\"" __FILE__ "\", line " << __LINE__ << ") DEBUG: " + + +class OSSIMDLLEXPORT ossimTrace +{ +public: + ossimTrace( const ossimString& trace_name ); + ~ossimTrace(); + + /** + * @returns true if enabled false if not. + */ + bool isEnabled() const { return theEnabledFlag; } + + /** + * Returns "theTraceName" as an ossimString. + */ + ossimString getTraceName() const { return theTraceName; } + + + /** + * Sets "theEnabled" flag. + * + * @param flag true == enabled, false == disabled. + */ + void setTraceFlag(bool flag) { theEnabledFlag = flag; } + + /** + * Operator() for ossimTrace. Given the static instance: + * static ossimTrace traceDebug("myTrace"); + * + * You can do: + * if (traceDebug()) + * { + * CLOG << "Your trace stuff goes here..." << endl; + * } + */ + bool operator()() const { return theEnabledFlag; } + +private: + ossimString theTraceName; + bool theEnabledFlag; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimTraceManager.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimTraceManager.cpp new file mode 100644 index 0000000000..a1d31b7f96 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimTraceManager.cpp @@ -0,0 +1,105 @@ +//***************************************************************************** +// Copyright (C) 2005 Garrett Potts, all rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// DESCRIPTION: +// Contains declaration of class ossimTraceManager. +// +//***************************************************************************** +// $Id: ossimTraceManager.cpp,v 1.2 2005/05/17 18:17:34 dburken Exp $ + +#include <algorithm> + +#include <base/common/ossimTraceManager.h> +#include <base/common/ossimTrace.h> +#include <base/data_types/ossimRegExp.h> + +ossimTraceManager* ossimTraceManager::theInstance = 0; + +ossimTraceManager::ossimTraceManager() +{ + theInstance = this; +} + +ossimTraceManager* ossimTraceManager::instance() +{ + if(!theInstance) + { + theInstance = new ossimTraceManager; + } + + return theInstance; +} + +void ossimTraceManager::setTracePattern(const ossimString& pattern) +{ + thePattern = pattern; + setTraceFlags(true); +} + +void ossimTraceManager::addTrace(ossimTrace* traceObj) +{ + if(!traceObj) + { + return; + } + + std::vector<ossimTrace*>::iterator iter = std::find(theTraceList.begin(), + theTraceList.end(), + traceObj); + if(iter == theTraceList.end()) + { + theTraceList.push_back(traceObj); + + if(thePattern.size()) + { + ossimRegExp rxp; + rxp.compile(thePattern.c_str()); + if(rxp.find(traceObj->getTraceName().c_str())) + { + // Found a match so set the flag and increment the counter. + traceObj->setTraceFlag(true); + } + else + { + traceObj->setTraceFlag(false); + } + } + else + { + traceObj->setTraceFlag(false); + } + } +} + +void ossimTraceManager::removeTrace(ossimTrace* traceObj) +{ + std::vector<ossimTrace*>::iterator iter = std::find(theTraceList.begin(), + theTraceList.end(), + traceObj); + + if(iter != theTraceList.end()) + { + theTraceList.erase(iter); + } +} + +void ossimTraceManager::setTraceFlags(bool flag) +{ + ossimRegExp rxp; + rxp.compile(thePattern.c_str()); + + for(ossim_uint32 idx = 0; idx < theTraceList.size(); ++idx) + { + if (rxp.find(theTraceList[idx]->getTraceName().c_str())) + { + // Found a match so set the flag and increment the counter. + theTraceList[idx]->setTraceFlag(flag); + } + } +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimTraceManager.h b/Utilities/OSSIM/ossim_core/base/common/ossimTraceManager.h new file mode 100644 index 0000000000..f7458b64b6 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimTraceManager.h @@ -0,0 +1,69 @@ +//***************************************************************************** +// Copyright (C) 2005 Garrett Potts, all rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// DESCRIPTION: +// Contains declaration of class ossimTraceManager. +// +//***************************************************************************** +// $Id: ossimTraceManager.h,v 1.1 2005/04/18 20:44:56 dburken Exp $ +#ifndef ossimTraceManager_HEADER +#define ossimTraceManager_HEADER + +#include <base/data_types/ossimString.h> + +class ossimTrace; + +class OSSIMDLLEXPORT ossimTraceManager +{ +public: + /** + * @return ossimTraceManager* to instance of the ossim trace manager. + */ + static ossimTraceManager* instance(); + + /** + * Sets "thePattern" to "pattern", then calls setTraceFlags(true). + * + * @param pattern Regular expression to enable trace for. + */ + void setTracePattern(const ossimString& pattern); + + /** + * @param traceObj ossimTrace* to add to "theTraceList". + */ + void addTrace(ossimTrace* traceObj); + + /** + * @param traceObj ossimTrace* to remove from "theTraceList". + */ + void removeTrace(ossimTrace* traceObj); + +protected: + /** Protected default constructor. */ + ossimTraceManager(); + +private: + /** + * Loops through "theTraceList" and sets any trace object's enable flag to + * flag if it matches regular expression of "thePattern". + * For trace objects not matching "thePattern" no action is taken. + */ + void setTraceFlags(bool flag); + + /** The instance of this manager. */ + static ossimTraceManager* theInstance; + + /** The regular expression pattern like "ossimDynamic|ossimGdal". */ + ossimString thePattern; + + /** The list of trace objects. */ + std::vector<ossimTrace*> theTraceList; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimViewController.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimViewController.cpp new file mode 100644 index 0000000000..fda21c6a91 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimViewController.cpp @@ -0,0 +1,173 @@ +#include <base/common/ossimViewController.h> +#include <base/common/ossimViewInterface.h> +#include <base/common/ossimConnectableContainerInterface.h> +#include <base/common/events/ossimListenerManager.h> +#include <base/common/events/ossimPropertyEvent.h> +#include <base/context/ossimNotifyContext.h> +#include <vector> +using namespace std; + +RTTI_DEF1(ossimViewController, "ossimViewController", ossimSource); + +ossimViewController::ossimViewController() + : + ossimSource((ossimObject*)NULL, 0, 0, true, false) +{ + theView = NULL; +} + +ossimViewController::ossimViewController(ossimObject* owner, + ossim_uint32 inputListSize, + ossim_uint32 outputListSize, + bool inputListFixedFlag, + bool outputListFixedFlag) + : + ossimSource(owner, + inputListSize, + outputListSize, + inputListFixedFlag, + outputListFixedFlag) +{ + theView = NULL; +} + +ossimViewController::~ossimViewController() +{ + if(theView) + { + delete theView; + theView = NULL; + propagateView(); + } +} + +ossimString ossimViewController::getShortName()const +{ + return ossimString("View"); +} + + ossimString ossimViewController::getLongName()const +{ + return ossimString("View controller"); +} + +bool ossimViewController::canConnectMyInputTo(ossim_int32, + const ossimConnectableObject*)const +{ + return false; +} + +bool ossimViewController::propagateView() +{ + bool returnResult = true; + if(!theOwner) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL: " << getClassName() << "::propagateView(), has no owner! We must find all views to set.\n"; + return false; + } + ossimConnectableContainerInterface* inter = PTR_CAST(ossimConnectableContainerInterface, + theOwner); + if(inter) + { + RTTItypeid typeId = STATIC_TYPE_INFO(ossimViewInterface); + vector<ossimConnectableObject*> result = inter->findAllObjectsOfType(typeId, + true); + if(result.size() > 0) + { + ossim_uint32 index = 0; + + // first set all views then update all outputs + // + for(index = 0; index < result.size(); ++index) + { + ossimViewInterface* viewInterface = PTR_CAST(ossimViewInterface, result[index]); + + if(viewInterface) + { + if(theView) + { + ossimObject* dupObject = theView->dup(); + if(!viewInterface->setView(dupObject, true)) + { + returnResult = false; + delete dupObject; + } + } + else + { + if(!viewInterface->setView((ossimObject*)NULL, true)) + { + returnResult = false; + } + } + } + } + + for(index = 0; index < result.size(); ++index) + { + ossimPropertyEvent event(result[index]); + result[index]->fireEvent(event); + result[index]->propagateEventToOutputs(event); + } + } + } + + return returnResult; +} + +bool ossimViewController::setView(ossimObject* object) +{ + if(theView&&(theView != object)) + { + delete theView; + theView = NULL; + } + theView = object; + + return true; +} + +ossimObject* ossimViewController::getView() +{ + return theView; +} + +const ossimObject* ossimViewController::getView()const +{ + return theView; +} + +const ossimObject* ossimViewController::findFirstViewOfType(RTTItypeid typeId)const +{ + ossimConnectableContainerInterface* inter = PTR_CAST(ossimConnectableContainerInterface, + theOwner); + if(inter) + { + RTTItypeid viewInterfaceType = STATIC_TYPE_INFO(ossimViewInterface); + vector<ossimConnectableObject*> result = inter->findAllObjectsOfType(viewInterfaceType, + true); + if(result.size() > 0) + { + ossim_uint32 index = 0; + + for(index = 0; index < result.size(); ++index) + { + + ossimViewInterface* viewInterface = PTR_CAST(ossimViewInterface, result[index]); + + if(viewInterface) + { + if(viewInterface->getView()) + { + if(typeId.can_cast(viewInterface->getView()->getType())) + { + return viewInterface->getView(); + } + } + } + } + } + } + + return (ossimObject*)NULL; +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimViewController.h b/Utilities/OSSIM/ossim_core/base/common/ossimViewController.h new file mode 100644 index 0000000000..f3e191276c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimViewController.h @@ -0,0 +1,65 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossimViewController.h,v 1.16 2004/05/20 14:41:10 dburken Exp $ +#ifndef ossimViewController_HEADER +#define ossimViewController_HEADER +#include "base/common/ossimSource.h" +//#include "base/common/ossimViewInterface.h" + +/*! + * All view sources will derive from this class. For example + * we can have a mapped view or Perspective view of the scene + * being rendered. All sources within the containers are expected + * to derive from the view interface. + */ +class OSSIMDLLEXPORT ossimViewController : public ossimSource +{ +public: + + ossimViewController(); + + ossimViewController(ossimObject* owner, + ossim_uint32 inputListSize, + ossim_uint32 outputListSize, + bool inputListFixedFlag=true, + bool outputListFixedFlag=false); + + virtual ~ossimViewController(); + + virtual ossimString getShortName()const; + + virtual ossimString getLongName()const; + + virtual bool propagateView(); + virtual bool setView(ossimObject* object); + virtual ossimObject* getView(); + virtual const ossimObject* getView()const; + virtual bool canConnectMyInputTo(ossim_int32 index, + const ossimConnectableObject* obj)const; + virtual const ossimObject* findFirstViewOfType(RTTItypeid typeId)const; +protected: + ossimObject* theView; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimViewInterface.cpp b/Utilities/OSSIM/ossim_core/base/common/ossimViewInterface.cpp new file mode 100644 index 0000000000..bdadb6f7ac --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimViewInterface.cpp @@ -0,0 +1,22 @@ +#include "ossimViewInterface.h" + +RTTI_DEF(ossimViewInterface, "ossimViewInterface"); + +ossimViewInterface::ossimViewInterface() + : theObject(NULL) +{} + +ossimViewInterface::ossimViewInterface(ossimObject* base) + : theObject(base) +{} + +ossimViewInterface::~ossimViewInterface() +{} + +void ossimViewInterface::refreshView() +{} + +ossimObject* ossimViewInterface::getBaseObject() +{ + return theObject; +} diff --git a/Utilities/OSSIM/ossim_core/base/common/ossimViewInterface.h b/Utilities/OSSIM/ossim_core/base/common/ossimViewInterface.h new file mode 100644 index 0000000000..1972560c64 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/common/ossimViewInterface.h @@ -0,0 +1,59 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossimViewInterface.h,v 1.7 2004/05/13 17:41:52 dburken Exp $ +#ifndef ossimViewInterface_HEADER +#define ossimViewInterface_HEADER +#include "base/common/ossimRtti.h" + +class OSSIMDLLEXPORT ossimObject; + +class OSSIMDLLEXPORT ossimViewInterface +{ +public: + ossimViewInterface(); + ossimViewInterface(ossimObject* base); + virtual ~ossimViewInterface(); + + /*! + * The derived classes should overrid this method and + * return true or fals whether it was able to cast the + * past in view to a view that it can interface to. + * So if you are a projective view you might + * cast to an ossimProjection. The ownsTheView specifies + * whether or not it owns the passed in view pointer. + * This will specifiy whether or not the derived classes + * need to re-allocate the pointer or just delete its old + * pointer and set it to the passed in pointer. + */ + virtual bool setView(ossimObject* baseObject, bool ownsTheView = false)=0; + virtual ossimObject* getView()=0; + virtual const ossimObject* getView()const=0; + virtual void refreshView(); + ossimObject* getBaseObject(); + +protected: + ossimObject* theObject; +TYPE_DATA + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/context/.cvsignore b/Utilities/OSSIM/ossim_core/base/context/.cvsignore new file mode 100644 index 0000000000..42d2532435 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/context/.cvsignore @@ -0,0 +1,2 @@ +*.d + diff --git a/Utilities/OSSIM/ossim_core/base/context/ossimErrorContext.h b/Utilities/OSSIM/ossim_core/base/context/ossimErrorContext.h new file mode 100644 index 0000000000..20b7f4ddc1 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/context/ossimErrorContext.h @@ -0,0 +1,31 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Contains class declaration for ossimErrorContext. +//******************************************************************* +// $Id: ossimErrorContext.h,v 1.10 2004/04/01 17:25:17 gpotts Exp $ + +#ifndef ossimErrorContext_HEADER +#define ossimErrorContext_HEADER + +#include <base/context/ossimNotifyContext.h> +#endif diff --git a/Utilities/OSSIM/ossim_core/base/context/ossimNotifyContext.cpp b/Utilities/OSSIM/ossim_core/base/context/ossimNotifyContext.cpp new file mode 100644 index 0000000000..963e93a719 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/context/ossimNotifyContext.cpp @@ -0,0 +1,403 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Contains class declaration for ossimErrorContext. +//******************************************************************* +// $Id: ossimNotifyContext.cpp,v 1.15 2005/10/17 18:37:16 gpotts Exp $ +#include <iostream> +#include <base/context/ossimNotifyContext.h> +#include <stdio.h> +#include <stdarg.h> +#include <stack> +#ifndef NULL +#include <stddef.h> +#endif + + + + + +static std::ostream* theOssimFatalStream = &std::cerr; +static std::ostream* theOssimWarnStream = &std::cerr; +static std::ostream* theOssimInfoStream = &std::cout; +static std::ostream* theOssimNoticeStream = &std::cout; +static std::ostream* theOssimDebugStream = &std::cout; +static std::ostream* theOssimAlwaysStream = &std::cout; + +static ossimNotifyFlags theNotifyFlags = ossimNotifyFlags_ALL; +std::stack<ossimNotifyFlags> theNotifyFlagsStack; + +template <class charT, class traits = std::char_traits<charT> > +class ossimNullBufferStream : public std::basic_streambuf<charT, traits> +{ +public: + ossimNullBufferStream(){}; + + +protected: + + std::streamsize xsputn(const charT * pChar, std::streamsize n) + { + return 0; + } + +private: + ossimNullBufferStream(const ossimNullBufferStream&); + ossimNullBufferStream& operator=(const ossimNullBufferStream&); +}; + +template <class charT, class traits = std::char_traits<charT> > +class ossimLogFileBufferStream : public std::basic_streambuf<charT, traits> +{ +public: + ossimLogFileBufferStream(){}; + + void setLogFilename(const ossimFilename& file) + { + theLogFilename = file; + } + ossimFilename getLogFilename()const + { + return theLogFilename; + } + +protected: + ossimFilename theLogFilename; + virtual int overflow(int c) + { + if(!traits::eq_int_type(c, traits::eof())) + { + tempString = tempString + ossimString(c); + } + + return c; + } + + virtual std::streamsize xsputn(const charT * pChar, std::streamsize n) + { + tempString = tempString + ossimString(pChar, pChar + n); + + return n; + } + + virtual int sync() + { + std::ofstream outFile(theLogFilename.c_str(), + std::ios::app|std::ios::out); + if(outFile) + { + outFile.write(tempString.c_str(), tempString.length()); + } + + tempString = ""; + return 0; + } + +private: + ossimString tempString; + + ossimLogFileBufferStream(const ossimLogFileBufferStream&); + ossimLogFileBufferStream& operator=(const ossimLogFileBufferStream&); +}; + + +class ossimNullStream : public std::ostream +{ +public: + ossimNullStream() : std::ostream(&nullBufferStream){} + virtual ~ossimNullStream() + { + nullBufferStream.pubsync(); + } + +private: + ossimNullBufferStream<char> nullBufferStream; + // Copy & assignment are undefined in iostreams + ossimNullStream(const ossimNullStream&); + ossimNullStream & operator=(const ossimNullStream&); +}; + +class ossimLogFileStream : public std::ostream +{ +public: + ossimLogFileStream() : std::ostream(&theLogFileBufferStream){} + virtual ~ossimLogFileStream() + { + theLogFileBufferStream.pubsync(); + } + void setLogFilename(const ossimFilename& filename) + { + theLogFileBufferStream.setLogFilename(filename); + } + ossimFilename getLogFilename()const + { + return theLogFileBufferStream.getLogFilename(); + } + +private: + ossimLogFileBufferStream<char> theLogFileBufferStream; + // Copy & assignment are undefined in iostreams + ossimLogFileStream(const ossimLogFileStream&); + ossimLogFileStream & operator=(const ossimLogFileStream&); +}; + +static ossimNullStream theOssimNullStream; +static ossimLogFileStream theLogFileStream; + +void ossimSetDefaultNotifyHandlers() +{ + theOssimFatalStream = &std::cerr; + theOssimWarnStream = &std::cout; + theOssimInfoStream = &std::cout; + theOssimNoticeStream = &std::cout; + theOssimDebugStream = &std::cout; + theOssimAlwaysStream = &std::cout; +} + +void ossimSetNotifyStream(std::ostream* outputStream, + ossimNotifyFlags whichLevelsToRedirect) +{ + if(whichLevelsToRedirect&ossimNotifyFlags_FATAL) + { + theOssimFatalStream = outputStream; + } + if(whichLevelsToRedirect&ossimNotifyFlags_WARN) + { + theOssimWarnStream = outputStream; + } + if(whichLevelsToRedirect&ossimNotifyFlags_INFO) + { + theOssimInfoStream = outputStream; + } + if(whichLevelsToRedirect&ossimNotifyFlags_NOTICE) + { + theOssimNoticeStream = outputStream; + } + if(whichLevelsToRedirect&ossimNotifyFlags_DEBUG) + { + theOssimDebugStream = outputStream; + } +} + +std::ostream* ossimGetNotifyStream(ossimNotifyLevel whichLevel) +{ + std::ostream* notifyStream = &theOssimNullStream; + + switch(whichLevel) + { + case ossimNotifyLevel_ALWAYS: + { + notifyStream = theOssimAlwaysStream; + break; + } + case ossimNotifyLevel_FATAL: + { + notifyStream = theOssimFatalStream; + break; + } + case ossimNotifyLevel_WARN: + { + notifyStream = theOssimWarnStream; + break; + } + case ossimNotifyLevel_INFO: + { + notifyStream = theOssimInfoStream; + break; + } + case ossimNotifyLevel_NOTICE: + { + notifyStream = theOssimNoticeStream; + break; + } + case ossimNotifyLevel_DEBUG: + { + notifyStream = theOssimDebugStream; + break; + } + } + return notifyStream; +} + +OSSIMDLLEXPORT std::ostream& ossimNotify(ossimNotifyLevel level) +{ + if(ossimIsReportingEnabled()) + { + if(theLogFileStream.getLogFilename() != "") + { + return theLogFileStream; + } + else + { + bool reportMessageFlag = false; + switch(level) + { + case ossimNotifyLevel_ALWAYS: + { + reportMessageFlag = true; + break; + } + case ossimNotifyLevel_FATAL: + { + if(theNotifyFlags&ossimNotifyFlags_FATAL) + { + reportMessageFlag = true; + } + break; + } + case ossimNotifyLevel_WARN: + { + if(theNotifyFlags&ossimNotifyFlags_WARN) + { + reportMessageFlag = true; + } + break; + } + case ossimNotifyLevel_INFO: + { + if(theNotifyFlags&ossimNotifyFlags_INFO) + { + reportMessageFlag = true; + } + break; + } + case ossimNotifyLevel_NOTICE: + { + if(theNotifyFlags&ossimNotifyFlags_NOTICE) + { + reportMessageFlag = true; + } + break; + } + case ossimNotifyLevel_DEBUG: + { + if(theNotifyFlags&ossimNotifyFlags_DEBUG) + { + reportMessageFlag = true; + } + break; + } + } + if(reportMessageFlag) + { + return *ossimGetNotifyStream(level); + } + } + } + + return theOssimNullStream; +} + +void ossimSetLogFilename(const ossimFilename& filename) +{ + theLogFileStream.setLogFilename(filename); +} + +ossimString ossimErrorV(const char *fmt, va_list args ) +{ + char temp[2024]; + if(fmt) + { + vsprintf(temp, fmt, args); + } + else + { + sprintf(temp,"%s", ""); + } + + return temp; +} + +void ossimEnableNotify(ossimNotifyFlags flags) +{ + theNotifyFlags = (ossimNotifyFlags)(theNotifyFlags | flags); +} + +void ossimDisableNotify(ossimNotifyFlags flags) +{ + theNotifyFlags = (ossimNotifyFlags)((ossimNotifyFlags_ALL^flags)& + theNotifyFlags); +} + +void ossimSetNotifyFlag(ossimNotifyFlags notifyFlags) +{ + theNotifyFlags = notifyFlags; +} + +void ossimPushNotifyFlags() +{ + theNotifyFlagsStack.push(theNotifyFlags); +} + +void ossimPopNotifyFlags() +{ + if(theNotifyFlagsStack.empty()) + { + return; + } + theNotifyFlags = theNotifyFlagsStack.top(); + theNotifyFlagsStack.pop(); +} + +ossimNotifyFlags ossimGetNotifyFlags() +{ + return theNotifyFlags; +} + + + +bool ossimIsReportingEnabled() +{ + return (theNotifyFlags != ossimNotifyFlags_NONE); +} + + +void ossimNotify(ossimString msg, + ossimNotifyLevel notifyLevel) +{ + ossimNotify(notifyLevel) << msg << "\n"; +} + +void ossimSetError( const char *className, + ossim_int32 error, + const char *fmtString=NULL, ...) +{ + va_list args; + + va_start(args, fmtString); + ossimString result = ossimErrorV(fmtString, args ); + va_end(args); + ossimNotify(ossimNotifyLevel_WARN) << result << "\n"; +} + +void ossimSetInfo( const char *className, + const char *fmtString=NULL, ...) +{ + va_list args; + + va_start(args, fmtString); + ossimString result = ossimErrorV(fmtString, args ); + va_end(args); + ossimNotify(ossimNotifyLevel_WARN) << result << "\n"; +} + + diff --git a/Utilities/OSSIM/ossim_core/base/context/ossimNotifyContext.h b/Utilities/OSSIM/ossim_core/base/context/ossimNotifyContext.h new file mode 100644 index 0000000000..64f6b3b92f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/context/ossimNotifyContext.h @@ -0,0 +1,119 @@ +//------------------------------------------------------------------- +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Contains class declaration for ossimErrorContext. +//------------------------------------------------------------------- +// $Id: ossimNotifyContext.h,v 1.6 2004/04/08 13:44:27 gpotts Exp $ +#ifndef ossimNotifyContext_HEADER +#define ossimNotifyContext_HEADER +#include <iostream> +#include <fstream> +#include <base/common/ossimErrorCodes.h> +#include <base/common/ossimConstants.h> +#include <base/data_types/ossimFilename.h> + +extern "C" +{ +/** + * Notification level enumeration. This specifies the + * level of the mesage being written. + */ +OSSIMDLLEXPORT enum ossimNotifyLevel +{ + ossimNotifyLevel_ALWAYS = 0, + ossimNotifyLevel_FATAL = 1, + ossimNotifyLevel_WARN = 2, + ossimNotifyLevel_NOTICE = 3, + ossimNotifyLevel_INFO = 4, + ossimNotifyLevel_DEBUG = 5 +}; + +/** + * Flags to allow the user to turn off certain notification levels + * + */ +OSSIMDLLEXPORT enum ossimNotifyFlags +{ + ossimNotifyFlags_NONE = 0, + ossimNotifyFlags_FATAL = 1, + ossimNotifyFlags_WARN = 2, + ossimNotifyFlags_NOTICE = 4, + ossimNotifyFlags_INFO = 8, + ossimNotifyFlags_DEBUG = 16, + ossimNotifyFlags_ALL = (ossimNotifyFlags_FATAL| + ossimNotifyFlags_WARN| + ossimNotifyFlags_NOTICE| + ossimNotifyFlags_INFO| + ossimNotifyFlags_DEBUG) +}; + +OSSIMDLLEXPORT void ossimSetDefaultNotifyHandlers(); + +OSSIMDLLEXPORT void ossimSetNotifyStream(std::ostream* outputStream, + ossimNotifyFlags whichLevelsToRedirect=ossimNotifyFlags_ALL); + +OSSIMDLLEXPORT std::ostream* ossimGetNotifyStream(ossimNotifyLevel whichLevel); + +OSSIMDLLEXPORT bool ossimIsReportingEnabled(); + +OSSIMDLLEXPORT std::ostream& ossimNotify(ossimNotifyLevel level = ossimNotifyLevel_WARN); + +/** + * + */ +OSSIMDLLEXPORT void ossimSetLogFilename(const ossimFilename& filename); + + +/** + * + */ +OSSIMDLLEXPORT void ossimDisableNotify(ossimNotifyFlags notifyLevel=ossimNotifyFlags_ALL); + +/** + * + */ +OSSIMDLLEXPORT void ossimEnableNotify(ossimNotifyFlags notifyLevel=ossimNotifyFlags_ALL); + + +OSSIMDLLEXPORT void ossimSetNotifyFlag(ossimNotifyFlags notifyFlags); +OSSIMDLLEXPORT void ossimPushNotifyFlags(); +OSSIMDLLEXPORT void ossimPopNotifyFlags(); +OSSIMDLLEXPORT ossimNotifyFlags ossimGetNotifyFlags(); + + +/** + * + */ +OSSIMDLLEXPORT void ossimSetError( const char *className, + ossim_int32 error, + const char *fmtString, ...); + +/** + * This is for general warnings and information feedback + * + * @param fmtString a C printf() style formatting string used (with the + * following arguments) to prepare an error message. + */ +OSSIMDLLEXPORT void ossimSetInfo( const char *className, + const char *fmtString, ...); +} +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/.cvsignore b/Utilities/OSSIM/ossim_core/base/data_types/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/base/data_types/color_space/.cvsignore b/Utilities/OSSIM/ossim_core/base/data_types/color_space/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/color_space/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimCmyVector.cpp b/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimCmyVector.cpp new file mode 100644 index 0000000000..fc7b21f4fe --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimCmyVector.cpp @@ -0,0 +1,41 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// Description: +// +//************************************************************************* +// $Id: ossimCmyVector.cpp,v 1.1 2002/11/01 19:08:48 gpotts Exp $ +#include "ossimCmyVector.h" +#include "ossimRgbVector.h" + +ossimCmyVector::ossimCmyVector(const ossimRgbVector& rgb) +{ + theC = 255 - rgb.getR(); + theM = 255 - rgb.getG(); + theY = 255 - rgb.getB(); +} + +const ossimCmyVector& ossimCmyVector::operator = (const ossimRgbVector& rgb) +{ + theC = 255 - rgb.getR(); + theM = 255 - rgb.getG(); + theY = 255 - rgb.getB(); + + return *this; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimCmyVector.h b/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimCmyVector.h new file mode 100644 index 0000000000..ca62f39d4d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimCmyVector.h @@ -0,0 +1,68 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// Description: +// +//************************************************************************* +// $Id: ossimCmyVector.h,v 1.3 2003/05/13 11:31:02 dburken Exp $ +#include <iostream> +#include "base/common/ossimConstants.h" + +class OSSIMDLLEXPORT ossimJpegYCbCrVector; +class OSSIMDLLEXPORT ossimHsiVector; +class OSSIMDLLEXPORT ossimHsvVector; +class OSSIMDLLEXPORT ossimRgbVector; + +class OSSIMDLLEXPORT ossimCmyVector +{ +public: + friend std::ostream& operator <<(std::ostream& out, const ossimCmyVector& cmy) + { + out << "<" << cmy.theC << ", " << cmy.theM <<", " << cmy.theY << ">" << std::endl; + + return out; + } + ossimCmyVector(unsigned char c, + unsigned char m, + unsigned char y) + : + theC(c), + theM(m), + theY(y) + {} + ossimCmyVector(const ossimRgbVector& rgb); + + ossim_uint8 getC()const + { + return theC; + } + ossim_uint8 getM()const + { + return theC; + } + ossim_uint8 getY()const + { + return theC; + } + const ossimCmyVector& operator = (const ossimRgbVector& rgb); +protected: + ossim_uint8 theC; + ossim_uint8 theM; + ossim_uint8 theY; +}; diff --git a/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimHsiVector.cpp b/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimHsiVector.cpp new file mode 100644 index 0000000000..04343ee6ea --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimHsiVector.cpp @@ -0,0 +1,97 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@remotesensing.org) +// Description: +// +//************************************************************************* +// $Id: ossimHsiVector.cpp,v 1.5 2005/09/08 13:35:22 gpotts Exp $ +#include "ossimHsiVector.h" +#include "ossimRgbVector.h" +#include "ossimNormRgbVector.h" +#include <math.h> +#include "base/common/ossimCommon.h" + +ossimHsiVector::ossimHsiVector(const ossimRgbVector& rgb) +{ + setFromRgb(rgb.getR()/255.0, rgb.getG()/255.0, rgb.getB()/255.0); +} + +ossimHsiVector::ossimHsiVector(const ossimNormRgbVector& rgb) +{ + setFromRgb(rgb.getR(), rgb.getG(), rgb.getB()); +} + +ossimHsiVector& ossimHsiVector::operator =(const ossimRgbVector& rgb) +{ + setFromRgb(rgb.getR()/255.0, rgb.getG()/255.0, rgb.getB()/255.0); + + return *this; + +} + +ossimHsiVector& ossimHsiVector::operator =(const ossimNormRgbVector& rgb) +{ + setFromRgb(rgb.getR(), rgb.getG(), rgb.getB()); + + return *this; + +} + +void ossimHsiVector::setFromRgb(ossim_float64 r, ossim_float64 g, ossim_float64 b) +{ + ossim_float64 sum = r + g + b; + + theBuf[2] = sum/3; + + if(theBuf[2] > FLT_EPSILON) + { + double deltaI1I2 = r - g; + double root = deltaI1I2*deltaI1I2 + + ((r-b)*(g-b)); + + // compute Saturation from RGB + theBuf[1] = 1 - (3.0/sum)*(MIN(MIN(r,g),b)); + + // compte Hue from Rgb. + if(root >= FLT_EPSILON) + { + theBuf[0] = acos((.5*((r-g)+(r-b)))/ + sqrt(root))*DEG_PER_RAD; + + if(b > g) + { + theBuf[0] = 360 - theBuf[0]; + } + } + else + { + theBuf[0] = b; + } + } + else + { + theBuf[0] = 0; + theBuf[1] = 0; + theBuf[2] = 0; + } + + setH(theBuf[0]); + setS(theBuf[1]); + setI(theBuf[2]); +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimHsiVector.h b/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimHsiVector.h new file mode 100644 index 0000000000..2dd29f9eab --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimHsiVector.h @@ -0,0 +1,84 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@remotesensing.org) +// Description: +// +//************************************************************************* +// $Id: ossimHsiVector.h,v 1.5 2005/09/08 13:35:22 gpotts Exp $ +#ifndef ossimHsiVector_HEADER +#define ossimHsiVector_HEADER +#include <iostream> +#include "base/common/ossimConstants.h" + +class ossimRgbVector; +class ossimNormRgbVector; + +class OSSIMDLLEXPORT ossimHsiVector +{ +public: + friend std::ostream& operator << (std::ostream& out, const ossimHsiVector & data) + { + out << "<" << data.theBuf[0] << ", " + << data.theBuf[1] << ", " + << data.theBuf[2] << ">"; + + return out; + } + // assumed normalized ossim_float64s + // + // + ossimHsiVector(ossim_float64 h=0, ossim_float64 s=0, ossim_float64 i=0) + { + theBuf[0] = h; + theBuf[1] = s; + theBuf[2] = i; + } + ossimHsiVector(const ossimRgbVector& rgb); + ossimHsiVector(const ossimNormRgbVector& rgb); + + ossimHsiVector& operator =(const ossimRgbVector& rgb); + ossimHsiVector& operator =(const ossimNormRgbVector& rgb); + + void setFromRgb(ossim_float64 r, ossim_float64 g, ossim_float64 b); + + ossim_float64 getH()const { return theBuf[0]; } + ossim_float64 getS()const { return theBuf[1]; } + ossim_float64 getI()const { return theBuf[2]; } + void setH(ossim_float64 H) { theBuf[0] = H; } + void setS(ossim_float64 S) { theBuf[1] = S; } + void setI(ossim_float64 I) { theBuf[2] = I; } + + ossim_float64 clamp(ossim_float64 colorValue, ossim_float64 min=0, ossim_float64 max=1)const + { + colorValue = colorValue > max? max:colorValue; + colorValue = colorValue < min? min:colorValue; + + return colorValue; + } + +protected: + /*! + * buf[0] = hue + * buf[1] = saturation + * buf[2] = intensity + */ + ossim_float64 theBuf[3]; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimHsvVector.cpp b/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimHsvVector.cpp new file mode 100644 index 0000000000..f43f6d6617 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimHsvVector.cpp @@ -0,0 +1,107 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@remotesensing.org) +// Description: +// +//************************************************************************* +// $Id: ossimHsvVector.cpp,v 1.3 2002/01/14 16:28:04 gpotts Exp $ +#include <algorithm> +//using namespace std; + +#include "ossimHsvVector.h" +#include "ossimRgbVector.h" +#include <math.h> +#include "base/common/ossimCommon.h" + +const float ossimHsvVector::OSSIM_HSV_UNDEFINED = -1; +ossimHsvVector::ossimHsvVector(const ossimRgbVector& rgb) +{ + float r,g,b; + + r = rgb.getR()/255.0; + g = rgb.getG()/255.0; + b = rgb.getB()/255.0; + + // this code was taken from http://www.acm.org/jgt/papers/SmithLyons96/hsv_rgb.html + // the input RGB is required to be on [0, 1]. + // Their S and V are returned on [0, 1] and H is but we will try + // to make it return on 0..255 for S and V and see what that looks + // like and keep the H on 0..6. + // returned on [0, 6]. Exception: H is returned UNDEFINED if S==0. + + float x, v, f, i; + + x = min(min(r, g), b); + v = max(max(r, g), b); + if(v==x) + { + theBuf[0] = OSSIM_HSV_UNDEFINED, // we really need to mark as undefined + theBuf[1] = 0; + theBuf[2] = v; + } + else + { + f = (r == x) ? g - b : ((g == x) ? b - r : r - g); + i = (r == x) ? 3 : ((g == x) ? 5 : 1); + + theBuf[0] = clamp(i - f /(v - x), 0, 6); + theBuf[0]/=6.0; + theBuf[1] = clamp((v - x)/v, 0, 1); + theBuf[2] = clamp(v, 0, 1); + } +} + +const ossimHsvVector& ossimHsvVector::operator =(const ossimRgbVector& rgb) +{ + float r,g,b; + + r = rgb.getR()/255.0; + g = rgb.getG()/255.0; + b = rgb.getB()/255.0; + + // this code was taken from http://www.acm.org/jgt/papers/SmithLyons96/hsv_rgb.html + // the input RGB is required to be on [0, 1]. + // Their S and V are returned on [0, 1] and H is but we will try + // to make it return on 0..255 for S and V and see what that looks + // like and keep the H on 0..6. + // returned on [0, 6]. Exception: H is returned UNDEFINED if S==0. + + float x, v, f, i; + + x = min(min(r, g), b); + v = max(max(r, g), b); + if(v==x) + { + theBuf[0] = OSSIM_HSV_UNDEFINED, // we really need to mark as undefined + theBuf[1] = 0; + theBuf[2] = v; + } + else + { + f = (r == x) ? g - b : ((g == x) ? b - r : r - g); + i = (r == x) ? 3 : ((g == x) ? 5 : 1); + + theBuf[0] = clamp(i - f /(v - x), 0, 6); + theBuf[0]/=6.0; + theBuf[1] = clamp((v - x)/v, 0, 1); + theBuf[2] = clamp(v, 0, 1); + } + + return *this; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimHsvVector.h b/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimHsvVector.h new file mode 100644 index 0000000000..b3efe2074d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimHsvVector.h @@ -0,0 +1,86 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@remotesensing.org) +// Description: +// +//************************************************************************* +// $Id: ossimHsvVector.h,v 1.5 2002/11/25 18:59:55 gpotts Exp $ +#ifndef ossimHsvVector_HEADER +#define ossimHsvVector_HEADER +#include <iostream> +using namespace std; +#include "base/common/ossimConstants.h" +class OSSIMDLLEXPORT ossimRgbVector; + +class OSSIMDLLEXPORT ossimHsvVector +{ +public: + friend ostream& operator << (ostream& out, const ossimHsvVector & data) + { + out << "<" << data.theBuf[0] << ", " + << data.theBuf[1] << ", " + << data.theBuf[2] << ">"; + + return out; + } + // assumed normalized floats + // + // + ossimHsvVector(float h=0, float s=0, float i=0) + { + theBuf[0] = h; + theBuf[1] = s; + theBuf[2] = i; + } + ossimHsvVector(const ossimRgbVector& rgb); + + const ossimHsvVector& operator =(const ossimRgbVector& rgb); + + float getH()const { return theBuf[0]; } + float getS()const { return theBuf[1]; } + float getV()const { return theBuf[2]; } + + unsigned char getVUnNormalized()const + { + return static_cast<unsigned char>(theBuf[2]*255); + } + void setH(float H) { theBuf[0] = H; } + void setS(float S) { theBuf[1] = S; } + void setV(float V) { theBuf[2] = V; } + + float clamp(float colorValue, float min=0, float max=255)const + { + colorValue = colorValue > max? max:colorValue; + colorValue = colorValue < min? min:colorValue; + + return colorValue; + } + + static const float OSSIM_HSV_UNDEFINED; +protected: + /*! + * buf[0] = hue [0..1] + * buf[1] = saturation [0..1] + * buf[2] = value [0..1] + */ + float theBuf[3]; + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimJpegYCbCrVector.cpp b/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimJpegYCbCrVector.cpp new file mode 100644 index 0000000000..c34f2c2e83 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimJpegYCbCrVector.cpp @@ -0,0 +1,37 @@ +#include "ossimJpegYCbCrVector.h" +#include "base/common/ossimCommon.h" + +#include "ossimRgbVector.h" + +ossimJpegYCbCrVector::ossimJpegYCbCrVector(const ossimRgbVector& rgbColor) +{ + theBuf[0] = static_cast<unsigned char>(clamp(irint(0.299*rgbColor.getR() + + 0.587*rgbColor.getG() + + 0.114*rgbColor.getB()))); + + theBuf[1] = static_cast<unsigned char>(clamp(irint((-0.1687)*rgbColor.getR() - + 0.3313*rgbColor.getG() + + 0.5*rgbColor.getB() + 128))); + + theBuf[2] = static_cast<unsigned char>(clamp(irint(0.5*rgbColor.getR() - + .4187*rgbColor.getG() - + .0813*rgbColor.getB() + 128))); + +} + +ossimJpegYCbCrVector& ossimJpegYCbCrVector::operator =(const ossimRgbVector& rgbColor) +{ + theBuf[0] = static_cast<unsigned char>(clamp(irint(0.299*rgbColor.getR() + + 0.587*rgbColor.getG() + + 0.114*rgbColor.getB()))); + + theBuf[1] = static_cast<unsigned char>(clamp(irint((-0.1687)*rgbColor.getR() - + 0.3313*rgbColor.getG() + + 0.5*rgbColor.getB() + 128))); + + theBuf[2] = static_cast<unsigned char>(clamp(irint(0.5*rgbColor.getR() - + .4187*rgbColor.getG() - + .0813*rgbColor.getB() + 128))); + + return *this; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimJpegYCbCrVector.h b/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimJpegYCbCrVector.h new file mode 100644 index 0000000000..6d7b98a7bc --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimJpegYCbCrVector.h @@ -0,0 +1,84 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@remotesensing.org) +// Description: +// +//************************************************************************* +// $Id: ossimJpegYCbCrVector.h,v 1.3 2002/11/25 18:59:55 gpotts Exp $ +#ifndef ossimJpegYCbCrVector_HEADER +#define ossimJpegYCbCrVector_HEADER +#include <iostream> +using namespace std; +#include "base/common/ossimConstants.h" + +class OSSIMDLLEXPORT ossimRgbVector; + +class OSSIMDLLEXPORT ossimJpegYCbCrVector +{ +public: + friend ostream& operator << (ostream& out, const ossimJpegYCbCrVector& data) + { + out << "<" << (long)data.theBuf[0] << ", " + << (long)data.theBuf[1] << ", " + << (long)data.theBuf[2] << ">"; + + return out; + } + + ossimJpegYCbCrVector(unsigned char Y=0, + unsigned char Cb=0, + unsigned char Cr=0) + { + theBuf[0] = Y; + theBuf[1] = Cb; + theBuf[2] = Cr; + } + + ossimJpegYCbCrVector(const ossimRgbVector&); + + long clamp(long colorValue, unsigned char min=0, unsigned char max=255)const + { + colorValue = colorValue > max? max:colorValue; + colorValue = colorValue < min? min:colorValue; + + return colorValue; + } + + + ossimJpegYCbCrVector& operator =(const ossimRgbVector&); + + unsigned char getY() const { return theBuf[0]; } + unsigned char getCb()const { return theBuf[1]; } + unsigned char getCr()const { return theBuf[2]; } + void setY(unsigned char Y) { theBuf[0] = Y; } + void setCb(unsigned char Cb) { theBuf[1] = Cb; } + void setCr(unsigned char Cr) { theBuf[2] = Cr; } + +protected: + /*! + * JpegYCbCr is an 8-bit YCbCr color model. We + * will let: + * buf[0] = Y + * buf[1] = Cb + * buf[2] = Cr + */ + unsigned char theBuf[3]; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimNormRgbVector.cpp b/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimNormRgbVector.cpp new file mode 100644 index 0000000000..545668dc78 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimNormRgbVector.cpp @@ -0,0 +1,183 @@ +//******************************************************************* +// Copyright (C) 2005 Garrett Potts +// +// License: LGPL +// Author: Garrett Potts +// Description: +// +//************************************************************************* +// $Id: ossimNormRgbVector.cpp,v 1.1 2005/09/08 13:08:29 gpotts Exp $ +#include "ossimNormRgbVector.h" +#include "ossimRgbVector.h" +#include "ossimJpegYCbCrVector.h" +#include "ossimHsiVector.h" +#include "ossimHsvVector.h" +#include "ossimCmyVector.h" +#include "base/common/ossimCommon.h" +#include <math.h> + +ossimNormRgbVector::ossimNormRgbVector(const ossimRgbVector& rgb) +{ + theBuf[0] = rgb.getR()/255.0; + theBuf[1] = rgb.getG()/255.0; + theBuf[2] = rgb.getB()/255.0; +} + +ossimNormRgbVector::ossimNormRgbVector(const ossimJpegYCbCrVector& YCbCr) +{ + (*this) = YCbCr; + +} + +ossimNormRgbVector::ossimNormRgbVector(const ossimHsiVector& hsi) +{ + (*this)=hsi; +} + +ossimNormRgbVector::ossimNormRgbVector(const ossimHsvVector& hsv) +{ + (*this) = hsv; +} + +ossimNormRgbVector::ossimNormRgbVector(const ossimCmyVector& cmy) +{ + theBuf[0] = 255 - cmy.getC(); + theBuf[1] = 255 - cmy.getM(); + theBuf[2] = 255 - cmy.getY(); +} + +const ossimNormRgbVector& ossimNormRgbVector::operator =(const ossimHsvVector& hsv) +{ + // H is given on [0, 6] or UNDEFINED. S and V are given on [0, 1]. + // RGB are each returned on [0, 1]. + float h = hsv.getH(), // unnormalize it + s = hsv.getS(), + v = hsv.getV(); + float m, n, f; + int i; + if(h == ossimHsvVector::OSSIM_HSV_UNDEFINED) + { + theBuf[0] = clamp(v); + theBuf[1] = clamp(v); + theBuf[2] = clamp(v); + } + else + { + h*=6.0; // unnormalize h + i = (int)floor(h); + f = h - i; + if(!(i & 1)) f = 1 - f; // if i is even + m = v * (1 - s); + n = v * (1 - s * f); + switch (i) + { + case 6: + case 0: + { + theBuf[0] = clamp(v); + theBuf[1] = clamp(n); + theBuf[2] = clamp(m); + break; + } + case 1: + { + theBuf[0] = clamp(n); + theBuf[1] = clamp(v); + theBuf[2] = clamp(m); + break; + } + case 2: + { + theBuf[0] = clamp(m); + theBuf[1] = clamp(v); + theBuf[2] = clamp(n); + break; + } + case 3: + { + theBuf[0] = clamp(m); + theBuf[1] = clamp(n); + theBuf[2] = clamp(v); + break; + } + case 4: + { + theBuf[0] = clamp(n); + theBuf[1] = clamp(m); + theBuf[2] = clamp(v); + break; + } + case 5: + { + theBuf[0] = clamp(v); + theBuf[1] = clamp(m); + theBuf[2] = clamp(n); + break; + } + } + } + return *this; +} + +const ossimNormRgbVector& ossimNormRgbVector::operator =(const ossimJpegYCbCrVector& YCbCr) +{ + theBuf[0] = clamp((YCbCr.getY() + + 1.402 * (YCbCr.getCr()-128.0))/255.0); + theBuf[1] = clamp((YCbCr.getY() - + 0.34414 *(YCbCr.getCb()-128.0) - + 0.71414*(YCbCr.getCr()-128.0))/255.0); + theBuf[2] = clamp((YCbCr.getY() + + 1.772 * ( YCbCr.getCb()-128.0))/255.0); + + return *this; +} + +const ossimNormRgbVector& ossimNormRgbVector::operator =(const ossimHsiVector& hsi) +{ + ossim_float32 h = hsi.getH(); + ossim_float32 s = hsi.getS(); + ossim_float32 i = hsi.getI(); + + ossim_float32 r=0; + ossim_float32 g=0; + ossim_float32 b=0; + + if(h <= 120.0) + { + b = i*(1-s); + + r = i*(1 + s*cos(RAD_PER_DEG*h)/cos((60-h)*RAD_PER_DEG)); + g = 3*i - (r+b); + } + else if(h <= 240.0) + { + h-=120; + + r = i*(1-s); + g = i*(1 + s*cos(RAD_PER_DEG*h)/cos((60-h)*RAD_PER_DEG)); + b = 3*i - (r+g); + } + else if(h <= 360.0) + { + h-=240; + + g = i*(1-s); + b = i*(1 + s*cos(RAD_PER_DEG*h)/cos((60-h)*RAD_PER_DEG)); + r = 3*i - (g+b); + } + + theBuf[0] = clamp(r); + theBuf[1] = clamp(g); + theBuf[2] = clamp(b); + + return *this; +} + +const ossimNormRgbVector& ossimNormRgbVector::operator =(const ossimCmyVector& cmy) +{ + theBuf[0] = (255 - cmy.getC())/255.0; + theBuf[1] = (255 - cmy.getM())/255.0; + theBuf[2] = (255 - cmy.getY())/255.0; + + return *this; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimNormRgbVector.h b/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimNormRgbVector.h new file mode 100644 index 0000000000..dfbcfbec94 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimNormRgbVector.h @@ -0,0 +1,109 @@ +//******************************************************************* +// Copyright (C) 2005 Garrett Potts +// +// License: LGPL +// Author: Garrett Potts +// Description: +// +//************************************************************************* +// $Id: ossimNormRgbVector.h,v 1.1 2005/09/08 13:08:29 gpotts Exp $ +#ifndef ossimNormRgbVector_HEADER +#define ossimNormRgbVector_HEADER +#include <iostream> +#include "base/common/ossimConstants.h" + +class ossimJpegYCbCrVector; +class ossimHsiVector; +class ossimHsvVector; +class ossimCmyVector; +class ossimRgbVector; + +class OSSIM_DLL ossimNormRgbVector +{ +public: + friend std::ostream& operator <<(std::ostream& out, const ossimNormRgbVector& data) + { + out << "<" << data.theBuf[0] << ", " + << data.theBuf[1] << ", " + << data.theBuf[2] << ">"; + + return out; + } + ossimNormRgbVector(ossim_float64 r=0, ossim_float64 g=0, ossim_float64 b=0) + { + theBuf[0] = r; + theBuf[1] = g; + theBuf[2] = b; + } + ossimNormRgbVector(ossim_float64 grey) + { + theBuf[0] = grey; + theBuf[1] = grey; + theBuf[2] = grey; + } + ossimNormRgbVector(ossim_float64 colorData[3]) + { + theBuf[0] = colorData[0]; + theBuf[1] = colorData[1]; + theBuf[2] = colorData[2]; + } + ossimNormRgbVector(const ossimNormRgbVector& rgb) + { + theBuf[0] = rgb.theBuf[0]; + theBuf[1] = rgb.theBuf[1]; + theBuf[2] = rgb.theBuf[2]; + } + ossimNormRgbVector(const ossimRgbVector& rgb); + ossimNormRgbVector(const ossimJpegYCbCrVector& YCbCr); + ossimNormRgbVector(const ossimHsiVector& hsi); + ossimNormRgbVector(const ossimHsvVector& hsv); + ossimNormRgbVector(const ossimCmyVector& cmy); + ossimNormRgbVector operator -(const ossimNormRgbVector& rgb)const + { + return ossimNormRgbVector(clamp(theBuf[0] - rgb.theBuf[0]), + clamp(theBuf[1] - rgb.theBuf[1]), + clamp(theBuf[2] - rgb.theBuf[2])); + } + ossimNormRgbVector operator *(ossim_float64 t)const + { + return ossimNormRgbVector(clamp(theBuf[0]*t), + clamp(theBuf[1]*t), + clamp(theBuf[2]*t)); + } + + const ossimNormRgbVector& operator =(const ossimJpegYCbCrVector& data); + const ossimNormRgbVector& operator =(const ossimHsiVector& hsi); + const ossimNormRgbVector& operator =(const ossimHsvVector& hsv); + const ossimNormRgbVector& operator =(const ossimCmyVector& cmy); + bool operator ==(const ossimNormRgbVector& rgb) + { + return ( (rgb.theBuf[0] == theBuf[0])&& + (rgb.theBuf[1] == theBuf[1])&& + (rgb.theBuf[2] == theBuf[2])); + } + bool operator !=(const ossimNormRgbVector& rgb) + { + return ( (rgb.theBuf[0] != theBuf[0])|| + (rgb.theBuf[1] != theBuf[1])|| + (rgb.theBuf[2] != theBuf[2])); + } + static ossim_float64 clamp(ossim_float64 colorValue, ossim_float64 min=0.0, ossim_float64 max=1.0) + { + colorValue = colorValue > max? max:colorValue; + colorValue = colorValue < min? min:colorValue; + + return colorValue; + } + ossim_float64 getR() const { return theBuf[0]; } + ossim_float64 getG()const { return theBuf[1]; } + ossim_float64 getB()const { return theBuf[2]; } + void setR(ossim_float64 r) { theBuf[0] = r; } + void setG(ossim_float64 g) { theBuf[1] = g; } + void setB(ossim_float64 b) { theBuf[2] = b; } + +protected: + ossim_float64 theBuf[3]; + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimRgbVector.cpp b/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimRgbVector.cpp new file mode 100644 index 0000000000..f69952373b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimRgbVector.cpp @@ -0,0 +1,296 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@remotesensing.org) +// Description: +// +//************************************************************************* +// $Id: ossimRgbVector.cpp,v 1.7 2005/09/08 13:35:22 gpotts Exp $ +#include "ossimRgbVector.h" +#include "ossimJpegYCbCrVector.h" +#include "ossimHsiVector.h" +#include "ossimHsvVector.h" +#include "ossimCmyVector.h" +#include "base/common/ossimCommon.h" +#include <math.h> + +ossimRgbVector::ossimRgbVector(const ossimJpegYCbCrVector& YCbCr) +{ + theBuf[0] = static_cast<unsigned char>(clamp(irint(YCbCr.getY() + + 1.402 * (YCbCr.getCr()-128.0)))); + theBuf[1] = static_cast<unsigned char>(clamp(irint(YCbCr.getY() - + 0.34414 *(YCbCr.getCb()-128.0) - + 0.71414*(YCbCr.getCr()-128.0)))); + theBuf[2] = static_cast<unsigned char>(clamp(irint(YCbCr.getY() + + 1.772 * ( YCbCr.getCb()-128.0)))); + +} + +ossimRgbVector::ossimRgbVector(const ossimHsiVector& hsi) +{ + float h = hsi.getH(); + float s = hsi.getS(); + float i = hsi.getI(); + + float r=0; + float g=0; + float b=0; + + if(h <= 120.0) + { + b = i*(1-s); + + r = i*(1 + s*cos(RAD_PER_DEG*h)/cos((60-h)*RAD_PER_DEG)); + g = 3*i - (r+b); + } + else if(h <= 240.0) + { + h-=120; + + r = i*(1-s); + g = i*(1 + s*cos(RAD_PER_DEG*h)/cos((60-h)*RAD_PER_DEG)); + b = 3*i - (r+g); + } + else if(h <= 360.0) + { + h-=240; + + g = i*(1-s); + b = i*(1 + s*cos(RAD_PER_DEG*h)/cos((60-h)*RAD_PER_DEG)); + r = 3*i - (g+b); + } + + theBuf[0] = clamp((long)(r*255)); + theBuf[1] = clamp((long)(g*255)); + theBuf[2] = clamp((long)(b*255)); +} + +ossimRgbVector::ossimRgbVector(const ossimHsvVector& hsv) +{ + // H is given on [0, 6] or UNDEFINED. S and V are given on [0, 1]. + // RGB are each returned on [0, 1]. + float h = hsv.getH(), // unnormalize it + s = hsv.getS(), + v = hsv.getV(); + float m, n, f; + int i; + if(h == ossimHsvVector::OSSIM_HSV_UNDEFINED) + { + theBuf[0] = clamp(irint(v*255)); + theBuf[1] = clamp(irint(v*255)); + theBuf[2] = clamp(irint(v*255)); + } + else + { + h*=6.0; // unnormalize h + i = (int)floor(h); + f = h - i; + if(!(i & 1)) f = 1 - f; // if i is even + m = v * (1 - s); + n = v * (1 - s * f); + switch (i) + { + case 6: + case 0: + { + theBuf[0] = clamp(irint(v*255)); + theBuf[1] = clamp(irint(n*255)); + theBuf[2] = clamp(irint(m*255)); + break; + } + case 1: + { + theBuf[0] = clamp(irint(n*255)); + theBuf[1] = clamp(irint(v*255)); + theBuf[2] = clamp(irint(m*255)); + break; + } + case 2: + { + theBuf[0] = clamp(irint(m*255)); + theBuf[1] = clamp(irint(v*255)); + theBuf[2] = clamp(irint(n*255)); + break; + } + case 3: + { + theBuf[0] = clamp(irint(m*255)); + theBuf[1] = clamp(irint(n*255)); + theBuf[2] = clamp(irint(v*255)); + break; + } + case 4: + { + theBuf[0] = clamp(irint(n*255)); + theBuf[1] = clamp(irint(m*255)); + theBuf[2] = clamp(irint(v*255)); + break; + } + case 5: + { + theBuf[0] = clamp(irint(v*255)); + theBuf[1] = clamp(irint(m*255)); + theBuf[2] = clamp(irint(n*255)); + break; + } + } + } +} + +ossimRgbVector::ossimRgbVector(const ossimCmyVector& cmy) +{ + theBuf[0] = 255 - cmy.getC(); + theBuf[1] = 255 - cmy.getM(); + theBuf[2] = 255 - cmy.getY(); +} + +const ossimRgbVector& ossimRgbVector::operator =(const ossimHsvVector& hsv) +{ + // H is given on [0, 6] or UNDEFINED. S and V are given on [0, 1]. + // RGB are each returned on [0, 1]. + float h = hsv.getH(), // unnormalize it + s = hsv.getS(), + v = hsv.getV(); + float m, n, f; + int i; + if(h == ossimHsvVector::OSSIM_HSV_UNDEFINED) + { + theBuf[0] = clamp(irint(v*255)); + theBuf[1] = clamp(irint(v*255)); + theBuf[2] = clamp(irint(v*255)); + } + else + { + h*=6.0; // unnormalize h + i = (int)floor(h); + f = h - i; + if(!(i & 1)) f = 1 - f; // if i is even + m = v * (1 - s); + n = v * (1 - s * f); + switch (i) + { + case 6: + case 0: + { + theBuf[0] = clamp(irint(v*255)); + theBuf[1] = clamp(irint(n*255)); + theBuf[2] = clamp(irint(m*255)); + break; + } + case 1: + { + theBuf[0] = clamp(irint(n*255)); + theBuf[1] = clamp(irint(v*255)); + theBuf[2] = clamp(irint(m*255)); + break; + } + case 2: + { + theBuf[0] = clamp(irint(m*255)); + theBuf[1] = clamp(irint(v*255)); + theBuf[2] = clamp(irint(n*255)); + break; + } + case 3: + { + theBuf[0] = clamp(irint(m*255)); + theBuf[1] = clamp(irint(n*255)); + theBuf[2] = clamp(irint(v*255)); + break; + } + case 4: + { + theBuf[0] = clamp(irint(n*255)); + theBuf[1] = clamp(irint(m*255)); + theBuf[2] = clamp(irint(v*255)); + break; + } + case 5: + { + theBuf[0] = clamp(irint(v*255)); + theBuf[1] = clamp(irint(m*255)); + theBuf[2] = clamp(irint(n*255)); + break; + } + } + } + return *this; +} + +const ossimRgbVector& ossimRgbVector::operator =(const ossimJpegYCbCrVector& YCbCr) +{ + theBuf[0] = static_cast<unsigned char>(clamp(irint(YCbCr.getY() + + 1.402 * (YCbCr.getCr()-128.0)))); + theBuf[1] = static_cast<unsigned char>(clamp(irint(YCbCr.getY() - + 0.34414 *(YCbCr.getCb()-128.0) - + 0.71414*(YCbCr.getCr()-128.0)))); + theBuf[2] = static_cast<unsigned char>(clamp(irint(YCbCr.getY() + + 1.772 * ( YCbCr.getCb()-128.0)))); + + return *this; +} + +const ossimRgbVector& ossimRgbVector::operator =(const ossimHsiVector& hsi) +{ + float h = hsi.getH(); + float s = hsi.getS(); + float i = hsi.getI(); + + float r=0; + float g=0; + float b=0; + + if(h <= 120.0) + { + b = i*(1-s); + + r = i*(1 + s*cos(RAD_PER_DEG*h)/cos((60-h)*RAD_PER_DEG)); + g = 3*i - (r+b); + } + else if(h <= 240.0) + { + h-=120; + + r = i*(1-s); + g = i*(1 + s*cos(RAD_PER_DEG*h)/cos((60-h)*RAD_PER_DEG)); + b = 3*i - (r+g); + } + else if(h <= 360.0) + { + h-=240; + + g = i*(1-s); + b = i*(1 + s*cos(RAD_PER_DEG*h)/cos((60-h)*RAD_PER_DEG)); + r = 3*i - (g+b); + } + + theBuf[0] = clamp((long)(r*255)); + theBuf[1] = clamp((long)(g*255)); + theBuf[2] = clamp((long)(b*255)); + + return *this; +} + +const ossimRgbVector& ossimRgbVector::operator =(const ossimCmyVector& cmy) +{ + theBuf[0] = 255 - cmy.getC(); + theBuf[1] = 255 - cmy.getM(); + theBuf[2] = 255 - cmy.getY(); + + return *this; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimRgbVector.h b/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimRgbVector.h new file mode 100644 index 0000000000..b69a473598 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/color_space/ossimRgbVector.h @@ -0,0 +1,123 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@remotesensing.org) +// Description: +// +//************************************************************************* +// $Id: ossimRgbVector.h,v 1.10 2002/11/01 19:08:48 gpotts Exp $ +#ifndef ossimRgbVector_HEADER +#define ossimRgbVector_HEADER +#include <iostream> +using namespace std; +#include "base/common/ossimConstants.h" + +class OSSIMDLLEXPORT ossimJpegYCbCrVector; +class OSSIMDLLEXPORT ossimHsiVector; +class OSSIMDLLEXPORT ossimHsvVector; +class OSSIMDLLEXPORT ossimCmyVector; + +class OSSIMDLLEXPORT ossimRgbVector +{ +public: + friend ostream& operator <<(ostream& out, const ossimRgbVector& data) + { + out << "<" << (long)data.theBuf[0] << ", " + << (long)data.theBuf[1] << ", " + << (long)data.theBuf[2] << ">"; + + return out; + } + ossimRgbVector(unsigned char r=0, unsigned char g=0, unsigned char b=0) + { + theBuf[0] = r; + theBuf[1] = g; + theBuf[2] = b; + } + ossimRgbVector(unsigned char grey) + { + theBuf[0] = grey; + theBuf[1] = grey; + theBuf[2] = grey; + } + ossimRgbVector(unsigned char colorData[3]) + { + theBuf[0] = colorData[0]; + theBuf[1] = colorData[1]; + theBuf[2] = colorData[2]; + } + + ossimRgbVector(const ossimJpegYCbCrVector& YCbCr); + ossimRgbVector(const ossimHsiVector& hsi); + ossimRgbVector(const ossimHsvVector& hsv); + ossimRgbVector(const ossimCmyVector& cmy); + + ossimRgbVector operator -(const ossimRgbVector& rgb)const + { + return ossimRgbVector((unsigned char)clamp((long)theBuf[0] - (long)rgb.theBuf[0]), + (unsigned char)clamp((long)theBuf[1] - (long)rgb.theBuf[1]), + (unsigned char)clamp((long)theBuf[2] - (long)rgb.theBuf[2])); + } + + ossimRgbVector operator +(const ossimRgbVector& rgb)const + { + return ossimRgbVector((unsigned char)clamp((long)theBuf[0] + (long)rgb.theBuf[0]), + (unsigned char)clamp((long)theBuf[1] + (long)rgb.theBuf[1]), + (unsigned char)clamp((long)theBuf[2] + (long)rgb.theBuf[2])); + } + ossimRgbVector operator *(double t)const + { + return ossimRgbVector((unsigned char)clamp((long)(theBuf[0]*t)), + (unsigned char)clamp((long)(theBuf[1]*t)), + (unsigned char)clamp((long)(theBuf[2]*t))); + } + const ossimRgbVector& operator =(const ossimJpegYCbCrVector& data); + const ossimRgbVector& operator =(const ossimHsiVector& hsi); + const ossimRgbVector& operator =(const ossimHsvVector& hsv); + const ossimRgbVector& operator =(const ossimCmyVector& cmy); + bool operator ==(const ossimRgbVector& rgb) + { + return ( (rgb.theBuf[0] == theBuf[0])&& + (rgb.theBuf[1] == theBuf[1])&& + (rgb.theBuf[2] == theBuf[2])); + } + bool operator !=(const ossimRgbVector& rgb) + { + return ( (rgb.theBuf[0] != theBuf[0])|| + (rgb.theBuf[1] != theBuf[1])|| + (rgb.theBuf[2] != theBuf[2])); + } + static long clamp(long colorValue, unsigned char min=0, unsigned char max=255) + { + colorValue = colorValue > (long)max? (long)max:colorValue; + colorValue = colorValue < (long)min? (long)min:colorValue; + + return colorValue; + } + unsigned char getR() const { return theBuf[0]; } + unsigned char getG()const { return theBuf[1]; } + unsigned char getB()const { return theBuf[2]; } + void setR(unsigned char R) { theBuf[0] = R; } + void setG(unsigned char G) { theBuf[1] = G; } + void setB(unsigned char B) { theBuf[2] = B; } + +protected: + unsigned char theBuf[3]; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/datum/.cvsignore b/Utilities/OSSIM/ossim_core/base/data_types/datum/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/datum/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/base/data_types/datum/datum.h b/Utilities/OSSIM/ossim_core/base/data_types/datum/datum.h new file mode 100644 index 0000000000..aa99cb3638 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/datum/datum.h @@ -0,0 +1,528 @@ +#ifndef DATUM_H +#define DATUM_H + +/***************************************************************************/ +/* RSC IDENTIFIER: Datum + * + * ABSTRACT + * + * This component provides datum shifts for a large collection of local + * datums, WGS72, and WGS84. A particular datum can be accessed by using its + * standard 5-letter code to find its index in the datum table. The index + * can then be used to retrieve the name, type, ellipsoid code, and datum + * shift parameters, and to perform shifts to or from that datum. + * + * By sequentially retrieving all of the datum codes and/or names, a menu + * of the available datums can be constructed. The index values resulting + * from selections from this menu can then be used to access the parameters + * of the selected datum, or to perform datum shifts involving that datum. + * + * This component supports both 3-parameter local datums, for which only X, + * Y, and Z translations relative to WGS 84 have been defined, and + * 7-parameter local datums, for which X, Y, and Z rotations, and a scale + * factor, are also defined. It also includes entries for WGS 84 (with an + * index of 0), and WGS 72 (with an index of 1), but no shift parameter + * values are defined for these. + * + * This component provides datum shift functions for both geocentric and + * geodetic coordinates. WGS84 is used as an intermediate state when + * shifting from one local datum to another. When geodetic coordinates are + * given Molodensky's method is used, except near the poles where the 3-step + * step method is used instead. Specific algorithms are used for shifting + * between WGS72 and WGS84. + * + * This component depends on two data files, named 3_param.dat and + * 7_param.dat, which contain the datum parameter values. Copies of these + * files must be located in the directory specified by the value of the + * environment variable "DATUM_DATA", if defined, or else in the current + * directory whenever a program containing this component is executed. + * + * Additional datums can be added to these files, either manually or using + * the Create_Datum function. However, if a large number of datums are + * added, the datum table array sizes in this component will have to be + * increased. + * + * This component depends on two other components: the Ellipsoid component + * for access to ellipsoid parameters; and the Geocentric component for + * conversions between geodetic and geocentric coordinates. + * + * ERROR HANDLING + * + * This component checks for input file errors and input parameter errors. + * If an invalid value is found, the error code is combined with the current + * error code using the bitwise or. This combining allows multiple error + * codes to be returned. The possible error codes are: + * + * DATUM_NO_ERROR : No errors occurred in function + * DATUM_NOT_INITIALIZED_ERROR : Datum module has not been initialized + * DATUM_7PARAM_FILE_OPEN_ERROR : 7 parameter file opening error + * DATUM_7PARAM_FILE_PARSING_ERROR : 7 parameter file structure error + * DATUM_7PARAM_OVERFLOW_ERROR : 7 parameter table overflow + * DATUM_3PARAM_FILE_OPEN_ERROR : 3 parameter file opening error + * DATUM_3PARAM_FILE_PARSING_ERROR : 3 parameter file structure error + * DATUM_3PARAM_OVERFLOW_ERROR : 3 parameter table overflow + * DATUM_INVALID_INDEX_ERROR : Index out of valid range (less than one + * or more than Datum_Count) + * DATUM_INVALID_SRC_INDEX_ERROR : Source datum index invalid + * DATUM_INVALID_DEST_INDEX_ERROR : Destination datum index invalid + * DATUM_INVALID_CODE_ERROR : Datum code not found in table + * DATUM_LAT_ERROR : Latitude out of valid range (-90 to 90) + * DATUM_LON_ERROR : Longitude out of valid range (-180 to + * 360) + * DATUM_SIGMA_ERROR : Standard error values must be positive + * (or -1 if unknown) + * DATUM_DOMAIN_ERROR : Domain of validity not well defined + * DATUM_ELLIPSE_ERROR : Error in ellipsoid module + * + * + * REUSE NOTES + * + * Datum is intended for reuse by any application that needs access to + * datum shift parameters relative to WGS 84. + * + * + * REFERENCES + * + * Further information on Datum can be found in the Reuse Manual. + * + * Datum originated from : U.S. Army Topographic Engineering Center (USATEC) + * Geospatial Information Division (GID) + * 7701 Telegraph Road + * Alexandria, VA 22310-3864 + * + * LICENSES + * + * None apply to this component. + * + * RESTRICTIONS + * + * Datum has no restrictions. + * + * ENVIRONMENT + * + * Datum was tested and certified in the following environments: + * + * 1. Solaris 2.5 with GCC 2.8.1 + * 2. MS Windows 95 with MS Visual C++ 6 + * + * MODIFICATIONS + * + * Date Description + * ---- ----------- + * 03/30/97 Original Code + * 05/28/99 Added user-definable datums (for JMTK) + * Added datum domain of validity checking (for JMTK) + * Added datum shift accuracy calculation (for JMTK) + */ + + +/***************************************************************************/ +/* + * DEFINES + */ + +#define DATUM_NO_ERROR 0x0000 +#define DATUM_NOT_INITIALIZED_ERROR 0x0001 +#define DATUM_7PARAM_FILE_OPEN_ERROR 0x0002 +#define DATUM_7PARAM_FILE_PARSING_ERROR 0x0004 +#define DATUM_7PARAM_OVERFLOW_ERROR 0x0008 +#define DATUM_3PARAM_FILE_OPEN_ERROR 0x0010 +#define DATUM_3PARAM_FILE_PARSING_ERROR 0x0020 +#define DATUM_3PARAM_OVERFLOW_ERROR 0x0040 +#define DATUM_INVALID_INDEX_ERROR 0x0080 +#define DATUM_INVALID_SRC_INDEX_ERROR 0x0100 +#define DATUM_INVALID_DEST_INDEX_ERROR 0x0200 +#define DATUM_INVALID_CODE_ERROR 0x0400 +#define DATUM_LAT_ERROR 0x0800 +#define DATUM_LON_ERROR 0x1000 +#define DATUM_SIGMA_ERROR 0x2000 +#define DATUM_DOMAIN_ERROR 0x4000 +#define DATUM_ELLIPSE_ERROR 0x8000 + + +/***************************************************************************/ +/* + * GLOBAL DECLARATIONS + */ +typedef enum Datum_Types +{ + Three_Param_Datum, + Seven_Param_Datum, + WGS84_Datum, + WGS72_Datum +} Datum_Type; /* different types of datums */ + + +/***************************************************************************/ +/* + * FUNCTION PROTOTYPES + */ + +/* ensure proper linkage to c++ programs */ +#ifdef __cplusplus +extern "C" { +#endif + + long Initialize_Datums(void); +/* + * The function Initialize_Datums creates the datum table from two external + * files. If an error occurs, the initialization stops and an error code is + * returned. This function must be called before any of the other functions + * in this component. + */ + + + long Create_Datum ( const char *Code, + const char *Name, + const char *Ellipsoid_Code, + double Delta_X, + double Delta_Y, + double Delta_Z, + double Sigma_X, + double Sigma_Y, + double Sigma_Z, + double South_latitude, + double North_latitude, + double West_longitude, + double East_longitude); +/* + * Code : 5-letter new datum code. (input) + * Name : Name of the new datum (input) + * Ellipsoid_Code : 2-letter code for the associated ellipsoid (input) + * Delta_X : X translation to WGS84 in meters (input) + * Delta_Y : Y translation to WGS84 in meters (input) + * Delta_Z : Z translation to WGS84 in meters (input) + * Sigma_X : Standard error in X in meters (input) + * Sigma_Y : Standard error in Y in meters (input) + * Sigma_Z : Standard error in Z in meters (input) + * South_latitude : Southern edge of validity rectangle in radians(input) + * North_latitude : Northern edge of validity rectangle in radians(input) + * West_longitude : Western edge of validity rectangle in radians (input) + * East_longitude : Eastern edge of validity rectangle in radians (input) + * + * The function Create_Datum creates a new local (3-parameter) datum with the + * specified code, name, shift values, and standard error values. If the + * datum table has not been initialized, the specified code is already in use, + * or a new version of the 3-param.dat file cannot be created, an error code + * is returned, otherwise DATUM_NO_ERROR is returned. Note that the indexes + * of all datums in the datum table may be changed by this function. + */ + + + long Datum_Count ( long *Count ); +/* + * The function Datum_Count returns the number of Datums in the table + * if the table was initialized without error. + * + * Count : number of datums in the datum table (output) + */ + + + long Datum_Index ( const char *Code, + long *Index ); +/* + * The function Datum_Index returns the index of the datum with the + * specified code. + * + * Code : The datum code being searched for (input) + * Index : The index of the datum in the table with the (output) + * specified code + */ + + + long Datum_Code ( const long Index, + char *Code ); +/* + * The function Datum_Code returns the 5-letter code of the datum + * referenced by index. + * + * Index : The index of a given datum in the datum table (input) + * Code : The datum code of the datum referenced by index (output) + */ + + + long Datum_Name ( const long Index, + char *Name ); +/* + * The function Datum_Name returns the name of the datum referenced by + * index. + * + * Index : The index of a given datum in the datum table (input) + * Name : The datum name of the datum referenced by index (output) + */ + + + long Datum_Ellipsoid_Code ( const long Index, + char *Code ); +/* + * The function Datum_Ellipsoid_Code returns the 2-letter ellipsoid code + * for the ellipsoid associated with the datum referenced by index. + * + * Index : The index of a given datum in the datum table (input) + * Code : The ellisoid code for the ellipsoid associated with the (output) + * datum referenced by index + */ + + + long Get_Datum_Type ( const long Index, + Datum_Type *Type ); +/* + * The function Get_Datum_Type returns the type of the datum referenced by + * index. + * + * Index : The index of a given datum in the datum table (input) + * Type : The type of the datum referenced by index (output) + */ + + + long Datum_Seven_Parameters ( const long Index, + double *Delta_X, + double *Delta_Y, + double *Delta_Z, + double *Rx, + double *Ry, + double *Rz, + double *Scale_Factor ); +/* + * The function Datum_Seven_Parameters returns the seven parameters + * for the datum referenced by index. + * + * Index : The index of a given datum in the datum table (input) + * Delta_X : X translation in meters (output) + * Delta_Y : Y translation in meters (output) + * Delta_Z : Z translation in meters (output) + * Rx : X rotation in radians (output) + * Rx : Y rotation in radians (output) + * Ry : Z rotation in radians (output) + * Scale_Factor : Scale factor (output) + */ + + + long Datum_Three_Parameters ( const long Index, + double *Delta_X, + double *Delta_Y, + double *Delta_Z); +/* + * The function Datum_Three_Parameters returns the three parameters + * for the datum referenced by index. + * + * Index : The index of a given datum in the datum table (input) + * Delta_X : X translation in meters (output) + * Delta_Y : Y translation in meters (output) + * Delta_Z : Z translation in meters (output) + */ + + + long Datum_Errors ( const long Index, + double *Sigma_X, + double *Sigma_Y, + double *Sigma_Z); +/* + * The function Datum_Errors returns the standard errors in X,Y, & Z + * for the datum referenced by index. + * + * Index : The index of a given datum in the datum table (input) + * Sigma_X : Standard error in X in meters (output) + * Sigma_Y : Standard error in Y in meters (output) + * Sigma_Z : Standard error in Z in meters (output) + */ + + + long Datum_Valid_Rectangle ( const long Index, + double *South_latitude, + double *North_latitude, + double *West_longitude, + double *East_longitude); +/* + * The function Datum_Valid_Rectangle returns the edges of the validity + * rectangle for the datum referenced by index. + * + * Index : The index of a given datum in the datum table (input) + * South_latitude : Southern edge of validity rectangle in radians (input) + * North_latitude : Northern edge of validity rectangle in radians (input) + * West_longitude : Western edge of validity rectangle in radians (input) + * East_longitude : Eastern edge of validity rectangle in radians (input) + */ + + + long Valid_Datum ( const long Index, + double latitude, + double longitude, + long *result); +/* + * This function checks whether or not the specified location is within the + * validity rectangle for the specified datum. It returns zero if the specified + * location is NOT within the validity rectangle, and returns 1 otherwise. + * + * Index : The index of a given datum in the datum table (input) + * latitude : Latitude of the location to be checked in radians (input) + * longitude : Longitude of the location to be checked in radians (input) + * result : Indicates whether location is inside (1) or outside (0) + * of the validity rectangle of the specified datum (output) + */ + + + long Geocentric_Shift_To_WGS84 (const long Index, + const double X, + const double Y, + const double Z, + double *X_WGS84, + double *Y_WGS84, + double *Z_WGS84); +/* + * This function shifts a geocentric coordinate (X, Y, Z in meters) relative + * to the datum referenced by index to a geocentric coordinate (X, Y, Z in + * meters) relative to WGS84. + * + * Index : Index of local datum (input) + * X : X coordinate relative to the source datum (input) + * Y : Y coordinate relative to the source datum (input) + * Z : Z coordinate relative to the source datum (input) + * X_WGS84 : X coordinate relative to WGS84 (output) + * Y_WGS84 : Y coordinate relative to WGS84 (output) + * Z_WGS84 : Z coordinate relative to WGS84 (output) + */ + + + long Geocentric_Shift_From_WGS84 (const double X_WGS84, + const double Y_WGS84, + const double Z_WGS84, + const long Index, + double *X, + double *Y, + double *Z); +/* + * This function shifts a geocentric coordinate (X, Y, Z in meters) relative + * to WGS84 to a geocentric coordinate (X, Y, Z in meters) relative to the + * local datum referenced by index. + * + * X_WGS84 : X coordinate relative to WGS84 (input) + * Y_WGS84 : Y coordinate relative to WGS84 (input) + * Z_WGS84 : Z coordinate relative to WGS84 (input) + * Index : Index of destination datum (input) + * X : X coordinate relative to the destination datum (output) + * Y : Y coordinate relative to the destination datum (output) + * Z : Z coordinate relative to the destination datum (output) + */ + + + long Geocentric_Datum_Shift ( const long Index_in, + const double X_in, + const double Y_in, + const double Z_in, + const long Index_out, + double *X_out, + double *Y_out, + double *Z_out); +/* + * This function shifts a geocentric coordinate (X, Y, Z in meters) relative + * to the source datum to geocentric coordinate (X, Y, Z in meters) relative + * to the destination datum. + * + * Index_in : Index of source datum (input) + * X_in : X coordinate relative to source datum (input) + * Y_in : Y coordinate relative to source datum (input) + * Z_in : Z coordinate relative to source datum (input) + * Index_out : Index of destination datum (input) + * X_out : X coordinate relative to destination datum (output) + * Y_out : Y coordinate relative to destination datum (output) + * Z_out : Z coordinate relative to destination datum (output) + */ + + + long Geodetic_Shift_To_WGS84 (const long Index, + const double Lat_in, + const double Lon_in, + const double Hgt_in, + double *WGS84_Lat, + double *WGS84_Lon, + double *WGS84_Hgt); +/* + * This function shifts geodetic coordinates relative to a given source datum + * to geodetic coordinates relative to WGS84. + * + * Index : Index of source datum (input) + * Lat_in : Latitude in radians relative to source datum (input) + * Lon_in : Longitude in radians relative to source datum (input) + * Hgt_in : Height in meters relative to source datum's ellipsoid (input) + * WGS84_Lat : Latitude in radians relative to WGS84 (output) + * WGS84_Lon : Longitude in radians relative to WGS84 (output) + * WGS84_Hgt : Height in meters relative to WGS84 ellipsoid (output) + */ + + + long Geodetic_Shift_From_WGS84( const double WGS84_Lat, + const double WGS84_Lon, + const double WGS84_Hgt, + const long Index, + double *Lat_out, + double *Lon_out, + double *Hgt_out); +/* + * This function shifts geodetic coordinates relative to a WGS84 + * to geodetic coordinates relative to a given local datum. + * + * WGS84_Lat : Latitude in radians relative to WGS84 (input) + * WGS84_Lon : Longitude in radians relative to WGS84 (input) + * WGS84_Hgt : Height in meters relative to WGS84 ellipsoid (input) + * Index : Index of destination datum (input) + * Lat_in : Latitude in radians relative to destination datum (output) + * Lon_in : Longitude in radians relative to destination datum (output) + * Hgt_in : Height in meters relative to destination datum's ellipsoid (output) + */ + + + long Geodetic_Datum_Shift ( const long Index_in, + const double Lat_in, + const double Lon_in, + const double Hgt_in, + const long Index_out, + double *Lat_out, + double *Lon_out, + double *Hgt_out); +/* + * This function shifts geodetic coordinates (latitude, longitude in radians + * and height in meters) relative to the source datum to geodetic coordinates + * (latitude, longitude in radians and height in meters) relative to the + * destination datum. + * + * Index_in : Index of source datum (input) + * Lat_in : Latitude in radians relative to source datum (input) + * Lon_in : Longitude in radians relative to source datum (input) + * Hgt_in : Height in meters relative to source datum's ellipsoid (input) + * Index_out : Index of destination datum (input) + * Lat_out : Latitude in radians relative to destination datum (output) + * Lon_out : Longitude in radians relative to destination datum (output) + * Hgt_out : Height in meters relative to destination datum's ellipsoid (output) + */ + + + long Datum_Shift_Error (const long Index_in, + const long Index_out, + double latitude, + double longitude, + double *ce90, + double *le90, + double *se90); +/* + * This function returns the 90% horizontal (circular), vertical (linear), and + * spherical errors for a shift from the specified source datum to the + * specified destination datum at the specified location. + * + * Index_in : Index of source datum (input) + * Index_out : Index of destination datum (input) + * latitude : Latitude of point being converted in radians (input) + * longitude : Longitude of point being converted in radians (input) + * ce90 : Combined 90% circular horizontal error in meters (output) + * le90 : Combined 90% linear vertical error in meters (output) + * se90 : Combined 90% spherical error in meters (output) + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* DATUM_H */ + + diff --git a/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimDatum.cpp b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimDatum.cpp new file mode 100644 index 0000000000..e77e24c148 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimDatum.cpp @@ -0,0 +1,124 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimDatum.cpp,v 1.3 2002/05/24 16:36:02 gpotts Exp $ +#include "ossimDatum.h" +#include "base/data_types/ossimGpt.h" +#include "base/data_types/ellipse/ossimEllipsoid.h" + +void ossimDatum::molodenskyShift(double a, + double da, + double f, + double df, + double dx, + double dy, + double dz, + double Lat_in, + double Lon_in, + double Hgt_in, + double &Lat_out, + double &Lon_out, + double &Hgt_out +)const +{ + /* Begin Molodensky_Shift */ + /* + * This function shifts geodetic coordinates using the Molodensky method. + * + * a : Semi-major axis of source ellipsoid in meters (input) + * da : Destination a minus source a (input) + * f : Flattening of source ellipsoid (input) + * df : Destination f minus source f (input) + * dx : X coordinate shift in meters (input) + * dy : Y coordinate shift in meters (input) + * dz : Z coordinate shift in meters (input) + * Lat_in : Latitude in radians. (input) + * Lon_in : Longitude in radians. (input) + * Hgt_in : Height in meters. (input) + * Lat_out : Calculated latitude in radians. (output) + * Lon_out : Calculated longitude in radians. (output) + * Hgt_out : Calculated height in meters. (output) + */ + double tLon_in; /* temp longitude */ + double e2; /* Intermediate calculations for dp, dl */ + double ep2; /* Intermediate calculations for dp, dl */ + double sin_Lat; /* sin(Latitude_1) */ + double sin2_Lat; /* (sin(Latitude_1))^2 */ + double sin_Lon; /* sin(Longitude_1) */ + double cos_Lat; /* cos(Latitude_1) */ + double cos_Lon; /* cos(Longitude_1) */ + double w2; /* Intermediate calculations for dp, dl */ + double w; /* Intermediate calculations for dp, dl */ + double w3; /* Intermediate calculations for dp, dl */ + double m; /* Intermediate calculations for dp, dl */ + double n; /* Intermediate calculations for dp, dl */ + double dp; /* Delta phi */ + double dp1; /* Delta phi calculations */ + double dp2; /* Delta phi calculations */ + double dp3; /* Delta phi calculations */ + double dl; /* Delta lambda */ + double dh; /* Delta height */ + double dh1; /* Delta height calculations */ + double dh2; /* Delta height calculations */ + + if(Hgt_in == OSSIM_DBL_NAN) + { + Hgt_in = 0.0; + } + + if (Lon_in > M_PI) + tLon_in = Lon_in - (2*M_PI); + else + tLon_in = Lon_in; + + e2 = 2 * f - f * f; + ep2 = e2 / (1 - e2); + sin_Lat = sin(Lat_in); + cos_Lat = cos(Lat_in); + sin_Lon = sin(tLon_in); + cos_Lon = cos(tLon_in); + sin2_Lat = sin_Lat * sin_Lat; + w2 = 1.0 - e2 * sin2_Lat; + w = sqrt(w2); + w3 = w * w2; + m = (a * (1.0 - e2)) / w3; + n = a / w; + dp1 = cos_Lat * dz - sin_Lat * cos_Lon * dx - sin_Lat * sin_Lon * dy; + dp2 = ((e2 * sin_Lat * cos_Lat) / w) * da; + dp3 = sin_Lat * cos_Lat * (2.0 * n + ep2 * m * sin2_Lat) * (1.0 - f) * df; + dp = (dp1 + dp2 + dp3) / (m + Hgt_in); + dl = (-sin_Lon * dx + cos_Lon * dy) / ((n + Hgt_in) * cos_Lat); + dh1 = (cos_Lat * cos_Lon * dx) + (cos_Lat * sin_Lon * dy) + (sin_Lat * dz); + dh2 = -(w * da) + ((a * (1 - f)) / w) * sin2_Lat * df; + dh = dh1 + dh2; + + Lat_out = Lat_in + dp; + Lon_out = Lon_in + dl; + Hgt_out = Hgt_in + dh; + + if (Lon_out > (M_PI * 2)) + Lon_out -= 2*M_PI; + if (Lon_out < (- M_PI)) + Lon_out += 2*M_PI; +} + diff --git a/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimDatum.h b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimDatum.h new file mode 100644 index 0000000000..1a9bf0f571 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimDatum.h @@ -0,0 +1,160 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Contains class declaration for OssimDatum. This is a class wrapper +// for Geotrans datum. For more thorough description of each function +// look at the datum.h file. +//******************************************************************* +// $Id: ossimDatum.h,v 1.9 2003/05/13 11:31:03 dburken Exp $ +#ifndef ossimDatum_HEADER +#define ossimDatum_HEADER +#include "base/common/ossimConstants.h" +#include "base/data_types/ossimString.h" +#include "base/data_types/ossimGpt.h" +#include "base/data_types/ellipse/ossimEllipsoid.h" + +class OSSIMDLLEXPORT ossimDatum +{ +public: + ossimDatum(const ossimString &code, const ossimString &name, + const ossimEllipsoid* anEllipsoid, + ossim_float64 sigmaX, ossim_float64 sigmaY, ossim_float64 sigmaZ, + ossim_float64 westLongitude, ossim_float64 eastLongitude, + ossim_float64 southLatitude, ossim_float64 northLatitude) + :theCode(code), + theName(name), + theEllipsoid(anEllipsoid), + theSigmaX(sigmaX), + theSigmaY(sigmaY), + theSigmaZ(sigmaZ), + theWestLongitude(westLongitude), + theEastLongitude(eastLongitude), + theSouthLatitude(southLatitude), + theNorthLatitude(northLatitude) + {}; + virtual ~ossimDatum(){}; + + // Argument holds the source point and datum. Returns another + // point with this datum. + // + virtual ossimGpt shift(const ossimGpt &aPt)const=0; + //utility functions to shift to and from the standard coordinates. + //Users should use the shift instead!!! + // + virtual ossimGpt shiftToWgs84(const ossimGpt &aPt)const = 0; + virtual ossimGpt shiftFromWgs84(const ossimGpt &aPt)const = 0; + + + virtual bool isTheSameAs(const ossimDatum *aDatum)const + {return this == aDatum;} + virtual const ossimString& code()const{return theCode;} + virtual const ossimString& name()const{return theName;} + virtual const ossimEllipsoid* ellipsoid()const{return theEllipsoid;} + virtual ossim_float64 sigmaX()const{return theSigmaX;} + virtual ossim_float64 sigmaY()const{return theSigmaY;} + virtual ossim_float64 sigmaZ()const{return theSigmaZ;} + + virtual ossim_float64 westLongitude()const{return theWestLongitude;} + virtual ossim_float64 eastLongitude()const{return theEastLongitude;} + virtual ossim_float64 southLatitude()const{return theSouthLatitude;} + virtual ossim_float64 northLatitude()const{return theNorthLatitude;} + + virtual ossim_float64 param1()const=0; + virtual ossim_float64 param2()const=0; + virtual ossim_float64 param3()const=0; + virtual ossim_float64 param4()const=0; + virtual ossim_float64 param5()const=0; + virtual ossim_float64 param6()const=0; + virtual ossim_float64 param7()const=0; + + virtual bool isInside(ossim_float64 latitude, ossim_float64 longitude)const + { + return ((theSouthLatitude <= latitude) && + (latitude <= theNorthLatitude) && + (theWestLongitude <= longitude) && + (longitude <= theEastLongitude)); + } + + bool operator ==(const ossimDatum& rhs)const + { + return ( (theCode == rhs.theCode)&& + (theName == rhs.theName)&& + (*theEllipsoid == *rhs.theEllipsoid)&& + (theSigmaX == rhs.theSigmaX)&& + (theSigmaY == rhs.theSigmaY)&& + (theSigmaZ == rhs.theSigmaZ)&& + (theWestLongitude == rhs.theWestLongitude)&& + (theEastLongitude == rhs.theEastLongitude)&& + (theSouthLatitude == rhs.theSouthLatitude)&& + (theNorthLatitude == rhs.theNorthLatitude)); + } +protected: + + /*! + * This is directly from Geotrans: + * Begin Molodensky_Shift + * This function shifts geodetic coordinates using the Molodensky method. + * + * a : Semi-major axis of source ellipsoid in meters (input) + * da : Destination a minus source a (input) + * f : Flattening of source ellipsoid (input) + * df : Destination f minus source f (input) + * dx : X coordinate shift in meters (input) + * dy : Y coordinate shift in meters (input) + * dz : Z coordinate shift in meters (input) + */ + virtual void molodenskyShift( double a, + double da, + double f, + double df, + double dx, + double dy, + double dz, + double Lat_in, + double Lon_in, + double Hgt_in, + double &Lat_out, + double &Lon_out, + double &Hgt_out)const; + bool withinMolodenskyRange(const ossimGpt& pt)const + { + double lat = pt.latd(); + + return ((lat < 89.75) && (lat > -89.75)); + } + +private: + ossimString theCode; + ossimString theName; + const ossimEllipsoid *theEllipsoid; + + ossim_float64 theSigmaX; + ossim_float64 theSigmaY; + ossim_float64 theSigmaZ; + + ossim_float64 theWestLongitude; + ossim_float64 theEastLongitude; + ossim_float64 theSouthLatitude; + ossim_float64 theNorthLatitude; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconGridDatum.cpp b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconGridDatum.cpp new file mode 100644 index 0000000000..ee14dfda57 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconGridDatum.cpp @@ -0,0 +1,128 @@ +#include "ossimNadconGridDatum.h" + +ossimNadconGridDatum::ossimNadconGridDatum(const ossimFilename& datumDirectory, + const ossimString &code, const ossimString &name, + const ossimEllipsoid* anEllipsoid, + double sigmaX, + double sigmaY, + double sigmaZ, + double westLongitude, + double eastLongitude, + double southLatitude, + double northLatitude, + double param1, + double param2, + double param3) + :ossimThreeParamDatum(code, + name, + anEllipsoid, + sigmaX, + sigmaY, + sigmaZ, + westLongitude, + eastLongitude, + southLatitude, + northLatitude, + param1, + param2, + param3), + theDatumDirectory(datumDirectory) +{ + theCurrentGridRect.makeNan(); + + ossimNadconGridHeader header; + theConusRect.makeNan(); + theHawaiiRect.makeNan(); + theAlaskaRect.makeNan(); + theStGeorgeRect.makeNan(); + theLatStLaurenceRect.makeNan(); + theStPaulRect.makeNan(); + thePrviRect.makeNan(); + + if(header.readHeader(theDatumDirectory.dirCat("conus.las"))) + { + theConusRect = header.getBoundingRect(); + } + if(header.readHeader(theDatumDirectory.dirCat("hawaii.las"))) + { + theHawaiiRect = header.getBoundingRect(); + } + if(header.readHeader(theDatumDirectory.dirCat("alaska.las"))) + { + theAlaskaRect = header.getBoundingRect(); + } + if(header.readHeader(theDatumDirectory.dirCat("stgeorge.las"))) + { + theStGeorgeRect = header.getBoundingRect(); + } + if(header.readHeader(theDatumDirectory.dirCat("stlrnc.las"))) + { + theLatStLaurenceRect = header.getBoundingRect(); + } + if(header.readHeader(theDatumDirectory.dirCat("stpaul.las"))) + { + theStPaulRect = header.getBoundingRect(); + } + if(header.readHeader(theDatumDirectory.dirCat("prvi.las"))) + { + thePrviRect = header.getBoundingRect(); + } +} + +void ossimNadconGridDatum::checkGrid(const ossimDpt& latLon)const +{ + if(theCurrentGridRect.pointWithin(latLon)) + { + return; + } + else if(theConusRect.pointWithin(latLon)) + { + theLatGrid.open(theDatumDirectory.dirCat("conus.las")); + theLonGrid.open(theDatumDirectory.dirCat("conus.los")); + + theCurrentGridRect = theConusRect; + } + else if(theHawaiiRect.pointWithin(latLon)) + { + theLatGrid.open(theDatumDirectory.dirCat("hawaii.las")); + theLonGrid.open(theDatumDirectory.dirCat("hawaii.los")); + + theCurrentGridRect = theHawaiiRect; + } + else if(theAlaskaRect.pointWithin(latLon)) + { + theLatGrid.open(theDatumDirectory.dirCat("alaska.las")); + theLonGrid.open(theDatumDirectory.dirCat("alaska.los")); + + theCurrentGridRect = theAlaskaRect; + } + else if(theStGeorgeRect.pointWithin(latLon)) + { + theLatGrid.open(theDatumDirectory.dirCat("stgeorge.las")); + theLonGrid.open(theDatumDirectory.dirCat("stgeorge.los")); + + theCurrentGridRect = theStGeorgeRect; + } + else if(theLatStLaurenceRect.pointWithin(latLon)) + { + theLatGrid.open(theDatumDirectory.dirCat("stlrnc.las")); + theLonGrid.open(theDatumDirectory.dirCat("stlrnc.los")); + + theCurrentGridRect = theLatStLaurenceRect; + } + else if(theStPaulRect.pointWithin(latLon)) + { + theLatGrid.open(theDatumDirectory.dirCat("stpaul.las")); + theLonGrid.open(theDatumDirectory.dirCat("stpaul.los")); + + theCurrentGridRect = theStPaulRect; + } + else if(thePrviRect.pointWithin(latLon)) + { + theLatGrid.open(theDatumDirectory.dirCat("prvi.las")); + theLonGrid.open(theDatumDirectory.dirCat("prvi.los")); + + theCurrentGridRect = thePrviRect; + } +} + diff --git a/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconGridDatum.h b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconGridDatum.h new file mode 100644 index 0000000000..77e5024318 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconGridDatum.h @@ -0,0 +1,44 @@ +#ifndef ossimNadconGridDatum_HEADER +#define ossimNadconGridDatum_HEADER + +#include "ossimThreeParamDatum.h" +#include "ossimNadconGridFile.h" +#include "base/data_types/ossimDrect.h" + +class ossimNadconGridDatum : public ossimThreeParamDatum +{ +public: + ossimNadconGridDatum(const ossimFilename& datumDirectory, + const ossimString &code, + const ossimString &name, + const ossimEllipsoid* anEllipsoid, + double sigmaX, + double sigmaY, + double sigmaZ, + double westLongitude, + double eastLongitude, + double southLatitude, + double northLatitude, + double param1, + double param2, + double param3); + +protected: + mutable ossimDrect theConusRect; + mutable ossimDrect theHawaiiRect; + mutable ossimDrect theAlaskaRect; + mutable ossimDrect theStGeorgeRect; + mutable ossimDrect theLatStLaurenceRect; + mutable ossimDrect theStPaulRect; + mutable ossimDrect thePrviRect; + + mutable ossimNadconGridFile theLatGrid; + mutable ossimNadconGridFile theLonGrid; + + mutable ossimDrect theCurrentGridRect; + ossimFilename theDatumDirectory; + + void checkGrid(const ossimDpt& latLon)const; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconGridFile.cpp b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconGridFile.cpp new file mode 100644 index 0000000000..dfe0e029f9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconGridFile.cpp @@ -0,0 +1,100 @@ +#include <base/data_types/datum/ossimNadconGridFile.h> +#include <base/misc/ossimEndian.h> + +using namespace std; + +ossimNadconGridFile::~ossimNadconGridFile() +{ + close(); +} + +bool ossimNadconGridFile::open(const ossimFilename& file) +{ + if(theHeader.readHeader(file)) + { + theInputFile.close(); + theInputFile.clear(); + theInputFile.open(file, ios::in|ios::binary); + + theBoundingRect = theHeader.getBoundingRect(); + theLatLonOrigin.lat = theHeader.getMinY(); + theLatLonOrigin.lon = theHeader.getMinX(); + theFilename = file; + theFileOkFlag = true; + return theInputFile.good(); + } + theFileOkFlag = false; + theFilename = ""; + + return false; +} + +void ossimNadconGridFile::close() +{ + theInputFile.close(); +} + +double ossimNadconGridFile::getShiftAtLatLon(double lat, double lon)const +{ + double result = OSSIM_DBL_NAN; + if(pointWithin(lat, lon)) + { + double x = (lon - theLatLonOrigin.lon)/(double)theHeader.getDeltaX(); + double y = (lat - theLatLonOrigin.lat)/(double)theHeader.getDeltaY(); + + int lat0 = (int)y; + int lat1 = lat0 + 1; + int lon0 = (int)x; + int lon1 = lon0 + 1; + + int rows = theHeader.getNumberOfRows(); + int cols = theHeader.getNumberOfCols(); + + if(lat1 >= rows) lat1 = lat0; + if(lon1 >= cols) lon1 = lon0; + + double tLat = y - lat0; + double tLon = x - lon0; + + int offset00 = lat0*theHeader.getBytesPerRow() + lon0*4 + theHeader.getStartOffset(); + int offset01 = lat0*theHeader.getBytesPerRow() + lon1*4 + theHeader.getStartOffset(); + int offset11 = lat1*theHeader.getBytesPerRow() + lon1*4 + theHeader.getStartOffset(); + int offset10 = lat1*theHeader.getBytesPerRow() + lon0*4 + theHeader.getStartOffset(); + + + double v00 = 0.0; + double v01 = 0.0; + double v11 = 0.0; + double v10 = 0.0; + + theInputFile.seekg((std::streampos)offset00); + theInputFile.read((char*)&v00, 4); + theInputFile.seekg((std::streampos)offset01); + theInputFile.read((char*)&v01, 4); + theInputFile.seekg((std::streampos)offset11); + theInputFile.read((char*)&v11, 4); + theInputFile.seekg((std::streampos)offset10); + theInputFile.read((char*)&v10, 4); + ossimEndian anEndian; + + if(anEndian.getSystemEndianType() != OSSIM_LITTLE_ENDIAN) + { + anEndian.swap(v00); + anEndian.swap(v01); + anEndian.swap(v11); + anEndian.swap(v10); + } + + double top = (double)v00 + ((double)v01 - (double)v00)*tLon; + double bottom = (double)v10 + ((double)v11 - (double)v10)*tLon; + + result = top + (bottom-top)*tLat; + } + + return result; +} + +bool ossimNadconGridFile::pointWithin(double lat, double lon)const +{ + return theBoundingRect.pointWithin(ossimDpt(lon, lat)); +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconGridFile.h b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconGridFile.h new file mode 100644 index 0000000000..85d9b2ffb9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconGridFile.h @@ -0,0 +1,54 @@ +//************************************************************************** +// Copyright (C) 2003 Storage Area Networks, Inc. +// +// Written by: Kenneth Melero <kmelero@sanz.com> +// +//************************************************************************** + +#ifndef ossimNadconGridFile_HEADER +#define ossimNadconGridFile_HEADER +#include "ossimNadconGridHeader.h" +#include <fstream> + +class ossimNadconGridFile +{ +public: + ossimNadconGridFile(): + theFileOkFlag(false) + {} + ~ossimNadconGridFile(); + bool open(const ossimFilename& file); + void close(); + + /*! + */ + double getShiftAtLatLon(double lat, double lon)const; + bool pointWithin(double lat, double lon)const; + const ossimDrect getBoundingRect()const + { + return theBoundingRect; + } + + const ossimFilename& getFilename()const + { + return theFilename; + } + bool getFileOkFlag()const + { + return theFileOkFlag; + } + ossimDpt getSpacing()const + { + return theHeader.getSpacing(); + } + +protected: + mutable std::ifstream theInputFile; + mutable bool theFileOkFlag; + ossimFilename theFilename; + ossimNadconGridHeader theHeader; + ossimDrect theBoundingRect; + ossimDpt theLatLonOrigin; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconGridHeader.cpp b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconGridHeader.cpp new file mode 100644 index 0000000000..4fc4d338ca --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconGridHeader.cpp @@ -0,0 +1,60 @@ +//************************************************************************** +// Copyright (C) 2003 Storage Area Networks, Inc. +// +// Written by: Kenneth Melero <kmelero@sanz.com> +// +//************************************************************************** + +#include <fstream> +#include "ossimNadconGridHeader.h" +#include "base/misc/ossimEndian.h" + +std::ostream& operator <<(std::ostream& out, const ossimNadconGridHeader& rhs) +{ + out << "theCols: " << rhs.theCols << endl + << "theRows: " << rhs.theRows << endl + << "theZ: " << rhs.theZ << endl + << "theMinX: " << rhs.theMinX <<endl + << "theDx: " << rhs.theDx << endl + << "theMinY: " << rhs.theMinY << endl + << "theDy: " << rhs.theDy << endl + << "Bounds: " << rhs.getBoundingRect() << endl; + return out; +} + +bool ossimNadconGridHeader::readHeader(const ossimFilename& file) +{ + ifstream in(file.c_str(), ios::in|ios::binary); + + if(in) + { + return readHeader(in); + } + + return false; +} + +bool ossimNadconGridHeader::readHeader(std::istream& in) +{ + in.read((char*)theCharBuf, 64); + in.read((char*)&theCols, 4); + in.read((char*)&theRows, 4); + in.read((char*)&theZ, 4); + in.read((char*)&theMinX, 4); + in.read((char*)&theDx, 4); + in.read((char*)&theMinY, 4); + in.read((char*)&theDy, 4); + ossimEndian anEndian; + if(anEndian.getSystemEndianType() != OSSIM_LITTLE_ENDIAN) + { + anEndian.swap(theCols); + anEndian.swap(theRows); + anEndian.swap(theZ); + anEndian.swap(theMinX); + anEndian.swap(theDx); + anEndian.swap(theMinY); + anEndian.swap(theDy); + } + + return in.good(); +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconGridHeader.h b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconGridHeader.h new file mode 100644 index 0000000000..bedade8d20 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconGridHeader.h @@ -0,0 +1,89 @@ +//************************************************************************** +// Copyright (C) 2003 Storage Area Networks, Inc. +// +// Written by: Kenneth Melero <kmelero@sanz.com> +// +//************************************************************************** + +#ifndef ossimNadconGridHeader_HEADER +#define ossimNadconGridHeader_HEADER +#include <iostream> +#include "base/common/ossimConstants.h" +#include "base/data_types/ossimFilename.h" +#include "base/data_types/ossimDrect.h" + +class ossimNadconGridHeader +{ +public: + friend std::ostream& operator <<(std::ostream& out, const ossimNadconGridHeader& rhs); + ossimNadconGridHeader() + :theCols(0), + theRows(0), + theZ(0), + theMinX(0), + theDx(0), + theMinY(0), + theDy(0) + { + } + bool readHeader(const ossimFilename& file); + bool readHeader(std::istream& in); + + int getStartOffset()const + { + return (theCols+2)*4; + } + + int getBytesPerRow()const + { + return (theCols+1)*4; + } + + int getNumberOfRows()const + { + return theRows; + } + int getNumberOfCols()const + { + return theCols; + } + double getDeltaX()const + { + return (double)theDx; + } + double getDeltaY()const + { + return (double)theDy; + } + ossimDrect getBoundingRect()const + { + return ossimDrect(theMinX, + theMinY + (theRows)*theDy, + theMinX + (theCols)*theDx, + theMinY, + OSSIM_RIGHT_HANDED); + } + double getMinX()const + { + return theMinX; + } + double getMinY()const + { + return theMinY; + } + ossimDpt getSpacing()const + { + return ossimDpt(theDx, theDy); + } +protected: + int* theCharBuf[64]; + int theCols; + int theRows; + int theZ; + double theMinX; + double theDx; + double theMinY; + double theDy; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconNarDatum.cpp b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconNarDatum.cpp new file mode 100644 index 0000000000..eb2efa898d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconNarDatum.cpp @@ -0,0 +1,66 @@ +#include "ossimNadconNarDatum.h" + +ossimNadconNarDatum::ossimNadconNarDatum(const ossimFilename& nadconDirectory) + : + ossimNadconGridDatum(nadconDirectory, + ossimString("NAR"), + ossimString("NORTH AMERICAN 1983 NADCON, CONUS GRID"), + ossimEllipsoidFactory::instance()->create(ossimString("RF")), + 2.000000000000000, 2.000000000000000, 2.000000000000000, + -135.0, -60.0, 15.0, 60.0, + 0.000000000000000, 0.000000000000000, 0.000000000000000) +{ +} + +ossimGpt ossimNadconNarDatum::shift(const ossimGpt &aPt)const +{ + const ossimDatum* datum = aPt.datum(); + ossimString code = datum->code(); + ossimString subCode(code.begin(), + code.begin() + 3); + if(subCode == "NAR") + { + return aPt; + } + else + { + if(subCode == "NAS") + { + checkGrid(aPt); + if(!theLatGrid.getFileOkFlag()|| + !theLonGrid.getFileOkFlag()) + { + return ossimThreeParamDatum::shift(aPt); + } + + double shiftLat = theLatGrid.getShiftAtLatLon(aPt.latd(), aPt.lond()); + double shiftLon = theLonGrid.getShiftAtLatLon(aPt.latd(), aPt.lond()); + + if((shiftLat == OSSIM_DBL_NAN)|| + (shiftLon == OSSIM_DBL_NAN)) + { + return ossimThreeParamDatum::shift(aPt); + } + else + { + // Note the shifts are stored in the file + // as seconds. + // + // convert the seconds into decimal degrees. + // + shiftLat /= 3600.0; + shiftLon /= 3600.0; + return ossimGpt(aPt.latd() + shiftLat, + aPt.lond() - shiftLon, + aPt.height(), + this); + } + } + else + { + return ossimThreeParamDatum::shift(aPt); + } + } + + return ossimThreeParamDatum::shift(aPt); +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconNarDatum.h b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconNarDatum.h new file mode 100644 index 0000000000..d629fe86d3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconNarDatum.h @@ -0,0 +1,21 @@ +#ifndef ossimNadconNarDatum_HEADER +#define ossimNadconNarDatum_HEADER + +#include "ossimNadconGridDatum.h" +#include "ossimNadconGridFile.h" +class ossimNadconNarDatum : public ossimNadconGridDatum +{ +public: + ossimNadconNarDatum(const ossimFilename& nadconDirectory); + + // Argument holds the source point and datum. Returns another + // point with this datum. + // + virtual ossimGpt shift(const ossimGpt &aPt)const; + //utility functions to shift to and from the standard coordinates. + //Users should use the shift instead!!! + // + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconNasDatum.cpp b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconNasDatum.cpp new file mode 100644 index 0000000000..a16bb61ff5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconNasDatum.cpp @@ -0,0 +1,106 @@ +#include "ossimNadconNasDatum.h" + +ossimNadconNasDatum::ossimNadconNasDatum(const ossimFilename& nadconDirectory) + : + ossimNadconGridDatum(nadconDirectory, + ossimString("NAS"), + ossimString("NORTH AMERICAN 1927 NADCON, CONUS GRID"), + ossimEllipsoidFactory::instance()->create(ossimString("CC")), + 5.000000000000000, 5.000000000000000, 6.000000000000000, + -135, -60.0, 15.0, 60.0, -8.0, 160.0, 176.0) +{ +} + +ossimGpt ossimNadconNasDatum::shift(const ossimGpt& aPt)const +{ + const ossimDatum* datum = aPt.datum(); + ossimString code = datum->code(); + ossimString subCode(code.begin(), + code.begin() + 3); + if(subCode == "NAS") + { + return aPt; + } + else + { + if(subCode == "NAR") + { + checkGrid(aPt); + if(!theLatGrid.getFileOkFlag()|| + !theLonGrid.getFileOkFlag()) + { + return ossimThreeParamDatum::shift(aPt); + } + ossimDpt pt; + ossimDpt tempPt; + ossimDpt deltaPt; + double shiftLat; + double shiftLon; + double minLat = theCurrentGridRect.ll().lat; + double maxLat = theCurrentGridRect.ul().lat; + double minLon = theCurrentGridRect.ul().lon; + double maxLon = theCurrentGridRect.ur().lon; + int maxIter = 20; + double epsilon = 1.0e-9; + int c = 0; + + pt.lat = aPt.latd(); + pt.lon = aPt.lond(); + ossimDpt pt2; + tempPt = pt; + ossimDpt delta2; + while(c < maxIter) + { + if(tempPt.lat < minLat) tempPt.lat = minLat; + if(tempPt.lat > maxLat) tempPt.lat = maxLat; + if(tempPt.lon < minLon) tempPt.lon = minLon; + if(tempPt.lon > maxLon) tempPt.lon = maxLon; + + shiftLat = theLatGrid.getShiftAtLatLon(tempPt.lat, tempPt.lon); + shiftLon = theLonGrid.getShiftAtLatLon(tempPt.lat, tempPt.lon); + + + pt2.lat = tempPt.lat + shiftLat/3600.0; + pt2.lon = tempPt.lon - shiftLon/3600.0; + + delta2 = pt2-pt; + if(c == 0) + { + if(fabs(deltaPt.lon) > epsilon) + { + tempPt.lon = pt.lon - shiftLon/3600.0; + } + if(fabs(deltaPt.lat) > epsilon) + { + tempPt.lat = pt.lat + shiftLat/3600.0; + } + } + else + { + if(fabs(delta2.lon) > epsilon) + { + tempPt.lon = tempPt.lon - delta2.lon; + } + if(fabs(delta2.lat) > epsilon) + { + tempPt.lat =tempPt.lat - delta2.lat; + } + } + if((fabs(delta2.lat) < epsilon)&& + (fabs(delta2.lon) < epsilon)) + { + break; + } + else + { + ++c; + } + } + return ossimGpt(tempPt.lat, + tempPt.lon, + aPt.height(), + this); + } + } + return ossimThreeParamDatum::shift(aPt); +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconNasDatum.h b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconNasDatum.h new file mode 100644 index 0000000000..202779d43f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimNadconNasDatum.h @@ -0,0 +1,19 @@ +#ifndef ossimNadconNasDatum_HEADER +#define ossimNadconNasDatum_HEADER + +#include "ossimNadconGridDatum.h" +#include "ossimNadconGridFile.h" + +class ossimNadconNasDatum : public ossimNadconGridDatum +{ +public: + ossimNadconNasDatum(const ossimFilename& nadconDirectory); + + // Argument holds the source point and datum. Returns another + // point with this datum. + // + virtual ossimGpt shift(const ossimGpt &aPt)const; + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimSevenParamDatum.cpp b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimSevenParamDatum.cpp new file mode 100644 index 0000000000..03eefd5f03 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimSevenParamDatum.cpp @@ -0,0 +1,172 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// SevenParamDatum. This is a base class for all +// seven param datums. +//******************************************************************* +// $Id: ossimSevenParamDatum.cpp,v 1.9 2003/09/29 13:57:19 gpotts Exp $ + +#include "ossimSevenParamDatum.h" +#include "base/factory/ossimDatumFactory.h" +#include "base/data_types/ellipse/ossimEllipsoid.h" +#include "base/data_types/ossimEcefPoint.h" +#include "ossimWgs84Datum.h" + +ossimGpt ossimSevenParamDatum::shift(const ossimGpt &aPt)const +{ + const ossimDatum* aDatum = aPt.datum(); + + if( (ellipsoid()->getA()== aPt.datum()->ellipsoid()->getA())&& + (ellipsoid()->getB()== aPt.datum()->ellipsoid()->getB())) + { + return ossimGpt(aPt.latd(), aPt.lond(), aPt.height(), this); + } + + if(aDatum) + { + return shiftFromWgs84( aDatum->shiftToWgs84(aPt) ); + } + + return aPt; +} + +ossimGpt ossimSevenParamDatum::shiftToWgs84(const ossimGpt &aPt)const +{ + ossimEcefPoint p1 = aPt; + ossimEcefPoint p2; + +// if(aPt.isHgtNan()) +// { +// p1 = ossimEcefPoint(ossimGpt(aPt.latd(), +// aPt.lond(), +// 0, +// aPt.datum())); +// } + +// if(withinMolodenskyRange(aPt.latd())) +// { +// ossimWgs84Datum wgs84; +// double latin, lonin, hgtin; +// double latout, lonout, hgtout; + +// double a = wgs84.ellipsoid()->getA(); +// double f = wgs84.ellipsoid()->getFlattening(); +// double da = a - ellipsoid()->getA(); +// double df = f - ellipsoid()->getFlattening(); + +// latin = aPt.latr(); +// lonin = aPt.lonr(); +// hgtin = aPt.height(); + +// if(aPt.isHgtNan()) +// { +// hgtin = 0.0; +// } +// molodenskyShift(a, da, f, df, param1(), param2(), param3(), +// latin, lonin, hgtin, +// latout, lonout, hgtout); + +// ossimGpt g; + +// g.latr(latout); +// g.lonr(lonout); +// g.height(hgtout); +// if(aPt.isHgtNan()) +// { +// g.height(OSSIM_DBL_NAN); +// } +// return g; +// } +// else + { + //this is straight from Geotrans + p2.x() = p1.x() + theParam1 + theParam6*p1.y() - + theParam5*p1.z() + theParam7*p1.x(); + p2.y() = p1.y() + theParam2 - theParam6*p1.x()+ + theParam4*p1.z() + theParam7*p1.y(); + p2.z() = p1.z() + theParam3 + theParam5*p1.x() - + theParam4*p1.y() + theParam7*p1.z(); + } + + return ossimGpt(p2); // defaults to WGS84 +} + +ossimGpt ossimSevenParamDatum::shiftFromWgs84(const ossimGpt &aPt)const +{ + ossimEcefPoint p1; + ossimEcefPoint p2; + + if(aPt.isHgtNan()) + { + p1 = ossimEcefPoint(ossimGpt(aPt.latd(), + aPt.lond(), + 0, + aPt.datum())); + } + else + { + p1 = ossimEcefPoint(aPt); + } +// if(withinMolodenskyRange(aPt.latd())) +// { +// ossimWgs84Datum wgs84; +// double latin, lonin, hgtin; +// double latout, lonout, hgtout; + +// double a = wgs84.ellipsoid()->getA(); +// double f = wgs84.ellipsoid()->getFlattening(); +// double da = ellipsoid()->getA() - a; +// double df = ellipsoid()->getFlattening() - f; + +// latin = aPt.latr(); +// lonin = aPt.lonr(); +// hgtin = aPt.height(); + +// if(aPt.isHgtNan()) +// { +// hgtin = 0.0; +// } +// molodenskyShift(a, da, f, df, -param1(), -param2(), -param3(), +// latin, lonin, hgtin, +// latout, lonout, hgtout); +// ossimGpt g; + +// g.latr(latout); +// g.lonr(lonout); +// g.height(hgtout); +// g.datum(this); +// return g; +// } +// else +// { + p2.x() = p1.x() - theParam1 - theParam6 * p1.y() + + theParam5 * p1.z() - theParam7 * p1.x(); + p2.y() = p1.y() - theParam2 + theParam6 * p1.x() + - theParam4 *p1.z() - theParam7 * p1.y(); + + p2.z() = p1.z() - theParam3 - theParam5 * p1.x() + + theParam4 * p1.y() - theParam7 * p1.z(); +// } + + return ossimGpt(p2, this); +} + diff --git a/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimSevenParamDatum.h b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimSevenParamDatum.h new file mode 100644 index 0000000000..8e3e5de815 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimSevenParamDatum.h @@ -0,0 +1,91 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// SevenParamDatum. This is a base class for all +// seven param datums. +//******************************************************************* +// $Id: ossimSevenParamDatum.h,v 1.5 2003/05/13 11:31:03 dburken Exp $ + +#ifndef ossimSevenParamDatum_HEADER +#define ossimSevenParamDatum_HEADER +#include "ossimDatum.h" +class OSSIMDLLEXPORT ossimEllipsoid; + +class OSSIMDLLEXPORT ossimSevenParamDatum : public ossimDatum +{ +public: + ossimSevenParamDatum(const ossimString &code, const ossimString &name, + const ossimEllipsoid* anEllipsoid, + ossim_float64 sigmaX, + ossim_float64 sigmaY, + ossim_float64 sigmaZ, + ossim_float64 westLongitude, + ossim_float64 eastLongitude, + ossim_float64 southLatitude, + ossim_float64 northLatitude, + ossim_float64 aParam1, + ossim_float64 aParam2, + ossim_float64 aParam3, + ossim_float64 aParam4, + ossim_float64 aParam5, + ossim_float64 aParam6, + ossim_float64 aParam7) + : ossimDatum(code, name, anEllipsoid, + sigmaX, sigmaY, sigmaZ, + westLongitude, eastLongitude, + southLatitude, northLatitude), + theParam1(aParam1), + theParam2(aParam2), + theParam3(aParam3), + theParam4(aParam4), + theParam5(aParam5), + theParam6(aParam6), + theParam7(aParam7) + {} + + + /*! + * Will shift the ground point relative to this datum. + */ + ossimGpt shift(const ossimGpt &aPt)const; + virtual ossimGpt shiftToWgs84(const ossimGpt &aPt)const; + virtual ossimGpt shiftFromWgs84(const ossimGpt &aPt)const; + + virtual ossim_float64 param1()const{return theParam1;} + virtual ossim_float64 param2()const{return theParam2;} + virtual ossim_float64 param3()const{return theParam3;} + virtual ossim_float64 param4()const{return theParam4;} + virtual ossim_float64 param5()const{return theParam5;} + virtual ossim_float64 param6()const{return theParam6;} + virtual ossim_float64 param7()const{return theParam7;} + +private: + ossim_float64 theParam1; + ossim_float64 theParam2; + ossim_float64 theParam3; + ossim_float64 theParam4; + ossim_float64 theParam5; + ossim_float64 theParam6; + ossim_float64 theParam7; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimThreeParamDatum.cpp b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimThreeParamDatum.cpp new file mode 100644 index 0000000000..e684a0cf4d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimThreeParamDatum.cpp @@ -0,0 +1,138 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +//******************************************************************* +// $Id: ossimThreeParamDatum.cpp,v 1.13 2005/09/19 11:40:10 gpotts Exp $ + +#include <math.h> + +#include "ossimThreeParamDatum.h" +#include "base/common/ossimConstants.h" +#include "base/factory/ossimDatumFactory.h" +#include "base/data_types/ellipse/ossimEllipsoid.h" +#include "base/data_types/ossimGpt.h" +#include "base/data_types/ossimEcefPoint.h" +#include "base/data_types/datum/ossimWgs84Datum.h" + +ossimGpt ossimThreeParamDatum::shiftToWgs84(const ossimGpt &aPt)const +{ + ossimEcefPoint p1 = aPt; + ossimEcefPoint p2; + + if(withinMolodenskyRange(aPt.latd())) + { + ossimWgs84Datum wgs84; + double latin, lonin, hgtin; + double latout, lonout, hgtout; + + double da = wgs84.ellipsoid()->getA() - ellipsoid()->getA(); + double df = wgs84.ellipsoid()->getFlattening() - ellipsoid()->getFlattening(); + + latin = aPt.latr(); + lonin = aPt.lonr(); + hgtin = aPt.height(); + + if(aPt.isHgtNan()) + { + hgtin = 0.0; + } + molodenskyShift(ellipsoid()->getA(), da, ellipsoid()->getFlattening(), df, param1(), param2(), param3(), + latin, lonin, hgtin, + latout, lonout, hgtout); + ossimGpt g; + + g.latr(latout); + g.lonr(lonout); + g.height(hgtout); + g.datum(this); + return g; + } + else + { + p2 = ossimEcefPoint(p1.x() + theParam1, + p1.y() + theParam2, + p1.z() + theParam3); + } + + return ossimGpt(p2); // defaults to WGS84 +} + +ossimGpt ossimThreeParamDatum::shiftFromWgs84(const ossimGpt &aPt)const +{ + ossimEcefPoint p1=aPt; + ossimEcefPoint p2=aPt; + + if(withinMolodenskyRange(aPt.latd())) + { + ossimWgs84Datum wgs84; + double latin, lonin, hgtin; + double latout, lonout, hgtout; + + double da = ellipsoid()->getA() - wgs84.ellipsoid()->getA(); + double df = ellipsoid()->getFlattening() - wgs84.ellipsoid()->getFlattening(); + + latin = aPt.latr(); + lonin = aPt.lonr(); + hgtin = aPt.height(); + + if(aPt.isHgtNan()) + { + hgtin = 0.0; + } + molodenskyShift(wgs84.ellipsoid()->getA(), da, wgs84.ellipsoid()->getFlattening(), df, -param1(), -param2(), -param3(), + latin, lonin, hgtin, + latout, lonout, hgtout); + ossimGpt g; + + g.latr(latout); + g.lonr(lonout); + g.height(hgtout); + g.datum(this); + return g; + } + else + { + p2 = ossimEcefPoint(p1.x() - theParam1, + p1.y() - theParam2, + p1.z() - theParam3); + } + + + return ossimGpt(p2, this); +} + + +ossimGpt ossimThreeParamDatum::shift(const ossimGpt &aPt)const +{ + const ossimDatum *aDatum = aPt.datum(); + + if( code() == aDatum->code()) + { + return ossimGpt(aPt.latd(), aPt.lond(), aPt.height(), this); + } + + if(aDatum) + { + return shiftFromWgs84(aDatum->shiftToWgs84(aPt)); + } + + return aPt; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimThreeParamDatum.h b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimThreeParamDatum.h new file mode 100644 index 0000000000..98754e63a9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimThreeParamDatum.h @@ -0,0 +1,81 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// ossimThreeParamDatum. This is a base class for all +// three param datums. +//******************************************************************* +// $Id: ossimThreeParamDatum.h,v 1.5 2003/05/13 11:31:03 dburken Exp $ + +#ifndef ossimThreeParamDatum_HEADER +#define ossimThreeParamDatum_HEADER +#include "ossimDatum.h" + +class OSSIMDLLEXPORT ossimThreeParamDatum : public ossimDatum +{ +public: + ossimThreeParamDatum(const ossimString &code, const ossimString &name, + const ossimEllipsoid* anEllipsoid, + ossim_float64 sigmaX, + ossim_float64 sigmaY, + ossim_float64 sigmaZ, + ossim_float64 westLongitude, + ossim_float64 eastLongitude, + ossim_float64 southLatitude, + ossim_float64 northLatitude, + ossim_float64 param1, + ossim_float64 param2, + ossim_float64 param3) + : ossimDatum(code, name, anEllipsoid, + sigmaX, sigmaY, sigmaZ, + westLongitude, eastLongitude, + southLatitude, northLatitude), + theParam1(param1), + theParam2(param2), + theParam3(param3) + {} + virtual ~ossimThreeParamDatum(){} + + /*! + * Will shift a ground point to this datum. If they are the same + * datum then nothing happens. + */ + virtual ossimGpt shift(const ossimGpt &aPt)const; + + virtual ossimGpt shiftToWgs84(const ossimGpt &aPt)const; + virtual ossimGpt shiftFromWgs84(const ossimGpt &aPt)const; + virtual ossim_float64 param1()const{return theParam1;} + virtual ossim_float64 param2()const{return theParam2;} + virtual ossim_float64 param3()const{return theParam3;} + virtual ossim_float64 param4()const{return 0.0;} + virtual ossim_float64 param5()const{return 0.0;} + virtual ossim_float64 param6()const{return 0.0;} + virtual ossim_float64 param7()const{return 1.0;} + +protected: + + ossim_float64 theParam1; + ossim_float64 theParam2; + ossim_float64 theParam3; +}; + + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimWgs72Datum.cpp b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimWgs72Datum.cpp new file mode 100644 index 0000000000..c202dd6fc2 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimWgs72Datum.cpp @@ -0,0 +1,223 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Wgs72Datum. Special hardcoded datum. It will create a static +// instance of a Wgs72Ellipsoid and set the initial defaults for +// that are specific to a Wgs72Datum +//******************************************************************* +// $Id: ossimWgs72Datum.cpp,v 1.8 2004/04/02 21:17:00 gpotts Exp $ + +#include <iostream> +using namespace std; +#include <base/data_types/datum/ossimWgs72Datum.h> + +#include <base/common/ossimConstants.h> +#include <base/factory/ossimDatumFactory.h> +#include <base/factory/ossimEllipsoidFactory.h> +#include <base/data_types/ellipse/ossimEllipsoid.h> +#include <base/data_types/ossimGpt.h> +#include <base/context/ossimNotifyContext.h> + +/***************************************************************************/ +/* + * DEFINES FROM GEOTRANS + */ + + +ossimWgs72Datum::ossimWgs72Datum() + :ossimThreeParamDatum("WGD", + "World Geodetic System 1972", + ossimEllipsoidFactory::instance()->wgs72(), + 0.0, + 0.0, + 0.0, + -M_PI/2.0, + M_PI/2.0, + -M_PI, + M_PI, + 0.0, + 0.0, + 0.0) +{ + if(!ellipsoid()) + { + //ERROR + } +} + +ossimGpt ossimWgs72Datum::shift(const ossimGpt &aPt)const +{ + const ossimDatum *aDatum = aPt.datum(); + + if( (ellipsoid()->getA()== aPt.datum()->ellipsoid()->getA())&& + (ellipsoid()->getB()== aPt.datum()->ellipsoid()->getB())) + { + return ossimGpt(aPt.latd(), aPt.lond(), aPt.height(), this); + } + + if(aDatum) + { + return shiftFromWgs84(aDatum->shiftToWgs84(aPt)); + } + + return aPt; +} + +ossimGpt ossimWgs72Datum::shiftToWgs84(const ossimGpt &aPt)const +{ +/* Begin Geodetic_Shift_WGS72_To_WGS84 */ + /* + * This function shifts a geodetic coordinate (latitude, longitude in radians + * and height in meters) relative to WGS72 to a geodetic coordinate + * (latitude, longitude in radians and height in meters) relative to WGS84. + * + * WGS72_Lat : Latitude in radians relative to WGS72 (input) + * WGS72_Lon : Longitude in radians relative to WGS72 (input) + * WGS72_Hgt : Height in meters relative to WGS72 (input) + * WGS84_Lat : Latitude in radians relative to WGS84 (output) + * WGS84_Lon : Longitude in radians relative to WGS84 (output) + * WGS84_Hgt : Height in meters relative to WGS84 (output) + */ + double Delta_Lat; + double Delta_Lon; + double Delta_Hgt; + double WGS84_a; /* Semi-major axis of WGS84 ellipsoid */ + double WGS84_f; /* Flattening of WGS84 ellipsoid */ + double WGS72_a; /* Semi-major axis of WGS72 ellipsoid */ + double WGS72_f; /* Flattening of WGS72 ellipsoid */ + double da; /* WGS84_a - WGS72_a */ + double df; /* WGS84_f - WGS72_f */ + double Q; + double sin_Lat; + double sin2_Lat; + + const ossimDatum *wgs84 = ossimDatumFactory::instance()->wgs84(); + const ossimDatum *wgs72 = ossimDatumFactory::instance()->wgs72(); + const ossimEllipsoid *wgs84Ellipsoid = ossimEllipsoidFactory::instance()->wgs84(); + const ossimEllipsoid *wgs72Ellipsoid = ossimEllipsoidFactory::instance()->wgs72(); + + if(!wgs84 || !wgs72 || !wgs72Ellipsoid || !wgs84Ellipsoid) + { + ossimNotify(ossimNotifyLevel_WARN) << "ossimWgs72Datum::shiftToWgs84, NULL pointer found and no shift will be performed\n"; + return (aPt); + } + + WGS84_a = wgs84Ellipsoid->a(); + WGS84_f = wgs84Ellipsoid->flattening(); + WGS72_a = wgs72Ellipsoid->a(); + WGS72_f = wgs72Ellipsoid->flattening(); + da = WGS84_a - WGS72_a; + df = WGS84_f - WGS72_f; + Q = M_PI / 648000; + sin_Lat = sin(aPt.latr()); + sin2_Lat = sin_Lat * sin_Lat; + + Delta_Lat = (4.5 * cos(aPt.latr())) / (WGS72_a*Q) + (df * sin(2*aPt.latr())) / Q; + Delta_Lat /= SEC_PER_RAD; + Delta_Lon = 0.554 / SEC_PER_RAD; + Delta_Hgt = 4.5 * sin_Lat + WGS72_a * df * sin2_Lat - da + 1.4; + + if(aPt.isHgtNan()) + { + return ossimGpt(aPt.latd() + Delta_Lat*DEG_PER_RAD, + aPt.lond() + Delta_Lon*DEG_PER_RAD, + Delta_Hgt, + wgs84); + } + return ossimGpt(aPt.latd() + Delta_Lat*DEG_PER_RAD, + aPt.lond() + Delta_Lon*DEG_PER_RAD, + aPt.height() + Delta_Hgt, + wgs84); + /* End Geodetic_Shift_WGS72_To_WGS84 */ +} + +ossimGpt ossimWgs72Datum::shiftFromWgs84(const ossimGpt &aPt)const +{ + /* Begin Geodetic_Shift_WGS84_To_WGS72 */ + /* + * This function shifts a geodetic coordinate (latitude, longitude in radians + * and height in meters) relative to WGS84 to a geodetic coordinate + * (latitude, longitude in radians and height in meters) relative to WGS72. + * + * WGS84_Lat : Latitude in radians relative to WGS84 (input) + * WGS84_Lon : Longitude in radians relative to WGS84 (input) + * WGS84_Hgt : Height in meters relative to WGS84 (input) + * WGS72_Lat : Latitude in radians relative to WGS72 (output) + * WGS72_Lon : Longitude in radians relative to WGS72 (output) + * WGS72_Hgt : Height in meters relative to WGS72 (output) + */ + double Delta_Lat; + double Delta_Lon; + double Delta_Hgt; + double WGS84_a; /* Semi-major axis of WGS84 ellipsoid */ + double WGS84_f; /* Flattening of WGS84 ellipsoid */ + double WGS72_a; /* Semi-major axis of WGS72 ellipsoid */ + double WGS72_b; /* Semi-minor axis of WGS72 ellipsoid */ + double WGS72_f; /* Flattening of WGS72 ellipsoid */ + double da; /* WGS72_a - WGS84_a */ + double df; /* WGS72_f - WGS84_f */ + double Q; + double sin_Lat; + double sin2_Lat; + const ossimDatum *wgs84 = ossimDatumFactory::instance()->wgs84(); + const ossimDatum *wgs72 = ossimDatumFactory::instance()->wgs72(); + const ossimEllipsoid *wgs84Ellipsoid = ossimEllipsoidFactory::instance()->wgs84(); + const ossimEllipsoid *wgs72Ellipsoid = ossimEllipsoidFactory::instance()->wgs72(); + + if(!wgs84 || !wgs72 || !wgs72Ellipsoid || !wgs84Ellipsoid) + { + ossimNotify(ossimNotifyLevel_WARN) << "ossimWgs72Datum::shiftFromWgs84, NULL pointer found and no shift will be performed\n"; + + return (aPt); + } + + WGS84_a = wgs84Ellipsoid->a(); + WGS84_f = wgs84Ellipsoid->flattening(); + WGS72_a = wgs72Ellipsoid->a(); + WGS72_b = wgs72Ellipsoid->b(); + WGS72_f = wgs72Ellipsoid->flattening(); + + da = WGS72_a - WGS84_a; + df = WGS72_f - WGS84_f; + Q = M_PI / 648000; + sin_Lat = sin(aPt.latr()); + sin2_Lat = sin_Lat * sin_Lat; + + Delta_Lat = (-4.5 * cos(aPt.latr())) / (WGS84_a*Q) + + (df * sin(2*aPt.latr())) / Q; + Delta_Lat /= SEC_PER_RAD; + Delta_Lon = -0.554 / SEC_PER_RAD; + Delta_Hgt = -4.5 * sin_Lat + WGS84_a * df * sin2_Lat - da - 1.4; + + if(aPt.isHgtNan()) + { + + return ossimGpt(aPt.latd() + Delta_Lat*DEG_PER_RAD, + aPt.lond() + Delta_Lon*DEG_PER_RAD, + Delta_Hgt, + this); + } + return ossimGpt(aPt.latd() + Delta_Lat*DEG_PER_RAD, + aPt.lond() + Delta_Lon*DEG_PER_RAD, + aPt.height() + Delta_Hgt, + this); +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimWgs72Datum.h b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimWgs72Datum.h new file mode 100644 index 0000000000..825fdb45e7 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimWgs72Datum.h @@ -0,0 +1,45 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Wgs72Datum. Special hardcoded datum. It will create a static +// instance of a Wgs72Ellipsoid and set the initial defaults for +// that are specific to a Wgs72Datum +//******************************************************************* +// $ID$ +#ifndef ossimWgs72Datum_HEADER +#define ossimWgs72Datum_HEADER +#include "ossimThreeParamDatum.h" + +class OSSIMDLLEXPORT ossimWgs72Datum : public ossimThreeParamDatum +{ +public: + ossimWgs72Datum(); + + virtual ~ossimWgs72Datum(){} + virtual ossimGpt shift(const ossimGpt &aPt)const; + virtual ossimGpt shiftToWgs84(const ossimGpt &aPt)const; + virtual ossimGpt shiftFromWgs84(const ossimGpt &aPt)const; + + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimWgs84Datum.cpp b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimWgs84Datum.cpp new file mode 100644 index 0000000000..d47a802e24 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimWgs84Datum.cpp @@ -0,0 +1,79 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Wgs84Datum. Special hardcoded datum. It will create a static +// instance of a Wgs84Ellipsoid and set the initial defaults for +// that are specific to a Wgs84Datum +//******************************************************************* +// $Id: ossimWgs84Datum.cpp,v 1.5 2001/10/26 19:41:17 gpotts Exp $ + +#include "ossimWgs84Datum.h" +#include "base/common/ossimConstants.h" +#include "base/factory/ossimEllipsoidFactory.h" +#include "base/data_types/ellipse/ossimEllipsoid.h" + + + +ossimWgs84Datum::ossimWgs84Datum() + :ossimThreeParamDatum("WGE", + "World Geodetic System 1984", + ossimEllipsoidFactory::instance()->wgs84(), + 0.0, 0.0, 0.0, + -M_PI/2.0, M_PI/2.0, -M_PI, M_PI, + 0.0, 0.0, 0.0) +{ + if(!ellipsoid()) + { + //ERROR + } +} + + +ossimGpt ossimWgs84Datum::shift(const ossimGpt &aPt)const +{ + const ossimDatum *aDatum = aPt.datum(); + + if( aPt.datum()->code() == code()) + { + return ossimGpt(aPt.latd(), aPt.lond(), aPt.height(), this); + } + + if(aDatum) + { + return aDatum->shiftToWgs84(aPt); + } + + return aPt; +} + +ossimGpt ossimWgs84Datum::shiftToWgs84(const ossimGpt &aPt)const +{ + return ossimGpt(aPt.latd(), + aPt.lond(), + aPt.height(), + ossimDatumFactory::instance()->wgs84()); +} + +ossimGpt ossimWgs84Datum::shiftFromWgs84(const ossimGpt &aPt)const +{ + return aPt; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimWgs84Datum.h b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimWgs84Datum.h new file mode 100644 index 0000000000..115790d329 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/datum/ossimWgs84Datum.h @@ -0,0 +1,48 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// ossimWgs84Datum. Special hardcoded datum. It will create a static +// instance of a Wgs84Ellipsoid and set the initial defaults for +// that are specific to a ossimWgs84Datum +//******************************************************************* +// $Id: ossimWgs84Datum.h,v 1.4 2002/09/01 19:06:34 gpotts Exp $ + +#ifndef ossimWgs84Datum_HEADER +#define ossimWgs84Datum_HEADER +#include "ossimThreeParamDatum.h" + +class OSSIMDLLEXPORT ossimWgs84Datum : public ossimThreeParamDatum +{ +public: + ossimWgs84Datum(); + virtual ~ossimWgs84Datum(){} + + virtual ossimGpt shift(const ossimGpt &aPt)const; + + virtual ossimGpt shiftToWgs84(const ossimGpt &aPt)const; + virtual ossimGpt shiftFromWgs84(const ossimGpt&aPt)const; + +protected: + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ellipse/.cvsignore b/Utilities/OSSIM/ossim_core/base/data_types/ellipse/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ellipse/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ellipse/ellips.dat b/Utilities/OSSIM/ossim_core/base/data_types/ellipse/ellips.dat new file mode 100644 index 0000000000..ab74751f7a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ellipse/ellips.dat @@ -0,0 +1,23 @@ +Airy AA 6377563.396 6356256.9090 299.324964600 +Modified Airy AM 6377340.189 6356034.4480 299.324964600 +Australian National AN 6378160.000 6356774.7190 298.250000000 +Bessel 1841 BR 6377397.155 6356078.9630 299.152812800 +Bessel 1841(Namibia) BN 6377483.865 6356165.3830 299.152812800 +Clarke 1866 CC 6378206.400 6356583.8000 294.978698200 +Clarke 1880 CD 6378249.145 6356514.8700 293.465000000 +Everest EA 6377276.345 6356075.4130 300.801700000 +Everest (E. Malasia, Brunei) EB 6377298.556 6356097.5500 300.801700000 +Everest 1956 (India) EC 6377301.243 6356100.2280 300.801700000 +Everest 1969 (West Malasia) ED 6377295.664 6356094.6680 300.801700000 +Everest 1948(W.Mals. & Sing.) EE 6377304.063 6356103.0390 300.801700000 +Everest (Pakistan) EF 6377309.613 6356109.5710 300.801700000 +Mod. Fischer 1960(South Asia) FA 6378155.000 6356773.3200 298.300000000 +GRS 80 RF 6378137.000 6356752.3141 298.257222101 +Helmert 1906 HE 6378200.000 6356818.1700 298.300000000 +Hough HO 6378270.000 6356794.3430 297.000000000 +Indonesian 1974 ID 6378160.000 6356774.5040 298.247000000 +International IN 6378388.000 6356911.9460 297.000000000 +Krassovsky KA 6378245.000 6356863.0190 298.300000000 +South American 1969 SA 6378160.000 6356774.7190 298.250000000 +WGS 72 WD 6378135.000 6356750.5200 298.260000000 +WGS 84 WE 6378137.000 6356752.3142 298.257223563 diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ellipse/ossimEllipse.c b/Utilities/OSSIM/ossim_core/base/data_types/ellipse/ossimEllipse.c new file mode 100644 index 0000000000..db2f89fb31 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ellipse/ossimEllipse.c @@ -0,0 +1,663 @@ +/****************************************************************************/ +/* RSC IDENTIFIER: Ellipsoid + * +* ABSTRACT + * + * The purpose of ELLIPSOID is to provide access to ellipsoid parameters + * for a collection of common ellipsoids. A particular ellipsoid can be + * accessed by using its standard 2-letter code to find its index in the + * ellipsoid table. The index can then be used to retrieve the ellipsoid + * name and parameters. + * + * By sequentially retrieving all of the ellipsoid codes and/or names, a + * menu of the available ellipsoids can be constructed. The index values + * resulting from selections from this menu can then be used to access the + * parameters of the selected ellipsoid. + * + * This component depends on a data file named "ellips.dat", which contains + * the ellipsoid parameter values. A copy of this file must be located in + * the directory specified by the environment variable "ELLIPSOID_DATA", if + * defined, or else in the current directory, whenever a program containing + * this component is executed. + * + * Additional ellipsoids can be added to this file, either manually or using + * the Create_Ellipsoid function. However, if a large number of ellipsoids + * are added, the ellipsoid table array size in this component will have to + * be increased. + * + * ERROR HANDLING + * + * This component checks parameters for valid values. If an invalid value + * is found, the error code is combined with the current error code using + * the bitwise or. This combining allows multiple error codes to be + * returned. The possible error codes are: + * + * ELLIPSE_NO_ERROR : No errors occured in function + * ELLIPSE_FILE_OPEN_ERROR : Ellipsoid file opening error + * ELLIPSE_INITIALIZE_ERROR : Ellipsoid table can not initialize + * ELLIPSE_TABLE_OVERFLOW_ERROR : Ellipsoid table overflow + * ELLIPSE_NOT_INITIALIZED_ERROR: Ellipsoid table not initialized properly + * ELLIPSE_INVALID_INDEX_ERROR : Index is an invalid value + * ELLIPSE_INVALID_CODE_ERROR : Code was not found in table + * ELLIPSE_A_ERROR : Semi-major axis less than or equal to zero + * ELLIPSE_B_ERROR : Semi-minor axis less than or equal to zero + * ELLIPSE_A_LESS_B_ERROR : Semi-major axis less than semi-minor axis + * + * REUSE NOTES + * + * Ellipsoid is intended for reuse by any application that requires Earth + * approximating ellipsoids. + * + * REFERENCES + * + * Further information on Ellipsoid can be found in the Reuse Manual. + * + * Ellipsoid originated from : U.S. Army Topographic Engineering Center (USATEC) + * Geospatial Information Division (GID) + * 7701 Telegraph Road + * Alexandria, VA 22310-3864 + * + * LICENSES + * + * None apply to this component. + * + * RESTRICTIONS + * + * Ellipsoid has no restrictions. + * + * ENVIRONMENT + * + * Ellipsoid was tested and certified in the following environments + * + * 1. Solaris 2.5 + * 2. Windows 95 + * + * MODIFICATIONS + * + * Date Description + * ---- ----------- + * 11-19-95 Original Code + * 17-Jan-97 Moved local constants out of public interface + * Improved efficiency in algorithms (GEOTRANS) + * 24-May-99 Added user-defined ellipsoids (GEOTRANS for JMTK) + * + */ + + +/***************************************************************************/ +/* + * INCLUDES + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include "ossimEllipse.h" + +/* + * ctype.h - standard C character handling library + * stdio.h - standard C input/output library + * stdlib.h - standard C general utilities library + * string.h - standard C string handling library + * ellipse.h - prototype error checking and error codes + */ + + +/***************************************************************************/ +/* + * GLOBAL DATA STRUCTURES + */ + +#define MAX_ELLIPSOIDS 32 /* Maximum number of ellipsoids in table */ +#define ELLIPSOID_CODE_LENGTH 3 /* Length of ellipsoid code (including null) */ +#define ELLIPSOID_NAME_LENGTH 30 /* Max length of ellipsoid name */ +#define ELLIPSOID_BUF 90 +#define FILENAME_LENGTH 128 + +const char *WGS84_Ellipsoid_Code = "WE"; +const char *WGS72_Ellipsoid_Code = "WD"; + +typedef struct Ellipsoid_Table_Row +{ + char Name[ELLIPSOID_NAME_LENGTH]; + char Code[ELLIPSOID_CODE_LENGTH]; + double A; + double B; + double Recp_F; +} Ellipsoid_Row; + +#include "ossimEllipse.hpp" + +static long WGS84_Index = 0; /* Index of WGS84 in ellipsoid table */ +static long WGS72_Index = 0; /* Index of WGS72 in ellipsoid table */ +static long Ellipsoid_Initialized = 0; /* Indicates successful initialization */ + +/***************************************************************************/ +/* FUNCTIONS */ + + +void Assign_Ellipsoid_Row (Ellipsoid_Row *destination, + const Ellipsoid_Row *source) +{ + /* Begin Assign_Ellipsoid_Row */ + /* + * destination : The destination of the copy (output) + * source : The source for the copy (input) + * + * The function Assign_Ellipsoid_Row copies ellipsoid data. + */ + + strcpy(destination->Name, source->Name); + strcpy(destination->Code, source->Code); + destination->A = source->A; + destination->B = source->B; + destination->Recp_F = source->Recp_F; +} /* End Assign_Ellipsoid_Row */ + + +long Initialize_Ellipsoids () +{ + /* Begin Initialize_Ellipsoids */ + /* + * The function Initialize_Ellipsoids reads ellipsoid data from ellips.dat + * in the current directory and builds the ellipsoid table from it. If an + * error occurs, the error code is returned, otherwise ELLIPSE_NO_ERROR is + * returned. + */ + long error_code = ELLIPSE_NO_ERROR; + + if (error_code) + { + Ellipsoid_Initialized = 0; + Number_of_Ellipsoids = 0; + } + else + Ellipsoid_Initialized = 1; + + /* Store WGS84 Index*/ + if (Ellipsoid_Index(WGS84_Ellipsoid_Code, &WGS84_Index)) + error_code |= ELLIPSE_INITIALIZE_ERROR; + + /* Store WGS72 Index*/ + if (Ellipsoid_Index(WGS72_Ellipsoid_Code, &WGS72_Index)) + error_code |= ELLIPSE_INITIALIZE_ERROR; + + return (error_code); +} /* End of Initialize_Ellipsoids */ + + +long Create_Ellipsoid (const char* Code, + const char* Name, + double A, + double B) +{ /* Begin Create_Ellipsoid */ +/* + * Code : 2-letter ellipsoid code. (input) + * Name : Name of the new ellipsoid (input) + * A : Semi-major axis, in meters, of new ellipsoid (input) + * B : Semi-minor axis, in meters, of new ellipsoid. (input) + * + * The function Create_Ellipsoid creates a new ellipsoid with the specified + * Code, name, and axes. If the ellipsoid table has not been initialized, + * the specified code is already in use, or a new version of the ellips.dat + * file cannot be created, an error code is returned, otherwise ELLIPSE_NO_ERROR + * is returned. Note that the indexes of all ellipsoids in the ellipsoid + * table may be changed by this function. + */ + + long error_code = ELLIPSE_NO_ERROR; + long index = 0; + char *PathName; + char FileName[FILENAME_LENGTH]; + FILE *fp = NULL; /* File pointer to file ellips.dat */ + + if (!Ellipsoid_Initialized) + error_code |= ELLIPSE_NOT_INITIALIZED_ERROR; + else if (!(Number_of_Ellipsoids < MAX_ELLIPSOIDS)) + error_code |= ELLIPSE_TABLE_OVERFLOW_ERROR; + else + { + if (!Ellipsoid_Index(Code, &index)) + error_code |= ELLIPSE_INVALID_CODE_ERROR; + if (A <= 0.0) + error_code |= ELLIPSE_A_ERROR; + if (B <= 0.0) + error_code |= ELLIPSE_B_ERROR; + if (A < B) + error_code |= ELLIPSE_A_LESS_B_ERROR; + if (!error_code) + { + index = Number_of_Ellipsoids; + strcpy(Ellipsoid_Table[index].Name, Name); + strcpy(Ellipsoid_Table[index].Code, Code); + Ellipsoid_Table[index].A = A; + Ellipsoid_Table[index].B = B; + Ellipsoid_Table[index].Recp_F = A / (A - B); + Number_of_Ellipsoids++; + + /*output updated ellipsoid table*/ + PathName = getenv( "ELLIPSOID_DATA" ); + if (PathName != NULL) + { + strcpy( FileName, PathName ); + strcat( FileName, "/" ); + } + else + { + strcpy( FileName, "./" ); + } + strcat( FileName, "ellips.dat" ); + + if ((fp = fopen(FileName, "w")) == NULL) + { /* fatal error */ + return ELLIPSE_FILE_OPEN_ERROR; + } + + /* write file */ + index = 0; + while (index < Number_of_Ellipsoids) + { + fprintf(fp, "%-29s %-2s %11.3f %12.4f %13.9f \n", + Ellipsoid_Table[index].Name, + Ellipsoid_Table[index].Code, + Ellipsoid_Table[index].A, + Ellipsoid_Table[index].B, + Ellipsoid_Table[index].Recp_F); + index++; + } + fclose(fp); + + /* Store WGS84 */ + Ellipsoid_Index(WGS84_Ellipsoid_Code, &WGS84_Index); + + /* Store WGS72 */ + Ellipsoid_Index(WGS72_Ellipsoid_Code, &WGS72_Index); + } + } + return (error_code); +} /* End Create_Ellipsoid */ + + +long Ellipsoid_Count ( long *Count ) +{ /* Begin Ellipsoid_Count */ +/* + * Count : The number of ellipsoids in the ellipsoid table. (output) + * + * The function Ellipsoid_Count returns the number of ellipsoids in the + * ellipsoid table. If the ellipsoid table has been initialized without error, + * ELLIPSE_NO_ERROR is returned, otherwise ELLIPSE_NOT_INITIALIZED_ERROR + * is returned. + */ + + long error_code = ELLIPSE_NO_ERROR; + + if (!Ellipsoid_Initialized) + error_code |= ELLIPSE_NOT_INITIALIZED_ERROR; + *Count = Number_of_Ellipsoids; + return (error_code); +} /* End Ellipsoid_Count */ + + +long Ellipsoid_Index ( const char *Code, + long *Index ) +{ /* Begin Ellipsoid_Index */ +/* + * Code : 2-letter ellipsoid code. (input) + * Index : Index of the ellipsoid in the ellipsoid table with the + * specified code (output) + * + * The function Ellipsoid_Index returns the index of the ellipsoid in + * the ellipsoid table with the specified code. If ellipsoid_Code is found, + * ELLIPSE_NO_ERROR is returned, otherwise ELLIPSE_INVALID_CODE_ERROR is + * returned. + */ + + char temp_code[3]; + long error_code = ELLIPSE_NO_ERROR; + long i = 0; /* index for ellipsoid table */ + long j = 0; + + *Index = 0; + if (Ellipsoid_Initialized) + { + while (j < ELLIPSOID_CODE_LENGTH) + { + temp_code[j] = toupper(Code[j]); + j++; + } + temp_code[ELLIPSOID_CODE_LENGTH - 1] = 0; + while ((i < Number_of_Ellipsoids) + && strcmp(temp_code, Ellipsoid_Table[i].Code)) + { + i++; + } + if (strcmp(temp_code, Ellipsoid_Table[i].Code)) + error_code |= ELLIPSE_INVALID_CODE_ERROR; + else + *Index = i+1; + } + else + { + error_code |= ELLIPSE_NOT_INITIALIZED_ERROR; + } + return (error_code); +} /* End Ellipsoid_Index */ + + +long Ellipsoid_Name ( const long Index, + char *Name ) +{ /* Begin Ellipsoid_Name */ +/* + * Index : Index of a given ellipsoid.in the ellipsoid table with the + * specified index (input) + * Name : Name of the ellipsoid referencd by index (output) + * + * The Function Ellipsoid_Name returns the name of the ellipsoid in + * the ellipsoid table with the specified index. If index is valid, + * ELLIPSE_NO_ERROR is returned, otherwise ELLIPSE_INVALID_INDEX_ERROR is + * returned. + */ + + long error_code = ELLIPSE_NO_ERROR; + + strcpy(Name,""); + if (Ellipsoid_Initialized) + { + if ((Index < 1) || (Index > Number_of_Ellipsoids)) + error_code |= ELLIPSE_INVALID_INDEX_ERROR; + else + strcpy(Name, Ellipsoid_Table[Index-1].Name); + } + else + error_code |= ELLIPSE_NOT_INITIALIZED_ERROR; + return (error_code); +} /* End Ellipsoid_Name */ + + +long Ellipsoid_Code ( const long Index, + char *Code ) +{ /* Begin Ellipsoid_Code */ +/* + * Index : Index of a given ellipsoid in the ellipsoid table (input) + * Code : 2-letter ellipsoid code. (output) + * + * The Function Ellipsoid_Code returns the 2-letter code for the + * ellipsoid in the ellipsoid table with the specified index. If index is + * valid, ELLIPSE_NO_ERROR is returned, otherwise ELLIPSE_INVALID_INDEX_ERROR + * is returned. + */ + + long error_code = ELLIPSE_NO_ERROR; + + strcpy(Code,""); + if (Ellipsoid_Initialized) + { + if ((Index < 1) || (Index > Number_of_Ellipsoids)) + error_code |= ELLIPSE_INVALID_INDEX_ERROR; + else + strcpy(Code, Ellipsoid_Table[Index-1].Code); + } + else + error_code |= ELLIPSE_NOT_INITIALIZED_ERROR; + return (error_code); +} /* End Ellipsoid_Name */ + + +long Ellipsoid_Axes ( const long Index, + double *A, + double *B ) +{ /* Begin Ellipsoid_Axes */ +/* + * Index : Index of a given ellipsoid in the ellipsoid table (input) + * a : Semi-major axis, in meters, of ellipsoid (output) + * B : Semi-minor axis, in meters, of ellipsoid. (output) + * + * The function Ellipsoid_Axes returns the semi-major and semi-minor axes + * for the ellipsoid with the specified index. If index is valid, + * ELLIPSE_NO_ERROR is returned, otherwise ELLIPSE_INVALID_INDEX_ERROR is + * returned. + */ + + long error_code = ELLIPSE_NO_ERROR; + + *A = 0; + *B = 0; + if (Ellipsoid_Initialized) + { + if ((Index < 1) || (Index > Number_of_Ellipsoids)) + { + error_code |= ELLIPSE_INVALID_INDEX_ERROR; + } + else + { + *A = Ellipsoid_Table[Index-1].A; + *B = Ellipsoid_Table[Index-1].B; + } + } + else + error_code |= ELLIPSE_NOT_INITIALIZED_ERROR; + return (error_code); +} /* End Ellipsoid_Axes */ + + +long Ellipsoid_Eccentricity2 ( const long Index, + double *e2 ) +{ /* Begin Ellipsoid_Eccentricity2 */ +/* + * Index : Index of a given ellipsoid in the ellipsoid table (input) + * e2 : Square of eccentricity of ellipsoid (output) + * + * The function Ellipsoid_Eccentricity2 returns the square of the + * eccentricity for the ellipsoid with the specified index. If index is + * valid, ELLIPSE_NO_ERROR is returned, otherwise ELLIPSE_INVALID_INDEX_ERROR + * is returned. + */ + double a2,b2; + long error_code = ELLIPSE_NO_ERROR; + + *e2 = 0; + if (Ellipsoid_Initialized) + { + if ((Index < 1) || (Index > Number_of_Ellipsoids)) + { + error_code |= ELLIPSE_INVALID_INDEX_ERROR; + } + else + { + a2 = Ellipsoid_Table[Index-1].A * Ellipsoid_Table[Index-1].A; + b2 = Ellipsoid_Table[Index-1].B * Ellipsoid_Table[Index-1].B; + *e2 = (a2 - b2) / a2; + } + } + else + error_code |= ELLIPSE_NOT_INITIALIZED_ERROR; + return (error_code); +} /* End Ellipsoid_Eccentricity2 */ + + +long Ellipsoid_Flattening ( const long Index, + double *f ) +{ /* Begin Ellipsoid_Flattening */ +/* + * Index : Index of a given ellipsoid in the ellipsoid table (input) + * f : Flattening of ellipsoid. (output) + * + * The function Ellipsoid_Flattening returns the flattening of the + * ellipsoid with the specified index. If index is valid ELLIPSE_NO_ERROR is + * returned, otherwise ELLIPSE_INVALID_INDEX_ERROR is returned. + */ + + long error_code = ELLIPSE_NO_ERROR; + + *f = 0; + if (Ellipsoid_Initialized) + { + if ((Index < 1) || (Index > Number_of_Ellipsoids)) + error_code |= ELLIPSE_INVALID_INDEX_ERROR; + else + *f = 1 / Ellipsoid_Table[Index-1].Recp_F; + } + else + error_code |= ELLIPSE_NOT_INITIALIZED_ERROR; + return (error_code); +} /* End Ellipsoid_Flattening */ + + +long WGS84_Axes ( double *A, + double *B) +{ /* Begin WGS84_Axes */ +/* + * A : Semi-major axis, in meters, of ellipsoid (output) + * B : Semi-minor axis, in meters, of ellipsoid (output) + * + * The function WGS84_Axes returns the lengths of the semi-major and + * semi-minor axes for the WGS84 ellipsoid. If the ellipsoid table was + * initialized successfully, ELLIPSE_NO_ERROR is returned, otherwise + * ELLIPSE_NOT_INITIALIZED_ERROR is returned. + */ + + long error_code = ELLIPSE_NO_ERROR; + + *A = 0; + *B = 0; + if (Ellipsoid_Initialized) + { + *A = Ellipsoid_Table[WGS84_Index-1].A; + *B = Ellipsoid_Table[WGS84_Index-1].B; + } + else + error_code |= ELLIPSE_NOT_INITIALIZED_ERROR; + return (error_code); +} /* End WGS84_Axes */ + + +long WGS84_Eccentricity2 ( double *e2 ) +{ /* Begin WGS84_Eccentricity2 */ +/* + * e2 : Square of eccentricity of WGS84 ellipsoid (output) + * + * The function WGS84_Eccentricity2 returns the square of the + * eccentricity for the WGS84 ellipsoid. If the ellipsoid table was + * initialized successfully, ELLIPSE_NO_ERROR is returned, otherwise + * ELLIPSE_NOT_INITIALIZED_ERROR is returned. + */ + + long error_code = ELLIPSE_NO_ERROR; + double a2, b2; + + *e2 = 0; + if (Ellipsoid_Initialized) + { + a2 = Ellipsoid_Table[WGS84_Index-1].A * Ellipsoid_Table[WGS84_Index-1].A; + b2 = Ellipsoid_Table[WGS84_Index-1].B * Ellipsoid_Table[WGS84_Index-1].B; + *e2 = (a2 - b2) / a2; + } + else + error_code |= ELLIPSE_NOT_INITIALIZED_ERROR; + return (error_code); +} /* End WGS84_Eccentricity2 */ + + +long WGS84_Flattening ( double *f ) +{ /* Begin WGS84_Flattening */ +/* + * f : Flattening of WGS84 ellipsoid. (output) + * + * The function WGS84_Flattening returns the flattening of the WGS84 + * ellipsoid. If the ellipsoid table was initialized successfully, + * ELLIPSE_NO_ERROR is returned, otherwise ELLIPSE_NOT_INITIALIZED_ERROR + * is returned. + */ + + long error_code = ELLIPSE_NO_ERROR; + + *f = 0; + if (Ellipsoid_Initialized) + { + *f = 1 / Ellipsoid_Table[WGS84_Index-1].Recp_F; + } + else + error_code |= ELLIPSE_NOT_INITIALIZED_ERROR; + return (error_code); +} /* End WGS84_Flattening */ + + +long WGS72_Axes( double *A, + double *B) +{ /* Begin WGS72_Axes */ +/* + * A : Semi-major axis, in meters, of ellipsoid (output) + * B : Semi-minor axis, in meters, of ellipsoid (output) + * + * The function WGS72_Axes returns the lengths of the semi-major and + * semi-minor axes for the WGS72 ellipsoid. If the ellipsoid table was + * initialized successfully, ELLIPSE_NO_ERROR is returned, otherwise + * ELLIPSE_NOT_INITIALIZED_ERROR is returned. + */ + + long error_code = ELLIPSE_NO_ERROR; + + *A = 0; + *B = 0; + if (Ellipsoid_Initialized) + { + *A = Ellipsoid_Table[WGS72_Index-1].A; + *B = Ellipsoid_Table[WGS72_Index-1].B; + } + else + error_code |= ELLIPSE_NOT_INITIALIZED_ERROR; + return (error_code); +} /* End WGS72_Axes */ + + +long WGS72_Eccentricity2 ( double *e2 ) +{ /* Begin WGS72_Eccentricity2 */ +/* + * e2 : Square of eccentricity of WGS84 ellipsoid (output) + * + * The function WGS72_Eccentricity2 returns the square of the + * eccentricity for the WGS72 ellipsoid. If the ellipsoid table was + * initialized successfully, ELLIPSE_NO_ERROR is returned, otherwise + * ELLIPSE_NOT_INITIALIZED_ERROR is returned. + */ + + long error_code = ELLIPSE_NO_ERROR; + double a2, b2; + + *e2 = 0; + if (Ellipsoid_Initialized) + { + a2 = Ellipsoid_Table[WGS72_Index-1].A * Ellipsoid_Table[WGS72_Index-1].A; + b2 = Ellipsoid_Table[WGS72_Index-1].B * Ellipsoid_Table[WGS72_Index-1].B; + *e2 = (a2 - b2) / a2; + } + else + error_code |= ELLIPSE_NOT_INITIALIZED_ERROR; + return (error_code); +} /* End WGS72_Eccentricity2 */ + + +long WGS72_Flattening (double *f ) +{ /* Begin WGS72_Flattening */ +/* + * f : Flattening of WGS72 ellipsoid. (output) + * + * The function WGS72_Flattening returns the flattening of the WGS72 + * ellipsoid . If the ellipsoid table was initialized successfully, + * ELLIPSE_NO_ERROR is returned, otherwise ELLIPSE_NOT_INITIALIZED_ERROR + * is returned. + */ + long error_code = ELLIPSE_NO_ERROR; + + *f = 0; + if (Ellipsoid_Initialized) + { + *f = 1 / Ellipsoid_Table[WGS72_Index-1].Recp_F; + } + else + error_code |= ELLIPSE_NOT_INITIALIZED_ERROR; + return (error_code); +} /* End WGS72_Flattening */ + + diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ellipse/ossimEllipse.h b/Utilities/OSSIM/ossim_core/base/data_types/ellipse/ossimEllipse.h new file mode 100644 index 0000000000..c68e42175b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ellipse/ossimEllipse.h @@ -0,0 +1,308 @@ +#ifndef ELLIPSE_H +#define ELLIPSE_H + +/****************************************************************************/ +/* RSC IDENTIFIER: Ellipsoid + * + * ABSTRACT + * + * The purpose of ELLIPSOID is to provide access to ellipsoid parameters + * for a collection of common ellipsoids. A particular ellipsoid can be + * accessed by using its standard 2-letter code to find its index in the + * ellipsoid table. The index can then be used to retrieve the ellipsoid + * name and parameters. + * + * By sequentially retrieving all of the ellipsoid codes and/or names, a + * menu of the available ellipsoids can be constructed. The index values + * resulting from selections from this menu can then be used to access the + * parameters of the selected ellipsoid. + * + * This component depends on a data file named "ellips.dat", which contains + * the ellipsoid parameter values. A copy of this file must be located in + * the directory specified by the environment variable "ELLIPSOID_DATA", if + * defined, or else in the current directory, whenever a program containing + * this component is executed. + * + * Additional ellipsoids can be added to this file, either manually or using + * the Create_Ellipsoid function. However, if a large number of ellipsoids + * are added, the ellipsoid table array size in this component will have to + * be increased. + * + * ERROR HANDLING + * + * This component checks parameters for valid values. If an invalid value + * is found, the error code is combined with the current error code using + * the bitwise or. This combining allows multiple error codes to be + * returned. The possible error codes are: + * + * ELLIPSE_NO_ERROR : No errors occured in function + * ELLIPSE_FILE_OPEN_ERROR : Ellipsoid file opening error + * ELLIPSE_INITIALIZE_ERROR : Ellipsoid database can not initialize + * ELLIPSE_TABLE_OVERFLOW_ERROR : Ellipsoid table overflow + * ELLIPSE_NOT_INITIALIZED_ERROR: Ellipsoid database not initialized properly + * ELLIPSE_INVALID_INDEX_ERROR : Index is an invalid value + * ELLIPSE_INVALID_CODE_ERROR : Code was not found in database + * ELLIPSE_A_ERROR : Semi-major axis less than or equal to zero + * ELLIPSE_B_ERROR : Semi-minor axis less than or equal to zero + * ELLIPSE_A_LESS_B_ERROR : Semi-major axis less than semi-minor axis + * + * REUSE NOTES + * + * Ellipsoid is intended for reuse by any application that requires Earth + * approximating ellipsoids. + * + * REFERENCES + * + * Further information on Ellipsoid can be found in the Reuse Manual. + * + * Ellipsoid originated from : U.S. Army Topographic Engineering Center (USATEC) + * Geospatial Information Division (GID) + * 7701 Telegraph Road + * Alexandria, VA 22310-3864 + * + * LICENSES + * + * None apply to this component. + * + * RESTRICTIONS + * + * Ellipsoid has no restrictions. + * + * ENVIRONMENT + * + * Ellipsoid was tested and certified in the following environments + * + * 1. Solaris 2.5 + * 2. Windows 95 + * + * MODIFICATIONS + * + * Date Description + * ---- ----------- + * 11-19-95 Original Code + * 17-Jan-97 Moved local constants out of public interface + * Improved efficiency in algorithms (GEOTRANS) + * 24-May-99 Added user-defined ellipsoids (GEOTRANS for JMTK) + * + */ + + +/***************************************************************************/ +/* + * GLOBALS + */ + +#define ELLIPSE_NO_ERROR 0x0000 +#define ELLIPSE_FILE_OPEN_ERROR 0x0001 +#define ELLIPSE_INITIALIZE_ERROR 0x0002 +#define ELLIPSE_TABLE_OVERFLOW_ERROR 0x0004 +#define ELLIPSE_NOT_INITIALIZED_ERROR 0x0008 +#define ELLIPSE_INVALID_INDEX_ERROR 0x0010 +#define ELLIPSE_INVALID_CODE_ERROR 0x0020 +#define ELLIPSE_A_ERROR 0x0040 +#define ELLIPSE_B_ERROR 0x0080 +#define ELLIPSE_A_LESS_B_ERROR 0x0100 + +/***************************************************************************/ +/* + * FUNCTION PROTOTYPES + * for ellipse.c + */ + +/* ensure proper linkage to c++ programs */ +#ifdef __cplusplus +extern "C" { +#endif + + long Initialize_Ellipsoids (); +/* + * The function Initialize_Ellipsoids reads ellipsoid data from ellips.dat in + * the current directory and builds the ellipsoid table from it. If an error + * occurs, the error code is returned, otherwise ELLIPSE_NO_ERROR is returned. + */ + + + long Create_Ellipsoid (const char* Code, + const char* Name, + double a, + double b); +/* + * Code : 2-letter ellipsoid code. (input) + * Name : Name of the new ellipsoid (input) + * a : Semi-major axis, in meters, of new ellipsoid (input) + * b : Semi-minor axis, in meters, of new ellipsoid. (input) + * + * The function Create_Ellipsoid creates a new ellipsoid with the specified + * code, name, and axes. If the ellipsoid table has not been initialized, + * the specified code is already in use, or a new version of the ellips.dat + * file cannot be created, an error code is returned, otherwise ELLIPSE_NO_ERROR + * is returned. Note that the indexes of all ellipsoids in the ellipsoid + * table may be changed by this function. + */ + + + long Ellipsoid_Count ( long *Count ); +/* + * Count : The number of ellipsoids in the ellipsoid table. (output) + * + * The function Ellipsoid_Count returns the number of ellipsoids in the + * ellipsoid table. If the ellipsoid table has been initialized without error, + * ELLIPSE_NO_ERROR is returned, otherwise ELLIPSE_NOT_INITIALIZED_ERROR + * is returned. + */ + + + long Ellipsoid_Index ( const char *Code, + long *Index ); +/* + * Code : 2-letter ellipsoid code. (input) + * Index : Index of the ellipsoid in the ellipsoid table with the + * specified code (output) + * + * The function Ellipsoid_Index returns the index of the ellipsoid in + * the ellipsoid table with the specified code. If ellipsoid_Code is found, + * ELLIPSE_NO_ERROR is returned, otherwise ELLIPSE_INVALID_CODE_ERROR is + * returned. + */ + + + long Ellipsoid_Name ( const long Index, + char *Name ); +/* + * Index : Index of a given ellipsoid.in the ellipsoid table with the + * specified index (input) + * Name : Name of the ellipsoid referencd by index (output) + * + * The Function Ellipsoid_Name returns the name of the ellipsoid in + * the ellipsoid table with the specified index. If index is valid, + * ELLIPSE_NO_ERROR is returned, otherwise ELLIPSE_INVALID_INDEX_ERROR is + * returned. + */ + + + long Ellipsoid_Code ( const long Index, + char *Code ); +/* + * Index : Index of a given ellipsoid in the ellipsoid table (input) + * Code : 2-letter ellipsoid code. (output) + * + * The Function Ellipsoid_Code returns the 2-letter code for the + * ellipsoid in the ellipsoid table with the specified index. If index is + * valid, ELLIPSE_NO_ERROR is returned, otherwise ELLIPSE_INVALID_INDEX_ERROR + * is returned. + */ + + + long Ellipsoid_Axes ( const long Index, + double *a, + double *b ); +/* + * Index : Index of a given ellipsoid in the ellipsoid table (input) + * a : Semi-major axis, in meters, of ellipsoid (output) + * b : Semi-minor axis, in meters, of ellipsoid. (output) + * + * The function Ellipsoid_Axes returns the semi-major and semi-minor axes + * for the ellipsoid with the specified index. If index is valid, + * ELLIPSE_NO_ERROR is returned, otherwise ELLIPSE_INVALID_INDEX_ERROR is + * returned. + */ + + + long Ellipsoid_Eccentricity2 ( const long Index, + double *e2 ); +/* + * Index : Index of a given ellipsoid in the ellipsoid table (input) + * e2 : Square of eccentricity of ellipsoid (output) + * + * The function Ellipsoid_Eccentricity2 returns the square of the + * eccentricity for the ellipsoid with the specified index. If index is + * valid, ELLIPSE_NO_ERROR is returned, otherwise ELLIPSE_INVALID_INDEX_ERROR + * is returned. + */ + + + long Ellipsoid_Flattening ( const long Index, + double *f ); +/* + * Index : Index of a given ellipsoid in the ellipsoid table (input) + * f : Flattening of ellipsoid. (output) + * + * The function Ellipsoid_Flattening returns the flattening of the + * ellipsoid with the specified index. If index is valid ELLIPSE_NO_ERROR is + * returned, otherwise ELLIPSE_INVALID_INDEX_ERROR is returned. + */ + + + long WGS84_Axes ( double *a, + double *b ); +/* + * a : Semi-major axis, in meters, of ellipsoid (output) + * b : Semi-minor axis, in meters, of ellipsoid (output) + * + * The function WGS84_Axes returns the lengths of the semi-major and + * semi-minor axes for the WGS84 ellipsoid. If the ellipsoid table was + * initialized successfully, ELLIPSE_NO_ERROR is returned, otherwise + * ELLIPSE_NOT_INITIALIZED_ERROR is returned. + */ + + + long WGS84_Eccentricity2 ( double *e2 ); +/* + * e2 : Square of eccentricity of WGS84 ellipsoid (output) + * + * The function WGS84_Eccentricity2 returns the square of the + * eccentricity for the WGS84 ellipsoid. If the ellipsoid table was + * initialized successfully, ELLIPSE_NO_ERROR is returned, otherwise + * ELLIPSE_NOT_INITIALIZED_ERROR is returned. + */ + + + long WGS84_Flattening ( double *f ); +/* + * f : Flattening of WGS84 ellipsoid. (output) + * + * The function WGS84_Flattening returns the flattening of the WGS84 + * ellipsoid. If the ellipsoid table was initialized successfully, + * ELLIPSE_NO_ERROR is returned, otherwise ELLIPSE_NOT_INITIALIZED_ERROR + * is returned. + */ + + long WGS72_Axes( double *a, + double *b); +/* + * a : Semi-major axis, in meters, of ellipsoid (output) + * b : Semi-minor axis, in meters, of ellipsoid (output) + * + * The function WGS72_Axes returns the lengths of the semi-major and + * semi-minor axes for the WGS72 ellipsoid. If the ellipsoid table was + * initialized successfully, ELLIPSE_NO_ERROR is returned, otherwise + * ELLIPSE_NOT_INITIALIZED_ERROR is returned. + */ + + long WGS72_Eccentricity2 ( double *e2 ); +/* + * e2 : Square of eccentricity of WGS84 ellipsoid (output) + * + * The function WGS72_Eccentricity2 returns the square of the + * eccentricity for the WGS72 ellipsoid. If the ellipsoid table was + * initialized successfully, ELLIPSE_NO_ERROR is returned, otherwise + * ELLIPSE_NOT_INITIALIZED_ERROR is returned. + */ + + long WGS72_Flattening (double *f ); +/* + * f : Flattening of WGS72 ellipsoid. (output) + * + * The function WGS72_Flattening returns the flattening of the WGS72 + * ellipsoid . If the ellipsoid table was initialized successfully, + * ELLIPSE_NO_ERROR is returned, otherwise ELLIPSE_NOT_INITIALIZED_ERROR + * is returned. + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ELLIPSE_H */ + + diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ellipse/ossimEllipse.hpp b/Utilities/OSSIM/ossim_core/base/data_types/ellipse/ossimEllipse.hpp new file mode 100644 index 0000000000..c65d9d8fb9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ellipse/ossimEllipse.hpp @@ -0,0 +1,28 @@ +static Ellipsoid_Row Ellipsoid_Table [] = +{ + {"Airy", "AA", 6377563.396, 6356256.9090, 299.324964600}, + {"Modified Airy","AM", 6377340.189, 6356034.4480, 299.324964600}, + {"Australian National", "AN", 6378160.000, 6356774.7190, 298.250000000}, + {"Bessel 1841", "BR", 6377397.155, 6356078.9630, 299.152812800}, + {"Bessel 1841(Namibia)", "BN", 6377483.865, 6356165.3830, 299.152812800}, + {"Clarke 1866", "CC", 6378206.400, 6356583.8000, 294.978698200}, + {"Clarke 1880", "CD", 6378249.145, 6356514.8700, 293.465000000}, + {"Everest", "EA", 6377276.345, 6356075.4130, 300.801700000}, + {"Everest (E. Malasia, Brunei)", "EB", 6377298.556, 6356097.5500, 300.801700000}, + {"Everest 1956 (India)", "EC", 6377301.243, 6356100.2280, 300.801700000}, + {"Everest 1969 (West Malasia)", "ED", 6377295.664, 6356094.6680, 300.801700000}, + {"Everest 1948(W.Mals. & Sing.)", "EE", 6377304.063, 6356103.0390, 300.801700000}, + {"Everest (Pakistan)", "EF", 6377309.613, 6356109.5710, 300.801700000}, + {"Mod. Fischer 1960(South Asia)", "FA", 6378155.000, 6356773.3200, 298.300000000}, + {"GRS 80", "RF", 6378137.000, 6356752.3141, 298.257222101}, + {"Helmert 1906", "HE", 6378200.000, 6356818.1700, 298.300000000}, + {"Hough", "HO", 6378270.000, 6356794.3430, 297.000000000}, + {"Indonesian 1974", "ID", 6378160.000, 6356774.5040, 298.247000000}, + {"International", "IN", 6378388.000, 6356911.9460, 297.000000000}, + {"Krassovsky","KA", 6378245.000, 6356863.0190, 298.300000000}, + {"South American 1969", "SA", 6378160.000, 6356774.7190, 298.250000000}, + {"WGS 72", "WD", 6378135.000, 6356750.5200, 298.260000000}, + {"WGS 84", "WE", 6378137.000, 6356752.3142, 298.257223563} +}; + +static long Number_of_Ellipsoids = 23; diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ellipse/ossimEllipsoid.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ellipse/ossimEllipsoid.cpp new file mode 100644 index 0000000000..eb6fb11608 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ellipse/ossimEllipsoid.cpp @@ -0,0 +1,453 @@ +//***************************************************************************** +// FILE: ossimEllipsoid.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// DESCRIPTION: +// Contains implementation of class ossimEllipsoid. The implementation is +// actually for an OBLATE SPHEROID (x.radius = y.radius) as Earth is +// considered. +// +// SOFTWARE HISTORY: +//> +// 06Aug2001 Garrett Potts, Oscar Kramer (okramer@imagelinks.com) +// Initial coding. +//< +//***************************************************************************** +// $Id: ossimEllipsoid.cpp,v 1.15 2005/05/12 14:52:52 gpotts Exp $ + +#include <base/data_types/ellipse/ossimEllipsoid.h> + +#include <base/data_types/ossimEcefRay.h> +#include <base/data_types/ossimEcefPoint.h> +#include <base/data_types/ossimEcefVector.h> +#include <base/common/ossimKeywordNames.h> + +//*** +// Define Trace flags for use within this file: +//*** +#include "base/common/ossimTrace.h" +static ossimTrace traceExec ("ossimEllipsoid:exec"); +static ossimTrace traceDebug ("ossimEllipsoid:debug"); + + +//***************************************************************************** +// CONSTRUCTOR: ossimEllipsoid #1 (COPY) +// +//***************************************************************************** +ossimEllipsoid::ossimEllipsoid(const ossimEllipsoid &ellipsoid) + : + theName(ellipsoid.theName), + theCode(ellipsoid.theCode), + theA(ellipsoid.theA), + theB(ellipsoid.theB), + theFlattening(ellipsoid.theFlattening), + theA_squared(ellipsoid.theA_squared), + theB_squared(ellipsoid.theB_squared), + theEccentricitySquared(ellipsoid.theEccentricitySquared) +{ +} + +//***************************************************************************** +// CONSTRUCTOR: ossimEllipsoid #2 +// +//***************************************************************************** +ossimEllipsoid::ossimEllipsoid(const ossimString &name, + const ossimString &code, + const double &a, + const double &b) + : + theName(name), + theCode(code), + theA(a), + theB(b), + theA_squared(a*a), + theB_squared(b*b) +{ + computeFlattening(); + + theEccentricitySquared = 2*theFlattening - theFlattening*theFlattening; +} + +ossimEllipsoid::ossimEllipsoid() +{ + const ossimEllipsoid* ellipse = ossimEllipsoidFactory::instance()->wgs84(); + + *this = *ellipse; +} + +//***************************************************************************** +// CONSTRUCTOR: ossimEllipsoid #3 +// +//***************************************************************************** +ossimEllipsoid::ossimEllipsoid(const double &a, + const double &b) + : + theName(""), // initialize to empty + theCode(""), + theA(a), + theB(b), + theA_squared(a*a), + theB_squared(b*b) +{ + computeFlattening(); + + theEccentricitySquared = 2*theFlattening - theFlattening*theFlattening; + } + +//***************************************************************************** +// METHOD: ossimEllipsoid::nearestIntersection +// +//***************************************************************************** +bool ossimEllipsoid::nearestIntersection(const ossimEcefRay &ray, + ossimEcefPoint& rtnPt) const +{ + return nearestIntersection(ray, 0.0, rtnPt); +} + +//***************************************************************************** +// METHOD: ossimEllipsoid::nearestIntersection +// +// geographic objects that are derive this class will asssume that +// the reference datum is wgs84 and that the ray origin is a +// geocentric coordinate relative to the wgs84 datum. Will return +// true if the object was intersected and false otherwise. +// +// The nearest intersection will use the ray sphere intersection +// found in most ray tracers. We will take a Ray defined by the +// parametric equation: +// +// x = x0 + dxt +// y = y0 + dyt +// z = z0 + dzt +// +// and intersect this with the equation of a spheroid: +// +// x^2/theXRadius^2 + y^2/theYRadius^2 + z^2/theZRadius^2 = 1 +// +// +// the intersection is achived by substituting the parametric line +// into the equation of the sphereroid. By doing this you should +// get a quadratic in t and the equation should look like this: +// +// a*t^2 + b*t + c = 0 +// +// let a = dx^2/theXRadius^2 + dy^2/theYRadius^2 + dz^2/theZRadius^2 +// let b = 2*(x0*dx/theXRadius^2 +y0*dy/theYRadius^2 + z0*dz/theZRadius^2 +// let c = x0^2/theXRadius^2 + y0^2/theYRadius^2 + z0^2/theZRadius^2 - 1 +// +// +// Now solve the quadratic (-b +- sqrt(b^2 - 4ac) ) / 2a +// +// After solving for t, the parameter is applied to the ray to determine +// the 3D point position in X,Y,Z, passed back in rtnPt. The boolean +// "true" is returned if an intersection was found. +// +//***************************************************************************** +bool ossimEllipsoid::nearestIntersection(const ossimEcefRay& ray, + const double& offset, + ossimEcefPoint& rtnPt) const +{ + static const char MODULE[] = "ossimEllipsoid::nearestIntersection"; + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG: " << MODULE << ", entering...\n"; + + + double A_squared = (theA + offset)*(theA + offset); + double B_squared = (theB + offset)*(theB + offset); + +// double adjustedOffset = offset/theA; +// double bOverA = theB/theA; +// double A_squared = (1.0+adjustedOffset)*(1.0+adjustedOffset); +// double B_squared = ((bOverA+adjustedOffset)*(bOverA+adjustedOffset));//(theB + offset)*(theB + offset); + + //*** + // get the origin and direction of ray: + //*** + ossimEcefPoint start = ray.origin(); + ossimEcefVector direction = ray.direction(); +// start = ossimEcefPoint(start.x()/theA, +// start.y()/theA, +// start.z()/theA); + //*** + // Solve the coefficents of the quadratic formula + //*** + double a = ((direction.x() * direction.x())/A_squared) + + ((direction.y() * direction.y())/A_squared) + + ((direction.z() * direction.z())/B_squared); + + double b = 2.0*( ((start.x()*direction.x())/A_squared) + + ((start.y()*direction.y())/A_squared) + + ((start.z()*direction.z())/B_squared) ); + + double c = ((start.x()*start.x())/A_squared) + + ((start.y()*start.y())/A_squared) + + ((start.z()*start.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; +// t = t1; + } + + //*** + // Now apply solved t to ray to extrapolate correct distance to intersection + //*** + bool rtnval = false; + if (t >= 0) + { + rtnval = true; + rtnPt = ray.extend(t); +// rtnPt = ray.extend(t*theA); + } + + return rtnval; +} + + +//***************************************************************************** +// METHOD: ossimEllipsoid::evaluate(ossimColumnVector3d) +// +// Returns neg number if inside, 0 if on, and pos number if outside of +// ellipsoid. +// +//***************************************************************************** +double ossimEllipsoid::evaluate(const ossimEcefPoint &location)const +{ + //*** + // get the axis + //*** + return (((location.x() * location.x())/theA_squared) + + ((location.y() * location.y())/theA_squared) + + ((location.z() * location.z())/theB_squared) - 1.0); +} + +//***************************************************************************** +// METHOD: ossimEllipsoid::gradient() version A +// +// Returns vector normal to the ellipsoid at point specified. +// +//***************************************************************************** +void ossimEllipsoid::gradient(const ossimEcefPoint& location, + ossimEcefVector& result) const +{ + result.x() = (2.0*location.x())/theA_squared; + result.y() = (2.0*location.y())/theA_squared; + result.z() = (2.0*location.z())/theB_squared; +} + +//***************************************************************************** +// METHOD: ossimEllipsoid::gradient() version B +// +// Returns vector normal to the ellipsoid at point specified. +// +//***************************************************************************** +ossimEcefVector +ossimEllipsoid::gradient(const ossimEcefPoint &location)const +{ + ossimEcefVector result; + gradient(location, result); + return result; +} + + +bool ossimEllipsoid::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* code = kwl.find(prefix, + ossimKeywordNames::ELLIPSE_CODE_KW); + bool foundCode = false; + if(code) + { + const ossimEllipsoid* ellipse = ossimEllipsoidFactory::instance()->create(ossimString(code)); + + if(ellipse) + { + foundCode = true; + *this = *ellipse; + } + } + if(!foundCode) + { + const char* majorAxis = kwl.find(prefix, + ossimKeywordNames::MAJOR_AXIS_KW); + const char* minorAxis = kwl.find(prefix, + ossimKeywordNames::MAJOR_AXIS_KW); + + theName = ""; + theCode = ""; + if(majorAxis && minorAxis) + { + theA = ossimString(majorAxis).toDouble(); + theB = ossimString(minorAxis).toDouble(); + + computeFlattening(); + theA_squared = theA*theA; + theB_squared = theB*theB; + } + else + { + const ossimEllipsoid* ellipse = ossimEllipsoidFactory::instance()->wgs84(); + + *this = *ellipse; + } + } + + return true; +} + +bool ossimEllipsoid::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + if(theCode != "") + { + kwl.add(prefix, + ossimKeywordNames::ELLIPSE_CODE_KW, + theCode.c_str(), + true); + + kwl.add(prefix, + ossimKeywordNames::ELLIPSE_NAME_KW, + theName.c_str(), + true); + } + kwl.add(prefix, + ossimKeywordNames::MAJOR_AXIS_KW, + theA, + true); + + kwl.add(prefix, + ossimKeywordNames::MINOR_AXIS_KW, + theB, + true); + + return true; +} + + +//***************************************************************************** +// METHOD: ossimEllipsoid::geodeticRadius() +// +// Computes the "geodetic" radius for a given latitude in degrees +// +//***************************************************************************** +double ossimEllipsoid::geodeticRadius(const double& lat) const +{ + double sin_lat = sind(lat); + double sin2_lat = sin_lat*sin_lat; + + return (theA_squared/ + sqrt(theA_squared - theA_squared*sin2_lat + theB_squared*sin2_lat)); +} + +void ossimEllipsoid::latLonHeightToXYZ(double lat, double lon, double height, + double &x, double &y, double &z)const +{ + double sin_latitude = sind(lat); + double cos_latitude = cosd(lat); + double N = theA / sqrt( 1.0 - theEccentricitySquared*sin_latitude*sin_latitude); + x = (N+height)*cos_latitude*cosd(lon); + y = (N+height)*cos_latitude*sind(lon); + z = (N*(1-theEccentricitySquared)+height)*sin_latitude; +} + +void ossimEllipsoid::XYZToLatLonHeight(double x, double y, double z, + double& lat, double& lon, double& height)const +{ + double d = sqrt(x*x + y*y); + + double phi2 = z / ((1 - theEccentricitySquared) * d); + double p = 1.0; + double phi1 = 0.0; + double N1 = 0.0; + double height1 = 0.0; + int iterIdx = 0; + const int MAX_ITER = 10; + if (fabs(phi2) > 1e-16 ) + { + while ( (p > 1e-17) && (iterIdx < MAX_ITER)) + { + phi1 = phi2; + N1 = theA / sqrt(1.0 - (theEccentricitySquared * pow(sin(phi1), 2.0))); + height1 = (d / cos(phi1) - N1); + phi2 = atan((z / d) * (1.0 + (theEccentricitySquared * N1 * sin(phi1)) / z)); + p = fabs(phi2 - phi1); + ++iterIdx; + /* printf("phi: %e phi2: %e p: %e \n", phi1, phi2, p); */ + } + } + else + { + phi1 = phi2; + N1 = theA / sqrt(1.0 - (theEccentricitySquared * pow(sin(phi1), 2.0))); + height1 = (d / cos(phi1)) - N1; + } + + /* *Latitude = phi2 * 180/PI; */ + /* *Longitude = atan2(Y, X) * 180/PI; */ + lat = phi2*DEG_PER_RAD; + lon = atan2(y, x)*DEG_PER_RAD; + height = height1; + +#if 0 + double p = sqrt(x*x + y*y); + double theta = atan(z*theA/ (p*theB)); + double eDashSquared = (theA*theA - theB*theB)/ + (theB*theB); + + double sin_theta = sin(theta); + double cos_theta = cos(theta); + + lat = atan( (z + eDashSquared*theB*sin_theta*sin_theta*sin_theta) / + (p - theEccentricitySquared*theA*cos_theta*cos_theta*cos_theta) ); + lon = atan2(y,x); + + double sin_latitude = sin(lat); + double N = theA / sqrt( 1.0 - theEccentricitySquared*sin_latitude*sin_latitude); + + height = p/cos(lat) - N; + lat*=DEG_PER_RAD; + lon*=DEG_PER_RAD; +#endif +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ellipse/ossimEllipsoid.h b/Utilities/OSSIM/ossim_core/base/data_types/ellipse/ossimEllipsoid.h new file mode 100644 index 0000000000..847a5602fb --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ellipse/ossimEllipsoid.h @@ -0,0 +1,159 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// This is the class declaration for ossimEllipsoid. Though valid for the +// general class of geometric shape, this implementation contains additional +// methods suited to the Earth ellipsoid. +// +//******************************************************************* +// $ID$ + +#ifndef ossimEllipsoid_HEADER +#define ossimEllipsoid_HEADER + +#include "base/common/ossimConstants.h" +#include "base/data_types/ossimString.h" +#include "base/data_types/ossimColumnVector3d.h" +#include "base/data_types/ossimKeywordlist.h" + +class OSSIMDLLEXPORT ossimEcefRay; +class OSSIMDLLEXPORT ossimEcefPoint; +class OSSIMDLLEXPORT ossimEcefVector; + +/*!**************************************************************************** + * + * CLASS: ossimEllipsoid + * + *****************************************************************************/ +class OSSIMDLLEXPORT ossimEllipsoid +{ +public: + + /*! + * CONSTRUCTORS... + */ + ossimEllipsoid(const ossimEllipsoid &ellipsoid); + ossimEllipsoid(const ossimString &name, + const ossimString &code, + const double &major_axis, + const double &minor_axis); + ossimEllipsoid(const double &major_axis, + const double &minor_axis); + ossimEllipsoid(); + + virtual ~ossimEllipsoid(){}; + + /*! + * ACCESS METHOD... + */ + virtual const ossimString& name()const{return theName;} + virtual const ossimString& code()const{return theCode;} + + virtual const double& a()const{return theA;} // major axis + virtual const double& b()const{return theB;} // minor axis + + virtual const double& getA()const{return theA;} + virtual const double& getB()const{return theB;} + virtual const double& getFlattening()const{return theFlattening;} + + virtual void setA(double a){theA = a;computeFlattening();} + virtual void setB(double b){theB = b;computeFlattening();} + virtual void setAB(double a, double b){theA = a; theB = b; computeFlattening();} + + virtual double eccentricitySquared() const + { return theEccentricitySquared; } + + virtual double flattening()const + { return theFlattening; } + + virtual double eccentricity()const + { return sqrt(theEccentricitySquared); } + + /*! + * METHOD: nearestIntersection() + * Returns the point of nearest intersection of the ray with the ellipsoid. + * The first version performs the intersection at the ellipsoid surface. + * The second version computes the ray's intersection with a surface at + * some offset outside (for positive offset) of the ellipsoid (think + * elevation). + */ + virtual bool nearestIntersection(const ossimEcefRay& ray, + ossimEcefPoint& rtnPt) const; + virtual bool nearestIntersection(const ossimEcefRay& ray, + const double& offset, + ossimEcefPoint& rtnPt) const; + + /*! + * METHOD: evaluate() + * evaluate will evalate the function at location x, y, z (ECEF). + */ + virtual double evaluate(const ossimEcefPoint&)const; + + /*! + * METHOD: gradient() + * Compute the partials along location x, y, and z and place + * the result in the result vector. + */ + virtual void gradient(const ossimEcefPoint& location, + ossimEcefVector& result)const; + virtual ossimEcefVector gradient(const ossimEcefPoint& loc)const; + + /*! + * Computes the "geodetic" radius for a given latitude in DEGREES: + */ + double geodeticRadius(const double& latitude) const; + + void latLonHeightToXYZ(double lat, double lon, double height, + double &x, double &y, double &z)const; + + void XYZToLatLonHeight(double x, double y, double z, + double& lat, double& lon, double& height)const; + + virtual bool operator ==(const ossimEllipsoid& rhs)const + { + return ( (theName == rhs.theName)&& + (theCode == rhs.theCode)&& + (theB == rhs.theB)&& + (theFlattening == rhs.theFlattening)); + } + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; +protected: + virtual void computeFlattening() + { + theFlattening = (theA - theB)/theA; + } + + ossimString theName; + ossimString theCode; + double theA; //semi-major axis in meters + double theB; //semi-minor axis in meters + double theFlattening; + double theA_squared; + double theB_squared; + double theEccentricitySquared; + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/geoid/.cvsignore b/Utilities/OSSIM/ossim_core/base/data_types/geoid/.cvsignore new file mode 100644 index 0000000000..fa9d7a6f91 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/geoid/.cvsignore @@ -0,0 +1,3 @@ +*.d +ww15mgh.grd + diff --git a/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoid.cpp b/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoid.cpp new file mode 100644 index 0000000000..94c09d70d4 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoid.cpp @@ -0,0 +1,42 @@ +//***************************************************************************** +// FILE: ossimGeoid.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// DESCRIPTION: +// Contains implementation of class ossimGeoid +// +// SOFTWARE HISTORY: +//> +// 17Apr2001 Oscar Kramer (okramer@imagelinks.com) +// Initial coding. +//< +//***************************************************************************** + +#include "ossimGeoid.h" + +RTTI_DEF2(ossimGeoid, "ossimGeoid", ossimObject, ossimErrorStatusInterface) + +ossimGeoid::ossimGeoid() + : + ossimObject(), + ossimErrorStatusInterface() +{} + +ossimGeoid::~ossimGeoid() +{} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoid.h b/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoid.h new file mode 100644 index 0000000000..37c9f62628 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoid.h @@ -0,0 +1,61 @@ +//***************************************************************************** +// FILE: ossimGeoid.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// DESCRIPTION: +// Contains declaration of class ossimGeoid. Maintains a grid of elevation +// offsets for the geoid (mean sea level) relative to WGS-84 ellipsoid. +// +// SOFTWARE HISTORY: +//> +// 17Apr2001 Oscar Kramer (okramer@imagelinks.com) +// Initial coding. +//< +//***************************************************************************** + +#ifndef ossimGeoid_HEADER +#define ossimGeoid_HEADER + +#include "base/common/ossimObject.h" +#include "base/common/ossimErrorStatusInterface.h" + +class OSSIMDLLEXPORT ossimGpt; +class OSSIMDLLEXPORT ossimFilename; + +class OSSIMDLLEXPORT ossimGeoid : public ossimObject, + public ossimErrorStatusInterface +{ +public: + ossimGeoid(); + ossimGeoid(const ossimFilename& dir); + virtual ~ossimGeoid(); + + virtual bool open(const ossimFilename& dir, ossimByteOrder byteOrder=OSSIM_LITTLE_ENDIAN) = 0; + + /*! + * Returns the offset from the ellipsoid to the geoid. + * Returns OSSIM_DBL_NAN if grid does not contain the point. + */ + virtual double offsetFromEllipsoid(const ossimGpt& gpt) const = 0; + +protected: + + TYPE_DATA +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidEgm96.cpp b/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidEgm96.cpp new file mode 100644 index 0000000000..0484f8a88f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidEgm96.cpp @@ -0,0 +1,328 @@ +//******************************************************************* +// Copyright (C) 2002 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +//******************************************************************* +// $Id: ossimGeoidEgm96.cpp,v 1.18 2005/11/10 14:15:33 gpotts Exp $ + +#include <stdio.h> + +#include <base/data_types/geoid/ossimGeoidEgm96.h> +#include <base/common/ossimConstants.h> +#include <base/data_types/ossimGpt.h> +#include <base/data_types/ossimFilename.h> +#include <base/misc/ossimEndian.h> +#include <base/common/ossimTrace.h> +#include <base/context/ossimNotifyContext.h> +#include <base/factory/ossimDatumFactory.h> + +static ossimTrace traceDebug ("ossimGeoidEgm96:debug"); + + +#define NumbGeoidCols 1441 /* 360 degrees of longitude at 15 minute spacing */ +#define NumbGeoidRows 721 /* 180 degrees of latitude at 15 minute spacing */ +#define NumbHeaderItems 6 /* min, max lat, min, max long, lat, long spacing*/ +#define ScaleFactor 4 /* 4 grid cells per degree at 15 minute spacing */ +#define NumbGeoidElevs NumbGeoidCols * NumbGeoidRows +// #define PI 3.14159265358979323e0 + + +RTTI_DEF1(ossimGeoidEgm96, "ossimGeoidEgm96", ossimGeoid) + +ossimGeoidEgm96::ossimGeoidEgm96() + : + theGeoidHeightBuffer(NULL) +{} + +ossimGeoidEgm96::ossimGeoidEgm96(const ossimFilename& grid_file, + ossimByteOrder byteOrder) + : + theGeoidHeightBuffer(NULL) +{ + open(grid_file, byteOrder); + if (getErrorStatus() != ossimErrorCodes::OSSIM_OK) + { + if (theGeoidHeightBuffer) + { + delete theGeoidHeightBuffer; + theGeoidHeightBuffer = NULL; + } + } +} + +ossimGeoidEgm96::~ossimGeoidEgm96() +{ + if (theGeoidHeightBuffer) delete [] theGeoidHeightBuffer; +} + +ossimString ossimGeoidEgm96::getShortName()const +{ + return "geoid1996"; +} + +bool ossimGeoidEgm96::open(const ossimFilename& grid_file, ossimByteOrder byteOrder) +{ + static const char MODULE[] = "ossimGeoidEgm96::open"; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " Entered...\n"; + } + + if (theGeoidHeightBuffer) + { + delete theGeoidHeightBuffer; + } + + theGeoidHeightBuffer = new float[NumbGeoidElevs]; + + int ItemsRead = 0; + long ElevationsRead = 0; + long ItemsDiscarded = 0; + long num = 0; + + ossimFilename grid = grid_file; + if (grid_file.isDir()) + { + grid = grid_file.dirCat("egm96.grd"); + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " Grid file:" << grid << "\n"; + } + + // Open the File READONLY, or Return Error Condition: + FILE* GeoidHeightFile; + + if ( ( GeoidHeightFile = fopen( grid.c_str(), "rb" ) ) == NULL) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_WARN) << MODULE << " could not open file " + << grid.c_str() << "\n"; + } + setErrorStatus(); + return false; + } + + // Skip the Header Line: + ossimEndian oe; + bool swap_bytes = (ossimGetByteOrder() != byteOrder) ? true : false; + while ( num < NumbHeaderItems ) + { + if (feof( GeoidHeightFile )) break; + if (ferror( GeoidHeightFile )) break; + + float f; + ItemsRead = fread( &f, 4, 1, GeoidHeightFile ); + if (swap_bytes) oe.swap(f); + theGeoidHeightBuffer[num] = f; + ItemsDiscarded += ItemsRead; + ++num; + } + + // Determine if header read properly, or NOT: + if (theGeoidHeightBuffer[0] != -90.0 || + theGeoidHeightBuffer[1] != 90.0 || + theGeoidHeightBuffer[2] != 0.0 || + theGeoidHeightBuffer[3] != 360.0 || + theGeoidHeightBuffer[4] != ( 1.0 / ScaleFactor ) || + theGeoidHeightBuffer[5] != ( 1.0 / ScaleFactor ) || + ItemsDiscarded != NumbHeaderItems) + { + + fclose(GeoidHeightFile); + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_WARN) << MODULE << " bad header file " + << grid.c_str() << "\n"; + } + setErrorStatus(); + return false; + } + + // Extract elements from the file: + num = 0; + while ( num < NumbGeoidElevs ) + { + if (feof( GeoidHeightFile )) break; + if (ferror( GeoidHeightFile )) break; + + float f; + fread( &f, 4, 1, GeoidHeightFile ); + if (swap_bytes) oe.swap(f); + theGeoidHeightBuffer[num] = f; + ++ElevationsRead; + ++num; + } + + fclose(GeoidHeightFile); + + // Determine if all elevations of file read properly, or NOT: + if (ElevationsRead != NumbGeoidElevs) + { + setErrorStatus(); + ossimSetError("ossimGeoidEgm96::open", + ossimErrorCodes::OSSIM_ERROR, + "Bad grid file...%s", grid.c_str()); + return false; + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "Opened geoid grid: " << grid.c_str() << endl; + } + + return true; +} + +double ossimGeoidEgm96::offsetFromEllipsoid(const ossimGpt& gpt) const +{ + double offset = OSSIM_DBL_NAN; + ossimGpt savedGpt = gpt; + if(ossimDatumFactory::instance()->wgs84()) + { + savedGpt.changeDatum(ossimDatumFactory::instance()->wgs84()); + } + + if (!theGeoidHeightBuffer) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_FATAL) + << "ossimGeoidEgm96::offsetFromEllipsoid, " + << "Object not initialized!\n"; + } + + return offset; + } + + long Index; + double DeltaX, DeltaY; + double ElevationSE, ElevationSW, ElevationNE, ElevationNW; + double LatitudeDD, LongitudeDD; + double OffsetX, OffsetY; + double PostX, PostY; + double UpperY, LowerY; + + LatitudeDD = savedGpt.latd(); + + // Check for wrap. + if (LatitudeDD < -90.0) + { + LatitudeDD = -180.0 - LatitudeDD; + } + else if (LatitudeDD > 90.0) + { + LatitudeDD = 180.0 - LatitudeDD; + } + + if ( (LatitudeDD < -90.0) || LatitudeDD > 90.0) + { + if(traceDebug()) + { + // Latitude out of range + ossimNotify(ossimNotifyLevel_FATAL) + << "FATAL: " << "ossimGeoidEgm96::offsetFromEllipsoid, " + << "Point out of range: " << savedGpt << "\n"; + } + return offset; + } + + LongitudeDD = savedGpt.lond(); + + // Check for wrap. + if (LongitudeDD < -180) + { + LongitudeDD = LongitudeDD + 360.0; + } + else if (LongitudeDD > 180.0) + { + LongitudeDD = LongitudeDD - 360.0; + } + + if ( (LongitudeDD < -180.0) || (LongitudeDD > 180.0) ) + { + // Longitude out of range + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_FATAL) + << "FATAL: " << "ossimGeoidEgm96::offsetFromEllipsoid, " + << "Point out of range: " << savedGpt << "\n"; + } + return offset; + } + + // Compute X and Y Offsets into Geoid Height Array: + + if (LongitudeDD < 0.0) + { + OffsetX = ( LongitudeDD + 360.0 ) * ScaleFactor; + } + else + { + OffsetX = LongitudeDD * ScaleFactor; + } + OffsetY = ( 90.0 - LatitudeDD ) * ScaleFactor; + + //*** + // Find Four Nearest Geoid Height Cells for specified Latitude, + // Longitude; Assumes that (0,0) of Geoid Height Array is at + // Northwest corner: + //*** + PostX = floor( OffsetX ); + if ((PostX + 1) == NumbGeoidCols) + PostX--; + PostY = floor( OffsetY ); + if ((PostY + 1) == NumbGeoidRows) + PostY--; + + Index = (long)(PostY * NumbGeoidCols + PostX); + ElevationNW = theGeoidHeightBuffer[ Index ]; + ElevationNE = theGeoidHeightBuffer[ Index+ 1 ]; + + Index = (long)((PostY + 1) * NumbGeoidCols + PostX); + ElevationSW = theGeoidHeightBuffer[ Index ]; + ElevationSE = theGeoidHeightBuffer[ Index + 1 ]; + + //Perform Bi-Linear Interpolation to compute Height above Ellipsoid: + DeltaX = OffsetX - PostX; + DeltaY = OffsetY - PostY; + + UpperY = ElevationNW + DeltaX * ( ElevationNE - ElevationNW ); + LowerY = ElevationSW + DeltaX * ( ElevationSE - ElevationSW ); + + offset = UpperY + DeltaY * ( LowerY - UpperY ); + + return offset; +} + +double ossimGeoidEgm96::geoidToEllipsoidHeight(double lat, + double lon, + double geoidHeight) +{ + ossimGpt gpt(lat, lon); + + double height = offsetFromEllipsoid(gpt); + + return (height + geoidHeight); +} + +double ossimGeoidEgm96::ellipsoidToGeoidHeight(double lat, + double lon, + double ellipsoidHeight) +{ + ossimGpt gpt(lat, lon); + + double height = offsetFromEllipsoid(gpt); + + return ellipsoidHeight - height; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidEgm96.h b/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidEgm96.h new file mode 100644 index 0000000000..e54a31f09e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidEgm96.h @@ -0,0 +1,78 @@ +//******************************************************************* +// Copyright (C) 2002 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken <dburken@imagelinks.com> +// +// Description: +// +// Contains class definition for ossimGeoidEgm96 which is +// "Earth Gravity Model 1996". +// +//******************************************************************* +// $Id: ossimGeoidEgm96.h,v 1.5 2005/11/10 14:15:33 gpotts Exp $ + +#ifndef ossimGeoidEgm96_HEADER +#define ossimGeoidEgm96_HEADER + +#include "ossimGeoid.h" + + +#define GEOID_NO_ERROR 0x0000 +#define GEOID_FILE_OPEN_ERROR 0x0001 +#define GEOID_INITIALIZE_ERROR 0x0002 +#define GEOID_NOT_INITIALIZED_ERROR 0x0004 +#define GEOID_LAT_ERROR 0x0008 +#define GEOID_LON_ERROR 0x0010 + +class OSSIMDLLEXPORT ossimGpt; + +class OSSIMDLLEXPORT ossimGeoidEgm96 : public ossimGeoid +{ + +public: + ossimGeoidEgm96(); + ossimGeoidEgm96(const ossimFilename& grid_file, ossimByteOrder byteOrder=OSSIM_BIG_ENDIAN); + + virtual ~ossimGeoidEgm96(); + + virtual bool open(const ossimFilename& grid_file, ossimByteOrder byteOrder=OSSIM_BIG_ENDIAN); + + virtual ossimString getShortName()const; + + /*! + * Returns the offset from the ellipsoid to the geoid. + * Returns OSSIM_DBL_NAN if grid does not contain the point. + */ + virtual double offsetFromEllipsoid(const ossimGpt& gpt) const; + + double geoidToEllipsoidHeight(double lat, + double lon, + double geoidHeight); + + double ellipsoidToGeoidHeight(double lat, + double lon, + double ellipsoidHeight); + +protected: + + float* theGeoidHeightBuffer; + + TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidManager.cpp b/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidManager.cpp new file mode 100644 index 0000000000..50c223b847 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidManager.cpp @@ -0,0 +1,239 @@ +//***************************************************************************** +// FILE: ossimGeoidManager.cpp +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// AUTHOR: Oscar Kramer +// +// DESCRIPTION: Contains implementation of class ossimGeoidManager +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimGeoidManager.cpp,v 1.8 2005/11/10 14:15:33 gpotts Exp $ + +#include <base/data_types/geoid/ossimGeoidManager.h> +RTTI_DEF1(ossimGeoidManager, "ossimGeoidManager", ossimGeoid); + +#include <base/data_types/geoid/ossimGeoidNgs.h> +#include <base/data_types/geoid/ossimGeoidEgm96.h> +#include <base/data_types/ossimFilename.h> +#include <base/data_types/ossimFilename.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimKeyword.h> +#include <base/context/ossimNotifyContext.h> +//*** +// Define Trace flags for use within this file: +//*** +#include <base/common/ossimTrace.h> +static ossimTrace traceExec ("ossimGeoidManager:exec"); +static ossimTrace traceDebug ("ossimGeoidManager:debug"); + +ossimGeoidManager* ossimGeoidManager::theInstance = NULL; + +//***************************************************************************** +// CONSTRUCTOR: ossimGeoidManager +// +//***************************************************************************** +ossimGeoidManager::ossimGeoidManager() +{ +} + +//***************************************************************************** +// DESTRUCTOR: ~ossimGeoidManager +// +//***************************************************************************** +ossimGeoidManager::~ossimGeoidManager() +{ +// vector<ossimGeoid*>::iterator g = theGeoidList.begin(); +// while (g != theGeoidList.end()) +// { +// delete *g; +// ++g; +// } + theGeoidList.clear(); +} + +//***************************************************************************** +// METHOD: ossimGeoidManager::instance() +// +//***************************************************************************** +ossimGeoidManager* ossimGeoidManager::instance() +{ + if (!theInstance) + theInstance = new ossimGeoidManager(); + + return theInstance; +} + +//***************************************************************************** +// METHOD: ossimElevManager::addGeoidSource +// +//***************************************************************************** +void ossimGeoidManager::addGeoid(ossimRefPtr<ossimGeoid> geoid) +{ + theGeoidList.push_back(geoid); +} + +//***************************************************************************** +// METHOD: ossimGeoidManager::loadState() +// +//***************************************************************************** +bool ossimGeoidManager::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + static const char MODULE[] = "ossimGeoidManager::loadState()"; + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG: " << MODULE << ", entering...\n"; + + + // Look for the ngs geoid directories + const char* lookup = kwl.find(prefix, "geoid_99_directory"); + ossimByteOrder geoidNgsByteOrder = OSSIM_LITTLE_ENDIAN; + const char* byteOrder = kwl.find(prefix, "geoid_99_directory.byte_order"); + if (!lookup) + { + lookup = kwl.find(prefix, "geoid_ngs_directory"); + byteOrder = kwl.find(prefix, "geoid_ngs_directory.byte_order"); + } + if(byteOrder) + { + if(ossimString(byteOrder).contains("little")) + { + geoidNgsByteOrder = OSSIM_LITTLE_ENDIAN; + } + else + { + geoidNgsByteOrder = OSSIM_BIG_ENDIAN; + } + } + if(lookup) + { + ossimFilename f = lookup; + if (f.isDir()) + { + ossimGeoid* geoid = new ossimGeoidNgs(f, geoidNgsByteOrder); + + if (geoid->getErrorStatus() == ossimErrorCodes::OSSIM_OK) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG: " << MODULE + << "\nAdded geoid dir: " << f.c_str() << "\n"; + } + + addGeoid(geoid); + } + else + { + delete geoid; + geoid = NULL; + } + } + } + // Look for the geoid Earth Gravity Model (EGM) 96 directory. + lookup = kwl.find(prefix, "geoid_egm_96_grid"); + if (lookup) + { + ossimFilename f = lookup; + if (f.isDir() || f.isFile()) + { + ossimGeoid* geoid = new ossimGeoidEgm96(f); + + if (geoid->getErrorStatus() == ossimErrorCodes::OSSIM_OK) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG: " << MODULE + << "\nAdded geoid egm 96: " << f.c_str() + << "\n"; + } + + addGeoid(geoid); + } + else + { + delete geoid; + geoid = NULL; + } + } + } + + if (traceExec()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG: " << MODULE << ", returning...\n"; + } + + return true; +} + + +//***************************************************************************** +// METHOD: ossimGeoidManager::open() +// +//***************************************************************************** +bool ossimGeoidManager::open(const ossimFilename& dir, ossimByteOrder byteOrder) +{ + vector<ossimRefPtr<ossimGeoid> >::iterator g = theGeoidList.begin(); + bool status = true; + while (g != theGeoidList.end()) + { + status &= (*g)->open(dir, byteOrder); + ++g; + } + + return status; +} + +//***************************************************************************** +// METHOD: ossimGeoidManager::open() +// +//***************************************************************************** +double ossimGeoidManager::offsetFromEllipsoid(const ossimGpt& gpt) const +{ + double offset = OSSIM_DBL_NAN; + vector<ossimRefPtr<ossimGeoid> >::const_iterator geoid = theGeoidList.begin(); + + while ((offset == OSSIM_DBL_NAN) && (geoid != theGeoidList.end())) + { + offset = ((*geoid))->offsetFromEllipsoid(gpt); + ++geoid; + } + + return offset; +} + +const ossimRefPtr<ossimGeoid> ossimGeoidManager::findGeoidByShortName(const ossimString& shortName, + bool caseSensitive)const +{ + ossim_uint32 idx=0; + ossimString testString = shortName; + if(!caseSensitive) + { + testString = testString.downcase(); + } + for(idx = 0; idx < theGeoidList.size(); ++idx) + { + if(!caseSensitive) + { + if(theGeoidList[idx]->getShortName().downcase() == testString) + { + return theGeoidList[idx]; + } + } + else + { + if(theGeoidList[idx]->getShortName() == testString) + { + return theGeoidList[idx]; + } + } + } + return 0; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidManager.h b/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidManager.h new file mode 100644 index 0000000000..83fbdccb32 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidManager.h @@ -0,0 +1,101 @@ +//***************************************************************************** +// FILE: ossimGeoidManager.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// AUTHOR: Oscar Kramer (okramer@imagelinks.com) +// +// DESCRIPTION: Contains declaration of class ossimGeoidManager. Maintains +// a list of geoids. +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimGeoidManager.h,v 1.7 2005/11/10 14:15:33 gpotts Exp $ + +#ifndef ossimGeoidManager_HEADER +#define ossimGeoidManager_HEADER + +#include <vector> +#include <base/common/ossimRefPtr.h> +#include "ossimGeoid.h" + +/*!**************************************************************************** + * + * CLASS: ossimGeoidManager + * + *****************************************************************************/ +class OSSIMDLLEXPORT ossimGeoidManager : public ossimGeoid +{ +public: + + + virtual ~ossimGeoidManager(); + + /*! + * Implements singelton pattern: + */ + static ossimGeoidManager* instance(); + + + /*! + * Permits initialization of geoids from directory name. Should never be + * called since called on specific geoid types: + */ + virtual bool open(const ossimFilename& dir, ossimByteOrder byteOrder); + + /*! + * Returns the offset from the ellipsoid to the geoid. + * Returns OSSIM_DBL_NAN if grid does not contain the point. + */ + virtual double offsetFromEllipsoid(const ossimGpt& gpt) const; + + /*! + * Method to save the state of the object to a keyword list. + * Return true if ok or false on error. DO NOTHING + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0) const { return true; } + + /*! + * Method to the load (recreate) the state of the object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /*! + * Permits adding additional geoids to the list: + */ + virtual void addGeoid(ossimRefPtr<ossimGeoid> geoid); + + const ossimRefPtr<ossimGeoid> findGeoidByShortName(const ossimString& shortName, + bool caseSensitive=true)const; +private: + /*! + * Private constructor. Use "instance" method. + */ + ossimGeoidManager(); + + static ossimGeoidManager* theInstance; + mutable std::vector< ossimRefPtr<ossimGeoid> > theGeoidList; + + TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidNgs.cpp b/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidNgs.cpp new file mode 100644 index 0000000000..928ceacc56 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidNgs.cpp @@ -0,0 +1,272 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimGeoidNgs.cpp,v 1.3 2005/11/10 14:15:33 gpotts Exp $ +#include <base/data_types/geoid/ossimGeoidNgs.h> + +#include <base/common/ossimCommon.h> +#include <base/common/ossimConstants.h> +#include <base/data_types/ossimString.h> +#include <base/data_types/ossimFilename.h> +#include <base/data_types/ossimGpt.h> +#include <base/context/ossimNotifyContext.h> +#include <base/common/ossimTrace.h> +#include <base/factory/ossimDatumFactory.h> + + +#include <stdlib.h> /* standard C general utility library */ +#include <iostream> +#include <fstream> +using namespace std; + +RTTI_DEF1(ossimGeoidNgs, "ossimGeoidNgs", ossimGeoid) + +static ossimTrace traceDebug ("ossimGeoidNgs:debug"); + +ossimGeoidNgs::ossimGeoidNgs() + :theShortName("") +{ +} + +ossimGeoidNgs::ossimGeoidNgs(const ossimFilename& dir, + ossimByteOrder byteOrder) +{ + open(dir); +} + + +bool ossimGeoidNgs::open(const ossimFilename& dir, + ossimByteOrder byteOrder) +{ + if (!dir.isDir()) + { + return false; + } + + if(dir.isDir()) + { + ossimGeoidNgsHeader h; + + if(dir.dirCat("g2003u01.bin").exists()) + { + theShortName = "geoid2003"; + addFile(dir.dirCat("g2003u01.bin"), byteOrder); + } + if(dir.dirCat("g2003u02.bin").exists()) + { + theShortName = "geoid2003"; + addFile(dir.dirCat("g2003u02.bin"), byteOrder); + } + if(dir.dirCat("g2003u02.bin").exists()) + { + theShortName = "geoid2003"; + addFile(dir.dirCat("g2003u02.bin"), byteOrder); + } + if(dir.dirCat("g2003u02.bin").exists()) + { + theShortName = "geoid2003"; + addFile(dir.dirCat("g2003u02.bin"), byteOrder); + } + if(dir.dirCat("g2003u02.bin").exists()) + { + theShortName = "geoid2003"; + addFile(dir.dirCat("g2003u02.bin"), byteOrder); + } + if(dir.dirCat("g2003u02.bin").exists()) + { + theShortName = "geoid2003"; + addFile(dir.dirCat("g2003u02.bin"), byteOrder); + } + + if(dir.dirCat("g1999u01.bin").exists()) + { + theShortName = "geoid1999"; + addFile(dir.dirCat("g1999u01.bin"), byteOrder); + } + if(dir.dirCat("g1999u02.bin").exists()) + { + theShortName = "geoid1999"; + addFile(dir.dirCat("g1999u02.bin"), byteOrder); + } + if(dir.dirCat("g1999u03.bin").exists()) + { + theShortName = "geoid1999"; + addFile(dir.dirCat("g1999u03.bin"), byteOrder); + } + if(dir.dirCat("g1999u04.bin").exists()) + { + theShortName = "geoid1999"; + addFile(dir.dirCat("g1999u04.bin"), byteOrder); + } + if(dir.dirCat("g1999u05.bin").exists()) + { + theShortName = "geoid1999"; + addFile(dir.dirCat("g1999u05.bin"), byteOrder); + } + if(dir.dirCat("g1999u06.bin").exists()) + { + theShortName = "geoid1999"; + addFile(dir.dirCat("g1999u06.bin"), byteOrder); + } + if(dir.dirCat("g1999u07.bin").exists()) + { + theShortName = "geoid1999"; + addFile(dir.dirCat("g1999u07.bin"), byteOrder); + } + if(dir.dirCat("g1999u08.bin").exists()) + { + theShortName = "geoid1999"; + addFile(dir.dirCat("g1999u08.bin"), byteOrder); + } + if(dir.dirCat("g1999a01.bin").exists()) + { + theShortName = "geoid1999"; + addFile(dir.dirCat("g1999a01.bin"), byteOrder); + } + if(dir.dirCat("g1999a02.bin").exists()) + { + theShortName = "geoid1999"; + addFile(dir.dirCat("g1999a02.bin"), byteOrder); + } + if(dir.dirCat("g1999a03.bin").exists()) + { + theShortName = "geoid1999"; + addFile(dir.dirCat("g1999a03.bin"), byteOrder); + } + if(dir.dirCat("g1999a04.bin").exists()) + { + theShortName = "geoid1999"; + addFile(dir.dirCat("g1999a04.bin"), byteOrder); + } + if(dir.dirCat("g1999h01.bin")) + { + theShortName = "geoid1999"; + addFile(dir.dirCat("g1999h01.bin"), byteOrder); + } + if(dir.dirCat("g1999p01.bin").exists()) + { + theShortName = "geoid1999"; + addFile(dir.dirCat("g1999p01.bin"), byteOrder); + } + } + else + { + addFile(dir, byteOrder); + } + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "Opened geoid grids from: " << dir.c_str() << endl; + } + + return true; +} + +ossimGeoidNgs::~ossimGeoidNgs() +{ +} + + +bool ossimGeoidNgs::addFile(const ossimFilename& file, ossimByteOrder byteOrder) +{ + bool result = false; + if(file.exists()) + { + ossim_uint32 idx = 0; + for(idx = 0; idx < theGridVector.size();++idx) + { + if(file == theGridVector[idx].filename()) + { + result = true; + return result; + } + } + ossimGeoidNgsHeader h; + result = h.initialize(file, byteOrder); + if(result) + { + theGridVector.push_back(h); + } + } + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimGeoidNgs::addFile: Adding file = " << file << std::endl; + } + return result; +} + +double ossimGeoidNgs::offsetFromEllipsoid(const ossimGpt& gpt) const +{ + ossimGpt savedGpt = gpt; + if(ossimDatumFactory::instance()->wgs84()) + { + savedGpt.changeDatum(ossimDatumFactory::instance()->wgs84()); + } + double lat = savedGpt.latd(); + double lon = savedGpt.lond(); + fixLatLon(lat, lon); + + return deltaHeight(lat, lon); +} + +double ossimGeoidNgs::geoidToEllipsoidHeight(double lat, + double lon, + double geoidHeight) +{ + + fixLatLon(lat, lon); + double delta = deltaHeight(lat, lon); + + return geoidHeight + delta; +} + +double ossimGeoidNgs::ellipsoidToGeoidHeight(double lat, + double lon, + double ellipsoidHeight) +{ + + fixLatLon(lat, lon); + double delta = deltaHeight(lat, lon); + + return ellipsoidHeight - delta; +} + +void ossimGeoidNgs::fixLatLon(double &lat, double &lon) const +{ + if(lat < 0) + { + lat += 180; + } + if(lon < 0) + { + lon += 360; + } +} + +double ossimGeoidNgs::deltaHeight(double lat, double lon)const +{ + ossim_uint32 idx = 0; + for(idx = 0; idx < theGridVector.size();++idx) + { + if( theGridVector[idx].pointWithin(lat, lon) ) + { + return theGridVector[idx].getHeightDelta(lat, + lon); + } + } + + return OSSIM_DBL_NAN; +} + +ossimString ossimGeoidNgs::getShortName()const +{ + return theShortName; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidNgs.h b/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidNgs.h new file mode 100644 index 0000000000..e4e3997e20 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidNgs.h @@ -0,0 +1,70 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimGeoidNgs.h,v 1.3 2005/11/10 14:15:33 gpotts Exp $ +#ifndef ossimGeoidNgs_HEADER +#define ossimGeoidNgs_HEADER + +#include "ossimGeoid.h" +#include "ossimGeoidNgsHeader.h" + +class OSSIMDLLEXPORT ossimGeoidNgs : public ossimGeoid +{ + +public: + ossimGeoidNgs(); + ossimGeoidNgs(const ossimFilename& dir, + ossimByteOrder byteOrder = OSSIM_LITTLE_ENDIAN); + virtual ~ossimGeoidNgs(); + + virtual ossimString getShortName()const; + + virtual bool open(const ossimFilename& dir, + ossimByteOrder byteOrder = OSSIM_LITTLE_ENDIAN); + + virtual bool addFile(const ossimFilename& file, + ossimByteOrder byteOrder = OSSIM_LITTLE_ENDIAN); + /*! + * Returns the offset from the ellipsoid to the geoid. + * Returns OSSIM_DBL_NAN if grid does not contain the point. + */ + virtual double offsetFromEllipsoid(const ossimGpt&) const; + + double geoidToEllipsoidHeight(double lat, + double lon, + double geoidHeight); + + double ellipsoidToGeoidHeight(double lat, + double lon, + double ellipsoidHeight); +protected: + void fixLatLon(double &lat, double &lon) const; + double deltaHeight(double lat, double lon)const; + + std::vector<ossimGeoidNgsHeader> theGridVector; + ossimString theShortName; + + TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidNgsHeader.cpp b/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidNgsHeader.cpp new file mode 100644 index 0000000000..ceb7ee6ba7 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidNgsHeader.cpp @@ -0,0 +1,173 @@ +#include "ossimGeoidNgsHeader.h" +#include <fstream> +#include <base/misc/ossimEndian.h> +#include <cmath> +#include <base/context/ossimNotifyContext.h> + +using namespace std; + +ostream& operator << (ostream &out, const ossimGeoidNgsHeader &data) +{ + out << "Filename: " << data.theFilename << endl + << "Southern lat: " << data.theSouthernMostLatitude << endl + << "Western lon: " << data.theWesternMostLongitude << endl + << "Lat spacing: " << data.theLatDelta << endl + << "Lon spacing: " << data.theLonDelta << endl + << "rows: " << data.theRows << endl + << "cols: " << data.theCols << endl + << "Datatype: " << data.theDataType << endl; + + return out; +} + + +ossimGeoidNgsHeader::ossimGeoidNgsHeader() + :theFilename(""), + theByteOrder(OSSIM_LITTLE_ENDIAN), + theSouthernMostLatitude(0.0), + theWesternMostLongitude(0.0), + theLatDelta(0.0), + theLonDelta(0.0), + theRows(0), + theCols(0), + theDataType(0) +{ +} + +ossimGeoidNgsHeader::ossimGeoidNgsHeader(const ossimFilename &fileName, + ossimByteOrder byteOrder) +{ + initialize(fileName, byteOrder); +} + +bool ossimGeoidNgsHeader::initialize(const ossimFilename &fileName, + ossimByteOrder byteOrder) +{ + ifstream input(fileName.c_str(), ios::in|ios::binary); + if(!input) + { +// cerr << MODULE << " Cannot open geoid file in " << fileName.c_str() +// << endl; + return false; + } + + theByteOrder = byteOrder; + double latOrigin = 0.0; + double lonOrigin = 0.0; + double latSpacing = 0.0; + double lonSpacing = 0.0; + int rows = 0; + int cols = 0; + int type = 0; + + input.read((char*)&latOrigin, 8); + input.read((char*)&lonOrigin, 8); + input.read((char*)&latSpacing, 8); + input.read((char*)&lonSpacing, 8); + input.read((char*)&rows, 4); + input.read((char*)&cols, 4); + input.read((char*)&type, 4); + + ossimEndian endian; + + if(endian.getSystemEndianType() != byteOrder) + { + endian.swap(latOrigin); + endian.swap(lonOrigin); + endian.swap(latSpacing); + endian.swap(lonSpacing); + endian.swap(rows); + endian.swap(cols); + endian.swap(type); + } + + theFilename = fileName; + theSouthernMostLatitude = latOrigin; + theWesternMostLongitude = lonOrigin; + theLatDelta = latSpacing; + theLonDelta = lonSpacing; + theRows = rows; + theCols = cols; + theDataType = type; + + return ((theSouthernMostLatitude >= -FLT_EPSILON)&& + (theSouthernMostLatitude <= 90.0)&& + (theWesternMostLongitude >= -FLT_EPSILON)&& + (theWesternMostLongitude <= 360.0)); +} + +bool ossimGeoidNgsHeader::pointWithin(double lat, double lon)const +{ + return( (lat >= theSouthernMostLatitude) && + (lat <= (theSouthernMostLatitude + theRows*theLatDelta)) && + (lon >= theWesternMostLongitude) && + (lon <= theWesternMostLongitude + theCols*theLonDelta)); +} + +double ossimGeoidNgsHeader::getHeightDelta(double lat, + double lon)const +{ + float result=0.0; + + // note the headers go from 0 to 360 degrees starting at the prime meridian. + // ours goes from -180 to 180 degrees. We will need to shift + // + if(lon < 0.0) lon += 360; + double latSpaces = (lat - theSouthernMostLatitude)/theLatDelta; + double lonSpaces = (lon - theWesternMostLongitude)/theLonDelta; + + if(latSpaces < -FLT_EPSILON) return OSSIM_DBL_NAN; + if(lonSpaces < -FLT_EPSILON) return OSSIM_DBL_NAN; + + long latSpace0 = (long)std::floor(latSpaces); + long latSpace1 = latSpace0 + 1; + long lonSpace0 = (long)std::floor(lonSpaces); + long lonSpace1 = lonSpace0 + 1; + + ifstream input(filename().c_str(), ios::in|ios::binary); + if(!input) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL: " << "ossimGeoid99::getGeoidHeight, " << "unable to open file: " << theFilename << "\n"; + return 0; + } + + long offset00 = (long)(headerSize() + (latSpace0*theCols + lonSpace0)*dataTypeSize()); + long offset01 = (long)(headerSize() + (latSpace0*theCols + lonSpace1)*dataTypeSize()); + long offset11 = (long)(headerSize() + (latSpace1*theCols + lonSpace1)*dataTypeSize()); + long offset10 = (long)(headerSize() + (latSpace1*theCols + lonSpace0)*dataTypeSize()); + + double tLat = latSpaces - floor(latSpaces); + double tLon = lonSpaces - floor(lonSpaces); + + + float v00; + float v01; + float v11; + float v10; + + input.seekg(offset00,ios::beg); + input.read((char*)&v00, 4); + + input.seekg(offset01,ios::beg); + input.read((char*)&v01, 4); + + input.seekg(offset11,ios::beg); + input.read((char*)&v11, 4); + + input.seekg(offset10,ios::beg); + input.read((char*)&v10, 4); + ossimEndian endian; + if(endian.getSystemEndianType() != theByteOrder) + { + endian.swap(v00); + endian.swap(v01); + endian.swap(v11); + endian.swap(v10); + } + double bottom = (v00 + (v01 - v00)*tLat); + double top = (v10 + (v11 - v10)*tLat); + result = bottom + (top - bottom)*tLon; + + return result; + +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidNgsHeader.h b/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidNgsHeader.h new file mode 100644 index 0000000000..c6f9585253 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/geoid/ossimGeoidNgsHeader.h @@ -0,0 +1,97 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimGeoidNgsHeader.h,v 1.2 2005/11/04 17:50:35 gpotts Exp $ +#ifndef ossimGeoidNgsHeader_HEADER +#define ossimGeoidNgsHeader_HEADER +#include "base/data_types/ossimFilename.h" + +#include <iostream> + +class OSSIMDLLEXPORT ossimGeoidNgsHeader +{ +public: + friend std::ostream& operator << (std::ostream &out, const ossimGeoidNgsHeader &data); + + ossimGeoidNgsHeader(); + ossimGeoidNgsHeader(const ossimFilename &fileName, + ossimByteOrder byteOrder=OSSIM_LITTLE_ENDIAN); + + bool initialize(const ossimFilename &fileName, + ossimByteOrder byteOrder=OSSIM_LITTLE_ENDIAN); + + double southernMostLat()const{return theSouthernMostLatitude;} + double westernMostLon()const{return theWesternMostLongitude;} + double latDelta()const{return theLatDelta;} + double lonDelta()const{return theLonDelta;} + int rows()const{return theRows;} + int cols()const{return theCols;} + int dataType()const{return theDataType;} + bool pointWithin(double lat, double lon)const; + const ossimFilename& filename()const{return theFilename;} + + int headerSize()const{return 44;} + int dataTypeSize()const{return theDataType==1?4:0;} + + double getHeightDelta(double lat, + double lon)const; +private: + ossimFilename theFilename; + ossimByteOrder theByteOrder; + double theSouthernMostLatitude; + + /*! + * Important: The geoid.bin files expresses this as a possitive value. + * + * example: -90.0 is 270 degrees. + */ + double theWesternMostLongitude; + + /*! + * Specifies the spacing of the latitude direction. + */ + double theLatDelta; + + /*! + * longitude spacing. + */ + double theLonDelta; + + /*! + * theRows specifies the number of lat increments + */ + int theRows; + + /*! + * theCols specifies the number of lon increments + */ + int theCols; + + /*! + * Specifies the datatype. if this is 1 then the data that follows + * is 4 byte floats. + */ + int theDataType; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimActiveEdgeTable.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimActiveEdgeTable.cpp new file mode 100644 index 0000000000..6bb0113e0e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimActiveEdgeTable.cpp @@ -0,0 +1,227 @@ +//***************************************************************************** +// FILE: ossimPolygon.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// AUTHOR: Garrett Potts (gpotts@imagelinks.com) +// +//***************************************************************************** +// $Id: ossimActiveEdgeTable.cpp,v 1.8 2004/04/02 22:03:54 gpotts Exp $ +#include <base/data_types/ossimActiveEdgeTable.h> +#include <base/data_types/ossimPolygon.h> +#include <base/data_types/ossimLine.h> +#include <base/data_types/ossimString.h> +#include <base/context/ossimNotifyContext.h> +#include <iterator> +using namespace std; + + +ossimActiveEdgeTable::ossimActiveEdgeTable() +{ + +} + +void ossimActiveEdgeTable::addPolygon(const ossimPolygon& polygon) +{ + createTable(polygon); + if(theTable.size()) + { + ossim_int32 iNextY, iY; + ossimActiveEdgeTableNode edge; + ossim_uint32 numPts = polygon.getVertexCount(); + theLastScanLine = 0; + + for (ossim_uint32 i=0; i<numPts; ++i) + { + // CURRENT EDGE IS FROM polygon[i] to polygon[(i+1)%numPts] + int iNext = (i+1)%numPts; // INDEX FOR SECOND EDGE VERTEX + iNextY = irint(polygon[iNext].y-theRectOrigin.y); + iY = (irint)(polygon[i].y-theRectOrigin.y); + int dy = (iNextY - iY); + if (dy != 0) // ADD ONLY IF EDGE NOT HORIZONTAL + { + if (dy> 0) // local max + { + double m = (polygon[iNext].x-polygon[i].x)/ + (polygon[iNext].y-polygon[i].y); + + edge = ossimActiveEdgeTableNode(iNextY+1, + m, + polygon[i].x); + + addEdgeToTable(edge, iY); + + } + else // local min so + { + double m = (polygon[i].x-polygon[iNext].x)/ + (polygon[i].y-polygon[iNext].y); + + edge = ossimActiveEdgeTableNode(iY, + m, + polygon[iNext].x); + + addEdgeToTable(edge, iNextY); + } + + } + } + } +} + +void ossimActiveEdgeTable::createTable(const ossimPolygon& polygon) +{ + theBoundingRect.makeNan(); + theRectOrigin.makeNan(); + if(polygon.getVertexCount() >2) + { + theTable.clear(); + polygon.getBoundingRect(theBoundingRect); + if(!theBoundingRect.hasNans()) + { + theTable.resize(theBoundingRect.height()+1); + theRectOrigin = theBoundingRect.ul(); + } + } +} + +void ossimActiveEdgeTable::addEdgeToTable(const ossimActiveEdgeTableNode& edge, + ossim_int32 scanLine) +{ + theTable[scanLine].push_back(edge); +} + +void ossimActiveEdgeTable::initializeActiveList() +{ + int i = 0; + for(i=0;i<(int)theTable.size();++i) + { + if(theTable[i].size()) + { + theActiveList = theTable[i]; + theTable[i].clear(); + theCurrentScanLine = i; + theActiveList.sort(); + return; + } + } +} + +void ossimActiveEdgeTable::updateActiveEdges() +{ + std::list<ossimActiveEdgeTableNode>::iterator current = theActiveList.begin(); + + while(current != theActiveList.end()) + { + (*current).theCurrentX += (*current).theSlope; + + if((*current).theMaxY == theCurrentScanLine) + { + current = theActiveList.erase(current); + } + else + { + ++current; + } + } +}; + +void ossimActiveEdgeTable::mergeCurrentScanLine() +{ + if((theCurrentScanLine < (int)theTable.size())&& + theTable[theCurrentScanLine].size()) + { + theTable[theCurrentScanLine].sort(); + theActiveList.merge(theTable[theCurrentScanLine]); + theActiveList.sort(); + + theTable[theCurrentScanLine].clear(); + } +} + +void ossimActiveEdgeTable::printActiveEdgeList()const +{ + copy(theActiveList.begin(), + theActiveList.end(), + ostream_iterator<ossimActiveEdgeTableNode>(ossimNotify(ossimNotifyLevel_INFO) << "->")); + ossimNotify(ossimNotifyLevel_INFO) << "NULL\n"; +} + +ossimActiveEdgeTableHelper::ossimActiveEdgeTableHelper(ossimActiveEdgeTable* edgeTable) + :theEdgeTable(edgeTable), + theTableInitializedFlag(false) +{ +} + +bool ossimActiveEdgeTableHelper::advanceScanLine() +{ + if(!theEdgeTable) return false; + + if(!theTableInitializedFlag) + { + theEdgeTable->initializeActiveList(); + theTableInitializedFlag = true; + } + else + { + ++theEdgeTable->theCurrentScanLine; + theEdgeTable->updateActiveEdges(); + theEdgeTable->mergeCurrentScanLine(); + } + + theIterator = theEdgeTable->theActiveList.begin(); + + return (theEdgeTable->theActiveList.size()); +} + +bool ossimActiveEdgeTableHelper::getNextLineSegment(ossimIpt& start, + ossimIpt& end) +{ + if(!theEdgeTable) return false; + if(!theTableInitializedFlag) advanceScanLine(); + + if(theIterator == theEdgeTable->theActiveList.end()) + { + return false; + } + else + { + int y = theEdgeTable->getCurrentScanLine()+getYShift(); + + start = ossimIpt( irint((*theIterator).theCurrentX), + y); + ++theIterator; + if(theIterator == theEdgeTable->theActiveList.end()) + { + end = start; + } + else + { + end = ossimIpt( irint((*theIterator).theCurrentX), + y); + + ++theIterator; + } + } + + if(start.x > end.x) + { + swap(start.x, end.x); + } + return true; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimActiveEdgeTable.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimActiveEdgeTable.h new file mode 100644 index 0000000000..4a200cc973 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimActiveEdgeTable.h @@ -0,0 +1,146 @@ +//***************************************************************************** +// +// License: See top level LICENSE.txt file. +// +// AUTHOR: Garrett Potts +// +//***************************************************************************** +// $Id: ossimActiveEdgeTable.h,v 1.6 2005/12/16 14:35:56 dburken Exp $ +#include <iostream> +#include <vector> +#include <list> +#include "ossimIrect.h" +class OSSIMDLLEXPORT ossimPolygon; + + +class OSSIMDLLEXPORT ossimActiveEdgeTableNode +{ +public: + friend std::ostream& operator <<(std::ostream& out, + const ossimActiveEdgeTableNode& rhs) + { + return out <<"| maxy="<<rhs.theMaxY<<" |dx=" + <<rhs.theSlope<<" |"<<"x=" + <<rhs.theCurrentX << "|"<< std::endl; +// return out <<"|dy="<<rhs.theDeltaY<<" |dx=" +// <<rhs.theSlope<<" |"<<"x=" +// <<rhs.theCurrentX << "|"<<endl; + } + ossimActiveEdgeTableNode(ossim_int32 maxY = 0, + double slope = 0.0, + double currentX = 0.0) +// :theDeltaY(deltaY), + :theMaxY(maxY), + theSlope(slope), + theCurrentX(currentX) + { + } + bool operator()(const ossimActiveEdgeTableNode& left, + const ossimActiveEdgeTableNode& right)const + { + return (left.theCurrentX < right.theCurrentX); + } + bool operator<(const ossimActiveEdgeTableNode& right)const + { + return (theCurrentX < right.theCurrentX); + } + bool operator>(const ossimActiveEdgeTableNode& right)const + { + return (theCurrentX > right.theCurrentX); + } + + ossim_int32 theMaxY; +// ossim_int32 theDeltaY; + double theSlope; + double theCurrentX; +}; + +class ossimActiveEdgeTableHelper; +/*! + * This class is used in fast efficient scanliine rasterization. It will take a polygon and insert + * it into the table sorted by y's + */ +class ossimActiveEdgeTable +{ +public: + friend class ossimActiveEdgeTableHelper; + ossimActiveEdgeTable(); + + /*! + * Currently will only work on a single polygon. If you call this + * twice it currently will use the last called polygon and + * will wipe out the previous one. + * + * Note: this is used for scanline rasterization and will round + * to integer values all vertices as they are initially added + * to the Active Edge Table. + */ + void addPolygon(const ossimPolygon& polygon); + + const std::list<ossimActiveEdgeTableNode>& getActiveList()const; + +// bool getNextScanline(list<ossimActiveEdgeTable>::const_iterator& iterator)const; + + ossim_int32 getCurrentScanLine()const + { + return theCurrentScanLine; + } + ossim_int32 getYShift()const + { + return theRectOrigin.y; + } + + void initializeActiveList(); + void updateActiveEdges(); + void mergeCurrentScanLine(); + void printActiveEdgeList()const; + +protected: + std::vector< std::list<ossimActiveEdgeTableNode> > theTable; + std::list<ossimActiveEdgeTableNode> theActiveList; + + void createTable(const ossimPolygon& polygon); + void addEdgeToTable(const ossimActiveEdgeTableNode& edge, + ossim_int32 scanLine); + /*! + * Used in computing the number of scanlines of the passed in polygon and + * is also used to shift the y's relative to 0,0 + */ + ossimIrect theBoundingRect; + ossimIpt theRectOrigin; + ossim_int32 theLastScanLine; + ossim_int32 theCurrentScanLine; +}; + +class ossimActiveEdgeTableHelper +{ +public: + ossimActiveEdgeTableHelper(ossimActiveEdgeTable* edgeTable); + + bool advanceScanLine(); + + bool getNextLineSegment(ossimIpt& start, + ossimIpt& end); + + ossim_int32 getCurrentScanLine()const + { + if(theEdgeTable) + { + return theEdgeTable->getCurrentScanLine(); + } + return 0; + } + ossim_int32 getYShift()const + { + if(theEdgeTable) + { + return theEdgeTable->getYShift(); + } + return 0; + } +protected: + ossimActiveEdgeTable* theEdgeTable; + bool theTableInitializedFlag; + + std::list<ossimActiveEdgeTableNode>::const_iterator theIterator; +}; diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimAxes.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimAxes.h new file mode 100644 index 0000000000..301745507d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimAxes.h @@ -0,0 +1,110 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Contains class declaration for ossimAxes. This will allow you to +// define three orthogonal ossimAxes and an origin in 3-D space. This +// information will be used to allow you to place points relative +// to the defined axes. +//******************************************************************* +// $Id: ossimAxes.h,v 1.3 2002/11/25 18:59:54 gpotts Exp $ + +#ifndef ossimAxes_HEADER +#define ossimAxes_HEADER +#include <iostream> +#include <iomanip> +using namespace std; +#include "ossimMatrix3x3.h" +#include "ossimMatrix4x4.h" +class OSSIMDLLEXPORT ossimAxes +{ +public: + + friend inline ostream& operator <<(ostream &out, const ossimAxes &axes); + + /*! + * Default constructor is at position 0, 0, 0 with unit axes + * + */ + ossimAxes(const ossimColumnVector3d &origin=ossimColumnVector3d(0,0,0), + const ossimColumnVector3d &xAxis=ossimColumnVector3d(1,0,0), + const ossimColumnVector3d &yAxis=ossimColumnVector3d(0,1,0), + const ossimColumnVector3d &zAxis=ossimColumnVector3d(0,0,1)) + : + theOrigin(origin), + theXAxis(xAxis), + theYAxis(yAxis), + theZAxis(zAxis) + {} + + ossimColumnVector3d projectPoint(const ossimColumnVector3d &pt) + { + return ossimColumnVector3d(theXAxis.dot(pt), + theYAxis.dot(pt), + theZAxis.dot(pt)); + } + + ossimColumnVector3d pointRelative(const ossimColumnVector3d& pt) + { + return projectPoint(pt - theOrigin); + } + + void rotateAxes(const ossimMatrix3x3& m) + { + theXAxis = m*theXAxis; + theYAxis = m*theYAxis; + theZAxis = m*theZAxis; + } + void rotateAxes(const ossimMatrix4x4& m) + { + theXAxis = m.rotateOnly(theXAxis); + theYAxis = m.rotateOnly(theYAxis); + theZAxis = m.rotateOnly(theZAxis); + } + void transformOrigin(const ossimMatrix3x3& m) + { + theOrigin = m*theOrigin; + } + void transformOrigin(const ossimMatrix4x4& m) + { + theOrigin = m*theOrigin; + } + const ossimColumnVector3d& origin()const{return theOrigin;} + const ossimColumnVector3d& xAxis()const{return theXAxis;} + const ossimColumnVector3d& yAxis()const{return theYAxis;} + const ossimColumnVector3d& zAxis()const{return theZAxis;} + +private: + ossimColumnVector3d theOrigin; // Is the origin of this axes + ossimColumnVector3d theXAxis; // Is the direction of the x axis + ossimColumnVector3d theYAxis; // Is the direction of the y axis + ossimColumnVector3d theZAxis; // Is the direction of the z axis +}; + +inline ostream& operator <<(ostream &out, const ossimAxes &axes) +{ + return out << "position: " << axes.theOrigin << endl + << "x axis : " << axes.theXAxis << endl + << "Y axis : " << axes.theYAxis << endl + << "z axis : " << axes.theZAxis; +} + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimColumnVector3d.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimColumnVector3d.h new file mode 100644 index 0000000000..fa7a81a7b1 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimColumnVector3d.h @@ -0,0 +1,258 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: This is a 3-D vector without the homogeneous +// coordinate. +// +//******************************************************************* +// $Id: ossimColumnVector3d.h,v 1.7 2005/06/28 15:04:13 gpotts Exp $ +#ifndef ossimColumnVector3d_HEADER +#define ossimColumnVector3d_HEADER +#include <base/common/ossimConstants.h> +#include <base/context/ossimNotifyContext.h> +#include <float.h> // for FLT_EPSILON +#include <iomanip> +#include <iostream> +#include <cmath> +using namespace std; + +#include <matrix/newmat.h> + +class OSSIMDLLEXPORT ossimColumnVector3d +{ +public: + ossimColumnVector3d() + { + data[0]=0; + data[1]=0; + data[2]=0; + } + + ossimColumnVector3d(double x, double y, double z=0) + { + data[0]=x; + data[1]=y; + data[2]=z; + } + + ossimColumnVector3d(const ossimColumnVector3d &rhs) + { + data[0] = rhs.data[0]; + data[1] = rhs.data[1]; + data[2] = rhs.data[2]; + } + + const ossimColumnVector3d& operator=(const NEWMAT::ColumnVector& rhs) + { + if ( (rhs.Ncols() == 1) && (rhs.Nrows() == 3) ) + { + data[0] = rhs[0]; + data[1] = rhs[1]; + data[2] = rhs[2]; + } + return *this; + } + + friend ostream& operator <<(ostream& out, const ossimColumnVector3d& v) + { + return out << setiosflags(ios::fixed) << setprecision(15) + << v[0] << " " << v[1] <<" " + << v[2]; + } + + friend ossimColumnVector3d operator*(double scalar, + const ossimColumnVector3d &v) + { + return ossimColumnVector3d(v.data[0]*scalar, + v.data[1]*scalar, + v.data[2]*scalar); + } + + /*! + * Multiplies column vector times matrix. + * Note: + * If "lhs" is not a 3x3 that's an error and a blank column vector + * is returned. + */ + friend ossimColumnVector3d operator*(const NEWMAT::Matrix& lhs, + const ossimColumnVector3d& rhs) + { + if ((lhs.Ncols() == 3) && (lhs.Nrows() == 3)) + { + return ossimColumnVector3d( (lhs[0][0]*rhs[0] + lhs[0][1]*rhs[1] + lhs[0][2]*rhs[2]), + (lhs[1][0]*rhs[0] + lhs[1][1]*rhs[1] + lhs[1][2]*rhs[2]), + (lhs[2][0]*rhs[0] + lhs[2][1]*rhs[1] + lhs[2][2]*rhs[2])); + } + else if((lhs.Ncols() == 4) && (lhs.Nrows() == 4)) + { + return ossimColumnVector3d( (lhs[0][0]*rhs[0] + lhs[0][1]*rhs[1] + lhs[0][2]*rhs[2] + lhs[0][3]) , + (lhs[1][0]*rhs[0] + lhs[1][1]*rhs[1] + lhs[1][2]*rhs[2] + lhs[1][3]) , + (lhs[2][0]*rhs[0] + lhs[2][1]*rhs[1] + lhs[2][2]*rhs[2] + lhs[2][3])); + } + ossimNotify(ossimNotifyLevel_WARN) << "Multiplying a 3 row column vector by an invalid matrix" << std::endl; + return rhs; + } + + double& operator [](int index) + { + return data[index]; + } + + const double& operator [](int index)const + { + return data[index]; + } + + ossimColumnVector3d operator*(double scalar)const + { + return ossimColumnVector3d(data[0]*scalar, + data[1]*scalar, + data[2]*scalar); + } + + ossimColumnVector3d operator +(const ossimColumnVector3d &rhs)const + { + return ossimColumnVector3d( data[0]+rhs[0], + data[1]+rhs[1], + data[2]+rhs[2]); + } + + const ossimColumnVector3d& operator +=(const ossimColumnVector3d &rhs) + { + data[0] += rhs[0]; + data[1] += rhs[1]; + data[2] += rhs[2]; + + return *this; + } + + ossimColumnVector3d operator - ()const + { + return ossimColumnVector3d(-data[0], + -data[1], + -data[2]); + } + + ossimColumnVector3d operator /(double scalar)const + { + return ossimColumnVector3d( data[0]/scalar, + data[1]/scalar, + data[2]/scalar); + } + + const ossimColumnVector3d& operator /=(double scalar) + { + data[0]/=scalar; + data[1]/=scalar; + data[2]/=scalar; + + return *this; + } + + ossimColumnVector3d operator -(const ossimColumnVector3d &rhs)const + { + return ossimColumnVector3d( data[0]-rhs[0], + data[1]-rhs[1], + data[2]-rhs[2]); + } + + const ossimColumnVector3d& operator -=(const ossimColumnVector3d &rhs) + { + data[0] -= rhs[0]; + data[1] -= rhs[1]; + data[2] -= rhs[2]; + + return *this; + } + + bool operator ==(const ossimColumnVector3d &rhs) const + { return ((fabs(data[0] - rhs[0]) <= FLT_EPSILON) && + (fabs(data[1] - rhs[1]) <= FLT_EPSILON) && + (fabs(data[2] - rhs[2]) <= FLT_EPSILON)); + } + + bool operator !=(const ossimColumnVector3d &rhs) const + { return !(*this == rhs); } + + double magnitude()const + { + return sqrt(data[0]*data[0] + + data[1]*data[1] + + data[2]*data[2]); + } + double dot(const ossimColumnVector3d &rhs) const + { + return (data[0]*rhs[0]+ + data[1]*rhs[1]+ + data[2]*rhs[2]); + } + + ossimColumnVector3d unit() const + { + double mag = magnitude(); + + if(fabs(mag) > FLT_EPSILON) + { + mag = 1.0/mag; + return (*this *mag); + } + + return *this; + } + + ossimColumnVector3d cross(const ossimColumnVector3d &rhs) const + { + return ossimColumnVector3d( data[1]*rhs[2] - data[2]*rhs[1], + data[2]*rhs[0] - data[0]*rhs[2], + data[0]*rhs[1] - data[1]*rhs[0]); + } + + const ossimColumnVector3d& xAligned() + { + data[0] = 1; + data[1] = 0; + data[2] = 0; + + return *this; + } + const ossimColumnVector3d& yAligned()// + { + data[0] = 0; + data[1] = 1; + data[2] = 0; + + return *this; + } + const ossimColumnVector3d& zAligned() // + { + data[0] = 0; + data[1] = 0; + data[2] = 1; + + return *this; + } + +private: + double data[3]; +}; + + + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimColumnVector4d.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimColumnVector4d.h new file mode 100644 index 0000000000..0be3f174cf --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimColumnVector4d.h @@ -0,0 +1,213 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: This is your 3-D vector where the 4-th dimension is +// for the homogenious coordinate. +// +//******************************************************************* +// $Id: ossimColumnVector4d.h,v 1.3 2004/09/10 15:45:34 gpotts Exp $ +#ifndef ossimColumnVector4d_HEADER +#define ossimColumnVector4d_HEADER +#include <base/common/ossimConstants.h> +#include <base/common/ossimCommon.h> +#include <float.h> // for FLT_EPSILON +#include <iomanip> +#include <iostream> +#include <cmath> +using namespace std; + +class OSSIMDLLEXPORT ossimColumnVector4d +{ +public: + ossimColumnVector4d() + { + data[0]=0; + data[1]=0; + data[2]=0; + data[3]=1; + } + + ossimColumnVector4d(double x, double y, double z, double w=1.0) + { + data[0]=x; + data[1]=y; + data[2]=z; + data[3]=w; + } + + ossimColumnVector4d(const ossimColumnVector4d &rhs) + { + data[0] = rhs.data[0]; + data[1] = rhs.data[1]; + data[2] = rhs.data[2]; + data[3] = rhs.data[3]; + } + friend ostream& operator <<(ostream& out, const ossimColumnVector4d& v) + { + return out << setiosflags(ios::fixed) << setprecision(15) + << v[0] << " " << v[1] <<" " + << v[2] << " " << v[3]; + } + + friend ossimColumnVector4d operator*(double scalar, const ossimColumnVector4d &v) + { + return ossimColumnVector4d(v.data[0]*scalar, + v.data[1]*scalar, + v.data[2]*scalar); + } + + double& operator [](int index) + { + return data[index]; + } + + const double& operator [](int index)const + { + return data[index]; + } + + ossimColumnVector4d operator*(double scalar)const + { + return ossimColumnVector4d(data[0]*scalar, + data[1]*scalar, + data[2]*scalar); + } + + ossimColumnVector4d operator +(const ossimColumnVector4d &rhs)const + { + return ossimColumnVector4d( data[0]+rhs[0], + data[1]+rhs[1], + data[2]+rhs[2]); + } + + ossimColumnVector4d operator +=(const ossimColumnVector4d &rhs) + { + data[0] += rhs[0]; + data[1] += rhs[1]; + data[2] += rhs[2]; + + return *this; + } + + ossimColumnVector4d operator - ()const + { + return ossimColumnVector4d(-data[0], + -data[1], + -data[2]); + } + + ossimColumnVector4d operator /(double scalar)const + { + return ossimColumnVector4d( data[0]/scalar, + data[1]/scalar, + data[2]/scalar); + } + + ossimColumnVector4d& operator /=(double scalar) + { + data[0]/=scalar; + data[1]/=scalar; + data[2]/=scalar; + + return *this; + } + + ossimColumnVector4d operator -(const ossimColumnVector4d &rhs)const + { + return ossimColumnVector4d( data[0]-rhs[0], + data[1]-rhs[1], + data[2]-rhs[2]); + } + + ossimColumnVector4d operator -=(const ossimColumnVector4d &rhs) + { + data[0] -= rhs[0]; + data[1] -= rhs[1]; + data[2] -= rhs[2]; + + return *this; + } + + double magnitude()const + { + return std::sqrt(data[0]*data[0] + + data[1]*data[1] + + data[2]*data[2]); + } + double dot(const ossimColumnVector4d &rhs)const + { + return (data[0]*rhs[0]+ + data[1]*rhs[1]+ + data[2]*rhs[2]); + } + + ossimColumnVector4d unit()const + { + double mag = magnitude(); + + if(ossimAbs(mag) > DBL_EPSILON) + { + mag = 1.0/mag; + return (*this *mag); + } + + return *this; + } + + ossimColumnVector4d cross(const ossimColumnVector4d &rhs) + { + return ossimColumnVector4d( data[1]*rhs[2] - data[2]*rhs[1], + data[2]*rhs[0] - data[0]*rhs[2], + data[0]*rhs[1] - data[1]*rhs[0]); + } + + ossimColumnVector4d& xAligned()// creates 4-D homogeneous vectors + { + data[0] = 1; + data[1] = 0; + data[2] = 0; + data[3] = 1; + + return *this; + } + ossimColumnVector4d& yAligned()// + { + data[0] = 0; + data[1] = 1; + data[2] = 0; + data[3] = 1; + + return *this; + } + ossimColumnVector4d& zAligned() // + { + data[0] = 0; + data[1] = 0; + data[2] = 1; + data[3] = 1; + + return *this; + } + +private: + double data[4]; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimDblGrid.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimDblGrid.cpp new file mode 100644 index 0000000000..470d30bbde --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimDblGrid.cpp @@ -0,0 +1,1127 @@ +//***************************************************************************** +// FILE: ossimDblGrid.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// AUTHOR: Oscar Kramer (okramer@imagelinks.com) +// +// DESCRIPTION: +// Contains implementation of class ossimDblGrid. This class maintains +// a regular grid of floating point (double) values. Access methods to the +// grid include interpolation between grid nodes. Capability is included +// to address the grid in an arbitrary, floating-point x, y coordinate +// system. +// +//***************************************************************************** +// $Id: ossimDblGrid.cpp,v 1.24 2004/04/02 22:03:54 gpotts Exp $ + +#include <base/data_types/ossimDblGrid.h> +#include <limits.h> +#include <iostream> +using namespace std; + +#include <base/data_types/ossimDrect.h> + +//*** +// Define Trace flags for use within this file: +//*** +#include <base/common/ossimTrace.h> +#include <base/context/ossimNotifyContext.h> + +static ossimTrace traceExec ("ossimDblGrid:exec"); +static ossimTrace traceDebug ("ossimDblGrid:debug"); + +const double ossimDblGrid::DEFAULT_NULL_VALUE = OSSIM_DBL_NAN; +static const ossimString MAGIC_NUMBER ("OSSIM_DBL_GRID"); +static const int MAX_LENGTH_DESCR = 80; + +/*!**************************************************************************** + * DEFAULT CONSTRUCTOR: ossimDblGrid + * + *****************************************************************************/ +ossimDblGrid::ossimDblGrid() + : + theGridData (0), + theSize (0, 0), + theOrigin (0.0, 0.0), + theSpacing (0.0, 0.0), + theMinValue (OSSIM_INFINITY), + theMaxValue (-OSSIM_INFINITY), + theNullValue (DEFAULT_NULL_VALUE), + theMeanIsComputed (false) +{ } + + +/*!**************************************************************************** + * COPY CONSTRUCTOR: ossimDblGrid + * + *****************************************************************************/ +ossimDblGrid::ossimDblGrid(const ossimDblGrid& source) + : + theGridData(NULL), + theSize (source.theSize), + theOrigin (source.theOrigin), + theSpacing (source.theSpacing), + theMinValue (source.theMinValue), + theMaxValue (source.theMaxValue), + theNullValue (source.theNullValue), + theMeanValue (source.theMeanValue), + theDeviation (source.theDeviation), + theMeanIsComputed (source.theMeanIsComputed) +{ + static const char MODULE[] = "ossimDblGrid Constructor"; + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entering...\n"; + + *this = source; + /*! + * Allocate mem for the grid, and initialize: + */ +// int buflen = theSize.x * theSize.y; +// theGridData = new double [buflen]; + +// for (int i=0; i<buflen; i++) +// theGridData[i] = source.theGridData[i]; + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " returning...\n"; +} + +/*!**************************************************************************** + * CONSTRUCTOR: ossimDblGrid + * + *****************************************************************************/ +ossimDblGrid::ossimDblGrid(const ossimIpt& size, + const ossimDpt& origin, + const ossimDpt& spacing, + double null_value) + : + theGridData (0) +{ + static const char MODULE[] = "ossimDblGrid Constructor"; + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entering...\n"; + + initialize(size, origin, spacing, null_value); + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " returning...\n"; +} + +/*!**************************************************************************** + * CONSTRUCTOR: ossimDblGrid + * + *****************************************************************************/ +ossimDblGrid::ossimDblGrid(const ossimDrect& rect, + const ossimDpt& spacing, + double null_value) + : + theGridData (0) +{ + static const char MODULE[] = "ossimDblGrid Constructor"; + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entering...\n"; + + ossimIpt size ((int) (rect.width()/spacing.x) + 1, + (int) (rect.height()/spacing.y) + 1); + + initialize(size, rect.ul(), spacing, null_value); + + if (traceExec()) ossimNotify(ossimNotifyLevel_WARN) << MODULE << " returning...\n"; +} + +//***************************************************************************** +// DESTRUCTOR: ~ossimDblGrid() +// +//***************************************************************************** +ossimDblGrid::~ossimDblGrid() +{ + if(theGridData) + { + delete [] theGridData; + theGridData = NULL; + } +} + +//***************************************************************************** +// METHOD: ossimDblGrid::initialize() +// +// Permits initialization after construction +// +//***************************************************************************** +void ossimDblGrid::initialize(const ossimIpt& size, + const ossimDpt& origin, + const ossimDpt& spacing, + double null_value) +{ + static const char MODULE[] = "ossimDblGrid::initialize()"; + if (traceExec()) ossimNotify(ossimNotifyLevel_WARN) << MODULE << " entering...\n"; + + //*** + // Delete any existing grid: + //*** + if (theGridData) + { + delete [] theGridData; + theGridData = 0; + } + + //*** + // Initialize data members: + //*** + theSize = size; + theOrigin = origin; + theSpacing = spacing; + theMinValue = OSSIM_INFINITY; + theMaxValue = -OSSIM_INFINITY; + theNullValue = null_value; + theMeanIsComputed = false; + + /*! + * Allocate mem for the grid, and initialize: + */ + int buflen = theSize.x * theSize.y; + if(buflen > 0) + { + theGridData = new double [buflen]; + + for (int i=0; i<buflen; i++) + theGridData[i] = theNullValue; + } + if (traceExec()) ossimNotify(ossimNotifyLevel_WARN) << MODULE << " returning...\n"; + + return; +} + +//***************************************************************************** +// METHOD: ossimDblGrid::initialize() +// +// Permits initialization after construction +// +//***************************************************************************** +void ossimDblGrid::initialize(const ossimDrect& uv_rect, + const ossimDpt& spacing, + double null_value) +{ + static const char MODULE[] = "ossimDblGrid::initialize()"; + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entering...\n"; + + ossimIpt size ((int) (uv_rect.width()/spacing.x) + 1, + (int) (uv_rect.height()/spacing.y) + 1); + + initialize(size, uv_rect.ul(), spacing, null_value); + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " returning...\n"; + return; +} + +void ossimDblGrid::deallocate() +{ + if(theGridData) + { + delete [] theGridData; + theGridData = 0; + } + theSize = ossimIpt(0,0); +} + +/*!**************************************************************************** + * METHOD: ossimDblGrid::setNode(x, y) NON-CONST + * + * This method is used to assign the grid data values. + * + *****************************************************************************/ +void ossimDblGrid::setNode (int x, int y, + const double& value) +{ + if(!theGridData) return; + + if ((x>=0)&&(x<theSize.x)&&(y>=0)&&(y<theSize.y)) + { + theGridData[index(x, y)] = value; + + if (value != theNullValue) + { + if (value < theMinValue) + theMinValue = value; + if (value > theMaxValue) + theMaxValue = value; + } + + theMeanIsComputed = false; + } + + return; +} + +/*!**************************************************************************** + * METHOD: ossimDblGrid::setNearestNode(uv) + * + * Sets the node nearest the U,V point specified to the value given. This is + * different from setNode() in that the UV coordinate system is used to + * address a node instead of an XY grid point. + * + *****************************************************************************/ +void ossimDblGrid::setNearestNode (const ossimDpt& uv_point, + const double& value) +{ + if(!theGridData) return; + //*** + // Establish the grid indexes: + //*** + int xi = (int) irint((uv_point.u - theOrigin.u)/theSpacing.x); + int yi = (int) irint((uv_point.v - theOrigin.v)/theSpacing.y); + + if (xi < 0) + xi = 0; + if (xi >= theSize.x) + xi = theSize.x - 1; + if (yi < 0) + yi = 0; + if (yi >= theSize.y) + yi = theSize.y - 1; + + setNode (xi, yi, value); + + return; +} + +/*!**************************************************************************** + * METHOD: ossimDblGrid::getNode(x, y) CONST + * + * This method is used to return the grid data values. + * + *****************************************************************************/ +double ossimDblGrid::getNode (int x, int y) const +{ + if(!theGridData) return theNullValue; + if ((x>=0)&&(x<theSize.x)&&(y>=0)&&(y<theSize.y)) + return theGridData[index(x, y)]; + + return theNullValue; +} + +/*!**************************************************************************** + * METHOD: ossimDblGrid::operator(double, double) + * + * This method interpolates between grid points given a fractional location + * in UV (external) world space. + * + *****************************************************************************/ +double ossimDblGrid::operator() (const double& u, + const double& v) const +{ + if(!theGridData) return theNullValue; + + if (isInside(u, v)) + { + /*! + * Establish the grid indexes: + */ + double xi = (u - theOrigin.u)/theSpacing.x; + double yi = (v - theOrigin.v)/theSpacing.y; + + + int x0 = (int) xi; + int y0 = (int) yi; + + x0 = (x0<theSize.x)?x0:(theSize.x-1); + y0 = (y0<theSize.y)?y0:(theSize.y-1); + xi = (xi<theSize.x)?xi:(theSize.x-1); + yi = (yi<theSize.y)?yi:(theSize.y-1); + /*! + * Perform bilinear interpolation: + */ + double wx1 = xi - x0; + double wy1 = yi - y0; + + + double wx0 = 1.0 - wx1; + double wy0 = 1.0 - wy1; + + int index00; + int index10; + int index11; + int index01; + + + index00 = theSize.x*y0 + x0; + if(x0 < (theSize.x-1)) + { + index10 = index00 + 1; + } + else + { + index10 = index00; + } + if(y0 < (theSize.y-1)) + { + index01 = index00 + theSize.x; + } + else + { + index01 = index00; + } + if(y0 < (theSize.y-1)) + { + index01 = index00 + theSize.x; + } + else + { + index01 = index00; + } + + if(x0 < (theSize.x-1)) + { + index11 = index01 + 1; + } + else + { + index11 = index01; + } + + + double p00 = (double) theGridData[index00]; + double p01 = (double) theGridData[index01]; + double p10 = (double) theGridData[index10]; + double p11 = (double) theGridData[index11]; + + double w00 = wx0*wy0; + double w01 = wx0*wy1; + double w10 = wx1*wy0; + double w11 = wx1*wy1; + + return (p00*w00 + p01*w01 + p10*w10 + p11*w11) / + (w00 + w01 + w10 + w11); + } + + // else + return theNullValue; +} + +//***************************************************************************** +// OPERATOR: = +// +//***************************************************************************** +const ossimDblGrid& ossimDblGrid::operator = (const ossimDblGrid& source) +{ + if(&source == this) return *this; + + if (theGridData) + { + delete [] theGridData; + theGridData = 0; + } + + //*** + // Assign data members: + //*** + theSize = source.theSize; + theOrigin = source.theOrigin; + theSpacing = source.theSpacing; + theMinValue = source.theMinValue; + theMaxValue = source.theMaxValue; + theNullValue = source.theNullValue; + theMeanValue = source.theMeanValue; + theDeviation = source.theDeviation; + theMeanIsComputed = source.theMeanIsComputed; + + //*** + // Allocate mem for the grid, and initialize: + //*** + int buflen = theSize.x * theSize.y; + if(buflen>0) + { + theGridData = new double [buflen]; + + for (int i=0; i<buflen; i++) + { + theGridData[i] = source.theGridData[i]; + } + } + return *this; +} + + +/*!**************************************************************************** + * METHOD: ossimDblGrid::meanValue() + * + *****************************************************************************/ +double ossimDblGrid::meanValue() +{ + static const char MODULE[] = "ossimDblGrid::meanValue()"; + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entering...\n"; + + if (!theMeanIsComputed) + { + computeMean(); + } + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " returning...\n"; + return theMeanValue; +} + +/*!**************************************************************************** + * METHOD: ossimDblGrid::meanStdDev() + * + *****************************************************************************/ +double ossimDblGrid::meanStdDev() +{ + static const char MODULE[] = "ossimDblGrid::meanStdDev()"; + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entering...\n"; + + if (!theMeanIsComputed) + computeMean(); + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " returning...\n";; + return theDeviation; +} + +/*!**************************************************************************** + * METHOD: ossimDblGrid::computeMean() + * + *****************************************************************************/ +void ossimDblGrid::computeMean() +{ + static const char MODULE[] = "ossimDblGrid::meanStdDev()"; + if(!theGridData) return; + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "entering...\n"; + + if (!theMeanIsComputed) + { + double accum = 0.0; + double num_samples = 0.0; + + /*! + * Loop to compute mean: + */ + for (int i=0; i<(theSize.x*theSize.y); i++) + { + if (theGridData[i] != theNullValue) + { + accum += theGridData[i]; + num_samples += 1.0; + } + } + theMeanValue = accum/num_samples; + + /*! + * Loop again to compute deviation: + */ + accum = 0.0; + double diff; + for (int i=0; i<(theSize.x*theSize.y); i++) + { + if (theGridData[i] != theNullValue) + { + diff = theMeanValue - theGridData[i]; + accum += diff*diff; + } + } + theDeviation = sqrt(accum/num_samples); + + theMeanIsComputed = true; + } + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " returning...\n"; + return; +} + +/*!**************************************************************************** + * INLINE METHOD: ossimDblGrid::isInside(const ossimDpt& pt) const + *****************************************************************************/ +bool ossimDblGrid::isInside(const double& u, + const double& v) const +{ + double xi = (u - theOrigin.u)/theSpacing.x; + double yi = (v - theOrigin.v)/theSpacing.y; +// return ((xi >= 0.0) && (xi <= ((double)theSize.x - 1.0)) && +// (yi >= 0.0) && (yi <= ((double)theSize.y - 1.0))); + return ((xi >= 0.0) && (xi < ((double)theSize.x)) && + (yi >= 0.0) && (yi < ((double)theSize.y))); +} + + +//***************************************************************************** +// METHOD: ossimDblGrid::save() +// +// Saves the grid to the stream in compact ASCII format (not necessarily +// human readable). +// +//***************************************************************************** +bool ossimDblGrid::save(ostream& os, const char* descr) const +{ + static const char MODULE[] = "ossimDblGrid::save()"; + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entering...\n"; + + //*** + // Preserve the stream's settings: + //*** + ios::fmtflags new_options = ios::scientific|ios::dec; + //ios::streamsize new_precision = 12; + int new_precision = 12; + + ios::fmtflags old_options = os.flags(new_options); + int old_precision = os.precision(new_precision); + + //*** + // Verify the description string is not too long: + //*** + char descr_buf[81]; + strncpy(descr_buf, descr, 80); + descr_buf[80] = '\0'; + + //*** + // write magic number tag and the grid size X, Y, num params: + //*** + os << MAGIC_NUMBER << " " << descr_buf << "\n" + << theSize.x << " " + << theSize.y << " " + << theOrigin.u << " " + << theOrigin.v << " " + << theSpacing.u << " " + << theSpacing.v << " " + << theNullValue << "\n"; + + if(theGridData) + { + //*** + // Loop to write grid points: + //*** + int max_index = theSize.x*theSize.y; + for (int i=0; i<max_index; i++) + os << theGridData[i] << " "; + } + os << "\n"; + + //*** + // Restore the stream's state: + //*** + os.flags(old_options); + os.precision(old_precision); + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " returning...\n"; + return true; +} + +//***************************************************************************** +// METHOD: ossimDblGrid::load() +// +// Loads the grid from the stream in compact ASCII format (not necessarily +// human readable). +// +//***************************************************************************** +bool ossimDblGrid::load(istream& is) +{ + static const char MODULE[] = "ossimDblGrid::load()"; + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entering...\n"; + + char strbuf[128]; + + //*** + // Read magic number tag to insure it is an ossimDblGrid record: + //*** + is >> strbuf; + if (strncmp(strbuf, MAGIC_NUMBER.c_str(), MAGIC_NUMBER.length())) + { + ossimNotify(ossimNotifyLevel_FATAL) << MODULE << "Error reading OSSIM_DBL_GRID magic number from stream. " + << "Aborting...\n"; + return false; + } + is.getline(strbuf, 128, '\n'); + theSize = ossimDpt(0,0); + theOrigin = ossimDpt(0,0); + theSpacing = ossimDpt(0,0); + theMinValue = OSSIM_INFINITY; + theMaxValue = -OSSIM_INFINITY; + theNullValue = theNullValue; + theMeanIsComputed = false; + + + //*** + // Read the grid size, origin, and spacing: + //*** + ossimIpt size; + ossimDpt origin, spacing; + double null_value; + is >> size.x + >> size.y + >> origin.u + >> origin.v + >> spacing.u + >> spacing.v + >> null_value; + + initialize(size, origin, spacing, null_value); + + //*** + // Loop to read grid points: + //*** + int max_index = theSize.x*theSize.y; + for (int i=0; i<max_index; i++) + { + is >> theGridData[i]; + } + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " returning...\n"; + + return true; +} + +//***************************************************************************** +// PRIVATE FUNCTION: isBlocked() +// +// Used by interpolateNullValuedNodes. Returns true if the direction indicated +// by the vector (x, y) has been blocked from further sampling. This occurs if +// a sample has already been found in that general direction. The directions +// are discrete (16) evenly distributed about a "compass rose." Each index +// corresponds to one of the directions as illustrated here: +// +// 15 0 1 +// 14 | 2 +// 13 | 3 +// 12------+------4 +// 11 | 5 +// 10 | 6 +// 9 8 7 +// +//***************************************************************************** +bool isBlocked(bool* blocked, int x, int y) +{ + if (y == 0) + { + if (x > 0) return blocked[4]; + return blocked[12]; + } + + double r = x/y; + int c = 0; + int i; + if (x < 0.0) c = 8; + + //*** + // Test the tangent value instead of computing angle: + //*** + if (r > 5.02734) i = 12 + c; + else if (r > 1.49660) i = 13 + c; + else if (r > 0.66818) i = 14 + c; + else if (r > 0.19891) i = 15 + c; + else if (r > -0.19891) i = 0 + c; + else if (r > -0.66818) i = 1 + c; + else if (r > -1.49660) i = 2 + c; + else if (r > -5.02734) i = 3 + c; + else i = 4 + c; + + if (i > 15) i -= 16; // modulo 16 + + return blocked[i]; +} + +//***************************************************************************** +// PRIVATE FUNCTION: blockDirection() +// +// Used by interpolateNullValuedNodes. Blocks the resampler from exploring +// further in a general direction, specified by thevector (x, y). The blocking +// is requested when a sample is found. This prevents a sample that is shadowed +// by a closer sample from having influence. +// +// See method isBlocked() above for a description of the compass rose indexing. +// +//***************************************************************************** +void blockDirection(bool* blocked, int x, int y) +{ + if (y == 0) + { + if (x > 0) blocked[4] = true; + else blocked[12] = true; + return; + } + + double r = x/y; + int c = 0; + int i; + if (x < 0.0) c = 8; + + //*** + // Test the tangent value instead of computing angle: + //*** + if (r > 5.02734) i = 12 + c; + else if (r > 1.49660) i = 13 + c; + else if (r > 0.66818) i = 14 + c; + else if (r > 0.19891) i = 15 + c; + else if (r > -0.19891) i = 0 + c; + else if (r > -0.66818) i = 1 + c; + else if (r > -1.49660) i = 2 + c; + else if (r > -5.02734) i = 3 + c; + else i = 4 + c; + + if (i > 15) i -= 16; // modulo 16 + blocked[i] = true; + + return; +} + +//***************************************************************************** +// METHOD: ossimDblGrid::interpolateNullValuedNodes(decay_rate) +// +// This method performs a resampling of the defined grid nodes in order to +// compute interpolated values for those uninitialized nodes. This is +// necessary when only a subset of nodes are available for initializing the +// grid. +// +// The decay rate is a geometric (1/r) factor applied to the weights to +// amplify the rate at which a neighbor's influence diminishes. For a +// decay_rate = 1, the influence of a sample diminishes linearly with the +// distance. +// +//***************************************************************************** +void ossimDblGrid::interpolateNullValuedNodes(const double& decay_rate) +{ + static const char MODULE[] = "ossimDblGrid::interpolateNullValuedNodes()"; + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entering...\n"; + if(!theGridData) return; + + //*** + // Allocate buffer to store resampled nodes: + //*** + int buf_size = theSize.x*theSize.y; + double* resampled_grid = new double [buf_size]; + double min_weight_needed = 4.0/decay_rate; + + int start_x, start_y, end_x, end_y; + int diameter; + double sum_weights; + double accumulator; + double weight; + double sample; + double node_value; + bool sample_found; + int node_idx; + double adj_delta; + int dx, dy; + bool blocked[16]; + + //*** + // Loop over the entire grid to resample all NULL nodes: + //*** + for (int y=0; y<theSize.y; y++) + { + for (int x=0; x<theSize.x; x++) + { + //*** + // Only resample those nodes that contain NULL: + //*** + node_idx = index(x, y); + node_value = theGridData[node_idx]; + if (node_value != theNullValue) + { + //*** + // This node had a value. Simply copy it into the resample_grid: + //*** + resampled_grid[node_idx] = node_value; + } + + else + { + //*** + // Resampling is necessary. Initialize quantities used: + //*** + start_x = x; + start_y = y; + diameter = 0; + sum_weights = 0; + accumulator = 0; + weight = 1.0; + sample_found = true; + + for (int i=0; i<16; i++) + blocked[i] = false; + + //*** + // Loop collecting contributions from non-null neighbors. Begin with + // a small kernel size (diameter) and successively grow until a + // sufficient number of contributors is found: + //*** + while ((sum_weights < min_weight_needed) && sample_found) + { + diameter += 2; + start_x -= 1; + start_y -= 1; + weight *= decay_rate; + sample_found = false; + + //*** + // Loop over each pixel in kernel and sum in it's contribution: + //*** + end_y = start_y + diameter; + end_x = start_x + diameter; + + for (int yn=start_y; yn<=end_y; yn++) + { + if ((yn == start_y) || (yn == end_y)) + { + //*** + // This is the top edge or bottom edge, need samples from + // each x along kernel edge: + //*** + for (int xn=start_x; xn<=end_x; xn++) + { + sample_found = sample_found || isInside(xn, yn); + sample = getNode(xn, yn); + if (sample != theNullValue) + { + dx = x - xn; dy = y - yn; + if (!isBlocked(blocked, dx, dy)) + { + adj_delta = weight*sqrt((double)(dx*dx + dy*dy)); + accumulator += sample/adj_delta; + sum_weights += 1.0/adj_delta; + blockDirection(blocked, dx, dy); + } + } + } + } + else + { + //*** + // For the left/right edge of the kernel, need to sample + // only the first (start_x) and last (end_x): + //*** + sample_found = sample_found || isInside(start_x, yn); + sample = getNode(start_x, yn); + if (sample != theNullValue) + { + dx = x - start_x; dy = y - yn; + if (!isBlocked(blocked, dx, dy)) + { + adj_delta = weight*sqrt((double)(dx*dx + dy*dy)); + accumulator += sample/adj_delta; + sum_weights += 1.0/adj_delta; + blockDirection(blocked, dx, dy); + } + } + + sample_found = sample_found || isInside(end_x, yn); + sample = getNode(end_x, yn); + if (sample != theNullValue) + { + dx = x - end_x; dy = y - yn; + if (!isBlocked(blocked, dx, dy)) + { + adj_delta = weight*sqrt((double)(dx*dx + dy*dy)); + accumulator += sample/adj_delta; + sum_weights += 1.0/adj_delta; + blockDirection(blocked, dx, dy); + } + } + } // end else + } // end for loop over all rows in kernel + } // end while loop inflating kernel size + + //*** + // Finished collecting sample contributions for this node. compute + // convolution and save in buffer: + //*** + if (sum_weights != 0) + resampled_grid[node_idx] = accumulator/sum_weights; + else + resampled_grid[node_idx] = theNullValue; + + } // end else (if input node is NULL) + } // end for loop over all columns in grid + } // end for loop over all lines in grid + + //*** + // Now copy the resampled grid back into the original buffer: + //*** + for (node_idx=0; node_idx<buf_size; node_idx++) + theGridData[node_idx] = resampled_grid[node_idx]; + + delete [] resampled_grid; + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " returning...\n"; + return; +} + +//***************************************************************************** +// METHOD: ossimDblGrid::filter(size_x, size_y, kernel) +// +// Passes the grid data through a convolution filter given in the kernel array. +// The grid must not contain any NULL nodes as these are not scanned for. +// The kernel sizes should be odd numbers. +// +//***************************************************************************** +void ossimDblGrid::filter(int size_x, int size_y, double* kernel) +{ + static const char MODULE[] = "ossimDblGrid::filter()"; + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << "entering...\n"; + if(!theGridData) return; + + //*** + // Allocate buffer to store resampled nodes: + //*** + int buf_size = theSize.x*theSize.y; + double* resampled_grid = new double [buf_size]; + for (int i=0; i<buf_size; i++) + resampled_grid[i] = 0.0; + + int rx = (size_x - 1)/2; // kernel radii + int ry = (size_y - 1)/2; + int start_x = rx; // indexes to start sampling grid + int start_y = ry; + int end_x = theSize.x - rx; // indexes to end buffer sampling + int end_y = theSize.y - ry; + int knl_ctr = ry*size_x + rx; // offset to center of kernel buffer + double node_value; + double kernel_value; + int node_idx; + + //*** + // Loop over the entire grid to resample all NULL nodes: + //*** + for (int y=start_y; y<end_y; y++) + { + for (int x=start_x; x<end_x; x++) + { + node_idx = index(x, y); + + //*** + // Fetch samples for each kernel element, apply gain, then accumulate + // in output buffer: + //*** + for (int ky=-ry; ky<=ry; ky++) + { + for (int kx=-rx; kx<=rx; kx++) + { + node_value = theGridData[index(x+kx, y+ky)]; + kernel_value = kernel[knl_ctr + ky*size_x + kx]; + resampled_grid[node_idx] += kernel_value*node_value; + } + } + } + } + + //*** + // The grid margin has unfiltered data due to the kernel radius. Set these + // nodes equal to the nearest filtered nodes: + //*** + for (int y=0; y<theSize.y; y++) + { + for (int x=0; x<theSize.x; x++) + { + //*** + // Top edge: + //*** + if (y < start_y) + { + if (x < start_x) // top-left corner + resampled_grid[index(x, y)] = resampled_grid[index(rx, ry)]; + else if (x >= end_x) // top-right corner + resampled_grid[index(x, y)] = resampled_grid[index(end_x-1, ry)]; + else // top region + resampled_grid[index(x, y)] = resampled_grid[index(x, ry)]; + } + + //*** + // Middle: + //*** + else if (y < end_y) + { + if (x < start_x) // left edge + resampled_grid[index(x, y)] = resampled_grid[index(rx, y)]; + else if (x >= end_x) // right edge + resampled_grid[index(x, y)] = resampled_grid[index(end_x-1, y)]; + } + + //*** + // Bottom: + //*** + else + { + if (x < start_x) // bottom-left corner + resampled_grid[index(x, y)] = resampled_grid[index(rx, end_y-1)]; + else if (x >= end_x) // bottom-right corner + resampled_grid[index(x, y)] = resampled_grid[index(end_x-1, + end_y-1)]; + else // bottom region + resampled_grid[index(x, y)] = resampled_grid[index(x, end_y-1)]; + } + } + } + + //*** + // Now copy the resampled grid back into the original buffer: + //*** + for (node_idx=0; node_idx<buf_size; node_idx++) + theGridData[node_idx] = resampled_grid[node_idx]; + + delete [] resampled_grid; + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " returning...\n"; + return; +} + + +//***************************************************************************** +// METHOD: ossimDblGrid::fill +// +// Fills the current grid with constant value provided. +// +//***************************************************************************** +void ossimDblGrid::fill(double fill_value) +{ + if (!theGridData) + { + return; + } + + int size = theSize.x * theSize.y; + for (int i=0; i<size; i++) + theGridData[i] = fill_value; + + return; +} + + +//***************************************************************************** +// FRIEND OPERATOR: ostream& << (ostream&) +// +//***************************************************************************** +ostream& operator<<(ostream& os, const ossimDblGrid& grid) +{ + os << "\nDump of ossimDblGrid at " << (void*) &grid + << "\n theSize: " << grid.theSize + << "\n theOrigin: " << grid.theOrigin + << "\n theSpacing: " << grid.theSpacing + << "\n theMinValue: " << grid.theMinValue + << "\n theMaxValue: " << grid.theMaxValue + << "\n theNullValue: " << grid.theNullValue + << "\n theMeanValue: " << grid.theMeanValue + << "\n theDeviation: " << grid.theDeviation + << "\n theMeanIsComputed: " << grid.theMeanIsComputed + << "\n"; + + if(grid.theGridData) + { + + for (int y=0; y<grid.theSize.y; y++) + { + for (int x=0; x<grid.theSize.x; x++) + { + os << "\n node(" << x << ", " << y << "): " << grid.getNode(x,y); + } + } + } + + return os; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimDblGrid.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimDblGrid.h new file mode 100644 index 0000000000..0e9ab4ea2c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimDblGrid.h @@ -0,0 +1,214 @@ +//***************************************************************************** +// FILE: ossimDblGrid.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: See top level LICENSE.txt file. +// +// AUTHOR: Oscar Kramer +// +// DESCRIPTION: +// Contains declaration of class ossimDblGrid. This object class maintains +// a regular grid of floating point (double) values. Access methods to the +// grid include interpolation between grid nodes. Capability is included +// to address the grid in an arbitrary, floating-point u, v coordinate +// system which is related to the integer grid x, y system by scale and +// offset: +// +// u = Sx*(x + Xo), v = Sy*(y + Y0) +// +// where Xo, Yo is the origin of the U/V cood system. Sx, Sy are the scale +// relations. For example, if the grid is being used to hold a grid of +// elevation posts, then the origin will be the SW corner post ground point, +// and the scale will be derived from the post spacing. Both origin and +// spacing are specified to the constructor. +// +//***************************************************************************** +// $Id: ossimDblGrid.h,v 1.13 2005/12/16 14:36:44 dburken Exp $ + +#ifndef ossimDblGrid_HEADER +#define ossimDblGrid_HEADER + +#include "base/data_types/ossimDpt.h" +#include "base/data_types/ossimIpt.h" +#include "base/common/ossimCommon.h" + +class OSSIMDLLEXPORT ossimDrect; + +/*!**************************************************************************** + * + * CLASS: ossimDblGrid + * + *****************************************************************************/ +class OSSIMDLLEXPORT ossimDblGrid +{ +public: + static const double DEFAULT_NULL_VALUE; + + /*! + * Default Constructor. + */ + ossimDblGrid (); + + /*! + * Copy Constructor. + */ + ossimDblGrid (const ossimDblGrid& source_to_copy); + + /*! + * Constructs given a U/V origin and spacing, and a grid size. + */ + ossimDblGrid (const ossimIpt& size, + const ossimDpt& origin, + const ossimDpt& spacing, + double null_value = DEFAULT_NULL_VALUE); + + /*! + * Constructs given a rectangle in U/V space and grid spacing. The origin is + * taken as the upper-left corner of the rectangle. The lower-rightmost grid + * point may not coincide with the rectangles LR corner if the side is not + * evenly divisible by the corresponding spacing. + */ + ossimDblGrid (const ossimDrect& uv_rect, + const ossimDpt& spacing, + double null_value = DEFAULT_NULL_VALUE); + + ~ossimDblGrid (); + + /*! + * When constructed with default, permits initialization afterward. + */ + void initialize(const ossimIpt& size, + const ossimDpt& origin, + const ossimDpt& spacing, + double null_value = DEFAULT_NULL_VALUE); + void initialize(const ossimDrect& uv_rect, + const ossimDpt& spacing, + double null_value = DEFAULT_NULL_VALUE); + void deallocate(); + /*! + * Fills the current grid with the value specified. + */ + void fill(double fill_value); + + /*! + * Fills the current grid with null values. + */ + void clear() { fill(theNullValue); } + + /*! + * Access individual node value by node index in the X/Y (grid) coord system. + */ + void setNode (const ossimIpt& p, + const double& value) { setNode(p.x, p.y, value); } + void setNode (int x, int y, const double& value); + + double getNode (const ossimIpt& p) const { return getNode(p.x, p.y); } + double getNode (int x, int y) const; + + /*! + * Sets the node nearest the U,V point specified to the value given. This is + * different from setNode() in that the UV coordinate system is used to + * address a node instead of an XY grid point. + */ + void setNearestNode(const ossimDpt& uv_point, + const double& value); + + /*! + * This method performs a resampling of the defined grid nodes in order to + * compute interpolated values for those uninitialized nodes. This is + * necessary when only a subset of nodes are available for initializing the + * grid. + */ + void interpolateNullValuedNodes(const double& decay_rate=10.0); + + /*! + * Passes the grid data through a convolution filter given the kernel array. + * The grid must not contain any NULL nodes as these are treated as valid + * quantities. The kernel sizes should be odd numbers. To avoid shrinking + * the grid by the kernel radius, the edge nodes outside of the filter's + * reach are set equal to the nearest filtered node. X is the contiguous + * axis in the kernel array, i.e., kernel(x,y) = kernel[y*size_x + x]. + */ + void filter(int size_x, int size_y, double* kernel); + + /*! + * Interpolate between grid nodes given arbitrary u/v coord system: + */ + enum InterpType + { + BILINEAR + }; + void setInterpolationType (InterpType interp); + + /*! + * Access an interpolated value in the U/V (output) coordinate system. + */ + double operator() (const ossimDpt& p) const {return (*this)(p.u,p.v);} + double value (const ossimDpt& p) const {return (*this)(p.u,p.v);} + + double operator() (const double& u, const double& v) const; + double value (const double& u, const double& v) const {return (*this)(u,v);} + + /*! + * operator for initializing this grid with another. + */ + const ossimDblGrid& operator = (const ossimDblGrid& grid); + + /*! + *Statistics methods: + */ + double minValue() const { return theMinValue; } + double maxValue() const { return theMaxValue; } + double nullValue() const { return theNullValue; } + double meanValue(); + double meanStdDev(); + + void setMinValue(double value) {theMinValue = value;} + void setMaxValue(double value) {theMaxValue = value;} + void setNullValue(double value) {theNullValue = value;} + /*! + * Other member access methods: + */ + const ossimIpt& size() const { return theSize; } + const ossimDpt& origin() const { return theOrigin; } + const ossimDpt& spacing() const { return theSpacing; } + unsigned long getSizeInBytes() const + { return theSize.x*theSize.y*sizeof(double); } + + /*! + * Returns true if double point lies within world space coverage: + */ + bool isInside(const ossimDpt& p) const {return isInside(p.u, p.v);} + bool isInside(const double& u, const double& v) const; + + /*! + * Loads and saves the grid from/to a stream. Returns TRUE if successful. + */ + bool save(std::ostream& os, const char* descr) const; + bool load(std::istream& is); + + + friend std::ostream& operator << (std::ostream& os, + const ossimDblGrid& grid); + +private: + + void computeMean(); + int index(int x, int y) const { return y*theSize.x + x; } + + double* theGridData; + ossimIpt theSize; + ossimDpt theOrigin; + ossimDpt theSpacing; + double theMinValue; + double theMaxValue; + double theNullValue; + double theMeanValue; + double theDeviation; + bool theMeanIsComputed; + +}; + +#endif + diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimDirectory.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimDirectory.cpp new file mode 100644 index 0000000000..9c01f1f7db --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimDirectory.cpp @@ -0,0 +1,275 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: A brief description of the contents of the file. +// +//************************************************************************* +// $Id: ossimDirectory.cpp,v 1.16 2005/10/28 14:01:03 gpotts Exp $ + +#include <iostream> + +#if defined (_WIN32) +#include <io.h> +#include <direct.h> +#else +#include "ossimDirectoryData.h" +#endif +#ifdef __BORLANDC__ +# include <dir.h> +#include <direct.h> +#include <stdio.h> +#include <stdlib.h> +#include <io.h> +#define _chdir chdir +#endif + +#include "ossimDirectory.h" +#include "ossimRegExp.h" + +//#include "wx/filefn.h" // for wxMatchWild + +// #include <sys/types.h> + +// #include <dirent.h> + +// ---------------------------------------------------------------------------- +// ossimDirectory construction/destruction +// ---------------------------------------------------------------------------- + +#if defined (_WIN32) +ossimDirectory::ossimDirectory() + : + theData(0), + theDirectoryName(), + theFlags(0) +{} + +ossimDirectory::ossimDirectory(const ossimFilename &dirname) + : + theData(0), + theDirectoryName(dirname), + theFlags(0) +{ + open(dirname); +} + +ossimDirectory::~ossimDirectory() +{ + if (theData != 0) _findclose( theData ); +} + +bool ossimDirectory::open(const ossimFilename &dirname) +{ + // close out currently open directory + if (theData != 0) + { + _findclose( theData ); + theData = 0; + } + + // set new directory name + theDirectoryName = dirname; + + return (dirname.isDir()); + // cd to the new directory +// if (_chdir( theDirectoryName) == -1) +// { +// return false; +// } + +// return true; +} + +bool ossimDirectory::getFirst(ossimFilename &filename, int flags) +{ + struct _finddata_t c_file; + ossimFilename temp; + //long theData1 = _findfirst( "*.*", &c_file ); + ossimFilename dirName = theDirectoryName.dirCat("*"); + if( (theData = _findfirst( dirName.c_str(), &c_file )) != 0L ) + { + setFlags(flags); + + temp = theDirectoryName.dirCat(c_file.name); + + + while (!fileMatched(temp)) + { + // look for next file in the directory + if (_findnext( theData, &c_file ) == 0 ) + { + temp = theDirectoryName.dirCat(c_file.name); + } + else + { + // no more file in the directory + return false; + } + } + } + + // set the filenane that matches + filename = temp.trim(); + + return (filename!=""); +} + +bool ossimDirectory::getNext(ossimFilename &filename) const +{ + struct _finddata_t c_file; + bool matches = false; + ossimFilename temp; + + while (!matches ) + { + // look for next file in the directory + if (_findnext( theData, &c_file ) == 0 ) + { + temp = theDirectoryName.dirCat(c_file.name); + matches = fileMatched(temp); + } + else + { + // no more file in the directory + return false; + } + } + + // set the filenane that matches + if (matches) + { + filename = temp.trim(); + } + + return (matches&&(filename!="")); +} + +bool ossimDirectory::fileMatched(ossimFilename &filename) const +{ + bool matches=false; + + // don't return "." and ".." unless asked for + if ( (filename == "..") || (filename == ".") ) + { + if (theFlags & ossimDirectory::OSSIM_DIR_DOTDOT) + { + matches = true; + } + } + else if((filename.isDir()) && (theFlags & ossimDirectory::OSSIM_DIR_DIRS)) + { + matches = true; + } + else if((filename.isFile()) && (theFlags & ossimDirectory::OSSIM_DIR_FILES)) + { + matches = true; + } + else + { + matches = false; + } + + return matches; +} + +bool ossimDirectory::isOpened() const +{ + return theData != 0; +} + +#else + +ossimDirectory::ossimDirectory() + : + theData(NULL) +{} + +ossimDirectory::ossimDirectory(const ossimFilename &dirname) +{ + theData = NULL; + open(dirname); +} + +bool ossimDirectory::open(const ossimFilename &dirname) +{ + delete theData; + theData = new ossimDirectoryData(dirname); + + if ( theData && + (!theData->isOk()) ) + { + delete theData; + theData = NULL; + + return false; + } + + return true; +} + +ossimDirectory::~ossimDirectory() +{ + delete theData; +} + +// ---------------------------------------------------------------------------- +// ossimDirectory enumerating +// ---------------------------------------------------------------------------- + +bool ossimDirectory::getFirst(ossimFilename &filename, + int flags) +{ + if(theData && isOpened()) + { + theData->rewind(); + + theData->setFlags(flags); + + return getNext(filename); + } + + return false; +} + +bool ossimDirectory::getNext(ossimFilename &filename) const +{ + if(theData && isOpened()) + { + return theData->read(filename); + } + + return false; +} + +bool ossimDirectory::isOpened() const +{ + return theData != NULL; +} + +#endif + +void ossimDirectory::findAllFilesThatMatch(std::vector<ossimFilename>& result, + const ossimString& regularExpressionPattern, + int flags) +{ + ossimFilename filename; + ossimRegExp regExpr; + regExpr.compile(regularExpressionPattern.c_str()); + if(getFirst(filename, flags)) + { + do + { + ossimString fileOnly = filename.file(); + if(regExpr.find(fileOnly.c_str())) + { + result.push_back(filename); + } + }while(getNext(filename)); + } +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimDirectory.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimDirectory.h new file mode 100644 index 0000000000..d0351ed83e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimDirectory.h @@ -0,0 +1,83 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +//************************************************************************* +// $Id: ossimDirectory.h,v 1.7 2004/11/04 20:11:35 dburken Exp $ +#ifndef ossimDirectory_HEADER +#define ossimDirectory_HEADER + +#include "ossimFilename.h" + +#ifndef _WIN32 +class ossimDirectoryData; +#endif + +class OSSIMDLLEXPORT ossimDirectory +{ +public: + + /*! + * These flags define what kind of filenames is included in the list + * of files enumerated by GetFirst/GetNext. + */ + enum + { + OSSIM_DIR_FILES = 0x0001, // include files + OSSIM_DIR_DIRS = 0x0002, // include directories + OSSIM_DIR_HIDDEN = 0x0004, // include hidden files + OSSIM_DIR_DOTDOT = 0x0008, // include '.' and '..' + + // by default, enumerate everything except '.' and '..' + OSSIM_DIR_DEFAULT = OSSIM_DIR_FILES | OSSIM_DIR_DIRS | OSSIM_DIR_HIDDEN + }; + + + ossimDirectory(); + + ossimDirectory(const ossimFilename& dir); + + ~ossimDirectory(); + + bool open(const ossimFilename& dir); + + bool isOpened() const; + + bool getFirst(ossimFilename &filename, + int flags = OSSIM_DIR_DEFAULT); + + /*! + * Get next file in the enumeration started with either GetFirst() or + * GetFirstNormal(). + */ + bool getNext(ossimFilename &filename) const; + + void findAllFilesThatMatch(std::vector<ossimFilename>& result, + const ossimString& regularExpressionPattern, + int flags = OSSIM_DIR_DEFAULT); + +#if defined (_WIN32) + void setFlags(int flags) { theFlags = flags; }; + bool fileMatched(ossimFilename &filename) const; +#endif + + // TODO using scandir() when available later, emulating it otherwise + +private: +#if defined (_WIN32) + long theData; + ossimFilename theDirectoryName; + int theFlags; +#else + ossimDirectoryData *theData; +#endif +}; + +#endif /* #ifndef ossimDirectory_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimDirectoryData.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimDirectoryData.cpp new file mode 100644 index 0000000000..655e967b18 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimDirectoryData.cpp @@ -0,0 +1,168 @@ +//******************************************************************* +// Copyright (C) 2002 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +// Description: +// Class designed to be used by ossimDirectory class. Should not be used +// directly. +// +//************************************************************************* +// $Id: ossimDirectoryData.cpp,v 1.4 2004/05/12 17:34:04 dburken Exp $ + +#ifndef _MSC_VER + +#include <sys/types.h> +#include <iostream> +using namespace std; + +#include "ossimDirectoryData.h" +#include "ossimDirectory.h" /* for flag enumerations */ + +// ---------------------------------------------------------------------------- +// ossimDirectoryData +// ---------------------------------------------------------------------------- + +#if !defined( __VMS__ ) || ( __VMS_VER >= 70000000 ) + +ossimDirectoryData::ossimDirectoryData(const ossimFilename& dirname) + : theDirectoryName(dirname) +{ + theDir = NULL; + + // throw away the trailing slashes + size_t n = theDirectoryName.length(); + if(n > 0) + { + + while ( n > 0 && theDirectoryName[--n] == '/' ) + ; + +// theDirectoryName.Truncate(n + 1); + + // do open the dir + theDir = opendir(theDirectoryName.c_str()); + } +} + +ossimDirectoryData::~ossimDirectoryData() +{ + if ( theDir ) + { + if ( closedir(theDir) != 0 ) + { + // ERROR closing directory + } + } +} + +bool ossimDirectoryData::read(ossimFilename &filename) +{ + filename = ossimFilename::NIL; + dirent *de = (dirent *)NULL; // just to silent compiler warnings + bool matches = false; + ossimFilename temp; + + while ( !matches ) + { + de = readdir(theDir); + if ( !de ) + { + return false; + } + + temp = theDirectoryName.dirCat(de->d_name); + + //*** + // NOTE: + // The check for "." and ".." did not work so added pattern match check. + //*** + + // Check for "." and ".." match at the end of the name. + ossimString s = temp.match("\\.$|\\.\\.$"); + + // don't return "." and ".." unless asked for + if ( (temp == "..") || + (temp == ".") || + (s == ".") || + (s == "..") ) + { + if (theFlags & ossimDirectory::OSSIM_DIR_DOTDOT) + { + matches = true; + } + } + else if((temp.isDir()) && + (theFlags & ossimDirectory::OSSIM_DIR_DIRS)) + { + matches = true; + } + else if((temp.isFile()) && + (theFlags & ossimDirectory::OSSIM_DIR_FILES)) + { + matches = true; + } + else + { + matches = false; + } + } + + if (matches) + { + filename = temp;//de->d_name; + } + + return matches; +} + +#else // old VMS (TODO) + +ossimDirectoryData::ossimDirectoryData(const ossimFilename& WXUNUSED(dirname)) +{ +} + +ossimDirectoryData::~ossimDirectoryData() +{ +} + +bool ossimDirectoryData::read(ossimFilename &filename) +{ + return false; +} + +#endif // not or new VMS/old VMS + +void ossimDirectoryData::setFlags(int flags) +{ + theFlags = flags; +} + +int ossimDirectoryData::getFlags() const +{ + return theFlags; +} + +void ossimDirectoryData::rewind() +{ + rewinddir(theDir); +} + +#endif /* #ifndef _MSC_VER */ + + diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimDirectoryData.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimDirectoryData.h new file mode 100644 index 0000000000..70d661d66d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimDirectoryData.h @@ -0,0 +1,57 @@ +//******************************************************************* +// Copyright (C) 2002 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +// Description: +// Class designed to be used by ossimDirectory class. Should not be used +// directly. +// +//************************************************************************* +// $Id: ossimDirectoryData.h,v 1.2 2004/05/12 17:34:04 dburken Exp $ +#ifndef ossimDirectoryData_HEADER +#define ossimDirectoryData_HEADER + +#ifndef _MSC_VER + +#include <dirent.h> +#include "ossimFilename.h" + +class OSSIMDLLEXPORT ossimDirectoryData +{ + public: + ossimDirectoryData(const ossimFilename& dirname); + ~ossimDirectoryData(); + + bool isOk() const { return theDir != NULL; } + + void setFlags(int flags); + int getFlags() const; + + void rewind(); + bool read(ossimFilename &filename); + + private: + DIR* theDir; + ossimFilename theDirectoryName; + int theFlags; +}; + +#endif /* #ifndef _MSC_VER */ + +#endif /* #ifndef ossimDirectoryData_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimDirectoryTree.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimDirectoryTree.cpp new file mode 100644 index 0000000000..09cb87c7c1 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimDirectoryTree.cpp @@ -0,0 +1,169 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: A brief description of the contents of the file. +// +//************************************************************************* +// $Id: ossimDirectoryTree.cpp,v 1.4 2004/05/04 12:17:06 gpotts Exp $ + +#include "ossimDirectoryTree.h" +#include "ossimDirectory.h" +#include "ossimRegExp.h" +ossimDirectoryTree::ossimDirectoryTree() + : + theCurrentDirectoryData(NULL), + theFlags(0) +{ +} + +ossimDirectoryTree::~ossimDirectoryTree() +{ + deleteAll(); +} + +void ossimDirectoryTree::findAllFilesThatMatch(std::vector<ossimFilename>& result, + const ossimString& regularExpressionPattern, + int flags) +{ + ossimFilename filename; + ossimRegExp regExpr; + regExpr.compile(regularExpressionPattern.c_str()); + if(getFirst(filename, flags)) + { + do + { + if(regExpr.find(filename.c_str())) + { + result.push_back(filename); + } + }while(getNext(filename)); + } +} + +bool ossimDirectoryTree::open(const ossimFilename& dir) +{ + if(theCurrentDirectoryData) + { + deleteAll(); + } + + theCurrentDirectoryData = new ossimDirData(new ossimDirectory, dir); + theCurrentDirectoryData->theDirectory->open(dir); + if(theCurrentDirectoryData->theDirectory->isOpened()) + { + return true; + } + else + { + delete theCurrentDirectoryData; + theCurrentDirectoryData = NULL; + } + + return isOpened(); +} + +bool ossimDirectoryTree::isOpened() const +{ + if(theCurrentDirectoryData) + { + return theCurrentDirectoryData->theDirectory->isOpened(); + } + + return false; +} + +bool ossimDirectoryTree::getFirst(ossimFilename &filename, int flags) +{ + bool result = false; + theFlags = flags | ossimDirectory::OSSIM_DIR_DIRS; + if(theCurrentDirectoryData && isOpened()) + { + result = theCurrentDirectoryData->theDirectory->getFirst(filename, + flags); + while(result&&filename.isDir()) + { + checkToPushDirectory(filename); + result = theCurrentDirectoryData->theDirectory->getNext(filename); + } + + if(!result) + { + if(!theDirectoryQueue.empty()) + { + ossimFilename newDir = theDirectoryQueue.front(); + theDirectoryQueue.pop(); + theCurrentDirectoryData->theDirectory->open(newDir); + + return getFirst(filename, flags); + } + } + } + + return result; +} + +// get next file in the enumeration started with either GetFirst() or +// GetFirstNormal() +bool ossimDirectoryTree::getNext(ossimFilename &filename) +{ + bool result = false; + + if(theCurrentDirectoryData) + { + result = theCurrentDirectoryData->theDirectory->getNext(filename); + if(result) + { + checkToPushDirectory(filename); + } + else + { + if(!theDirectoryQueue.empty()) + { + ossimFilename newDir = theDirectoryQueue.front(); + theDirectoryQueue.pop(); + theCurrentDirectoryData->theDirectory->open(newDir); + return getFirst(filename); + } + } + } + + return result; +} + +void ossimDirectoryTree::deleteAll() +{ + if(theCurrentDirectoryData) + { + delete theCurrentDirectoryData; + theCurrentDirectoryData = NULL; + } +} + +void ossimDirectoryTree::checkToPushDirectory(const ossimFilename &filename) +{ + if((filename.file().trim() == ".") || + (filename.file().trim() == "..")) + { + return; + } + else if(filename.isDir()) + { + theDirectoryQueue.push(filename); + } +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimDirectoryTree.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimDirectoryTree.h new file mode 100644 index 0000000000..ffce4407eb --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimDirectoryTree.h @@ -0,0 +1,87 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: A brief description of the contents of the file. +// +//************************************************************************* +// $Id: ossimDirectoryTree.h,v 1.5 2004/05/04 12:17:25 gpotts Exp $ +#ifndef ossimDirectoryTree_HEADER +#define ossimDirectoryTree_HEADER +#include <queue> +#include <vector> +using namespace std; + +#include "ossimDirectory.h" + +class OSSIMDLLEXPORT ossimDirectoryTree +{ +public: + ossimDirectoryTree(); + ~ossimDirectoryTree(); + + bool open(const ossimFilename& dir); + + bool isOpened() const; + + bool getFirst(ossimFilename &filename, + int flags = ossimDirectory::OSSIM_DIR_DEFAULT); + + // get next file in the enumeration started with either GetFirst() or + // GetFirstNormal() + bool getNext(ossimFilename &filename) ; + + void findAllFilesThatMatch(std::vector<ossimFilename>& result, + const ossimString& regularExpressionPattern, + int flags = ossimDirectory::OSSIM_DIR_DEFAULT); +private: + class OSSIMDLLEXPORT ossimDirData + { + public: + ~ossimDirData() + { + if(theDirectory) + { + delete theDirectory; + theFilename = ""; + } + } + ossimDirData(ossimDirectory *aDir, + const ossimFilename &filename) + :theDirectory(aDir), + theFilename(filename) + { + + } + ossimDirectory* theDirectory; + ossimFilename theFilename; + }; + + queue<ossimFilename> theDirectoryQueue; + ossimDirData* theCurrentDirectoryData; + int theFlags; + + void deleteAll(); + + void checkToPushDirectory(const ossimFilename &filename); + // for now we will hide copy + ossimDirectoryTree(const ossimDirectoryTree &rhs); + const ossimDirectoryTree& operator =(const ossimDirectoryTree& rhs); +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimDms.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimDms.cpp new file mode 100644 index 0000000000..d0fc519914 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimDms.cpp @@ -0,0 +1,941 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +// Contains class definition for Degrees Minutes Seconds (ossimDms) +//******************************************************************* +// $Id: ossimDms.cpp,v 1.17 2005/07/18 11:05:42 gpotts Exp $ + +#include <math.h> +#include <iomanip> +#include <sstream> +using namespace std; +#include <stdio.h> + +#include "ossimDms.h" +#include <iomanip> +using namespace std; + +const ossim_uint8 ossimDms::theDegreeSign = 176; +char *ossimDms::DEFAULT_FORMAT = "ddd mm.mmC"; +char *ossimDms::SPACES = " "; + + +ossimDms::ossimDms(double someDegrees, bool latFlag) + : theDegrees(someDegrees), + theLatFlag(latFlag), + theDecDegs(0.0), + theAfterDot(false), + theDoingSeconds(true), + theIntDegs(0), + theSign(1), + theWorking(0.0) +{ +} + +ossimDms::ossimDms(char *value) + : theDegrees(0.0), + theLatFlag(false), + theDecDegs(0.0), + theAfterDot(false), + theDoingSeconds(true), + theIntDegs(0), + theSign(1), + theWorking(0.0) +{ + if(value && (ossimString(value)!=ossimString(""))) + { + theDegrees = string_to_degree(value); + } + else + { + theDegrees = 0.0; + } + +} + +ossimDms& ossimDms::setDegrees(double degrees) +{ + theDegrees = degrees; + + return *this; +} + +bool ossimDms::setDegrees(const char *cdegrees) +{ + bool status = true; + + ossimString copy = cdegrees; + + double degrees, factor, dividend, units; + int i; + bool afterdelim; + char* cptr = const_cast<char*>(copy.c_str()); + char c; + + theAfterDot = false; + afterdelim = false; + degrees = 0.0; + units = 0.0; + factor = 1.0; + dividend = 60.0; + theSign = 1; + + /* get rid of leading spaces */ + + while (*cptr == ' ') + { + cptr++; + } + + while(*cptr != '\0') + { + switch (*cptr) + { + + // north, west and + values will change sign of degrees to plus. + + case '+': + { + theSign = 1; + cptr++; + } + case 'n': + case 'N': + { + theSign = 1; + theLatFlag = true; + cptr++; + break; + } + case 'e': + case 'E': + { + theLatFlag = false; + theSign = 1; + cptr++; + break; + } + + // south, east and - values will change sign of degrees to minus + + case '-': + { + theSign = -1; + cptr++; + break; + } + case 's': + case 'S': + { + theSign = -1; + cptr++; + theLatFlag = true; + break; + } + case 'w': + case 'W': + { + theSign = -1; + cptr++; + theLatFlag = false; + break; + } + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + c = *cptr; + i = (c - '0'); + + if (afterdelim == true) + { + if (theAfterDot == true) + { + units = units + (((double)i * factor) / dividend); + } + else + { + units = (units * factor) + ((double)i / dividend); + } + } + else + { + if (theAfterDot == true) + { + degrees = degrees + ((double)i * factor); + } + else + { + degrees = (degrees * factor) + (double)i; + } + } + if (theAfterDot == true) + { + factor = factor * .10; + } + else + { + factor = 10.; + } + + cptr++; + break; + } + + //--- + // a decimal point indicates a change in the factor used + // to calculate degrees or units (minutes or seconds) + //--- + case '.': + { + factor = .10; + theAfterDot = true; + cptr++; + break; + } + + // after a delimiter the value contains minutes, first time through + case ' ': + case '\"': + case '\'': + { + while (*(cptr + 1) == ' ') + { + cptr++; + } + + degrees = degrees + units; + units = 0.0; + + if (afterdelim == true) /* must be seconds */ + { + dividend = dividend * dividend; + } + else + { + afterdelim = true; + } + + factor = 1.; + + cptr++; + + // skip any leading zeroes after delimiter */ + + while (*cptr == '0') + { + cptr++; + } + + break; + } + + //--- + // check for a delimiter that is allowable: + // isspace allows: space, tab, cr, nl, vt, ff + // ispunct allows: punctuation char != space or control or letter + //--- + default: + { + if(isspace(*cptr) || + ispunct(*cptr) || + ((ossim_uint8)(*cptr) == theDegreeSign)) + { + *cptr = ' '; + } + else + { + status = false; + ++cptr; + } + } + + } // end switch + + if (status == false) + { + break; + } + + } // end while loop + + // add any units that may have been calculated (minutes or seconds) + degrees = degrees + units; + + theDegrees = (degrees * (double)theSign); + + return status; +} + +ossimString ossimDms::toString(const ossimString& formatString)const +{ + ossimString result=""; + ossimString::const_iterator stringIter; + ossimString tempFormatString = formatString; + if(formatString == ossimString("")) + { + tempFormatString = ossimDms::DEFAULT_FORMAT; + } + + stringIter = tempFormatString.begin(); + int i, d_s; + +/* assign a default format if none is given */ + + init_values(theDegrees); + + while(stringIter != tempFormatString.end()) + { + switch(*stringIter) + { + case '-': + { + result +=(theWorking < 0.0) ? ('-') : (' '); + stringIter++; + break; + } + + case 'c': + case 'C': + { + char temp; + if (theWorking < 0.0) + { + temp = (theLatFlag == true) ? ('S') : ('W'); + } + else + { + temp= (theLatFlag == true) ? ('N') : ('E'); + } + + if(*stringIter == 'c') + { + temp = tolower(temp); + } + result += temp; + stringIter++; + break; + } + + case 'd': + case 'D': { /* how many 'd's until not 'd' */ + d_s = 1, stringIter++; + while (*stringIter == 'd' || *stringIter == 'D') + { + d_s++, stringIter++; + } + if (theAfterDot == true) + { /* beyond the decimal point */ + i = d_s; + while (i-- > 0) + { + theDecDegs = theDecDegs * 10.0; + } +// theIntDegs = (int)(theDecDegs + 0.5); + theIntDegs = (int)(theDecDegs); + } + + // fill the rest with blanks + ossimString temp = ossimString::toString(theIntDegs); + d_s -= temp.length(); + if(d_s>0) + { + if(theAfterDot) + { + + while(d_s > 0) + { + temp+='0'; + --d_s; + } + } + else + { + ossimString prefix; + while(d_s > 0) + { + prefix += '0'; + --d_s; + } + temp = prefix + temp; + } + } + result += temp; + + break; + } + + case ' ': + { + result += *stringIter; + + while (*stringIter == ' ') + { + result += *stringIter; + stringIter++; + } + break; + } + + case '.': + { + theAfterDot = true; + result += *stringIter++; + break; + } + + case 'm': + case 'M': + case 's': + case 'S': + { + if((*stringIter == 's') || + (*stringIter == 'S')) + { + theDoingSeconds = true; + } + + calc_mins_or_secs(&theDecDegs, stringIter, result); + break; + } + + // This is code that I added so you can do additional + // formatting. + // + case '\'': + case '"': + { + result += *stringIter++; + break; + } + case '@': + { + result += (char)theDegreeSign; + stringIter++; + break; + } + default: + { + if(theDoingSeconds) + { + theAfterDot = true; + } + result += *stringIter++; + } + } /* end switch statement */ + } /* end while loop */ + + return result; +} + +// The functions that follow are all dts stuff + +ossimString ossimDms::degree_to_string(double degrees, + char format[], + bool lat_flag)const +{ + char cdegrees[64]; + char str_fmt[10]; + char *rptr, *fptr, *sptr; + int i, d_s; + +/* assign a default format if none is given */ + + if (format[0] == '\0') + { + set_default(format, cdegrees); + } + else + { + memset(cdegrees, ' ', 64); +// strcpy(cdegrees, SPACES); + } + + init_values(degrees); + + rptr = cdegrees; + fptr = format; + sptr = str_fmt; + +/* cycle through characters of the format and plug in values */ + + while (*fptr != '\0') { + + switch (*fptr) { + + case '-': { + (theWorking < 0.0) ? (*rptr = '-') : (*rptr = ' '); + rptr++, fptr++; + break; + } + + case 'c': + case 'C': { + if (theWorking < 0.0) + (lat_flag == true) ? (*rptr = 'S') : (*rptr = 'W'); + else + (lat_flag == true) ? (*rptr = 'N') : (*rptr = 'E'); + + rptr++, fptr++; + break; + } + + case 'd': + case 'D': { /* how many 'd's until not 'd' */ + d_s = 1, fptr++; + while (*fptr == 'd') { + d_s++, fptr++; + } + setup_printf(d_s, sptr); /* printf's fmt will be %x.xd */ + + if (theAfterDot == true) { /* beyond the decimal point */ + i = d_s; + while (i-- > 0) + theDecDegs = theDecDegs * 10.0; +// theIntDegs = (int)(theDecDegs + 0.5); + theIntDegs = (int)(theDecDegs); + } + + sprintf(rptr, str_fmt, theIntDegs); + + if (*rptr == '0' && !theAfterDot) /* remove leading zero */ + *rptr = ' '; + rptr += d_s; + break; + } + + case ' ': { /* compress multiple spaces in format */ + *rptr = *fptr; + while (*fptr == ' ') + fptr++; + rptr++; + break; + } + + case '.': { + if (theAfterDot == true) { /* a second decimal point? */ + set_default(format, cdegrees); + fptr = format; + rptr = cdegrees; + init_values(degrees); + } + else { + *rptr = *fptr; + rptr++, fptr++; + theAfterDot = true; + } + break; + } + + case 'm': + case 'M': + case 's': + case 'S': + { + i = calc_mins_or_secs(&theDecDegs, fptr, rptr); + fptr += i, rptr += i; /* i == num to advance format */ + break; + } + + // This is code that I added so you can do additional + // formatting. + // + case '\'': + case '"': + { + *rptr = *fptr; + rptr++; + fptr++; + break; + } + case '@': + { + *rptr = (char)theDegreeSign; + rptr++; + fptr++; + break; + } + default: { + set_default(format, cdegrees); + fptr = format; + rptr = cdegrees; + init_values(degrees); + } + } /* end switch statement */ + + } /* end while loop */ + + *rptr = '\0'; + return(cdegrees); +} + + +void ossimDms::calc_mins_or_secs(double *dd, + ossimString::const_iterator &formatIter, + ossimString &result)const +{ + double du; + int ufactor, ires, numunits; + char unit; + + unit = *formatIter; /* set to 'm' or 's' */ + + ufactor = 1, numunits = 0; + +/* count minutes (or seconds) desired in this part of format */ + + while (*formatIter == unit) + { + numunits++; + formatIter++, ufactor *= 10; + } + +/* different calc based on beyond decimal pt or not */ + + if (theAfterDot == true) + { + du = *dd * (double)ufactor; +// ires = (int)(du + 0.5); + ires = (int)(du); + *dd = (du - ires); + if(*dd < 0.0) *dd = 0.0; + } + else + { + du = (*dd * 60.0) * (double)ufactor; +// ires = (int)(du + 0.5) / ufactor; + ires = (int)(du) / ufactor; + *dd = (du - (ires * ufactor)) / (double)ufactor; + if(*dd < 0.0) *dd = 0.0; + } + ostringstream out; + + out << setw(numunits) + << setfill('0') + << setiosflags(ios::right) + << setprecision(numunits) + << ires + << ends; + result+=out.str().c_str(); + + +// result += ossimString::toString(ires); +} + +/**************************************************************** + * integer function calc_mins_or_secs * + * calculates minutes from degrees, seconds from minutes, * + * based on "format", returning the resultant string * + * in "res". "dd" is the part of 'degrees' that provides * + * the value to manipulate. the integer returned as the * + * value of this function is the number of places in the * + * format that have been parsed here, to be used in the * + * main function to advance the format-parsing pointer. * + ****************************************************************/ + + +int ossimDms::calc_mins_or_secs(double *dd, + char *format, + char *res)const +{ + double du; + int ufactor, ires, numunits; + char unit, str_fmt[8]; + + unit = *format; /* set to 'm' or 's' */ + + ufactor = 1, numunits = 0; + +/* count minutes (or seconds) desired in this part of format */ + + while (*format == unit) { + numunits++; + format++, ufactor *= 10; + } + +/* different calc based on beyond decimal pt or not */ + + if (theAfterDot == true) { + du = *dd * (double)ufactor; +// ires = (int)(du + 0.5); + ires = (int)(du + 0.5); + *dd = (du - ires); + } + else { + du = (*dd * 60.0) * (double)ufactor; +// ires = (int)(du + 0.5) / ufactor; + ires = (int)(du) / ufactor; + *dd = (du - (ires * ufactor)) / (double)ufactor; + } + setup_printf(numunits, str_fmt); + sprintf(res, str_fmt, ires); + + return(numunits); +} + +/**************************************************************** + * function setup_printf * + * the C library function sprintf takes as its second * + * argument, a format specifier. this function constructs * + * that specifier based on 'ival', an integer indicating * + * the number of d's or m's or s's seen in the group * + * just parsed. * + ****************************************************************/ + +void ossimDms::setup_printf(int ival, char *fmt)const +{ + char precis[3]; + + strcpy(fmt, "%"); + sprintf(precis, "%d", ival); + strcat(fmt,precis); + strcat(fmt,"."); + strcat(fmt,precis); + strcat(fmt,"d"); +} + +/**************************************************************** + * function set_default * + * assigns a default format to be used as the template for * + * the conversion of the double precision value, degrees. * + * either an error was detected in parsing the format that * + * the user entered, or no format was entered at all. * + * also, clears the result string of any characters which * + * may have been placed therein prior to the call here. * + ****************************************************************/ + + +void ossimDms::set_default(char *fp, char *rp)const +{ + strcpy(fp, DEFAULT_FORMAT); /* assign default format */ + strcpy(rp, SPACES); + +} + +/**************************************************************** + * function init_values * + * initializes the global values used throughout the * + * function. see notes in header file. * + ****************************************************************/ + +void ossimDms::init_values(double d)const +{ + + theAfterDot = false; + theDoingSeconds = false; + theSign = 1; + if (d < 0.0) + theSign = -1; + + theWorking = d; + theIntDegs = (int)theWorking * theSign; + theDecDegs = (theWorking * theSign) - theIntDegs; + + return; +} + + +/************************************************************************ + * double function string_to_degree * + * * + * requires: dts.h * + * input: string variable parameter * + * returns: double precision number * + * * + * purpose: to calculate a double precision number, representing * + * degrees latitude or longitude, given a string "cdegrees". * + * valid input consists of the following characters: * + * * + * +, -, N, n, S, s, E, e, W, w -- direction indicators * + * any digit [0-9] * + * a decimal point, '.' -- says decimal degrees follow * + * an ascii delimiter, for example ' ', TAB, '/' to * + * indicate that either minutes or seconds follow. * + * * + * output is a double precision number, which will be either * + * latitude or longitude degrees and decimal degrees * + * * + * written as part of the DIAL facility, G&G, WHOI * + * April 1992 * + * Christine L. Hammond * + ************************************************************************/ + + + +double ossimDms::string_to_degree(char *cdegrees) +{ + double degrees, factor, dividend, units; + int i; + bool afterdelim; + char *cptr, c; + + theAfterDot = false; + afterdelim = false; + cptr = cdegrees; + degrees = 0.0; + units = 0.0; + factor = 1.0; + dividend = 60.0; + theSign = 1; + +/* get rid of leading spaces */ + + while (*cptr == ' ') + cptr++; + + while(*cptr != '\0') { + + switch (*cptr) { + +/* north, west and + values will change sign of degrees to plus */ + + case '+': + case 'n': + case 'N': + case 'e': + case 'E': + { + if(toupper(*cptr) == 'N') + { + theLatFlag = true; + } + else if(toupper(*cptr) == 'E') + { + theLatFlag = false; + } + theSign = 1; + cptr++; + break; + } + +/* south, east and - values will change sign of degrees to minus */ + + case '-': + case 's': + case 'S': + case 'w': + case 'W': + { + if(toupper(*cptr) == 'S') + { + theLatFlag = true; + } + else if(toupper(*cptr) == 'W') + { + theLatFlag = false; + } + theSign = -1; + cptr++; + break; + } + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + c = *cptr; + i = (c - '0'); + + if (afterdelim == true) { + + if (theAfterDot == true) + units = units + (((double)i * factor) / dividend); + else + units = (units * factor) + ((double)i / dividend); + } + else { + + if (theAfterDot == true) + degrees = degrees + ((double)i * factor); + else + degrees = (degrees * factor) + (double)i; + } + + if (theAfterDot == true) + factor = factor * .10; + else + factor = 10.; + + cptr++; + break; + } + +/* a decimal point indicates a change in the factor used */ +/* to calculate degrees or units (minutes or seconds) */ + + case '.': + { + factor = .10; + theAfterDot = true; + cptr++; + break; + } + +/* after a delimiter the value contains minutes, first time through */ + + case ' ': { + + while (*(cptr + 1) == ' ') + cptr++; + + degrees = degrees + units; + units = 0.0; + + if (afterdelim == true) /* must be seconds */ + dividend = dividend * dividend; + else + afterdelim = true; + + factor = 1.; + + cptr++; + +/* skip any leading zeroes after delimiter */ + + while (*cptr == '0') + cptr++; + + break; + } + +/* check for a delimiter that is allowable: + isspace allows: space, tab, cr, nl, vt, ff + ispunct allows: punctuation char != space or control or letter */ + + default: { + if (isspace(*cptr) || ispunct(*cptr)) + *cptr = ' '; + } + + } /* end switch */ + + } /* end while loop */ + +/* add any units that may have been calculated (minutes or seconds) */ + + degrees = degrees + units; + + return(degrees * (double)theSign); +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimDms.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimDms.h new file mode 100644 index 0000000000..111f036812 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimDms.h @@ -0,0 +1,209 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +// Contains class definition for Degrees Minutes Seconds (ossimDms) +//******************************************************************* +// $Id: ossimDms.h,v 1.12 2005/07/18 11:06:00 gpotts Exp $ +#ifndef ossimDms_HEADER +#define ossimDms_HEADER +#include <iostream> +using namespace std; + +#include <base/data_types/ossimString.h> + +class OSSIMDLLEXPORT ossimDms +{ +public: + friend ostream& operator << (ostream& out, const ossimDms &dms); + + + /*! + * + * Constructor ossimDms(double, bool) + * + * You can construct a DMS class with a decimal + * degree and specify if its for the lat or lon. + * + * latFlag true its for the lat + * false its for the lon + * + */ + ossimDms(double someDegrees, bool latFlag = true); + + /*! + *` Constructor. You can specify the value in a formated + * string. Example: + * "45N" will set the decimal degree to 45 and will + * set the lat flag to true + * + * "45W" will set the internal degree to negative and + * set the lat flag to false. + */ + ossimDms(char *value); + + /*! + * You can specify a number of different formats. + * special characters: + * + * @ is replaced with a degree character. + * ' minutes character + * " seconds character + * d replaced with degree portion + * m replaced with minute portion + * s replaced with second portion + * c or C replaces with N/S or E/W + * + * examples for format string + * + * + */ + ossimString toString(const ossimString& formatString=ossimString(""))const; + + double getDegrees() const { return theDegrees; } + bool getLatFlag() const { return theLatFlag; } + + /*! + * setDegrees(char*). Will allow you to set the internal + * paramters through a string. examples: + * + * "45 5 6" will assume degrees minutes seconds + * "45" will assume degrees. + * "-45" + * "4e5W" + * + * @return true on success, false if unhandled characters are found. + */ + bool setDegrees(const char *value); + + ossimDms& setDegrees(double degrees); + + ossimDms& setLatFlag(bool latFlag){theLatFlag = latFlag;return *this;} + static const ossim_uint8 theDegreeSign; + +private: + static char *DEFAULT_FORMAT; + static char *SPACES; + + double theDegrees; + bool theLatFlag; + + // This is a port of the dts written by Christine Hammond + // into the OSSIM dms class. We will use this to aid in + // formatting DMS data. + mutable double theDecDegs;/* decimal part of degrees */ + mutable bool theAfterDot;/* decimal values flag */ + mutable bool theDoingSeconds; + mutable int theIntDegs;/* integer part of double degrees */ + mutable int theSign;/* what sign is degrees */ + mutable double theWorking;/* degrees value to use during calc */ + + /*! + * char * function degree_to_string + * + * requires: dts.h + * input: double precision, string, integer params + * returns: pointer to a string + * + * purpose: to convert a double precision number "degrees" + * to a character string based on the input "format" and a + * flag indicating whether or not the degrees are latitude. + * If 'lat_flag' is TRUE, then degrees are latitude, otherwise + * they are longitude. default format: ddd mm.mmC + * + * returns: a pointer to a string which contains the formatted + * degree value. + * + * written as part of the DIAL facility, G&G, WHOI + * April 1992 + * Christine L. Hammond + ************************************************************************/ + + ossimString degree_to_string(double degrees, + char format[], + bool lat_flag)const; + + void calc_mins_or_secs(double *dd, + ossimString::const_iterator &formatIter, + ossimString &result)const; + /*! + * integer function calc_mins_or_secs * + * calculates minutes from degrees, seconds from minutes, + * based on "format", returning the resultant string + * in "res". "dd" is the part of 'degrees' that provides + * the value to manipulate. the integer returned as the + * value of this function is the number of places in the + * format that have been parsed here, to be used in the + * main function to advance the format-parsing pointer. + */ + + int calc_mins_or_secs(double *dd, + char *format, + char *res)const; + + /*! + * function setup_printf + * the C library function sprintf takes as its second + * argument, a format specifier. this function constructs + * that specifier based on 'ival', an integer indicating + * the number of d's or m's or s's seen in the group + * just parsed. + */ + void setup_printf(int ival, char *fmt)const; + + /*! + * function set_default * + * assigns a default format to be used as the template for + * the conversion of the double precision value, degrees. + * either an error was detected in parsing the format that + * the user entered, or no format was entered at all. + * also, clears the result string of any characters which + * may have been placed therein prior to the call here. + */ + void set_default(char *fp, char *rp)const; + + /*! + * function init_values + * initializes the global values used throughout the + * function. see notes in header file. + */ + void init_values(double d)const; + + /*! + * double function string_to_degree + * + * requires: dts.h + * input: string variable parameter + * returns: double precision number + * + * purpose: to calculate a double precision number, representing + * degrees latitude or longitude, given a string "cdegrees". + * valid input consists of the following characters: + * + * +, -, N, n, S, s, E, e, W, w -- direction indicators + * any digit [0-9] + * a decimal point, '.' -- says decimal degrees follow + * an ascii delimiter, for example ' ', TAB, '/' to + * indicate that either minutes or seconds follow. + * + * output is a double precision number, which will be either + * latitude or longitude degrees and decimal degree + * + * written as part of the DIAL facility, G&G, WHOI + * April 1992 + * Christine L. Hammond + */ + + + double string_to_degree(char *cdegrees); + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimDpt.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimDpt.cpp new file mode 100644 index 0000000000..a87ef83259 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimDpt.cpp @@ -0,0 +1,232 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: David Burken +// +// Description: +// Contains class definitions for ossimDpt. +// +//******************************************************************* +// $Id: ossimDpt.cpp,v 1.7 2005/12/16 14:25:11 dburken Exp $ + +#include <iostream> +#include <iomanip> +#include <sstream> + +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimDpt3d.h> +#include <base/data_types/ossimIpt.h> +#include <base/data_types/ossimFpt.h> +#include <base/data_types/ossimGpt.h> +#include <base/data_types/ossimString.h> + + +//******************************************************************* +// Public Constructor: +//******************************************************************* +ossimDpt::ossimDpt(const ossimFpt& pt) + : + x(pt.x), y(pt.y) +{ + if(pt.hasNans()) + { + makeNan(); + } + } + +//******************************************************************* +// Public Constructor: +//******************************************************************* +ossimDpt::ossimDpt(const ossimIpt& pt) + : + x(pt.x), y(pt.y) +{ + if(pt.hasNans()) + { + makeNan(); + } +} + +//******************************************************************* +// Public Constructor: +//******************************************************************* +ossimDpt::ossimDpt(const ossimDpt3d &pt) + : + x(pt.x), y(pt.y) +{ + if(pt.hasNans()) + { + makeNan(); + } +} + +//******************************************************************* +// Public Constructor: +//******************************************************************* +ossimDpt::ossimDpt(const ossimGpt &pt) + : + x(pt.lon), y(pt.lat) +{ + if(pt.isLatNan() || pt.isLonNan()) + { + makeNan(); + } +} + +//******************************************************************* +// Public Method: +//******************************************************************* +const ossimDpt& ossimDpt::operator=(const ossimFpt& pt) +{ + x = pt.x; + y = pt.y; + + if(pt.hasNans()) + { + makeNan(); + } + return *this; +} + +//******************************************************************* +// Public Method: +//******************************************************************* +const ossimDpt& ossimDpt::operator=(const ossimIpt& pt) +{ + x = pt.x; + y = pt.y; + if(pt.hasNans()) + { + makeNan(); + } + + return *this; +} + +//******************************************************************* +// Public Method: +//******************************************************************* +const ossimDpt& ossimDpt::operator=(const ossimDpt3d& pt) +{ + x = pt.x; + y = pt.y; + + if(pt.hasNans()) + { + makeNan(); + } + + return *this; +} + +const ossimDpt& ossimDpt::operator=(const ossimGpt& pt) +{ + x = pt.lon; + y = pt.lat; + return *this; +} + +std::ostream& ossimDpt::print(std::ostream& os, ossim_uint32 precision) const +{ + os << std::setiosflags(std::ios::fixed) << std::setprecision(precision) + << "( "; + + if (x != OSSIM_DBL_NAN) + { + os << x; + } + else + { + os << "nan"; + } + + os << ", "; + + if (y != OSSIM_DBL_NAN) + { + os << y; + } + else + { + os << "nan"; + } + + os << " )"; + + return os; +} + +std::ostream& operator<<(std::ostream& os, const ossimDpt& pt) +{ + return pt.print(os); +} + +ossimString ossimDpt::toString(ossim_uint32 precision) const +{ + std::ostringstream os; + print(os, precision); + return ossimString(os.str()); +} + +std::istream& operator>>(std::istream& is, ossimDpt &pt) +{ + //--- + // Expected input format: + // ( 30.00000000000000, -90.00000000000000 ) + // --------x-------- ---------y-------- + //--- + + // Start with a nan point. + pt.makeNan(); + + // Check the stream. + if (!is) return is; + + const int SZ = 64; // Real big number with 15 digit precision. + ossimString tempString; + char tempChars[SZ]; + char c; + + // Gobble the "(". + is >> tempString; + if (!is) return is; + + // Get the x. + is.get(tempChars, SZ, ','); + if (!is) return is; + tempChars[SZ-1] = '\0'; + tempString = tempChars; + tempString.trim(); + if (tempString == "nan") + { + pt.x = OSSIM_DBL_NAN; + } + else + { + pt.x = tempString.toDouble(); + } + + // Eat the ",". + is.get(c); + + // Get the y. + is >> tempString; + tempString.trim(); + if (tempString == "nan") + { + pt.y = OSSIM_DBL_NAN; + } + else + { + pt.y = tempString.toDouble(); + } + + // Gobble the trailing ")". + is >> tempString; + + // Finished + return is; +} + diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimDpt.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimDpt.h new file mode 100644 index 0000000000..b5d1a63347 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimDpt.h @@ -0,0 +1,153 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: David Burken +// +// Description: +// +// Contains class declaration for ossimDpt. +// Used to represent an double point containing an x and y data member. +// +//******************************************************************* +// $Id: ossimDpt.h,v 1.11 2005/12/16 14:25:11 dburken Exp $ +#ifndef ossimDpt_HEADER +#define ossimDpt_HEADER +#include <iostream> +#include <cmath> + +#include <base/common/ossimConstants.h> +#include <base/common/ossimCommon.h> + +// Forward class declarations. +class OSSIMDLLEXPORT ossimIpt; +class OSSIMDLLEXPORT ossimFpt; +class OSSIMDLLEXPORT ossimDpt3d; +class OSSIMDLLEXPORT ossimGpt; +class OSSIMDLLEXPORT ossimString; + +class OSSIMDLLEXPORT ossimDpt +{ +public: + + ossimDpt() : x(0), y(0) {} + + ossimDpt(double anX, double aY) : x(anX), y(aY) {} + + ossimDpt(const ossimDpt& pt) : x(pt.x), y(pt.y) {} + + ossimDpt(const ossimFpt& pt); + + ossimDpt(const ossimIpt& pt); + + ossimDpt(const ossimDpt3d &pt); + + ossimDpt(const ossimGpt &pt); // assigns lat, lon only + + const ossimDpt& operator=(const ossimDpt&); + + const ossimDpt& operator=(const ossimFpt&); + + const ossimDpt& operator=(const ossimIpt&); + + const ossimDpt& operator=(const ossimDpt3d&); + + const ossimDpt& operator=(const ossimGpt&); // assigns lat, lon only + + bool operator==(const ossimDpt& pt) const + { return ( (x == pt.x) && (y == pt.y) ); } + + bool operator!=(const ossimDpt& pt) const + { return ( (x != pt.x) || (y != pt.y) ); } + + void makeNan(){x = OSSIM_DBL_NAN; y=OSSIM_DBL_NAN;} + + bool hasNans()const + { + return (ossimIsNan(x) || ossimIsNan(y)); + } + + bool isNan()const + { + return (ossimIsNan(x) && ossimIsNan(y)); + } + /*! + * METHOD: length() + * Returns the RSS of the components. + */ + double length() const { return sqrt(x*x + y*y); } + + //*** + // OPERATORS: +, -, +=, -= + // Point add/subtract with other point: + //*** + ossimDpt operator+(const ossimDpt& p) const + { return ossimDpt(x+p.x, y+p.y); } + ossimDpt operator-(const ossimDpt& p) const + { return ossimDpt(x-p.x, y-p.y); } + const ossimDpt& operator+=(const ossimDpt& p) + { x += p.x; y += p.y; return *this; } + const ossimDpt& operator-=(const ossimDpt& p) + { x -= p.x; y -= p.y; return *this; } + + //*** + // OPERATORS: *, / + // Scale point components by scalar: + //*** + ossimDpt operator*(const double& d) const + { return ossimDpt(d*x, d*y); } + ossimDpt operator/(const double& d) const + { return ossimDpt(x/d, y/d); } + + std::ostream& print(std::ostream& os, ossim_uint32 precision=15) const; + + friend OSSIMDLLEXPORT std::ostream& operator<<(std::ostream& os, + const ossimDpt& pt); + + /** + * @param precision Output floating point precision. + * + * @return ossimString representing point. + * + * Output format: ( 30.00000000000000, -90.00000000000000 ) + * --------x-------- ---------y-------- + */ + ossimString toString(ossim_uint32 precision=15) const; + + /** + * Method to input the formatted string of the "operator<<". + * + * Expected format: ( 30.00000000000000, -90.00000000000000 ) + * --------x-------- ---------y-------- + * + * This method starts by doing a "makeNan" on pt. So if anything goes + * wrong with the stream or parsing pt could be all or partially nan. + * + * @param is Input stream istream to formatted text. + * @param pt osimDpt to be initialized from stream. + * @return istream pass in. + */ + friend OSSIMDLLEXPORT std::istream& operator>>(std::istream& is, + ossimDpt& pt); + + //*** + // Public data members: + //*** + union {double x; double samp; double u; double lon;}; + union {double y; double line; double v; double lat;}; + +}; + +inline const ossimDpt& ossimDpt::operator=(const ossimDpt& pt) +{ + if (this != &pt) + { + x = pt.x; + y = pt.y; + } + + return *this; +} + +#endif /* #ifndef ossimDpt_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimDpt3d.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimDpt3d.cpp new file mode 100644 index 0000000000..1b024e6571 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimDpt3d.cpp @@ -0,0 +1,26 @@ +#include "ossimDpt3d.h" +#include "ossimIpt.h" +#include "ossimDpt.h" + + +ossimDpt3d::ossimDpt3d(const ossimDpt &aPt) + :x(aPt.x), + y(aPt.y), + z(0) +{ + if(aPt.isNan()) + { + makeNan(); + } +} + +ossimDpt3d::ossimDpt3d(const ossimIpt &aPt) + :x(aPt.x), + y(aPt.y), + z(0) +{ + if(aPt.isNan()) + { + makeNan(); + } +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimDpt3d.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimDpt3d.h new file mode 100644 index 0000000000..447a9e7863 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimDpt3d.h @@ -0,0 +1,113 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Contains class declaration for dpt3d +// Used to represent a 3d double point containing an x, y and z data member. +//******************************************************************* +// $Id: ossimDpt3d.h,v 1.5 2002/11/25 18:59:54 gpotts Exp $ + +#ifndef ossimDpt3d_HEADER +#define ossimDpt3d_HEADER +#include <iostream> +#include <iomanip> +#include <math.h> + +#include "ossimString.h" +#include "ossimDpt.h" +#include "ossimColumnVector3d.h" + +class OSSIMDLLEXPORT ossimDpt3d +{ +public: + friend inline std::ostream & operator << (std::ostream &out, const ossimDpt3d &rhs); + ossimDpt3d(const double &aX=0, const double &aY=0, const double &aZ=0) + :x(aX), y(aY), z(aZ) {} + + ossimDpt3d(const ossimDpt &aPt); + ossimDpt3d(const ossimIpt &aPt); + + ossimDpt3d(const ossimColumnVector3d &pt) + : x(pt[0]), y(pt[1]), z(pt[2]) {} + + bool operator ==(const ossimDpt3d &rhs) const + { + return ( (x == rhs.x) && + (y == rhs.y) && + (z == rhs.z)); + } + bool operator !=(const ossimDpt3d &rhs) const + { + return ( (x != rhs.x) || + (y != rhs.y) || + (z != rhs.z) ); + } + + void makeNan(){x = OSSIM_DBL_NAN; y=OSSIM_DBL_NAN; z=OSSIM_DBL_NAN;} + + bool hasNans()const + { + return (ossimIsNan(x) || ossimIsNan(y) || ossimIsNan(z)); + } + /*! + * METHOD: length() + * Returns the RSS of the components. + */ + double length() const { return sqrt(x*x + y*y + z*z); } + + //*** + // OPERATORS: +, -, +=, -= + // Point add/subtract with other point: + //*** + ossimDpt3d operator+(const ossimDpt3d& p) const + { return ossimDpt3d(x+p.x, y+p.y, z+p.z); } + ossimDpt3d operator-(const ossimDpt3d& p) const + { return ossimDpt3d(x-p.x, y-p.y, z-p.z); } + const ossimDpt3d& operator+=(const ossimDpt3d& p) + { x += p.x; y += p.y; z += p.z; return *this; } + const ossimDpt3d& operator-=(const ossimDpt3d& p) + { x -= p.x; y -= p.y; z -= p.z; return *this; } + + //*** + // OPERATORS: *, / + // Scale point components by scalar: + //*** + ossimDpt3d operator*(const double& d) const + { return ossimDpt3d(d*x, d*y, d*z); } + ossimDpt3d operator/(const double& d) const + { return ossimDpt3d(x/d, y/d, z/d); } + + double x; + double y; + double z; +}; + +inline std::ostream &operator << (std::ostream &out, const ossimDpt3d &rhs) +{ + return out << std::setiosflags(std::ios::fixed) + << std::setprecision(15) + << (rhs.x==OSSIM_DBL_NAN?ossimString("nan"):ossimString::toString(rhs.x)) + << " " + << (rhs.y==OSSIM_DBL_NAN?ossimString("nan"):ossimString::toString(rhs.y)) + << " " + << (rhs.z ==OSSIM_DBL_NAN?ossimString("nan"):ossimString::toString(rhs.z))<< endl; +} +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimDrect.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimDrect.cpp new file mode 100644 index 0000000000..9a167d7377 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimDrect.cpp @@ -0,0 +1,736 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class definition for ossimDrect. +//******************************************************************* +// $Id: ossimDrect.cpp,v 1.34 2005/07/15 18:51:25 dburken Exp $ + +#include <iostream> +using namespace std; + +#include "ossimDrect.h" +#include "ossimIrect.h" +#include "ossimPolygon.h" + +#define d_MIN(a,b) (((a)<(b)) ? a : b) +#define d_MAX(a,b) (((a)>(b)) ? a : b) + +static int +clip_1d (double *x0, + double *y0, + double *x1, + double *y1, + double maxdim) +{ + double m; /* gradient of line */ + if (*x0 < 0) + { /* start of line is left of window */ + if (*x1 < 0) /* as is the end, so the line never cuts the window */ + return 0; + m = (*y1 - *y0) / (double) (*x1 - *x0); /* calculate the slope of the line */ + /* adjust x0 to be on the left boundary (ie to be zero), and y0 to match */ + *y0 -= m * *x0; + *x0 = 0; + /* now, perhaps, adjust the far end of the line as well */ + if (*x1 > maxdim) + { + *y1 += m * (maxdim - *x1); + *x1 = maxdim; + } + return 1; + } + if (*x0 > maxdim) + { /* start of line is right of window - + complement of above */ + if (*x1 > maxdim) /* as is the end, so the line misses the window */ + return 0; + m = (*y1 - *y0) / (double) (*x1 - *x0); /* calculate the slope of the line */ + *y0 += m * (maxdim - *x0); /* adjust so point is on the right + boundary */ + *x0 = maxdim; + /* now, perhaps, adjust the end of the line */ + if (*x1 < 0) + { + *y1 -= m * *x1; + *x1 = 0; + } + return 1; + } + /* the final case - the start of the line is inside the window */ + if (*x1 > maxdim) + { /* other end is outside to the right */ + m = (*y1 - *y0) / (double) (*x1 - *x0); /* calculate the slope of the line */ + *y1 += m * (maxdim - *x1); + *x1 = maxdim; + return 1; + } + if (*x1 < 0) + { /* other end is outside to the left */ + m = (*y1 - *y0) / (double) (*x1 - *x0); /* calculate the slope of the line */ + *y1 -= m * *x1; + *x1 = 0; + return 1; + } + /* only get here if both points are inside the window */ + return 1; +} + +//******************************************************************* +// Public Constructor: ossimDrect +// +//******************************************************************* +ossimDrect::ossimDrect(const ossimIrect& rect) + : + theUlCorner(rect.ul()), + theUrCorner(rect.ur()), + theLrCorner(rect.lr()), + theLlCorner(rect.ll()), + theOrientMode(rect.orientMode()) +{ + if(rect.isNan()) + { + makeNan(); + } +} + + +//***************************************************************************** +// CONSTRUCTOR: ossimDrect(const vector<ossimDpt>& points) +// +//***************************************************************************** +ossimDrect::ossimDrect(const ossimPolygon& polygon, + ossimCoordSysOrientMode mode) + : + theOrientMode (mode) +{ + vector<ossimDpt> vertices; + ossimDpt point; + int index = 0; + while (polygon.vertex(index, point)) + { + vertices.push_back(point); + index++; + } + + initBoundingRect(vertices); +} + +//***************************************************************************** +// CONSTRUCTOR: ossimDrect(const vector<ossimDpt>& points) +// +//***************************************************************************** +ossimDrect::ossimDrect(const vector<ossimDpt>& points, + ossimCoordSysOrientMode mode) + : + theOrientMode (mode) +{ + if(points.size()) + { + unsigned long index; + double minx, miny; + double maxx, maxy; + + minx = points[0].x; + miny = points[0].y; + maxx = points[0].x; + maxy = points[0].y; + + // find the bounds + for(index = 1; index < points.size();index++) + { + + minx = std::min(minx, points[index].x); + miny = std::min(miny, points[index].y); + maxx = std::max(maxx, points[index].x); + maxy = std::max(maxy, points[index].y); + + } + if(theOrientMode == OSSIM_LEFT_HANDED) + { + *this = ossimDrect(minx, miny, maxx, maxy, mode); + } + else + { + *this = ossimDrect(minx,maxy, maxx, miny, mode); + } + } + else + { + makeNan(); + } +} +ossimDrect::ossimDrect(const ossimDpt& p1, + const ossimDpt& p2, + const ossimDpt& p3, + const ossimDpt& p4, + ossimCoordSysOrientMode mode) +{ + if(p1.hasNans()||p2.hasNans()||p3.hasNans()||p4.hasNans()) + { + makeNan(); + } + else + { + double minx, miny; + double maxx, maxy; + + minx = std::min( p1.x, std::min(p2.x, std::min(p3.x, p4.x))); + miny = std::min( p1.y, std::min(p2.y, std::min(p3.y, p4.y))); + maxx = std::max( p1.x, std::max(p2.x, std::max(p3.x, p4.x))); + maxy = std::max( p1.y, std::max(p2.y, std::max(p3.y, p4.y))); + + if(mode == OSSIM_LEFT_HANDED) + { + *this = ossimDrect(minx, miny, maxx, maxy, mode); + } + else + { + *this = ossimDrect(minx,maxy, maxx, miny, mode); + } + } +} + +ossimDrect::~ossimDrect() +{ +} + +void ossimDrect::initBoundingRect(const vector<ossimDpt>& points) +{ + unsigned long index; + + // initialize everyone to the first point + if(points.size() > 0) + { + theUlCorner.x = points[0].x; + theUlCorner.y = points[0].y; + theLrCorner.x = theUlCorner.x; + theLrCorner.y = theUlCorner.y; + } + + // find the bounds + for(index = 1; index < points.size();index++) + { + // find left most + if(points[index].x < theUlCorner.x) + theUlCorner.x = points[index].x; + + // find right most + else if(points[index].x > theLrCorner.x) + theLrCorner.x = points[index].x; + + if (theOrientMode == OSSIM_LEFT_HANDED) + { + //find top most + if(points[index].y < theUlCorner.y) + theUlCorner.y = points[index].y; + + // find bottom most + else if(points[index].y > theLrCorner.y) + theLrCorner.y = points[index].y; + } + + else // right handed coord system + { + if(points[index].y > theUlCorner.y) + theUlCorner.y = points[index].y; + + // find bottom most + else if(points[index].y < theLrCorner.y) + theLrCorner.y = points[index].y; + } + } + + // now set the other points for the rect. + theUrCorner.x = theLrCorner.x; + theUrCorner.y = theUlCorner.y; + theLlCorner.x = theUlCorner.x; + theLlCorner.y = theLrCorner.y; +} + +//******************************************************************* +// Public Method: +//******************************************************************* +bool ossimDrect::intersects(const ossimDrect& rect) const +{ + if(rect.hasNans() || hasNans()) + { + return false; + } + if (theOrientMode != rect.theOrientMode) + return false; + + ossim_float64 ulx = d_MAX(rect.ul().x,ul().x); + ossim_float64 lrx = d_MIN(rect.lr().x,lr().x); + ossim_float64 uly, lry; + bool rtn; + + if (theOrientMode == OSSIM_LEFT_HANDED) + { + uly = d_MAX(rect.ul().y,ul().y); + lry = d_MIN(rect.lr().y,lr().y); + rtn = ((ulx <= lrx) && (uly <= lry)); + } + else + { + uly = d_MAX(rect.ul().y,ul().y); + lry = d_MIN(rect.lr().y,lr().y); + rtn = ((ulx <= lrx) && (uly >= lry)); + } + + return (rtn); +} + +//******************************************************************* +// Public Method: ossimDrect::completely_within +//******************************************************************* +bool ossimDrect::completely_within(const ossimDrect& rect) const +{ + if(hasNans() || rect.hasNans()) + { + return false; + } + if (theOrientMode != rect.theOrientMode) + return false; + + /* -------------- + | 1 | + | ---------- | + | | | | + | | | | + | | 2 | | + | | | | + | | | | + | ---------- | + | | + -------------- */ + + bool rtn = true; + + if (theUlCorner.x < rect.ul().x) + rtn = false; + + else if (theLrCorner.x > rect.lr().x) + rtn = false; + + else if (theOrientMode == OSSIM_LEFT_HANDED) + { + if (theUlCorner.y < rect.ul().y) + rtn = false; + + else if (theLrCorner.y > rect.lr().y) + rtn = false; + } + + else + { + if (theUlCorner.y > rect.ul().y) + rtn = false; + + else if (theLrCorner.y < rect.lr().y) + rtn = false; + } + + return rtn; +} + +//******************************************************************* +// Public Method: ossimDrect::stretchOut +//******************************************************************* +void ossimDrect::stretchOut() +{ + set_ulx(floor(theUlCorner.x)); + set_lrx(ceil(theLrCorner.x)); + + if (theOrientMode == OSSIM_LEFT_HANDED) + { + set_uly(floor(theUlCorner.y)); + set_lry(ceil(theLrCorner.y)); + } + else + { + set_uly(ceil(theUlCorner.y)); + set_lry(floor(theLrCorner.y)); + } +} + +void ossimDrect::stretchToTileBoundary(const ossimDpt& widthHeight) +{ + ossimDpt ul; + ossimDpt lr; + ossim_int32 evenDivision=0; + + if(theOrientMode == OSSIM_LEFT_HANDED) + { + ul.x = theUlCorner.x; + if( fmod(theUlCorner.x, widthHeight.x) != 0) + { + ul.x = ((long)(ul.x / widthHeight.x))*widthHeight.x; + if(ul.x > theUlCorner.x) + { + ul.x -= widthHeight.x; + } + } + ul.y = theUlCorner.y; + if( fmod(theUlCorner.y, widthHeight.y) != 0) + { + ul.y = ((long)(ul.y / widthHeight.y))*widthHeight.y; + if(ul.y > theUlCorner.y) + { + ul.y -= widthHeight.y; + } + } + + evenDivision = fmod(theLrCorner.x, widthHeight.x) == 0; + lr.x = theLrCorner.x; + if(!evenDivision) + { + lr.x = ((long)((lr.x)/widthHeight.x)) * widthHeight.x; + if(lr.x < theLrCorner.x) + { + lr.x += widthHeight.x; + } + } + + evenDivision = fmod(theLrCorner.y, widthHeight.y) == 0; + lr.y = theLrCorner.y; + if(!evenDivision) + { + lr.y = ((long)(lr.y/widthHeight.y)) * widthHeight.y; + if(lr.y < theLrCorner.y) + { + lr.y += widthHeight.y; + } + } + } + else + { + ul.x = theUlCorner.x; + ul.y = theUlCorner.y; + if( !equals(fmod(theUlCorner.x, widthHeight.x), 0.0)) + { + ul.x = ((long)(ul.x/ widthHeight.x))*widthHeight.x; + if(ul.x > theUlCorner.x) + { + ul.x -= widthHeight.x; + } + } + if( !equals((double)fmod(theUlCorner.y, widthHeight.y), (double)0.0) ) + { + ul.y = ((long)(ul.y / widthHeight.y))*widthHeight.y; + if(ul.y < theUlCorner.y) + { + ul.y += widthHeight.y; + } + } + + evenDivision = equals( fmod(theLrCorner.x, widthHeight.x), (double)0.0); + lr.x = theLrCorner.x; + if(!evenDivision) + { + lr.x = ((long)(lr.x/widthHeight.x)) * widthHeight.x; + if(lr.x < theLrCorner.x) + { + lr.x += widthHeight.x; + } + } + + evenDivision = equals(fmod(theLrCorner.y, widthHeight.y), 0); + lr.y = theLrCorner.y; + if(!evenDivision) + { + lr.y = ((long)(lr.y/widthHeight.y)) * widthHeight.y; + + if(lr.y > theLrCorner.y) + { + lr.y -= widthHeight.y; + } + } + } + + *this = ossimDrect(ul, lr, theOrientMode); +} + + + +//******************************************************************* +// Public Method: ossimDrect::print +//******************************************************************* +void ossimDrect::print(std::ostream& os) const +{ + os << (theOrientMode==OSSIM_LEFT_HANDED?"left handed: ":"right handed: ") << theUlCorner << theLrCorner; +} + +//******************************************************************* +// friend function: operator<< +//******************************************************************* +std::ostream& operator<<(std::ostream& os, const ossimDrect& rect) +{ + rect.print(os); + + return os; +} + +//******************************************************************* +// Public Method: ossimDrect::clip +//******************************************************************* +bool ossimDrect::clip(ossimDpt &p1, ossimDpt &p2)const +{ + if(p1.isNan() || p2.isNan()) + { + return false; + } + ossimDpt shift(-theUlCorner.x, + -theUlCorner.y); + + ossimDpt tempShiftP1 = p1+shift; + ossimDpt tempShiftP2 = p2+shift; + double maxW = width()-1; + double maxH = height()-1; + if (clip_1d (&tempShiftP1.x, &tempShiftP1.y, + &tempShiftP2.x, &tempShiftP2.y, + maxW) == 0) + { + return false; + } + if(clip_1d (&tempShiftP1.y, + &tempShiftP1.x, + &tempShiftP2.y, + &tempShiftP2.x, maxH) == 0) + { + return false; + } + p1 = tempShiftP1-shift; + p2 = tempShiftP2-shift; + return true; +// bool done = false; + +// long p1Code = getCode(p1, (*this)); +// long p2Code = getCode(p2, (*this)); +// long codeOut; + +// do{ + +// if((!p1Code) && (!p2Code)) +// { +// visible = true; +// done = true; +// } +// else if(p1Code&p2Code) +// { +// done = true; +// } +// else +// { +// if(p1Code) +// { +// codeOut = p1Code; +// } +// else +// { +// codeOut = p2Code; +// } + +// if(codeOut&TOP) // divide rect at the top +// { +// tempPt.x = p1.x + (p2.x - p1.x)* +// ((*this).ul().y - p1.y)/(p2.y - p1.y); +// tempPt.y = (*this).ul().y; +// } +// else if(codeOut&BOTTOM) +// { +// tempPt.x = p1.x + (p2.x - p1.x)* +// ((*this).lr().y - p1.y)/(p2.y - p1.y); +// tempPt.y = (*this).lr().y; +// } +// else if(codeOut&RIGHT) +// { +// tempPt.y = p1.y + (p2.y - p1.y)* +// ((*this).lr().x - p1.x)/(p2.x - p1.x); +// tempPt.x = (*this).lr().x; +// } +// else if(codeOut&LEFT) +// { +// tempPt.y = p1.y + (p2.y - p1.y)* +// ((*this).ul().x - p1.x)/(p2.x - p1.x); +// tempPt.x = (*this).ul().x; +// } +// if(codeOut == p1Code) +// { +// p1.x = tempPt.x; +// p1.y = tempPt.y; +// p1Code = getCode(p1, (*this)); +// } +// else +// { +// p2.x = tempPt.x; +// p2.y = tempPt.y; +// p2Code = getCode(p2, (*this)); +// } +// } +// }while(!done); +// return visible; +} + +//******************************************************************* +// Public Method: ossimDrect::getCode +//******************************************************************* +long ossimDrect::getCode(const ossimDpt& aPoint, + const ossimDrect& clipRect) +{ + long result=NONE; // initialize to inside rect + + if( (aPoint.x > clipRect.lr().x) ) + result |= RIGHT; + else if( (aPoint.x < clipRect.ul().x) ) + result |= LEFT; + + if (clipRect.theOrientMode == OSSIM_LEFT_HANDED) + { + if( (aPoint.y < clipRect.ul().y) ) + result |= TOP; + else if( (aPoint.y > clipRect.lr().y) ) + result |= BOTTOM; + } + else + { + if( (aPoint.y > clipRect.ul().y) ) + result |= TOP; + else if( (aPoint.y < clipRect.lr().y) ) + result |= BOTTOM; + } + + return result; +} + + +void ossimDrect::splitToQuad(ossimDrect& ulRect, + ossimDrect& urRect, + ossimDrect& lrRect, + ossimDrect& llRect) +{ + ossimDpt ulPt = this->ul(); + ossimDpt urPt = this->ur(); + ossimDpt lrPt = this->lr(); + ossimDpt llPt = this->ll(); + ossimIpt midPt = this->midPoint(); + + ulRect = ossimDrect(ulPt.x, + ulPt.y, + midPt.x, + midPt.y, + theOrientMode); + + urRect = ossimDrect(midPt.x+DBL_EPSILON, + ulPt.y, + urPt.x, + midPt.y, + theOrientMode); + + if(theOrientMode == OSSIM_LEFT_HANDED) + { + lrRect = ossimDrect(midPt.x+DBL_EPSILON, + midPt.y+DBL_EPSILON, + lrPt.x, + theOrientMode); + } + else + { + lrRect = ossimDrect(midPt.x+DBL_EPSILON, + midPt.y-DBL_EPSILON, + lrPt.x, + theOrientMode); + } + + if(theOrientMode == OSSIM_LEFT_HANDED) + { + llRect = ossimDrect(ulPt.x, + midPt.y+DBL_EPSILON, + midPt.x, + llPt.y, + theOrientMode); + } + else + { + llRect = ossimDrect(ulPt.x, + midPt.y-DBL_EPSILON, + midPt.x, + llPt.y, + theOrientMode); + } +} + +//******************************************************************* +// Public Method: ossimDrect::clipToRect +//******************************************************************* +ossimDrect ossimDrect::clipToRect(const ossimDrect& rect)const +{ + if(rect.hasNans() || hasNans()) + { + ossimDrect result; + result.makeNan(); + + return result; + } + + if (theOrientMode != rect.theOrientMode) + return (*this); + + double x0 = d_MAX(rect.ul().x, ul().x); + double x1 = d_MIN(rect.lr().x, lr().x); + double y0, y1; + + if(!this->intersects(rect)) + { + return ossimDrect(OSSIM_DBL_NAN, + OSSIM_DBL_NAN, + OSSIM_DBL_NAN, + OSSIM_DBL_NAN); + } + if (theOrientMode == OSSIM_LEFT_HANDED) + { + y0 = d_MAX(rect.ul().y, ul().y); + y1 = d_MIN(rect.lr().y, lr().y); + + if( (x1 < x0) || (y1 < y0) ) + return ossimDrect(ossimDpt(0,0), ossimDpt(0,0), theOrientMode); + else + return ossimDrect(x0, y0, x1, y1, theOrientMode); + } + else + { + y1 = d_MIN(rect.ul().y,ul().y); + y0 = d_MAX(rect.lr().y,lr().y); + + if((x1 < x0) || (y1 < y0)) + return ossimDrect(ossimDpt(0,0), ossimDpt(0,0), theOrientMode); + else + return ossimDrect(x0, y1, x1, y0, theOrientMode); + } +} + +const ossimDrect& ossimDrect::operator=(const ossimIrect& rect) +{ + if(rect.isNan()) + { + makeNan(); + } + else + { + theUlCorner = rect.ul(); + theUrCorner = rect.ur(); + theLrCorner = rect.lr(); + theLlCorner = rect.ll(); + theOrientMode = rect.orientMode(); + } + + return *this; +} + diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimDrect.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimDrect.h new file mode 100644 index 0000000000..bbfc6c6410 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimDrect.h @@ -0,0 +1,766 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class declaration for drect. +// Container class for four double points representing a rectangle. +// +//******************************************************************* +// $Id: ossimDrect.h,v 1.23 2005/07/15 18:51:25 dburken Exp $ + +#ifndef ossimDrect_HEADER +#define ossimDrect_HEADER +#include <vector> +using namespace std; + +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimIpt.h> +#include <base/data_types/ossimFpt.h> + +//*** +// NOTE: A word on corner points... +// +// There is the concept of "pixel is area" and "pixel is point". +// - Pixel is area means the (x,y) pixel coordinate refers to the upper left +// corner of the pixel, NOT the center of the pixel. +// - Pixel is point means the (x,y) pixel coordinate refers to the center +// of the pixel, NOT the upper left corner. +// +// For the uniformity purposes, all pixel points should be in the +// "pixel is point" form; therefore, the (x,y) point should represent the +// CENTER of the pixel. +//*** + +//*** +// Forward class declarations. +//*** +class OSSIMDLLEXPORT ossimIrect; +class OSSIMDLLEXPORT ossimPolygon; + +//******************************************************************* +// CLASS: ossimDrect +//******************************************************************* + +class OSSIMDLLEXPORT ossimDrect +{ +public: + enum + { + UPPER_LEFT = 1, + LOWER_LEFT = 2, + LOWER_RIGHT = 4, + UPPER_RIGHT = 8 + }; + + ossimDrect() + : + theUlCorner(0.0, 0.0), + theUrCorner(0.0, 0.0), + theLrCorner(0.0, 0.0), + theLlCorner(0.0, 0.0), + theOrientMode(OSSIM_LEFT_HANDED) + {} + + ossimDrect(const ossimDpt& ul_corner, + const ossimDpt& lr_corner, + ossimCoordSysOrientMode mode=OSSIM_LEFT_HANDED) + : + theUlCorner(ul_corner), + theUrCorner(lr_corner.x, ul_corner.y), + theLrCorner(lr_corner), + theLlCorner(ul_corner.x, lr_corner.y), + theOrientMode(mode) + { + } + + ossimDrect(const double& ul_corner_x, + const double& ul_corner_y, + const double& lr_corner_x, + const double& lr_corner_y, + ossimCoordSysOrientMode mode=OSSIM_LEFT_HANDED) + : + theUlCorner(ul_corner_x, ul_corner_y), + theUrCorner(lr_corner_x, ul_corner_y), + theLrCorner(lr_corner_x, lr_corner_y), + theLlCorner(ul_corner_x, lr_corner_y), + theOrientMode(mode) + {} + + ossimDrect(const ossimDrect& rect) + : + theUlCorner(rect.ul()), + theUrCorner(rect.ur()), + theLrCorner(rect.lr()), + theLlCorner(rect.ll()), + theOrientMode(rect.orientMode()) + {} + + ossimDrect(const ossimIrect& rect); + + /*! + * Must compute a bounding rect given a collection of points or polygon: + */ + ossimDrect(const vector<ossimDpt>& points, + ossimCoordSysOrientMode mode=OSSIM_LEFT_HANDED); + ossimDrect(const ossimDpt& p1, + const ossimDpt& p2, + const ossimDpt& p3, + const ossimDpt& p4, + ossimCoordSysOrientMode mode=OSSIM_LEFT_HANDED); + ossimDrect(const ossimPolygon& polygon, + ossimCoordSysOrientMode mode=OSSIM_LEFT_HANDED); + + /** destructor */ + ~ossimDrect(); + + const ossimDrect& operator= (const ossimDrect& rect); + const ossimDrect& operator= (const ossimIrect& rect); + bool operator!= (const ossimDrect& rect) const; + bool operator== (const ossimDrect& rect) const; + friend ossimDrect operator*(double scalar, const ossimDrect& rect) + { + ossimDpt ul(rect.theUlCorner.x*scalar, + rect.theUlCorner.y*scalar); + + if(rect.theOrientMode == OSSIM_LEFT_HANDED) + { + return ossimDrect(ul.x, + ul.y, + ul.x+rect.width()*scalar-1, + ul.y+rect.height()*scalar-1, + rect.theOrientMode); + } + return ossimDrect(ul.x, + ul.y, + ul.x+rect.width()*scalar-1, + ul.y-(rect.height()*scalar-1), + rect.theOrientMode); + + } + + const ossimDrect& operator *=(double scalar) + { + ossimDpt ul(theUlCorner.x*scalar, + theUlCorner.y*scalar); + + if(theOrientMode == OSSIM_LEFT_HANDED) + { + *this = ossimDrect(ul.x, + ul.y, + (ul.x+width()*scalar-1), + (ul.y+height()*scalar-1), + theOrientMode); + } + else + { + *this = ossimDrect(ul.x, + ul.y, + (ul.x+width()*scalar-1), + (ul.y-(height()*scalar-1)), + theOrientMode); + + } + return *this; + } + + ossimDrect operator *(double scalar)const + { + ossimDpt ul((theUlCorner.x*scalar), + (theUlCorner.y*scalar)); + + if(theOrientMode == OSSIM_LEFT_HANDED) + { + return ossimDrect(ul.x, + ul.y, + (ul.x+width()*scalar-1), + (ul.y+height()*scalar-1), + theOrientMode); + } + + return ossimDrect(ul.x, + ul.y, + (ul.x+width()*scalar-1), + ul.y-(height()*scalar-1), + theOrientMode); + } + const ossimDrect& operator *=(const ossimDpt& scalar) + { + ossimDpt ul((theUlCorner.x*scalar.x), + (theUlCorner.y*scalar.y)); + + if(theOrientMode == OSSIM_LEFT_HANDED) + { + *this = ossimDrect(ul.x, + ul.y, + (ul.x+width()*scalar.x - 1), + (ul.y+height()*scalar.y - 1), + theOrientMode); + } + else + { + *this = ossimDrect(ul.x, + ul.y, + (ul.x+width()*scalar.x - 1), + (ul.y-(height()*scalar.y - 1)), + theOrientMode); + } + return *this; + } + + ossimDrect operator *(const ossimDpt& scalar)const + { + ossimDpt ul((theUlCorner.x*scalar.x), + (theUlCorner.y*scalar.y)); + + if(theOrientMode == OSSIM_LEFT_HANDED) + { + return ossimDrect(ul.x, + ul.y, + (ul.x+width()*scalar.x-1), + (ul.y+height()*scalar.y-1), + theOrientMode); + } + return ossimDrect(ul.x, + ul.y, + (ul.x+width()*scalar.x-1), + (ul.y-(height()*scalar.y-1)), + theOrientMode); + } + const ossimDrect& operator +=(const ossimDpt& shift) + { + ossimDpt ul((theUlCorner.x+shift.x), + (theUlCorner.y+shift.y)); + + if(theOrientMode == OSSIM_LEFT_HANDED) + { + *this = ossimDrect(ul.x, + ul.y, + ul.x+width()-1, + ul.y+height()-1, + theOrientMode); + } + else + { + *this = ossimDrect(ul.x, + ul.y, + ul.x+width()-1, + ul.y-(height()-1), + theOrientMode); + } + return *this; + } + + const ossimDrect& operator -=(const ossimDpt& shift) + { + ossimDpt ul((theUlCorner.x-shift.x), + (theUlCorner.y-shift.y)); + + if(theOrientMode == OSSIM_LEFT_HANDED) + { + *this = ossimDrect(ul.x, + ul.y, + ul.x+width()-1, + ul.y+height()-1, + theOrientMode); + } + else + { + *this = ossimDrect(ul.x, + ul.y, + ul.x+width()-1, + ul.y-(height()-1), + theOrientMode); + } + return *this; + } + + ossimDrect operator +(const ossimDpt& shift)const + { + ossimDpt ul((theUlCorner.x+shift.x), + (theUlCorner.y+shift.y)); + + if(theOrientMode == OSSIM_LEFT_HANDED) + { + return ossimDrect(ul.x, + ul.y, + ul.x+width()-1, + ul.y+height()-1, + theOrientMode); + } + else + { + return ossimDrect(ul.x, + ul.y, + ul.x+width()-1, + ul.y-(height()-1), + theOrientMode); + } + } + + ossimDrect operator -(const ossimDpt& shift)const + { + ossimIpt ul(irint(theUlCorner.x-shift.x), + irint(theUlCorner.y-shift.y)); + + if(theOrientMode == OSSIM_LEFT_HANDED) + { + return ossimDrect(ul.x, + ul.y, + ul.x+width()-1, + ul.y+height()-1, + theOrientMode); + } + else + { + return ossimDrect(ul.x, + ul.y, + ul.x+width()-1, + ul.y-(height()-1), + theOrientMode); + } + } + + ossimDpt ul() const { return theUlCorner; } + ossimDpt ur() const { return theUrCorner; } + ossimDpt lr() const { return theLrCorner; } + ossimDpt ll() const { return theLlCorner; } + + void getBounds(double& minx, double& miny, + double& maxx, double& maxy)const + { + minx = theUlCorner.x; + maxx = theUrCorner.x; + if(theOrientMode == OSSIM_LEFT_HANDED) + { + miny = theUlCorner.y; + maxy = theUrCorner.y; + } + else + { + maxy = theUlCorner.y; + miny = theUrCorner.y; + } + } + void makeNan() + { + theUlCorner.makeNan(); + theLlCorner.makeNan(); + theLrCorner.makeNan(); + theUrCorner.makeNan(); + } + + bool hasNans()const{ return (theUlCorner.hasNans() || + theLlCorner.hasNans() || + theLrCorner.hasNans() || + theUrCorner.hasNans());} + + bool isNan()const{ return (theUlCorner.hasNans() && + theLlCorner.hasNans() && + theLrCorner.hasNans() && + theUrCorner.hasNans());} + + double area()const + { + return width()*height(); + } + //*** + // This class supports both left and right-handed coordinate systems. For + // both, the positive x-axis extends to the "right". + //*** + ossimCoordSysOrientMode orientMode() const { return theOrientMode; } + void setOrientMode(ossimCoordSysOrientMode mode) { theOrientMode = mode; } + + /*! + * Sets the upper left corner to "pt". Adjusts the remaining corners + * accordingly. + */ + void set_ul(const ossimDpt& pt); + + /*! + * Sets the upper right corner to "pt". Adjusts the remaining corners + * accordingly. + */ + void set_ur(const ossimDpt& pt); + + /*! + * Sets the lower right corner to "pt". Adjusts the remaining corners + * accordingly. + */ + void set_lr(const ossimDpt& pt); + + /*! + * Sets the lower left corner to "pt". Adjusts the remaining corners + * accordingly. + */ + void set_ll(const ossimDpt& pt); + + /*! + * Sets the upper left x. Adjusts the remaining corners accordingly. + */ + void set_ulx(ossim_float64 x); + + /*! + * Sets the upper left y. Adjusts the remaining corners accordingly. + */ + void set_uly(ossim_float64 y); + + /*! + * Sets the upper right x. Adjusts the remaining corners accordingly. + */ + void set_urx(ossim_float64 x); + + /*! + * Sets the upper right y. Adjusts the remaining corners accordingly. + */ + void set_ury(ossim_float64 y); + + /*! + * Sets the lower right x. Adjusts the remaining corners accordingly. + */ + void set_lrx(ossim_float64 x); + + /*! + * Sets the lower right y. Adjusts the remaining corners accordingly. + */ + void set_lry(ossim_float64 y); + + /*! + * Sets the lower left x. Adjusts the remaining corners accordingly. + */ + void set_llx(ossim_float64 x); + + /*! + * Sets the lower left y. Adjusts the remaining corners accordingly. + */ + void set_lly(ossim_float64 y); + + /*! + * METHOD: initBoundingRect(points) + * Initializes this rect to the bounding rect containing all points in the + * collection passed in. + */ + void initBoundingRect(const vector<ossimDpt>& points); + + /*! + * Returns true if "pt" falls within rectangle. Fall on an edge is also + * considered to be within. + */ + bool pointWithin(const ossimDpt& pt) const; + + /*! + * Returns true if "pt" falls within rectangle. Fall on an edge is also + * considered to be within. + */ + bool pointWithin(const ossimFpt& pt) const; + + /*! + * Returns true if any portion of an input rectangle "rect" intersects + * "this" rectangle. + */ + bool intersects(const ossimDrect& rect) const; + + /*! + * Returns true if "this" rectangle is contained completely within the + * input rectangle "rect". + */ + bool completely_within(const ossimDrect& rect) const; + + /*! + * Returns the height of a rectangle. + */ + ossim_float64 height() const { return fabs(theLlCorner.y - theUlCorner.y) + 1.0; } + + /*! + * Returns the width of a rectangle. + */ + ossim_float64 width() const { return fabs(theLrCorner.x - theLlCorner.x) + 1.0; } + + /*! + * Stretches this rectangle out to integer boundaries. + */ + void stretchOut(); + + /*! + * Will stretch the rect to the passed in tiled boundary. + */ + void stretchToTileBoundary(const ossimDpt& widthHeight); + + /*! + * Will subdivide this rect into four partiions. + */ + void splitToQuad(ossimDrect& ulRect, + ossimDrect& urRect, + ossimDrect& lrRect, + ossimDrect& llRect); + + ossimDrect clipToRect(const ossimDrect& rect)const; + + inline ossimDpt midPoint()const; + + void print(ostream& os) const; + + ossimDrect combine(const ossimDrect& rect)const; + + friend OSSIMDLLEXPORT ostream& operator<<(ostream& os, + const ossimDrect& rect); + + bool clip(ossimDpt &p1, + ossimDpt &p2)const; + + static long getCode(const ossimDpt& aPoint, + const ossimDrect& clipRect); +private: + + enum ossimCohenSutherlandClipCodes + { + NONE = 0, + LEFT = 1, + RIGHT = 2, + BOTTOM = 4, + TOP = 8 + }; + + //*** + // Private data members representing the rectangle corners. + //*** + ossimDpt theUlCorner; + ossimDpt theUrCorner; + ossimDpt theLrCorner; + ossimDpt theLlCorner; + + ossimCoordSysOrientMode theOrientMode; +}; + +//******************************************************************* +// Inline Method: ossimDrect::operator=(ossimDrect) +//******************************************************************* +inline const ossimDrect& ossimDrect::operator=(const ossimDrect& rect) +{ + if (this != &rect) + { + theUlCorner = rect.theUlCorner; + theUrCorner = rect.theUrCorner; + theLrCorner = rect.theLrCorner; + theLlCorner = rect.theLlCorner; + theOrientMode = rect.theOrientMode; + } + + return *this; +} + +//******************************************************************* +// Inline Method: ossimDrect::operator!= +//******************************************************************* +inline bool ossimDrect::operator!=(const ossimDrect& rect) const +{ + return ( (theUlCorner != rect.theUlCorner) || + (theUrCorner != rect.theUrCorner) || + (theLrCorner != rect.theLrCorner) || + (theLlCorner != rect.theLlCorner) || + (theOrientMode != rect.theOrientMode)); +} + +//******************************************************************* +// Inline Method: ossimDrect::operator== +//******************************************************************* +inline bool ossimDrect::operator==(const ossimDrect& rect) const +{ + return ( (theUlCorner == rect.theUlCorner) && + (theUrCorner == rect.theUrCorner) && + (theLrCorner == rect.theLrCorner) && + (theLlCorner == rect.theLlCorner) && + (theOrientMode == rect.theOrientMode)); +} + +//******************************************************************* +// Inline Method: ossimDrect::set_ul +//******************************************************************* +inline void ossimDrect::set_ul(const ossimDpt& pt) +{ + theUlCorner = pt; + theUrCorner.y = pt.y; + theLlCorner.x = pt.x; +} + +//******************************************************************* +// Inline Method: ossimDrect::set_ur +//******************************************************************* +inline void ossimDrect::set_ur(const ossimDpt& pt) +{ + theUrCorner = pt; + theUlCorner.y = pt.y; + theLrCorner.x = pt.x; +} + +//******************************************************************* +// Inline Method: ossimDrect::set_lr +//******************************************************************* +inline void ossimDrect::set_lr(const ossimDpt& pt) +{ + theLrCorner = pt; + theUrCorner.x = pt.x; + theLlCorner.y = pt.y; +} + +//******************************************************************* +// Inline Method: ossimDrect::set_ll +//******************************************************************* +inline void ossimDrect::set_ll(const ossimDpt& pt) +{ + theLlCorner = pt; + theUlCorner.x = pt.x; + theLrCorner.y = pt.y; +} + +//******************************************************************* +// Inline Method: ossimDrect::set_ulx +//******************************************************************* +inline void ossimDrect::set_ulx(ossim_float64 x) +{ + theUlCorner.x = x; + theLlCorner.x = x; +} + +//******************************************************************* +// Inline Method: ossimDrect::set_uly +//******************************************************************* +inline void ossimDrect::set_uly(ossim_float64 y) +{ + theUlCorner.y = y; + theUrCorner.y = y; +} + +//******************************************************************* +// Inline Method: ossimDrect::set_urx +//******************************************************************* +inline void ossimDrect::set_urx(ossim_float64 x) +{ + theUrCorner.x = x; + theLrCorner.x = x; +} + +//******************************************************************* +// Inline Method: ossimDrect::set_ury +//******************************************************************* +inline void ossimDrect::set_ury(ossim_float64 y) +{ + theUrCorner.y = y; + theUlCorner.y = y; +} + +//******************************************************************* +// Inline Method: ossimDrect::set_lrx +//******************************************************************* +inline void ossimDrect::set_lrx(ossim_float64 x) +{ + theLrCorner.x = x; + theUrCorner.x = x; +} + +//******************************************************************* +// Inline Method: ossimDrect::set_lry +//******************************************************************* +inline void ossimDrect::set_lry(ossim_float64 y) +{ + theLrCorner.y = y; + theLlCorner.y = y; +} + +//******************************************************************* +// Inline Method: ossimDrect::set_llx +//******************************************************************* +inline void ossimDrect::set_llx(ossim_float64 x) +{ + theLlCorner.x = x; + theUlCorner.x = x; +} + +//******************************************************************* +// Inline Method: ossimDrect::set_lly +//******************************************************************* +inline void ossimDrect::set_lly(ossim_float64 y) +{ + theLlCorner.y = y; + theLrCorner.y = y; +} + +//******************************************************************* +// Inline Method: ossimDrect::pointWithin(const ossimDpt& pt) +//******************************************************************* +inline bool ossimDrect::pointWithin(const ossimDpt& pt) const +{ + if (theOrientMode == OSSIM_LEFT_HANDED) + return ((pt.x >= ul().x) && + (pt.x <= ur().x) && + (pt.y >= ul().y) && + (pt.y <= ll().y)); + else + return ((pt.x >= ul().x) && + (pt.x <= ur().x) && + (pt.y <= ul().y) && + (pt.y >= ll().y)); +} + +//******************************************************************* +// Inline Method: ossimDrect::pointWithin(const ossimFpt& pt) +//******************************************************************* +inline bool ossimDrect::pointWithin(const ossimFpt& pt) const +{ + if (theOrientMode == OSSIM_LEFT_HANDED) + { + return ( (pt.x >= ul().x) && + (pt.x <= ur().x) && + (pt.y >= ul().y) && + (pt.y <= ll().y) ); + } + return ((pt.x >= ul().x) && + (pt.x <= ur().x) && + (pt.y <= ul().y) && + (pt.y >= ll().y)); +} + +//******************************************************************* +// Inline Method: ossimDrect::midPoint() +//******************************************************************* +inline ossimDpt ossimDrect::midPoint()const +{ + return ossimDpt( (ul().x + ur().x + ll().x + lr().x)*.25, + (ul().y + ur().y + ll().y + lr().y)*.25); +} + +//******************************************************************* +// Inline Method: ossimDrect::combine(const ossimDrect& rect) +//******************************************************************* +inline ossimDrect ossimDrect::combine(const ossimDrect& rect)const +{ + if (theOrientMode != rect.theOrientMode) + return(*this); + + ossimDpt ulCombine; + ossimDpt lrCombine; + + if(theOrientMode == OSSIM_LEFT_HANDED) + { + ulCombine.x = ((ul().x <= rect.ul().x)?ul().x:rect.ul().x); + ulCombine.y = ((ul().y <= rect.ul().y)?ul().y:rect.ul().y); + lrCombine.x = ((lr().x >= rect.lr().x)?lr().x:rect.lr().x); + lrCombine.y = ((lr().y >= rect.lr().y)?lr().y:rect.lr().y); + } + else + { + ulCombine.x = ((ul().x <= rect.ul().x)?ul().x:rect.ul().x); + ulCombine.y = ((ul().y >= rect.ul().y)?ul().y:rect.ul().y); + lrCombine.x = ((lr().x >= rect.lr().x)?lr().x:rect.lr().x); + lrCombine.y = ((lr().y <= rect.lr().y)?lr().y:rect.lr().y); + } + + return ossimDrect(ulCombine, lrCombine); +} +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimEcefPoint.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimEcefPoint.cpp new file mode 100644 index 0000000000..1a0115eade --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimEcefPoint.cpp @@ -0,0 +1,89 @@ +//***************************************************************************** +// FILE: ossimEcefPoint.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// DESCRIPTION: +// Contains declaration of a 3D point object in the Earth-centered, earth +// fixed (ECEF) coordinate system. +// +// SOFTWARE HISTORY: +//> +// 08Aug2001 Oscar Kramer (http://www.oscarkramer.com) +// Initial coding. +//< +//***************************************************************************** +// $Id: ossimEcefPoint.cpp,v 1.9 2005/07/29 20:47:04 dburken Exp $ + +#include <base/data_types/ossimEcefPoint.h> +#include <base/data_types/ossimGpt.h> +#include <base/data_types/ossimGeocent.h> +#include <base/data_types/ossimDpt3d.h> +#include <base/data_types/datum/ossimDatum.h> +#include <base/data_types/ellipse/ossimEllipsoid.h> +#include <base/data_types/ossimEcefVector.h> + +//***************************************************************************** +// CONSTRUCTOR: ossimEcefPoint(const ossimGpt& convert_this) +// +//***************************************************************************** +ossimEcefPoint::ossimEcefPoint(const ossimGpt& gpt) +{ + if(!gpt.isHgtNan()) + { + gpt.datum()->ellipsoid()->latLonHeightToXYZ(gpt.latd(), + gpt.lond(), + gpt.height(), + theData[0], + theData[1], + theData[2]); + } + else + { + gpt.datum()->ellipsoid()->latLonHeightToXYZ(gpt.latd(), + gpt.lond(), + 0.0, + theData[0], + theData[1], + theData[2]); + } +} + +ossimEcefPoint::ossimEcefPoint(const ossimDpt3d& pt) + :theData(pt.x, pt.y, pt.z) +{ +} + + +//***************************************************************************** +// METHOD: ossimEcefPoint::operator-(ossimEcefPoint) +//***************************************************************************** +ossimEcefVector ossimEcefPoint::operator-(const ossimEcefPoint& p) const +{ + return ossimEcefVector(theData - p.theData); +} + +//***************************************************************************** +// METHOD: ossimEcefPoint::operator+(ossimEcefVector) +//***************************************************************************** +ossimEcefPoint ossimEcefPoint::operator+(const ossimEcefVector& v) const +{ + return ossimEcefPoint(theData + v.data()); +} + +//***************************************************************************** +// METHOD: ossimEcefPoint::operator-(ossimEcefVector) +//***************************************************************************** +ossimEcefPoint ossimEcefPoint::operator-(const ossimEcefVector& v) const +{ + return ossimEcefPoint(theData - v.data()); +} + +std::ostream& operator<<(std::ostream& os , const ossimEcefPoint& instance) +{ + instance.print(os); return os; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimEcefPoint.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimEcefPoint.h new file mode 100644 index 0000000000..42c338b615 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimEcefPoint.h @@ -0,0 +1,192 @@ +//***************************************************************************** +// FILE: ossimEcefPoint.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// DESCRIPTION: +// Contains declaration of a 3D point object in the Earth-centered, earth +// fixed (ECEF) coordinate system. +// +// SOFTWARE HISTORY: +//> +// 08Aug2001 Oscar Kramer (okramer@imagelinks.com) +// Initial coding. +//< +//***************************************************************************** +// $Id: ossimEcefPoint.h,v 1.10 2005/05/13 17:39:01 gpotts Exp $ + +#ifndef ossimEcefPoint_HEADER +#define ossimEcefPoint_HEADER +#include <iostream> +#include <stdio.h> +#include <base/data_types/ossimColumnVector3d.h> +#include <base/context/ossimNotifyContext.h> + +class ossimGpt; +class ossimEcefVector; +class ossimDpt3d; +//***************************************************************************** +// CLASS: ossimEcefPoint +// +//***************************************************************************** +class OSSIMDLLEXPORT ossimEcefPoint +{ +public: + /*! + * CONSTRUCTORS: + */ + ossimEcefPoint() + : theData(0,0,0) {} + + ossimEcefPoint(const ossimEcefPoint& copy_this) + : theData (copy_this.theData) {} + + ossimEcefPoint(const ossimGpt& convert_this); + + ossimEcefPoint(const double& x, + const double& y, + const double& z) + : theData(x, y, z) {} + + ossimEcefPoint(const ossimColumnVector3d& assign_this) + : theData(assign_this) {} + + ossimEcefPoint(const ossimDpt3d& pt); + + void makeNan() + { + theData[0] = OSSIM_DBL_NAN; + theData[1] = OSSIM_DBL_NAN; + theData[2] = OSSIM_DBL_NAN; + } + + bool hasNans()const + { + return ((theData[0]==OSSIM_DBL_NAN)|| + (theData[1]==OSSIM_DBL_NAN)|| + (theData[2]==OSSIM_DBL_NAN)); + + } + + bool isNan()const + { + return ((theData[0]==OSSIM_DBL_NAN)&& + (theData[1]==OSSIM_DBL_NAN)&& + (theData[2]==OSSIM_DBL_NAN)); + + } + /*! + * OPERATORS: + */ + ossimEcefVector operator- (const ossimEcefPoint&) const; + ossimEcefPoint operator+ (const ossimEcefVector&) const; + ossimEcefPoint operator- (const ossimEcefVector&) const; + const ossimEcefPoint& operator= (const ossimEcefPoint&); // inline + bool operator==(const ossimEcefPoint&) const; // inline + bool operator!=(const ossimEcefPoint&) const; // inline + + /*! + * COMPONENT ACCESS METHODS: + */ + double x() const { return theData[0]; } + double& x() { return theData[0]; } + double y() const { return theData[1]; } + double& y() { return theData[1]; } + double z() const { return theData[2]; } + double& z() { return theData[2]; } + double& operator[](int idx){return theData[idx];} + const double& operator[](int idx)const{return theData[idx];} + const ossimColumnVector3d& data() const { return theData; } + ossimColumnVector3d& data() { return theData; } + + double getMagnitude() const + { + return theData.magnitude(); + } + double magnitude()const + { + return theData.magnitude(); + } + double length()const + { + return theData.magnitude(); + } + double normalize() + { + double result = magnitude(); + + if(result > 1e-15) + { + theData[0]/=result; + theData[1]/=result; + theData[2]/=result; + } + + return result; + } + /*! + * Debug Dump: + */ + void print(std::ostream& os = ossimNotify(ossimNotifyLevel_INFO)) const + { + if(isNan()) + { + os << "(ossimEcefPoint) " << "nan nan nan"; + } + + os << "(ossimEcefPoint) " << theData; + } + + friend std::ostream& operator<<(std::ostream& os , + const ossimEcefPoint& instance); + +protected: + ossimColumnVector3d theData; +}; + +//================== BEGIN DEFINITIONS FOR INLINE METHODS ===================== + +//***************************************************************************** +// INLINE METHOD: ossimEcefPoint::operator=(ossimEcefPoint) +//***************************************************************************** +inline const ossimEcefPoint& +ossimEcefPoint::operator=(const ossimEcefPoint& p) +{ + theData = p.theData; + return *this; +} + +//***************************************************************************** +// INLINE METHOD: ossimEcefPoint::operator==(ossimEcefPoint) +//***************************************************************************** +inline bool ossimEcefPoint::operator==(const ossimEcefPoint& p) const +{ + return (theData == p.theData); +} + +//***************************************************************************** +// INLINE METHOD: ossimEcefPoint::operator!=(ossimEcefPoint) +//***************************************************************************** +inline bool ossimEcefPoint::operator!=(const ossimEcefPoint& p) const +{ + return (theData != p.theData); +} + +#endif + + diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimEcefRay.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimEcefRay.cpp new file mode 100644 index 0000000000..15c9aa552a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimEcefRay.cpp @@ -0,0 +1,108 @@ +//***************************************************************************** +// FILE: ossimEcefRay.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// DESCRIPTION: +// Class for representing a ray in the earth-centered, earth-fixed (ECEF) +// coordinate system. A ray is defined as having an origin point and a +// unit direction vector radiating from the origin. +// +// SOFTWARE HISTORY: +//> +// 10Aug2001 Oscar Kramer (okramer@imagelinks.com) +// Initial coding. +//< +//***************************************************************************** +// $Log: ossimEcefRay.cpp,v $ +// Revision 1.2 2002/05/31 12:51:14 okramer +// Added ossimEcefRay::intersectAboveEarthEllipsoid() +// +// Revision 1.1 2001/08/14 15:01:45 okramer +// Initial delivery (okramer@imagelinks.com) +// + +#include "ossimEcefRay.h" +#include "ossimGpt.h" +#include "base/data_types/datum/ossimDatum.h" +#include "base/data_types/ellipse/ossimEllipsoid.h" + +//*** +// Define Trace flags for use within this file: +//*** +#include "base/common/ossimTrace.h" +static ossimTrace traceExec ("ossimEcefRay:exec"); +static ossimTrace traceDebug ("ossimEcefRay:debug"); + +//***************************************************************************** +// CONSTRUCTOR: ossimEcefRay(ossimEcefPoint, ossimEcefPoint) +// +// Constructs a ray originating at "from" and pointing in direction of "to" +// +//***************************************************************************** +ossimEcefRay::ossimEcefRay(const ossimEcefPoint& from, + const ossimEcefPoint& to) + : theOrigin(from) +{ + ossimEcefVector ecef (to - from); + ecef.normalize(); + theDirection = ecef; +} + + +//***************************************************************************** +// CONSTRUCTOR: ossimEcefRay(ossimGpt, ossimGpt) +// +// Constructs a ray originating at "from" and pointing in direction of "to" +// +//***************************************************************************** +ossimEcefRay::ossimEcefRay(const ossimGpt& from, + const ossimGpt& to) + : theOrigin(from) +{ + ossimEcefVector ecef (ossimEcefPoint(to) - ossimEcefPoint(from)); + ecef.normalize(); + theDirection = ecef; +} + +//***************************************************************************** +// METHOD: ossimEcefRay::intersectAboveEarthEllipsoid +// +// Intersects the ray with the given elevation above the earth ellipsoid. +// +//***************************************************************************** +ossimEcefPoint ossimEcefRay::intersectAboveEarthEllipsoid + (const double& argHeight, + const ossimDatum* argDatum) const +{ + const ossimDatum* datum = argDatum; + if (!datum) + datum = ossimDatumFactory::instance()->wgs84(); + + //*** + // Pass the call on to ellipsoid where intersection math is implemented: + //*** + ossimEcefPoint solution; + bool intersected = datum->ellipsoid()->nearestIntersection + (*this, argHeight, solution); + + if (!intersected) + solution.makeNan(); + + return solution; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimEcefRay.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimEcefRay.h new file mode 100644 index 0000000000..f22c751eeb --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimEcefRay.h @@ -0,0 +1,198 @@ +//***************************************************************************** +// FILE: ossimEcefRay.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// DESCRIPTION: +// Class for representing a ray in the earth-centered, earth-fixed (ECEF) +// coordinate system. A ray is defined as having an origin point and a +// unit direction vector radiating from the origin. +// +// SOFTWARE HISTORY: +//> +// 08Aug2001 Oscar Kramer (okramer@imagelinks.com) +// Initial coding. +//< +//***************************************************************************** +// $Id: ossimEcefRay.h,v 1.10 2004/04/02 22:03:54 gpotts Exp $ + +#ifndef ossimEcefRay_HEADER +#define ossimEcefRay_HEADER + +#include <stdio.h> +#include <base/data_types/ossimEcefPoint.h> +#include <base/data_types/ossimEcefVector.h> +#include <base/factory/ossimDatumFactory.h> +#include <base/context/ossimNotifyContext.h> + +class OSSIMDLLEXPORT ossimGpt; +class OSSIMDLLEXPORT ossimLsrRay; + +//***************************************************************************** +// CLASS: ossimEcefRay +// +//***************************************************************************** +class OSSIMDLLEXPORT ossimEcefRay +{ +public: + /*! + * CONSTRUCTORS: + */ + ossimEcefRay() {}; + + ossimEcefRay(const ossimEcefRay& copy_this) + : theOrigin(copy_this.theOrigin), theDirection(copy_this.theDirection) {} + + ossimEcefRay(const ossimEcefPoint& origin, + const ossimEcefVector& direction) + : theOrigin(origin), theDirection(direction.unitVector()) {} + + ossimEcefRay(const ossimEcefPoint& from, + const ossimEcefPoint& to); + + ossimEcefRay(const ossimGpt& from, + const ossimGpt& to); + + bool isNan()const + { + return theOrigin.isNan()&&theDirection.isNan(); + } + bool hasNans()const + { + return theOrigin.isNan()||theDirection.isNan(); + } + void makeNan() + { + theOrigin.makeNan(); + theDirection.makeNan(); + } + /*! + * OPERATORS: + */ + const ossimEcefRay& operator= (const ossimEcefRay& r); // inline below + bool operator==(const ossimEcefRay& r) const; // inline below + bool operator!=(const ossimEcefRay& r) const; // inline below + + /*! + * DATA ACCESS METHODS: + */ + const ossimEcefPoint& origin() const { return theOrigin; } + const ossimEcefVector& direction() const { return theDirection; } + void setOrigin(const ossimEcefPoint& orig) { theOrigin = orig; } + void setDirection(const ossimEcefVector& d) { theDirection=d.unitVector();} + + /*! + * Extends the ray by distance t (meters) from the origin to the ECEF + * point returned. + */ + ossimEcefPoint extend(const double& t) const; // inline below + + /*! + * This method computes a ray with the same origin but a new direction + * corresponding to a reflection from some surface defined by its normal + * vector (assumed to be a unit vector): + */ + ossimEcefRay reflectRay(const ossimEcefVector& normal) const;// inline below + + /*! + * Intersects the ray with the given elevation above the earth ellipsoid. + */ + ossimEcefPoint intersectAboveEarthEllipsoid + (const double& heightAboveEllipsoid, + const ossimDatum* aDatum = ossimDatumFactory::instance()->wgs84()) const; + + /*! + * Debug Dump + */ + void print(ostream& os = ossimNotify(ossimNotifyLevel_INFO)) const; // inline below + + friend ostream& operator<< (ostream& os , const ossimEcefRay& instance) + { instance.print(os); return os; } + +private: + ossimEcefPoint theOrigin; + ossimEcefVector theDirection; +}; + +//================== BEGIN DEFINITIONS FOR INLINE METHODS ===================== + +//***************************************************************************** +// INLINE METHOD: ossimEcefRay::operator=(ossimEcefRay) +//***************************************************************************** +inline const ossimEcefRay& ossimEcefRay::operator=(const ossimEcefRay& r) +{ + theOrigin = r.theOrigin; + theDirection = r.theDirection; + return *this; +} + +//***************************************************************************** +// INLINE METHOD: ossimEcefRay::operator==(ossimEcefRay) +//***************************************************************************** +inline bool ossimEcefRay::operator==(const ossimEcefRay& r) const +{ + return ((theOrigin == r.theOrigin) && (theDirection == r.theDirection)); +} + +//***************************************************************************** +// INLINE METHOD: ossimEcefRay::operator!=(ossimEcefRay) +//***************************************************************************** +inline bool ossimEcefRay::operator!=(const ossimEcefRay& r) const +{ + return !(*this == r); +} + +//***************************************************************************** +// INLINE METHOD: ossimEcefRay::extend(double t) +// +// Extends the ray by distance t (meters) from the origin to the ECEF +// point returned. +//***************************************************************************** +inline ossimEcefPoint ossimEcefRay::extend(const double& t) const +{ + return (theOrigin + theDirection*t); +} + +//***************************************************************************** +// INLINE METHOD: ossimEcefRay::reflectRay(normal) +// +// This method computes a ray with the same origin but a new direction +// corresponding to a reflection from some surface defined by its normal +// vector: +//***************************************************************************** +inline ossimEcefRay +ossimEcefRay::reflectRay(const ossimEcefVector& normal) const +{ + ossimEcefVector new_dir(theDirection - normal*2.0*normal.dot(theDirection)); + return ossimEcefRay(theOrigin, new_dir); +} + +//***************************************************************************** +// INLINE METHOD: ossimEcefRay::print(ostream) +// Dumps contents for debug purposes. +//***************************************************************************** +inline void ossimEcefRay::print(ostream& os) const +{ + os << "(ossimEcefRay)\n" + << " theOrigin = " << theOrigin + << "\n theDirection = " << theDirection << ends; +} + +#endif + + diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimEcefVector.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimEcefVector.h new file mode 100644 index 0000000000..1133975e47 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimEcefVector.h @@ -0,0 +1,300 @@ +//***************************************************************************** +// FILE: ossimEcefVector.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// DESCRIPTION: +// Contains declaration of a 3D vector object in the Earth-centered, earth +// fixed (ECEF) coordinate system. +// +// NOTE: There is no associated ossimEcefVector.cc file. All methods are +// inlined here +// +// SOFTWARE HISTORY: +//> +// 08Aug2001 Oscar Kramer (okramer@imagelinks.com) +// Initial coding. +//< +//***************************************************************************** +// $Id: ossimEcefVector.h,v 1.6 2005/05/13 17:39:02 gpotts Exp $ + +#ifndef ossimEcefVector_HEADER +#define ossimEcefVector_HEADER + +#include <stdio.h> +#include <math.h> +#include <base/common/ossimCommon.h> +#include <base/data_types/ossimColumnVector3d.h> +#include <base/data_types/ossimEcefPoint.h> +#include <base/data_types/ossimGpt.h> +#include <base/context/ossimNotifyContext.h> + +//***************************************************************************** +// CLASS: ossimEcefVector +// +//***************************************************************************** +class OSSIMDLLEXPORT ossimEcefVector +{ +public: + /*! + * CONSTRUCTORS: + */ + ossimEcefVector() + : theData(0,0,0) {} + + ossimEcefVector(const ossimEcefVector& copy_this) + : theData (copy_this.theData) {} + + ossimEcefVector(const ossimEcefPoint& from, + const ossimEcefPoint& to) + : theData (to.data() - from.data()) {} + + ossimEcefVector(const ossimGpt& from, + const ossimGpt& to) + : theData ((ossimEcefPoint(to) - ossimEcefPoint(from)).data()) {} + + ossimEcefVector(const double& x, + const double& y, + const double& z) + : theData(x, y, z) {} + + ossimEcefVector(const ossimColumnVector3d& assign_this) + : theData(assign_this) {} + + + void makeNan() + { + theData[0] = OSSIM_DBL_NAN; + theData[1] = OSSIM_DBL_NAN; + theData[2] = OSSIM_DBL_NAN; + } + + bool hasNans()const + { + return ((theData[0]==OSSIM_DBL_NAN)|| + (theData[1]==OSSIM_DBL_NAN)|| + (theData[2]==OSSIM_DBL_NAN)); + + } + + bool isNan()const + { + return ((theData[0]==OSSIM_DBL_NAN)&& + (theData[1]==OSSIM_DBL_NAN)&& + (theData[2]==OSSIM_DBL_NAN)); + + } + /*! + * OPERATORS: (all inlined below) + */ + inline ossimEcefVector operator- () const; + inline ossimEcefVector operator+ (const ossimEcefVector&) const; + inline ossimEcefVector operator- (const ossimEcefVector&) const; + inline ossimEcefPoint operator+ (const ossimEcefPoint&) const; + inline ossimEcefVector operator* (const double&) const; + inline ossimEcefVector operator/ (const double&) const; + inline bool operator==(const ossimEcefVector&) const; + inline bool operator!=(const ossimEcefVector&) const; + inline const ossimEcefVector& operator= (const ossimEcefVector&); + + /*! + * Vector-related functions: (all inlined below) + */ + inline double dot (const ossimEcefVector&) const; + inline double angleTo(const ossimEcefVector&) const; // degrees + inline ossimEcefVector cross (const ossimEcefVector&) const; + inline ossimEcefVector unitVector() const; + inline double magnitude() const; // meters + inline double length() const; + inline double normalize(); + + /*! + * COMPONENT ACCESS METHODS: + */ + double x() const { return theData[0]; } + double& x() { return theData[0]; } + double y() const { return theData[1]; } + double& y() { return theData[1]; } + double z() const { return theData[2]; } + double& z() { return theData[2]; } + double& operator [](int idx){return theData[idx];} + const double& operator [](int idx)const{return theData[idx];} + + const ossimColumnVector3d& data() const { return theData; } + ossimColumnVector3d& data() { return theData; } + + /*! + * Debug Dump: + */ + void print(ostream& os = ossimNotify(ossimNotifyLevel_INFO)) const + { os << "(ossimEcefVector) " << theData; } + + friend ostream& operator<< (ostream& os , const ossimEcefVector& instance) + { instance.print(os); return os; } + +protected: + ossimColumnVector3d theData; +}; + +//================== BEGIN DEFINITIONS FOR INLINE METHODS ===================== + +//***************************************************************************** +// INLINE METHOD: ossimEcefVector::operator-() +// Reverses direction of vector. +//***************************************************************************** +inline ossimEcefVector ossimEcefVector::operator-() const +{ + return ossimEcefVector(-theData); +} + +//***************************************************************************** +// INLINE METHOD: ossimEcefVector::operator+(const ossimEcefVector&) +//***************************************************************************** +inline ossimEcefVector +ossimEcefVector::operator+(const ossimEcefVector& v) const +{ + return ossimEcefVector(theData + v.theData); +} + +//***************************************************************************** +// INLINE METHOD: ossimEcefVector::operator-(const ossimEcefVector&) +//***************************************************************************** +inline ossimEcefVector +ossimEcefVector::operator-(const ossimEcefVector& v) const +{ + return ossimEcefVector(theData - v.theData); +} + +//***************************************************************************** +// INLINE METHOD: ossimEcefVector::operator+(const ossimEcefPoint&) +//***************************************************************************** +inline ossimEcefPoint +ossimEcefVector::operator+(const ossimEcefPoint& p) const +{ + return ossimEcefPoint(theData + p.data()); +} + +//***************************************************************************** +// INLINE METHOD: ossimEcefVector::operator*(const double&) +//***************************************************************************** +inline ossimEcefVector ossimEcefVector::operator*(const double& scalar) const +{ + return ossimEcefVector(theData*scalar); +} + +//***************************************************************************** +// INLINE METHOD: ossimEcefVector::operator/(const double&) +//***************************************************************************** +inline ossimEcefVector ossimEcefVector::operator/(const double& scalar) const +{ + return ossimEcefVector(theData/scalar); +} + +//***************************************************************************** +// INLINE METHOD: ossimEcefVector::operator==(const ossimEcefVector&) +//***************************************************************************** +inline bool ossimEcefVector::operator==(const ossimEcefVector& v) const +{ + return (theData == v.theData); +} + +//***************************************************************************** +// INLINE METHOD: ossimEcefVector::operator!=(const ossimEcefVector&) +//***************************************************************************** +inline bool ossimEcefVector::operator!=(const ossimEcefVector& v) const +{ + return (theData != v.theData); +} + +//***************************************************************************** +// INLINE METHOD: ossimEcefVector::operator= +//***************************************************************************** +inline const ossimEcefVector& +ossimEcefVector::operator=(const ossimEcefVector& v) +{ + theData = v.theData; + return *this; +} + +//***************************************************************************** +// INLINE METHOD: ossimEcefVector::dot() +// Computes the scalar product. +//***************************************************************************** +inline double ossimEcefVector::dot(const ossimEcefVector& v) const +{ + return theData.dot(v.theData); +} + +//***************************************************************************** +// INLINE METHOD: ossimEcefVector::angleTo() +// Returns the angle subtended (in DEGREES) between this and arg vector +//***************************************************************************** +inline double ossimEcefVector::angleTo(const ossimEcefVector& v) const +{ + double mag_product = theData.magnitude() * v.theData.magnitude(); + return acosd(theData.dot(v.theData)/mag_product); +} + +//***************************************************************************** +// INLINE METHOD: ossimEcefVector::cross() +// Computes the cross product. +//***************************************************************************** +inline ossimEcefVector ossimEcefVector::cross(const ossimEcefVector& v) const +{ + return ossimEcefVector(theData.cross(v.theData)); +} + +//***************************************************************************** +// INLINE METHOD: ossimEcefVector::unitVector() +// Returns a unit vector parallel to this. +//***************************************************************************** +inline ossimEcefVector ossimEcefVector::unitVector() const +{ + return ossimEcefVector(theData/theData.magnitude()); +} + +//***************************************************************************** +// INLINE METHOD: ossimEcefVector::magnitude() +//***************************************************************************** +inline double ossimEcefVector::magnitude() const +{ + return theData.magnitude(); +} + +inline double ossimEcefVector::length() const +{ + return theData.magnitude(); +} + +//***************************************************************************** +// INLINE METHOD: ossimEcefVector::normalize() +// Normalizes this vector. +//***************************************************************************** +inline double ossimEcefVector::normalize() +{ + double result = theData.magnitude(); + if(result > 1e-15) + { + theData /= result; + } + + return result; +} +#endif + + diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimFilename.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimFilename.cpp new file mode 100644 index 0000000000..75d04cb926 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimFilename.cpp @@ -0,0 +1,665 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Ken Melero +// +// Description: This class provides manipulation of filenames. +// +//************************************************************************* +// $Id: ossimFilename.cpp,v 1.55 2005/11/25 16:14:08 dburken Exp $ + +#include <ossimConfig.h> /* to pick up platform defines */ + +#include <iostream> +using namespace std; + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include "ossimDirectory.h" + +#if defined(_WIN32) +# include <direct.h> +#else +# if HAVE_UNISTD_H +# include <unistd.h> +# endif +# if HAVE_DIRENT_H +# include <dirent.h> +# endif +# if HAVE_FCNTL_H +# include <fcntl.h> +# endif +#endif + +#include <sys/stat.h> + +#ifdef __BORLANDC__ +# include <dir.h> +# include <direct.h> +# include <stdio.h> +# include <stdlib.h> +# include <io.h> +#endif + +#include <base/data_types/ossimFilename.h> +#include <base/data_types/ossimRegExp.h> +#include <base/common/ossimConstants.h> +#include <base/context/ossimNotifyContext.h> + +#if defined(_WIN32) +const char ossimFilename::thePathSeparator = '\\'; +#else +const char ossimFilename::thePathSeparator = '/'; +#endif + +const ossimFilename ossimFilename::NIL=(""); + +ossimFilename::ossimFilename() + : ossimString() +{} + +ossimFilename::ossimFilename(const ossimFilename& src) + : ossimString(src) +{} +ossimFilename::ossimFilename(const ossimString& src) + : ossimString(src) +{} +ossimFilename::ossimFilename(const char* src) + : ossimString(src) +{} + +template <class Iter> ossimFilename::ossimFilename(Iter s, Iter e) + : ossimString(s, e) +{} + +bool ossimFilename::operator == (const ossimFilename& rhs)const +{ +// ossimFilename tempLeft = *this; +// ossimFilename tempRight = rhs; + +// tempLeft.convertBackToForwardSlashes(); +// tempRight.convertBackToForwardSlashes(); + + return ossimString::operator==(rhs); +// return (*this==ossimString(rhs)); +} + +bool ossimFilename::operator == (const ossimString& rhs)const +{ + return ossimString::operator==(rhs); +} + +bool ossimFilename::operator == (const char* rhs)const +{ + return ossimString::operator ==(rhs); +} + +void ossimFilename::convertBackToForwardSlashes() +{ + ossimFilename::iterator currentChar = this->begin(); + + while(currentChar != this->end()) + { + if(*currentChar == '\\') + { + *currentChar = '/'; + } + ++currentChar; + } +} + +void ossimFilename::convertForwardToBackSlashes() +{ + ossimFilename::iterator currentChar = this->begin(); + + while(currentChar != this->end()) + { + if(*currentChar == '/') + { + *currentChar = '\\'; + } + ++currentChar; + } +} + + +bool ossimFilename::exists() const +{ +#if defined(_WIN32) + + struct _stat sbuf; + return( _stat(c_str(), &sbuf ) == 0); +#else + return ((access(c_str(), ossimFilename::OSSIM_EXIST)) == 0); +#endif +} + +bool ossimFilename::isFile() const +{ +#if defined(_WIN32) + + struct _stat sbuf; + if ( _stat(c_str(), &sbuf ) == -1) + return false; + return (_S_IFMT & sbuf.st_mode ? true : false); +#else + struct stat sbuf; + + stat(c_str(), &sbuf); + return ((sbuf.st_mode & S_IFMT) == S_IFREG); +#endif +} + +bool ossimFilename::isDir() const +{ +#if defined(_WIN32) + + struct _stat sbuf; + if ( _stat(c_str(), &sbuf ) == -1) + return false; + return (_S_IFDIR & sbuf.st_mode ? true : false); +#else + struct stat sbuf; + if (stat(c_str(), &sbuf) == -1) + return false; + return (S_ISDIR(sbuf.st_mode)); +#endif +} + +bool ossimFilename::isReadable() const +{ +#if defined(_WIN32) + + struct _stat sbuf; + if ( _stat(c_str(), &sbuf ) == -1) + return false; + return (_S_IREAD & sbuf.st_mode ? true : false); +#else + return (access(c_str(), ossimFilename::OSSIM_READ) == 0); +#endif +} + +bool ossimFilename::isWritable() const +{ +#if defined(_WIN32) + + struct _stat sbuf; + if ( _stat(c_str(), &sbuf ) == -1) + return false; + return (_S_IWRITE & sbuf.st_mode ? true : false); +#else + return (access(c_str(), ossimFilename::OSSIM_WRITE) == 0); +#endif +} + +bool ossimFilename::isExecutable() const +{ +#if defined(_WIN32) + + struct _stat sbuf; + if ( _stat(c_str(), &sbuf ) == -1) + return false; + return (_S_IEXEC & sbuf.st_mode ? true : false); +#else + return (access(c_str(), ossimFilename::OSSIM_EXE) == 0); +#endif +} + +ossimString ossimFilename::ext() const +{ + ossimFilename file = *this; + size_type pos = file.rfind('.'); + if (pos == npos) + { + return ossimFilename::NIL; + } + + return ossimFilename(file.substr(pos+1)); +} + +ossimFilename ossimFilename::file() const +{ + ossimFilename file = *this; + + file.convertBackToForwardSlashes(); + + size_type pos = file.rfind('/'); + if (pos == npos) + return *this; + else + return ossimFilename(file.substr(pos+1)); +} + +ossimFilename ossimFilename::path() const +{ + ossimFilename file = *this; + file.convertBackToForwardSlashes(); + + size_type pos = file.rfind('/'); + + if (pos == 0) + return ossimFilename(ossimFilename("/")); + if (pos == npos) + { + // We got to the end of the file and did not find a path separator. + return ossimFilename::NIL; + } + + return ossimFilename(file.substr(0, pos)); +} + +ossimFilename ossimFilename::drive()const +{ + ossimFilename tempFile(*this); + ossimFilename result; + + tempFile.convertForwardToBackSlashes(); + + ossimRegExp regEx("^([a-z|A-Z])+:"); + + if(regEx.find(tempFile.c_str())) + { + result = ossimFilename(ossimString(this->begin() + regEx.start(), + this->begin() + regEx.end())); + } + else + { + result = ""; + } + + return result; +} + +ossimFilename ossimFilename::fileNoExtension()const +{ + ossimFilename f = *this; + f.convertBackToForwardSlashes(); + + size_type dot_pos = f.rfind('.'); + size_type slash_pos = f.rfind('/'); + + if(dot_pos == npos) + { + if(slash_pos == npos) + { + return *this; + } + else + { + return ossimFilename(this->begin()+slash_pos+1, + this->end()); + } + } + else if(slash_pos == npos) + { + return ossimFilename(this->begin(), this->begin()+dot_pos); + } + else if(slash_pos < dot_pos) + { + return ossimFilename(this->begin()+slash_pos+1, + this->begin() + dot_pos); + } + + return ossimFilename(this->begin()+slash_pos+1, + this->end()); + +} +ossimFilename ossimFilename::noExtension()const +{ + ossimString drivePart; + ossimString pathPart; + ossimString filePart; + ossimString extPart; + + split(drivePart, pathPart, filePart, extPart); + + extPart.clear(); + + ossimFilename result; + + result.merge(drivePart, pathPart, filePart, extPart); + + return result; +} + +ossimFilename& ossimFilename::setExtension(const ossimString& e) +{ + ossimString newExtPart = e; + + //--- + // If e has a dot "." in the front of it strip it off... + //--- + if ( (*(e.begin())) == '.') + { + newExtPart = ossimString(e.begin() + 1, e.end()); + } + + ossimString drivePart; + ossimString pathPart; + ossimString filePart; + ossimString extPart; + + split(drivePart, + pathPart, + filePart, + extPart); + + merge(drivePart, + pathPart, + filePart, + newExtPart); + + return *this; +} + +ossimFilename& ossimFilename::setPath(const ossimString& p) +{ + ossimString drivePart; + ossimString pathPart; + ossimString filePart; + ossimString extPart; + + split(drivePart, + pathPart, + filePart, + extPart); + + merge(drivePart, + p, + filePart, + extPart); + + return *this; +} + +ossimFilename& ossimFilename::setFile(const ossimString& f) +{ + ossimString drivePart; + ossimString pathPart; + ossimString filePart; + ossimString extPart; + + split(drivePart, + pathPart, + filePart, + extPart); + + merge(drivePart, + pathPart, + f, + extPart); + + return *this; +} + + +void ossimFilename::split(ossimString& drivePart, + ossimString& pathPart, + ossimString& filePart, + ossimString& extPart)const +{ + drivePart = drive(); + pathPart = path(); + if(drivePart != "") + { + pathPart = pathPart.substitute(drivePart, ""); + } + filePart = fileNoExtension(); + extPart = ext(); +} + +void ossimFilename::merge(const ossimString& drivePart, + const ossimString& pathPart, + const ossimString& filePart, + const ossimString& extPart) +{ + ossimFilename result = drivePart; + + if(pathPart != "") + { + result = result.dirCat(ossimFilename(pathPart)); + } + + if(filePart!="") + { + result = result.dirCat(ossimFilename(filePart)); + } + + if(extPart != "") + { + result += "."; + result += extPart; + } + + *this = result; +} + +ossimFilename ossimFilename::dirCat(const ossimFilename& file) const +{ + // If this string is empty simply return the input file. + if (empty()) return file; + + ossimFilename dir = *this; + ossimFilename tempFile = file; + + dir.convertBackToForwardSlashes(); + + // Check the end and see if it already has a "/". + string::const_iterator i = dir.end(); + + --i; // decrement past the trailing null. + + if ( (*i) != '/') + { + dir += "/"; + } + + if( (*(tempFile.begin())) == '/') // let's not duplicate a forward slash + { + dir += ossimString(tempFile.begin() + 1, + tempFile.end()); + } + else + { + dir += tempFile; // Already has a separator. + } + + return dir; +} + +ossim_int64 ossimFilename::fileSize() const +{ + struct stat sbuf; + +#ifndef __BORLANDC__ + if (stat(c_str(), &sbuf) == 0) + { + return (ossim_int64)sbuf.st_size; + } + else + { + ifstream in(c_str()); + if(in) + { + in.seekg(SEEK_END); + return (ossim_int64)in.tellg(); + } + } +#else + ifstream in(c_str()); + if(in) + { + in.seekg(SEEK_END); + return (ossim_int64)in.tellg(); + } +#endif + return 0; +} + +bool ossimFilename::createDirectory(bool recurseFlag, + int perm) +{ + if(exists()) return true; + + ossimFilename tempFile = *this; + tempFile.convertBackToForwardSlashes(); + vector<ossimString> result; + + + if(recurseFlag) + { + ossimString::split(result,"/"); + + if(result.size()) + { + ossimString current; + + for(ossim_uint32 i = 1; i < result.size(); ++i) + { + current += ("/"+result[i]); + + if(current != "/") + { + if(!ossimFilename(current).exists()) + { + +#if defined(__BORLANDC__) + if ( _mkdir(current.c_str()) != 0 ) +#elif defined(_WIN32) + if ( mkdir(current.c_str()) != 0 ) +#else + if ( mkdir(current.c_str(), perm) != 0 ) +#endif + { + return false; + } + } + } + } + } + } + else + { +#if defined (__BORLANDC__) + if ( _mkdir(c_str()) != 0 ) + +#elif defined(_WIN32) + if ( mkdir(c_str()) != 0 ) +#else + if ( mkdir(c_str(), perm) != 0 ) +#endif + { + return false; + } + else + { + return true; + } + } + return true; +} + +bool ossimFilename::remove(const ossimFilename& pathname) +{ + bool result = true; +#if defined(__VISUALC__) || defined(__BORLANDC__) || defined(__WATCOMC__) || \ + defined(__GNUWIN32__) || defined(_MSC_VER) + + if(::remove(pathname.c_str()) != 0) + { + result = false; + } +#elif HAVE_UNISTD_H + if(pathname.isDir()) + { + result = (rmdir(pathname) >=0); + } + else if (unlink(pathname.c_str()) < 0) + { + result = false; + } +#else + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "WARNING: " + << "ossimFilename::remove, Not supported by platform!" + << endl; + } +#endif /* HAVE_UNISTD_H */ + + return result; +} + +bool ossimFilename::wildcardRemove(const ossimFilename& pathname) +{ + std::vector<ossimFilename> fileListToRemove; + ossimFilename tempPathname = pathname; + + if(!tempPathname.isDir()) + { + ossimFilename file = tempPathname.file(); + ossimFilename path = tempPathname.path(); + if(path == "") + { + path = "."; + } + ossimDirectory dir; + if(dir.open(path)) + { + dir.findAllFilesThatMatch(fileListToRemove, + file.c_str()); + } + else + { + } + } + else + { + fileListToRemove.push_back(ossimFilename(pathname)); + } + ossim_uint32 idx = 0; + bool result = true; + for(idx = 0; idx < fileListToRemove.size(); ++idx) + { +#if defined(__VISUALC__) || defined(__BORLANDC__) || defined(__WATCOMC__) || \ + defined(__GNUWIN32__) || defined(_MSC_VER) + + if(remove(fileListToRemove[idx].c_str()) != 0) + { + result = false; + } +#elif HAVE_UNISTD_H + if (unlink(fileListToRemove[idx]) == -1) + { + result = false; + } +#else + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "WARNING: " + << "ossimFilename::remove, Not supported by platform!" + << endl; + } + result = false; +#endif /* HAVE_UNISTD_H */ + } + return result; +} + +bool ossimFilename::remove()const +{ + return ossimFilename::remove(*this); +} + +bool ossimFilename::wildcardRemove()const +{ + return ossimFilename::wildcardRemove(*this); +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimFilename.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimFilename.h new file mode 100644 index 0000000000..8b79ec1973 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimFilename.h @@ -0,0 +1,179 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Ken Melero +// +// Description: This class provides manipulation of filenames. +// +//************************************************************************* +// $Id: ossimFilename.h,v 1.21 2005/11/25 16:14:08 dburken Exp $ + +#ifndef ossimFilename_HEADER +#define ossimFilename_HEADER + +#include "base/common/ossimConstants.h" +#include "ossimString.h" + +class OSSIMDLLEXPORT ossimFilename : public ossimString +{ +public: + enum AccessModes + { + OSSIM_READ_WRITE = 6, + OSSIM_READ = 4, + OSSIM_WRITE = 2, + OSSIM_EXE = 1, // The PC docs say that this is ignored + OSSIM_EXIST = 0 + }; + ossimFilename(); + ossimFilename(const ossimFilename& src); + ossimFilename(const ossimString& src); + ossimFilename(const char* src); + + template <class Iter> ossimFilename(Iter s, Iter e); + + static const ossimFilename NIL; + + bool operator == (const ossimFilename& rhs)const; + + bool operator == (const ossimString& rhs)const; + bool operator == (const char* rhs)const; + + void convertBackToForwardSlashes(); + void convertForwardToBackSlashes(); + + // Methods to test ossimFilename for various states. + bool exists() const; + bool isFile() const; + bool isDir() const; + bool isReadable() const; + bool isWritable() const; + bool isExecutable() const; + ossim_int64 fileSize() const; + + // Methods to access parts of the ossimFilename. + + /** + * @return "tif" if file is "/data/images/t1.tif". + * + * @note The '.' (dot) is not returned. + */ + ossimString ext() const; + + /** + * @return @return "/data/images" if file is "/data/images/t1.tif". + */ + ossimFilename path() const; + + /** + * @return @return "c:" if file is "c:\data\images\t1.tif". + */ + ossimFilename drive() const; + + /** + * @return @return "t1.tif" if file is "/data/images/t1.tif". + */ + ossimFilename file() const; + + /** + * @return @return "t1.tif" if file is "/data/images/t1.tif". + */ + ossimFilename fileNoExtension() const; + + /** + * @return @return "/data/images/t1" if file is "/data/images/t1.tif". + * + * @note The '.' (dot) is not returned. + */ + ossimFilename noExtension() const; + + /** + * Sets the extension of a file name. + * + * Given: + * ossimFilename f = "foo"; + * f.setExtension("tif"); + * f now equals "foo.tif" + * + * Given: + * ossimFilename f = "foo.jpg"; + * f.setExtension("tif"); + * f now equals "foo.tif" + * + * Given: + * ossimFilename f = "foo.jpg"; + * f.setExtension(".tif"); + * f now equals "foo.tif" + * + * Given: + * ossimFilename f = "foo."; + * ossimFilename f2; + * f2 = f.setExtension("tif"); + * f now equals "foo.tif" + * f2 now equals "foo.tif" + * + * @param e Extension to add or replace. + * + * @returns a reference to this. + */ + ossimFilename& setExtension(const ossimString& e); + + ossimFilename& setPath(const ossimString& p); + ossimFilename& setFile(const ossimString& f); + + void split(ossimString& drivePart, + ossimString& pathPart, + ossimString& filePart, + ossimString& extPart)const; + + void merge(const ossimString& drivePart, + const ossimString& pathPart, + const ossimString& filePart, + const ossimString& extPart); + /*! + * Returns file appended onto this string. Path seperator is always placed + * between this and file. Returns file if this string is empty. + * Given: this = /foo and file = bar output = /foo/bar + * Given: this = /foo/ and file = bar output = /foo/bar + */ + ossimFilename dirCat(const ossimFilename& file) const; + + /*! + */ + bool createDirectory(bool recurseFlag=true, + int perm=0775); + + /*! + * Removes pathname from filesystem if supported by platform. + * Return true on success, false on error. + * If supported will set errno and output equivalent string if one occurs. + */ + static bool remove(const ossimFilename& pathname); + + /** + * Will use a wildcard remove. NOTE: This is in + * a regular expression format so if you want all + * files with prefix myfile to be erased then you would give + * it <path>/myfile.* + * + * The . here is a regular expression '.' character which says any character + * and the * "is any number of" + * + */ + static bool wildcardRemove(const ossimFilename& pathname); + + bool remove()const; + bool wildcardRemove()const; + + /*! + * since windows uses \ for path separation + * and unix / we need to be consistent. + */ + static const char thePathSeparator; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimFpt.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimFpt.cpp new file mode 100644 index 0000000000..2e0e71a2f0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimFpt.cpp @@ -0,0 +1,107 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// Description: +// +// Contains class definitions for ossimFpt. +// +//******************************************************************* +// $Id: ossimFpt.cpp,v 1.3 2001/10/27 20:16:11 gpotts Exp $ + +#include <iostream> +#include <iomanip> + +#include "ossimFpt.h" +#include "ossimIpt.h" +#include "ossimDpt.h" + +//******************************************************************* +// Public Constructor: +//******************************************************************* +ossimFpt::ossimFpt(const ossimIpt& pt) + : + x(pt.x), y(pt.y) +{ + if(pt.hasNans()) + { + makeNan(); + } +} + +//******************************************************************* +// Public Constructor: +//******************************************************************* +ossimFpt::ossimFpt(const ossimDpt& pt) + : + x(pt.x), y(pt.y) +{ + if(pt.hasNans()) + { + makeNan(); + } +} + +//******************************************************************* +// Public Method: +//******************************************************************* +const ossimFpt& ossimFpt::operator=(const ossimDpt& pt) +{ + x = pt.x; + y = pt.y; + + if(pt.hasNans()) + { + makeNan(); + } + return *this; +} + +//******************************************************************* +// Public Method: +//******************************************************************* +const ossimFpt& ossimFpt::operator=(const ossimIpt& pt) +{ + x = pt.x; + y = pt.y; + if(pt.hasNans()) + { + makeNan(); + } + + return *this; +} + +//******************************************************************* +// Public Method: +//******************************************************************* +void ossimFpt::print(std::ostream& os) const +{ + os << std::setiosflags(std::ios::fixed) << std::setprecision(15) + << "( " << x << " " << y << " )"; +} + +//******************************************************************* +// friend function: +//******************************************************************* +std::ostream& operator<<(std::ostream& os, const ossimFpt& pt) +{ + pt.print(os); + + return os; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimFpt.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimFpt.h new file mode 100644 index 0000000000..f0506a2fa4 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimFpt.h @@ -0,0 +1,100 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// +// Description: +// +// Contains class declaration for fpt. +// Used to represent a two dimensional point containing data members x and y. +//******************************************************************* +// $Id: ossimFpt.h,v 1.7 2003/05/13 11:31:02 dburken Exp $ + +#ifndef ossimFpt_HEADER +#define ossimFpt_HEADER +#include <iostream> +#include "base/common/ossimConstants.h" +#include "base/common/ossimCommon.h" + +// Forward class declarations. +class OSSIMDLLEXPORT ossimIpt; +class OSSIMDLLEXPORT ossimDpt; + + +class OSSIMDLLEXPORT ossimFpt +{ +public: + + ossimFpt() : x(0), y(0) {} + + ossimFpt(ossim_float32 x, ossim_float32 y) + : x(x), y(y) + {} + + ossimFpt(ossim_float64 x, ossim_float64 y) + : x((ossim_float64)x), y((ossim_float64)y) + {} + + ossimFpt(const ossimFpt& pt) : x(pt.x), y(pt.y) {} + + ossimFpt(const ossimDpt& pt); + + ossimFpt(const ossimIpt& pt); + + const ossimFpt& operator=(const ossimFpt& pt); + + const ossimFpt& operator=(const ossimDpt&); + + const ossimFpt& operator=(const ossimIpt&); + + bool operator==(const ossimFpt& pt) const + { return ( (x == pt.x) && (y == pt.y) ); } + + bool operator!=(const ossimFpt& pt) const + { return ( (x != pt.x) || (y != pt.y) ); } + + void makeNan(){x = OSSIM_FLT_NAN; y=OSSIM_FLT_NAN;} + + bool hasNans()const + { + return (ossimIsNan(x) || ossimIsNan(y)); + } + + void print(std::ostream& os) const; + + friend std::ostream& operator<<(std::ostream& os, const ossimFpt& pt); + + //*** + // Public data members: + //*** + ossim_float32 x; + ossim_float32 y; +}; + +inline const ossimFpt& ossimFpt::operator=(const ossimFpt& pt) +{ + if (this != &pt) + { + x = pt.x; + y = pt.y; + } + + return *this; +} + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimFpt3d.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimFpt3d.cpp new file mode 100644 index 0000000000..443824f9e1 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimFpt3d.cpp @@ -0,0 +1,59 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// Description: +// +// Contains class definitions for ossimFpt3d. +// +//******************************************************************* +// $Id: ossimFpt3d.cpp,v 1.1.1.1 2001/02/05 20:13:22 dburken Exp $ + +#include <iostream> +#include <iomanip> +using namespace std; + +#include "ossimFpt3d.h" + +//******************************************************************* +// Public Method: +//******************************************************************* +ostream& ossimFpt3d::print(ostream& os) const +{ + os << setiosflags(ios::fixed) << setprecision(14) + << "( " << x << " " << y << " " << z << " )"; + return os; +} + +//******************************************************************* +// friend function: +//******************************************************************* +ostream& operator<<(ostream& os, const ossimFpt3d& pt) +{ + return pt.print(os); +} + +//******************************************************************* +// friend function: +//******************************************************************* +istream& operator>>(istream& is, ossimFpt3d& pt) +{ + is >> pt.x >> pt.y >> pt.z; + + return is; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimFpt3d.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimFpt3d.h new file mode 100644 index 0000000000..276692fdc8 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimFpt3d.h @@ -0,0 +1,63 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// +// Description: +// +// Contains class declaration for fpt3d. +// +// Used to represent a three dimensional point containing an x and y data +// member. +// +//******************************************************************* +// $Id: ossimFpt3d.h,v 1.3 2003/05/13 11:31:02 dburken Exp $ + +#ifndef ossimFpt3d_HEADER +#define ossimFpt3d_HEADER + +#include "../common/ossimConstants.h" +#include "ossimFpt.h" + + +class OSSIMDLLEXPORT ossimFpt3d +{ +public: + + ossimFpt3d() + : x(0.0), y(0.0), z(0.0) + {} + ossimFpt3d(const ossim_float32& aX, + const ossim_float32& aY, + const ossim_float32& aZ) + : x(aX), y(aY), z(aZ) + {} + + ossimFpt pt2d() const { return ossimFpt(x, y); } + + ostream& print(ostream& os) const; + + friend ostream& operator<<(ostream& os, const ossimFpt3d& pt); + friend istream& operator>>(istream& is, ossimFpt3d& pt); + + ossim_float32 x; + ossim_float32 y; + ossim_float32 z; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimGeoPolygon.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimGeoPolygon.cpp new file mode 100644 index 0000000000..8366f6786a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimGeoPolygon.cpp @@ -0,0 +1,356 @@ +//***************************************************************************** +// FILE: ossimPolygon.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// AUTHOR: Garrett Potts (gpotts@imagelinks.com) +// +//***************************************************************************** +// $Id: ossimGeoPolygon.cpp,v 1.10 2003/09/09 18:33:57 dburken Exp $ + +#include <sstream> +#include <algorithm> +#include "ossimGeoPolygon.h" +#include "base/factory/ossimDatumFactory.h" +#include "base/data_types/datum/ossimDatum.h" +#include "base/common/ossimKeywordNames.h" + +static const char* NUMBER_VERTICES_KW = "number_vertices"; + +std::ostream& operator <<(std::ostream& out, const ossimGeoPolygon& poly) +{ + if(poly.size()) + { + if(poly.size() >1) + { + for(ossim_uint32 i = 0; i < poly.size()-1; ++i) + { + out << "P" << i << ": " << poly[i] << endl; + } + out << "P" << (poly.size()-1) + << ": " << poly[poly.size()-1] << endl; + } + else + { + out << "P0: " << poly[0] << endl; + } + } + + return out; +} + +bool ossimGeoPolygon::hasNans()const +{ + int upper = (int)theVertexList.size(); + int i = 0; + + for(i = 0; i < upper; ++i) + { + if(theVertexList[i].hasNans()) + { + return true; + } + } + + return false; +} + +bool ossimGeoPolygon::vertex(int index, ossimGpt& v) const +{ + if((index >= (int)theVertexList.size()) || + (index < 0)) + { + return false; + } + + v = theVertexList[index]; + theCurrentVertex = index; + + return true; +} + +bool ossimGeoPolygon::nextVertex(ossimDpt& v) const +{ + ++theCurrentVertex; + if(theCurrentVertex >= (ossim_int32)theVertexList.size()) + { + return false; + } + v = theVertexList[theCurrentVertex]; + + return true; +} + +void ossimGeoPolygon::stretchOut(ossimGeoPolygon& newPolygon, + double displacement) +{ + newPolygon.resize(size()); + if(size() >= 3) + { + const ossimDatum* datum = theVertexList[0].datum(); + checkOrdering(); + double signMult = 1.0; + if(theOrderingType == OSSIM_COUNTERCLOCKWISE_ORDER) + { + signMult = -1.0; + } + + ossimDpt prev, current, next; + + ossim_uint32 prevI; + ossim_uint32 currentI; + ossim_uint32 nextI; + ossim_uint32 i = 0; + ossim_uint32 upper = size(); + + bool equalEndsFlag = false; + if(theVertexList[0] == theVertexList[theVertexList.size()-1]) + { + equalEndsFlag = true; + prevI = 0; + currentI = 1; + nextI = 2; + i = 1; + --upper; + } + else + { + equalEndsFlag = false; + prevI = size()-1; + currentI = 0; + nextI = 1; + } + for(; i < upper;++i) + { + prev = theVertexList[prevI]; + current = theVertexList[currentI]; + next = theVertexList[nextI]; + + ossimDpt averageNormal; + + ossimDpt diffPrev = current - prev; + ossimDpt diffNext = next - current; + + diffPrev = diffPrev*(1.0/diffPrev.length()); + diffNext = diffNext*(1.0/diffNext.length()); + + ossimDpt diffPrevNormal(-diffPrev.y, + diffPrev.x); + ossimDpt diffNextNormal(-diffNext.y, + diffNext.x); + + averageNormal = (diffPrevNormal + diffNextNormal); + averageNormal = averageNormal*(signMult*(1.0/averageNormal.length())); + ossimDpt newPoint = ossimDpt( theVertexList[i].lond(), + theVertexList[i].latd()) + + averageNormal*displacement; + newPolygon[i].latd(newPoint.lat); + newPolygon[i].lond(newPoint.lon); + newPolygon[i].height(theVertexList[i].height()); + newPolygon[i].datum(datum); + + ++prevI; + ++currentI; + ++nextI; + + prevI%=size(); + nextI%=size(); + } + if(equalEndsFlag) + { + + prev = theVertexList[theVertexList.size()-2]; + current = theVertexList[0]; + next = theVertexList[1]; + + ossimDpt averageNormal; + + ossimDpt diffPrev = current - prev; + ossimDpt diffNext = next - current; + + diffPrev = diffPrev*(1.0/diffPrev.length()); + diffNext = diffNext*(1.0/diffNext.length()); + + ossimDpt diffPrevNormal(-diffPrev.y, + diffPrev.x); + ossimDpt diffNextNormal(-diffNext.y, + diffNext.x); + + averageNormal = (diffPrevNormal + diffNextNormal); + averageNormal = averageNormal*(signMult*(1.0/averageNormal.length())); + ossimDpt newPoint = ossimDpt( theVertexList[i].lond(), + theVertexList[i].latd()) + + averageNormal*displacement; + newPolygon[0].latd(newPoint.lat); + newPolygon[0].lond(newPoint.lon); + newPolygon[0].height(theVertexList[i].height()); + newPolygon[0].datum(datum); + + newPolygon[theVertexList.size()-1] = newPolygon[0]; + } + } +} + + +double ossimGeoPolygon::area()const +{ + double area = 0; + int i=0; + int j=0; + int size = theVertexList.size(); + + for (i=0;i<(int)size;i++) + { + j = (i + 1) % (int)size; + area += theVertexList[i].lon * theVertexList[j].lat; + area -= theVertexList[i].lat * theVertexList[j].lon; + } + + area /= 2; + + return area; +} + +void ossimGeoPolygon::reverseOrder() +{ + std::reverse(theVertexList.begin(), theVertexList.end()); + + if(theOrderingType == OSSIM_COUNTERCLOCKWISE_ORDER) + { + theOrderingType = OSSIM_CLOCKWISE_ORDER; + } + else if(theOrderingType == OSSIM_CLOCKWISE_ORDER) + { + theOrderingType = OSSIM_COUNTERCLOCKWISE_ORDER; + } + +} + +void ossimGeoPolygon::checkOrdering()const +{ + if(theOrderingType == OSSIM_VERTEX_ORDER_UNKNOWN) + { + double areaValue = area(); + if(areaValue > 0) + { + theOrderingType = OSSIM_COUNTERCLOCKWISE_ORDER; + } + else if(areaValue <= 0) + { + theOrderingType = OSSIM_CLOCKWISE_ORDER; + } + } +} + +ossimGpt ossimGeoPolygon::computeCentroid()const +{ + if(!size()) + { + return ossimGpt(); + } + ossimDpt average(0.0,0.0); + double height=0.0; + for(ossim_uint32 i = 0; i < size(); ++i) + { + average += ossimDpt(theVertexList[i]); + height += theVertexList[i].height(); + } + + + average.x /= size(); + average.y /= size(); + height /= size(); + + return ossimGpt(average.y, average.x, height, theVertexList[0].datum()); +} + +bool ossimGeoPolygon::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + int i = 0; + + kwl.add(prefix, + ossimKeywordNames::TYPE_KW, + "ossimGeoPolygon", + true); + kwl.add(prefix, + NUMBER_VERTICES_KW, + theVertexList.size(), + true); + if(theVertexList.size()) + { + kwl.add(prefix, + ossimKeywordNames::DATUM_KW, + theVertexList[0].datum()->code(), + true); + } + else + { + kwl.add(prefix, + ossimKeywordNames::DATUM_KW, + "WGE", + true); + } + + for(i = 0; i < (int)theVertexList.size();++i) + { + ossimString vert = "v"+ossimString::toString(i); + ossimString value = (ossimString::toString(theVertexList[i].latd()) + " " + + ossimString::toString(theVertexList[i].lond()) + " " + + ( theVertexList[i].isHgtNan()?ossimString("nan"):ossimString::toString(theVertexList[i].height()))); + kwl.add(prefix, + vert.c_str(), + value.c_str(), + true); + } + + return true; +} + +bool ossimGeoPolygon::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* number_vertices = kwl.find(prefix, NUMBER_VERTICES_KW); + const char* datumStr = kwl.find(prefix, ossimKeywordNames::DATUM_KW); + const ossimDatum* datum = ossimDatumFactory::instance()->create(datumStr); + + theVertexList.clear(); + int i = 0; + int vertexCount = ossimString(number_vertices).toLong(); + double lat = 0.0, lon =0.0; + ossimString height; + for(i = 0; i < vertexCount; ++i) + { + ossimString v = kwl.find(prefix, (ossimString("v")+ossimString::toString(i)).c_str()); + v = v.trim(); + + istringstream vStream(v); + vStream >> lat >> lon >> height; + height = height.trim(); + if(height == "nan") + { + theVertexList.push_back(ossimGpt(lat, lon, OSSIM_DBL_NAN, datum)); + } + else + { + theVertexList.push_back(ossimGpt(lat, lon, height.toDouble(), datum)); + } + } + + return true; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimGeoPolygon.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimGeoPolygon.h new file mode 100644 index 0000000000..e9ef92e87d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimGeoPolygon.h @@ -0,0 +1,170 @@ +//***************************************************************************** +// FILE: ossimPolygon.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// AUTHOR: Garrett Potts (gpotts@imagelinks.com) +// +//***************************************************************************** +// $Id: ossimGeoPolygon.h,v 1.13 2006/01/03 20:55:56 gpotts Exp $ +#ifndef ossimGeoPolygon_HEADER +#define ossimGeoPolygon_HEADER +#include <vector> +#include "ossimGpt.h" +#include "ossimKeywordlist.h" + +class OSSIMDLLEXPORT ossimGeoPolygon +{ +public: + friend OSSIM_DLL std::ostream& operator <<(std::ostream& out, const ossimGeoPolygon& poly); + ossimGeoPolygon():theCurrentVertex(-1), + theOrderingType(OSSIM_VERTEX_ORDER_UNKNOWN) + {} + ossimGeoPolygon(const std::vector<ossimGpt>& points) + :theVertexList(points), + theOrderingType(OSSIM_VERTEX_ORDER_UNKNOWN) + { + theCurrentVertex = 0; + } + ossimGeoPolygon(const ossimGeoPolygon& rhs) + { + theVertexList = rhs.theVertexList; + theOrderingType = rhs.theOrderingType; + theAttributeList = rhs.theAttributeList; + theHoleList = rhs.theHoleList; + theCurrentVertex = rhs.theCurrentVertex; + } + + void addPoint(const ossimGpt& pt) + { + theVertexList.push_back(pt); + } + void addPoint(double lat, double lon, double h=OSSIM_DBL_NAN, const ossimDatum* datum=NULL) + { + theVertexList.push_back(ossimGpt(lat, lon, h, datum)); + } + void addAttribute( const ossimString& attribute ) + { + theAttributeList.push_back( attribute ); + } + void addHole( const ossimGeoPolygon& polygon ) + { + theHoleList.push_back( polygon ); + } + ossimGpt& operator[](int index) + { + return theVertexList[index]; + } + const ossimGpt& operator[](int index)const + { + return theVertexList[index]; + } + + const vector<ossimGpt>& getVertexList()const + { + return theVertexList; + } + vector<ossimString>& getAttributeList() + { + return theAttributeList; + } + vector<ossimGeoPolygon>& getHoleList() + { + return theHoleList; + } + + void clear() + { + theVertexList.clear(); + } + ossim_uint32 size()const + { + return (ossim_uint32)theVertexList.size(); + } + void resize(ossim_uint32 newSize) + { + theVertexList.resize(newSize); + theCurrentVertex = 0; + theOrderingType = OSSIM_VERTEX_ORDER_UNKNOWN; + } + const ossimGeoPolygon& operator = (const vector<ossimGpt>& rhs) + { + theVertexList = rhs; + theCurrentVertex = 0; + theOrderingType = OSSIM_VERTEX_ORDER_UNKNOWN; + + return *this; + } + + const ossimGeoPolygon& operator = (const ossimGeoPolygon& rhs) + { + if(&rhs != this) + { + theVertexList = rhs.theVertexList; + theCurrentVertex = rhs.theCurrentVertex; + theAttributeList = rhs.theAttributeList; + theHoleList = rhs.theHoleList; + } + theOrderingType = rhs.theOrderingType; + + return *this; + } + void stretchOut(ossimGeoPolygon& newPolygon, + double displacement); + double area()const; + + ossimGpt computeCentroid()const; + + bool vertex(int index, ossimGpt& v) const; + bool nextVertex(ossimDpt& v) const; + bool hasNans()const; + void reverseOrder(); + + bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + void checkOrdering()const; + ossimVertexOrdering getOrdering()const + { + if(theOrderingType == OSSIM_VERTEX_ORDER_UNKNOWN) + { + checkOrdering(); + } + return theOrderingType; + } + void setOrdering(ossimVertexOrdering ordering) + { + theOrderingType = ordering; + } +protected: + vector<ossimGpt> theVertexList; + vector<ossimString> theAttributeList; + vector<ossimGeoPolygon> theHoleList; + mutable ossim_int32 theCurrentVertex; + + /*! + * This enumeration is found in ossimConstants.h + */ + mutable ossimVertexOrdering theOrderingType; + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimGeocent.c b/Utilities/OSSIM/ossim_core/base/data_types/ossimGeocent.c new file mode 100644 index 0000000000..0ca395230b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimGeocent.c @@ -0,0 +1,384 @@ +/***************************************************************************/ +/* RSC IDENTIFIER: GEOCENTRIC + * + * ABSTRACT + * + * This component provides conversions between Geodetic coordinates (latitude, + * longitude in radians and height in meters) and Geocentric coordinates + * (X, Y, Z) in meters. + * + * ERROR HANDLING + * + * This component checks parameters for valid values. If an invalid value + * is found, the error code is combined with the current error code using + * the bitwise or. This combining allows multiple error codes to be + * returned. The possible error codes are: + * + * GEOCENT_NO_ERROR : No errors occurred in function + * GEOCENT_LAT_ERROR : Latitude out of valid range + * (-90 to 90 degrees) + * GEOCENT_LON_ERROR : Longitude out of valid range + * (-180 to 360 degrees) + * GEOCENT_A_ERROR : Semi-major axis less than or equal to zero + * GEOCENT_INV_F_ERROR : Inverse flattening outside of valid range + * (250 to 350) + * + * + * REUSE NOTES + * + * GEOCENTRIC is intended for reuse by any application that performs + * coordinate conversions between geodetic coordinates and geocentric + * coordinates. + * + * + * REFERENCES + * + * An Improved Algorithm for Geocentric to Geodetic Coordinate Conversion, + * Ralph Toms, February 1996 UCRL-JC-123138. + * + * Further information on GEOCENTRIC can be found in the Reuse Manual. + * + * GEOCENTRIC originated from : U.S. Army Topographic Engineering Center + * Geospatial Information Division + * 7701 Telegraph Road + * Alexandria, VA 22310-3864 + * + * LICENSES + * + * None apply to this component. + * + * RESTRICTIONS + * + * GEOCENTRIC has no restrictions. + * + * ENVIRONMENT + * + * GEOCENTRIC was tested and certified in the following environments: + * + * 1. Solaris 2.5 with GCC version 2.8.1 + * 2. Windows 95 with MS Visual C++ version 6 + * + * MODIFICATIONS + * + * Date Description + * ---- ----------- + * 25-02-97 Original Code + * + */ + + +/***************************************************************************/ +/* + * INCLUDES + */ +#include <float.h> +#include <math.h> +#include <base/data_types/ossimGeocent.h> +/* + * math.h - is needed for calls to sin, cos, tan and sqrt. + * geocent.h - is needed for Error codes and prototype error checking. + */ + + +/***************************************************************************/ +/* + * DEFINES + */ +#define PI 3.14159265358979323e0 +#define PI_OVER_2 (PI / 2.0e0) +#define FALSE 0 +#define TRUE 1 +#define COS_67P5 0.38268343236508977 /* cosine of 67.5 degrees */ +#define AD_C 1.0026000 /* Toms region 1 constant */ + + +/***************************************************************************/ +/* + * GLOBAL DECLARATIONS + */ +/* Ellipsoid parameters, default to WGS 84 */ +double Geocent_a = 6378137.0; /* Semi-major axis of ellipsoid in meters */ +double Geocent_f = 1 / 298.257223563; /* Flattening of ellipsoid */ + +double Geocent_e2 = 0.0066943799901413800; /* Eccentricity squared */ +double Geocent_ep2 = 0.00673949675658690300; /* 2nd eccentricity squared */ +/* + * These state variables are for optimization purposes. The only function + * that should modify them is Set_Geocentric_Parameters. + */ + + +/***************************************************************************/ +/* + * FUNCTIONS + */ + + +long Set_Geocentric_Parameters (double a, + double f) +{ /* BEGIN Set_Geocentric_Parameters */ +/* + * The function Set_Geocentric_Parameters receives the ellipsoid parameters + * as inputs and sets the corresponding state variables. + * + * a : Semi-major axis of ellipsoid, in meters. (input) + * f : Flattening of ellipsoid. (input) + */ + +/* double inv_f = 1 / f; */ + long Error_Code = GEOCENT_NO_ERROR; + +#if 0 + if (a <= 0.0) + Error_Code |= GEOCENT_A_ERROR; + if ((inv_f < 250) || (inv_f > 350)) + { /* Inverse flattening must be between 250 and 350 */ + Error_Code |= GEOCENT_INV_F_ERROR; + } +#endif + if (!Error_Code) + { + Geocent_a = a; + Geocent_f = f; + Geocent_e2 = 2 * Geocent_f - Geocent_f * Geocent_f; + Geocent_ep2 = (1 / (1 - Geocent_e2)) - 1; + } + return (Error_Code); +} /* END OF Set_Geocentric_Parameters */ + + +void Get_Geocentric_Parameters (double *a, + double *f) +{ /* BEGIN Get_Geocentric_Parameters */ +/* + * The function Get_Geocentric_Parameters returns the ellipsoid parameters + * to be used in geocentric coordinate conversions. + * + * a : Semi-major axis of ellipsoid, in meters. (output) + * f : Flattening of ellipsoid. (output) + */ + + *a = Geocent_a; + *f = Geocent_f; +} /* END OF Get_Geocentric_Parameters */ + + +long Convert_Geodetic_To_Geocentric (double Latitude, + double Longitude, + double Height, + double *X, + double *Y, + double *Z) +{ /* BEGIN Convert_Geodetic_To_Geocentric */ +/* + * The function Convert_Geodetic_To_Geocentric converts geodetic coordinates + * (latitude, longitude, and height) to geocentric coordinates (X, Y, Z), + * according to the current ellipsoid parameters. + * + * Latitude : Geodetic latitude in radians (input) + * Longitude : Geodetic longitude in radians (input) + * Height : Geodetic height, in meters (input) + * X : Calculated Geocentric X coordinate, in meters (output) + * Y : Calculated Geocentric Y coordinate, in meters (output) + * Z : Calculated Geocentric Z coordinate, in meters (output) + * + */ + long Error_Code = GEOCENT_NO_ERROR; + double Rn; /* Earth radius at location */ + double Sin_Lat; /* sin(Latitude) */ + double Sin2_Lat; /* Square of sin(Latitude) */ + double Cos_Lat; /* cos(Latitude) */ + +#if 0 + if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2)) + { /* Latitude out of range */ + Error_Code |= GEOCENT_LAT_ERROR; + } + if ((Longitude < -PI) || (Longitude > (2*PI))) + { /* Longitude out of range */ + Error_Code |= GEOCENT_LON_ERROR; + } +#endif + if (!Error_Code) + { /* no errors */ + if (Longitude > PI) + Longitude -= (2*PI); + Sin_Lat = sin(Latitude); + Cos_Lat = cos(Latitude); + Sin2_Lat = Sin_Lat * Sin_Lat; + Rn = Geocent_a / (sqrt(1.0e0 - Geocent_e2 * Sin2_Lat)); + *X = (Rn + Height) * Cos_Lat * cos(Longitude); + *Y = (Rn + Height) * Cos_Lat * sin(Longitude); + *Z = ((Rn * (1 - Geocent_e2)) + Height) * Sin_Lat; + + } + return (Error_Code); +} /* END OF Convert_Geodetic_To_Geocentric */ + +void Convert_Geocentric_To_Geodetic (double X, + double Y, + double Z, + double *Latitude, + double *Longitude, + double *Height) +{ + /* BEGIN Convert_Geocentric_To_Geodetic */ + /* + * The function Convert_Geocentric_To_Geodetic converts geocentric + * coordinates (X, Y, Z) to geodetic coordinates (latitude, longitude, + * and height), according to the current ellipsoid parameters. + * + * X : Geocentric X coordinate, in meters. (input) + * Y : Geocentric Y coordinate, in meters. (input) + * Z : Geocentric Z coordinate, in meters. (input) + * Latitude : Calculated latitude value in radians. (output) + * Longitude : Calculated longitude value in radians. (output) + * Height : Calculated height value, in meters. (output) + * + */ + + double d = sqrt(pow(X, 2) + pow(Y, 2)); + + double phi2 = Z / ((1 - Geocent_e2) * d); + double p = 1.0; + double phi1 = 0.0; + double N1 = 0.0; + double height1 = 0.0; + int iterIdx = 0; + const int MAX_ITER = 10; + if (phi2 != 0.0) + { + while ( (p > 1e-16) && (iterIdx < MAX_ITER)) + { + phi1 = phi2; + N1 = Geocent_a / sqrt(1.0 - (Geocent_e2 * pow(sin(phi1), 2.0))); + height1 = (d / cos(phi1) - N1); + phi2 = atan((Z / d) * (1.0 + (Geocent_e2 * N1 * sin(phi1)) / Z)); + p = fabs(phi2 - phi1); + ++iterIdx; + /* printf("phi: %e phi2: %e p: %e \n", phi1, phi2, p); */ + } + } + else + { + phi1 = phi2; + N1 = Geocent_a / sqrt(1.0 - (Geocent_e2 * pow(sin(phi1), 2.0))); + height1 = (d / cos(phi1)) - N1; + } + + /* *Latitude = phi2 * 180/PI; */ + /* *Longitude = atan2(Y, X) * 180/PI; */ + *Latitude = phi2; + *Longitude = atan2(Y, X); + *Height = height1; +} /* END OF Convert_Geocentric_To_Geodetic */ + + +#if 0 +void Convert_Geocentric_To_Geodetic (double X, + double Y, + double Z, + double *Latitude, + double *Longitude, + double *Height) +{ /* BEGIN Convert_Geocentric_To_Geodetic */ +/* + * The function Convert_Geocentric_To_Geodetic converts geocentric + * coordinates (X, Y, Z) to geodetic coordinates (latitude, longitude, + * and height), according to the current ellipsoid parameters. + * + * X : Geocentric X coordinate, in meters. (input) + * Y : Geocentric Y coordinate, in meters. (input) + * Z : Geocentric Z coordinate, in meters. (input) + * Latitude : Calculated latitude value in radians. (output) + * Longitude : Calculated longitude value in radians. (output) + * Height : Calculated height value, in meters. (output) + * + * The method used here is derived from 'An Improved Algorithm for + * Geocentric to Geodetic Coordinate Conversion', by Ralph Toms, Feb 1996 + */ + +/* Note: Variable names follow the notation used in Toms, Feb 1996 */ + + double W; /* distance from Z axis */ + double W2; /* square of distance from Z axis */ + double T0; /* initial estimate of vertical component */ + double T1; /* corrected estimate of vertical component */ + double S0; /* initial estimate of horizontal component */ + double S1; /* corrected estimate of horizontal component */ + double Sin_B0; /* sin(B0), B0 is estimate of Bowring aux variable */ + double Sin3_B0; /* cube of sin(B0) */ + double Cos_B0; /* cos(B0) */ + double Sin_p1; /* sin(phi1), phi1 is estimated latitude */ + double Cos_p1; /* cos(phi1) */ + double Rn; /* Earth radius at location */ + double Sum; /* numerator of cos(phi1) */ + int At_Pole; /* indicates location is in polar region */ + double Geocent_b = Geocent_a * (1 - Geocent_f); /* Semi-minor axis of ellipsoid, in meters */ + + At_Pole = FALSE; + if (X != 0.0) + { + *Longitude = atan2(Y,X); + } + else + { + if (Y > 0) + { + *Longitude = PI_OVER_2; + } + else if (Y < 0) + { + *Longitude = -PI_OVER_2; + } + else + { + At_Pole = TRUE; + *Longitude = 0.0; + if (Z > 0.0) + { /* north pole */ + *Latitude = PI_OVER_2; + } + else if (Z < 0.0) + { /* south pole */ + *Latitude = -PI_OVER_2; + } + else + { /* center of earth */ + *Latitude = PI_OVER_2; + *Height = -Geocent_b; + return; + } + } + } + W2 = X*X + Y*Y; + W = sqrt(W2); + T0 = Z * AD_C; + S0 = sqrt(T0 * T0 + W2); + Sin_B0 = T0 / S0; + Cos_B0 = W / S0; + Sin3_B0 = Sin_B0 * Sin_B0 * Sin_B0; + T1 = Z + Geocent_b * Geocent_ep2 * Sin3_B0; + Sum = W - Geocent_a * Geocent_e2 * Cos_B0 * Cos_B0 * Cos_B0; + S1 = sqrt(T1*T1 + Sum * Sum); + Sin_p1 = T1 / S1; + Cos_p1 = Sum / S1; + Rn = Geocent_a / sqrt(1.0 - Geocent_e2 * Sin_p1 * Sin_p1); + if (Cos_p1 >= COS_67P5) + { + *Height = W / Cos_p1 - Rn; + } + else if (Cos_p1 <= -COS_67P5) + { + *Height = W / -Cos_p1 - Rn; + } + else + { + *Height = Z / Sin_p1 + Rn * (Geocent_e2 - 1.0); + } + if (At_Pole == FALSE) + { + *Latitude = atan(Sin_p1 / Cos_p1); + } +} /* END OF Convert_Geocentric_To_Geodetic */ +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimGeocent.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimGeocent.h new file mode 100644 index 0000000000..f23406902e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimGeocent.h @@ -0,0 +1,162 @@ +#ifndef GEOCENT_H + #define GEOCENT_H + +/***************************************************************************/ +/* RSC IDENTIFIER: GEOCENTRIC + * + * ABSTRACT + * + * This component provides conversions between Geodetic coordinates (latitude, + * longitude in radians and height in meters) and Geocentric coordinates + * (X, Y, Z) in meters. + * + * ERROR HANDLING + * + * This component checks parameters for valid values. If an invalid value + * is found, the error code is combined with the current error code using + * the bitwise or. This combining allows multiple error codes to be + * returned. The possible error codes are: + * + * GEOCENT_NO_ERROR : No errors occurred in function + * GEOCENT_LAT_ERROR : Latitude out of valid range + * (-90 to 90 degrees) + * GEOCENT_LON_ERROR : Longitude out of valid range + * (-180 to 360 degrees) + * GEOCENT_A_ERROR : Semi-major axis less than or equal to zero + * GEOCENT_INV_F_ERROR : Inverse flattening outside of valid range + * (250 to 350) + * + * + * REUSE NOTES + * + * GEOCENTRIC is intended for reuse by any application that performs + * coordinate conversions between geodetic coordinates and geocentric + * coordinates. + * + * + * REFERENCES + * + * An Improved Algorithm for Geocentric to Geodetic Coordinate Conversion, + * Ralph Toms, February 1996 UCRL-JC-123138. + * + * Further information on GEOCENTRIC can be found in the Reuse Manual. + * + * GEOCENTRIC originated from : U.S. Army Topographic Engineering Center + * Geospatial Information Division + * 7701 Telegraph Road + * Alexandria, VA 22310-3864 + * + * LICENSES + * + * None apply to this component. + * + * RESTRICTIONS + * + * GEOCENTRIC has no restrictions. + * + * ENVIRONMENT + * + * GEOCENTRIC was tested and certified in the following environments: + * + * 1. Solaris 2.5 with GCC version 2.8.1 + * 2. Windows 95 with MS Visual C++ version 6 + * + * MODIFICATIONS + * + * Date Description + * ---- ----------- + * + * + */ + + +/***************************************************************************/ +/* + * DEFINES + */ + #define GEOCENT_NO_ERROR 0x0000 + #define GEOCENT_LAT_ERROR 0x0001 + #define GEOCENT_LON_ERROR 0x0002 + #define GEOCENT_A_ERROR 0x0004 + #define GEOCENT_INV_F_ERROR 0x0008 + + +/***************************************************************************/ +/* + * FUNCTION PROTOTYPES + */ + +/* ensure proper linkage to c++ programs */ + #ifdef __cplusplus +extern "C" { + #endif + + + long Set_Geocentric_Parameters (double a, + double f); +/* + * The function Set_Geocentric_Parameters receives the ellipsoid parameters + * as inputs and sets the corresponding state variables. + * + * a : Semi-major axis of ellipsoid, in meters. (input) + * f : Flattening of ellipsoid. (input) + */ + + + void Get_Geocentric_Parameters (double *a, + double *f); +/* + * The function Get_Geocentric_Parameters returns the ellipsoid parameters + * to be used in geocentric coordinate conversions. + * + * a : Semi-major axis of ellipsoid, in meters. (output) + * f : Flattening of ellipsoid. (output) + */ + + + long Convert_Geodetic_To_Geocentric (double Latitude, + double Longitude, + double Height, + double *X, + double *Y, + double *Z); +/* + * The function Convert_Geodetic_To_Geocentric converts geodetic coordinates + * (latitude, longitude, and height) to geocentric coordinates (X, Y, Z), + * according to the current ellipsoid parameters. + * + * Latitude : Geodetic latitude in radians (input) + * Longitude : Geodetic longitude in radians (input) + * Height : Geodetic height, in meters (input) + * X : Calculated Geocentric X coordinate, in meters. (output) + * Y : Calculated Geocentric Y coordinate, in meters. (output) + * Z : Calculated Geocentric Z coordinate, in meters. (output) + * + */ + + + void Convert_Geocentric_To_Geodetic (double X, + double Y, + double Z, + double *Latitude, + double *Longitude, + double *Height); +/* + * The function Convert_Geocentric_To_Geodetic converts geocentric + * coordinates (X, Y, Z) to geodetic coordinates (latitude, longitude, + * and height), according to the current ellipsoid parameters. + * + * X : Geocentric X coordinate, in meters. (input) + * Y : Geocentric Y coordinate, in meters. (input) + * Z : Geocentric Z coordinate, in meters. (input) + * Latitude : Calculated latitude value in radians. (output) + * Longitude : Calculated longitude value in radians. (output) + * Height : Calculated height value, in meters. (output) + */ + + + #ifdef __cplusplus +} + #endif + +#endif /* GEOCENT_H */ diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimGeoref.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimGeoref.cpp new file mode 100644 index 0000000000..27a1809152 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimGeoref.cpp @@ -0,0 +1,375 @@ +#include "ossimGeoref.h" + +#include <stdio.h> // for geotrans stuff +#include <math.h> + +// These are Geotrans defines and code. +/***************************************************************************/ +/* + * DEFINES + */ +#define GEOREF_NO_ERROR 0x0000 +#define GEOREF_LAT_ERROR 0x0001 +#define GEOREF_LON_ERROR 0x0002 +#define GEOREF_STR_ERROR 0x0004 +#define GEOREF_STR_LAT_ERROR 0x0008 +#define GEOREF_STR_LON_ERROR 0x0010 +#define GEOREF_STR_LAT_MIN_ERROR 0x0020 +#define GEOREF_STR_LON_MIN_ERROR 0x0040 +#define GEOREF_PRECISION_ERROR 0x0080 + + +ossimGeoref::ossimGeoref(const ossimString &georefString, + long precision) +{ + double lat, lon; + + long result = Convert_GEOREF_To_Geodetic(const_cast<char*>(georefString.c_str()), + &lat, + &lon); + if(result == GEOREF_NO_ERROR) + { + thePt.latr(lat); + thePt.lonr(lon); + } +} + +ossimGeoref::ossimGeoref(const ossimGpt &groundPt) +{ + thePt = groundPt; +} + +ossimGeoref::ossimGeoref() +{ +} + +ossimString ossimGeoref::toString(long precision) +{ + char resultString[100]; + + long result = Convert_Geodetic_To_GEOREF(thePt.latr(), + thePt.lonr(), + precision, + resultString); + if(result == GEOREF_NO_ERROR) + { + return ossimString(resultString); + } + + return ossimString(""); +} + +/***************************************************************************/ +/* + * DEFINES + */ + +#define TRUE 1 +#define FALSE 0 +#define LATITUDE_LOW -90 /* Minimum latitude */ +#define LATITUDE_HIGH 90 /* Maximum latitude */ +#define LONGITUDE_LOW -180 /* Minimum longitude */ +#define LONGITUDE_HIGH 360 /* Maximum longitude */ +#define MIN_PER_DEG 60 /* Number of minutes per degree */ +#define GEOREF_MINIMUM 4 /* Minimum number of chars for GEOREF */ +#define GEOREF_MAXIMUM 14 /* Maximum number of chars for GEOREF */ +#define GEOREF_LETTERS 4 /* Number of letters in GEOREF string */ +#define MAX_PRECISION 5 /* Maximum precision of minutes part */ +#define LETTER_I 8 /* Index for letter I */ +#define LETTER_M 12 /* Index for letter M */ +#define LETTER_O 14 /* Index for letter O */ +#define LETTER_Q 16 /* Index for letter Q */ +#define LETTER_Z 25 /* Index for letter Z */ +#define LETTER_A_OFFSET 65 /* Letter A offset in character set */ +#define ZERO_OFFSET 48 /* Number zero offset in character set */ +#define PI 3.14159265358979323e0 /* PI */ +#define DEGREE_TO_RADIAN (PI / 180.0) +#define RADIAN_TO_DEGREE (180.0 / PI) +#define QUAD 15 /* Degrees per grid square */ +#define ROUND_ERROR 0.0000005 /* Rounding factor */ + + +/***************************************************************************/ +/* + * FUNCTIONS + */ + + +long Extract_Degrees (char *georef, + double *latitude, + double *longitude) +{ /* BEGIN Extract_Degrees */ +/* + * This function extracts the latitude and longitude degree parts of the + * GEOREF string. The latitude and longitude degree parts are the first four + * characters. + * + * georef : GEOREF string (input) + * latitude : Latitude in degrees (output) + * longitude : Longitude in degrees (output) + */ + long i; /* counter in for loops */ + long temp_char; /* temporary character */ + long letter_number[GEOREF_LETTERS]; /* number corresponding to letter */ + long error_code = GEOREF_NO_ERROR; + + for (i=0;i<GEOREF_LETTERS;i++) + { + temp_char = toupper(georef[i]); + temp_char = temp_char - LETTER_A_OFFSET; + if ((!isalpha(georef[i])) + || (temp_char == LETTER_I) + || (temp_char == LETTER_O)) + { + if ((i == 0) || (i == 2)) + error_code |= GEOREF_STR_LON_ERROR; + else + error_code |= GEOREF_STR_LAT_ERROR; + } + letter_number[i] = temp_char; + } + for (i=0;i<4;i++) + { + if (letter_number[i] > LETTER_O) + letter_number[i] -= 2; + else if (letter_number[i] > LETTER_I) + letter_number[i] -= 1; + } + if ((letter_number[0] > 23) || (letter_number[2] > 14)) + error_code |= GEOREF_STR_LON_ERROR; + if ((letter_number[1] > 11) || (letter_number[3] > 14)) + error_code |= GEOREF_STR_LAT_ERROR; + *latitude = (double)(letter_number[1]) * QUAD + (double)(letter_number[3]); + *longitude = (double)(letter_number[0]) * QUAD + (double)(letter_number[2]); + return (error_code); +} /* END Extract_Degrees */ + + +long Extract_Minutes (char *georef, + long start, + long length, + long ERROR_TYPE, + double *minutes) +{ /* BEGIN Extract_Minutes */ +/* + * This function extracts the minutes from the GEOREF string. The minutes + * part begins at position start and has length length. The ERROR_TYPE is + * to allow this function to work with both latitude and longitude minutes. + * + * georef : GEOREF string (input) + * start : Start position in the GEOREF string (input) + * length : length of minutes in the GEOREF string (input) + * ERROR_TYPE : has a value of either GEOREF_STR_LAT_MIN_ERROR (input) + * or GEOREF_STR_LON_MIN_ERROR + * minutes: minute part (output) + */ + long i; /* counter in for loop */ + long error_code = GEOREF_NO_ERROR; + char temp_str[(GEOREF_MAXIMUM-GEOREF_LETTERS)/2 + 1]; + + for (i=0;i<length;i++) + { + if (isdigit(georef[start+i])) + temp_str[i] = georef[start+i]; + else + error_code |= ERROR_TYPE; + } + temp_str[length] = 0; + *minutes = (double)atof(temp_str); /* need atof, atoi can't handle 59999 */ + while (length > 2) + { + *minutes = *minutes / 10; + length = length - 1; + } + if (*minutes > (double)MIN_PER_DEG) + error_code |= ERROR_TYPE; + return (error_code); +} /* END OF Extract_Minutes */ + + +long Round_GEOREF (double value) +/* Round value to nearest integer, using standard engineering rule */ +{ /* Round_GEOREF */ + double ivalue; + long ival; + double fraction = modf (value, &ivalue); + ival = (long)(ivalue); + if ((fraction > 0.5) || ((fraction == 0.5) && (ival%2 == 1))) + ival++; + return (ival); +} /* Round_GEOREF */ + + +void Convert_Minutes_To_String(double minutes, + long precision, + char *str) +{ /* BEGIN Convert_Minutes_To_String */ +/* + * This function converts minutes to a string of length precision. + * + * minutes : Minutes to be converted (input) + * precision : Length of resulting string (input) + * str : String to hold converted minutes (output) + */ + double divisor; + long min; + divisor = pow ((double)10.0, (int)(5 - precision)); + if (minutes == 60.0) + minutes = 59.999; + minutes = minutes * 1000; + min = Round_GEOREF (minutes/divisor); + sprintf (str, "%*.*ld", (int)precision, (int)precision, min); + if (precision == 1) + strcat (str, "0"); +} /* END Convert_Minutes_To_String */ + + +long ossimGeoref::Convert_GEOREF_To_Geodetic (char *georef, + double *latitude, + double *longitude) +{ /* BEGIN Convert_GEOREF_To_Geodetic */ +/* + * This function converts a GEOREF coordinate string to Geodetic (latitude + * and longitude in radians) coordinates. + * + * georef : GEOREF coordinate string. (input) + * latitude : Latitude in radians. (output) + * longitude : Longitude in radians. (output) + * + * CALLS THE FOLLOWING FUNCTIONS: + * + * Extract_Degrees + * Extract_Minutes + */ + long start; /* Position in the GEOREF string */ + long minutes_length; /* length of minutes in the GEOREF string */ + long georef_length; /* length of GEOREF string */ + double origin_long; /* Origin longitude */ + double origin_lat; /* Origin latitude */ + double long_minutes; /* Longitude minute part of GEOREF */ + double lat_minutes; /* Latitude minute part of GEOREF */ + long error_code = GEOREF_NO_ERROR; + + origin_long = (double)LONGITUDE_LOW; + origin_lat = (double)LATITUDE_LOW; + georef_length = strlen(georef); + if ((georef_length < GEOREF_MINIMUM) || (georef_length > GEOREF_MAXIMUM) + || ((georef_length % 2) != 0)) + { + error_code |= GEOREF_STR_ERROR; + } + if (!error_code) + { + error_code |= Extract_Degrees(georef,latitude,longitude); + start = GEOREF_LETTERS; + minutes_length = (georef_length - start) / 2; + if (!error_code) + { + error_code |= Extract_Minutes(georef, start, minutes_length, + GEOREF_STR_LON_MIN_ERROR, &long_minutes); + if (!error_code) + { + error_code |= Extract_Minutes(georef, (start+minutes_length), + minutes_length, GEOREF_STR_LAT_MIN_ERROR, &lat_minutes); + *latitude = *latitude + origin_lat + lat_minutes / (double)MIN_PER_DEG; + *longitude = *longitude + origin_long + long_minutes / (double)MIN_PER_DEG; + *latitude = *latitude * DEGREE_TO_RADIAN; + *longitude = *longitude * DEGREE_TO_RADIAN; + } + } + } + return (error_code); +} /* END OF Convert_GEOREF_To_Geodetic */ + + +long ossimGeoref::Convert_Geodetic_To_GEOREF (double latitude, + double longitude, + long precision, + char *georef) +{ /* BEGIN Convert_Geodetic_To_GEOREF */ +/* + * This function converts Geodetic (latitude and longitude in radians) + * coordinates to a GEOREF coordinate string. Precision specifies the + * number of digits in the GEOREF string for latitude and longitude: + * 0 for nearest degree + * 1 for nearest ten minutes + * 2 for nearest minute + * 3 for nearest tenth of a minute + * 4 for nearest hundredth of a minute + * 5 for nearest thousandth of a minute + * + * latitude : Latitude in radians. (input) + * longitude : Longitude in radians. (input) + * precision : Precision specified by the user. (input) + * georef : GEOREF coordinate string. (output) + * + * CALLS THE FOLLOWING FUNCTIONS: + * + * Convert_Minutes_To_String + */ + + double long_min; /* GEOREF longitude minute part */ + double lat_min; /* GEOREF latitude minute part */ + double origin_long; /* Origin longitude (-180 degrees)*/ + double origin_lat; /* Origin latitude (-90 degrees) */ + long letter_number[GEOREF_LETTERS + 1]; /* GEOREF letters */ + char long_min_str[MAX_PRECISION + 1]; /* Longitude minute string */ + char lat_min_str[MAX_PRECISION + 1]; /* Latitude minute string */ + long i; /* counter in for loop */ + long error_code = GEOREF_NO_ERROR; + + latitude = latitude * RADIAN_TO_DEGREE; + longitude = longitude * RADIAN_TO_DEGREE; + if ((latitude < (double)LATITUDE_LOW) + || (latitude > (double)LATITUDE_HIGH)) + error_code |= GEOREF_LAT_ERROR; + if ((longitude < (double)LONGITUDE_LOW) + || (longitude > (double)LONGITUDE_HIGH)) + error_code |= GEOREF_LON_ERROR; + if ((precision < 0) || (precision > MAX_PRECISION)) + error_code |= GEOREF_PRECISION_ERROR; + if (!error_code) + { + if (longitude > 180) + longitude -= 360; + origin_long = (double)LONGITUDE_LOW; + origin_lat = (double)LATITUDE_LOW; + letter_number[0] = (long)((longitude-origin_long) / QUAD + ROUND_ERROR); + longitude = longitude - ((double)letter_number[0] * QUAD + origin_long); + letter_number[2] = (long)(longitude + ROUND_ERROR); + long_min = (longitude - (double)letter_number[2]) * (double)MIN_PER_DEG; + letter_number[1] = (long)((latitude - origin_lat) / QUAD + ROUND_ERROR); + latitude = latitude - ((double)letter_number[1] * QUAD + origin_lat); + letter_number[3] = (long)(latitude + ROUND_ERROR); + lat_min = (latitude - (double)letter_number[3]) * (double)MIN_PER_DEG; + for (i = 0;i < 4; i++) + { + if (letter_number[i] >= LETTER_I) + letter_number[i] += 1; + if (letter_number[i] >= LETTER_O) + letter_number[i] += 1; + } + + if (letter_number[0] == 26) + { /* longitude of 180 degrees */ + letter_number[0] = LETTER_Z; + letter_number[2] = LETTER_Q; + long_min = 59.999; + } + if (letter_number[1] == 13) + { /* latitude of 90 degrees */ + letter_number[1] = LETTER_M; + letter_number[3] = LETTER_Q; + lat_min = 59.999; + } + + for (i=0;i<4;i++) + georef[i] = (char)(letter_number[i] + LETTER_A_OFFSET); + georef[4] = 0; + Convert_Minutes_To_String(long_min,precision,long_min_str); + Convert_Minutes_To_String(lat_min,precision,lat_min_str); + strcat(georef,long_min_str); + strcat(georef,lat_min_str); + } + return (error_code); +} /* END OF Convert_Geodetic_To_GEOREF */ diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimGeoref.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimGeoref.h new file mode 100644 index 0000000000..c256d285f6 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimGeoref.h @@ -0,0 +1,70 @@ +#ifndef ossimGeoref_HEADER +#define ossimGeoref_HEADER +#include "base/data_types/ossimString.h" +#include "base/data_types/ossimGpt.h" + +class OSSIMDLLEXPORT ossimGeoref +{ +public: + ossimGeoref(const ossimString &georefString, + long precision); + ossimGeoref(const ossimGpt &groundPt); + ossimGeoref(); + + /*! + * This function converts Geodetic (latitude and longitude in radians) + * coordinates to a GEOREF coordinate string. Precision specifies the + * number of digits in the GEOREF string for latitude and longitude: + * 0 for nearest degree + * 1 for nearest 10 minutes + * 2 for nearest minute + * 3 for nearest tenth of a minute + * 4 for nearest hundredth of a minute + * 5 for nearest thousandth of a minute + * + * Precision : level of precision specified by the user (input) + * ossimGeoref : GEOREF coordinate string (return) + */ + ossimString toString(long precision); + +private: + ossimGpt thePt; + + // This code belongs to Geotrans + + /*! + * This function converts Geodetic (latitude and longitude in radians) + * coordinates to a GEOREF coordinate string. Precision specifies the + * number of digits in the GEOREF string for latitude and longitude: + * 0 for nearest degree + * 1 for nearest 10 minutes + * 2 for nearest minute + * 3 for nearest tenth of a minute + * 4 for nearest hundredth of a minute + * 5 for nearest thousandth of a minute + * + * Latitude : Latitude in radians (input) + * Longitude : Longitude in radians (input) + * Precision : level of precision specified by the user (input) + * ossimGeoref : GEOREF coordinate string (output) + */ + long Convert_Geodetic_To_GEOREF (double Latitude, + double Longitude, + long Precision, + char *georef); + + + /*! + * This function converts a GEOREF coordinate string to Geodetic (latitude + * and longitude in radians) coordinates. + * + * ossimGeoref : GEOREF coordinate string (input) + * Latitude : Latitude in radians (output) + * Longitude : Longitude in radians (output) + */ + long Convert_GEOREF_To_Geodetic (char *georef, + double *Latitude, + double *Longitude); +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimGpt.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimGpt.cpp new file mode 100644 index 0000000000..26a61b62c6 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimGpt.cpp @@ -0,0 +1,341 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: Garrett Potts +// +// Description: +// +// LATITUDE AND LONGITUDE VALUES ARE IN DEGREES. +// +//******************************************************************* +// $Id: ossimGpt.cpp,v 1.33 2005/12/16 14:25:11 dburken Exp $ + +#include <sstream> + +#include <base/data_types/ossimGpt.h> +#include <base/data_types/ossimEcefPoint.h> +#include <base/data_types/ossimEcefVector.h> +#include <base/data_types/ossimDms.h> +#include <base/data_types/datum/ossimDatum.h> +#include <base/data_types/geoid/ossimGeoidManager.h> +#include <base/data_types/ellipse/ossimEllipsoid.h> +#include <base/data_types/ossimGeocent.h> +#include <base/data_types/ossimString.h> + +std::ostream& ossimGpt::print(std::ostream& os, ossim_uint32 precision) const +{ + os << setiosflags(ios::fixed) << setprecision(precision); + os << "( "; + + if(isLatNan()) + { + os << "nan" << ", "; + } + else + { + os << latd() << ", "; + } + if(isLonNan()) + { + os << "nan" << ", "; + } + else + { + os << lond() << ", "; + } + if(isHgtNan()) + { + os << "nan" << ", "; + } + else + { + os << height() << ", "; + } + + os << (theDatum?theDatum->code().c_str():"") << " )"; + + return os; +} + +std::ostream& operator<<(std::ostream& os, const ossimGpt& pt) +{ + return pt.print(os); +} + +ossimString ossimGpt::toString(ossim_uint32 precision) const +{ + std::ostringstream os; + print(os, precision); + return ossimString(os.str()); +} + +std::istream& operator>>(std::istream& is, ossimGpt &pt) +{ + //--- + // Expected input format: + // ( 30.00000000000000, -90.00000000000000, 0.00000000000000, WGE ) + // -----latitude---- -----longitude---- ------height---- datum + //--- + + // Start with a nan point. + pt.makeNan(); + + // Check the stream. + if (!is) return is; + + const int SZ = 22; + ossimString tempString; + char tempChars[SZ]; + char c; + + // Gobble the "(". + is >> tempString; + if (!is) return is; + + // Get the latitude. + is.get(tempChars, SZ, ','); + if (!is) return is; + tempChars[SZ-1] = '\0'; + tempString = tempChars; + tempString.trim(); + if (tempString == "nan") + { + pt.latd(OSSIM_DBL_NAN); + } + else + { + pt.latd(tempString.toDouble()); + } + + // Eat the ",". + is.get(c); + + // Get the longitude. + is.get(tempChars, SZ, ','); + if (!is) return is; + tempChars[SZ-1] = '\0'; + tempString = tempChars; + tempString.trim(); + if (tempString == "nan") + { + pt.lond(OSSIM_DBL_NAN); + } + else + { + pt.lond(tempString.toDouble()); + } + + // Eat the ",". + is.get(c); + + // Get the height. + is.get(tempChars, SZ, ','); + if (!is) return is; + tempChars[SZ-1] = '\0'; + tempString = tempChars; + tempString.trim(); + if (tempString == "nan") + { + pt.height(OSSIM_DBL_NAN); + } + else + { + pt.height(tempString.toDouble()); + } + + // Eat the ",". + is.get(c); + + // Get the datum. + is >> tempString; + if (!is) return is; + const ossimDatum* datum = ossimDatumFactory::instance()->create(tempString); + if (datum) + { + pt.datum(datum); + } + else + { + pt.datum(ossimDatumFactory::instance()->wgs84()); + } + + // Gobble the trailing ")". + is >> tempString; + + // Finished + return is; +} + + +//***************************************************************************** +// COPY CONSTRUCTOR: ossimGpt(ossimGpt) +//***************************************************************************** +ossimGpt::ossimGpt(const ossimGpt& src) + : lat(src.lat), + lon(src.lon), + hgt(src.hgt) +{ + theDatum = src.datum(); + if(!theDatum) + { + theDatum = ossimDatumFactory::instance()->wgs84(); + } +// limitLonTo180(); +} + +//***************************************************************************** +// CONSTRUCTOR: ossimGpt(ossimEcefPoint, datum) +//***************************************************************************** +ossimGpt::ossimGpt(const ossimEcefPoint& ecef_point, + const ossimDatum* datum) + : + theDatum (datum) +{ + if(!theDatum) + { + theDatum = ossimDatumFactory::instance()->wgs84(); + } + if(ecef_point.isNan()) + { + makeNan(); + } + else + { + theDatum->ellipsoid()->XYZToLatLonHeight(ecef_point.x(), + ecef_point.y(), + ecef_point.z(), + lat, + lon, + hgt); + + } +} + +//***************************************************************************** +// METHOD: ossimGpt::operator = +//***************************************************************************** +const ossimGpt& ossimGpt::operator = (const ossimGpt &aPt) +{ + lat = aPt.lat; + lon = aPt.lon; + hgt = aPt.hgt; + + if(aPt.datum()) + { + theDatum = aPt.datum(); + } + if(!theDatum) + { + theDatum = ossimDatumFactory::instance()->wgs84(); + } + + return *this; +} + +//***************************************************************************** +// METHOD: ossimGpt::changeDatum +//***************************************************************************** +void ossimGpt::changeDatum(const ossimDatum *datum) +{ + if(datum == theDatum) return; + if(!isLatNan() && !isLonNan()) // only shift if all values lat and lon is good + { + if(datum) + { + double h = hgt; + *this = datum->shift(*this); + if(h == OSSIM_DBL_NAN) + { + hgt = h; + } + theDatum = datum; + } + } +} + + +//***************************************************************************** +// METHOD: ossimGpt::toDmsString() +//***************************************************************************** +ossimString ossimGpt::toDmsString()const +{ + ossimString result; + + result += "lat: "; + if(isLatNan()) + { + result += "nan"; + } + else + { + result += ossimDms(latd()).toString("dd@mm'ss.ssss\"C"); + } + result += " lon: "; + if(isLonNan()) + { + result += "nan"; + } + else + { + result += ossimDms(lond(),false).toString("dd@mm'ss.ssss\"C"); + } + + return result; +} + +//***************************************************************************** +// METHOD: ossimGpt::distanceTo(ossimGpt) +// +// Computes straight-line distance to arg point, in meters. +// +//***************************************************************************** +double ossimGpt::distanceTo(const ossimGpt& arg_pt) const +{ + ossimEcefPoint p1 (*this); + ossimEcefPoint p2 (arg_pt); + + return (p1 - p2).magnitude(); +} + +//***************************************************************************** +// METHOD: ossimGpt::heightMSL() const +// +// Returns the height data member adjusted for geoid. +// +//***************************************************************************** +double ossimGpt::heightMSL() const +{ + double offset = ossimGeoidManager::instance()->offsetFromEllipsoid(*this); + return (hgt - offset); +} + +//***************************************************************************** +// METHOD: ossimGpt::heightMSL(double) +// +// Sets the height data member adjusted for geoid. +// +//***************************************************************************** +void ossimGpt::heightMSL(double heightMSL) +{ + double offset = ossimGeoidManager::instance()->offsetFromEllipsoid(*this); + hgt = heightMSL + offset; +} + +//***************************************************************************** +// METHOD: ossimGpt::metersPerDegree(double) +// +// Computes geodetic arc lengths at this ground point. +// +//***************************************************************************** +ossimDpt ossimGpt::metersPerDegree() const +{ + ossimDpt result; + + double radius = theDatum->ellipsoid()->geodeticRadius(lat); + result.y = RAD_PER_DEG * radius; + result.x = result.y * cosd(lat); + + return result; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimGpt.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimGpt.h new file mode 100644 index 0000000000..082e7c5a3d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimGpt.h @@ -0,0 +1,259 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt. +// +// Author: Garrett Potts +// +// Description: +// +// Contains class declaration for gpt. +// +// CONSTRUCTOR TAKES LAT/LON IN DEGREES!!! +// +// Height is relative to the ellipsoid. +// +//******************************************************************* +// $Id: ossimGpt.h,v 1.23 2005/12/16 14:25:11 dburken Exp $ + +#ifndef gpt_HEADER +#define gpt_HEADER + +#include <iomanip> +#include <iostream> + +#include <base/common/ossimConstants.h> +#include <base/data_types/ossimIpt.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimString.h> +#include <base/factory/ossimDatumFactory.h> + +class OSSIMDLLEXPORT ossimDatum; +class OSSIMDLLEXPORT ossimEcefPoint; +class OSSIMDLLEXPORT ossimString; + +class OSSIMDLLEXPORT ossimGpt +{ +public: + /** + * Constructor. The values are assumed to be in DEGREES. + */ + ossimGpt(const double alat=0, // degrees + const double alon=0, // degrees + const double ahgt=0, + const ossimDatum* aDatum=ossimDatumFactory::instance()->wgs84()) + : lat(alat), + lon(alon), + hgt(ahgt), // relative to the ellipsoid + theDatum(aDatum) {}//limitLonTo180();} + + /** + * Copy Constructor: + */ + ossimGpt(const ossimGpt& src); + + /** + * Constructor. Conversion from geocentric to ground. + */ + ossimGpt(const ossimEcefPoint &aPt, + const ossimDatum* aDatum=ossimDatumFactory::instance()->wgs84()); + + /** + * latr(). Returns the latitude in radian measure. Since + * our internal format is radians we do not have to do any + * conversions. + */ + double latr()const{return lat*RAD_PER_DEG;} + + /** + * Returns the latitude in radian measure. Since + * our internal format is radians we do not have to do any + * conversions. + */ + void latr(double radianValue){lat = radianValue*DEG_PER_RAD;} + + /** + * Returns the longitude in radian measure. Since + * our internal format is radians we do not have to do any + * conversions. + */ + double lonr()const{return lon*RAD_PER_DEG;} + + /** + * Assumes the value being passed in is in radians. + */ + void lonr(double radianValue) + {lon = radianValue*DEG_PER_RAD; }//limitLonTo180();} + + /** + * Will convert the radian measure to degrees. + */ + double latd()const{return lat;} + + /** + * Assumes the passed in value is in degrees. + */ + void latd(double degreeValue){lat = degreeValue;} + + /** + * Will convert the radian measure to degrees. + */ + double lond()const{return lon;} + + /** + * Assumes the passed in value is in degrees. + */ + void lond(double degreeValue){lon = degreeValue; }//limitLonTo180();} + + /** + * @return Returns the height in meters above the ellipsoid. + */ + double height()const{return hgt;} + + /** + * @return Returns the height in meters above mean sea level (msl). + * + * @note This is the height above the ellipsoid minus any geoid offset. + */ + double heightMSL() const; + + /** + * Sets the "hgt" data member to height. + * + * @param height Height above the ellipsoid in meters. + */ + void height(double height){hgt = height;} + + /** + * Sets the "hgt" data member to heightMsl adding any geiod offset. + * + * @param heightMSL Height in meters above msl. + */ + void heightMSL(double heightMSL); + + void makeNan(){lat = OSSIM_DBL_NAN; lon=OSSIM_DBL_NAN; hgt=OSSIM_DBL_NAN;} + bool isNan()const{return isLatNan()&&isLonNan()&&isHgtNan();} + bool hasNans()const + { + return (ossimIsNan(lat) || ossimIsNan(lon) || ossimIsNan(hgt)); + } + bool isLatNan()const{return ossimIsNan(lat);} + bool isLonNan()const{return ossimIsNan(lon);} + bool isHgtNan()const{return ossimIsNan(hgt);} + + std::ostream& print(std::ostream& os, ossim_uint32 precision=15) const; + + friend OSSIMDLLEXPORT std::ostream& operator<<(std::ostream& os, + const ossimGpt& pt); + + /** + * @param precision Output floating point precision. + * + * @return ossimString representing point. + * + * Output format: + * ( 30.00000000000000, -90.00000000000000, 0.00000000000000, WGE ) + * -----latitude---- -----longitude---- ------height---- datum + */ + ossimString toString(ossim_uint32 precision=15) const; + + /** + * Method to input the formatted string of the "operator<<". + * + * This method starts by doing a "makeNan" on aPt. So if anything goes + * wrong with the stream or parsing aPt could be all or partially nan. + * + * @param is Input stream istream to formatted text. + * @param aPt osimGpt to be initialized from stream. + * @return istream pass in. + * + * Expected format: + * ( 30.00000000000000, -90.00000000000000, 0.00000000000000, WGE ) + * -----latitude---- -----longitude---- ------height---- datum + */ + friend OSSIMDLLEXPORT std::istream& operator>>(std::istream& is, + ossimGpt& pt); + + /** + * datum(). returns the datum associated with this ground. + * + */ + const ossimDatum* datum()const{return theDatum;} + + /** + * Note: this will not do a shift. This just allows you to set the datum. + * If you want an automatic shift to occur then you must call the + * changeDatum method + */ + void datum(const ossimDatum* aDatum){theDatum = aDatum?aDatum:theDatum;} + + /** + * This will actually perform a shift. + */ + void changeDatum(const ossimDatum *datum); + + const ossimGpt& operator = (const ossimGpt &aPt); + bool operator ==(const ossimGpt& gpt)const + { + return ( (lat == gpt.lat)&& + (lon == gpt.lon)&& + (hgt == gpt.hgt)&& + (theDatum == gpt.theDatum)); + } + + /** + * METHOD: limitLonTo180() + * Converts the lon data member to a value between -180 and +180: + */ + void limitLonTo180() + { if (lon < -180.0) lon += 360.0; else if (lon > 180.0) lon -= 360.0; } + + void clampLon(double low, double high) + { + if(lon < low) lon = low; + if(lon > high) lon = high; + } + + void clampLat(double low, double high) + { + if(lat < low) lat = low; + if(lat > high) lat = high; + } + + void clampHgt(double low, double high) + { + if(hgt < low) hgt = low; + if(hgt > high) hgt = high; + } + + /** + * METHOD: distanceTo(ossimGpt) + * Computes straight-line distance in meters between this and arg gpt: + */ + double distanceTo(const ossimGpt& arg_gpt) const; + + ossimDpt metersPerDegree() const; + + ossimString toDmsString()const; + + ossim_float64 lat; //> latitude in degrees measure + ossim_float64 lon; //> longitude in degrees measure + + /** + * Height in meters above the ellipsiod. + * + * @note This is NOT the same as "height msl". "Height msl" is above + * the geoid or better know as mean sea level. + */ + ossim_float64 hgt; + +private: + + /** + * Know reference location plus an implied ellipsoid. + */ + const ossimDatum* theDatum; + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimGrect.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimGrect.cpp new file mode 100644 index 0000000000..a63264ba3c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimGrect.cpp @@ -0,0 +1,234 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// Description: +// +//************************************************************************* +// $Id: ossimGrect.cpp,v 1.5 2005/09/23 20:11:42 dburken Exp $ + +#include <base/data_types/ossimGrect.h> +using namespace std; + +ostream& operator<<(ostream& os, const ossimGrect& rect) +{ + return os << rect.theUlCorner << ", " << rect.theLrCorner << endl; +} + +ossimGrect::ossimGrect(vector<ossimGpt>& points) +{ + unsigned long index; + + // initialize everyone to the first point + if(points.size() > 0) + { + theUlCorner = points[0]; + theLrCorner = theUlCorner; + } + + // find the bounds + for(index = 1; index < points.size(); index++) + { + // find left most + if(theUlCorner.lond() > points[index].lond()) + { + theUlCorner.lond(points[index].lond()); + } // find right most + else if(theLrCorner.lond() < points[index].lond()) + { + theLrCorner.lond(points[index].lond()); + } + //find top most + if(points[index].latd() > theUlCorner.latd()) + { + theUlCorner.latd(points[index].latd()); + }// find bottom most + else if(points[index].latd() < theLrCorner.latd()) + { + theLrCorner.latd(points[index].latd()); + } + } + + theUrCorner = ossimGpt(theUlCorner.latd(), + theLrCorner.lond(), + 0, + theUlCorner.datum()); + theLlCorner = ossimGpt(theLrCorner.latd(), + theUlCorner.lond(), + 0, + theLrCorner.datum()); +} + +ossimGrect::ossimGrect(const ossimGpt& p1, + const ossimGpt& p2, + const ossimGpt& p3, + const ossimGpt& p4) +{ + unsigned long index; + std::vector<ossimGpt> points(4); + points[0] = p1; + points[1] = p2; + points[2] = p3; + points[3] = p4; + // initialize everyone to the first point + if(points.size() > 0) + { + theUlCorner = points[0]; + theLrCorner = theUlCorner; + } + + // find the bounds + for(index = 1; index < points.size(); index++) + { + // find left most + if(theUlCorner.lond() > points[index].lond()) + { + theUlCorner.lond(points[index].lond()); + } // find right most + else if(theLrCorner.lond() < points[index].lond()) + { + theLrCorner.lond(points[index].lond()); + } + //find top most + if(points[index].latd() > theUlCorner.latd()) + { + theUlCorner.latd(points[index].latd()); + }// find bottom most + else if(points[index].latd() < theLrCorner.latd()) + { + theLrCorner.latd(points[index].latd()); + } + } + theUrCorner = ossimGpt(theUlCorner.latd(), + theLrCorner.lond(), + 0, + theUlCorner.datum()); + theLlCorner = ossimGpt(theLrCorner.latd(), + theUlCorner.lond(), + 0, + theLrCorner.datum()); +} + +ossimGrect ossimGrect::stretchToEvenBoundary(double latSpacingInDegrees, + double lonSpacingInDegrees)const +{ + double ulLat = ((long)ceil(theUlCorner.latd()/latSpacingInDegrees))* + latSpacingInDegrees; + double ulLon = ((long)floor(theUlCorner.lond()/lonSpacingInDegrees))* + lonSpacingInDegrees; + double lrLat = ((long)floor(theLrCorner.latd()/latSpacingInDegrees))* + latSpacingInDegrees; + double lrLon = ((long)ceil(theLrCorner.lond()/lonSpacingInDegrees))* + lonSpacingInDegrees; + + return ossimGrect(ulLat, ulLon, lrLat, lrLon); +} + +void ossimGrect::computeEvenTiles(std::vector<ossimGrect>& result, + double latSpacingInDegrees, + double lonSpacingInDegrees, + bool clipToGeographicBounds)const +{ + ossimGrect clipRect = ossimGrect(90, -180, -190, 180); + result.clear(); + ossimGrect temp = stretchToEvenBoundary(latSpacingInDegrees, + lonSpacingInDegrees); + + ossimGpt point = temp.ul(); + + while(temp.pointWithin(point)) + { + while(temp.pointWithin(point)) + { + ossimGrect rect(point.latd(), + point.lond(), + point.latd()-latSpacingInDegrees, + point.lond()+lonSpacingInDegrees); + + rect.theUlCorner.datum( theUlCorner.datum()); + rect.theLlCorner.datum( theUlCorner.datum()); + rect.theLrCorner.datum( theUlCorner.datum()); + rect.theUrCorner.datum( theUlCorner.datum()); + if(clipToGeographicBounds) + { + rect = rect.clipToRect(clipRect); + } + result.push_back(rect); + + point.lond(point.lond()+lonSpacingInDegrees); + } + point.lond(temp.ul().lond()); + point.latd(point.latd()-latSpacingInDegrees); + } +} + +//******************************************************************* +// Public Method: ossimGrect::completely_within +//******************************************************************* +bool ossimGrect::completely_within(const ossimGrect& rect) const +{ + if(rect.isLonLatNan() || isLonLatNan()) + { + return false; + } + + /* -------------- + | 1 | + | ---------- | + | | | | + | | | | + | | 2 | | + | | | | + | | | | + | ---------- | + | | + -------------- */ + + bool rtn = true; + + if (theUlCorner.lon < rect.ul().lon) + { + rtn = false; + } + else if (theLrCorner.lon > rect.lr().lon) + { + rtn = false; + } + else if (theUlCorner.lat < rect.ul().lat) + { + rtn = false; + } + else if (theLrCorner.lat > rect.lr().lat) + { + rtn = false; + } + + return rtn; +} + +//******************************************************************* +// Public Method: ossimGrect::intersects +//******************************************************************* +bool ossimGrect::intersects(const ossimGrect& rect) const +{ + + if(rect.isLonLatNan() || isLonLatNan()) + { + return false; + } + + ossim_float64 ulx = ossimMax(rect.ul().lon, ul().lon); + ossim_float64 lrx = ossimMin(rect.lr().lon, lr().lon); + ossim_float64 uly, lry; + bool rtn; + + uly = ossimMin(rect.ul().lat, ul().lat); + lry = ossimMax(rect.lr().lat, lr().lat); + rtn = ((ulx <= lrx) && (uly >= lry)); + + return (rtn); +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimGrect.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimGrect.h new file mode 100644 index 0000000000..6d09ef2a28 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimGrect.h @@ -0,0 +1,329 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimGrect.h,v 1.15 2005/09/23 20:10:55 dburken Exp $ +#ifndef ossimGrect_HEADER +#define ossimGrect_HEADER +#include <vector> +#include <iostream> + +#include <base/factory/ossimDatumFactory.h> +#include <base/data_types/ossimGpt.h> +#include <base/common/ossimCommon.h> /* for ossimMin/Max */ + +class OSSIMDLLEXPORT ossimGrect +{ +public: + friend std::ostream& operator<<(std::ostream& os, const ossimGrect& rect); + + /** + * Will default to 0,0,0,0. + */ + ossimGrect() + : + theUlCorner(0.0, 0.0, 0.0), + theUrCorner(0.0, 0.0, 0.0), + theLrCorner(0.0, 0.0, 0.0), + theLlCorner(0.0, 0.0, 0.0) + {} + + /** + * Copies the passed in rectangle to this + * object. + */ + ossimGrect(const ossimGrect& rect) + : + theUlCorner(rect.ul()), + theUrCorner(rect.ur()), + theLrCorner(rect.lr()), + theLlCorner(rect.ll()) + {} + + /** + * WIll take two ground points and fill the + * bounding rect appropriately. + */ + ossimGrect(const ossimGpt& ul, + const ossimGpt& lr) + : + theUlCorner(ul), + theUrCorner(ul.latd(), lr.lond(),0,ul.datum()), + theLrCorner(lr), + theLlCorner(lr.latd(), ul.lond(), 0, ul.datum()) + { + } + + /** + * Takes the upper left and lower right ground + * points + */ + ossimGrect(const double ulLat, + const double ulLon, + const double lrLat, + const double lrLon, + const ossimDatum* aDatum=ossimDatumFactory::instance()->wgs84()) + : + theUlCorner(ulLat, ulLon,0, aDatum), + theUrCorner(ulLat, lrLon, 0, aDatum), + theLrCorner(lrLat, lrLon, 0, aDatum), + theLlCorner(lrLat, ulLon, 0, aDatum) + {} + ossimGrect(const ossimGpt& point, + double latSpacingInDegrees, + double lonSpacingInDegrees) + : + theUlCorner(point), + theUrCorner(point), + theLrCorner(point), + theLlCorner(point) + { + std::vector<ossimGrect> v; + computeEvenTiles(v, latSpacingInDegrees, lonSpacingInDegrees); + if(v.size()) + *this = v[0]; + } + ossimGrect(std::vector<ossimGpt>& points); + ossimGrect(const ossimGpt& p1, + const ossimGpt& p2, + const ossimGpt& p3, + const ossimGpt& p4); + + + const ossimGrect& operator=(const ossimGrect& rect) + { + theUlCorner = rect.ul(); + theUrCorner = rect.ur(); + theLrCorner = rect.lr(); + theLlCorner = rect.ll(); + return *this; + } + + ossimGpt midPoint()const; + + /** + * Returns the height of a rectangle. + */ + ossim_float64 height() const; + + /** + * Returns the width of a rectangle. + */ + ossim_float64 width() const; + + const ossimGpt& ul()const; + const ossimGpt& ur()const; + const ossimGpt& ll()const; + const ossimGpt& lr()const; + + ossimGpt& ul(); + ossimGpt& ur(); + ossimGpt& ll(); + ossimGpt& lr(); + + void makeNan(); + + bool isLonLatNan()const; + + bool hasNans()const; + + bool isNan()const; + + /*! + * Returns true if "this" rectangle is contained completely within the + * input rectangle "rect". + */ + bool completely_within(const ossimGrect& rect) const; + + /*! + * Returns true if any portion of an input rectangle "rect" intersects + * "this" rectangle. + */ + bool intersects(const ossimGrect& rect) const; + + ossimGrect clipToRect(const ossimGrect& rect)const; + + ossimGrect combine(const ossimGrect& rect)const; + + /** + * METHOD: pointWithin(ossimGpt) + * + * @param gpt Point to test for withinness. + * + * @return true if argument is inside of horizontal rectangle + * + * @note Height is not considered and there is no datum shift applied if + * gpt is of a different datum than this datum. + */ + bool pointWithin(const ossimGpt& gpt) const; //inline below + + ossimGrect stretchToEvenBoundary(double latSpacingInDegrees, + double lonSpacingInDegrees)const; + + void computeEvenTiles(std::vector<ossimGrect>& result, + double latSpacingInDegrees, + double lonSpacingInDegrees, + bool clipToGeographicBounds = true)const; +private: + ossimGpt theUlCorner; + ossimGpt theUrCorner; + ossimGpt theLrCorner; + ossimGpt theLlCorner; + +}; + +//==================== BEGIN INLINE DEFINITIONS =============================== + +//***************************************************************************** +// INLINE METHOD: ossimGrect::midPoint() +//***************************************************************************** +inline ossimGpt ossimGrect::midPoint()const +{ + return ossimGpt((ul().latd() + ur().latd() + ll().latd() + lr().latd())*.25, + (ul().lond() + ur().lond() + ll().lond() + lr().lond())*.25, + (ul().height()+ur().height()+ll().height()+ + lr().height())*.25, + ul().datum() ); +} + +//***************************************************************************** +// INLINE METHOD: ossimGrect::clipToRect() +//***************************************************************************** +inline ossimGrect ossimGrect::clipToRect(const ossimGrect& rect)const +{ + double ulx, uly, lrx, lry; + + ulx = ossimMax(rect.ul().lond(),ul().lond()); + uly = ossimMin(rect.ul().latd(),ul().latd()); + lrx = ossimMin(rect.lr().lond(),lr().lond()); + lry = ossimMax(rect.lr().latd(),lr().latd()); + + if( lrx < ulx || lry > uly ) + { + return ossimGrect(ossimGpt(0,0,0),ossimGpt(0,0,0)); + } + else + { + return ossimGrect(ossimGpt(uly, ulx, 0, rect.ul().datum()), + ossimGpt(lry, lrx, 0, rect.ul().datum())); + } +} + +//******************************************************************* +// Inline Method: ossimDrect::combine(const ossimDrect& rect) +//******************************************************************* +inline ossimGrect ossimGrect::combine(const ossimGrect& rect)const +{ + ossimGpt ulCombine; + ossimGpt lrCombine; + + ulCombine.lon = ((ul().lon <= rect.ul().lon)?ul().lon:rect.ul().lon); + ulCombine.lat = ((ul().lat >= rect.ul().lat)?ul().lat:rect.ul().lat); + lrCombine.lon = ((lr().lon >= rect.lr().lon)?lr().lon:rect.lr().lon); + lrCombine.lat = ((lr().lat <= rect.lr().lat)?lr().lat:rect.lr().lat); + + return ossimGrect(ulCombine, lrCombine); +} + +//***************************************************************************** +// INLINE METHOD: ossimGrect::pointWithin() +//***************************************************************************** +inline bool ossimGrect::pointWithin(const ossimGpt& gpt) const +{ + return ((gpt.lat <= theUlCorner.lat) && (gpt.lat >= theLrCorner.lat) && + (gpt.lon >= theUlCorner.lon) && (gpt.lon <= theLrCorner.lon)); +} + +inline ossim_float64 ossimGrect::height() const +{ + return fabs(theLlCorner.latd() - theUlCorner.latd()) + 1.0; +} + +inline ossim_float64 ossimGrect::width() const +{ + return fabs(theLrCorner.lond() - theLlCorner.lond()) + 1.0; +} + +inline const ossimGpt& ossimGrect::ul() const +{ + return theUlCorner; +} + +inline const ossimGpt& ossimGrect::ur() const +{ + return theUrCorner; +} + +inline const ossimGpt& ossimGrect::ll() const +{ + return theLlCorner; +} + +inline const ossimGpt& ossimGrect::lr() const +{ + return theLrCorner; +} + +inline ossimGpt& ossimGrect::ul() +{ + return theUlCorner; +} + +inline ossimGpt& ossimGrect::ur() +{ + return theUrCorner; +} + +inline ossimGpt& ossimGrect::ll() +{ + return theLlCorner; +} + +inline ossimGpt& ossimGrect::lr() +{ + return theLrCorner; +} + +inline void ossimGrect::makeNan() +{ + theUlCorner.makeNan(); + theLlCorner.makeNan(); + theLrCorner.makeNan(); + theUrCorner.makeNan(); +} + +inline bool ossimGrect::isLonLatNan() const +{ + return ( ossimIsNan(theUlCorner.lat) || + ossimIsNan(theUlCorner.lon) || + ossimIsNan(theUrCorner.lat) || + ossimIsNan(theUrCorner.lon) || + ossimIsNan(theLrCorner.lat) || + ossimIsNan(theLrCorner.lon) || + ossimIsNan(theLlCorner.lat) || + ossimIsNan(theLlCorner.lon) ); +} + +inline bool ossimGrect::hasNans() const +{ + return ( theUlCorner.hasNans() || + theLlCorner.hasNans() || + theLrCorner.hasNans() || + theUrCorner.hasNans() ); +} + +inline bool ossimGrect::isNan()const +{ + return ( theUlCorner.hasNans() && + theLlCorner.hasNans() && + theLrCorner.hasNans() && + theUrCorner.hasNans() ); +} + +#endif /* End of "#ifndef ossimGrect_HEADER" */ diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimHexString.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimHexString.cpp new file mode 100644 index 0000000000..5c1742622b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimHexString.cpp @@ -0,0 +1,248 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//******************************************************************** +// $Id: ossimHexString.cpp,v 1.4 2003/07/08 12:35:40 gpotts Exp $ +#include "base/data_types/ossimHexString.h" + +ossim_int32 ossimHexString::toInt32()const +{ + return static_cast<ossim_int32>(toUint32()); +} + +ossim_int16 ossimHexString::toInt16()const +{ + return static_cast<ossim_int16>(toUint32()); +} + +ossim_int8 ossimHexString::toChar()const +{ + return static_cast<ossim_int8>(toUint32()); +} + +ossim_uint8 ossimHexString::toUchar()const +{ + return static_cast<ossim_uint8>(toUint32()); +} + +ossim_uint16 ossimHexString::toUint16()const +{ + return static_cast<ossim_uint16>(toUint32()); +} + +ossim_uint32 ossimHexString::toUint32()const +{ + ossim_uint32 temp=0; + + if(length()) + { + ossim_uint32 i = 0; + + if(((*this)[0] == '0')&& + (((*this)[1] == 'x')|| + ((*this)[1] == 'X'))) + { + i = 2; + } + + for(; i <length(); ++i) + { + temp <<=4; + if( ((*this)[(int)i] >= '0')&&((*this)[(int)i] <= '9')) + { + temp |= (ossim_uint32)((*this)[(int)i] - '0'); + } + else if( ((*this)[(int)i] >= 'A') && ((*this)[(int)i] <= 'F')) + { + temp |= (ossim_uint32)(10+((*this)[(int)i] - 'A')); + } + else if( ((*this)[(int)i] <= 'f') && ((*this)[(int)i] >= 'a')) + { + temp |= (ossim_uint32)(10 + ((*this)[(int)i] - 'a')); + } + } + } + + return temp; +} + +void ossimHexString::assign(ossim_uint8 value) +{ + *this = ""; + + ossim_int8 v1 = (ossim_int8)(value&0x0F); + ossim_int8 v2 = (ossim_int8)((value>>4)&0x0F); + if(v2 <=9) + { + (*this) += (ossim_int8)(v2+'0'); + } + else + { + (*this) += (ossim_int8)(v2-10 +'A'); + } + + if(v1 <=9) + { + (*this) += (ossim_int8)(v1+'0'); + } + else + { + (*this) += (ossim_int8)(v1-10 +'A'); + } +} + +void ossimHexString::assign(ossim_uint16 value) +{ + *this = ""; + + ossim_int8 v1 = (ossim_int8)(value&0x000F); + value >>=4; + ossim_int8 v2 = (ossim_int8)((value)&0x000F); + value >>=4; + ossim_int8 v3 = (ossim_int8)((value)&0x000F); + value >>=4; + ossim_int8 v4 = (ossim_int8)((value)&0x000F); + + if(v4 <=9) + { + (*this) += (ossim_int8)(v4+'0'); + } + else + { + (*this) += (ossim_int8)(v4-10 +'A'); + } + + if(v3 <=9) + { + (*this) += (ossim_int8)(v3+'0'); + } + else + { + (*this) += (ossim_int8)(v3-10 +'A'); + } + + if(v2 <=9) + { + (*this) += (ossim_int8)(v2+'0'); + } + else + { + (*this) += (ossim_int8)(v2-10 +'A'); + } + + if(v1 <=9) + { + (*this) += (ossim_int8)(v1+'0'); + } + else + { + (*this) += (ossim_int8)(v1-10 +'A'); + } +} + +void ossimHexString::assign(ossim_uint32 value) +{ + *this = ""; + + ossim_int8 v1 = (ossim_int8)(value&0x0000000F); + value >>=4; + ossim_int8 v2 = (ossim_int8)((value)&0x0000000F); + value >>=4; + ossim_int8 v3 = (ossim_int8)((value)&0x0000000F); + value >>=4; + ossim_int8 v4 = (ossim_int8)((value)&0x0000000F); + value >>=4; + ossim_int8 v5 = (ossim_int8)((value)&0x0000000F); + value >>=4; + ossim_int8 v6 = (ossim_int8)((value)&0x0000000F); + value >>=4; + ossim_int8 v7 = (ossim_int8)((value)&0x0000000F); + value >>=4; + ossim_int8 v8 = (ossim_int8)((value)&0x0000000F); + + if(v8 <=9) + { + (*this) += (ossim_int8)(v8+'0'); + } + else + { + (*this) += (ossim_int8)(v8-10 +'A'); + } + if(v7 <=9) + { + (*this) += (ossim_int8)(v7+'0'); + } + else + { + (*this) += (ossim_int8)(v7-10 +'A'); + } + if(v6 <=9) + { + (*this) += (ossim_int8)(v6+'0'); + } + else + { + (*this) += (ossim_int8)(v6-10 +'A'); + } + if(v5 <=9) + { + (*this) += (ossim_int8)(v5+'0'); + } + else + { + (*this) += (ossim_int8)(v5-10 +'A'); + } + + if(v4 <=9) + { + (*this) += (ossim_int8)(v4+'0'); + } + else + { + (*this) += (ossim_int8)(v4-10 +'A'); + } + + if(v3 <=9) + { + (*this) += (ossim_int8)(v3+'0'); + } + else + { + (*this) += (ossim_int8)(v3-10 +'A'); + } + + if(v2 <=9) + { + (*this) += (ossim_int8)(v2+'0'); + } + else + { + (*this) += (ossim_int8)(v2-10 +'A'); + } + + if(v1 <=9) + { + (*this) += (ossim_int8)(v1+'0'); + } + else + { + (*this) += (ossim_int8)(v1-10 +'A'); + } +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimHexString.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimHexString.h new file mode 100644 index 0000000000..6ec97e648e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimHexString.h @@ -0,0 +1,152 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//******************************************************************** +// $Id: ossimHexString.h,v 1.6 2005/10/17 18:37:16 gpotts Exp $ +#include "base/data_types/ossimString.h" +#include "base/common/ossimConstants.h" + +class OSSIMDLLEXPORT ossimHexString : public ossimString +{ +public: + ossimHexString():ossimString() + {} + ossimHexString(const std::string& aString):ossimString(aString) + {} + ossimHexString(const char *aString):ossimString(aString?aString:"") + {} + ossimHexString(const ossimString& aString):ossimString(aString.c_str()) + {} + + ossimHexString(char value):ossimString() + { + assign(value); + } + ossimHexString(ossim_int16 value):ossimString() + { + assign(value); + } + ossimHexString(ossim_int32 value):ossimString() + { + assign(value); + } + ossimHexString(ossim_uint8 value):ossimString() + { + assign(value); + } + ossimHexString(ossim_uint16 value):ossimString() + { + assign(value); + } + ossimHexString(ossim_uint32 value):ossimString() + { + assign(value); + } + + bool operator==(const ossimHexString& s) const {return (strcmp(this->c_str(),s.c_str())==0);} + bool operator==(const char* s) const {return (strcmp(this->c_str(),s)==0);} + bool operator!=(const ossimHexString& s) const {return (strcmp(this->c_str(),s.c_str())!=0);} + bool operator!=(const char* s) const {return (strcmp(this->c_str(),s)!=0);} + operator const char*()const{return c_str();} + const char* chars()const{return c_str();} + char& operator[](int i) + { + return *( const_cast<char*>(c_str())+i); + } + const char& operator[](int i)const + { + return *(c_str()+i); + } + const ossimHexString& operator =(ossim_int16 value) + { + assign(value); + return *this; + } + const ossimHexString& operator =(ossim_int32 value) + { + assign(value); + return *this; + } + const ossimHexString& operator =(ossim_uint16 value) + { + assign(value); + return *this; + } + const ossimHexString& operator =(ossim_uint32 value) + { + assign(value); + return *this; + } + const ossimHexString& operator =(ossim_int8 value) + { + assign(value); + return *this; + } + const ossimHexString& operator =(ossim_uint8 value) + { + assign(value); + return *this; + } + const ossimHexString& operator =(const ossim_int8* value) + { + ossimString::operator=(value); + return *this; + } + const ossimHexString& operator =(const ossimString& value) + { + ossimString::operator=(value); + return *this; + } + + const ossimHexString& operator =(const ossimHexString& value) + { + ossimString::operator=(value); + return *this; + } + + const ossimHexString& operator =(const std::string& value) + { + ossimString::operator=(value); + return *this; + } + + ossim_int32 toInt32()const; + ossim_int16 toInt16()const; + ossim_int8 toChar()const; + ossim_uint8 toUchar()const; + ossim_uint32 toUint32()const; + ossim_uint16 toUint16()const; + + void assign(ossim_int16 value) + { + assign((ossim_uint16)value); + } + void assign(ossim_int32 value) + { + assign((ossim_uint32)value); + } + void assign(ossim_int8 value) + { + assign((ossim_uint8)value); + } + void assign(ossim_uint16 value); + void assign(ossim_uint32 value); + void assign(ossim_uint8 value); +}; diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimHistogram.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimHistogram.cpp new file mode 100644 index 0000000000..c218f6e174 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimHistogram.cpp @@ -0,0 +1,1378 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Ken Melero (kmelero@imagelinks.com) +// Orginally developed by: +// Copyright (c) 1997 TargetJr Consortium +// GE Corporate Research and Development (GE CRD) +// 1 Research Circle +// Niskayuna, NY 12309 +// Adapted from: IUE v4.1.2 +// Description: +// A ossimHistogram contains an array of "buckets", which represent finite +// segments of some value axis, along with a corresponding array of +// frequency counts for each of these buckets. +// +//******************************************************************** +// $Id: ossimHistogram.cpp,v 1.26 2005/09/09 11:14:07 gpotts Exp $ +// + +#include <stdio.h> +#include <fstream> +#include <iostream> +#include <sstream> +using namespace std; + +#include <math.h> +#include <base/common/ossimCommon.h> +#include <base/data_types/ossimHistogram.h> +#include <base/context/ossimNotifyContext.h> + +static const int MEAN_FLAG = 1, SD_FLAG = 2; +RTTI_DEF1(ossimHistogram, "ossimHistogram", ossimObject); +ossimHistogram::ossimHistogram() +{ + vals = new float [1]; + vals[0] = 0.0; + counts = new float [1]; + counts[0] = 0.0; + num = 0; + vmin = 0; + vmax = 0; + delta = 0.0; + mean = 0.0; + standard_dev = 0.0; + stats_consistent = 0; + stats_consistent |= (MEAN_FLAG | SD_FLAG); +} + +ossimHistogram::ossimHistogram(int xres, float val1, float val2) +{ + vals = new float [xres]; + counts = new float [xres]; + num = xres; + vmax = MAX(val1, val2); + vmin = MIN(val1, val2); + delta = (vmax - vmin) / xres; + mean = (float)((vmax + vmin)/2.0); + standard_dev = (float)((vmax - vmin)/(2.0*sqrt(3.0))); + stats_consistent = 0; + stats_consistent |= (MEAN_FLAG | SD_FLAG); + int i = 0; + + if (vals == NULL || counts == NULL) + { + fprintf(stderr, "Histogram : Ran out of memory for arrays.\n"); + vals = NULL; + counts = NULL; + num = 0; + vmin = 0; + vmax = 0; + delta = 0.0; + } + else + { + for(i = 0; i < xres; i++) + { + vals[i] = vmin + delta * (float)(i + 0.5); + counts[i] = 0.0; + } + } +} + +ossimHistogram::ossimHistogram(float* uvals, float* ucounts, int xres) +{ + vals = uvals; + counts = ucounts; + num = xres; + delta = vals[1] - vals[0]; // Changed this from delta = 1.0 +// vmax = GetMaxVal(); +// vmin = GetMinVal(); JAF version + vmin = uvals[0] - .5f*delta; + vmax = uvals[num-1] + .5f*delta; + mean = GetMean(); + standard_dev = GetStandardDev(); + stats_consistent = 0; + stats_consistent |= (MEAN_FLAG | SD_FLAG); +} +//----------------------------------------------------------- +// -- Copy constructor +ossimHistogram::ossimHistogram(const ossimHistogram& his) +{ + + int i = 0; + num = his.GetRes(); + + vals = new float[num]; + const float* his_vals = his.GetVals(); + + counts = new float[num]; + const float* his_counts = his.GetCounts(); + + if (vals == NULL || counts == NULL) + { + fprintf(stderr, "Histogram : Ran out of memory for arrays.\n"); + vals = NULL; + counts = NULL; + num = 0; + vmin = 0; + vmax = 0; + delta = 0.0; + stats_consistent = 0; + return; + } + + mean = his.GetMean(); + standard_dev = his.GetStandardDev(); + + for(i=0; i<num; i++) + { + vals[i] = his_vals[i]; + counts[i] = his_counts[i]; + } + vmax = his.GetMaxVal(); + vmin = his.GetMinVal(); + delta = his.GetBucketSize(); + + stats_consistent = 0; + stats_consistent |= (MEAN_FLAG | SD_FLAG); +} + + +//--------------------------------------- +// -- Resample a histogram + +ossimHistogram::ossimHistogram(const ossimHistogram* his, float width) +{ + + stats_consistent =0; + +// Attributes of original histogram + + float del = his->GetBucketSize(); + int max_index = his->GetRes() - 1; + float minvalue = his->GetVals()[0] - del*.5f; + float maxvalue = his->GetVals()[max_index] + del*.5f; + + +// Intialize a new histogram + if(width == del) num = his->GetRes(); + else if(!(width == 0.0)) + num = (int)ceil((maxvalue - minvalue)/width); + else + num = 1; // This shouldn't happen anyway. + + vals = new float [num]; + counts = new float [num]; + delta = width; + float mean_val = (maxvalue + minvalue)/2.0f; + float half_range = (num * delta)/2.0f; + vmax = mean_val + half_range; + vmin = mean_val - half_range; + int i = 0; + + if (vals == NULL || counts == NULL) + { + fprintf(stderr, + "Histogram : Ran out of memory for arrays.\n"); + vals = NULL; + counts = NULL; + num = 0; + vmin = 0; + vmax = 0; + delta = 0.0; + mean = 0.0; + standard_dev = 0.0; + stats_consistent |= (MEAN_FLAG | SD_FLAG); + return; + + } + + else + { + for(i = 0; i < num; i++) + { + vals[i] = vmin + delta * (i + 0.5f); + counts[i] = 0.0; + } + } + + +// Cases: + + + if(width == del) // Then just copy his + { + const float* his_counts = his->GetCounts(); + for(i=0; i<num; i++) + counts[i] = his_counts[i]; + mean = GetMean(); + standard_dev = GetStandardDev(); + stats_consistent |= (MEAN_FLAG | SD_FLAG); + return; + } + + + if(del > width) // Then interpolate his counts. + { + +// Boundary conditions: +// Start + float his_start = minvalue + .5f*del; + float start = vmin + .5f*delta; + float c0 = his->GetCount(his_start); + float c1 = his->GetCount(his_start + del); + float s0 = (c1 - c0)/del; + + for(float x = start; x <= (his_start + del + delta);) + { + float interp = s0 * (x - his_start) + c0; + if(interp < 0) interp = 0; //Can be negative + SetCount(x,interp); + x += width; + } +// End + float his_end = maxvalue - .5f*del; + float end = vmax - .5f*delta; + float cn = his->GetCount(his_end); + float cn_1 = his->GetCount(his_end - del); + float sn = (cn_1 - cn)/del; + + for(float y = end; y >= (his_end - del + delta);) + { + float interp = sn * (his_end - y) + cn; + if(interp < 0) interp = 0; //Can be negative + SetCount(y, interp); + y -= delta; + } +// Interior Loop + + for(float z = his_start + del; z <= (his_end - del);) + { + float ci = his->GetCount(z); + float ci_1 = his->GetCount(z-del); + float cip1 = his->GetCount(z+del); + float deriv = (cip1 - ci_1)/(2.0f*del); + float second_drv = + ((cip1 + ci_1)/2.0f - ci)/(del*del); + int fine_x_index = GetIndex(z); + if (fine_x_index < 0) + { + if (z<vmin) fine_x_index = 0; + else fine_x_index = num-1; + } + float fine_x = vals[fine_x_index]; + for(float xfine = fine_x; xfine < z + del;) + { + float interp = ci + deriv*(xfine -z) + + second_drv*(xfine - z)*(xfine - z); + + if(interp < 0) interp = 0; //Can be negative + SetCount(xfine, interp); + xfine += width; + } + z += del; + } + } + + + if(del < width) //Just accumulate samples from his into larger bins + { + if( del != 0.0){ + float his_start = minvalue + .5f*del; + float his_end = maxvalue - .5f*del; + for(float x = his_start; x <= his_end;) + { + SetCount(x, (GetCount(x) + his->GetCount(x))); + x += del; + } + } + } + mean = GetMean(); + standard_dev = GetStandardDev(); + stats_consistent =0; + stats_consistent |= (MEAN_FLAG | SD_FLAG); +} + +void ossimHistogram::create(int xres, float val1, float val2) +{ + // clear all the data + deleteAll(); + + // now set it up and initialize; + xres = xres >0? xres:1; + + vals = new float [xres]; + counts = new float [xres]; + num = xres; + vmax = MAX(val1, val2); + vmin = MIN(val1, val2); + + delta = (vmax - vmin) / xres; + mean = (float)((vmax + vmin)/2.0); + standard_dev = (float)((vmax - vmin)/(2.0*sqrt(3.0))); + stats_consistent = 0; + stats_consistent |= (MEAN_FLAG | SD_FLAG); + int i = 0; + if (vals == NULL || counts == NULL) + { + ossimNotify(ossimNotifyLevel_FATAL) << "Histogram : Ran out of memory for arrays.\n"; + vals = NULL; + counts = NULL; + num = 0; + vmin = 0; + vmax = 0; + delta = 0.0; + } + else + { + for(i = 0; i < xres; i++) + { + vals[i] = vmin + delta * (float)(i + 0.5); + counts[i] = 0.0; + } + } +} +//-------------------------------------------------- +// -- Transform the value axis of a histogram by a +// translation, transl, and a scale factor, scale. +// The new histogram has the same resolution as his. + +ossimHistogram* ossimHistogram::Scale(float scale_factor) +{ + +// Extract attributes of self + +// float lowvalue = vals[0]; + float highvalue = vals[num-1]; + +// Construct a new histogram + + ossimHistogram* scaled_his = new ossimHistogram(this, delta); + float* new_counts = scaled_his->GetCounts(); + int i = 0; + for(i=0; i < num; i++) // Initialize + new_counts[i] = 0.0; + +// Compute scaled values +// We assume that the new histogram is to be scaled down from his + + float scale = scale_factor; + if(scale_factor > 1.0) scale = 1.0; + + for(float x = highvalue; x > vmin;) + { + float trans_x = (x-vmin)*scale + vmin; // Scaled x. + int index = GetIndex(trans_x); + if (index < 0) + { + if (trans_x<vmin) index = 0; + else index = num-1; + } + float fraction = (trans_x - vals[index])/delta; + float abs_fraction = (float)fabs(fraction); + int x_index = GetIndex(x); + if (x_index < 0) + { + if (x<vmin) x_index = 0; + else x_index = num-1; + } + +// Distribute the counts in proportion + + new_counts[index] += (1.0f - abs_fraction)*counts[x_index]; + if(fraction > 0) + if(index < (num-1)) + new_counts[index + 1] += + abs_fraction*counts[x_index]; + else + new_counts[index] += + abs_fraction*counts[x_index]; + else + if(index > 0) + new_counts[index - 1] += + abs_fraction*counts[x_index]; + else + new_counts[index] += + abs_fraction*counts[x_index]; + x -= delta; + } + +// Compute new Histogram attributes + + mean = scaled_his->GetMean(); + standard_dev = scaled_his->GetStandardDev(); + return scaled_his; +} + +//--------------------------------------------------------------------- +// -- Assuming that "this" is a histogram of population density, +// construct a new histogram which is the cumulative distribution. +// Each bin, xi, in his is assumed to represent a density, i.e., +// {x | (xi - .5*delta) < x <= (xi + .5*delta)} +// Each bin, xi, in the result represents a cumulative distribution, i.e., +// {x | x <= (xi + .5*delta)} +ossimHistogram* ossimHistogram::CumulativeGreaterThanEqual()const +{ + ossimHistogram* cum_his = new ossimHistogram(*this); + const float* density_counts = this->GetCounts(); + int res = this->GetRes(); + + // Intitialize cumulative counts + float* cum_counts = cum_his->GetCounts(); + int i = 0; + for(i=0; i < res; i++) + cum_counts[i] = 0; + + cum_counts[res-1] = density_counts[res-1]; + for(i = res-2; i>=0; --i) + { + cum_counts[i] += (density_counts[i] + cum_counts[i+1]); + } + + return cum_his; +} + +ossimHistogram* ossimHistogram::CumulativeLessThanEqual()const +{ + ossimHistogram* cum_his = new ossimHistogram(*this); + const float* density_counts = this->GetCounts(); + int res = this->GetRes(); + + // Intitialize cumulative counts + float* cum_counts = cum_his->GetCounts(); + int i = 0; + for(i=0; i < res; i++) + cum_counts[i] = 0; + + cum_counts[0] = density_counts[0]; + for(i = 1; i < res; i++) + { + cum_counts[i] += (density_counts[i] + cum_counts[i-1]); + } + + return cum_his; +} + +//Provides the correct values for histogram counts when the bin index +//extends outside the valid range of the counts array. This function +//permits easy array access logic for the NonMaximumSuppression algorithm. +//The cyclic flag indicates that the counts array index is circular, i.e, +//cnts[0] equivalent to cnts[n_bins-1] +inline float GetExtendedCount(int bin, int n_bins, float* cnts, bool cyclic) +{ + int nbm = n_bins-1; + if(!cyclic) + { + if(bin < 0) + return cnts[0]; + if(bin >= n_bins) + return cnts[nbm]; + } + else + { + if(bin<0) + return cnts[nbm+bin]; + if(bin >= n_bins) + return cnts[bin-n_bins]; + } + return cnts[bin]; +} +//Prune any sequences of more than one maxium value +//That is, it is possible to have a "flat" top peak with an arbitarily +//long sequence of equal, but maximum values. The cyclic flag indictates +//that the sequence wraps around, i.e. cnts[0] equivalent to cnts[nbins-1] +inline void RemoveFlatPeaks(int nbins, float* cnts, bool cyclic) +{ + int nbm = nbins-1; + + //Here we define a small state machine - parsing for runs of peaks + //init is the state corresponding to an initial run (starting at i ==0) + bool init=GetExtendedCount(0, nbins, cnts, cyclic); + int init_end =0; + + //start is the state corresponding to any other run of peaks + bool start=false; + int start_index=0; + int i = 0; + + //The scan of the state machine + for(i = 0; i < nbins; i++) + { + float v = GetExtendedCount(i, nbins, cnts, cyclic); + + //State init: a string of non-zeroes at the begining. + if(init&&v!=0) + continue; + + if(init&&v==0) + { + init_end = i; + init = false; + continue; + } + + //State !init&&!start: a string of "0s" + if(!start&&v==0) + continue; + + //State !init&&start: the first non-zero value + if(!start&&v!=0) + { + start_index = i; + start = true; + continue; + } + //State ending flat peak: encountered a subsequent zero after starting + if(start&&v==0) + { + int peak_location = (start_index+i-1)/2;//The middle of the run + int k = 0; + for(k = start_index; k<=(i-1); k++) + if(k!=peak_location) + cnts[k] = 0; + start = false; + } + } + //Now handle the boundary conditions + //The non-cyclic case + if(!cyclic) + { + if(init_end!=0) //Was there an initial run of peaks? + { + int init_location = (init_end-1)/2; + int k = 0; + for(k = 0; k<init_end; k++) + if(k!=init_location) + cnts[k] = 0; + } + if(start) // Did we reach the end of the array in a run of pks? + { + int end_location = (start_index + nbm)/2; + int k = 0; + for(k = start_index; k<nbins; k++) + if(k!=end_location) + cnts[k] = 0; + } + } + else //The cyclic case + { + if(init_end!=0) //Is there a run which crosses the cyclic cut? + if(start) + { //Yes, so define the peak location accordingly + int peak_location = (start_index + init_end - nbm -1)/2; + int k; + if(peak_location < 0) //Is the peak to the left of the cut? + {// Yes, to the left + peak_location += nbm; + for( k = 0; k< init_end; k++) + cnts[k]=0; + for( k= start_index; k <nbins; k++) + if(k!=peak_location) + cnts[k] = 0; + } + else + {//No, on the right. + for( k = start_index; k< nbins; k++) + cnts[k]=0; + for( k= 0; k < init_end; k++) + if(k!=peak_location) + cnts[k] = 0; + } + } + else + {//There wasn't a final run so just clean up the initial run + int init_location = (init_end-1)/2; + int k = 0; + for(k = start_index; k<init_end; k++) + if(k!=init_location) + cnts[k] = 0; + } + } +} + +//---------------------------------------------------------- +// -- Suppress values in the Histogram which are not locally +// a maxium. The neighborhood for computing the local maximum +// is [radius X radius], e.g. for radius =1 the neighborhood +// is [-X-], for radius = 2, the neighborhood is [--X--], etc. +// If the cyclic flag is true then the index space is assumed to +// be equivalent to a circle. That is, elements "0" and (n_buckets-1) +// are in correspondence. +ossimHistogram* ossimHistogram::NonMaximumSupress(int radius, bool cyclic) +{ + if((2*radius +1)> num/2) + { + ossimNotify(ossimNotifyLevel_WARN)<<"ossimHistogram::NonMaximumSupress the radius is too large \n"; + return NULL; + } + //Get the counts array of "this" + ossimHistogram* h_new = new ossimHistogram(*this); + int n_buckets = h_new->GetRes(); + float* counts_old = this->GetCounts(); + + //Make a new Histogram for the suppressed version + float* counts_new = h_new->GetCounts(); + int i; + for( i =0; i < n_buckets; i++) + counts_new[i] = 0; + + //Find local maxima + for( i = 0; i< n_buckets; i++) + { + //find the maxium value in the current kernel + float max_count = counts_old[i]; + int k = 0; + for(k = -radius; k <= radius ;k++) + { + int index = i+k; + float c = GetExtendedCount(index, n_buckets, counts_old, cyclic); + if( c > max_count) + max_count = c; + } + //Is position i a local maxium? + if(max_count == counts_old[i]) + counts_new[i] = max_count;//Yes. So set the counts to the max value + } + RemoveFlatPeaks(n_buckets, counts_new, cyclic); + return h_new; +} +//---------------------------------------------------------- +// -- Compute the mean of the histogram population +float ossimHistogram::GetMean()const +{ + float xsum = 0.0; + + if(MEAN_FLAG&stats_consistent) + return mean; + else + { + if( this->GetBucketSize() > 0.0){ + for(float x=this->GetMinVal(); x<= this->GetMaxVal(); x +=this->GetBucketSize()) + xsum += x*GetCount(x); + } + + float area = ComputeArea(vmin, vmax); + if(area <= 0.0) + { + // fprintf(stderr, "Histogram : Area <= 0.0\n"); + return 0.0; + } + else + { + stats_consistent |=1; + mean = xsum/area; + return mean; + } + } +} + + + +float ossimHistogram::GetStandardDev()const +{ + float sum = 0.0; + + if(SD_FLAG&stats_consistent) + return standard_dev; + else + { + float xm = this -> GetMean(); // Force an Update of Mean + + if( this->GetBucketSize() > 0.0){ + for(float x=this->GetMinVal(); + x<= this->GetMaxVal(); + x +=this->GetBucketSize()) + + sum += (x-xm)*(x-xm)*GetCount(x); + } + + float area = ComputeArea(vmin, vmax); + if(area <= 0.0) + { + // fprintf(stderr, "Histogram : Area <= 0.0\n"); + return 0.0; + } + else + { + stats_consistent |= 2; + standard_dev = (float)sqrt(sum/area); + return standard_dev; + } + } +} + +int ossimHistogram::GetIndex(float pixelval)const +{ + if ((pixelval > vmax) || (pixelval < vmin)||(num==0)) + { + return -1; + } +// ossim_float32 d = vmax-vmin; + int bandIdx = (ossim_int32)((pixelval-vmin)/delta); + return bandIdx<GetRes()?bandIdx:-1; +// if(bandIdx == num) +// { +// return num-1; +// } +// else if(bandIdx < num) +// { +// return bandIdx; +// } +// return -1; +#if 0 + if ((pixelval > vmax) || (pixelval < vmin)) + return -1; + + int idx = 0; + int i = 0; + + for(i = 0; i < num; i++) + { + // RWMC: This is very dangerous - might get an intermediate + // value which is between vals[i]+0.5*delta and + // vals[i+1]-0.5*delta, which would then return index of 0. + // Changed to check range one-sided, which is safe because of + // previous check on range. + // if ((pixelval > (vals[i] - 0.5 * delta)) && + // (pixelval <= (vals[i] + 0.5 * delta))) + if (pixelval <= (vals[i] + 0.5 * delta)) + { + idx = i; + break; + } + } + + return idx; +#endif +} + + +int ossimHistogram::GetValIndex(float pixelval)const +{ + if ((pixelval > vmax) || (pixelval < vmin)) + return -1; + + int idx = 0; + int i = 0; + + for(i = 0; i < num; i++) + { + if ((pixelval > (vals[i] - 0.5 * delta)) && + (pixelval <= (vals[i] + 0.5 * delta))) + { + idx = i; + break; + } + } + + return idx; +} + + + +float ossimHistogram::GetCount(float pixelval)const +{ + int index = GetIndex(pixelval); + + if (index < 0) + return -1; + else + return counts[index]; +} + + + +float ossimHistogram::GetMinVal()const +{ + register int i=0; + + while (i<num-1 && !counts[i]) + i++; + + return vals[i]; +} + + + + +float ossimHistogram::GetMaxVal()const +{ + register int i=num-1; + + while (i>0 && !counts[i]) + i--; + + if (i < 0) + return 0.0; + + return vals[i]; +} + + +float ossimHistogram::GetMaxCount()const +{ + register int i=0; + float max; + max = 0.0; + for (i=0; i < num; i++) + if (counts[i] > max) + max = counts[i]; + return max; +} + + + + +float ossimHistogram::SetCount(float pixelval, float count) +{ + stats_consistent = 0; + + int index = GetIndex(pixelval); + + if (index < 0) + return -1; + else + { + counts[index] = count; + return count; + } +} + + +void ossimHistogram::UpCount(float pixelval) +{ + + stats_consistent = 0; + int idx = GetIndex(pixelval); + if (idx >= 0) // Originally (index > 0) + { + counts[idx] += 1.0; + } +} + +float ossimHistogram::ComputeArea(float low, float high)const +{ + float maxval = GetMaxVal(); + float minval = GetMinVal(); + + if (low < minval) low = minval; + if (high > maxval) high = maxval; + + if (low <= high) + { + int indexlow, indexhigh; + indexlow = (int) GetIndex(low); + if (indexlow < 0) + { + if (low<vmin) indexlow = 0; + else indexlow = num-1; + } + indexhigh = (int) GetIndex(high); + if (indexhigh < 0) + { + if (high<vmin) indexhigh = 0; + else indexhigh = num-1; + } + register int i=indexlow; + float sum = 0.0; + + while (i<=indexhigh) + { + sum+= counts[i]; + i++; + } + return sum; + } + else + { + // fprintf(stderr, "Histogram : Range for ComputeArea is out of bounds.\n"); + return 0.0; + } +} +//---------------------------------------------------------------------- +// --Compute the total area under the histogram +// +float ossimHistogram::ComputeArea()const +{ + float vmin = this->GetMinVal(); + float vmax = this->GetMaxVal(); + if(vmin>vmax) + { + float temp = vmin; + vmin = vmax; + vmax = temp; + } + return this->ComputeArea(vmin, vmax); +} + +float ossimHistogram::getLowFractionFromValue(float val) const +{ + + float min = floor(GetMinVal()); + float max = ceil(GetMaxVal()); + if (val < min || val > max) + { + return OSSIM_FLT_NAN; + } + + int total_buckets = GetRes(); + int cutoff_bucket = GetValIndex(val); + float partial_sum = 0.0; + float total_sum = 0.0; + + for(int i = 0; i < total_buckets; ++i) + { + total_sum += counts[i]; + if (i <= cutoff_bucket) + { + partial_sum += counts[i]; + } + } + + return (partial_sum/total_sum); +} + +float ossimHistogram::getHighFractionFromValue(float val) const +{ + float min = floor(GetMinVal()); + float max = ceil(GetMaxVal()); + if (val < min || val > max) + { + return OSSIM_FLT_NAN; + } + + int total_buckets = GetRes(); + int cutoff_bucket = GetValIndex(val); + float partial_sum = 0.0; + float total_sum = 0.0; + + for(int i = (total_buckets-1); i >= 0; --i) + { + total_sum += counts[i]; + if (i >= cutoff_bucket) + { + partial_sum += counts[i]; + } + } + + return (partial_sum/total_sum); +} + +//---------------------------------------------------------------------- +// -- Finds the lower bound value which elminates a given fraction of +// histogram area. +// +float ossimHistogram::LowClipVal(float clip_fraction)const +{ + if(clip_fraction<0) clip_fraction=0.0; + if(clip_fraction>1.0) clip_fraction=1.0; + float area = this->ComputeArea(); + if(area==0.0) return this->GetMinVal(); + if(clip_fraction==0.0) return this->GetMinVal(); + if(clip_fraction==1.0) return this->GetMaxVal(); + float clip_area = area*clip_fraction; + const float* COUNTS = this->GetCounts(); + const float* VALS = this->GetVals(); + int res = this->GetRes(); + float sum = 0; + int i=0; + for(; i<res; i++) + { + sum+=COUNTS[i]; + if(sum>=clip_area) + break; + } + return VALS[i]; +} + +//---------------------------------------------------------------------- +// -- Finds the lower bound value which elminates a given fraction of +// histogram area. +// +float ossimHistogram::HighClipVal(float clip_fraction)const +{ + if(clip_fraction<0) clip_fraction=0.0; + if(clip_fraction>1.0) clip_fraction=1.0; + float area = this->ComputeArea(); + if(area==0.0) return this->GetMaxVal(); + if(clip_fraction==0.0) return this->GetMaxVal(); + if(clip_fraction==1.0) return this->GetMinVal(); + float clip_area = area*clip_fraction; + const float* COUNTS = this->GetCounts(); + const float* VALS = this->GetVals(); + int res = this->GetRes(); + float sum = 0; + int i = (res-1); + for(; i>=0; i--) + { + sum+=COUNTS[i]; + if(sum>=clip_area) + break; + } + return VALS[i]; +} + +//-------------------------------------------------------------------------- +// -- Prints histogram counts onto cout +void ossimHistogram::Print()const +{ + ostream& out = ossimNotify(ossimNotifyLevel_INFO); + const float* VALS = this->GetVals(); + const float* COUNTS = this->GetCounts(); + int res = this->GetRes(); + int width = 0; + int i = 0; + for(i =0; i < res; i++) + { + if(width++ > 5) + { + width = 0; + out << "\n"; + } + out << VALS[i] << " " + << COUNTS[i] << " | " ; + } + out << "\n MaxVal " << this->GetMaxVal() << "\n"; + out << " MinVal " << this->GetMinVal() << "\n"; + out << " BucketSize " << this->GetBucketSize() << "\n"; + out << " Resolution " << this->GetRes() << "\n"; + out << " Area " + << this->ComputeArea(this->GetMinVal(),this->GetMaxVal()) << "\n"; + out << "------------------------------------------------\n\n"; +} + +//--------------------------------------------------------------------------- +// --- dumps histogram values to file. + +void ossimHistogram::Dump(char *dumpfile)const +{ + FILE *dumpfp = fopen(dumpfile, "w"); + + if (!dumpfp) + { + fprintf(stderr, "Error opening histogram data file.\n"); + return; + } + int i = 0; + + for(i = 0; i < num; i++) + fprintf(dumpfp, "%f %f\n", vals[i], counts[i]); + + fclose(dumpfp); + return; +} + +//--------------------------------------------------------------------------- +// -- Writes histogram in format suitable for plotting tools like Gnuplot. + +int ossimHistogram::WritePlot(const char *fname)const +{ + FILE *fp = fopen(fname, "w"); + + if (!fp) + { + fprintf(stderr, "Error opening histogram plot file.\n"); + return 0; + } + + int stat_res = this->GetRes(); + + float * x = new float[2*stat_res]; + float * y = new float[2*stat_res]; + + const float * temp_x = this->GetVals(); + const float * temp_y = this->GetCounts(); + float delt = this->GetBucketSize(); + + for (register int i=0; i < stat_res ;i++) + { + x[2*i] = temp_x[i] - 0.5f * delt; + x[2*i+1] = temp_x[i] + 0.5f * delt; + y[2*i] = temp_y[i]; + y[2*i+1] = temp_y[i]; + } + + + for(register int j = 0; j < 2*stat_res; j++) + fprintf(fp, "%f %f\n", x[j], y[j]); + + delete [] x; + delete [] y; + + fclose(fp); + return 1; +} + +void ossimHistogram::deleteAll() +{ + if (vals) + { + delete []vals; + vals = NULL; + } + if (counts) + { + delete []counts; + counts = NULL; + } +} + +ossimHistogram::~ossimHistogram() +{ + deleteAll(); +} + + +bool ossimHistogram::importHistogram(istream& in) +{ + ossimProprietaryHeaderInformation header; + bool binsCreated = false; + + if(header.parseStream(in)) + { + long numberOfBins = header.getNumberOfBins(); + + if(numberOfBins) + { + create(numberOfBins, 0, numberOfBins - 1); + binsCreated = true; + + if(binsCreated) + { + ossimString buffer; + ossimString binNumber; + ossimString count; + + while(in.good() && + !in.eof() && + *binNumber.c_str() != '.') + { + + getline(in, buffer); + + istringstream s(buffer); + + s >> binNumber >> count; + if(*binNumber.c_str() != (char)'.') + { + SetCount((float)binNumber.toDouble(), + (float)count.toDouble()); + } + } + } + } + else + { + return false; + } + } + return true; +} + +bool ossimHistogram::importHistogram(const ossimFilename& inputFile) +{ + if(inputFile.exists()) + { + ifstream input(inputFile.c_str()); + + return importHistogram(input); + } + + return false; +} + + +bool ossimHistogram::ossimProprietaryHeaderInformation::parseStream(istream& in) +{ + ossimString inputLine; + + getline(in, inputLine); + if(inputLine.find("File Type") != string::npos) + { + unsigned long index = inputLine.find(":"); + if(index != string::npos) + { + theFileType = inputLine.substr(index+1); + theFileType = theFileType.trim(); + } + else + { + return false; + } + + } + else + { + return false; + } + + getline(in, inputLine); + if(inputLine.find("Version") != string::npos) + { + unsigned long index = inputLine.find(":"); + if(index != string::npos) + { + theVersion = inputLine.substr(index+1); + theVersion = theVersion.trim(); + } + else + { + return false; + } + } + else + { + return false; + } + + getline(in, inputLine); + if(inputLine.find("Mapper Type") != string::npos) + { + unsigned long index = inputLine.find(":"); + if(index != string::npos) + { + theMapperType = inputLine.substr(index+1); + theMapperType = theMapperType.trim(); + } + else + { + return false; + } + } + else + { + return false; + } + + getline(in, inputLine); + if(inputLine.find("Number of Bins") != string::npos) + { + unsigned long index = inputLine.find(":"); + if(index != string::npos) + { + theNumberOfBins = inputLine.substr(index+1); + theNumberOfBins = theNumberOfBins.trim(); + } + else + { + return false; + } + } + else + { + return false; + } + + return true; +} + +bool ossimHistogram::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + "type", + "ossimHistogram", + true); + kwl.add(prefix, + "number_of_bins", + num, + true); + kwl.add(prefix, + "min_value", + vmin, + true); + kwl.add(prefix, + "max_value", + vmax, + true); + ossimString binValue = ""; + for(long index = 0; index < num; ++index) + { + if(fabs(counts[index]) > FLT_EPSILON) + { + // binValue = prefix; + binValue = "bin"; + binValue += ossimString::toString(index); + + kwl.add(prefix, + binValue.c_str(), + counts[index], + true); + } + } + + return true; +} + +bool ossimHistogram::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* number_of_bins = kwl.find(prefix, "number_of_bins"); + + if(number_of_bins) + { + long bins = ossimString(number_of_bins).toLong(); + + if(bins > 0) + { + // setup some defaults + float minValue = 0; + float maxValue = bins - 1; + + // see if there is a range set for the data + const char* min_value = kwl.find(prefix, "min_value"); + const char* max_value = kwl.find(prefix, "max_value"); + + if(min_value) + { + minValue = (ossim_float32)ossimString(min_value).toDouble(); + } + if(max_value) + { + maxValue = (ossim_float32)ossimString(max_value).toDouble(); + } + // create the bins + create(bins, minValue, maxValue); + ossimString binNumber = ""; + ossimString regExpression = ossimString("^(") + ossimString(prefix) + "bin[0-9]+)"; + vector<ossimString> keys = kwl.getSubstringKeyList( regExpression ); + ossim_uint32 numberOfBins = keys.size(); + ossim_uint32 offset = (ossimString(prefix)+"bin").size(); + + std::vector<ossim_uint32> theNumberList(numberOfBins); + ossim_uint32 idx = 0; + for(idx = 0; idx < theNumberList.size();++idx) + { + ossimString numberStr(keys[idx].begin() + offset, + keys[idx].end()); + theNumberList[idx] = numberStr.toUInt32(); + + } + + float* countsPtr = GetCounts(); + memset(countsPtr, '\0', bins*sizeof(float)); + for(idx = 0; idx < numberOfBins;++idx) + { + const char* binCount = kwl.find(prefix, ossimString("bin") + ossimString::toString(theNumberList[idx])); + countsPtr[theNumberList[idx]] = (float)ossimString(binCount).toDouble(); + } + } + } + return true; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimHistogram.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimHistogram.h new file mode 100644 index 0000000000..b053f70a0a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimHistogram.h @@ -0,0 +1,206 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Ken Melero (kmelero@imagelinks.com) +// Orginally developed by: +// Copyright (c) 1997 TargetJr Consortium +// GE Corporate Research and Development (GE CRD) +// 1 Research Circle +// Niskayuna, NY 12309 +// Adapted from: IUE v4.1.2 +// Description: +// A Histogram contains an array of "buckets", which represent finite +// segments of some value axis, along with a corresponding array of +// frequency counts for each of these buckets. +// +//******************************************************************** +// $Id: ossimHistogram.h,v 1.11 2005/09/01 13:59:47 gpotts Exp $ +// + +#ifndef ossimHistogram_HEADER +#define ossimHistogram_HEADER +#include <base/common/ossimObject.h> +#include "ossimString.h" +#include "ossimFilename.h" +#include "ossimKeywordlist.h" +class OSSIMDLLEXPORT ossimHistogram : public ossimObject +{ + private: + + mutable int stats_consistent; // A 2 bit state flag Mean =1 | StandDev = 2 + + protected: + + virtual void deleteAll(); + + float * vals; // histogram x array + // (value = midpoint of each bucket) + float * counts; // histogram y array ie. count[i] is + // the number of pixels with value within range + // of bucket i + + int num; // number of indices + + float delta; // "Width" of each bucket on value axis + float vmin, vmax; // Maximum and minimum values on plot + mutable float mean; // Mean value of the distribution + mutable float standard_dev; // + protected: + + + class ossimProprietaryHeaderInformation + { + public: + ossimProprietaryHeaderInformation(){clear();} + + bool parseStream(istream& in); + + long getNumberOfBins() + { + return theNumberOfBins.toLong(); + } + void clear() + { + theFileType = ""; + theVersion = ""; + theMapperType = ""; + theNumberOfBins = ""; + } + ossimString theFileType; + ossimString theVersion; + ossimString theMapperType; + ossimString theNumberOfBins; + }; + + public: +// Constructors + ossimHistogram(); + ossimHistogram(int xres, float min, float max); + ossimHistogram(float*, float*, int); + ossimHistogram(const ossimHistogram& his); // Copy constructor + ossimHistogram(const ossimHistogram*, float width); // Resampling constructor + + virtual int GetIndex(float)const; +// Other histogram formation operations + ossimHistogram* Scale(float scale_factor); // Scale Transformation + ossimHistogram* CumulativeGreaterThanEqual()const;// From density to cumulative + ossimHistogram* CumulativeLessThanEqual()const;// From density to cumulative + //Suppress non-peak values. + ossimHistogram* NonMaximumSupress(int radius = 1, bool cyclic = false); + void create(int xres, float val1, float val2); + +// Attribute accessors + void UpCount(float newval); + float GetCount(float uval)const; + float SetCount(float pixelval, float count); + + float GetMinVal()const; + float GetMaxVal()const; + float GetMaxCount()const; + + float GetRangeMin()const + { + return vmin; + } + float GetRangeMax()const + { + return vmax; + } + float * GetVals() + { + stats_consistent = 0; // Values might change. + return vals; + } + const float * GetVals()const + { + stats_consistent = 0; // Values might change. + return vals; + } + + float * GetCounts() + { + stats_consistent = 0; // Counts might change. + return counts; + } + + const float * GetCounts()const + { + stats_consistent = 0; // Counts might change. + return counts; + } + + int GetRes()const + { return num; } + + float GetBucketSize()const { return delta; } + + float * GetMinValAddr() + { return vals+GetIndex(GetMinVal()); } + + float * GetMinCountAddr() + { return counts+GetIndex(GetMinVal()); } + + const float * GetMinValAddr()const + { return vals+GetIndex(GetMinVal()); } + + const float * GetMinCountAddr()const + { return counts+GetIndex(GetMinVal()); } + + float ComputeArea(float low, float high)const;// bounded area + float ComputeArea()const;//total area + + /*! + * Returns the fraction of accumulation up to and including "val" bucket + * from min divided by the total accumulation. + * returns OSSIM_FLT_NAN if "val" is not between GetMinVal and GetMaxVal. + */ + float getLowFractionFromValue(float val) const; + + /*! + * Returns the fraction of accumulation down to and including "val" bucket + * from max divided by the total accumulation. + * returns OSSIM_FLT_NAN if "val" is not between GetMin() and GetMax(). + */ + float getHighFractionFromValue(float val) const; + + //Find bounds that clip off a given percent of the area + float LowClipVal(float clip_fraction)const; + float HighClipVal(float clip_fraction)const; + + int GetValIndex(float val)const; + + float GetMean()const; + float GetStandardDev()const; + + void Print()const; + void Dump(char *)const; + int WritePlot(const char* fname)const; + virtual ~ossimHistogram(); + + + virtual bool importHistogram(const ossimFilename& inputFile); + virtual bool importHistogram(istream& in); + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); +TYPE_DATA +}; + +#endif + diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimIpt.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimIpt.cpp new file mode 100644 index 0000000000..029003e566 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimIpt.cpp @@ -0,0 +1,204 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: David Burken +// +// Description: +// +// Contains class definitions for ipt. +// +//******************************************************************* +// $Id: ossimIpt.cpp,v 1.5 2005/12/16 14:25:11 dburken Exp $ + +#include <iostream> +#include <sstream> + +#include <base/data_types/ossimIpt.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimDpt3d.h> +#include <base/data_types/ossimFpt.h> +#include <base/common/ossimCommon.h> +#include <base/data_types/ossimString.h> + +//******************************************************************* +// Public constructor: +//******************************************************************* +ossimIpt::ossimIpt(const ossimDpt& pt) +{ + if(pt.hasNans()) + { + makeNan(); + } + else + { + x = irint(pt.x); + y = irint(pt.y); + } +} + +//******************************************************************* +// Public constructor: +//******************************************************************* +ossimIpt::ossimIpt(const ossimFpt& pt) +{ + if(pt.hasNans()) + { + makeNan(); + } + else + { + x = irint(pt.x); + y = irint(pt.y); + } +} + +ossimIpt::ossimIpt(const ossimDpt3d &pt) +{ + if(pt.hasNans()) + { + makeNan(); + } + else + { + x = irint(pt.x); + y = irint(pt.y); + } +} +//******************************************************************* +// Public method: +//******************************************************************* +const ossimIpt& ossimIpt::operator=(const ossimDpt& pt) +{ + if(pt.hasNans()) + { + makeNan(); + } + else + { + x = irint(pt.x); + y = irint(pt.y); + } + + return *this; +} + +//******************************************************************* +// Public method: +//******************************************************************* +const ossimIpt& ossimIpt::operator=(const ossimFpt& pt) +{ + if(pt.hasNans()) + { + makeNan(); + } + else + { + x = irint(pt.x); + y = irint(pt.y); + } + + return *this; +} + +std::ostream& ossimIpt::print(std::ostream& os) const +{ + os << "( "; + + if (x != OSSIM_INT_NAN) + { + os << x; + } + else + { + os << "nan"; + } + + os << ", "; + + if (y != OSSIM_INT_NAN) + { + os << y; + } + else + { + os << "nan"; + } + + os << " )"; + + return os; +} + +std::ostream& operator<<(std::ostream& os, const ossimIpt& pt) +{ + return pt.print(os); +} + +ossimString ossimIpt::toString() const +{ + std::ostringstream os; + print(os); + return ossimString(os.str()); +} + +std::istream& operator>>(std::istream& is, ossimIpt &pt) +{ + //--- + // Expected input format: + // ( 30, -90 ) + // -x- -y- + //--- + + // Start with a nan point. + pt.makeNan(); + + // Check the stream. + if (!is) return is; + + const int SZ = 64; // Handle real big number... + ossimString tempString; + char tempChars[SZ]; + char c; + + // Gobble the "(". + is >> tempString; + if (!is) return is; + + // Get the x. + is.get(tempChars, SZ, ','); + if (!is) return is; + tempChars[SZ-1] = '\0'; + tempString = tempChars; + tempString.trim(); + if (tempString == "nan") + { + pt.x = OSSIM_INT_NAN; + } + else + { + pt.x = tempString.toInt32(); + } + + // Eat the ",". + is.get(c); + + // Get the y. + is >> tempString; + tempString.trim(); + if (tempString == "nan") + { + pt.y = OSSIM_INT_NAN; + } + else + { + pt.y = tempString.toInt32(); + } + + // Gobble the trailing ")". + is >> tempString; + + // Finished + return is; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimIpt.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimIpt.h new file mode 100644 index 0000000000..d9fc774d7b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimIpt.h @@ -0,0 +1,142 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: David Burken +// +// Description: +// +// Contains class declaration for ipt. +// Used to represent an interger point containing an x and y data member. +// +//******************************************************************* +// $Id: ossimIpt.h,v 1.13 2005/12/16 14:25:11 dburken Exp $ + +#ifndef ossimIpt_HEADER +#define ossimIpt_HEADER +#include <iostream> +#include <cmath> + +#include <base/common/ossimConstants.h> +#include <base/data_types/ossimDpt.h> + +// Forward class declarations. +class OSSIMDLLEXPORT ossimFpt; +class OSSIMDLLEXPORT ossimDpt3d; +class OSSIMDLLEXPORT ossimString; + +class OSSIMDLLEXPORT ossimIpt +{ +public: + + ossimIpt() : x(0), y(0) {} + + ossimIpt(ossim_int32 anX, ossim_int32 aY) : x(anX), y(aY) {} + + ossimIpt(const ossimIpt& pt) : x(pt.x), y(pt.y) {} + + ossimIpt(const ossimDpt& pt); + + ossimIpt(const ossimFpt& pt); + + ossimIpt(const ossimDpt3d &pt); + + const ossimIpt& operator=(const ossimIpt& pt); + + const ossimIpt& operator=(const ossimDpt& pt); + + const ossimIpt& operator=(const ossimFpt& pt); + + bool operator==(const ossimIpt& pt) const + { return ( (x == pt.x) && (y == pt.y) ); } + + bool operator!=(const ossimIpt& pt) const + { return ( (x != pt.x) || (y != pt.y) ); } + + void makeNan(){x = OSSIM_INT_NAN; y=OSSIM_INT_NAN;} + bool hasNans()const + { + return (ossimIsNan(x) || ossimIsNan(y)); + } + bool isNan()const + { + return (ossimIsNan(x) && ossimIsNan(y)); + } + + std::ostream& print(std::ostream& os) const; + + friend OSSIMDLLEXPORT std::ostream& operator<<(std::ostream& os, + const ossimIpt& pt); + + /** + * @return ossimString representing point. + * + * Format: ( 30, -90 ) + * -x- -y- + */ + ossimString toString() const; + + /** + * Method to input the formatted string of the "operator<<". + * + * Expected format: ( 30, -90 ) + * -x- -y- + * + * This method starts by doing a "makeNan" on pt. So if anything goes + * wrong with the stream or parsing pt could be all or partially nan. + * + * @param is Input stream istream to formatted text. + * @param pt osimIpt to be initialized from stream. + * @return istream pass in. + */ + friend OSSIMDLLEXPORT std::istream& operator>>(std::istream& is, + ossimIpt& pt); + + /*! + * METHOD: length() + * Returns the RSS of the components. + */ + double length() const { return sqrt((double)x*x + (double)y*y); } + + //*** + // OPERATORS: +, -, +=, -= + // Point add/subtract with other point: + //*** + ossimIpt operator+(const ossimIpt& p) const + { return ossimIpt(x+p.x, y+p.y); } + ossimIpt operator-(const ossimIpt& p) const + { return ossimIpt(x-p.x, y-p.y); } + const ossimIpt& operator+=(const ossimIpt& p) + { x += p.x; y += p.y; return *this; } + const ossimIpt& operator-=(const ossimIpt& p) + { x -= p.x; y -= p.y; return *this; } + + //*** + // OPERATORS: *, / + // Scale point components by scalar: + //*** + ossimDpt operator*(const double& d) const + { return ossimDpt(d*x, d*y); } + ossimDpt operator/(const double& d) const + { return ossimDpt(x/d, y/d); } + + //*** + // Public data members: + //*** + union {ossim_int32 x; ossim_int32 u; ossim_int32 samp;}; + union {ossim_int32 y; ossim_int32 v; ossim_int32 line;}; + +}; + +inline const ossimIpt& ossimIpt::operator=(const ossimIpt& pt) +{ + if (this != &pt) + { + x = pt.x; + y = pt.y; + } + + return *this; +} +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimIrect.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimIrect.cpp new file mode 100644 index 0000000000..ac84de0d1a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimIrect.cpp @@ -0,0 +1,451 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class definition for ossimIrect. +// +//******************************************************************* +// $Id: ossimIrect.cpp,v 1.32 2005/07/15 18:51:25 dburken Exp $ + +#include <base/data_types/ossimIrect.h> +#include <base/data_types/ossimDrect.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/common/ossimKeywordNames.h> + +ossimIrect::ossimIrect(const ossimDrect& rect) + : + theUlCorner(rect.ul()), + theUrCorner(rect.ur()), + theLrCorner(rect.lr()), + theLlCorner(rect.ll()), + theOrientMode(rect.orientMode()) +{} + +ossimIrect::ossimIrect(const vector<ossimIpt>& points, + ossimCoordSysOrientMode mode) + : + theOrientMode (mode) +{ + if(points.size()) + { + unsigned long index; + ossim_int32 minx, miny; + ossim_int32 maxx, maxy; + + minx = points[0].x; + miny = points[0].y; + maxx = points[0].x; + maxy = points[0].y; + + // find the bounds + for(index = 1; index < points.size();index++) + { + minx = ossimMin(minx, points[index].x); + miny = ossimMin(miny, points[index].y); + maxx = ossimMax(maxx, points[index].x); + maxy = ossimMax(maxy, points[index].y); + + } + if(theOrientMode == OSSIM_LEFT_HANDED) + { + *this = ossimIrect(minx, miny, maxx, maxy, mode); + } + else + { + *this = ossimIrect(minx,maxy, maxx, miny, mode); + } + } + else + { + makeNan(); + } +} + +ossimIrect::ossimIrect(const ossimIpt& p1, + const ossimIpt& p2, + const ossimIpt& p3, + const ossimIpt& p4, + ossimCoordSysOrientMode mode) + :theOrientMode(mode) +{ + if(p1.hasNans()||p2.hasNans()||p3.hasNans()||p4.hasNans()) + { + makeNan(); + } + else + { + ossim_int32 minx, miny; + ossim_int32 maxx, maxy; + + minx = ossimMin( p1.x, ossimMin(p2.x, ossimMin(p3.x, p4.x))); + miny = ossimMin( p1.y, ossimMin(p2.y, ossimMin(p3.y, p4.y))); + maxx = ossimMax( p1.x, ossimMax(p2.x, ossimMax(p3.x, p4.x))); + maxy = ossimMax( p1.y, ossimMax(p2.y, ossimMax(p3.y, p4.y))); + + if(theOrientMode == OSSIM_LEFT_HANDED) + { + *this = ossimIrect(minx, miny, maxx, maxy, mode); + } + else + { + *this = ossimIrect(minx,maxy, maxx, miny, mode); + } + } +} + +ossimIrect::~ossimIrect() +{ +} + +//******************************************************************* +// Public Method: +//******************************************************************* +bool ossimIrect::intersects(const ossimIrect& rect) const +{ + if(rect.hasNans() || hasNans()) + { + return false; + } + if (theOrientMode != rect.theOrientMode) + return false; + + ossim_int32 ulx = MAX(rect.ul().x,ul().x); + ossim_int32 lrx = MIN(rect.lr().x,lr().x); + ossim_int32 uly, lry; + bool rtn; + + if (theOrientMode == OSSIM_LEFT_HANDED) + { + uly = MAX(rect.ul().y,ul().y); + lry = MIN(rect.lr().y,lr().y); + rtn = ((ulx <= lrx) && (uly <= lry)); + } + else + { + uly = MIN(rect.ul().y,ul().y); + lry = MAX(rect.lr().y,lr().y); + rtn = ((ulx <= lrx) && (uly >= lry)); + } + + return (rtn); +} + +void ossimIrect::stretchToTileBoundary(const ossimIpt& tileWidthHeight) +{ + ossimIpt ul; + ossimIpt lr; + + if(theOrientMode == OSSIM_LEFT_HANDED) + { + ul.x = theUlCorner.x; + if( (theUlCorner.x % tileWidthHeight.x) != 0) + { + ul.x = ((long)(ul.x / tileWidthHeight.x))*tileWidthHeight.x; + if(ul.x > theUlCorner.x) + { + ul.x -= tileWidthHeight.x; + } + } + ul.y = theUlCorner.y; + if( (theUlCorner.y % tileWidthHeight.y) != 0) + { + ul.y = ((long)(ul.y / tileWidthHeight.y))*tileWidthHeight.y; + if(ul.y > theUlCorner.y) + { + ul.y -= tileWidthHeight.y; + } + } + ossim_int32 w = (theLrCorner.x - ul.x) + 1; + ossim_int32 h = (theLrCorner.y - ul.y) + 1; + + ossim_int32 nw = (w / tileWidthHeight.x)*tileWidthHeight.x; + ossim_int32 nh = (h / tileWidthHeight.y)*tileWidthHeight.y; + + if(w%tileWidthHeight.x) + { + nw += tileWidthHeight.x; + } + if(h%tileWidthHeight.y) + { + nh += tileWidthHeight.y; + } + + lr.x = ul.x + (nw-1); + lr.y = ul.y + (nh-1); + } + else + { + ul.x = theUlCorner.x; + ul.y = theUlCorner.y; + if( (theUlCorner.x%tileWidthHeight.x)!= 0) + { + ul.x = ((long)(ul.x/ tileWidthHeight.x))*tileWidthHeight.x; + if(ul.x > theUlCorner.x) + { + ul.x -= tileWidthHeight.x; + } + } + if( (theUlCorner.y%tileWidthHeight.y)!=0 ) + { + ul.y = ((long)(ul.y / tileWidthHeight.y))*tileWidthHeight.y; + if(ul.y < theUlCorner.y) + { + ul.y += tileWidthHeight.y; + } + } + ossim_int32 w = ossimAbs(theLrCorner.x - ul.x) + 1; + ossim_int32 h = ossimAbs(theLrCorner.y - ul.y) + 1; + + ossim_int32 nw = (w / tileWidthHeight.x)*tileWidthHeight.x; + ossim_int32 nh = (h / tileWidthHeight.y)*tileWidthHeight.y; + + if(w%tileWidthHeight.x) + { + nw += tileWidthHeight.x; + } + if(h%tileWidthHeight.y) + { + nh += tileWidthHeight.y; + } + + lr.x = ul.x + (nw-1); + lr.y = ul.y - (nh-1); + } + + *this = ossimIrect(ul, lr, theOrientMode); +} + +//******************************************************************* +// Public Method: +//******************************************************************* +bool ossimIrect::completely_within(const ossimIrect& rect) const +{ + if(rect.hasNans() || hasNans()) + { + return false; + } + + if (theOrientMode != rect.theOrientMode) + return false; + + /* -------------- + | 1 | + | ---------- | + | | | | + | | | | + | | 2 | | + | | | | + | | | | + | ---------- | + | | + -------------- */ + + bool rtn = true; + + if (theUlCorner.x < rect.ul().x) + rtn = false; + + else if (theLrCorner.x > rect.lr().x) + rtn = false; + + else if (theOrientMode == OSSIM_LEFT_HANDED) + { + if (theUlCorner.y < rect.ul().y) + rtn = false; + + else if (theLrCorner.y > rect.lr().y) + rtn = false; + } + + else + { + if (theUlCorner.y > rect.ul().y) + rtn = false; + + else if (theLrCorner.y < rect.lr().y) + rtn = false; + } + + return rtn; +} + +//******************************************************************* +// Public Method: +//******************************************************************* +void ossimIrect::print(std::ostream& os) const +{ + os << theUlCorner << theLrCorner; +} + +//******************************************************************* +// friend function: operator<< +//******************************************************************* +ostream& operator<<(std::ostream& os, const ossimIrect& rect) +{ + rect.print(os); + + return os; +} + +//******************************************************************* +// Method: ossimIrect::clipToRect +//******************************************************************* +ossimIrect ossimIrect::clipToRect(const ossimIrect& rect)const +{ + if (theOrientMode != rect.theOrientMode) + return (*this); + + int x0 = MAX(rect.ul().x, ul().x); + int x1 = MIN(rect.lr().x, lr().x); + int y0, y1; + + if(!this->intersects(rect)) + { + return ossimIrect(OSSIM_INT_NAN, + OSSIM_INT_NAN, + OSSIM_INT_NAN, + OSSIM_INT_NAN); + + } + if (theOrientMode == OSSIM_LEFT_HANDED) + { + y0 = MAX(rect.ul().y, ul().y); + y1 = MIN(rect.lr().y, lr().y); + + if( (x1 < x0) || (y1 < y0) ) + return ossimIrect(ossimIpt(0,0), ossimIpt(0,0), theOrientMode); + else + return ossimIrect(x0, y0, x1, y1, theOrientMode); + } + else + { + y1 = MIN(rect.ul().y,ul().y); + y0 = MAX(rect.lr().y,lr().y); + + if((x1 < x0) || (y1 < y0)) + return ossimIrect(ossimIpt(0,0), ossimIpt(0,0), theOrientMode); + else + return ossimIrect(x0, y1, x1, y0, theOrientMode); + } +} + +//******************************************************************* +// Inline Method: ossimIrect::operator=(const ossimDrect& rect) +//******************************************************************* +const ossimIrect& ossimIrect::operator=(const ossimDrect& rect) +{ + theUlCorner = rect.ul(); + theUrCorner = rect.ur(); + theLrCorner = rect.lr(); + theLlCorner = rect.ll(); + theOrientMode = rect.orientMode(); + + return *this; +} + +bool ossimIrect::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + ossimKeywordNames::TYPE_KW, + "ossimIrect", + true); + + if(hasNans()) + { + kwl.add(prefix, + "ul_x", + "nan", + true); + kwl.add(prefix, + "ul_y", + "nan", + true); + kwl.add(prefix, + "lr_x", + "nan", + true); + kwl.add(prefix, + "lr_y", + "nan", + true); + } + else + { + kwl.add(prefix, + "ul_x", + theUlCorner.x, + true); + kwl.add(prefix, + "ul_y", + theUlCorner.y, + true); + kwl.add(prefix, + "lr_x", + theLrCorner.x, + true); + kwl.add(prefix, + "lr_y", + theLrCorner.y, + true); + } + + return true; +} + +bool ossimIrect::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* ulx = kwl.find(prefix, "ul_x"); + const char* uly = kwl.find(prefix, "ul_y"); + const char* lrx = kwl.find(prefix, "lr_x"); + const char* lry = kwl.find(prefix, "lr_y"); + + if(ulx&&uly&&lrx&&lry) + { + if( (ossimString(ulx).trim().upcase() == "NAN") || + (ossimString(uly).trim().upcase() == "NAN") || + (ossimString(lrx).trim().upcase() == "NAN") || + (ossimString(lry).trim().upcase() == "NAN")) + { + makeNan(); + } + else + { + *this = ossimIrect(ossimString(ulx).toLong(), + ossimString(uly).toLong(), + ossimString(lrx).toLong(), + ossimString(lry).toLong()); + } + } + else + { + makeNan(); + + return false; + } + + return true; +} + +void ossimIrect::getCenter(ossimDpt& center_point) const +{ + if (hasNans()) + { + center_point.makeNan(); + return; + } + + double d = (theUlCorner.x + theUrCorner.x + theLrCorner.x + theLlCorner.x); + center_point.x = d / 4.0; + + d = (theUlCorner.y + theUrCorner.y + theLrCorner.y + theLlCorner.y); + center_point.y = d / 4.0; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimIrect.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimIrect.h new file mode 100644 index 0000000000..d8a0667199 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimIrect.h @@ -0,0 +1,684 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: David Burken +// +// Description: +// +// Contains class declaration for ossimIrect. +// Container class for four integer points representing a rectangle. +// +//******************************************************************* +// $Id: ossimIrect.h,v 1.26 2005/12/16 14:26:21 dburken Exp $ + +#ifndef ossimIrect_HEADER +#define ossimIrect_HEADER +#include <iostream> +#include <vector> + +#include <base/data_types/ossimIpt.h> +#include <base/common/ossimCommon.h> + +//*** +// NOTE: A word on corner points... +// +// There is the concept of "pixel is area" and "pixel is point". +// - Pixel is area means the (x,y) pixel coordinate refers to the upper left +// corner of the pixel, NOT the center of the pixel. +// - Pixel is point means the (x,y) pixel coordinate refers to the center +// of the pixel, NOT the upper left corner. +// +// For the uniformity purposes, all pixel points should be in the +// "pixel is point" form; therefore, the (x,y) point should represent the +// CENTER of the pixel. +//*** + + +//*** +// Forward class declarations. +//*** +class OSSIMDLLEXPORT ossimDrect; +class OSSIMDLLEXPORT ossimKeywordlist; + +//******************************************************************* +// CLASS: ossimIrect +//******************************************************************* + +class OSSIMDLLEXPORT ossimIrect +{ +public: + enum + { + UPPER_LEFT = 1, + LOWER_LEFT = 2, + LOWER_RIGHT = 4, + UPPER_RIGHT = 8 + }; + + ossimIrect() + : + theUlCorner(0, 0), + theUrCorner(0, 0), + theLrCorner(0, 0), + theLlCorner(0, 0), + theOrientMode(OSSIM_LEFT_HANDED) + {} + + ossimIrect(ossimIpt ul_corner, + ossimIpt lr_corner, + ossimCoordSysOrientMode mode=OSSIM_LEFT_HANDED) + : + theUlCorner(ul_corner), + theUrCorner(lr_corner.x, ul_corner.y), + theLrCorner(lr_corner), + theLlCorner(ul_corner.x, lr_corner.y), + theOrientMode(mode) + {} + + ossimIrect(ossim_int32 ul_corner_x, + ossim_int32 ul_corner_y, + ossim_int32 lr_corner_x, + ossim_int32 lr_corner_y, + ossimCoordSysOrientMode mode=OSSIM_LEFT_HANDED) + : + theUlCorner(ul_corner_x, ul_corner_y), + theUrCorner(lr_corner_x, ul_corner_y), + theLrCorner(lr_corner_x, lr_corner_y), + theLlCorner(ul_corner_x, lr_corner_y), + theOrientMode(mode) + {} + + ossimIrect(const ossimIrect& rect) + : + theUlCorner(rect.ul()), + theUrCorner(rect.ur()), + theLrCorner(rect.lr()), + theLlCorner(rect.ll()), + theOrientMode(rect.orientMode()) + {} + + ossimIrect(const ossimDrect& rect); + + /*! + * Must compute a bounding rect given these image + * points. + */ + ossimIrect(const std::vector<ossimIpt>& points, + ossimCoordSysOrientMode mode=OSSIM_LEFT_HANDED); + + ossimIrect(const ossimIpt& p1, + const ossimIpt& p2, + const ossimIpt& p3, + const ossimIpt& p4, + ossimCoordSysOrientMode=OSSIM_LEFT_HANDED); + + /** destructor */ + ~ossimIrect(); + + const ossimIrect& operator= (const ossimIrect& rect); + const ossimIrect& operator= (const ossimDrect& rect); + bool operator!= (const ossimIrect& rect) const; + bool operator== (const ossimIrect& rect) const; + + friend ossimIrect operator*(double scalar, const ossimIrect& rect) + { + return ossimIrect((int)floor(rect.theUlCorner.x*scalar), + (int)floor(rect.theUlCorner.y*scalar), + (int)ceil(rect.theUlCorner.x*scalar+rect.width()*scalar-1), + (int)ceil(rect.theUlCorner.y*scalar+rect.height()*scalar-1), + rect.theOrientMode); + } + + const ossimIrect& operator *=(double scalar) + { + *this = ossimIrect((int)floor(theUlCorner.x*scalar), + (int)floor(theUlCorner.y*scalar), + (int)ceil(theUlCorner.x*scalar+width()*scalar-1), + (int)ceil(theUlCorner.y*scalar+height()*scalar-1), + theOrientMode); + return *this; + } + + ossimIrect operator *(double scalar)const + { + return ossimIrect((int)floor(theUlCorner.x*scalar), + (int)floor(theUlCorner.y*scalar), + (int)ceil(theUlCorner.x*scalar+width()*scalar-1), + (int)ceil(theUlCorner.y*scalar+height()*scalar-1), + theOrientMode); + } + const ossimIrect& operator *=(const ossimDpt& scalar) + { + *this = ossimIrect((int)floor(theUlCorner.x*scalar.x), + (int)floor(theUlCorner.y*scalar.y), + (int)ceil(theUlCorner.x*scalar.x+width()*scalar.x-1), + (int)ceil(theUlCorner.y*scalar.y+height()*scalar.y-1), + theOrientMode); + return *this; + } + + ossimIrect operator *(const ossimDpt& scalar)const + { + return ossimIrect((int)floor(theUlCorner.x*scalar.x), + (int)floor(theUlCorner.y*scalar.y), + (int)ceil(theUlCorner.x*scalar.x+width()*scalar.x-1), + (int)ceil(theUlCorner.y*scalar.y+height()*scalar.y-1), + theOrientMode); + } + const ossimIrect& operator +=(const ossimIpt& shift) + { + *this = ossimIrect(theUlCorner.x+shift.x, + theUlCorner.y+shift.y, + theLrCorner.x+shift.x, + theLrCorner.y+shift.y, + theOrientMode); + return *this; + } + + const ossimIrect& operator -=(const ossimIpt& shift) + { + *this = ossimIrect(theUlCorner.x-shift.x, + theUlCorner.y-shift.y, + theLrCorner.x-shift.x, + theLrCorner.y-shift.y, + theOrientMode); + return *this; + } + + ossimIrect operator +(const ossimIpt& shift)const + { + return ossimIrect(theUlCorner.x+shift.x, + theUlCorner.y+shift.y, + theLrCorner.x+shift.x, + theLrCorner.y+shift.y, + theOrientMode); + } + + ossimIrect operator -(const ossimIpt& shift)const + { + return ossimIrect(theUlCorner.x-shift.x, + theUlCorner.y-shift.y, + theLrCorner.x-shift.x, + theLrCorner.y-shift.y, + theOrientMode); + } + + + const ossimIrect& operator +=(const ossimDpt& shift) + { + *this = ossimIrect((int)floor(theUlCorner.x+shift.x), + (int)floor(theUlCorner.y+shift.y), + (int)ceil(theUlCorner.x+shift.x+width()-1), + (int)ceil(theUlCorner.y+shift.y+height()-1), + theOrientMode); + return *this; + } + + const ossimIrect& operator -=(const ossimDpt& shift) + { + *this = ossimIrect((int)floor(theUlCorner.x-shift.x), + (int)floor(theUlCorner.y-shift.y), + (int)ceil(theUlCorner.x-shift.x+width()-1), + (int)ceil(theUlCorner.y-shift.y+height()-1), + theOrientMode); + return *this; + } + + ossimIrect operator +(const ossimDpt& shift)const + { + return ossimIrect((int)floor(theUlCorner.x+shift.x), + (int)floor(theUlCorner.y+shift.y), + (int)ceil(theUlCorner.x+shift.x+width()-1), + (int)ceil(theUlCorner.y+shift.y+height()-1), + theOrientMode); + } + + ossimIrect operator -(const ossimDpt& shift)const + { + return ossimIrect((int)floor(theUlCorner.x-shift.x), + (int)floor(theUlCorner.y-shift.y), + (int)ceil(theUlCorner.x-shift.x+width()-1), + (int)ceil(theUlCorner.y-shift.y+height()-1), + theOrientMode); + return *this; + } + + + ossimIpt ul() const { return theUlCorner; } + ossimIpt ur() const { return theUrCorner; } + ossimIpt lr() const { return theLrCorner; } + ossimIpt ll() const { return theLlCorner; } + + void getBounds(ossim_int32& minx, ossim_int32& miny, + ossim_int32& maxx, ossim_int32& maxy)const + { + minx = theUlCorner.x; + maxx = theUrCorner.x; + if(theOrientMode == OSSIM_LEFT_HANDED) + { + miny = theUlCorner.y; + maxy = theUrCorner.y; + } + else + { + maxy = theUlCorner.y; + miny = theUrCorner.y; + } + } + + /*! + * Initializes center_point with center of the rectangle. + * Makes center_point nan if this rectangle has nans. + */ + void getCenter(ossimDpt& center_point) const; + + void makeNan() + { + theUlCorner.makeNan(); + theLlCorner.makeNan(); + theLrCorner.makeNan(); + theUrCorner.makeNan(); + } + + bool hasNans()const{ return (theUlCorner.hasNans() || + theLlCorner.hasNans() || + theLrCorner.hasNans() || + theUrCorner.hasNans());} + + bool isNan()const{ return (theUlCorner.hasNans() && + theLlCorner.hasNans() && + theLrCorner.hasNans() && + theUrCorner.hasNans());} + + //*** + // This class supports both left and right-handed coordinate systems. For + // both, the positive x-axis extends to the "right". + //*** + ossimCoordSysOrientMode orientMode() const { return theOrientMode; } + void setOrientMode(ossimCoordSysOrientMode mode) { theOrientMode = mode; } + + void stretchToTileBoundary(const ossimIpt& tileWidthHeight); + + ossim_uint32 area()const + { + return width()*height(); + } + + /*! + * Sets the upper left corner to "pt". Adjusts the remaining corners + * accordingly. + */ + void set_ul(const ossimIpt& pt); + + /*! + * Sets the upper right corner to "pt". Adjusts the remaining corners + * accordingly. + */ + void set_ur(const ossimIpt& pt); + + /*! + * Sets the lower right corner to "pt". Adjusts the remaining corners + * accordingly. + */ + void set_lr(const ossimIpt& pt); + + /*! + * Sets the lower left corner to "pt". Adjusts the remaining corners + * accordingly. + */ + void set_ll(const ossimIpt& pt); + + /*! + * Sets the upper left x. Adjusts the remaining corners accordingly. + */ + void set_ulx(ossim_int32 x); + + /*! + * Sets the upper left y. Adjusts the remaining corners accordingly. + */ + void set_uly(ossim_int32 y); + + /*! + * Sets the upper right x. Adjusts the remaining corners accordingly. + */ + void set_urx(ossim_int32 x); + + /*! + * Sets the upper right y. Adjusts the remaining corners accordingly. + */ + void set_ury(ossim_int32 y); + + /*! + * Sets the lower right x. Adjusts the remaining corners accordingly. + */ + void set_lrx(ossim_int32 x); + + /*! + * Sets the lower right y. Adjusts the remaining corners accordingly. + */ + void set_lry(ossim_int32 y); + + /*! + * Sets the lower left x. Adjusts the remaining corners accordingly. + */ + void set_llx(ossim_int32 x); + + /*! + * Sets the lower left y. Adjusts the remaining corners accordingly. + */ + void set_lly(ossim_int32 y); + + /*! + * Returns true if "pt" falls within rectangle. Fall on an edge is also + * considered to be within. + */ + bool pointWithin(const ossimIpt& pt) const; + + /*! + * Returns true if any portion of an input rectangle "rect" intersects + * "this" rectangle. + */ + bool intersects(const ossimIrect& rect) const; + + /*! + * Returns true if "this" rectangle is contained completely within + * the input rectangular "rect". + */ + bool completely_within(const ossimIrect& rect) const; + + /*! + * Returns the height of the rectangle. + */ + ossim_uint32 height() const + { + return static_cast<ossim_uint32>(ossimAbs(theLlCorner.y - + theUlCorner.y) + 1); + } + + /*! + * Returns the width of a rectangle. + */ + ossim_uint32 width() const + { + return static_cast<ossim_uint32>(ossimAbs(theLrCorner.x - + theLlCorner.x) + 1); + } + + ossimIrect clipToRect(const ossimIrect& rect)const; + + inline ossimIpt midPoint()const; + + void print(std::ostream& os) const; + + ossimIrect combine(const ossimIrect& rect)const; + + friend OSSIMDLLEXPORT std::ostream& operator<<(std::ostream& os, + const ossimIrect& rect); + + bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); +private: + + //*** + // Private data members representing the rectangle corners. + //*** + ossimIpt theUlCorner; + ossimIpt theUrCorner; + ossimIpt theLrCorner; + ossimIpt theLlCorner; + + ossimCoordSysOrientMode theOrientMode; +}; + +//******************************************************************* +// Inline Method: ossimIrect::operator=(ossimIrect) +//******************************************************************* +inline const ossimIrect& ossimIrect::operator=(const ossimIrect& rect) +{ + if (this != &rect) + { + theUlCorner = rect.ul(); + theUrCorner = rect.ur(); + theLrCorner = rect.lr(); + theLlCorner = rect.ll(); + theOrientMode = rect.theOrientMode; + + if(rect.hasNans()) + { + makeNan(); + } + } + + return *this; +} + +//******************************************************************* +// Inline Method: ossimIrect::operator!= +//******************************************************************* +inline bool ossimIrect::operator!=(const ossimIrect& rect) const +{ + return ( (theUlCorner != rect.ul()) || + (theUrCorner != rect.ur()) || + (theLrCorner != rect.lr()) || + (theLlCorner != rect.ll()) || + (theOrientMode != rect.theOrientMode)); +} + +//******************************************************************* +// Inline Method: ossimIrect::operator== +//******************************************************************* +inline bool ossimIrect::operator==(const ossimIrect& rect) const +{ + return ( (theUlCorner == rect.ul()) && + (theUrCorner == rect.ur()) && + (theLrCorner == rect.lr()) && + (theLlCorner == rect.ll()) && + (theOrientMode == rect.theOrientMode) ); +} + +//******************************************************************* +// Inline Method: ossimIrect::set_ul +//******************************************************************* +inline void ossimIrect::set_ul(const ossimIpt& pt) +{ + if(pt.hasNans()) + { + makeNan(); + } + else + { + theUlCorner = pt; + theUrCorner.y = pt.y; + theLlCorner.x = pt.x; + } +} + +//******************************************************************* +// Inline Method: ossimIrect::set_ur +//******************************************************************* +inline void ossimIrect::set_ur(const ossimIpt& pt) +{ + if(pt.hasNans()) + { + makeNan(); + } + else + { + theUrCorner = pt; + theUlCorner.y = pt.y; + theLrCorner.x = pt.x; + } +} + +//******************************************************************* +// Inline Method: ossimIrect::set_lr +//******************************************************************* +inline void ossimIrect::set_lr(const ossimIpt& pt) +{ + if(pt.hasNans()) + { + makeNan(); + } + else + { + theLrCorner = pt; + theUrCorner.x = pt.x; + theLlCorner.y = pt.y; + } +} + +//******************************************************************* +// Inline Method: ossimIrect::set_ll +//******************************************************************* +inline void ossimIrect::set_ll(const ossimIpt& pt) +{ + if(pt.hasNans()) + { + makeNan(); + } + else + { + theLlCorner = pt; + theUlCorner.x = pt.x; + theLrCorner.y = pt.y; + } +} + +//******************************************************************* +// Inline Method: ossimIrect::set_ulx +//******************************************************************* +inline void ossimIrect::set_ulx(ossim_int32 x) +{ + theUlCorner.x = x; + theLlCorner.x = x; +} + +//******************************************************************* +// Inline Method: ossimIrect::set_uly +//******************************************************************* +inline void ossimIrect::set_uly(ossim_int32 y) +{ + theUlCorner.y = y; + theUrCorner.y = y; +} + +//******************************************************************* +// Inline Method: ossimIrect::set_urx +//******************************************************************* +inline void ossimIrect::set_urx(ossim_int32 x) +{ + theUrCorner.x = x; + theLrCorner.x = x; +} + +//******************************************************************* +// Inline Method: ossimIrect::set_ury +//******************************************************************* +inline void ossimIrect::set_ury(ossim_int32 y) +{ + theUrCorner.y = y; + theUlCorner.y = y; +} + +//******************************************************************* +// Inline Method: ossimIrect::set_lrx +//******************************************************************* +inline void ossimIrect::set_lrx(ossim_int32 x) +{ + theLrCorner.x = x; + theUrCorner.x = x; +} + +//******************************************************************* +// Inline Method: ossimIrect::set_lry +//******************************************************************* +inline void ossimIrect::set_lry(ossim_int32 y) +{ + theLrCorner.y = y; + theLlCorner.y = y; +} + +//******************************************************************* +// Inline Method: ossimIrect::set_llx +//******************************************************************* +inline void ossimIrect::set_llx(ossim_int32 x) +{ + theLlCorner.x = x; + theUlCorner.x = x; +} + +//******************************************************************* +// Inline Method: ossimIrect::set_lly +//******************************************************************* +inline void ossimIrect::set_lly(ossim_int32 y) +{ + theLlCorner.y = y; + theLrCorner.y = y; +} + +//******************************************************************* +// Inline Method: ossimIrect::pointWithin +//******************************************************************* +inline bool ossimIrect::pointWithin(const ossimIpt& pt) const +{ + if(hasNans()) + { + return false; + } + if (theOrientMode == OSSIM_LEFT_HANDED) + return ((pt.x >= ul().x) && + (pt.x <= ur().x) && + (pt.y >= ul().y) && + (pt.y <= ll().y)); + else + return ((pt.x >= ul().x) && + (pt.x <= ur().x) && + (pt.y <= ul().y) && + (pt.y >= ll().y)); +} + +//******************************************************************* +// Inline Method: ossimIrect::midPoint +//******************************************************************* +inline ossimIpt ossimIrect::midPoint()const +{ + if(hasNans()) + { + return ossimIpt(OSSIM_INT_NAN, OSSIM_INT_NAN); + } + double x = (ul().x + ur().x + ll().x + lr().x) * 0.25; + double y = (ul().y + ur().y + ll().y + lr().y) * 0.25; + + return ossimIpt(static_cast<ossim_int32>(irint(x)), + static_cast<ossim_int32>(irint(y))); +} + +//******************************************************************* +// Inline Method: ossimIrect::combine +//******************************************************************* +inline ossimIrect ossimIrect::combine(const ossimIrect& rect)const +{ + if(rect.hasNans() || hasNans()) + { + ossimIrect result; + + result.makeNan(); + + return result; + } + if (theOrientMode != rect.theOrientMode) + return(*this); + + int ulx = ((ul().x <= rect.ul().x)?ul().x:rect.ul().x); + int uly = ((ul().y <= rect.ul().y)?ul().y:rect.ul().y); + int lrx = ((lr().x >= rect.lr().x)?lr().x:rect.lr().x); + int lry = ((lr().y >= rect.lr().y)?lr().y:rect.lr().y); + + return ossimIrect(ulx, uly, lrx, lry); +} + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimKeyword.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimKeyword.cpp new file mode 100644 index 0000000000..42520fcd32 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimKeyword.cpp @@ -0,0 +1,136 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class definition for Keyword.h +//******************************************************************* +// $Id: ossimKeyword.cpp,v 1.3 2005/10/17 18:37:16 gpotts Exp $ + +#include <base/data_types/ossimKeyword.h> + +ossimKeyword::ossimKeyword() + : + theKey(""), + theDesc(""), + theValue("") +{} + +ossimKeyword::ossimKeyword(const char* key, const char* description) + : + theKey(key), + theDesc(description), + theValue("") +{} + +ossimKeyword::ossimKeyword(const char* key, + const char* description, + const char* value) + : + theKey(key), + theDesc(description), + theValue(value) +{} + +ossimKeyword::ossimKeyword(const ossimKeyword& src) + : + theKey(src.key()), + theDesc(src.description()), + theValue(src.value()) +{} + +ossimKeyword::~ossimKeyword() +{} + +ossimKeyword::operator const char*() const +{ + return theKey.c_str(); +} + +const char* ossimKeyword::key() const +{ + return theKey.c_str(); +} + +const char* ossimKeyword::description() const +{ + return theDesc.c_str(); +} + +const char* ossimKeyword::value() const +{ + return theValue.c_str(); +} + +ossimString ossimKeyword::keyString() const +{ + return theKey; +} + +ossimString ossimKeyword::descriptionString() const +{ + return theDesc; +} + +ossimString ossimKeyword::valueString() const +{ + return theValue; +} + +void ossimKeyword::setValue(const char* val) +{ + theValue = val; +} + +void ossimKeyword::setValue(const ossimString& val) +{ + theValue = val; +} + +void ossimKeyword::setDescription(const char* desc) +{ + theDesc = desc; +} + +void ossimKeyword::setDescription(const ossimString& desc) +{ + theDesc = desc; +} + +const ossimKeyword& ossimKeyword::operator=(const ossimKeyword& kw) +{ + if (this != &kw) + { + theKey = kw.key(); + theDesc = kw.description(); + theValue = kw.value(); + } + + return *this; +} + +std::ostream& operator<<(std::ostream& os, const ossimKeyword& kw) +{ + os << "\n key = " << kw.key() + << "\n desc = " << kw.description() + << "\n value = " << kw.value() + << std::endl; + return os; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimKeyword.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimKeyword.h new file mode 100644 index 0000000000..1de3984add --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimKeyword.h @@ -0,0 +1,64 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Ken Melero +// Description: This class defines a keyword. +// NOTE: The keywordlist class cleans up all allocated +// memory from instantiating a keyword. +// +//******************************************************************** +// $Id: ossimKeyword.h,v 1.5 2005/10/17 18:37:16 gpotts Exp $ +#ifndef ossimKeyword_HEADER +#define ossimKeyword_HEADER + +#include <base/data_types/ossimString.h> + +class OSSIMDLLEXPORT ossimKeyword +{ +public: + ossimKeyword(); + ossimKeyword(const char* key, const char* description); + ossimKeyword(const char* key, const char* description, const char* value); + ossimKeyword(const ossimKeyword& src); + ~ossimKeyword(); + + const ossimKeyword& operator=(const ossimKeyword& kw); + operator const char*() const; + + const char* key() const; + const char* description() const; + const char* value() const; + ossimString keyString() const; + ossimString descriptionString() const; + ossimString valueString() const; + + void setValue(const char* val); + void setValue(const ossimString& val); + void setDescription(const char* desc); + void setDescription(const ossimString& desc); + + + friend OSSIM_DLL std::ostream& operator<<(std::ostream& os, const ossimKeyword& kw); + +private: + ossimString theKey; + ossimString theDesc; + ossimString theValue; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimKeywordlist.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimKeywordlist.cpp new file mode 100644 index 0000000000..ef1f841d02 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimKeywordlist.cpp @@ -0,0 +1,1244 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Description: This class provides capabilities for keywordlists. +// +//******************************************************************** +// $Id: ossimKeywordlist.cpp,v 1.62 2005/10/17 19:16:33 gpotts Exp $ +#include <algorithm> +#include <fstream> +#include <iostream> + +#include <base/data_types/ossimRegExp.h> +#include <base/data_types/ossimFilename.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/context/ossimNotifyContext.h> +#include <base/common/ossimTrace.h> + +static ossimTrace traceDebug("ossimKeywordlist:debug"); +static const ossim_int32 MAX_LINE_LENGTH = 256; +static const char NULL_KEY_NOTICE[] + = "ossimKeywordlist Notice: Null key passed to method."; + + +#ifdef OSSIM_ID_ENABLED +static const bool TRACE = false; +static const char OSSIM_ID[] = "$Id: ossimKeywordlist.cpp,v 1.62 2005/10/17 19:16:33 gpotts Exp $"; +#endif + +ossimKeywordlist::ossimKeywordlist(char delimiter) + : + theMap(), + theDelimiter(delimiter) +{ +#ifdef OSSIM_ID_ENABLED + if (TRACE) ossimNotify(ossimNotifyLevel_DEBUG) << OSSIM_ID << endl; +#endif +} + +ossimKeywordlist::ossimKeywordlist(const char* file, + char delimiter, + bool ignoreBinaryChars) + : + theMap(), + theDelimiter(delimiter) +{ + ossimFilename in_file(file); + + if (!parseFile(in_file, ignoreBinaryChars)) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + } +} + +ossimKeywordlist::ossimKeywordlist(const ossimFilename& file, + char delimiter, + bool ignoreBinaryChars) + : + theMap(), + theDelimiter(delimiter) + +{ + if (!parseFile(file, ignoreBinaryChars)) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + } +} + +ossimKeywordlist::~ossimKeywordlist() +{ + theMap.clear(); +} + +bool ossimKeywordlist::addFile(const char* file) +{ + ossimFilename in_file(file); + + return parseFile(in_file); +} + +bool ossimKeywordlist::addFile(const ossimFilename& file) +{ + return parseFile(file); +} + +void ossimKeywordlist::addList(const ossimKeywordlist &src, bool overwrite) +{ + KeywordMap::const_iterator i = src.theMap.begin(); + + while (i != src.theMap.end()) + { + add( (*i).first, (*i).second, overwrite ); + i++; + } +} + +void ossimKeywordlist::add(const ossimKeywordlist& kwl, + const char* prefix, + bool stripPrefix) +{ + map<ossimString, ossimString>::const_iterator iter = kwl.theMap.begin(); + + ossimRegExp regExp; + + regExp.compile(("^("+ossimString(prefix)+")").c_str()); + + while(iter != kwl.theMap.end()) + { + ossimString newKey; + + if(regExp.find( (*iter).first.c_str())) + { + newKey = (*iter).first; + if(stripPrefix) + { + newKey = newKey.substitute(prefix, + ""); + + } + + add(newKey, + (*iter).second, + true); + } + ++iter; + } + +} + +void ossimKeywordlist::add(const char* prefix, + const ossimKeywordlist& kwl, + bool overwrite) +{ + map<ossimString, ossimString>::const_iterator iter = kwl.theMap.begin(); + + while(iter != kwl.theMap.end()) + { + ossimString valueToAdd = (*iter).second; + ossimString newKey = (*iter).first; + + add(prefix, + newKey, + valueToAdd, + overwrite); + ++iter; + } +} + +void ossimKeywordlist::add(const char* key, + const char* value, + bool overwrite) +{ + if (key) + { + ossimString k = key; + + ossimString v; + if (value) v = value; + + KeywordMap::iterator i = getMapEntry(k); + + if (i == theMap.end()) + { + theMap.insert(std::make_pair(k, v)); + } + else if (overwrite) + { + (*i).second = v; + } + } +} + +void ossimKeywordlist::add(const char* prefix, + const char* key, + const char* value, + bool overwrite) +{ + if (key) + { + ossimString k; + if (prefix) k = prefix; + k += key; + + ossimString v; + if (value) v = value; + + KeywordMap::iterator i = getMapEntry(k); + + if(i == theMap.end()) + { + theMap.insert(std::make_pair(k, v)); + } + else if(overwrite) + { + (*i).second = v; + } + } +} + +void ossimKeywordlist::add(const char* key, + char value, + bool overwrite) +{ + if (key) + { + ossimString k = key; + + char tmp[2]; + tmp[0] = value; + tmp[1] = '\0'; + ossimString v = tmp; + + KeywordMap::iterator i = getMapEntry(k); + + if (i == theMap.end()) + { + theMap.insert(std::make_pair(k, v)); + } + else if (overwrite) + { + (*i).second = v; + } + } +} + +void ossimKeywordlist::add(const char* prefix, + const char* key, + char value, + bool overwrite) +{ + if (key) + { + ossimString k; + if (prefix) k = prefix; + k += key; + + char tmp[2]; + tmp[0] = value; + tmp[1] = '\0'; + ossimString v = tmp; + + KeywordMap::iterator i = getMapEntry(k); + + if(i == theMap.end()) + { + theMap.insert(std::make_pair(k, v)); + } + else if(overwrite) + { + (*i).second = v; + } + } +} + +void ossimKeywordlist::add(const char* key, + ossim_int16 value, + bool overwrite) +{ + if (key) + { + ossimString k = key; + + ossimString v = ossimString::toString(value); + + KeywordMap::iterator i = getMapEntry(k); + + if(i == theMap.end()) + { + theMap.insert(std::make_pair(k, v)); + } + else if (overwrite) + { + (*i).second = v; + } + } +} + +void ossimKeywordlist::add(const char* prefix, + const char* key, + ossim_int16 value, + bool overwrite) +{ + if (key) + { + ossimString k; + if (prefix) k = prefix; + k += key; + + ossimString v = ossimString::toString(value); + + KeywordMap::iterator i = getMapEntry(k); + + if(i == theMap.end()) + { + theMap.insert(std::make_pair(k, v)); + } + else if (overwrite) + { + (*i).second = v; + } + } +} + +void ossimKeywordlist::add(const char* key, + ossim_uint16 value, + bool overwrite) +{ + if (key) + { + ossimString k = key; + + ossimString v = ossimString::toString(value); + + KeywordMap::iterator i = getMapEntry(k); + + if(i == theMap.end()) + { + theMap.insert(std::make_pair(k, v)); + } + else if (overwrite) + { + (*i).second = v; + } + } +} + +void ossimKeywordlist::add(const char* prefix, + const char* key, + ossim_uint16 value, + bool overwrite) +{ + if (key) + { + ossimString k; + if (prefix) k = prefix; + k += key; + + ossimString v = ossimString::toString(value); + + KeywordMap::iterator i = getMapEntry(k); + + if(i == theMap.end()) + { + theMap.insert(std::make_pair(k, v)); + } + else if (overwrite) + { + (*i).second = v; + } + } +} + +void ossimKeywordlist::add(const char* key, + ossim_int32 value, + bool overwrite) +{ + if (key) + { + ossimString k = key; + + ossimString v = ossimString::toString(value); + + KeywordMap::iterator i = getMapEntry(k); + + if(i == theMap.end()) + { + theMap.insert(std::make_pair(k, v)); + } + else if (overwrite) + { + (*i).second = v; + } + } +} + +void ossimKeywordlist::add(const char* prefix, + const char* key, + ossim_int32 value, + bool overwrite) +{ + if (key) + { + ossimString k; + if (prefix) k = prefix; + k += key; + + ossimString v = ossimString::toString(value); + + KeywordMap::iterator i = getMapEntry(k); + + if(i == theMap.end()) + { + theMap.insert(std::make_pair(k, v)); + } + else if (overwrite) + { + (*i).second = v; + } + } +} + +void ossimKeywordlist::add(const char* key, + ossim_uint32 value, + bool overwrite) +{ + if (key) + { + ossimString k = key; + + ossimString v = ossimString::toString(value); + + KeywordMap::iterator i = getMapEntry(k); + + if(i == theMap.end()) + { + theMap.insert(std::make_pair(k, v)); + } + else if (overwrite) + { + (*i).second = v; + } + } +} + +void ossimKeywordlist::add(const char* prefix, + const char* key, + ossim_uint32 value, + bool overwrite) +{ + if (key) + { + ossimString k; + if (prefix) k = prefix; + k += key; + + ossimString v = ossimString::toString(value); + + KeywordMap::iterator i = getMapEntry(k); + + if(i == theMap.end()) + { + theMap.insert(std::make_pair(k, v)); + } + else if (overwrite) + { + (*i).second = v; + } + } +} + +void ossimKeywordlist::add(const char* key, + long value, + bool overwrite) +{ + if (key) + { + ossimString k = key; + + ossimString v = ossimString::toString(value); + + KeywordMap::iterator i = getMapEntry(k); + + if(i == theMap.end()) + { + theMap.insert(std::make_pair(k, v)); + } + else if (overwrite) + { + (*i).second = v; + } + } +} + +void ossimKeywordlist::add(const char* prefix, + const char* key, + long value, + bool overwrite) +{ + if (key) + { + ossimString k; + if (prefix) k = prefix; + k += key; + + ossimString v = ossimString::toString(value); + + KeywordMap::iterator i = getMapEntry(k); + + if(i == theMap.end()) + { + theMap.insert(std::make_pair(k, v)); + } + else if (overwrite) + { + (*i).second = v; + } + } +} + +void ossimKeywordlist::add(const char* key, + unsigned long value, + bool overwrite) +{ + if (key) + { + ossimString k = key; + + ossimString v = ossimString::toString(value); + + KeywordMap::iterator i = getMapEntry(k); + + if(i == theMap.end()) + { + theMap.insert(std::make_pair(k, v)); + } + else if (overwrite) + { + (*i).second = v; + } + } +} + +void ossimKeywordlist::add(const char* prefix, + const char* key, + unsigned long value, + bool overwrite) +{ + if (key) + { + ossimString k; + if (prefix) k = prefix; + k += key; + + ossimString v = ossimString::toString(value); + + KeywordMap::iterator i = getMapEntry(k); + + if(i == theMap.end()) + { + theMap.insert(std::make_pair(k, v)); + } + else if (overwrite) + { + (*i).second = v; + } + } +} + +void ossimKeywordlist::add(const char* key, + ossim_float32 value, + bool overwrite, + int precision, + bool trimZeroFlag, + bool scientific) +{ + if (key) + { + ossimString k = key; + + ossimString v = ossimString::toString(value, + precision, + trimZeroFlag, + scientific); + + KeywordMap::iterator i = getMapEntry(k); + + if(i == theMap.end()) + { + theMap.insert(std::make_pair(k, v)); + } + else if (overwrite) + { + (*i).second = v; + } + } +} + +void ossimKeywordlist::add(const char* prefix, + const char* key, + ossim_float32 value, + bool overwrite, + int precision, + bool trimZeroFlag, + bool scientific) +{ + if (key) + { + ossimString k; + if (prefix) k = prefix; + k += key; + + ossimString v = ossimString::toString(value, + precision, + trimZeroFlag, + scientific); + + KeywordMap::iterator i = getMapEntry(k); + + if(i == theMap.end()) + { + theMap.insert(std::make_pair(k, v)); + } + else if (overwrite) + { + (*i).second = v; + } + } +} + +void ossimKeywordlist::add(const char* key, + ossim_float64 value, + bool overwrite, + int precision, + bool trimZeroFlag, + bool scientific) +{ + if (key) + { + ossimString k = key; + + ossimString v = ossimString::toString(value, + precision, + trimZeroFlag, + scientific); + + KeywordMap::iterator i = getMapEntry(k); + + if(i == theMap.end()) + { + theMap.insert(std::make_pair(k, v)); + } + else if (overwrite) + { + (*i).second = v; + } + } +} + +void ossimKeywordlist::add(const char* prefix, + const char* key, + ossim_float64 value, + bool overwrite, + int precision, + bool trimZeroFlag, + bool scientific) +{ + if (key) + { + ossimString k; + if (prefix) k = prefix; + k += key; + + ossimString v = ossimString::toString(value, + precision, + trimZeroFlag, + scientific); + + KeywordMap::iterator i = getMapEntry(k); + + if(i == theMap.end()) + { + theMap.insert(std::make_pair(k, v)); + } + else if (overwrite) + { + (*i).second = v; + } + } +} + +bool ossimKeywordlist::write(const char* file) const +{ + ofstream filename(file); + if (!filename) + { + ossimNotify(ossimNotifyLevel_WARN) + <<"ossimKeywordlist::write, Error opening file: " + << file << std::endl; + return false; + } + + writeToStream(filename); + + filename.close(); + + return true; +} + +ossimString ossimKeywordlist::toString()const +{ + KeywordMap::const_iterator i; + ossimString result; + + for(i = theMap.begin(); i != theMap.end(); i++) + { + result += (*i).first; + result += delimiter_str().c_str(); + result += " "; + result += (*i).second; + result += '\n'; + } + + return result; +} + +void ossimKeywordlist::toString(ossimString& result)const +{ + KeywordMap::const_iterator i; + + for(i = theMap.begin(); i != theMap.end(); i++) + { + result += (*i).first; + result += delimiter_str().c_str(); + result += " "; + result += (*i).second; + result += '\n'; + } +} + +void ossimKeywordlist::writeToStream(ostream& out) const +{ + KeywordMap::const_iterator i; + + for(i = theMap.begin(); i != theMap.end(); ++i) + { + out << (*i).first << delimiter_str().c_str() << " " + << (*i).second << endl; + } +} + + +const char* ossimKeywordlist::find(const char* key) const +{ + const char* result = NULL; + + if (key) + { + ossimString k = key; + + KeywordMap::const_iterator i = theMap.find(k.c_str()); + + if (i != theMap.end()) + { + result = (*i).second.c_str(); + } + } + + return result; +} + +const char* ossimKeywordlist::find(const char* prefix, + const char* key) const +{ + const char* result = NULL; + + if (key) + { + ossimString k; + if (prefix) k = prefix; + k += key; + KeywordMap::const_iterator i = theMap.find(k.c_str()); + if (i != theMap.end()) + { + result = (*i).second.c_str(); + } + } + + return result; +} + + +void ossimKeywordlist::remove(const char * key) +{ + ossimString k = key?key:""; + + KeywordMap::iterator i = theMap.find(k); + + if(i != theMap.end()) + { + theMap.erase(i); + } +} + +void ossimKeywordlist::remove(const char* prefix, const char * key) +{ + if (key) + { + ossimString k; + if (prefix) k = prefix; + k += key; + + KeywordMap::iterator i = theMap.find(k); + + if(i != theMap.end()) + { + theMap.erase(i); + } + } +} + +ossim_uint32 ossimKeywordlist::numberOf(const char* str) const +{ + ossim_uint32 count = 0; + + if (str) + { + KeywordMap::const_iterator i = theMap.begin(); + + while (i != theMap.end()) + { + if ( (*i).first.contains(str) ) + { + ++count; + } + ++i; + } + } + + return count; +} + +ossim_uint32 ossimKeywordlist::numberOf(const char* prefix, + const char* key) const +{ + if (!prefix && key) // Must have key, sometimes no prefix. + { + return numberOf(key); + } + + ossim_uint32 count = 0; + + if (prefix && key) + { + KeywordMap::const_iterator i = theMap.begin(); + + while (i != theMap.end()) + { + if ( (*i).first.contains(prefix) && (*i).first.contains(key)) + { + ++count; + } + ++i; + } + } + + return count; +} + +void ossimKeywordlist::clear() +{ + theMap.clear(); +} + +ossimKeywordlist::KeywordMap::iterator +ossimKeywordlist::getMapEntry(const char* key) +{ + if (key) + { + ossimString k = key; + return theMap.find(k); + } + else + { + return theMap.end(); + } +} + +ossimKeywordlist::KeywordMap::iterator +ossimKeywordlist::getMapEntry(const ossimString& key) +{ + return theMap.find(key); +} + + +//******************************************************************* +// Private Method: +//******************************************************************* +bool ossimKeywordlist::parseFile(const ossimFilename& file, + bool ignoreBinaryChars) +{ + std::ifstream is; + is.open(file.c_str(), ios::in | ios::binary); + + if (!is) + { + if(traceDebug()) + { + // report all errors that aren't existance problems. + // we want to know about things like permissions, too many open files, etc. + ossimNotify(ossimNotifyLevel_DEBUG) << "Error opening file: " << file.c_str() + << std::endl; + } + return false; + } + + bool result = parseStream(is, ignoreBinaryChars); + + is.close(); + + return result; +} + +bool ossimKeywordlist::parseStream(istream &is, + bool ignoreBinaryChars) +{ + ossimString line; + + while(!is.eof() && is.good()) + { + line = ""; + // get a line and parse it + char c = is.get(); + while((c != '\n') &&!is.eof()&&!is.bad()) + { + if (c >= 0x20) + { + if( (c > 0x7e) ) + { + return false; + } + else if (c <= 0x7e) + { + + line += c; + } + else + { + line += c; + } + } + + c = is.get(); + } + + if(line != "") + { + ossimString key; + ossimString value; + + // parse out key and value + ossim_uint32 pos = line.find(theDelimiter); + key = line.substr(0, pos); + key = key.trim(); + value = line.substr(pos + 1); + value = value.trim(); + + // if it's not a comment then add it + if(key.begin()[0] != (char)'/' || + key.begin()[1] != (char)'/') + { + if(pos != line.npos) + { + theMap.insert(std::make_pair(key, value)); + } + } + } + } + + return true; +} + +vector<ossimString> ossimKeywordlist::findAllKeysThatContains(const ossimString &searchString)const +{ + KeywordMap::const_iterator i; + vector<ossimString> result; + + for(i = theMap.begin(); i != theMap.end(); ++i) + { + if((*i).first.contains(searchString)) + { + result.push_back((*i).first); + } + } + + return result; +} + +vector<ossimString> ossimKeywordlist::findAllKeysThatMatch(const ossimString ®ularExpression)const +{ + KeywordMap::const_iterator i; + vector<ossimString> result; + ossimRegExp regExp; + + regExp.compile(regularExpression.c_str()); + + for(i = theMap.begin(); i != theMap.end(); ++i) + { + if(regExp.find( (*i).first.c_str())) + { + result.push_back((*i).first); + } + } + + return result; +} + +void ossimKeywordlist::extractKeysThatMatch(ossimKeywordlist& kwl, + const ossimString ®ularExpression)const +{ + KeywordMap::const_iterator i; + vector<ossimString> result; + ossimRegExp regExp; + + regExp.compile(regularExpression.c_str()); + + for(i = theMap.begin(); i != theMap.end(); ++i) + { + if(regExp.find( (*i).first.c_str())) + { + kwl.add((*i).first, (*i).second); + } + } +} + +void ossimKeywordlist::removeKeysThatMatch(const ossimString ®ularExpression) +{ + KeywordMap::const_iterator i; + vector<ossimString> result; + ossimRegExp regExp; + + regExp.compile(regularExpression.c_str()); + + for(i = theMap.begin(); i != theMap.end(); ++i) + { + if(regExp.find( (*i).first.c_str())) + { + result.push_back((*i).first); + } + } + for(ossim_uint32 i2 = 0; i2 < result.size(); ++i2) + { + remove(result[i2]); + } +} + +vector<ossimString> ossimKeywordlist::getSubstringKeyList(const ossimString& regularExpression)const +{ + KeywordMap::const_iterator i; + vector<ossimString> result; + ossimRegExp regExp; + + regExp.compile(regularExpression.c_str()); + + for(i = theMap.begin(); i != theMap.end(); ++i) + { + if(regExp.find( (*i).first.c_str())) + { + ossimString value = ossimString((*i).first.begin()+regExp.start(), + (*i).first.begin()+regExp.start()+regExp.end()); + + if(std::find(result.begin(), result.end(), value) == result.end()) + { + result.push_back(value); + } + } + } + + return result; +} + +ossim_uint32 ossimKeywordlist::getNumberOfSubstringKeys(const ossimString& regularExpression)const +{ + KeywordMap::const_iterator i; + list<ossimString> currentList; + ossim_uint32 result = 0; + ossimRegExp regExp; + + regExp.compile(regularExpression.c_str()); + + for(i = theMap.begin(); i != theMap.end(); ++i) + { + if(regExp.find( (*i).first.c_str())) + { + ossimString value = ossimString((*i).first.begin()+regExp.start(), + (*i).first.begin()+regExp.start()+regExp.end()); + + // make sure we have not already marked it as + // found + if(std::find(currentList.begin(), + currentList.end(), + value) == currentList.end()) + { + currentList.push_back(value); + ++result; + } + } + } + + return result; +} + +void ossimKeywordlist::addPrefixToAll(const ossimString& prefix) +{ + ossimKeywordlist tempKwl = *this; + + clear(); + + KeywordMap::const_iterator values = tempKwl.theMap.begin(); + + while(values != tempKwl.theMap.end()) + { + ossimString newKey = prefix + (*values).first; + add(newKey, + (*values).second, + true); + ++values; + } +} + +void ossimKeywordlist::stripPrefixFromAll(const ossimString& regularExpression) +{ + ossimKeywordlist tempKwl = *this; + + clear(); + + KeywordMap::const_iterator values = tempKwl.theMap.begin(); + ossimRegExp regExp; + + regExp.compile(regularExpression.c_str()); + + while(values != tempKwl.theMap.end()) + { + ossimString newKey = (*values).first; + if(regExp.find( (*values).first.c_str())) + { + newKey.erase(newKey.begin()+regExp.start(), + newKey.begin()+regExp.start()+regExp.end()); + + add(newKey.c_str(), + (*values).second, + true); + } + else + { + add(newKey.c_str(), + (*values).second, + true); + } + ++values; + } +} + + +ossim_uint32 ossimKeywordlist::getSize()const +{ + return theMap.size(); +} + +const ossimKeywordlist::KeywordMap& ossimKeywordlist::getMap()const +{ + return theMap; +} + +ossimKeywordlist::KeywordMap& ossimKeywordlist::getMap() +{ + return theMap; +} + +ossimString ossimKeywordlist::delimiter_str() const +{ + char tmp[2]; + tmp[0] = theDelimiter; + tmp[1] = '\0'; + return ossimString(tmp); +} + +//******************************************************************* +// Public Method: +//******************************************************************* +ostream& ossimKeywordlist::print(ostream& os) const +{ + KeywordMap::const_iterator i; + + for(i = theMap.begin(); i != theMap.end(); ++i) + { + os << (*i).first << delimiter_str().c_str() << " " + << (*i).second << endl; + } + return os; +} + +//******************************************************************* +// friend function: +//******************************************************************* +OSSIMDLLEXPORT ostream& operator<<(ostream& os, const ossimKeywordlist& kwl) +{ + kwl.print(os); + + return os; +} + + +bool ossimKeywordlist::operator ==(ossimKeywordlist& kwl)const +{ + if(this==&kwl) return true; + map<ossimString, ossimString>::const_iterator iter = theMap.begin(); + + while(iter != theMap.end()) + { + const char* value = kwl.find((*iter).first); + + if(ossimString(value) != (*iter).second) + { + return false; + } + ++iter; + } + + return true; +} + +void ossimKeywordlist::downcaseKeywords() +{ + KeywordMap tempMap; + KeywordMap::iterator iter = theMap.begin(); + + while(iter != theMap.end()) + { + tempMap.insert(make_pair(ossimString::downcase(iter->first), + iter->second)); + + ++iter; + } + theMap = tempMap; +} + +void ossimKeywordlist::upcaseKeywords() +{ + KeywordMap tempMap; + KeywordMap::iterator iter = theMap.begin(); + + while(iter != theMap.end()) + { + tempMap.insert(make_pair(ossimString::upcase(iter->first), + iter->second)); + + ++iter; + } + theMap = tempMap; +} + diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimKeywordlist.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimKeywordlist.h new file mode 100644 index 0000000000..cd71b50afb --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimKeywordlist.h @@ -0,0 +1,387 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Ken Melero +// +// Description: This class provides capabilities for keywordlists. +// +//******************************************************************** +// $Id: ossimKeywordlist.h,v 1.36 2005/06/06 16:56:05 gpotts Exp $ + +#ifndef ossimKeywordlist_HEADER +#define ossimKeywordlist_HEADER + +#include <map> +#include <list> +#include <iostream> +using namespace std; + +#include <base/common/ossimErrorStatusInterface.h> +#include <base/common/ossimConstants.h> +#include <base/common/ossimErrorCodes.h> +#include <base/data_types/ossimString.h> + +static const char DEFAULT_DELIMITER = ':'; + +class OSSIMDLLEXPORT ossimFilename; + +class OSSIMDLLEXPORT ossimKeywordlist : public ossimErrorStatusInterface +{ +public: + + typedef map<ossimString, ossimString> KeywordMap; + + ossimKeywordlist(char delimiter = DEFAULT_DELIMITER); + + ossimKeywordlist(const char* file, + char delimiter = DEFAULT_DELIMITER, + bool ignoreBinaryChars = false); + + ossimKeywordlist(const ossimFilename& fileName, + char delimiter = DEFAULT_DELIMITER, + bool ignoreBinaryChars = false); + + ~ossimKeywordlist(); + + /*! + * Reads file and adds keywords to the KeywordMap. + * Returns true if file was parsed, false on error. + */ + bool addFile(const char* file); + + /*! + * Reads file and adds keywords to the KeywordMap. + * Returns true if file was parsed, false on error. + */ + bool addFile(const ossimFilename& file); + + /*! + * Method to change default delimiter. Handy when parsing + * files similar to a ossimKeywordlist. (DEFAULT = ':') + */ + void change_delimiter(char del) { theDelimiter = del; } + + ossimString delimiter_str() const; + + void add(const char* prefix, + const ossimKeywordlist& kwl, + bool overwrite=true); + + + /*! + * Allows you to extract out a sub keywordlist from another + * you can also collapse the hieracrchy by setting + * strip prefix to true. + */ + void add(const ossimKeywordlist& kwl, + const char* prefix=0, + bool stripPrefix=true); + + // Methods to add keywords to list. + void add(const char* key, + const char* value, + bool overwrite = true); + + void add(const char* prefix, + const char* key, + const char* value, + bool overwrite = true); + + void add(const char* key, + char value, + bool overwrite = true); + + void add(const char* prefix, + const char* key, + char value, + bool overwrite = true); + + void add(const char* key, + ossim_int16 value, + bool overwrite = true); + + void add(const char* prefix, + const char* key, + ossim_int16 value, + bool overwrite = true); + + void add(const char* key, + ossim_uint16 value, + bool overwrite = true); + + void add(const char* prefix, + const char* key, + ossim_uint16 value, + bool overwrite = true); + + void add(const char* key, + ossim_int32 value, + bool overwrite = true); + + void add(const char* prefix, + const char* key, + ossim_int32 value, + bool overwrite = true); + + void add(const char* key, + ossim_uint32 value, + bool overwrite = true); + + void add(const char* prefix, + const char* key, + ossim_uint32 value, + bool overwrite = true); + + void add(const char* key, + long value, + bool overwrite = true); + + void add(const char* prefix, + const char* key, + long value, + bool overwrite = true); + + void add(const char* key, + unsigned long value, + bool overwrite = true); + + void add(const char* prefix, + const char* key, + unsigned long value, + bool overwrite = true); + + /** + * @param key Key for key-value pair. + * + * @param value Value to pair with key. Note this will be stored as a + * string. + * + * @param precision Decimal point precision of the output. (default = 8) + * + * @param trimZeroFlag If true trailing '0's and any trailing '.' will + * be trimmed from the converted string. (default = false) + * + * @param scientific If true output will be in scientific notation else + * fixed is used. (default = false) + */ + void add(const char* key, + ossim_float32 value, + bool overwrite = true, + int precision = 8, + bool trimZeroFlag = false, + bool scientific = false); + + /** + * @param key Key for key-value pair. + * + * @param value Value to pair with key. Note this will be stored as a + * string. + * + * @param precision Decimal point precision of the output. (default = 8) + * + * @param trimZeroFlag If true trailing '0's and any trailing '.' will + * be trimmed from the converted string. (default = false) + * + * @param scientific If true output will be in scientific notation else + * fixed is used. (default = false) + */ + void add(const char* prefix, + const char* key, + ossim_float32 value, + bool overwrite = true, + int precision = 8, + bool trimZeroFlag = false, + bool scientific = false); + + /** + * @param key Key for key-value pair. + * + * @param value Value to pair with key. Note this will be stored as a + * string. + * + * @param precision Decimal point precision of the output. (default = 15) + * + * @param trimZeroFlag If true trailing '0's and any trailing '.' will + * be trimmed from the converted string. (default = false) + * + * @param scientific If true output will be in scientific notation else + * fixed is used. (default = false) + */ + void add(const char* key, + ossim_float64 value, + bool overwrite = true, + int precision = 15, + bool trimZeroFlag = false, + bool scientific = false); + + /** + * @param key Key for key-value pair. + * + * @param value Value to pair with key. Note this will be stored as a + * string. + * + * @param precision Decimal point precision of the output. (default = 15) + * + * @param trimZeroFlag If true trailing '0's and any trailing '.' will + * be trimmed from the converted string. (default = false) + * + * @param scientific If true output will be in scientific notation else + * fixed is used. (default = false) + */ + void add(const char* prefix, + const char* key, + ossim_float64 value, + bool overwrite = true, + int precision = 15, + bool trimZeroFlag = false, + bool scientific = false); + + /*! + * find methods + * Searches the map for key(/prefix) and returns the resulting value + * or a null string if the key was not found. + */ + const char* find(const char* key) const; + const char* find(const char* prefix, + const char* key) const; + + void remove(const char * key); + void remove(const char* prefix, const char * key); + + /*! + * Searches the map for the number of keys containing the string. + */ + ossim_uint32 numberOf(const char* str) const; + + /*! + * Searches the map for the number of keys containing the prefix + * and the string. + * + * Given the keyword list contains: + * + * source1.type: foo + * source2.type: you + * + * This: + * + * int number_of_sources = numberOf("source", "type"); + * + * number_of_sources equals 2 + */ + ossim_uint32 numberOf(const char* prefix, const char* key) const; + + /** + * Methods to dump the ossimKeywordlist to a file on disk. + * @return true on success, false on error. + */ + bool write(const char* file) const; + + ossimString toString()const; + void toString(ossimString& result)const; + + void writeToStream(ostream &out)const; + + ostream& print(ostream& os) const; + OSSIMDLLEXPORT friend ostream& operator<<(ostream& os, const ossimKeywordlist& kwl); + bool operator ==(ossimKeywordlist& kwl)const; + + /*! + * Clear all contents out of the ossimKeywordlist. + */ + + void clear(); + + /*! + * Add contents of another keyword list to this one. + * + * @param src the keyword list to copy items from. + * @param overwrite true if keys existing in this and src should have + * their value overwritten by the src value, otherwise false to preserve + * the original value. Defaults to true. + */ + + void addList( const ossimKeywordlist &src, bool overwrite = true ); + + bool parseStream(istream& is, + bool ignoreBinaryChars = false); + + /*! + * Will return a list of keys that contain the string passed in. + * Later we will need to allow a user to specify regular expresion + * searches. + */ + vector<ossimString> findAllKeysThatContains(const ossimString &searchString)const; + + vector<ossimString> findAllKeysThatMatch(const ossimString ®ularExpression)const; + + void extractKeysThatMatch(ossimKeywordlist& kwl, + const ossimString ®ularExpression)const; + + void removeKeysThatMatch(const ossimString ®ularExpression); + /*! + * Will return only the portion of the key that + * matches the regular expression. + * + * example: + * + * source1.source1.a: + * source1.source2.a: + * source1.source3.a: + * source1.source4.a: + * source1.source10.a: + * + * kwl.getSubstringKeyList("source1.source[0-9]*\\."); + * + * will return: + * + * source1.source1. + * source1.source2. + * source1.source3. + * source1.source4. + * source1.source10. + * + */ + vector<ossimString> getSubstringKeyList(const ossimString& regularExpression)const; + + ossim_uint32 getNumberOfSubstringKeys(const ossimString& regularExpression)const; + + void addPrefixToAll(const ossimString& prefix); + void stripPrefixFromAll(const ossimString& regularExpression); + + /*! + * Returns the number of elements. + */ + ossim_uint32 getSize()const; + + const ossimKeywordlist::KeywordMap& getMap()const; + ossimKeywordlist::KeywordMap& getMap(); + void downcaseKeywords(); + void upcaseKeywords(); +private: + + /*! + * Method to parse files to initialize the list. Method will error on + * binary characters if "ignoreBinaryChars = false". This is used by + * ImageHandler factories that can be passed a binary file inadvertently + * by a user. The "ignoreBinaryChars" flag should be set to true if + * a text file contains mixed ascii/binary values. + * Returns true if file was parsed, false on error. + */ + bool parseFile(const ossimFilename& file, + bool ignoreBinaryChars = false); + + + // Method to see if keyword exists in list. + KeywordMap::iterator getMapEntry(const ossimString& key); + KeywordMap::iterator getMapEntry(const char* key); + + KeywordMap theMap; + char theDelimiter; +}; + +#endif /* #ifndef ossimKeywordlist_HEADER */ + diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimLine.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimLine.cpp new file mode 100644 index 0000000000..d466e5a7c3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimLine.cpp @@ -0,0 +1,176 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +//******************************************************************* +// $Id: ossimLine.cpp,v 1.14 2004/05/19 14:11:21 dburken Exp $ +#include "ossimLine.h" +#include "ossimDrect.h" +#include <iostream> +#include <algorithm> + +using namespace std; + +std::ostream& operator <<(std::ostream& out, const ossimLine& rhs) +{ + return out << "line: " << rhs.theP1 << "," << rhs.theP2 << endl; +} + +ossimDpt ossimLine::intersectInfinite(const ossimLine& line)const +{ + ossimDpt result; + ossimDpt p3 = line.theP1; + ossimDpt p4 = line.theP2; + + double numerator = ((p4.x-p3.x)*(theP1.y-p3.y) - (p4.y-p3.y)*(theP1.x-p3.x)); + double denominator = ((p4.y-p3.y)*(theP2.x-theP1.x) - (p4.x-p3.x)*(theP2.y-theP1.y)); + result.makeNan(); + // as long as the lines are not parallel + if(fabs(denominator) > FLT_EPSILON) + { + double ua = numerator/ denominator; + result = ossimDpt(theP1.x + ua*(theP2.x-theP1.x), + theP1.y + ua*(theP2.y-theP1.y)); + } + + return result; +} + +ossimDpt ossimLine::intersectSegment(const ossimLine& line)const +{ + ossimDpt result; + ossimDpt p3 = line.theP1; + ossimDpt p4 = line.theP2; + + double numerator = ((p4.x-p3.x)*(theP1.y-p3.y) - (p4.y-p3.y)*(theP1.x-p3.x)); + double denominator = ((p4.y-p3.y)*(theP2.x-theP1.x) - (p4.x-p3.x)*(theP2.y-theP1.y)); + result.makeNan(); + // as long as the lines are not parallel + if(fabs(denominator) > FLT_EPSILON) + { + double ua = numerator/ denominator; + + if((ua >= -FLT_EPSILON) && (ua <= (1.0 + FLT_EPSILON))) + { + ossimDpt test = ossimDpt(theP1.x + ua*(theP2.x-theP1.x), + theP1.y + ua*(theP2.y-theP1.y)); + ossimDpt midPoint = line.theP1 + (line.theP2-line.theP1)*.5; + if( ((test-midPoint).length()/line.length()) <= (.5+FLT_EPSILON)) + { + result = test; + } + } + } + + return result; +} + +double ossimLine::length()const +{ + return (theP2-theP1).length(); +} + +ossimDpt ossimLine::midPoint()const +{ + return (theP1 + (theP2-theP1)*.5); +} + +bool ossimLine::isPointWithin(const ossimDpt& point, double delta)const +{ + if(isPointOnInfiniteLine(point, delta)) + { + double minx = std::min(theP1.x, theP2.x); + double miny = std::min(theP1.y, theP2.y); + double maxx = std::max(theP1.x, theP2.x); + double maxy = std::max(theP1.y, theP2.y); + + ossimDrect rect(minx - delta, + miny - delta, + maxx + delta, + maxy + delta); + + return rect.pointWithin(point); + } + + return false; +} + +bool ossimLine::isPointOnInfiniteLine(const ossimDpt& point, double delta)const +{ + if((point == theP1) || (point == theP2)) + { + return true; + } + else if(fabs(theP1.x-theP2.x) <= FLT_EPSILON) + { + return (fabs(point.x - theP1.x) <= delta); + } + else if(fabs(theP1.y-theP2.y) <= FLT_EPSILON) + { + return (fabs(point.y - theP1.y) <= delta); + } + else + { + ossimDpt v1 = getVector(); + v1 = v1 * (1.0/v1.length()); + ossimDpt v2 = (point - theP1); + double s = v1.x*v2.x + v1.y*v2.y; + ossimDpt p = theP1 + v1*s; + double len = (point-p).length(); + + if(len < delta) + { + return true; + } + else + { + return false; + } + } + + return false; +} + +ossimDpt ossimLine::normal()const +{ + ossimDpt delta = getVector(); + ossimDpt result; + if(fabs(delta.x) <= FLT_EPSILON) + { + result.y = 0.0; + result.x = -delta.y; + } + else if(fabs(delta.y) <= FLT_EPSILON) + { + result.x = 0.0; + result.y = delta.x; + } + else + { + result.x = -delta.y; + result.y = delta.x; + } + double len = result.length(); + + if(len >FLT_EPSILON) + { + result = result*(1.0/len); + } + + return result; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimLine.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimLine.h new file mode 100644 index 0000000000..d5703d4f57 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimLine.h @@ -0,0 +1,94 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +//******************************************************************* +// $Id: ossimLine.h,v 1.4 2002/09/01 19:21:56 gpotts Exp $ +#ifndef ossimLine_HEADER +#define ossimLine_HEADER +#include "base/data_types/ossimDpt.h" +#include <iostream> + +class OSSIMDLLEXPORT ossimLine +{ +public: + friend std::ostream& operator <<(std::ostream& out, + const ossimLine& rhs); + ossimLine(const ossimDpt& p1=ossimDpt(0,0), + const ossimDpt& p2=ossimDpt(0,0)) + :theP1(p1), + theP2(p2) + { + } + + + ossimDpt getVector()const + { + return (theP2-theP1); + } + + /*! + * Computes the following equation: + * + * Note: this object will be line a and the passed + * in object will be line b; + * and + * P1 and P2 coorespond to this object and + * P3 and P4 will coorespond to the passed in object. + * + * Now find point formed at the intersection of line a and b: + * + * Pa = P1 + ua ( P2 - P1 ) + * Pb = P3 + ub ( P4 - P3 ) + *const ossimDpt& ul_corner, + const ossimDpt& lr_corner, + ossimCoordSysOrientMode mode=OSSIM_LEFT_HANDED); + * x1 + ua (x2 - x1) = x3 + ub (x4 - x3) + * and + * y1 + ua (y2 - y1) = y3 + ub (y4 - y3) + * + * Solve: + * ua = ((x4-x3)(y1-y3) - (y4-y3)(x1-x3))/ + * ((y4-y3)(x2-x1) - (x4-x3)(y2-y1)) + * ub = ((x2-x1)(y1-y3) - (y2-y1)(x1-x3))/ + * ((y4-y3)(x2-x1) - (x4-x3)(y2-y1)) + * substitute: + * + * x = x1 + ua (x2 - x1) + * y = y1 + ua (y2 - y1) + * + */ + ossimDpt intersectInfinite(const ossimLine& line)const; + + ossimDpt intersectSegment(const ossimLine& line)const; + + ossimDpt midPoint()const; + double length()const; + ossimDpt normal()const; + /*! + * Will return true if the point is on the line. + */ + bool isPointWithin(const ossimDpt& point, double delta=FLT_EPSILON)const; + + bool isPointOnInfiniteLine(const ossimDpt& point, double delta=FLT_EPSILON)const; + + ossimDpt theP1; + ossimDpt theP2; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimLsrPoint.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimLsrPoint.cpp new file mode 100644 index 0000000000..d82da89b8c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimLsrPoint.cpp @@ -0,0 +1,124 @@ +//***************************************************************************** +// FILE: ossimLsrPoint.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// DESCRIPTION: +// Contains declaration of a 3D point object in the Earth-centered, earth +// fixed (ECEF) coordinate system. +// +// SOFTWARE HISTORY: +//> +// 08Aug2001 Oscar Kramer (okramer@imagelinks.com) +// Initial coding. +//< +//***************************************************************************** +// $Log: ossimLsrPoint.cpp,v $ +// Revision 1.2 2003/05/02 15:34:17 dburken +// Fixed build errors on AIX VisualAge compiler. <dburken@imagelinks.com> +// +// Revision 1.1 2001/08/13 21:29:18 okramer +// Initial delivery of ECEF and LSR suite. (okramer@imagelinks.com) +// + +#include "ossimLsrPoint.h" +#include "ossimGpt.h" +#include "ossimLsrVector.h" +#include "ossimMatrix3x3.h" + +//***************************************************************************** +// CONSTRUCTOR: ossimLsrPoint(ossimLsrPoint, space) +// +//***************************************************************************** +ossimLsrPoint::ossimLsrPoint(const ossimLsrPoint& convert_this, + const ossimLsrSpace& new_space) + : theLsrSpace(new_space) +{ + initialize(ossimEcefPoint(convert_this)); +} + +//***************************************************************************** +// CONSTRUCTOR: ossimLsrPoint(const ossimLsrPoint& convert_this) +// +//***************************************************************************** +ossimLsrPoint::ossimLsrPoint(const ossimGpt& gpt, + const ossimLsrSpace& space) + : theLsrSpace(space) +{ + initialize(ossimEcefPoint(gpt)); +} + +//***************************************************************************** +// CONSTRUCTOR: ossimLsrPoint(const ossimLsrPoint& convert_this) +// +//***************************************************************************** +ossimLsrPoint::ossimLsrPoint(const ossimEcefPoint& convert_this, + const ossimLsrSpace& space) + : theLsrSpace(space) +{ + initialize(convert_this); +} + +//***************************************************************************** +// PROTECTED METHOD: ossimLsrPoint::initialize(ossimEcefPoint) +// +// Convenience method used by several constructors for initializing theData +// given an ECEF point. Assumes theLsrSpace has been previously initialized. +// +//***************************************************************************** +void ossimLsrPoint::initialize(ossimEcefPoint ecef_point) +{ + //*** + // Translate to new space given the space's offset origin: + //*** + ossimColumnVector3d xlated ((ecef_point - theLsrSpace.origin()).data()); + + //*** + // Rotate by the inverse (transpose) of the LSR-to-ECEF rot matrix: + //*** + theData = theLsrSpace.ecefToLsrRotMatrix() * xlated; +} + +//***************************************************************************** +// OPERATOR: ossimLsrPoint::operator-(ossimLsrPoint) +// +//***************************************************************************** +ossimLsrVector ossimLsrPoint::operator-(const ossimLsrPoint& p) const +{ + if (theLsrSpace == p.theLsrSpace) + return ossimLsrVector(theData-p.theData, theLsrSpace); + + //else error: + ossimLsrSpace::lsrSpaceErrorMessage(); + return ossimLsrVector(OSSIM_NAN, OSSIM_NAN, OSSIM_NAN, theLsrSpace); +} + +//***************************************************************************** +// OPERATOR: ossimLsrPoint::operator+(ossimLsrVector) +// +//***************************************************************************** +ossimLsrPoint ossimLsrPoint::operator+(const ossimLsrVector& v) const +{ + if (theLsrSpace == v.lsrSpace()) + return ossimLsrPoint(theData + v.data(), theLsrSpace); + + //else error: + theLsrSpace.lsrSpaceErrorMessage(); + return ossimLsrPoint(OSSIM_NAN, OSSIM_NAN, OSSIM_NAN, theLsrSpace); +} + diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimLsrPoint.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimLsrPoint.h new file mode 100644 index 0000000000..df88f3ae90 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimLsrPoint.h @@ -0,0 +1,194 @@ +//***************************************************************************** +// FILE: ossimLsrPoint.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// DESCRIPTION: +// Class for representing points in some local space rectangular (LSR) +// coordinate system. This coordinate system is related to the ECEF system +// by the ossimLsrSpace member object. This class simplifies coordinate +// conversions between LSR and ECEF, and other LSR points. +// +// SOFTWARE HISTORY: +//> +// 08Aug2001 Oscar Kramer (okramer@imagelinks.com) +// Initial coding. +//< +//***************************************************************************** +// $Id: ossimLsrPoint.h,v 1.5 2004/04/02 22:03:54 gpotts Exp $ + +#ifndef ossimLsrPoint_HEADER +#define ossimLsrPoint_HEADER + +#include <stdio.h> + +#include <base/data_types/ossimLsrSpace.h> +#include <base/data_types/ossimColumnVector3d.h> +#include <base/data_types/ossimEcefVector.h> +#include <base/data_types/ossimEcefVector.h> +#include <base/context/ossimNotifyContext.h> + +class OSSIMDLLEXPORT ossimGpt; +class OSSIMDLLEXPORT ossimLsrVector; + +//***************************************************************************** +// CLASS: ossimLsrPoint +// +//***************************************************************************** +class OSSIMDLLEXPORT ossimLsrPoint +{ +public: + /*! + * CONSTRUCTORS: + */ + ossimLsrPoint() + : theData(0,0,0) {} + + ossimLsrPoint(const ossimLsrPoint& copy_this) + : theData(copy_this.theData), theLsrSpace(copy_this.theLsrSpace) {} + + ossimLsrPoint(const ossimColumnVector3d& assign_this, + const ossimLsrSpace& space) + : theData(assign_this), theLsrSpace(space) {} + + ossimLsrPoint(const double& x, + const double& y, + const double& z, + const ossimLsrSpace& space) + : theData(x, y, z), theLsrSpace(space) {} + + ossimLsrPoint(const ossimLsrPoint& convert_this, + const ossimLsrSpace&); + + ossimLsrPoint(const ossimGpt& convert_this, + const ossimLsrSpace&); + + ossimLsrPoint(const ossimEcefPoint& convert_this, + const ossimLsrSpace&); + + /*! + * OPERATORS: + */ + const ossimLsrPoint& operator= (const ossimLsrPoint&); //inline below + ossimLsrVector operator- (const ossimLsrPoint&) const; + ossimLsrPoint operator+ (const ossimLsrVector&) const; + bool operator==(const ossimLsrPoint&) const;//inline below + bool operator!=(const ossimLsrPoint&) const;//inline below + + /*! + * CASTING OPERATOR: + * Used as: myEcefVector = ossimEcefPoint(this) -- looks like a constructor + * but is an operation on this object. ECEF knows nothing about LSR, so + * cannot provide an ossimEcefVector(ossimLsrPoint) constructor. + */ + operator ossimEcefPoint() const; // inline below + + /*! + * DATA ACCESS METHODS: + */ + double x() const { return theData[0]; } + double& x() { return theData[0]; } + double y() const { return theData[1]; } + double& y() { return theData[1]; } + double z() const { return theData[2]; } + double& z() { return theData[2]; } + + ossimColumnVector3d& data() { return theData; } + const ossimColumnVector3d& data() const { return theData; } + + ossimLsrSpace& lsrSpace() { return theLsrSpace; } + const ossimLsrSpace& lsrSpace() const { return theLsrSpace; } + + /*! + * Debug Dump: + */ + void print(ostream& stream = ossimNotify(ossimNotifyLevel_INFO)) const; + + friend ostream& operator<< (ostream& os , const ossimLsrPoint& instance) + { instance.print(os); return os; } + +protected: + /*! + * METHOD: initialize(ossimEcefPoint) + * Convenience method used by several constructors for initializing theData + * given an ECEF point. Assumes theLsrSpace has been previously initialized. + */ + void initialize(ossimEcefPoint ecef_point); + + ossimColumnVector3d theData; + ossimLsrSpace theLsrSpace; + +}; + +//================== BEGIN DEFINITIONS FOR INLINE METHODS ===================== + +//***************************************************************************** +// INLINE OPERATOR: ossimLsrPoint::operator=(ossimLsrPoint) +//***************************************************************************** +inline const ossimLsrPoint& +ossimLsrPoint::operator=(const ossimLsrPoint& p) +{ + theData = p.theData; + theLsrSpace = p.theLsrSpace; + + return *this; +} + +//***************************************************************************** +// INLINE OPERATOR: ossimLsrPoint::operator==(ossimLsrPoint) +//***************************************************************************** +inline bool ossimLsrPoint::operator==(const ossimLsrPoint& p) const +{ + return ((theData == p.theData) && (theLsrSpace == p.theLsrSpace)); +} + +//***************************************************************************** +// INLINE OPERATOR: ossimLsrPoint::operator!=(ossimLsrPoint) +//***************************************************************************** +inline bool ossimLsrPoint::operator!=(const ossimLsrPoint& p) const +{ + return (!(*this == p)); +} + +//***************************************************************************** +// INLINE OPERATOR: ossimLsrPoint::operator ossimEcefPoint() +// +// Looks like a constructor for an ossimEcefPoint but is an operation on this +// object. Returns the ossimEcefPoint equivalent. +//***************************************************************************** +inline ossimLsrPoint::operator ossimEcefPoint() const +{ + return ossimEcefPoint(theLsrSpace.origin().data() + + theLsrSpace.lsrToEcefRotMatrix()*theData); +} + +//***************************************************************************** +// INLINE METHOD: ossimLsrPoint::print(ostream) +// +// Dumps contents for debug purposes. +//***************************************************************************** +inline void ossimLsrPoint::print(ostream& os) const +{ + os << "(ossimLsrPoint)\n" + << " theData = " << theData + << "\n theLsrSpace = " << theLsrSpace; +} + +#endif + + diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimLsrRay.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimLsrRay.cpp new file mode 100644 index 0000000000..f093294ede --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimLsrRay.cpp @@ -0,0 +1,109 @@ +//***************************************************************************** +// FILE: ossimLsrRay.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// DESCRIPTION: +// Class for representing rays in some local space rectangular (LSR) +// coordinate system. This coordinate system is related to the ECEF system +// by the ossimLsrSpace member object. This class simplifies coordinate +// conversions between LSR and ECEF, and other LSR spaces. +// +// An LSR ray is defined as having an LSR origin point and an LSR unit +// direction vector radiating from the origin. +// +// SOFTWARE HISTORY: +//> +// 08Aug2001 Oscar Kramer (okramer@imagelinks.com) +// Initial coding. +//< +//***************************************************************************** +// $Log: ossimLsrRay.cpp,v $ +// Revision 1.6 2004/04/08 15:25:30 gpotts +// *** empty log message *** +// +// Revision 1.5 2004/04/08 14:12:39 gpotts +// Fixe clog to ossimNotify +// +// Revision 1.4 2002/10/21 21:51:46 gpotts +// *** empty log message *** +// +// Revision 1.3 2002/10/21 21:51:26 gpotts +// *** empty log message *** +// +// Revision 1.2 2001/12/20 22:26:41 bpayne +// Added constructor accepting two ossimLsrPoint args +// +// Revision 1.1 2001/08/13 21:29:18 okramer +// Initial delivery of ECEF and LSR suite. (okramer@imagelinks.com) +// + +#include "ossimLsrRay.h" + +//***************************************************************************** +// CONSTRUCTOR: ossimLsrRay(ossimLsrPoint, ossimLsrVector) +// +// Constructs by transforming the given ray into the new space. +// +//***************************************************************************** +ossimLsrRay::ossimLsrRay(const ossimLsrPoint& origin, + const ossimLsrVector& direction) + : theOrigin(origin), + theDirection(direction.unitVector()) +{ + if (origin.lsrSpace() != direction.lsrSpace()) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL -- ossimLsrRay(ossimLsrPoint,ossimLsrVector) Constructor:" + << "\n The origin and direction LSR quantities do not share the" + << "\n same LSR space. Setting to NAN. Check the data for errors." << std::endl; + + theOrigin = ossimLsrPoint (OSSIM_NAN, OSSIM_NAN, OSSIM_NAN, + origin.lsrSpace()); + theDirection = ossimLsrVector(OSSIM_NAN, OSSIM_NAN, OSSIM_NAN, + direction.lsrSpace()); + } +} + +//***************************************************************************** +// CONSTRUCTOR: ossimLsrRay(ossimLsrPoint, ossimLsrPoint) +// +// Constructs by transforming the given ray into the new space. +// +//***************************************************************************** +ossimLsrRay::ossimLsrRay(const ossimLsrPoint& origin, + const ossimLsrPoint& towards) + : theOrigin(origin) +{ + if (origin.lsrSpace() != towards.lsrSpace()) + { + ossimNotify(ossimNotifyLevel_FATAL) << "ERROR -- ossimLsrRay(ossimLsrPoint,ossimLsrPoint) Constructor:" + << "\n The origin and direction LSR quantities do not share the" + << "\n same LSR space. Setting to NAN. Check the data for errors." << std::endl; + + theOrigin = ossimLsrPoint (OSSIM_NAN, OSSIM_NAN, OSSIM_NAN, + origin.lsrSpace()); + theDirection = ossimLsrVector(OSSIM_NAN, OSSIM_NAN, OSSIM_NAN, + towards.lsrSpace()); + } + + else + { + theDirection = towards - origin; + theDirection.normalize(); + } +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimLsrRay.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimLsrRay.h new file mode 100644 index 0000000000..e8c32ed212 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimLsrRay.h @@ -0,0 +1,169 @@ +//***************************************************************************** +// FILE: ossimLsrRay.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// DESCRIPTION: +// Class for representing rays in some local space rectangular (LSR) +// coordinate system. This coordinate system is related to the ECEF system +// by the ossimLsrSpace member object. This class simplifies coordinate +// conversions between LSR and ECEF, and other LSR spaces. +// +// An LSR ray is defined as having an LSR origin point and an LSR unit +// direction vector radiating from the origin. +// +// SOFTWARE HISTORY: +//> +// 08Aug2001 Oscar Kramer (okramer@imagelinks.com) +// Initial coding. +//< +//***************************************************************************** +// $Id: ossimLsrRay.h,v 1.7 2004/04/02 22:03:54 gpotts Exp $ + +#ifndef ossimLsrRay_HEADER +#define ossimLsrRay_HEADER + +#include <stdio.h> +#include <base/data_types/ossimLsrPoint.h> +#include <base/data_types/ossimLsrVector.h> +#include <base/data_types/ossimEcefRay.h> +#include <base/context/ossimNotifyContext.h> + +//***************************************************************************** +// CLASS: ossimLsrRay +// +//***************************************************************************** +class OSSIMDLLEXPORT ossimLsrRay +{ +public: + /*! + * CONSTRUCTORS: + */ + ossimLsrRay() {} + + ossimLsrRay(const ossimLsrRay& copy_this) + : theOrigin(copy_this.theOrigin), theDirection(copy_this.theDirection) {} + + ossimLsrRay(const ossimLsrPoint& origin, + const ossimLsrVector& direction); + + ossimLsrRay(const ossimLsrPoint& origin, + const ossimLsrPoint& towards); + + ossimLsrRay(const ossimLsrRay& convert_this, + const ossimLsrSpace& new_space) + : theOrigin(convert_this.theOrigin, new_space), + theDirection(convert_this.theDirection, new_space) {} + + /*! + * OPERATORS: + */ + const ossimLsrRay& operator= (const ossimLsrRay& r); // inline below + bool operator==(const ossimLsrRay& r) const; // inline below + bool operator!=(const ossimLsrRay& r) const; // inline below + + /*! + * DATA ACCESS METHODS: + */ + const ossimLsrPoint& origin() const { return theOrigin; } + const ossimLsrVector& direction() const { return theDirection; } + const ossimLsrSpace& lsrSpace() const { return theOrigin.lsrSpace(); } + + /*! + * CASTING OPERATOR: ossimEcefRay() + * Looks like a constructor for an ossimEcefRay but is an operation on this + * object. Returns the ossimEcefRay equivalent. + */ + operator ossimEcefRay () const; // inline below + + /*! + * METHOD: extend(t) + * Extends the ray by distance t (meters) from the origin to the LSR + * point returned (in same space). + */ + ossimLsrPoint extend(const double& t) const + { return (theOrigin + theDirection*t); } + + /*! + * Debug Dump: + */ + void print(ostream& stream = ossimNotify(ossimNotifyLevel_INFO)) const; // inline below + + friend ostream& operator<< (ostream& os , const ossimLsrRay& instance) + { instance.print(os); return os; } + +private: + ossimLsrPoint theOrigin; + ossimLsrVector theDirection; + +}; + +//================== BEGIN DEFINITIONS FOR INLINE METHODS ===================== + +//***************************************************************************** +// INLINE METHOD: ossimEcefRay::operator=(ossimEcefRay) +//***************************************************************************** +inline const ossimLsrRay& ossimLsrRay::operator=(const ossimLsrRay& r) +{ + theOrigin = r.theOrigin; + theDirection = r.theDirection; + return *this; +} + +//***************************************************************************** +// INLINE METHOD: ossimEcefRay::operator==(ossimEcefRay) +//***************************************************************************** +inline bool ossimLsrRay::operator==(const ossimLsrRay& r) const +{ + return ((theOrigin == r.theOrigin) && (theDirection == r.theDirection)); +} + +//***************************************************************************** +// INLINE METHOD: ossimEcefRay::operator!=(ossimEcefRay) +//***************************************************************************** +inline bool ossimLsrRay::operator!=(const ossimLsrRay& r) const +{ + return !(*this == r); +} + +//***************************************************************************** +// INLINE CASTING OPERATOR: ossimEcefRay() +// +// Looks like a constructor for an ossimEcefRay but is an operation on this +// object. Returns the ossimEcefRay equivalent. +//***************************************************************************** +inline ossimLsrRay::operator ossimEcefRay() const +{ + return ossimEcefRay(ossimEcefPoint(theOrigin), + ossimEcefVector(theDirection)); +} + +//***************************************************************************** +// INLINE METHOD: ossimLsrRay::print(ostream) +// Dumps contents for debug purposes. +//***************************************************************************** +inline void ossimLsrRay::print(ostream& os) const +{ + os << "(ossimLsrRay)" + << "\n theOrigin = " << theOrigin + << "\n theDirection = " << theDirection << ends; +} + +#endif + + diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimLsrSpace.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimLsrSpace.cpp new file mode 100644 index 0000000000..c655127919 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimLsrSpace.cpp @@ -0,0 +1,236 @@ +//***************************************************************************** +// FILE: ossimLsrSpace.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// DESCRIPTION: +// This class maintains the relationship between a local space rectangular +// (LSR) coordinate system and the earth-centered, earth-fixed (ECEF) system. +// +// SOFTWARE HISTORY: +// +// 09Aug2001 Oscar Kramer (okramer@imagelinks.com) +// Initial coding. +// +//***************************************************************************** +// $Id: ossimLsrSpace.cpp,v 1.5 2004/04/02 22:03:54 gpotts Exp $ + +#include <base/data_types/ossimLsrSpace.h> +#include <base/common/ossimCommon.h> +#include <base/data_types/ossimGpt.h> + +//***************************************************************************** +// CONSTRUCTOR: ossimLsrSpace(origin, x_dir, y_dir, int) +// +// Constructs the space given origin, and X and Y ECEF directions. The int +// argument is a place holder only and not used. +// +//***************************************************************************** +ossimLsrSpace::ossimLsrSpace(const ossimEcefPoint& origin, + const ossimEcefVector& x_dir_ecf_vec, + const ossimEcefVector& y_dir_ecf_vec, + int z_not_provided_space_holder) + : theOrigin (origin) +{ + //*** + // Compute the remaining axis given first two: + //*** + ossimColumnVector3d xdir (x_dir_ecf_vec.data().unit()); + ossimColumnVector3d ydir (y_dir_ecf_vec.data().unit()); + ossimColumnVector3d zdir (xdir.cross(ydir)); + + //*** + // Fill the rotation matrix: + //*** + theLsrToEcefRotMatrix = ossimMatrix3x3::create(xdir[0], ydir[0], zdir[0], + xdir[1], ydir[1], zdir[1], + xdir[2], ydir[2], zdir[2]); +} + +//***************************************************************************** +// CONSTRUCTOR: ossimLsrSpace +// +// Constructs the space given origin, and X and Z ECEF directions. The int +// argument is a place holder only and not used. +// +//***************************************************************************** +ossimLsrSpace::ossimLsrSpace(const ossimEcefPoint& origin, + const ossimEcefVector& x_dir_ecf_vec, + int y_not_provided_space_holder, + const ossimEcefVector& z_dir_ecf_vec) + : theOrigin (origin) +{ + //*** + // Compute the remaining axis given first two: + //*** + ossimColumnVector3d xdir (x_dir_ecf_vec.data().unit()); + ossimColumnVector3d zdir (z_dir_ecf_vec.data().unit()); + ossimColumnVector3d ydir (zdir.cross(xdir)); + + //*** + // Fill the rotation matrix: + //*** + theLsrToEcefRotMatrix = ossimMatrix3x3::create(xdir[0], ydir[0], zdir[0], + xdir[1], ydir[1], zdir[1], + xdir[2], ydir[2], zdir[2]); +} + +//***************************************************************************** +// CONSTRUCTOR: ossimLsrSpace +// +// Constructs the space given origin, and Y and Z ECEF directions. The int +// argument is a place holder only and not used. +// +//***************************************************************************** +ossimLsrSpace::ossimLsrSpace(const ossimEcefPoint& origin, + int x_not_provided_space_holder, + const ossimEcefVector& y_dir_ecf_vec, + const ossimEcefVector& z_dir_ecf_vec) + : theOrigin (origin) +{ + //*** + // Compute the remaining axis given first two: + //*** + ossimColumnVector3d ydir (y_dir_ecf_vec.data().unit()); + ossimColumnVector3d zdir (z_dir_ecf_vec.data().unit()); + ossimColumnVector3d xdir (ydir.cross(zdir)); + + //*** + // Fill the rotation matrix: + //*** + theLsrToEcefRotMatrix = ossimMatrix3x3::create(xdir[0], ydir[0], zdir[0], + xdir[1], ydir[1], zdir[1], + xdir[2], ydir[2], zdir[2]); +} + +//***************************************************************************** +// CONSTRUCTORS: ossimLsrSpace(ossimGpt, y_azimuth) +// +// This constructor sets up a local coordinate system centered at the +// specified groundpoint, with the Z-axis normal to the ellipsoid and the +// Y-axis rotated clockwise from north by the y_azimuth. This angle defaults +// to 0, producing an East-North-Up system. +// +//***************************************************************************** +ossimLsrSpace::ossimLsrSpace(const ossimGpt& origin, + const double& y_azimuth) +{ + //*** + // Convert ground point origin to ECEF coordinates: + //*** + theOrigin = ossimEcefPoint(origin); + + //*** + // Establish the component vectors for ENU system:: + //*** + double sin_lat = sind(origin.lat); + double cos_lat = cosd(origin.lat); + double sin_lon = sind(origin.lon); + double cos_lon = cosd(origin.lon); + + ossimColumnVector3d E (-sin_lon, + cos_lon, + 0.0); + ossimColumnVector3d N (-sin_lat*cos_lon, + -sin_lat*sin_lon, + cos_lat); + ossimColumnVector3d U (E.cross(N)); + + //*** + // Fill rotation matrix with these components, rotated about the Z axis + // by the azimuth indicated: + //*** + if (y_azimuth != 0.0) + { + double cos_azim = cosd(y_azimuth); + double sin_azim = sind(y_azimuth); + ossimColumnVector3d X (cos_azim*E - sin_azim*N); + ossimColumnVector3d Y (sin_azim*E + cos_azim*N); + ossimColumnVector3d Z (X.cross(Y)); + + theLsrToEcefRotMatrix + = ossimMatrix3x3::create(X[0], Y[0], Z[0], + X[1], Y[1], Z[1], + X[2], Y[2], Z[2]); + } + else + { + //*** + // No azimuth rotation, so simplify: + //*** + theLsrToEcefRotMatrix = ossimMatrix3x3::create(E[0], N[0], U[0], + E[1], N[1], U[1], + E[2], N[2], U[2]); + } +} + +//***************************************************************************** +// OPERATOR: == +//***************************************************************************** +bool ossimLsrSpace::operator == (const ossimLsrSpace& that) const +{ + if (theOrigin != that.origin()) + return false; + + if (theLsrToEcefRotMatrix != that.theLsrToEcefRotMatrix) + return false; + + return true; +} + +//***************************************************************************** +// OPERATOR: = +//***************************************************************************** +const ossimLsrSpace& ossimLsrSpace::operator = (const ossimLsrSpace& space) +{ + theOrigin = space.theOrigin; + theLsrToEcefRotMatrix = space.theLsrToEcefRotMatrix; + return *this; +} + +//***************************************************************************** +// STATIC METHOD: lsrSpaceErrorMessage() +// +// Convenience method accessible to all owners of an ossimLsrSpace for +// displaying an error message when LSR spaces do not match between +// objects. All operations between LSR objects must be in a common space. +// +//***************************************************************************** +ostream& ossimLsrSpace::lsrSpaceErrorMessage(ostream& os) +{ + os<<"ossimLsrSpace ERROR: An operation was attempted between two LSR \n" + <<" objects with differing LSR spaces. This is an illegal condition.\n" + <<" Please check the data and/or report the error to OSSIM development." + <<endl; + + return os; +} + +//***************************************************************************** +// METHOD: print() +// +// Dumps contents to stream for debug purposes. Defaults to cout. +// +//***************************************************************************** +void ossimLsrSpace::print(ostream& stream) const +{ + stream << "(ossimLsrSpace)" + << "\n theOrigin = " << theOrigin + << "\n theLsrToEcefRotMatrix = \n" << theLsrToEcefRotMatrix; +} + diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimLsrSpace.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimLsrSpace.h new file mode 100644 index 0000000000..ad27665ea9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimLsrSpace.h @@ -0,0 +1,147 @@ +//***************************************************************************** +// FILE: ossimLsrSpace.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// DESCRIPTION: +// This class maintains the relationship between a local space rectangular +// (LSR) coordinate system and the earth-centered, earth-fixed (ECEF) system. +// +// SOFTWARE HISTORY: +//> +// 08Aug2001 Oscar Kramer (okramer@imagelinks.com) +// Initial coding. +//< +//***************************************************************************** +// $Id: ossimLsrSpace.h,v 1.7 2004/04/02 22:03:54 gpotts Exp $ + +#ifndef ossimLsrSpace_HEADER +#define ossimLsrSpace_HEADER + +#include <stdio.h> +#include <base/data_types/ossimEcefPoint.h> +#include <base/data_types/ossimEcefVector.h> +#include <base/data_types/ossimMatrix3x3.h> +#include <base/context/ossimNotifyContext.h> + +class OSSIMDLLEXPORT ossimGpt; + +//***************************************************************************** +// CLASS: ossimLsrSpace +// +// This class maintains the relationship between a local space rectangular +// (LSR) coordinate system and the earth-centered, earth-fixed (ECEF) system. +// +//***************************************************************************** +class OSSIMDLLEXPORT ossimLsrSpace +{ +public: + /*! + * DEFAULT & COPY CONSTRUCTOR: + */ + ossimLsrSpace() {} + + ossimLsrSpace(const ossimLsrSpace& copy_this) + : + theLsrToEcefRotMatrix(copy_this.theLsrToEcefRotMatrix), + theOrigin(copy_this.theOrigin) {} + + /*! + * CONSTRUCTORS: The following three constructors accept an ECEF origin + * and two of the three axes direction vectors. Note the use of the dummy + * "int" argument (not used) to hold the place of the unspecified axes. + */ + ossimLsrSpace(const ossimEcefPoint& origin, + const ossimEcefVector& x_dir_ecf_vec, + const ossimEcefVector& y_dir_ecf_vec, + const int z_not_provided_space_holder); + + ossimLsrSpace(const ossimEcefPoint& origin, + const ossimEcefVector& x_dir_ecf_vec, + const int y_not_provided_space_holder, + const ossimEcefVector& z_dir_ecf_vec); + + ossimLsrSpace(const ossimEcefPoint& origin, + const int x_not_provided_space_holder, + const ossimEcefVector& y_dir_ecf_vec, + const ossimEcefVector& z_dir_ecf_vec); + + /*! + * CONSTRUCTOR: ossimLsrSpace(ossimGpt, y_azimuth) + * This constructor sets up a local coordinate system centered at the + * specified groundpoint, with the Z-axis normal to the ellipsoid and the + * Y-axis rotated clockwise from north by the y_azimuth. This angle defaults + * to 0, producing an East-North-Up (ENU) system. + */ + ossimLsrSpace(const ossimGpt& origin, + const double& y_azimuth=0); + + /*! + * CONSTRUCTOR: ossimLsrSpace(ossimEcefPt, NEWMAT::Matrix) + * This constructor sets up a local coordinate system centered at the + * specified ECF, with given LSR-to-ECF rotation. + */ + ossimLsrSpace(const ossimEcefPoint& origin, + const NEWMAT::Matrix& lsrToEcfRot) + : theLsrToEcefRotMatrix (lsrToEcfRot), theOrigin (origin) {} + + ~ossimLsrSpace() {} + + /*! + * OPERATORS: + */ + bool operator == (const ossimLsrSpace&) const; + + bool operator != (const ossimLsrSpace& that) const + { return !(*this == that); } + + const ossimLsrSpace& operator = (const ossimLsrSpace& space); + + /*! + * DATA ACCESS METHODS: + */ + const ossimEcefPoint& origin() const { return theOrigin; } + const NEWMAT::Matrix& lsrToEcefRotMatrix() const + { return theLsrToEcefRotMatrix; } + NEWMAT::Matrix ecefToLsrRotMatrix() const + { return theLsrToEcefRotMatrix.t(); } + + /*! + * METHOD: lsrSpaceErrorMessage() + * Convenience method accessible to all owners of an ossimLsrSpace for + * displaying an error message when LSR spaces do not match between + * objects. All operations between LSR objects must be in a common space. + */ + static ostream& lsrSpaceErrorMessage(ostream& os=ossimNotify(ossimNotifyLevel_INFO)); + + /*! + * Debug Dump: + */ + void print(ostream& stream = ossimNotify(ossimNotifyLevel_INFO)) const; + + friend ostream& operator<< (ostream& os , const ossimLsrSpace& instance) + { instance.print(os); return os; } + +private: + NEWMAT::Matrix theLsrToEcefRotMatrix; + ossimEcefPoint theOrigin; +}; + +#endif + + diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimLsrVector.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimLsrVector.cpp new file mode 100644 index 0000000000..815c79fae0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimLsrVector.cpp @@ -0,0 +1,119 @@ +//***************************************************************************** +// FILE: ossimLsrVector.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// DESCRIPTION: +// Contains implementation of class +// +// SOFTWARE HISTORY: +//> +// ddmmm2001 Oscar Kramer (okramer@imagelinks.com) +// Initial coding. +//< +//***************************************************************************** +// $Log: ossimLsrVector.cpp,v $ +// Revision 1.2 2004/04/02 22:03:54 gpotts +// Fixing all occurences of cout and cerr and CLOG to use the ossimNotify interface. +// +// Revision 1.1 2001/08/13 21:29:18 okramer +// Initial delivery of ECEF and LSR suite. (okramer@imagelinks.com) +// + +#include <base/data_types/ossimLsrVector.h> +#include <base/data_types/ossimEcefVector.h> +#include <base/common/ossimCommon.h> + +//***************************************************************************** +// CONSTRUCTOR: ossimLsrVector(ossimEcefVector, ossimLsrSpace) +// +// Establishes an LSR vector given the ECEF equivalent and the LSR space. +// +//***************************************************************************** +ossimLsrVector::ossimLsrVector(const ossimEcefVector& convert_this, + const ossimLsrSpace& new_space) + : theLsrSpace (new_space) +{ + initialize(convert_this); +} + +//***************************************************************************** +// CONSTRUCTOR: ossimLsrVector(ossimLsrVector, ossimLsrSpace) +// +// Establishes an LSR vector in a new space given another LSR vector in a +// different space. +// +//***************************************************************************** +ossimLsrVector::ossimLsrVector(const ossimLsrVector& convert_this, + const ossimLsrSpace& new_space) + : theLsrSpace (new_space) +{ + initialize(ossimEcefVector(convert_this)); +} + +//***************************************************************************** +// METHOD: ossimLsrVector::dot(ossimLsrVector) +// +// Computes the scalar product. +// +//***************************************************************************** +double ossimLsrVector::dot(const ossimLsrVector& v) const +{ + if (theLsrSpace == v.theLsrSpace) + return theData.dot(v.data()); + + //else error: + ossimLsrSpace::lsrSpaceErrorMessage(); + return OSSIM_NAN; +} + +//***************************************************************************** +// METHOD: ossimLsrVector::angleTo(ossimLsrVector) +// +// Returns the angle subtended (in DEGREES) between this and arg vector +// +//***************************************************************************** +double ossimLsrVector::angleTo(const ossimLsrVector& v) const +{ + if (theLsrSpace == v.theLsrSpace) + { + double mag_product = theData.magnitude() * v.theData.magnitude(); + return acosd(theData.dot(v.theData)/mag_product); + } + + //else error: + ossimLsrSpace::lsrSpaceErrorMessage(); + return OSSIM_NAN; +} + +//***************************************************************************** +// METHOD: ossimLsrVector::cross(ossimLsrVector) +// +// Computes the cross product. +// +//***************************************************************************** +ossimLsrVector ossimLsrVector::cross(const ossimLsrVector& v) const +{ + if (theLsrSpace == v.theLsrSpace) + return ossimLsrVector(theData.cross(v.data()), theLsrSpace); + + //else error: + ossimLsrSpace::lsrSpaceErrorMessage(); + return ossimLsrVector(OSSIM_NAN, OSSIM_NAN, OSSIM_NAN, theLsrSpace); +} + diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimLsrVector.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimLsrVector.h new file mode 100644 index 0000000000..bd1d706c54 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimLsrVector.h @@ -0,0 +1,303 @@ +//***************************************************************************** +// FILE: ossimLsrVector.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// DESCRIPTION: +// Class for representing vectors in some local space rectangular (LSR) +// coordinate system. This coordinate system is related to the ECEF system +// by the ossimLsrSpace member object. This class simplifies coordinate +// conversions between LSR and ECEF, and other LSR vectors. +// +// SOFTWARE HISTORY: +//> +// 08Aug2001 Oscar Kramer (okramer@imagelinks.com) +// Initial coding. +//< +//***************************************************************************** +// $Id: ossimLsrVector.h,v 1.5 2004/04/02 22:03:54 gpotts Exp $ + +#ifndef ossimLsrVector_HEADER +#define ossimLsrVector_HEADER + +#include <stdio.h> +#include <base/data_types/ossimLsrPoint.h> +#include <base/data_types/ossimLsrSpace.h> +#include <base/data_types/ossimEcefPoint.h> +#include <base/data_types/ossimEcefVector.h> +#include <base/data_types/ossimColumnVector3d.h> +#include <base/context/ossimNotifyContext.h> + +class OSSIMDLLEXPORT ossimGpt; + +//***************************************************************************** +// CLASS: ossimLsrVector +// +//***************************************************************************** +class OSSIMDLLEXPORT ossimLsrVector +{ +public: + /*! + * CONSTRUCTORS: + */ + ossimLsrVector() + : theData (0,0,0) {} + + ossimLsrVector(const ossimLsrVector& copy_this) + : theData(copy_this.theData), theLsrSpace(copy_this.theLsrSpace) {} + + ossimLsrVector(const ossimColumnVector3d& assign_this, + const ossimLsrSpace& space) + : theData(assign_this), theLsrSpace(space) {} + + ossimLsrVector(const double& x, + const double& y, + const double& z, + const ossimLsrSpace& space) + : theData(x,y,z), theLsrSpace(space) {} + + ossimLsrVector(const ossimEcefVector& convert_this, + const ossimLsrSpace&); + ossimLsrVector(const ossimLsrVector& convert_this, + const ossimLsrSpace&); + + /*! + * OPERATORS: (all methods inlined below) + */ + const ossimLsrVector& operator= (const ossimLsrVector&); + ossimLsrVector operator- () const; + ossimLsrVector operator+ (const ossimLsrVector&) const; + ossimLsrVector operator- (const ossimLsrVector&) const; + ossimLsrPoint operator+ (const ossimLsrPoint&) const; + ossimLsrVector operator* (const double& scalar) const; + ossimLsrVector operator/ (const double& scalar) const; + bool operator==(const ossimLsrVector&) const; + bool operator!=(const ossimLsrVector&) const; + + /*! + * CASTING OPERATOR: + * Used as: myEcefVector = ossimEcefVector(this) -- looks like a constructor + * but is an operation on this object. ECEF knows nothing about LSR, so + * cannot provide an ossimEcefVector(ossimLsrVector) constructor. + */ + operator ossimEcefVector() const; // inline below + + /*! + * Vector-related functions: + */ + double dot(const ossimLsrVector&) const; + double angleTo(const ossimLsrVector&) const; + ossimLsrVector cross(const ossimLsrVector&) const; + ossimLsrVector unitVector() const;//inline below + double magnitude() const;//inline below + void normalize(); // inline below + + /*! + * DATA ACCESS METHODS: + */ + double x() const { return theData[0]; } + double& x() { return theData[0]; } + double y() const { return theData[1]; } + double& y() { return theData[1]; } + double z() const { return theData[2]; } + double& z() { return theData[2]; } + + ossimColumnVector3d& data() { return theData; } + const ossimColumnVector3d& data() const { return theData; } + + ossimLsrSpace& lsrSpace() { return theLsrSpace; } + const ossimLsrSpace& lsrSpace() const { return theLsrSpace; } + + /*! + * Debug Dump: + */ + void print(ostream& stream = ossimNotify(ossimNotifyLevel_INFO)) const; + + friend ostream& operator<< (ostream& os , const ossimLsrVector& instance) + { instance.print(os); return os; } + +protected: + /*! + * METHOD: initialize(ossimEcefVector) + * Convenience method used by several constructors for initializing theData + * given an ECEF vector. Assumes theLsrSpace has been previously initialized + */ + void initialize(const ossimEcefVector& ecef_point); + + ossimColumnVector3d theData; + ossimLsrSpace theLsrSpace; + +}; + +//================== BEGIN DEFINITIONS FOR INLINE METHODS ===================== + +//***************************************************************************** +// INLINE OPERATOR: ossimLsrVector::operator=(ossimLsrVector) +//***************************************************************************** +inline const ossimLsrVector& ossimLsrVector::operator=(const ossimLsrVector& v) +{ + theData = v.theData; + theLsrSpace = v.theLsrSpace; + + return *this; +} + +//***************************************************************************** +// INLINE OPERATOR: ossimLsrVector::operator-() (negate) +//***************************************************************************** +inline ossimLsrVector ossimLsrVector::operator-() const +{ + return ossimLsrVector(-theData, theLsrSpace); +} + +//***************************************************************************** +// INLINE OPERATOR: ossimLsrVector::operator+(ossimLsrVector) +//***************************************************************************** +inline ossimLsrVector ossimLsrVector::operator+(const ossimLsrVector& v) const +{ + if (theLsrSpace == v.theLsrSpace) + return ossimLsrVector(theData + v.theData, theLsrSpace); + + //else error: + theLsrSpace.lsrSpaceErrorMessage(); + return ossimLsrVector(OSSIM_NAN, OSSIM_NAN, OSSIM_NAN, theLsrSpace); +} + +//***************************************************************************** +// INLINE OPERATOR: ossimLsrVector::operator-(ossimLsrVector) +//***************************************************************************** +inline ossimLsrVector ossimLsrVector::operator-(const ossimLsrVector& v) const +{ + if (theLsrSpace == v.theLsrSpace) + return ossimLsrVector(theData - v.data(), theLsrSpace); + + //else error: + theLsrSpace.lsrSpaceErrorMessage(); + return ossimLsrVector(OSSIM_NAN, OSSIM_NAN, OSSIM_NAN, theLsrSpace); +} + +//***************************************************************************** +// INLINE OPERATOR: ossimLsrVector::operator+(ossimLsrPoint) +//***************************************************************************** +inline ossimLsrPoint ossimLsrVector::operator+(const ossimLsrPoint& p) const +{ + if (theLsrSpace == p.lsrSpace()) + return ossimLsrPoint(theData + p.data(), theLsrSpace); + + //else error: + theLsrSpace.lsrSpaceErrorMessage(); + return ossimLsrPoint(OSSIM_NAN, OSSIM_NAN, OSSIM_NAN, theLsrSpace); +} + +//***************************************************************************** +// INLINE OPERATOR: ossimLsrVector::operator*(double scalar) +//***************************************************************************** +inline ossimLsrVector ossimLsrVector::operator*(const double& scalar) const +{ + return ossimLsrVector(theData*scalar, theLsrSpace); +} + +//***************************************************************************** +// INLINE OPERATOR: ossimLsrVector::operator/(double scalar) +//***************************************************************************** +inline ossimLsrVector ossimLsrVector::operator/(const double& scalar) const +{ + return ossimLsrVector(theData/scalar, theLsrSpace); +} + +//***************************************************************************** +// INLINE OPERATOR: ossimLsrVector::operator==(ossimLsrVector) +//***************************************************************************** +inline bool ossimLsrVector::operator==(const ossimLsrVector& v) const +{ + return ((theData == v.theData) && (theLsrSpace == v.theLsrSpace)); +} + +//***************************************************************************** +// INLINE OPERATOR: ossimLsrVector::operator!=(ossimLsrVector) +//***************************************************************************** +inline bool ossimLsrVector::operator!=(const ossimLsrVector& v) const +{ + return (!(*this == v)); +} + +//***************************************************************************** +// INLINE OPERATOR: ossimEcefVector() +// +// Looks like a constructor for an ossimEcefVector but is an operation on this +// object. Returns the ossimEcefVector equivalent. +// +//***************************************************************************** +inline ossimLsrVector::operator ossimEcefVector() const +{ + return ossimEcefVector(theLsrSpace.lsrToEcefRotMatrix()*theData); +} + +//***************************************************************************** +// INLINE METHOD: ossimLsrVector::unitVector() +// Returns a unit vector parallel to this. +//***************************************************************************** +inline ossimLsrVector ossimLsrVector::unitVector() const +{ + return ossimLsrVector(theData/theData.magnitude(), theLsrSpace); +} + +//***************************************************************************** +// INLINE METHOD: ossimLsrVector::magnitude() +//***************************************************************************** +inline double ossimLsrVector::magnitude() const +{ + return theData.magnitude(); +} + +//***************************************************************************** +// INLINE METHOD: ossimLsrVector::normalize() +// Normalizes this vector. +//***************************************************************************** +inline void ossimLsrVector::normalize() +{ + theData /= theData.magnitude(); +} + +//***************************************************************************** +// INLINE METHOD: ossimLsrVector::print(ostream) +// +// Dumps contents for debug purposes. +//***************************************************************************** +inline void ossimLsrVector::print(ostream& os) const +{ + os << "(ossimLsrVector)\n" + << " theData = " << theData + << "\n theLsrSpace = " << theLsrSpace; +} + +//***************************************************************************** +// PROTECTED INLINE METHOD: ossimLsrPoint::initialize(ossimEcefPoint) +// +// Convenience method used by several constructors for initializing theData +// given an ECEF point. Assumes theLsrSpace has been previously initialized. +// +//***************************************************************************** +inline void ossimLsrVector::initialize(const ossimEcefVector& ecef_vector) +{ + theData = theLsrSpace.ecefToLsrRotMatrix() * ecef_vector.data(); +} + +#endif + + diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimMatrix3x3.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimMatrix3x3.cpp new file mode 100644 index 0000000000..442ba1d174 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimMatrix3x3.cpp @@ -0,0 +1,289 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimMatrix3x3.cpp,v 1.13 2005/09/06 16:23:41 gpotts Exp $ + +#include <base/data_types/ossimMatrix3x3.h> +#include <matrix/newmatap.h> +#include <base/data_types/ossimColumnVector3d.h> +#include <base/common/ossimConstants.h> + +NEWMAT::Matrix ossimMatrix3x3::create() +{ + NEWMAT::Matrix m(3, 3); + + m[0][0] = 1.0; + m[0][1] = 0.0; + m[0][2] = 0.0; + + m[1][0] = 0.0; + m[1][1] = 1.0; + m[1][2] = 0.0; + + m[2][0] = 0.0; + m[2][1] = 0.0; + m[2][2] = 1.0; + + return m; +} + +NEWMAT::Matrix ossimMatrix3x3::create(double v00, double v01, double v02, + double v10, double v11, double v12, + double v20, double v21, double v22) +{ + NEWMAT::Matrix m(3, 3); + + m[0][0] = v00; + m[0][1] = v01; + m[0][2] = v02; + + m[1][0] = v10; + m[1][1] = v11; + m[1][2] = v12; + + m[2][0] = v20; + m[2][1] = v21; + m[2][2] = v22; + + return m; +} + +NEWMAT::Matrix ossimMatrix3x3::create(const NEWMAT::Matrix& rhs) +{ + NEWMAT::Matrix m(3, 3); + + if (rhs.Ncols() != 3 || rhs.Nrows() != 3) + { + ossimNotify(ossimNotifyLevel_FATAL) << "ossimMatrix3x3::create(const NEWMAT::Matrix& rhs) ERROR:" + << "\nMatrix passed to function not a 3x3!" + << "\nnumber of columns: " << rhs.Ncols() + << "\nnumber of rows: " << rhs.Nrows() + << "\nReturn blank 3x3 matrix...\n"; + return m; + } + + m[0][0] = rhs[0][0]; + m[0][1] = rhs[0][1]; + m[0][2] = rhs[0][2]; + m[0][3] = rhs[0][3]; + m[1][0] = rhs[1][0]; + m[1][1] = rhs[1][1]; + m[1][2] = rhs[1][2]; + m[1][3] = rhs[1][3]; + m[2][0] = rhs[2][0]; + m[2][1] = rhs[2][1]; + m[2][2] = rhs[2][2]; + m[2][3] = rhs[2][3]; + + return m; +} + +ossimColumnVector3d ossimMatrix3x3::getEigenValues(const NEWMAT::Matrix& matrix) +{ + if (matrix.Ncols() != 3 || matrix.Nrows() != 3) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL: ossimColumnVector3d operator*(const NEWMAT::Matrix& lhs," + << "\nconst ossimColumnVector3d& rhs), " + << "\nMatrix passed to function not a 3x3!" + << "\nnumber of columns: " << matrix.Ncols() + << "\nnumber of rows: " << matrix.Nrows() + << "\nReturn blank ossimColumnVector3d...\n"; + return ossimColumnVector3d(); + } + + NEWMAT::DiagonalMatrix d; + NEWMAT::SymmetricMatrix s; + + s << matrix; + + EigenValues(s, d); + + return ossimColumnVector3d(d[0], d[1], d[2]); +} + +NEWMAT::Matrix ossimMatrix3x3::createIdentity() +{ + NEWMAT::Matrix m(3,3); + + m[0][0] = 1.0; + m[0][1] = 0.0; + m[0][2] = 0.0; + + m[1][0] = 0.0; + m[1][1] = 1.0; + m[1][2] = 0.0; + + m[2][0] = 0.0; + m[2][1] = 0.0; + m[2][2] = 1.0; + + return m; +} + +NEWMAT::Matrix ossimMatrix3x3::createZero() +{ + NEWMAT::Matrix m(3,3); + + m = 0.0; + + return m; +} + +NEWMAT::Matrix ossimMatrix3x3::createTranslationMatrix(double dx,double dy) +{ + NEWMAT::Matrix m(3,3); + + m[0][0] = 1.0; + m[0][1] = 0.0; + m[0][2] = dx; + + m[1][0] = 0.0; + m[1][1] = 1.0; + m[1][2] = dy; + + m[2][0] = 0.0; + m[2][1] = 0.0; + m[2][2] = 1.0; + + return m; +} + +NEWMAT::Matrix ossimMatrix3x3::createRotationMatrix(double angleX, + double angleY, + double angleZ, + ossimCoordSysOrientMode orientationMode) +{ + return (createRotationZMatrix(angleZ, orientationMode)* + createRotationYMatrix(angleY, orientationMode)* + createRotationXMatrix(angleX, orientationMode)); +} + +NEWMAT::Matrix ossimMatrix3x3::createRotationXMatrix(double angle, + ossimCoordSysOrientMode orientationMode) +{ + NEWMAT::Matrix m(3,3); + double Cosine = cos(angle*RAD_PER_DEG); + double Sine = sin(angle*RAD_PER_DEG); + + if(orientationMode == OSSIM_RIGHT_HANDED) + { + m << 1 << 0 << 0 + << 0 << Cosine << Sine + << 0 << -Sine << Cosine; + } + else + { + m << 1 << 0 << 0 + << 0 << Cosine << -Sine + << 0 << Sine << Cosine; + } + return m; +} + +NEWMAT::Matrix ossimMatrix3x3::createRotationYMatrix(double angle, + ossimCoordSysOrientMode orientationMode) +{ + NEWMAT::Matrix m(3,3); + double Cosine = cos(angle*RAD_PER_DEG); + double Sine = sin(angle*RAD_PER_DEG); + + if(orientationMode == OSSIM_RIGHT_HANDED) + { + m[0][0] = Cosine; + m[0][1] = 0.0; + m[0][2] = -Sine; + + m[1][0] = 0.0; + m[1][1] = 1.0; + m[1][2] = 0.0; + + m[2][0] = Sine; + m[2][1] = 0.0; + m[2][2] = Cosine; + } + else + { + m[0][0] = Cosine; + m[0][1] = 0.0; + m[0][2] = Sine; + + m[1][0] = 0.0; + m[1][1] = 1.0; + m[1][2] = 0.0; + + m[2][0] = -Sine; + m[2][1] = 0.0; + m[2][2] = Cosine; + } + return m; +} + + +NEWMAT::Matrix ossimMatrix3x3::createRotationZMatrix(double angle, + ossimCoordSysOrientMode orientationMode) +{ + NEWMAT::Matrix m(3,3); + double Cosine = cos(angle*RAD_PER_DEG); + double Sine = sin(angle*RAD_PER_DEG); + + if(orientationMode == OSSIM_RIGHT_HANDED) + { + m[0][0] = Cosine; + m[0][1] = Sine; + m[0][2] = 0.0; + + m[1][0] = -Sine; + m[1][1] = Cosine; + m[1][2] = 0.0; + + m[2][0] = 0.0; + m[2][1] = 0.0; + m[2][2] = 1.0; + } + else + { + m[0][0] = Cosine; + m[0][1] = -Sine; + m[0][2] = 0.0; + + m[1][0] = Sine; + m[1][1] = Cosine; + m[1][2] = 0.0; + + m[2][0] = 0.0; + m[2][1] = 0.0; + m[2][2] = 1.0; + } + return m; +} + +NEWMAT::Matrix ossimMatrix3x3::createScaleMatrix(double x, double y, double z) +{ + NEWMAT::Matrix m = createIdentity(); + + m[0][0] = x; + m[1][1] = y; + m[2][2] = z; + + return m; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimMatrix3x3.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimMatrix3x3.h new file mode 100644 index 0000000000..9c6c023dd7 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimMatrix3x3.h @@ -0,0 +1,96 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Helper class for using NEWMAT::Matrix's. +// +//******************************************************************* +// $Id: ossimMatrix3x3.h,v 1.14 2005/09/06 16:23:41 gpotts Exp $ + +#ifndef ossimMatrix3x3_HEADER +#define ossimMatrix3x3_HEADER + +#include <iostream> + +#include "matrix/newmat.h" +#include "matrix/newmatio.h" +#include "base/common/ossimConstants.h" + +class OSSIMDLLEXPORT ossimColumnVector3d; + +class OSSIMDLLEXPORT ossimMatrix3x3 +{ + public: + + + /*! + * Uses the matrix package to compute the eigenvalues for this + * matrix + */ + ossimColumnVector3d getEigenValues(const NEWMAT::Matrix& rhs); + + /*! + * Returns a blank 3x3 matrix. + */ + static NEWMAT::Matrix create(); + + /*! + * Returns a copy of "m". + * Note: + * If "m" is not a 3x3 that's an error and a blank matrix is returned. + */ + static NEWMAT::Matrix create(const NEWMAT::Matrix& m); + + /*! + * Create a 3x3 with assigned values. + */ + static NEWMAT::Matrix create(double v00, double v01, double v02, + double v10, double v11, double v12, + double v20, double v21, double v22); + + static NEWMAT::Matrix createIdentity(); + + static NEWMAT::Matrix createZero(); + static NEWMAT::Matrix createRotationMatrix(double angleX, + double angleY, + double angleZ, + ossimCoordSysOrientMode orientationMode=OSSIM_RIGHT_HANDED); + static NEWMAT::Matrix createRotationXMatrix(double angle, + ossimCoordSysOrientMode orientationMode=OSSIM_RIGHT_HANDED); + static NEWMAT::Matrix createRotationYMatrix(double angle, + ossimCoordSysOrientMode orientationMode=OSSIM_RIGHT_HANDED); + static NEWMAT::Matrix createRotationZMatrix(double angle, + ossimCoordSysOrientMode orientationMode=OSSIM_RIGHT_HANDED); + + static NEWMAT::Matrix createScaleMatrix(double X, double Y, double Z); + + static NEWMAT::Matrix createTranslationMatrix(double dx,double dy); + +protected: + ossimMatrix3x3(){} // To squash un-warranted compiler warnings... + +private: + ossimMatrix3x3(const ossimMatrix3x3& rhs){} + const ossimMatrix3x3& operator=(const ossimMatrix3x3& rhs){ return rhs; } + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimMatrix4x4.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimMatrix4x4.cpp new file mode 100644 index 0000000000..16ea57bcb9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimMatrix4x4.cpp @@ -0,0 +1,298 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Contains class declaration for locpt. This uses geotrans +// local cartesian implementation. +//******************************************************************* +// $Id: ossimMatrix4x4.cpp,v 1.6 2005/09/06 16:23:41 gpotts Exp $ + +#include "ossimMatrix4x4.h" +#include "matrix/newmatap.h" +#include "base/common/ossimConstants.h" + +ossimMatrix4x4::ossimMatrix4x4(const NEWMAT::Matrix& m) + :theData(4,4) +{ + if((m.Nrows() == 4) && + (m.Ncols() == 4)) + { + theData = m; + } + else if((m.Nrows()==3)&& + (m.Ncols()==3)) + { + theData[0][0] = m[0][0]; + theData[0][1] = m[0][1]; + theData[0][2] = m[0][2]; + theData[0][3] = 0.0; + theData[1][0] = m[1][0]; + theData[1][1] = m[1][1]; + theData[1][2] = m[1][2]; + theData[1][3] = 0.0; + theData[2][0] = m[2][0]; + theData[2][1] = m[2][1]; + theData[2][2] = m[2][2]; + theData[2][3] = 0.0; + theData[3][0] = 0.0; + theData[3][1] = 0.0; + theData[3][2] = 0.0; + theData[3][3] = 1.0; + } + else + { + theData[0][0] = 1.0; + theData[0][1] = 0.0; + theData[0][2] = 0.0; + theData[0][3] = 0.0; + + theData[1][0] = 0.0; + theData[1][1] = 1.0; + theData[1][2] = 0.0; + theData[1][3] = 0.0; + + theData[2][0] = 0.0; + theData[2][1] = 0.0; + theData[2][2] = 1.0; + theData[2][3] = 0.0; + + theData[3][0] = 0.0; + theData[3][1] = 0.0; + theData[3][2] = 0.0; + theData[3][3] = 1.0; + } +} + +ossimMatrix4x4::ossimMatrix4x4() + :theData(4, 4) +{ + theData[0][0] = 1.0; + theData[0][1] = 0.0; + theData[0][2] = 0.0; + theData[0][3] = 0.0; + + theData[1][0] = 0.0; + theData[1][1] = 1.0; + theData[1][2] = 0.0; + theData[1][3] = 0.0; + + theData[2][0] = 0.0; + theData[2][1] = 0.0; + theData[2][2] = 1.0; + theData[2][3] = 0.0; + + theData[3][0] = 0.0; + theData[3][1] = 0.0; + theData[3][2] = 0.0; + theData[3][3] = 1.0; +} + +ossimMatrix4x4::ossimMatrix4x4(double v00, double v01, double v02, double v03, + double v10, double v11, double v12, double v13, + double v20, double v21, double v22, double v23, + double v30, double v31, double v32, double v33) + :theData(4, 4) +{ + theData[0][0] = v00; + theData[0][1] = v01; + theData[0][2] = v02; + theData[0][3] = v03; + + theData[1][0] = v10; + theData[1][1] = v11; + theData[1][2] = v12; + theData[1][3] = v13; + + theData[2][0] = v20; + theData[2][1] = v21; + theData[2][2] = v22; + theData[2][3] = v23; + + theData[3][0] = v30; + theData[3][1] = v31; + theData[3][2] = v32; + theData[3][3] = v33; +} + +ossimColumnVector3d ossimMatrix4x4::getEigenValues()const +{ + NEWMAT::DiagonalMatrix d; + NEWMAT::SymmetricMatrix s; + + s << theData; + + EigenValues(s, d); + + return ossimColumnVector3d(d[0], d[1], d[2]); +} + +NEWMAT::Matrix ossimMatrix4x4::createIdentity() +{ + ossimMatrix4x4 m(1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0); + + return m.getData(); +} + +NEWMAT::Matrix ossimMatrix4x4::createRotateOnly(const ossimMatrix4x4 &aMatrix) +{ + ossimMatrix4x4 m = aMatrix; + + m.theData[0][3] = 0; + m.theData[1][3] = 0; + m.theData[2][3] = 0; + m.theData[3][3] = 1.0; + + m.theData[3][0] = 0.0; + m.theData[3][1] = 0.0; + m.theData[3][2] = 0.0; + m.theData[3][3] = 1.0; + + return m.getData(); +} + +NEWMAT::Matrix ossimMatrix4x4::createZero() +{ + ossimMatrix4x4 m; + + m.getData() = 0.0; + + return m.getData(); +} + +NEWMAT::Matrix ossimMatrix4x4::createTranslationMatrix(double x, + double y, + double z) +{ + ossimMatrix4x4 m(1.0, 0.0, 0.0, x, + 0.0, 1.0, 0.0, y, + 0.0, 0.0, 1.0, z, + 0.0, 0.0, 0.0, 1.0); + + return m.getData(); +} + +NEWMAT::Matrix ossimMatrix4x4::createRotationMatrix(double angleX, + double angleY, + double angleZ, + ossimCoordSysOrientMode orientationMode) +{ + return (createRotationZMatrix(angleZ, + orientationMode)* + createRotationYMatrix(angleY, + orientationMode)* + createRotationXMatrix(angleX, + orientationMode)); +} + +NEWMAT::Matrix ossimMatrix4x4::createRotationXMatrix(double angle, + ossimCoordSysOrientMode orientationMode) +{ + NEWMAT::Matrix m(4,4); + + double Cosine = cos(angle*RAD_PER_DEG); + double Sine = sin(angle*RAD_PER_DEG); + + if(orientationMode == OSSIM_RIGHT_HANDED) + { + m << 1.0 << 0.0 << 0.0 << 0.0 + << 0.0 << Cosine << Sine << 0.0 + << 0.0 << -Sine << Cosine << 0.0 + << 0.0 << 0.0 << 0.0 << 1.0; + } + else + { + m << 1.0 << 0.0 << 0.0 << 0.0 + << 0.0 << Cosine << -Sine << 0.0 + << 0.0 << Sine << Cosine << 0.0 + << 0.0 << 0.0 << 0.0 << 1.0; + } + + return m; +} + +NEWMAT::Matrix ossimMatrix4x4::createRotationYMatrix(double angle, + ossimCoordSysOrientMode orientationMode) +{ + NEWMAT::Matrix m(4,4); + + double Cosine = cos(angle*RAD_PER_DEG); + double Sine = sin(angle*RAD_PER_DEG); + + if(orientationMode == OSSIM_RIGHT_HANDED) + { + m << Cosine << 0.0 << -Sine << 0.0 + << 0.0 << 1.0 << 0.0 << 0.0 + << Sine << 0.0 << Cosine << 0.0 + << 0.0 << 0.0 << 0.0 << 1.0; + } + else + { + m << Cosine << 0.0 << Sine << 0.0 + << 0.0 << 1.0 << 0.0 << 0.0 + << -Sine << 0.0 << Cosine << 0.0 + << 0.0 << 0.0 << 0.0 << 1.0; + } + + return m; +} + + +NEWMAT::Matrix ossimMatrix4x4::createRotationZMatrix(double angle, + ossimCoordSysOrientMode orientationMode) +{ + NEWMAT::Matrix m(4,4); + + double Cosine = cos(angle*RAD_PER_DEG); + double Sine = sin(angle*RAD_PER_DEG); + + if(orientationMode == OSSIM_RIGHT_HANDED) + { + m << Cosine << Sine << 0.0 << 0.0 + << -Sine << Cosine << 0.0 << 0.0 + << 0.0 << 0.0 << 1.0 << 0.0 + << 0.0 << 0.0 << 0.0 << 1.0; + } + else + { + m << Cosine << -Sine << 0.0 << 0.0 + << Sine << Cosine << 0.0 << 0.0 + << 0.0 << 0.0 << 1.0 << 0.0 + << 0.0 << 0.0 << 0.0 << 1.0; + } + + return m; +} + + +NEWMAT::Matrix ossimMatrix4x4::createScaleMatrix(double x, double y, double z) +{ + NEWMAT::Matrix m(4, 4); + + m << x << 0.0 << 0.0 << 0.0 + << 0.0 << y << 0.0 << 0.0 + << 0.0 << 0.0 << z << 0.0 + << 0.0 << 0.0 << 0.0 << 1.0; + + return m; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimMatrix4x4.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimMatrix4x4.h new file mode 100644 index 0000000000..9c4a48e708 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimMatrix4x4.h @@ -0,0 +1,283 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimMatrix4x4.h,v 1.10 2005/09/06 16:23:41 gpotts Exp $ + +#ifndef ossimMatrix4x4_HEADER +#define ossimMatrix4x4_HEADER +#include <iostream> +#include "matrix/newmat.h" +#include "matrix/newmatio.h" +#include "ossimColumnVector4d.h" +#include "ossimColumnVector3d.h" + +class OSSIMDLLEXPORT ossimMatrix4x4 +{ + public: + friend std::ostream& operator<<(std::ostream& out, + const ossimMatrix4x4& data) + { + return out << data.getData(); + } + ossimMatrix4x4(); + ossimMatrix4x4(const NEWMAT::Matrix& m); + ossimMatrix4x4(double v00, double v01, double v02, double v03, + double v10, double v11, double v12, double v13, + double v20, double v21, double v22, double v23, + double v30, double v31, double v32, double v33); + ossimMatrix4x4(const ossimMatrix4x4& rhs) + :theData(4,4) + { + theData[0][0] = rhs.theData[0][0]; + theData[0][1] = rhs.theData[0][1]; + theData[0][2] = rhs.theData[0][2]; + theData[0][3] = rhs.theData[0][3]; + theData[1][0] = rhs.theData[1][0]; + theData[1][1] = rhs.theData[1][1]; + theData[1][2] = rhs.theData[1][2]; + theData[1][3] = rhs.theData[1][3]; + theData[2][0] = rhs.theData[2][0]; + theData[2][1] = rhs.theData[2][1]; + theData[2][2] = rhs.theData[2][2]; + theData[2][3] = rhs.theData[2][3]; + theData[3][0] = rhs.theData[3][0]; + theData[3][1] = rhs.theData[3][1]; + theData[3][2] = rhs.theData[3][2]; + theData[3][3] = rhs.theData[3][3]; + } + ossimMatrix4x4 operator+ (const ossimMatrix4x4& rhs)const + { + return ossimMatrix4x4(theData[0][0] + rhs.theData[0][0], theData[0][1] + rhs.theData[0][1], theData[0][2] + rhs.theData[0][2], theData[0][3] + rhs.theData[0][3], + theData[1][0] + rhs.theData[1][0], theData[1][1] + rhs.theData[1][1], theData[1][2] + rhs.theData[1][2], theData[1][3] + rhs.theData[1][3], + theData[2][0] + rhs.theData[2][0], theData[2][1] + rhs.theData[2][1], theData[2][2] + rhs.theData[2][2], theData[2][3] + rhs.theData[2][3], + theData[3][0] + rhs.theData[3][0], theData[3][1] + rhs.theData[3][1], theData[3][2] + rhs.theData[3][2], theData[3][3] + rhs.theData[3][3]); + } + ossimMatrix4x4 operator- (const ossimMatrix4x4& rhs)const + { + return ossimMatrix4x4(theData[0][0] - rhs.theData[0][0], theData[0][1] - rhs.theData[0][1], theData[0][2] - rhs.theData[0][2], theData[0][3] - rhs.theData[0][3], + theData[1][0] - rhs.theData[1][0], theData[1][1] - rhs.theData[1][1], theData[1][2] - rhs.theData[1][2], theData[1][3] - rhs.theData[1][3], + theData[2][0] - rhs.theData[2][0], theData[2][1] - rhs.theData[2][1], theData[2][2] - rhs.theData[2][2], theData[2][3] - rhs.theData[2][3], + theData[3][0] - rhs.theData[3][0], theData[3][1] - rhs.theData[3][1], theData[3][2] - rhs.theData[3][2], theData[3][3] - rhs.theData[3][3]); + } + friend ossimColumnVector4d operator * (const ossimMatrix4x4& lhs, const ossimColumnVector4d& rhs) + { + return ossimColumnVector4d( (lhs.theData[0][0]*rhs[0] + lhs.theData[0][1]*rhs[1] + lhs.theData[0][2]*rhs[2] + lhs.theData[0][3]*rhs[3]), + (lhs.theData[1][0]*rhs[0] + lhs.theData[1][1]*rhs[1] + lhs.theData[1][2]*rhs[2] + lhs.theData[1][3]*rhs[3]), + (lhs.theData[2][0]*rhs[0] + lhs.theData[2][1]*rhs[1] + lhs.theData[2][2]*rhs[2] + lhs.theData[2][3]*rhs[3]), + (lhs.theData[3][0]*rhs[0] + lhs.theData[3][1]*rhs[1] + lhs.theData[3][2]*rhs[2] + lhs.theData[3][3]*rhs[3])); + + } + friend ossimColumnVector3d operator * (const ossimMatrix4x4& lhs, const ossimColumnVector3d& rhs) + { + // assume the 4 coordinate (homogeneous coord) of the 3d vector is 1 + return ossimColumnVector3d( (lhs.theData[0][0]*rhs[0] + lhs.theData[0][1]*rhs[1] + lhs.theData[0][2]*rhs[2] + lhs.theData[0][3]), + (lhs.theData[1][0]*rhs[0] + lhs.theData[1][1]*rhs[1] + lhs.theData[1][2]*rhs[2] + lhs.theData[1][3]), + (lhs.theData[2][0]*rhs[0] + lhs.theData[2][1]*rhs[1] + lhs.theData[2][2]*rhs[2] + lhs.theData[2][3])); + } + ossimColumnVector4d rotateOnly(const ossimColumnVector4d& rhs)const + { + // multiply only by the 3x3 submatrix. + return ossimColumnVector4d( (theData[0][0]*rhs[0] + theData[0][1]*rhs[1] + theData[0][2]*rhs[2]), + (theData[1][0]*rhs[0] + theData[1][1]*rhs[1] + theData[1][2]*rhs[2]), + (theData[2][0]*rhs[0] + theData[2][1]*rhs[1] + theData[2][2]*rhs[2])); + } + ossimColumnVector3d rotateOnly(const ossimColumnVector3d& rhs)const + { + // assume the 4 coordinate (homogeneous coord) of the 3d vector is 1 + return ossimColumnVector3d( (theData[0][0]*rhs[0] + theData[0][1]*rhs[1] + theData[0][2]*rhs[2]), + (theData[1][0]*rhs[0] + theData[1][1]*rhs[1] + theData[1][2]*rhs[2]), + (theData[2][0]*rhs[0] + theData[2][1]*rhs[1] + theData[2][2]*rhs[2])); + } + ossimMatrix4x4 operator*(double scalar)const + { + return ossimMatrix4x4(theData[0][0]*scalar, theData[0][1]*scalar, theData[0][2]*scalar, theData[0][3]*scalar, + theData[1][0]*scalar, theData[1][1]*scalar, theData[1][2]*scalar, theData[1][3]*scalar, + theData[2][0]*scalar, theData[2][1]*scalar, theData[2][2]*scalar, theData[2][3]*scalar, + theData[0][0]*scalar, theData[0][1]*scalar, theData[0][2]*scalar, theData[0][3]*scalar); + + } + ossimMatrix4x4 operator*(const ossimMatrix4x4& rhs)const + { + ossimMatrix4x4 m; + + // element 0,0 is first row time first column + m.theData[0][0] = (theData[0][0]*rhs.theData[0][0] + + theData[0][1]*rhs.theData[1][0] + + theData[0][2]*rhs.theData[2][0] + + theData[0][3]*rhs.theData[3][0]); + + // element 0, 1 is first row second column + m.theData[0][1] = (theData[0][0]*rhs.theData[0][1] + + theData[0][1]*rhs.theData[1][1] + + theData[0][2]*rhs.theData[2][1] + + theData[0][3]*rhs.theData[3][1]); + + // element 0, 2 is first row third column + m.theData[0][2] = (theData[0][0]*rhs.theData[0][2] + + theData[0][1]*rhs.theData[1][2] + + theData[0][2]*rhs.theData[2][2] + + theData[0][3]*rhs.theData[3][2]); + + // element 0, 3 is first row fourth column + m.theData[0][3] = (theData[0][0]*rhs.theData[0][3] + + theData[0][1]*rhs.theData[1][3] + + theData[0][2]*rhs.theData[2][3] + + theData[0][3]*rhs.theData[3][3]); + + // element 1, 0 is second row first column + m.theData[1][0] = (theData[1][0]*rhs.theData[0][0] + + theData[1][1]*rhs.theData[1][0] + + theData[1][2]*rhs.theData[2][0] + + theData[1][3]*rhs.theData[3][0]); + + // element 1, 1 is second row second column + m.theData[1][1] = (theData[1][0]*rhs.theData[0][1] + + theData[1][1]*rhs.theData[1][1] + + theData[1][2]*rhs.theData[2][1] + + theData[1][3]*rhs.theData[3][1]); + + // element 1, 2 is second row third column + m.theData[1][2] = (theData[1][0]*rhs.theData[0][2] + + theData[1][1]*rhs.theData[1][2] + + theData[1][2]*rhs.theData[2][2] + + theData[1][3]*rhs.theData[3][2]); + + // element 1, 3 is second row fourth column + m.theData[1][3] = (theData[1][0]*rhs.theData[0][3] + + theData[1][1]*rhs.theData[1][3] + + theData[1][2]*rhs.theData[2][3] + + theData[1][3]*rhs.theData[3][3]); + + // element 2, 0 is third row first column + m.theData[2][0] = (theData[2][0]*rhs.theData[0][0] + + theData[2][1]*rhs.theData[1][0] + + theData[2][2]*rhs.theData[2][0] + + theData[2][3]*rhs.theData[3][0]); + + // element 2, 1 is third row second column + m.theData[2][1] = (theData[2][0]*rhs.theData[0][1] + + theData[2][1]*rhs.theData[1][1] + + theData[2][2]*rhs.theData[2][1] + + theData[2][3]*rhs.theData[3][1]); + + // element 2, 2 is third row third column + m.theData[2][2] = (theData[2][0]*rhs.theData[0][2] + + theData[2][1]*rhs.theData[1][2] + + theData[2][2]*rhs.theData[2][2] + + theData[2][3]*rhs.theData[3][2]); + + // element 2, 3 is third row fourth column + m.theData[2][3] = (theData[2][0]*rhs.theData[0][3] + + theData[2][1]*rhs.theData[1][3] + + theData[2][2]*rhs.theData[2][3] + + theData[2][3]*rhs.theData[3][3]); + + // element 3, 0 is fourth row first column + m.theData[3][0] = (theData[3][0]*rhs.theData[0][0] + + theData[3][1]*rhs.theData[1][0] + + theData[3][2]*rhs.theData[2][0] + + theData[3][3]*rhs.theData[3][0]); + + // element 3, 1 is fourth row second column + m.theData[3][1] = (theData[3][0]*rhs.theData[0][1] + + theData[3][1]*rhs.theData[1][1] + + theData[3][2]*rhs.theData[2][1] + + theData[3][3]*rhs.theData[3][1]); + + // element 3, 2 is fourth row third column + m.theData[3][2] = (theData[3][0]*rhs.theData[0][2] + + theData[3][1]*rhs.theData[1][2] + + theData[3][2]*rhs.theData[2][2] + + theData[3][3]*rhs.theData[3][2]); + + // element 3, 3 is fourth row fourth column + m.theData[3][3] = (theData[3][0]*rhs.theData[0][3] + + theData[3][1]*rhs.theData[1][3] + + theData[3][2]*rhs.theData[2][3] + + theData[3][3]*rhs.theData[3][3]); + + return m; + } + + /*! + * uses the matrix package to compute the inverse + */ + ossimMatrix4x4& i() + { + theData = theData.i(); + + return *this; + } + + /*! + * Uses the matrix package to compute the transpose. + */ + ossimMatrix4x4& t() + { + theData = theData.t(); + + return *this; + } + + /*! + * uses the matrix package to compute the determinant + */ + double getDeterminant()const + { + return theData.Determinant(); + } + + /*! + * Uses the matrix package to compute the eigenvalues for this + * matrix + */ + ossimColumnVector3d getEigenValues()const; + + static NEWMAT::Matrix createIdentity(); + static NEWMAT::Matrix createRotateOnly(const ossimMatrix4x4& aMatrix); + + static NEWMAT::Matrix createZero(); + static NEWMAT::Matrix createTranslationMatrix(double x, + double y, + double z); + static NEWMAT::Matrix createRotationMatrix(double angleX, + double angleY, + double angleZ, + ossimCoordSysOrientMode orientationMode=OSSIM_RIGHT_HANDED); + static NEWMAT::Matrix createRotationXMatrix(double angle, + ossimCoordSysOrientMode orientationMode=OSSIM_RIGHT_HANDED); + static NEWMAT::Matrix createRotationYMatrix(double angle, + ossimCoordSysOrientMode orientationMode=OSSIM_RIGHT_HANDED); + static NEWMAT::Matrix createRotationZMatrix(double angle, + ossimCoordSysOrientMode orientationMode=OSSIM_RIGHT_HANDED); + + static NEWMAT::Matrix createScaleMatrix(double X, double Y, double Z); + + const NEWMAT::Matrix& getData()const{return theData;} + NEWMAT::Matrix& getData(){return theData;} + +private: + NEWMAT::Matrix theData; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimMultiBandHistogram.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimMultiBandHistogram.cpp new file mode 100644 index 0000000000..d6e926dfef --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimMultiBandHistogram.cpp @@ -0,0 +1,400 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimMultiBandHistogram.cpp,v 1.14 2003/09/09 18:33:57 dburken Exp $ +#include "ossimMultiBandHistogram.h" +#include "ossimHistogram.h" +#include "ossimKeywordlist.h" + +#include <fstream> +using namespace std; + +ossimMultiBandHistogram::ossimMultiBandHistogram() +{ +} + +ossimMultiBandHistogram::~ossimMultiBandHistogram() +{ + deleteHistograms(); +} + +ossimMultiBandHistogram::ossimMultiBandHistogram(const ossimMultiBandHistogram& rhs) +{ + theHistogramList.resize(rhs.theHistogramList.size()); + + for(ossim_uint32 i = 0; i < theHistogramList.size(); ++i) + { + theHistogramList[i] = rhs.theHistogramList[i]? + new ossimHistogram(*rhs.theHistogramList[i]): + (ossimHistogram*)NULL; + } +} + +ossimMultiBandHistogram::ossimMultiBandHistogram(long numberOfBands, + long numberOfBuckets, + float minValue, + float maxValue) +{ + if(numberOfBands > 0) + { + create(numberOfBands, numberOfBuckets, minValue, maxValue); + } +} + +void ossimMultiBandHistogram::create(long numberOfBands, + long numberOfBuckets, + float minValue, + float maxValue) +{ + // make sure we clear our internal lists before + // we start. + // + deleteHistograms(); + + if(numberOfBands > 0) + { + numberOfBuckets = numberOfBuckets>0?numberOfBuckets:1; + + for(long bands = 0; bands < numberOfBands; ++bands) + { + theHistogramList.push_back(new ossimHistogram(numberOfBuckets, + minValue, + maxValue)); + } + } +} + +void ossimMultiBandHistogram::create(long numberOfBands) +{ + deleteHistograms(); + for(long bands = 0; bands < numberOfBands; ++bands) + { + theHistogramList.push_back(new ossimHistogram); + } +} + +ossim_uint32 ossimMultiBandHistogram::getNumberOfBands() const +{ + return theHistogramList.size(); +} + +ossimHistogram* ossimMultiBandHistogram::getHistogram(long band) +{ + if((band >=0) && (band < (long)theHistogramList.size())) + { + return theHistogramList[band]; + } + + return NULL; +} + +void ossimMultiBandHistogram::setBinCount(double binNumber, double count) +{ + if(theHistogramList.size() > 0) + { + for(long idx = 0; idx < (long)theHistogramList.size(); ++idx) + { + if(theHistogramList[idx]) + { + theHistogramList[idx]->SetCount(binNumber, count); + } + } + } +} + +ossimMultiBandHistogram* ossimMultiBandHistogram::createAccumulationLessThanEqual()const +{ + ossimMultiBandHistogram* result = NULL; + + if(theHistogramList.size() > 0) + { + result = new ossimMultiBandHistogram; + result->theHistogramList.resize(theHistogramList.size()); + + for(long index = 0; index < (long)theHistogramList.size(); ++index) + { + if(theHistogramList[index]) + { + result->theHistogramList[index] = theHistogramList[index]->CumulativeLessThanEqual(); + } + else + { + result->theHistogramList[index] = NULL; + } + } + } + + return result; +} + +ossimMultiBandHistogram* ossimMultiBandHistogram::createAccumulationGreaterThanEqual()const +{ + ossimMultiBandHistogram* result = NULL; + + if(theHistogramList.size() > 0) + { + result = new ossimMultiBandHistogram; + + for(long index = 0; index < (long)theHistogramList.size(); ++index) + { + if(theHistogramList[index]) + { + result->theHistogramList[index] = theHistogramList[index]->CumulativeGreaterThanEqual(); + } + else + { + result->theHistogramList[index] = NULL; + } + } + } + + return result; +} + +void ossimMultiBandHistogram::deleteHistograms() +{ + for(long index = 0; index < (long)theHistogramList.size(); ++index) + { + if(theHistogramList[index]) + { + delete theHistogramList[index]; + theHistogramList[index] = NULL; + } + } + + theHistogramList.clear(); +} + + +bool ossimMultiBandHistogram::importHistogram(istream& in) +{ + ossimProprietaryHeaderInformation header; + deleteHistograms(); + + if(header.parseStream(in)) + { + long numberOfBands = header.getNumberOfBands(); + + if(numberOfBands) + { + theHistogramList.resize(numberOfBands); + + for(long counter = 0; counter < (long)theHistogramList.size(); ++counter) + { + theHistogramList[counter] = NULL; + } + ossimString bandBuffer; + ossimString buffer; + + for(long index = 0; index < numberOfBands; ++index) + { + getline(in, buffer); + if(buffer.find("Band") != string::npos) + { + unsigned long offset = buffer.find(":"); + if(offset != string::npos) + { + bandBuffer = buffer.substr(offset+1); + } + else + { + deleteHistograms(); + return false; + } + } + else + { + deleteHistograms(); + return false; + } + long bandIndex = bandBuffer.toLong(); + + if(bandIndex < (long)theHistogramList.size()) + { + if(!theHistogramList[bandIndex]) + { + ossimHistogram* histogram = new ossimHistogram; + if(histogram->importHistogram(in)) + { + theHistogramList[bandIndex] = histogram; + } + else + { + delete histogram; + histogram = NULL; + + deleteHistograms(); + return false; + } + } + } + else + { + deleteHistograms(); + return false; + } + } + } + else + { + return false; + } + } + return true; +} + +bool ossimMultiBandHistogram::importHistogram(const ossimFilename& file) +{ + if(file.exists()) + { + ifstream input(file.c_str()); + + return importHistogram(input); + } + + return false; +} + +bool ossimMultiBandHistogram::ossimProprietaryHeaderInformation::parseStream(istream& in) +{ + ossimString inputLine; + + getline(in, inputLine); + if(inputLine.find("File Type") != string::npos) + { + unsigned long index = inputLine.find(":"); + if(index != string::npos) + { + theFileType = inputLine.substr(index+1); + theFileType = theFileType.trim(); + } + else + { + return false; + } + + } + else + { + return false; + } + + getline(in, inputLine); + if(inputLine.find("Version") != string::npos) + { + unsigned long index = inputLine.find(":"); + if(index != string::npos) + { + theVersion = inputLine.substr(index+1); + theVersion = theVersion.trim(); + } + else + { + return false; + } + } + else + { + return false; + } + + getline(in, inputLine); + if(inputLine.find("Number of Bands") != string::npos) + { + unsigned long index = inputLine.find(":"); + if(index != string::npos) + { + theNumberOfBands = inputLine.substr(index+1); + theNumberOfBands = theNumberOfBands.trim(); + } + else + { + return false; + } + } + else + { + return false; + } + + return true; +} + +bool ossimMultiBandHistogram::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + "type", + "ossimMultiBandHistogram", + true); + kwl.add(prefix, + "number_of_bands", + theHistogramList.size(), + true); + + for(ossim_uint32 index = 0; index < theHistogramList.size(); ++index) + { + ossimString band = ossimString(prefix) + "band"; + band += (ossimString::toString(index) + "."); + if(theHistogramList[index]) + { + ossimString newPrefix = (ossimString(prefix) + ossimString::toString(index) + "."); + + theHistogramList[index]->saveState(kwl, + band.c_str()); + } + } + + return true; +} + +bool ossimMultiBandHistogram::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + deleteHistograms(); + const char* number_of_bands = kwl.find(prefix, "number_of_bands"); + if(number_of_bands) + { + ossim_uint32 numberOfBands = ossimString(number_of_bands).toUInt32(); + + if(numberOfBands>0) + { + ossimString newPrefix; + for(ossim_uint32 index = 0; index < numberOfBands; ++index) + { + ossimHistogram* histo = new ossimHistogram; + + newPrefix = prefix; + newPrefix += "band"; + newPrefix += ossimString::toString(index); + newPrefix += "."; + + histo->loadState(kwl, newPrefix.c_str()); + + theHistogramList.push_back(histo); + } + } + } + + return true; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimMultiBandHistogram.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimMultiBandHistogram.h new file mode 100644 index 0000000000..17cbfdae08 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimMultiBandHistogram.h @@ -0,0 +1,101 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimMultiBandHistogram.h,v 1.11 2003/08/22 20:50:46 dburken Exp $ +#ifndef ossimMultiBandHistogram_HEADER +#define ossimMultiBandHistogram_HEADER +#include <vector> +using namespace std; +#include "ossimFilename.h" + +class OSSIMDLLEXPORT ossimHistogram; +class OSSIMDLLEXPORT ossimKeywordlist; + +class OSSIMDLLEXPORT ossimMultiBandHistogram +{ +public: + ossimMultiBandHistogram(); + ossimMultiBandHistogram(const ossimMultiBandHistogram& rhs); + ossimMultiBandHistogram(long numberOfBands, + long numberOfBuckets, + float minValue, + float maxValue); + virtual ~ossimMultiBandHistogram(); + + void create(long numberOfBands, + long numberOfBuckets, + float minValue, + float maxValue); + + ossim_uint32 getNumberOfBands() const; + + void create(long numberOfBands); + void setBinCount(double binNumber, double count); + ossimHistogram* getHistogram(long band); + + ossimMultiBandHistogram* createAccumulationLessThanEqual()const; + ossimMultiBandHistogram* createAccumulationGreaterThanEqual()const; + /*! + * Imports a text file that has histogram data + */ + virtual bool importHistogram(const ossimFilename& inputFile); + virtual bool importHistogram(istream& in); + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix = 0); + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix = 0)const; +protected: + class ossimProprietaryHeaderInformation + { + public: + ossimProprietaryHeaderInformation(){clear();} + + bool parseStream(istream& in); + + ossim_uint32 getNumberOfBands() + { + return theNumberOfBands.toULong(); + } + void clear() + { + theFileType = ""; + theVersion = ""; + theNumberOfBands = ""; + } + ossimString theFileType; + ossimString theVersion; + ossimString theNumberOfBands; + + }; + /*! + * Holds the histograms for each band + */ + vector<ossimHistogram*> theHistogramList; + + void deleteHistograms(); + + bool parseProprietaryHistogram(istream& in); + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimMultiResLevelHistogram.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimMultiResLevelHistogram.cpp new file mode 100644 index 0000000000..fa0d6a8940 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimMultiResLevelHistogram.cpp @@ -0,0 +1,500 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimMultiResLevelHistogram.cpp,v 1.17 2003/09/09 18:33:57 dburken Exp $ +#include "ossimMultiResLevelHistogram.h" +#include "ossimMultiBandHistogram.h" +#include "ossimKeyword.h" +#include "ossimKeywordlist.h" +#include "base/common/ossimKeywordNames.h" +#include <fstream> +using namespace std; + +static const ossimKeyword NUMBER_OF_RES_LEVELS("number_of_res_levels", + ""); + +ossimMultiResLevelHistogram::ossimMultiResLevelHistogram() + : + theHistogramList(), + theHistogramFile() +{ +} + +ossimMultiResLevelHistogram::ossimMultiResLevelHistogram(long numberOfResLevels) + : + theHistogramList(), + theHistogramFile() +{ + create(numberOfResLevels); +} + +ossimMultiResLevelHistogram::ossimMultiResLevelHistogram(const ossimMultiResLevelHistogram& rhs) + : + theHistogramList(), + theHistogramFile() +{ + + create(rhs.getNumberOfResLevels()); + for(ossim_uint32 i = 0; i < theHistogramList.size(); ++i) + { + theHistogramList[0] = rhs.theHistogramList[i]? + new ossimMultiBandHistogram(*rhs.theHistogramList[i]): + (ossimMultiBandHistogram*)NULL; + } +} + +ossimMultiResLevelHistogram::~ossimMultiResLevelHistogram() +{ + deleteHistograms(); +} + +void ossimMultiResLevelHistogram::create(long numberOfResLevels) +{ + deleteHistograms(); + + for(long index = 0; index < numberOfResLevels; ++index) + { + theHistogramList.push_back(new ossimMultiBandHistogram); + } +} + +ossimMultiResLevelHistogram* ossimMultiResLevelHistogram::createAccumulationLessThanEqual()const +{ + ossimMultiResLevelHistogram* result = NULL; + + if(theHistogramList.size() > 0) + { + result = new ossimMultiResLevelHistogram(theHistogramList.size()); + + for(long index=0; index < (long) theHistogramList.size(); ++ index) + { + if(theHistogramList[index]) + { + ossimMultiBandHistogram* multiBandAccumulator = theHistogramList[index]->createAccumulationLessThanEqual(); + result->theHistogramList[index] = multiBandAccumulator; + } + else + { + // we will push on a null since someone could + // turn off a band. A null accumulation will + // indicate no histogram data. + // + result->theHistogramList[index] = NULL; + } + } + + if(result->theHistogramList.size() < 1) + { + delete result; + } + } + + return result; +} + +void ossimMultiResLevelHistogram::setBinCount(double binNumber, double count) +{ + if(theHistogramList.size() > 0) + { + for(long index=0; index < (long) theHistogramList.size(); ++ index) + { + if(theHistogramList[index]) + { + theHistogramList[index]->setBinCount(binNumber, count); + } + } + } +} + +ossimMultiResLevelHistogram* ossimMultiResLevelHistogram::createAccumulationGreaterThanEqual()const +{ + ossimMultiResLevelHistogram* result = NULL; + + if(theHistogramList.size() > 0) + { + result = new ossimMultiResLevelHistogram(theHistogramList.size()); + + for(long index=0; index < (long) theHistogramList.size(); ++ index) + { + if(theHistogramList[index]) + { + ossimMultiBandHistogram* multiBandAccumulator = theHistogramList[index]->createAccumulationGreaterThanEqual(); + result->theHistogramList[index]=multiBandAccumulator; + } + else + { + // we will push on a null since someone could + // turn off a band. A null accumulation will + // indicate no histogram data. + // + result->theHistogramList[index] = NULL; + } + } + + if(result->theHistogramList.size() < 1) + { + delete result; + } + } + + return result; +} + +void ossimMultiResLevelHistogram::addHistogram(ossimMultiBandHistogram* histo) +{ + theHistogramList.push_back(histo); +} + +ossimMultiBandHistogram* ossimMultiResLevelHistogram::addHistogram() +{ + ossimMultiBandHistogram* result = new ossimMultiBandHistogram; + theHistogramList.push_back(result); + return result; +} + +bool ossimMultiResLevelHistogram::setHistogram(ossimMultiBandHistogram* histo, long resLevel) +{ + if( (resLevel >= 0) && (resLevel < getNumberOfResLevels())) + { + if(theHistogramList[resLevel]) + { + delete theHistogramList[resLevel]; + } + theHistogramList[resLevel] = histo; + return true; + } + return false; +} + +void ossimMultiResLevelHistogram::deleteHistograms() +{ + for(long index = 0; index < (long)theHistogramList.size(); ++index) + { + if(theHistogramList[index]) + { + delete theHistogramList[index]; + theHistogramList[index] = NULL; + } + } + + theHistogramList.clear(); +} + +ossimHistogram* ossimMultiResLevelHistogram::getHistogram(long band, + long resLevel) +{ + ossimMultiBandHistogram* temp = getMultiBandHistogram(resLevel); + if(temp) + { + return temp->getHistogram(band); + } + return NULL; +} + +long ossimMultiResLevelHistogram::getNumberOfResLevels()const +{ + return (long)theHistogramList.size(); +} + +ossim_uint32 ossimMultiResLevelHistogram::getNumberOfBands(long resLevel) const +{ + const ossimMultiBandHistogram* h = getMultiBandHistogram(resLevel); + if (h) + { + return h->getNumberOfBands(); + } + + return 0; +} + +ossimMultiBandHistogram* ossimMultiResLevelHistogram::getMultiBandHistogram(long resLevel) const +{ + if((resLevel >=0) &&(resLevel < (long)theHistogramList.size())) + { + return theHistogramList[resLevel]; + } + + return NULL; +} + +bool ossimMultiResLevelHistogram::importHistogram(istream& in) +{ + ossimString buffer; + getline(in, buffer); + // check to see if it is a proprietary histogram file + // + if((buffer =="") || (buffer.c_str()[0] != 'F' || + buffer.c_str()[1] != 'i')) + { + in.seekg(0, ios::beg); + ossimKeywordlist kwl; + kwl.parseStream(in); + return loadState(kwl); + + } + ossimProprietaryHeaderInformation header; + in.seekg(0, ios::beg); + deleteHistograms(); + if(header.parseStream(in)) + { + long numberOfResLevels = header.getNumberOfResLevels(); + + if(numberOfResLevels) + { + theHistogramList.resize(numberOfResLevels); + + for(long counter = 0; counter < (long)theHistogramList.size(); ++counter) + { + theHistogramList[counter] = NULL; + } + ossimString reslevelBuffer; + ossimString buffer; + + for(long index = 0; index < numberOfResLevels; ++index) + { + getline(in, buffer); + if(buffer.find("RR Level") != string::npos) + { + unsigned long offset = buffer.find(":"); + if(offset != string::npos) + { + reslevelBuffer = buffer.substr(offset+1); + } + else + { + deleteHistograms(); + return false; + } + } + else + { + deleteHistograms(); + return false; + } + long resLevelIndex = reslevelBuffer.toLong(); + + if(resLevelIndex < (long)theHistogramList.size()) + { + if(!theHistogramList[resLevelIndex]) + { + ossimMultiBandHistogram* histogram = new ossimMultiBandHistogram; + if(histogram->importHistogram(in)) + { + theHistogramList[resLevelIndex] = histogram; + } + else + { + delete histogram; + histogram = NULL; + + deleteHistograms(); + return false; + } + } + } + else + { + deleteHistograms(); + return false; + } + ossimString skipDot; + getline(in, skipDot); + } + } + else + { + return false; + } + } + + return true; +} + +bool ossimMultiResLevelHistogram::importHistogram(const ossimFilename& file) +{ + if(file.exists()) + { + theHistogramFile = file; + + ifstream input(file.c_str()); + + return importHistogram(input); + } + + return false; +} + +bool ossimMultiResLevelHistogram::ossimProprietaryHeaderInformation::parseStream(istream& in) +{ + ossimString inputLine; + + getline(in, inputLine); + if(inputLine.find("File Type") != string::npos) + { + unsigned long index = inputLine.find(":"); + if(index != string::npos) + { + theFileType = inputLine.substr(index+1); + theFileType = theFileType.trim(); + } + else + { + return false; + } + + } + else + { + return false; + } + + getline(in, inputLine); + if(inputLine.find("Version") != string::npos) + { + unsigned long index = inputLine.find(":"); + if(index != string::npos) + { + theVersion = inputLine.substr(index+1); + theVersion = theVersion.trim(); + } + else + { + return false; + } + } + else + { + return false; + } + + getline(in, inputLine); + if(inputLine.find("Creator ID") != string::npos) + { + unsigned long index = inputLine.find(":"); + if(index != string::npos) + { + theCreatorId = inputLine.substr(index+1); + theCreatorId = theCreatorId.trim(); + } + else + { + return false; + } + } + else + { + return false; + } + + getline(in, inputLine); + if(inputLine.find("RR Levels") != string::npos) + { + unsigned long index = inputLine.find(":"); + if(index != string::npos) + { + theNumberOfResLevels = inputLine.substr(index+1); + theNumberOfResLevels = theNumberOfResLevels.trim(); + } + else + { + return false; + } + } + else + { + return false; + } + + return true; +} + +bool ossimMultiResLevelHistogram::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + bool result = true; + if(theHistogramList.size() > 0) + { + ossimString s1 = prefix; + kwl.add(prefix, + ossimKeywordNames::TYPE_KW, + "ossimMultiResLevelHistogram", + true); + kwl.add(prefix, + NUMBER_OF_RES_LEVELS.key(), + theHistogramList.size(), + true); + + for(ossim_uint32 index = 0; index < theHistogramList.size(); ++index) + { + ossimString rr_level = ossimString(prefix) + "rr_level"; + rr_level += ossimString::toString(index) + "."; + if(theHistogramList[index]) + { + result = theHistogramList[index]->saveState(kwl, rr_level.c_str()); + + if(!result) + { + return result; + } + } + } + } + + return result; +} + +bool ossimMultiResLevelHistogram::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + deleteHistograms(); + const char* number_of_res_levels = kwl.find(prefix, NUMBER_OF_RES_LEVELS.key()); + + if(number_of_res_levels) + { + ossim_uint32 numberOfResLevels = ossimString(number_of_res_levels).toUInt32(); + + if(numberOfResLevels) + { + ossimString newPrefix; + for(ossim_uint32 index = 0; index < numberOfResLevels; ++index) + { + ossimMultiBandHistogram* histo = new ossimMultiBandHistogram; + + newPrefix = prefix; + newPrefix += "rr_level"; + newPrefix += ossimString::toString(index); + newPrefix += "."; + + histo->loadState(kwl, newPrefix.c_str()); + + theHistogramList.push_back(histo); + } + } + } + return true; +} + +ossimFilename ossimMultiResLevelHistogram::getHistogramFile() const +{ + return theHistogramFile; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimMultiResLevelHistogram.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimMultiResLevelHistogram.h new file mode 100644 index 0000000000..4791c131dc --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimMultiResLevelHistogram.h @@ -0,0 +1,115 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimMultiResLevelHistogram.h,v 1.10 2003/09/03 14:19:30 dburken Exp $ +#ifndef ossimMultiResLevelHistogram_HEADER +#define ossimMultiResLevelHistogram_HEADER +#include <vector> +using namespace std; +#include "ossimFilename.h" +#include "ossimKeywordlist.h" + +class OSSIMDLLEXPORT ossimMultiBandHistogram; +class OSSIMDLLEXPORT ossimHistogram; + +class OSSIMDLLEXPORT ossimMultiResLevelHistogram +{ +public: + ossimMultiResLevelHistogram(); + ossimMultiResLevelHistogram(long numberOfResLevels); + ossimMultiResLevelHistogram(const ossimMultiResLevelHistogram& rhs); + + virtual ~ossimMultiResLevelHistogram(); + + ossimHistogram* getHistogram(long band, + long resLevel=0); + long getNumberOfResLevels()const; + ossim_uint32 getNumberOfBands(long resLevel=0) const; + void create(long numberOfResLevels); + ossimMultiBandHistogram* getMultiBandHistogram(long resLevel) const; + ossimMultiResLevelHistogram* createAccumulationLessThanEqual()const; + ossimMultiResLevelHistogram* createAccumulationGreaterThanEqual()const; + + void setBinCount(double binNumber, double count); + /*! + * Will append to the list the passed in histogram. + */ + virtual void addHistogram(ossimMultiBandHistogram* histo); + + /*! + * This will create and append a histogram to the + * list and return a pointer to the new histogram. + */ + virtual ossimMultiBandHistogram* addHistogram(); + + /*! + * Will set the histogram to the passed in res level. + * It will delete the histogram at the res level before + * setting the pointer to the passed in histogram. if + * the resLevel is out of range it will return false meaning + * it was unable to assign the pointer. + */ + virtual bool setHistogram(ossimMultiBandHistogram* histo, long resLevel); + + virtual ossimFilename getHistogramFile() const; + virtual bool importHistogram(const ossimFilename& inputFile); + virtual bool importHistogram(istream& in); + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + +protected: + class ossimProprietaryHeaderInformation + { + public: + ossimProprietaryHeaderInformation(){clear();} + + bool parseStream(istream& in); + + long getNumberOfResLevels() + { + return theNumberOfResLevels.toLong(); + } + void clear() + { + theFileType = ""; + theVersion = ""; + theCreatorId = ""; + theNumberOfResLevels = ""; + } + ossimString theFileType; + ossimString theVersion; + ossimString theCreatorId; + ossimString theNumberOfResLevels; + }; + + vector<ossimMultiBandHistogram*> theHistogramList; + ossimFilename theHistogramFile; + + void deleteHistograms(); + bool parseProprietaryHistogram(istream& in); +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimPolyArea2d.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimPolyArea2d.cpp new file mode 100644 index 0000000000..0786494ba3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimPolyArea2d.cpp @@ -0,0 +1,949 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimPolyArea2d.cpp,v 1.20 2005/09/30 19:56:45 gpotts Exp $ +#include <list> +#include <sstream> +using namespace std; + +#include <base/data_types/ossimPolyArea2d.h> +#include <base/common/ossimKeywordNames.h> + +ostream& operator<<(ostream& out, const ossimPolyArea2d& data) +{ + if(!data.thePolygon) + { + return out; + } + int cnt; + PLINE *cntr; + POLYAREA * curpa; + + cnt = 0, curpa = data.thePolygon; + do + { + cnt++; + } while ( (curpa = curpa->f) != data.thePolygon); + + curpa = data.thePolygon; + do + { + for ( cntr = curpa->contours, cnt = 0; cntr != NULL; cntr = cntr->next, cnt++ ) + {} + out << cnt << endl; + + for ( cntr = curpa->contours; cntr != NULL; cntr = cntr->next ) + { + VNODE *cur; + + out << cntr->Count << endl; + cur = &cntr->head; + do + { + out << cur->point[0] << " " << cur->point[1] << endl; + } while ( ( cur = cur->next ) != &cntr->head ); + } + }while ( (curpa = curpa->f) != data.thePolygon); + + return out; +} + + + +ossimPolyArea2d::ossimPolyArea2d() + :thePolygon(NULL) +{ +} + +ossimPolyArea2d::ossimPolyArea2d(POLYAREA* polygon, + bool copyPolygonFlag) + :thePolygon(NULL) +{ + if(copyPolygonFlag) + { + poly_Copy0(&thePolygon, polygon); + } + else + { + thePolygon = polygon; + } +} + +ossimPolyArea2d::ossimPolyArea2d(const ossimPolyArea2d& rhs) + :thePolygon(NULL) +{ + poly_Copy0(&thePolygon, rhs.thePolygon); +} + +ossimPolyArea2d::ossimPolyArea2d(const vector<ossimDpt>& polygon) + :thePolygon(NULL) +{ + if(polygon.size() > 0) + { + PLINE *poly = NULL; + Vector v; + v[0] = polygon[0].x; + v[1] = polygon[0].y; + v[2] = 0; + poly = poly_NewContour(v); + for(long index = 1; index < (long)polygon.size(); ++index) + { + + v[0] = polygon[index].x; + v[1] = polygon[index].y; + v[2] = 0.0; + + poly_InclVertex(poly->head.prev, + poly_CreateNode(v)); + + } + poly_PreContour(poly, TRUE); + + if ( (poly->Flags & PLF_ORIENT) != PLF_DIR) + { + poly_InvContour(poly); + } + thePolygon = poly_Create(); + poly_InclContour(thePolygon, poly); +// if(!poly_Valid(thePolygon)) +// { +// if(thePolygon) +// { +// poly_Free(&thePolygon); +// thePolygon = NULL; +// } +// } + } +} + +ossimPolyArea2d::ossimPolyArea2d(const vector<ossimGpt>& polygon) + :thePolygon(NULL) +{ + if(polygon.size() > 0) + { + PLINE *poly = NULL; + Vector v; + v[0] = polygon[0].lon; + v[1] = polygon[0].lat; + v[2] = 0; + poly = poly_NewContour(v); + for(long index = 1; index < (long)polygon.size(); ++index) + { + + v[0] = polygon[index].lon; + v[1] = polygon[index].lat; + v[2] = 0.0; + + poly_InclVertex(poly->head.prev, + poly_CreateNode(v)); + + } + poly_PreContour(poly, TRUE); + + if ( (poly->Flags & PLF_ORIENT) != PLF_DIR) + { + poly_InvContour(poly); + } + thePolygon = poly_Create(); + poly_InclContour(thePolygon, poly); +// if(!poly_Valid(thePolygon)) +// { +// if(thePolygon) +// { +// poly_Free(&thePolygon); +// thePolygon = NULL; +// } +// } + } +} + +ossimPolyArea2d::ossimPolyArea2d(const ossimDpt& p1, + const ossimDpt& p2, + const ossimDpt& p3, + const ossimDpt& p4) + :thePolygon(NULL) +{ + PLINE *poly = NULL; + Vector v; + v[0] = p1.x; + v[1] = p1.y; + v[2] = 0; + poly = poly_NewContour(v); + poly_InclVertex(poly->head.prev, + poly_CreateNode(v)); + v[0] = p2.x; + v[1] = p2.y; + v[2] = 0; + poly_InclVertex(poly->head.prev, + poly_CreateNode(v)); + v[0] = p3.x; + v[1] = p3.y; + v[2] = 0; + poly_InclVertex(poly->head.prev, + poly_CreateNode(v)); + v[0] = p4.x; + v[1] = p4.y; + v[2] = 0; + poly_InclVertex(poly->head.prev, + poly_CreateNode(v)); + + poly_PreContour(poly, TRUE); + + if ( (poly->Flags & PLF_ORIENT) != PLF_DIR) + { + poly_InvContour(poly); + } + thePolygon = poly_Create(); + poly_InclContour(thePolygon, poly); +// if(!poly_Valid(thePolygon)) +// { +// if(thePolygon) +// { +// poly_Free(&thePolygon); +// thePolygon = NULL; +// } +// } +} + + +ossimPolyArea2d::ossimPolyArea2d(ossimDpt* polygon, + long number) + :thePolygon(NULL) +{ + if(number > 0) + { + PLINE *poly = NULL; + Vector v; + v[0] = polygon[0].x; + v[1] = polygon[0].y; + v[2] = 0; + poly = poly_NewContour(v); + for(long index = 1; index < number; ++index) + { + + v[0] = polygon[index].x; + v[1] = polygon[index].y; + v[2] = 0.0; + + poly_InclVertex(poly->head.prev, + poly_CreateNode(v)); + + } + poly_PreContour(poly, TRUE); + + if ( (poly->Flags & PLF_ORIENT) != PLF_DIR) + { + poly_InvContour(poly); + } + thePolygon = poly_Create(); + poly_InclContour(thePolygon, poly); +// if(!poly_Valid(thePolygon)) +// { +// poly_Free(&thePolygon); +// thePolygon = NULL; +// } + } +} + +ossimPolyArea2d::ossimPolyArea2d(const ossimPolygon& polygon) + :thePolygon(NULL) +{ + if(polygon.getVertexCount() > 0) + { + PLINE *poly = NULL; + Vector v; + v[0] = polygon[0].x; + v[1] = polygon[0].y; + v[2] = 0; + poly = poly_NewContour(v); + for(long index = 1; index < (long)polygon.getVertexCount(); ++index) + { + + v[0] = polygon[index].x; + v[1] = polygon[index].y; + v[2] = 0.0; + + poly_InclVertex(poly->head.prev, + poly_CreateNode(v)); + + } + poly_PreContour(poly, TRUE); + + // make sure that its clockwise + if ( (poly->Flags & PLF_ORIENT) != PLF_DIR) + { + poly_InvContour(poly); + } + thePolygon = poly_Create(); + poly_InclContour(thePolygon, poly); + if(!poly_Valid(thePolygon)) + { +// if(thePolygon) +// { +// poly_Free(&thePolygon); +// thePolygon = NULL; +// } + } + } +} + +ossimPolyArea2d::~ossimPolyArea2d() +{ + if(thePolygon) + { + poly_Free(&thePolygon); + thePolygon = NULL; + } +} +const ossimPolyArea2d& ossimPolyArea2d::operator *=(const ossimDpt& scale) +{ + if(!thePolygon) return *this; + + PLINE *cntr = (PLINE*)NULL; + POLYAREA *curpa = (POLYAREA*)NULL; + + curpa = thePolygon; + + do{ + for ( cntr = curpa->contours; cntr != NULL; cntr = cntr->next ) + { + VNODE *cur = &cntr->head; + double xmin, ymin; + double xmax, ymax; + xmin = xmax = cur->point[0]; + ymin = ymax = cur->point[1]; + do + { + cur->point[0] *= scale.x; + cur->point[1] *= scale.y; + xmin = std::min(cur->point[0], xmin); + xmax = std::max(cur->point[0], xmax); + ymin = std::min(cur->point[1], ymin); + ymax = std::max(cur->point[1], ymax); + } while ( ( cur = cur->next ) != &cntr->head ); + } + } + while( (curpa = curpa->f) != thePolygon); + + return *this; +} + +ossimPolyArea2d ossimPolyArea2d::operator *(const ossimDpt& scale)const +{ + if(!thePolygon) return *this; + + ossimPolyArea2d result(*this); + PLINE *cntr = (PLINE*)NULL; + POLYAREA *curpa = (POLYAREA*)NULL; + + curpa = result.thePolygon; + + do{ + for ( cntr = curpa->contours; cntr != NULL; cntr = cntr->next ) + { + VNODE *cur = &cntr->head; + double xmin, ymin; + double xmax, ymax; + xmin = xmax = cur->point[0]; + ymin = ymax = cur->point[1]; + + do + { + cur->point[0] *= scale.x; + cur->point[1] *= scale.y; + xmin = std::min(cur->point[0], xmin); + xmax = std::max(cur->point[0], xmax); + ymin = std::min(cur->point[1], ymin); + ymax = std::max(cur->point[1], ymax); + } while ( ( cur = cur->next ) != &cntr->head ); + + cntr->xmin = xmin; + cntr->ymin = ymin; + cntr->xmax = xmax; + cntr->ymax = ymax; + } + } + while( (curpa = curpa->f) != result.thePolygon); + + return result; +} + +const ossimPolyArea2d& ossimPolyArea2d::operator *=(double scale) +{ + return ((*this)*=ossimDpt(scale, scale)); +} + +ossimPolyArea2d ossimPolyArea2d::operator *(double scale)const +{ + return ((*this)*ossimDpt(scale, scale)); +} + +/*! + * Assignment operator. Allows you to assign + * or copy one polygon to another. + */ +const ossimPolyArea2d& ossimPolyArea2d::operator =(const ossimPolyArea2d& rhs) +{ + if(this != &rhs) + { + if(thePolygon) + { + poly_Free(&thePolygon); + thePolygon = NULL; + } + if(rhs.thePolygon) + { + poly_Copy0(&thePolygon, rhs.thePolygon); + } + } + + return *this; +} + +const ossimPolyArea2d& ossimPolyArea2d::operator =(const ossimIrect& rect) +{ + if(thePolygon) + { + poly_Free(&thePolygon); + thePolygon = NULL; + } + + PLINE *poly = NULL; + Vector v; + v[0] = rect.ul().x; + v[1] = rect.ul().y; + v[2] = 0; + poly = poly_NewContour(v); + poly_InclVertex(poly->head.prev, + poly_CreateNode(v)); + v[0] = rect.ur().x; + v[1] = rect.ur().y; + v[2] = 0; + poly_InclVertex(poly->head.prev, + poly_CreateNode(v)); + v[0] = rect.lr().x; + v[1] = rect.lr().y; + v[2] = 0; + poly_InclVertex(poly->head.prev, + poly_CreateNode(v)); + v[0] = rect.ll().x; + v[1] = rect.ll().y; + v[2] = 0; + poly_InclVertex(poly->head.prev, + poly_CreateNode(v)); + + poly_PreContour(poly, TRUE); + + if ( (poly->Flags & PLF_ORIENT) != PLF_DIR) + { + poly_InvContour(poly); + } + thePolygon = poly_Create(); + poly_InclContour(thePolygon, poly); +// if(!poly_Valid(thePolygon)) +// { +// if(thePolygon) +// { +// poly_Free(&thePolygon); +// thePolygon = NULL; +// } +// } + + return *this; +} + +const ossimPolyArea2d& ossimPolyArea2d::operator =(const ossimDrect& rect) +{ + if(thePolygon) + { + poly_Free(&thePolygon); + thePolygon = NULL; + } + + PLINE *poly = NULL; + Vector v; + v[0] = rect.ul().x; + v[1] = rect.ul().y; + v[2] = 0; + poly = poly_NewContour(v); + poly_InclVertex(poly->head.prev, + poly_CreateNode(v)); + v[0] = rect.ur().x; + v[1] = rect.ur().y; + v[2] = 0; + poly_InclVertex(poly->head.prev, + poly_CreateNode(v)); + v[0] = rect.lr().x; + v[1] = rect.lr().y; + v[2] = 0; + poly_InclVertex(poly->head.prev, + poly_CreateNode(v)); + v[0] = rect.ll().x; + v[1] = rect.ll().y; + v[2] = 0; + poly_InclVertex(poly->head.prev, + poly_CreateNode(v)); + + poly_PreContour(poly, TRUE); + + if ( (poly->Flags & PLF_ORIENT) != PLF_DIR) + { + poly_InvContour(poly); + } + thePolygon = poly_Create(); + poly_InclContour(thePolygon, poly); +// if(!poly_Valid(thePolygon)) +// { +// if(thePolygon) +// { +// poly_Free(&thePolygon); +// thePolygon = NULL; +// } +// } + + return *this; +} + +ossimPolyArea2d ossimPolyArea2d::operator -(const ossimPolyArea2d& rhs)const +{ + if(this == &rhs) + { + return ossimPolyArea2d(); + } + POLYAREA* result=NULL; + + if (poly_Boolean(this->thePolygon, + rhs.thePolygon, + &result, + PBO_SUB) == err_ok) + { + return ossimPolyArea2d(result, false); + } + + // if there were errors then we will just return an + // empty polygon. + // + return ossimPolyArea2d(); +} + +ossimPolyArea2d& ossimPolyArea2d::operator -=(const ossimPolyArea2d& rhs) +{ + if(this == &rhs) + { + poly_Free(&thePolygon); + thePolygon = NULL; + } + else + { + POLYAREA* result=NULL; + + if (poly_Boolean(this->thePolygon, + rhs.thePolygon, + &result, + PBO_SUB) == err_ok) + { + poly_Free(&thePolygon); + thePolygon = result; + } + else + { + // errors so make it empty + poly_Free(&thePolygon); + thePolygon = NULL; + } + } + + return *this; +} + +ossimPolyArea2d ossimPolyArea2d::operator +(const ossimPolyArea2d& rhs)const +{ + if(this == &rhs) + { + return *this; + } + POLYAREA* result=NULL; + + if (poly_Boolean(this->thePolygon, + rhs.thePolygon, + &result, + PBO_UNITE) == err_ok) + { + return ossimPolyArea2d(result, false); + } + + // if there were errors then we will just return an + // empty polygon. + // + return ossimPolyArea2d(); +} + +ossimPolyArea2d& ossimPolyArea2d::operator +=(const ossimPolyArea2d& rhs) +{ + if(this == &rhs) + { + poly_Free(&thePolygon); + thePolygon = NULL; + } + else + { + POLYAREA* result=NULL; + if (poly_Boolean(this->thePolygon, + rhs.thePolygon, + &result, + PBO_UNITE) == err_ok) + { + poly_Free(&thePolygon); + thePolygon = result; + } + else + { + // errors so make it empty + poly_Free(&thePolygon); + thePolygon = NULL; + } + } + + return *this; +} + +ossimPolyArea2d ossimPolyArea2d::operator &(const ossimPolyArea2d& rhs)const +{ + if(this == &rhs) + { + return ossimPolyArea2d(*this); + } + if(thePolygon&&rhs.thePolygon) + { + POLYAREA* result=NULL; + + if (poly_Boolean(this->thePolygon, + rhs.thePolygon, + &result, + PBO_ISECT) == err_ok) + { + return ossimPolyArea2d(result, false); + } + } + + // if there were errors then we will just return an + // empty polygon. + // + return ossimPolyArea2d(); +} + +ossimPolyArea2d& ossimPolyArea2d::operator &=(const ossimPolyArea2d& rhs) +{ + if(this != &rhs) + { + POLYAREA* result=NULL; + if (poly_Boolean(this->thePolygon, + rhs.thePolygon, + &result, + PBO_ISECT) == err_ok) + { + poly_Free(&thePolygon); + thePolygon = result; + } + else + { + // errors so make it empty + poly_Free(&thePolygon); + thePolygon = NULL; + } + } + + return *this; +} + +ossimPolyArea2d ossimPolyArea2d::operator ^(const ossimPolyArea2d& rhs)const +{ + if(this != &rhs) + { + POLYAREA* result=NULL; + + if (poly_Boolean(this->thePolygon, + rhs.thePolygon, + &result, + PBO_XOR) == err_ok) + { + return ossimPolyArea2d(result, false); + } + + } + + return ossimPolyArea2d(); +} + +ossimPolyArea2d& ossimPolyArea2d::operator ^=(const ossimPolyArea2d& rhs) +{ + if(this == &rhs) + { + poly_Free(&thePolygon); + thePolygon = NULL; + } + else + { + POLYAREA* result=NULL; + if (poly_Boolean(this->thePolygon, + rhs.thePolygon, + &result, + PBO_XOR) == err_ok) + { + poly_Free(&thePolygon); + thePolygon = result; + } + else + { + // errors so make it empty + poly_Free(&thePolygon); + thePolygon = NULL; + } + } + + return *this; +} + +bool ossimPolyArea2d::isPointWithin(const ossimDpt& point)const +{ + if(!thePolygon) + { + return false; + } + Vector v; + v[0] = point.x; + v[1] = point.y; + v[2] = 0; + + return (poly_CheckInside(thePolygon, v)==TRUE); + +} + +bool ossimPolyArea2d::isPointWithin(double x, double y)const +{ + if(!thePolygon) + { + return false; + } + Vector v; + v[0] = x; + v[1] = y; + v[2] = 0; + + return (poly_CheckInside(thePolygon, v)==TRUE); +} + +void ossimPolyArea2d::getBoundingRect(ossimDrect& rect) +{ + if(thePolygon) + { + PLINE* cntr = NULL; + POLYAREA* curpa = NULL; + + curpa = thePolygon; + rect = ossimDrect(curpa->contours->xmin, + curpa->contours->ymin, + curpa->contours->xmax, + curpa->contours->ymax); + do + { + for ( cntr = curpa->contours->next; cntr != NULL; cntr = cntr->next ) + { + ossimDrect rect2 = ossimDrect(curpa->contours->xmin, + curpa->contours->ymin, + curpa->contours->xmax, + curpa->contours->ymax); + if(rect2.width() != 1 && + rect2.height() != 1) + { + rect = rect.combine(rect2); + } + } + }while ( (curpa = curpa->f) != thePolygon); + } + else + { + rect = ossimDrect(0,0,0,0); + } +} + +bool ossimPolyArea2d::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + ossimKeywordNames::TYPE_KW, + "ossimPolyArea2d", + true); + + if(!thePolygon) + { + return true; + } + int cnt; + PLINE *cntr; + POLYAREA * curpa; + + cnt = 0, curpa = thePolygon; + do + { + cnt++; + } while ( (curpa = curpa->f) != thePolygon); + + curpa = thePolygon; + do + { + cnt = 1; + for ( cntr = curpa->contours; cntr != NULL; cntr = cntr->next ) + { + VNODE *cur; + ossimString newPrefix = prefix; + newPrefix+="contour"; + newPrefix += ossimString::toString(cnt); + newPrefix += "."; + kwl.add(newPrefix.c_str(), + "flags", + (int)cntr->Flags, + true); + + cur = &cntr->head; + int pointCount = 1; + do + { + ossimString pointString = "point"; + pointString += ossimString::toString(pointCount); + ossimString points; + points = ossimString::toString(cur->point[0]); + points += " "; + points += ossimString::toString(cur->point[1]); + kwl.add(newPrefix.c_str(), + pointString, + points.c_str(), + true); + ++pointCount; + } while ( ( cur = cur->next ) != &cntr->head ); + ++cnt; + } + }while ( (curpa = curpa->f) != thePolygon); + + return true; +} + +bool ossimPolyArea2d::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + + vector<ossimString> contourList = kwl.getSubstringKeyList(ossimString(prefix) + "contour[0-9]+\\."); + if(thePolygon) + { + poly_Free(&thePolygon); + thePolygon = NULL; + } + if(contourList.size() > 0) + { + thePolygon = poly_Create(); + vector<ossimString>::iterator currentContour = contourList.begin(); + + Vector v; + PLINE *poly = NULL; + ossim_uint32 currentContourIndex = 0; + while(currentContour != contourList.end()) + { + ossimString copyPrefix = *currentContour; + ossim_int32 contourFlags = 0; + + const char* lookupFlags = kwl.find((*currentContour).c_str(), + "flags"); + if(lookupFlags) + { + contourFlags = ossimString(lookupFlags).toInt32(); + } + ossim_uint32 numberOfPoints = kwl.getNumberOfSubstringKeys(copyPrefix + "point[0-9]"); + ossim_uint32 numberOfMatches = 0; + ossim_uint32 currentPoint = 0; + while(numberOfMatches < numberOfPoints) + { + ossimString pointString = "point"; + pointString += ossimString::toString(currentPoint); + const char* pointLookup = kwl.find((*currentContour).c_str(), + pointString); + if(pointLookup) + { + istringstream s(pointLookup); + + s >> v[0] >> v[1]; + v[2] = 0; + + // initialize the poly if we are on the + // first match point else we just add it. + if(!numberOfMatches) + { + poly = poly_NewContour(v); + } + else + { + poly_InclVertex(poly->head.prev, + poly_CreateNode(v)); + } + + ++numberOfMatches; + } + ++currentPoint; + } + poly->Flags = contourFlags; + poly_PreContour(poly, TRUE); + if ( (poly->Flags & PLF_ORIENT) != + (currentContourIndex ? PLF_INV : PLF_DIR) ) + { + poly_InvContour(poly); + } + if(!poly_InclContour(thePolygon, poly)) + { + poly_DelContour(&poly); + } + poly = NULL; + ++currentContour; + ++currentContourIndex; + } + } + return true; +} + +bool ossimPolyArea2d::getAllVisiblePolygons(vector<ossimPolygon>& polyList)const +{ + if(!thePolygon) return false; + if(!poly_Valid(thePolygon)) + { + return false; + } + polyList.clear(); + POLYAREA* curpa = thePolygon; + PLINE* cntr; + int index = 0; + do + { + for ( cntr = curpa->contours; cntr != NULL; cntr = cntr->next ) + { + if(cntr->Flags & PLF_DIR) + { + polyList.push_back(ossimPolygon()); + VNODE* cur = &cntr->head; + do + { + polyList[index].addPoint(cur->point[0], + cur->point[1]); + + } while ( ( cur = cur->next ) != &cntr->head ); + ++index; + } + } + }while ( (curpa = curpa->f) != thePolygon); + + return (polyList.size()>0); +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimPolyArea2d.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimPolyArea2d.h new file mode 100644 index 0000000000..aa86712b2d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimPolyArea2d.h @@ -0,0 +1,196 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimPolyArea2d.h,v 1.7 2005/09/30 19:56:45 gpotts Exp $ +#ifndef ossimPolyArea2d_HEADER +#define ossimPolyArea2d_HEADER +extern "C" +{ +#include "libpolyclip/polyarea.h" +} + +#include <iostream> +#include <vector> +using namespace std; + +#include "ossimDpt.h" +#include "ossimGpt.h" +#include "ossimDrect.h" +#include "ossimIrect.h" +#include "ossimKeywordlist.h" +#include "ossimPolygon.h" + +/*! + * This class uses the multiclip 2-d polygon library + * to do intersections, unions, set difference, and xor + * operations. It will also use the library to do quick + * point inside and poly inside tests. + */ +class OSSIMDLLEXPORT ossimPolyArea2d +{ +public: + friend ostream& operator <<(ostream& out, + const ossimPolyArea2d& data); + /*! + * we will use the multi clip library in + * libpolyclip directory. + */ + ossimPolyArea2d(); + /*! + * If the copy polygon flag is false + * it will set its internal thePolygon to polygon + * else it will make a copy of it. + */ + ossimPolyArea2d(POLYAREA* polygon, + bool copyPolygonFlag=false); + + ossimPolyArea2d(const ossimPolyArea2d& rhs); + ossimPolyArea2d(const vector<ossimDpt>& polygon); + ossimPolyArea2d(const vector<ossimGpt>& polygon); + ossimPolyArea2d(ossimDpt* points, + long number); + + ossimPolyArea2d(const ossimDpt& p1, + const ossimDpt& p2, + const ossimDpt& p3, + const ossimDpt& p4); + ossimPolyArea2d(const ossimIrect& rect) + :thePolygon(NULL) + { + (*this) = rect; + } + ossimPolyArea2d(const ossimDrect& rect) + :thePolygon(NULL) + { + (*this) = rect; + } + + ossimPolyArea2d(const ossimPolygon& polygon); + ~ossimPolyArea2d(); + + /*! + * Will scale the polygon along the x and y direction + * by the passed in scale. It will modify itself and + * return a const reference to itself. + */ + const ossimPolyArea2d& operator *=(const ossimDpt& scale); + + /*! + * Will scale the polygon along the x and y direction + * by the passed in scale. It will return another object. + */ + ossimPolyArea2d operator *(const ossimDpt& scale)const; + + /*! + * Scales evenly along the x and y direction. + */ + const ossimPolyArea2d& operator *=(double scale); + + /*! + * Scales evenly along the x and y direction. + */ + ossimPolyArea2d operator *(double scale)const; + + /*! + * Assignment operator. Allows you to assign + * or copy one polygon to another. + */ + const ossimPolyArea2d& operator =(const ossimPolyArea2d& rhs); + + const ossimPolyArea2d& operator =(const ossimIrect& rect); + const ossimPolyArea2d& operator =(const ossimDrect& rect); + + /*! + * Will do a set difference on the this - right + * and return a new polygon. + */ + ossimPolyArea2d operator -(const ossimPolyArea2d& rhs)const; + + /*! + * This will do the same as - but will + * update itself. + */ + ossimPolyArea2d& operator -=(const ossimPolyArea2d& rhs); + + /*! + * do a union of 2 polygons. + */ + ossimPolyArea2d operator +(const ossimPolyArea2d& rhs)const; + + /*! + * This will do the same as the operator + * + but will update itself. + */ + ossimPolyArea2d& operator +=(const ossimPolyArea2d& rhs); + + + /*! + * do an intersection of 2 polygons + */ + ossimPolyArea2d operator &(const ossimPolyArea2d& rhs)const; + + /*! + * This will do the same as the operator & + * but will update itself. + */ + + ossimPolyArea2d& operator &=(const ossimPolyArea2d& rhs); + + /*! + * Will perform the "excusive or" of the this + * object with the right side + */ + ossimPolyArea2d operator ^(const ossimPolyArea2d& rhs)const; + + /*! + * This is the non const version and will update + * itself. + */ + ossimPolyArea2d& operator ^=(const ossimPolyArea2d& rhs); + + /*! + * This only makes since if you know that there are no holes. + * For example, using it after an intersection only operation by loading + * up two filled regions and intersecting them. + */ + bool getAllVisiblePolygons(vector<ossimPolygon>& polyList)const; + + bool isEmpty()const + { + return (thePolygon == NULL); + } + + bool isPointWithin(const ossimDpt& point)const; + bool isPointWithin(double x, double y)const; + void getBoundingRect(ossimDrect& rect); + + bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); +protected: + POLYAREA *thePolygon; + + void loadPolygonForCurrentContour(ossimPolygon& polygon, + bool visible); +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimPolyLine.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimPolyLine.cpp new file mode 100644 index 0000000000..bde984f798 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimPolyLine.cpp @@ -0,0 +1,573 @@ +//***************************************************************************** +// FILE: ossimPolygon.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// AUTHOR: Garrett Potts (gpotts@imagelinks.com) +// +//***************************************************************************** +// $Id: ossimPolyLine.cpp,v 1.13 2004/12/21 20:12:40 gpotts Exp $ +// +#include "ossimPolyLine.h" +#include "base/common/ossimCommon.h" +#include <algorithm> +#include "base/common/ossimKeywordNames.h" +#include "base/data_types/ossimKeywordlist.h" +#include "base/data_types/ossimLine.h" +#include "base/data_types/ossimPolygon.h" +#include <sstream> +#include <iterator> +using namespace std; + +static const char* NUMBER_VERTICES_KW = "number_vertices"; + +ossimPolyLine::ossimPolyLine(const vector<ossimIpt>& polyLine) + :theCurrentVertex(0) +{ + theVertexList.insert(theVertexList.end(), + polyLine.begin(), + polyLine.end());; +} + +ossimPolyLine::ossimPolyLine(const vector<ossimDpt>& polyLine) + :theCurrentVertex(0) +{ + theVertexList = polyLine; +} + +//***************************************************************************** +// CONSTRUCTOR: ossimPolyLine(int numVertices, const ossimDpt* vertex_array) +// +//***************************************************************************** +ossimPolyLine::ossimPolyLine(int numVertices, const ossimDpt* v) + : theCurrentVertex(0) +{ + theVertexList.insert(theVertexList.begin(), + v, v+numVertices); +} + +//***************************************************************************** +// COPY CONSTRUCTOR: ossimPolyLine(ossimPolyLine) +// +//***************************************************************************** +ossimPolyLine::ossimPolyLine(const ossimPolyLine& polyLine) + :theCurrentVertex(0) +{ + *this = polyLine; +} + +ossimPolyLine::ossimPolyLine(ossimDpt v1, + ossimDpt v2, + ossimDpt v3, + ossimDpt v4) + : theVertexList(4), + theCurrentVertex(0) +{ + theVertexList[0] = v1; + theVertexList[1] = v2; + theVertexList[2] = v3; + theVertexList[3] = v4; +} + +ossimPolyLine::ossimPolyLine(const ossimIrect& rect) + : theVertexList(4), + theCurrentVertex(0) +{ + theVertexList[0] = rect.ul(); + theVertexList[1] = rect.ur(); + theVertexList[2] = rect.lr(); + theVertexList[3] = rect.ll(); +} + +ossimPolyLine::ossimPolyLine(const ossimDrect& rect) + : theVertexList(4), + theCurrentVertex(0) +{ + theVertexList[0] = rect.ul(); + theVertexList[1] = rect.ur(); + theVertexList[2] = rect.lr(); + theVertexList[3] = rect.ll(); +} + +ossimPolyLine::ossimPolyLine(const ossimPolygon& polygon) + :theVertexList(polygon.getNumberOfVertices()+1), + theCurrentVertex(0) +{ + ossim_uint32 n = polygon.getNumberOfVertices(); + + if(n) + { + for(ossim_uint32 i = 0; i < n; ++i) + { + theVertexList[i] = polygon[i]; + } + + theVertexList[n] = polygon[n-1]; + } + else + { + theVertexList.clear(); + } +} + +//***************************************************************************** +// DESTRUCTOR: ~ossimPolyLine +// +//***************************************************************************** +ossimPolyLine::~ossimPolyLine() +{ +} + +void ossimPolyLine::roundToIntegerBounds(bool compress) +{ + int i = 0; + for(i = 0; i < (int)theVertexList.size(); ++i) + { + theVertexList[i] = ossimIpt(theVertexList[i]); + } + if(compress&&theVertexList.size()) + { + vector<ossimDpt> polyLine; + + polyLine.push_back(theVertexList[0]); + ossimDpt testPt = theVertexList[0]; + for(i=1; i < (int)theVertexList.size(); ++i) + { + if(testPt!=theVertexList[i]) + { + testPt = theVertexList[i]; + polyLine.push_back(testPt); + } + } + theVertexList = polyLine; + theCurrentVertex = 0; + } +} + +bool ossimPolyLine::hasNans()const +{ + int upper = (int)theVertexList.size(); + int i = 0; + + for(i = 0; i < upper; ++i) + { + if(theVertexList[i].hasNans()) + { + return true; + } + } + + return false; +} + +void ossimPolyLine::getIntegerBounds(ossim_int32& minX, + ossim_int32& minY, + ossim_int32& maxX, + ossim_int32& maxY)const +{ + ossim_int32 npoly = (ossim_int32)theVertexList.size(); + int i = 0; + + if(npoly) + { + minX = (ossim_int32)floor(theVertexList[0].x); + maxX = (ossim_int32)ceil(theVertexList[0].x); + minY = (ossim_int32)floor(theVertexList[0].y); + maxY = (ossim_int32)ceil(theVertexList[0].y); + + for(i =1; i < npoly; ++i) + { + minX = std::min((ossim_int32)floor(theVertexList[i].x), + (ossim_int32)minX); + maxX = std::max((ossim_int32)ceil(theVertexList[i].x), + (ossim_int32)maxX); + minY = std::min((ossim_int32)floor(theVertexList[i].y), + (ossim_int32)minY); + maxY = std::max((ossim_int32)ceil(theVertexList[i].y), + (ossim_int32)maxY); + } + } + else + { + minX = OSSIM_INT_NAN; + minY = OSSIM_INT_NAN; + maxX = OSSIM_INT_NAN; + maxY = OSSIM_INT_NAN; + } +} + +void ossimPolyLine::getBounds(double& minX, + double& minY, + double& maxX, + double& maxY)const +{ + ossim_int32 npoly = (ossim_int32)theVertexList.size(); + + if(npoly) + { + int i = 0; + minX = theVertexList[0].x; + maxX = theVertexList[0].x; + minY = theVertexList[0].y; + maxY = theVertexList[0].y; + + for(i =1; i < npoly; ++i) + { + minX = std::min(theVertexList[i].x, minX); + maxX = std::max(theVertexList[i].x, maxX); + minY = std::min(theVertexList[i].y, minY); + maxY = std::max(theVertexList[i].y, maxY); + } + } + else + { + minX = OSSIM_DBL_NAN; + minY = OSSIM_DBL_NAN; + maxX = OSSIM_DBL_NAN; + maxY = OSSIM_DBL_NAN; + } +} + +bool ossimPolyLine::isWithin(const ossimDrect& rect)const +{ + if(theVertexList.size() == 1) + { + return rect.pointWithin(theVertexList[0]); + } + else if(theVertexList.size() > 1) + { + for(ossim_uint32 i = 0; i < (theVertexList.size() - 1); ++i) + { + ossimDpt p1 = theVertexList[i]; + ossimDpt p2 = theVertexList[i+1]; + + if(rect.clip(p1, p2)) + { + return true; + } + } + } + + return false; +} + + +bool ossimPolyLine::clipToRect(vector<ossimPolyLine>& result, + const ossimDrect& rect)const +{ + result.clear(); + + if(theVertexList.size() <1) return false; + + ossimPolyLine currentPoly; + + if(theVertexList.size() == 1) + { + rect.pointWithin(theVertexList[0]); + currentPoly.addPoint(theVertexList[0]); + result.push_back(currentPoly); + } + else + { + ossimDpt pt1 = theVertexList[0]; + ossimDpt pt2 = theVertexList[1]; + ossim_uint32 i = 1; + + while(i < theVertexList.size()) + { + + bool p1Inside = rect.pointWithin(pt1); + bool p2Inside = rect.pointWithin(pt2); + + if(p1Inside&&p2Inside) // both inside so save the first + { + currentPoly.addPoint(pt1); + pt1 = pt2; + } + // going from inside to outside + else if(p1Inside&& + !p2Inside) + { + currentPoly.addPoint(pt1); + ossimDpt save = pt2; + if(rect.clip(pt1, pt2)) + { + currentPoly.addPoint(pt2); + result.push_back(currentPoly); + + currentPoly.clear(); + } + pt2 = save; + pt1 = save; + }// going outside to the inside + else if(!p1Inside&& + p2Inside) + { + if(rect.clip(pt1, pt2)) + { + currentPoly.addPoint(pt1); + } + pt1 = pt2; + + } + else // both outside must do a clip to see if crosses rect + { + ossimDpt p1 = pt1; + ossimDpt p2 = pt2; + + if(rect.clip(p1, p2)) + { + currentPoly.addPoint(p1); + currentPoly.addPoint(p2); + } + pt1 = pt2; + } + ++i; + + if(i < theVertexList.size()) + { + pt2 = theVertexList[i]; + } + } + if(rect.pointWithin(pt2)) + { + currentPoly.addPoint(pt2); + } + } + + if(currentPoly.getNumberOfVertices() > 0) + { + result.push_back(currentPoly); + } + + return (result.size()>0); +} + +bool ossimPolyLine::isPointWithin(const ossimDpt& point) const +{ + if(theVertexList.size() == 1) + { + return (point == theVertexList[0]); + } + else + { + for(ossim_uint32 i = 1; i < theVertexList.size(); ++i) + { + if(ossimLine(theVertexList[i-1], + theVertexList[i]).isPointWithin(point)) + { + return true; + } + } + } + + return false; +} + +bool ossimPolyLine::vertex(int index, ossimDpt& tbd_vertex) const +{ + if((index >= (int)theVertexList.size()) || + (index < 0)) + { + return false; + } + + tbd_vertex = theVertexList[index]; + theCurrentVertex = index; + + return true; +} + +bool ossimPolyLine::nextVertex(ossimDpt& tbd_vertex) const +{ + ++theCurrentVertex; + if(theCurrentVertex >= (ossim_int32)theVertexList.size()) + { + return false; + } + tbd_vertex = theVertexList[theCurrentVertex]; + + return true; +} + + +const ossimPolyLine& ossimPolyLine::operator=(const ossimPolygon& polygon) +{ + theCurrentVertex = 0; + ossim_uint32 n = polygon.getNumberOfVertices(); + + if(n) + { + theVertexList.resize(n+1); + + for(ossim_uint32 i = 0; i < n; ++i) + { + theVertexList[i] = polygon[i]; + } + + theVertexList[n] = polygon[n-1]; + } + else + { + theVertexList.clear(); + } + + return *this; +} + +const ossimPolyLine& ossimPolyLine::operator=(const ossimPolyLine& polyLine) +{ + theVertexList = polyLine.theVertexList; + theCurrentVertex = polyLine.theCurrentVertex; + theAttributeList = polyLine.theAttributeList; + + return *this; +} + +const ossimPolyLine& ossimPolyLine::operator= (const vector<ossimDpt>& vertexList) +{ + theVertexList = vertexList; + theCurrentVertex = 0; + + return *this; +} + +const ossimPolyLine& ossimPolyLine::operator= (const vector<ossimIpt>& vertexList) +{ + theVertexList.clear(); + theVertexList.insert(theVertexList.end(), + vertexList.begin(), + vertexList.end()); + + theCurrentVertex = 0; + + return *this; +} + +//***************************************************************************** +// METHOD: operator==() +// +//***************************************************************************** +bool ossimPolyLine::operator==(const ossimPolyLine& polyLine) const +{ + if( (theVertexList.size() != polyLine.theVertexList.size())) + { + return false; + } + if(!theVertexList.size() && polyLine.theVertexList.size()) + { + return true; + } + + return (theVertexList == polyLine.theVertexList); +} + +const ossimPolyLine& ossimPolyLine::operator *=(const ossimDpt& scale) +{ + int upper = theVertexList.size(); + int i = 0; + + for(i = 0; i < upper; ++i) + { + theVertexList[i].x*=scale.x; + theVertexList[i].y*=scale.y; + } + + return *this; +} + +ossimPolyLine ossimPolyLine::operator *(const ossimDpt& scale)const +{ + ossimPolyLine result(*this); + + int i = 0; + int upper = theVertexList.size(); + for(i = 0; i < upper; ++i) + { + result.theVertexList[i].x*=scale.x; + result.theVertexList[i].y*=scale.y; + } + + return result; +} + + +void ossimPolyLine::reverseOrder() +{ + std::reverse(theVertexList.begin(), theVertexList.end()); +} + +//***************************************************************************** +// METHOD: ossimPolyLine::print(ostream) +// +//***************************************************************************** +void ossimPolyLine::print(ostream& os) const +{ + copy(theVertexList.begin(), + theVertexList.end(), + ostream_iterator<ossimDpt>(os, "\n")); +} + +bool ossimPolyLine::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + int i = 0; + kwl.add(prefix, + ossimKeywordNames::TYPE_KW, + "ossimPolyLine", + true); + kwl.add(prefix, + NUMBER_VERTICES_KW, + (int)theVertexList.size(), + true); + for(i = 0; i < (int)theVertexList.size();++i) + { + ossimString vert = "v"+ossimString::toString(i);; + ossimString value = (ossimString::toString(theVertexList[i].x) + " " + + ossimString::toString(theVertexList[i].y) ); + kwl.add(prefix, + vert.c_str(), + value.c_str(), + true); + } + ossimString order = ""; + + return true; +} + +bool ossimPolyLine::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* number_vertices = kwl.find(prefix, NUMBER_VERTICES_KW); + int i = 0; + + theVertexList.clear(); + int vertexCount = ossimString(number_vertices).toLong(); + double x = 0.0, y =0.0; + for(i = 0; i < vertexCount; ++i) + { + ossimString v = kwl.find(prefix, (ossimString("v")+ossimString::toString(i)).c_str()); + v = v.trim(); + + istringstream vStream(v); + vStream >> x >> y; + theVertexList.push_back(ossimDpt(x,y)); + } + + return true; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimPolyLine.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimPolyLine.h new file mode 100644 index 0000000000..ca7ad34ebc --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimPolyLine.h @@ -0,0 +1,257 @@ +//***************************************************************************** +// FILE: ossimPolygon.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// AUTHOR: Oscar Kramer (okramer@imagelinks.com) +// +// DESCRIPTION: Contains declaration of class ossimPolygon. +// This class provides utilities associated with N-vertex, convex +// (i.e., only two intersections for any line passing through the polygon). +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimPolyLine.h,v 1.10 2004/12/21 20:12:40 gpotts Exp $ + +#ifndef ossimPolyLine_HEADER +#define ossimPolyLine_HEADER +#include <iostream> +#include <vector> +using namespace std; + +#include "ossimDpt.h" +#include "ossimDrect.h" +#include "ossimIrect.h" +#include <base/data_types/ossimString.h> +class OSSIMDLLEXPORT ossimLine; +class OSSIMDLLEXPORT ossimPolygon; + +/*!**************************************************************************** + * + * CLASS: ossimPolyLine + * + *****************************************************************************/ +class OSSIMDLLEXPORT ossimPolyLine +{ +public: + ossimPolyLine() + :theCurrentVertex(0) + {} + ossimPolyLine(const vector<ossimIpt>& polygon); + ossimPolyLine(const vector<ossimDpt>& polygon); + ossimPolyLine(int numVertices, const ossimDpt* vertex_array); + + ossimPolyLine(const ossimPolyLine& copy_this); + ossimPolyLine(const ossimPolygon& polygon); + + /*! + * CONSTRUCTOR: Provided for convenience. Does not imply the polygon is + * limited to four vertices: + */ + ossimPolyLine(ossimDpt v1, + ossimDpt v2, + ossimDpt v3, + ossimDpt v4); + + ossimPolyLine(const ossimIrect& rect); + ossimPolyLine(const ossimDrect& rect); + + ~ossimPolyLine(); + + ossimDpt& operator[](int index) + { + return theVertexList[index]; + } + const ossimDpt& operator[](int index)const + { + return theVertexList[index]; + } + + ossim_uint32 getNumberOfVertices()const + { + return theVertexList.size(); + } + + void getIntegerBounds(ossim_int32& minX, + ossim_int32& minY, + ossim_int32& maxX, + ossim_int32& maxY)const; + void getBounds(double& minX, + double& minY, + double& maxX, + double& maxY)const; + void getBoundingRect(ossimDrect& rect)const + { + ossim_int32 minX; + ossim_int32 minY; + ossim_int32 maxX; + ossim_int32 maxY; + getIntegerBounds(minX, minY, maxX, maxY); + rect = ossimDrect(minX, minY, maxX, maxY); + + } + ossimDrect getBoundingRect()const + { + ossimDrect result; + + getBoundingRect(result); + + return result; + } + + void roundToIntegerBounds(bool compress=true); + void clear() + { + theVertexList.clear(); + } + void addPoint(const ossimDpt& pt) + { + theVertexList.push_back(pt); + } + void addPoint(double x, double y) + { + theVertexList.push_back(ossimDpt(x, y)); + } + void addAttribute( const ossimString& attribute ) + { + theAttributeList.push_back( attribute ); + } + + ossimDpt midPoint()const; + + /*! + * will sequence through the polygon and check to see if any values are NAN + */ + bool hasNans()const; + + ossim_uint32 size() + { + return getNumberOfVertices(); + } + void resize(ossim_uint32 newSize) + { + theVertexList.resize(newSize); + } + const vector<ossimDpt>& getVertexList()const + { + return theVertexList; + } + + vector<ossimDpt>& getVertexList() + { + return theVertexList; + } + vector<ossimString>& getAttributeList() + { + return theAttributeList; + } + + bool clipToRect(vector<ossimPolyLine>& result, + const ossimDrect& rect)const; + + /*! + * Will clip this poly line list to the past in rect and + * will return true if any part of this object is visible within + * the rectangle; + */ + bool isWithin(const ossimDrect& rect)const; + + + /*! + * METHOD: pointWithin(ossimDpt) + * Returns TRUE if point is inside polygon. + */ + bool pointWithin(const ossimDpt& point) const + { + return isPointWithin(point); + } + bool isPointWithin(const ossimDpt& point) const; + + /*! + * METHOD: vertex(index) + * Returns the ossimDpt vertex given the index. Returns false if no vertex + * defined. + */ + bool vertex(int index, ossimDpt& tbd_vertex) const; + + /*! + * METHOD: nextVertex() + * Assigns the ossimDpt tbd_vertex following the current vertex. The current + * vertex is initialized with a call to vertex(int), or after the last + * vertex is reached. Returns false if no vertex defined. Intended to be + * when cycling through all vertices. + */ + bool nextVertex(ossimDpt& tbd_vertex) const; + + void reverseOrder(); + /*! + * OPERATORS: (Some are inlined at bottom) + */ + const ossimPolyLine& operator= (const ossimPolyLine& copy_this); + const ossimPolyLine& operator= (const vector<ossimDpt>& vertexList); + const ossimPolyLine& operator= (const vector<ossimIpt>& vertexList); + const ossimPolyLine& operator= (const ossimIrect& rect); + const ossimPolyLine& operator= (const ossimPolygon& polygon); + const ossimPolyLine& operator= (const ossimDrect& rect); + bool operator==(const ossimPolyLine& compare_this) const; + bool operator!=(const ossimPolyLine& compare_this) const; + + const ossimPolyLine& operator *=(const ossimDpt& scale); + const ossimPolyLine& operator *=(double scale) + { + return ((*this)*=ossimDpt(scale, scale)); + } + + ossimPolyLine operator *(const ossimDpt& scale)const; + ossimPolyLine operator *(double scale)const + { + return ((*this)*ossimDpt(scale, scale)); + } + + /*! + * METHOD: print() + */ + void print(ostream& os) const; + friend ostream& operator<<(ostream&, const ossimPolyLine&); + + + bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); +protected: + vector<ossimDpt> theVertexList; + vector<ossimString> theAttributeList; + + mutable ossim_int32 theCurrentVertex; +}; + +inline bool ossimPolyLine::operator!=(const ossimPolyLine& compare_this) const +{ + return !(*this == compare_this); +} + +inline ostream& operator<<(ostream& os, const ossimPolyLine& polyLine) +{ + polyLine.print(os); + return os; +} + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimPolygon.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimPolygon.cpp new file mode 100644 index 0000000000..e1f4b12a9e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimPolygon.cpp @@ -0,0 +1,992 @@ +//***************************************************************************** +// FILE: ossimPolygon.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// AUTHOR: Oscar Kramer +// +// DESCRIPTION: Contains implementation of class +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimPolygon.cpp,v 1.47 2005/03/18 21:38:47 dburken Exp $ + +#include <algorithm> +#include <iterator> +#include <sstream> +#include <iterator> + +#include <base/data_types/ossimPolygon.h> +#include <base/data_types/ossimLine.h> +#include <base/common/ossimCommon.h> +#include <base/common/ossimKeywordNames.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimPolyArea2d.h> + +static const char* NUMBER_VERTICES_KW = "number_vertices"; +static const char* VERTEX_ORDER_KW = "order"; + +static const int RECT_LEFT_EDGE = 0; +static const int RECT_TOP_EDGE = 1; +static const int RECT_RIGHT_EDGE = 2; +static const int RECT_BOTTOM_EDGE = 3; + +ossimPolygon::ossimPolygon() + :theCurrentVertex(0), + theOrderingType(OSSIM_VERTEX_ORDER_UNKNOWN) +{} + +ossimPolygon::ossimPolygon(const vector<ossimIpt>& polygon) + :theCurrentVertex(0), + theOrderingType(OSSIM_VERTEX_ORDER_UNKNOWN) +{ + theVertexList.insert(theVertexList.end(), + polygon.begin(), + polygon.end());; +} + +ossimPolygon::ossimPolygon(const vector<ossimDpt>& polygon) + :theCurrentVertex(0), + theOrderingType(OSSIM_VERTEX_ORDER_UNKNOWN) +{ + theVertexList = polygon; +} + +//***************************************************************************** +// CONSTRUCTOR: ossimPolygon(int numVertices, const ossimDpt* vertex_array) +// +//***************************************************************************** +ossimPolygon::ossimPolygon(int numVertices, const ossimDpt* v) + : theCurrentVertex(0), + theOrderingType(OSSIM_VERTEX_ORDER_UNKNOWN) +{ + theVertexList.insert(theVertexList.begin(), + v, v+numVertices); +} + +//***************************************************************************** +// COPY CONSTRUCTOR: ossimPolygon(ossimPolygon) +// +//***************************************************************************** +ossimPolygon::ossimPolygon(const ossimPolygon& polygon) + :theCurrentVertex(0) +{ + *this = polygon; +} + +//***************************************************************************** +// CONSTRUCTOR: ossimPolygon(p1, p2, p3, p4) +// +// Provided for convenience. Does not imply the polygon is limited to four +// vertices +// +//***************************************************************************** +ossimPolygon::ossimPolygon(ossimDpt v1, + ossimDpt v2, + ossimDpt v3, + ossimDpt v4) + : theVertexList(4), + theCurrentVertex(0), + theOrderingType(OSSIM_VERTEX_ORDER_UNKNOWN) +{ + theVertexList[0] = v1; + theVertexList[1] = v2; + theVertexList[2] = v3; + theVertexList[3] = v4; +} + +ossimPolygon::ossimPolygon(const ossimIrect& rect) + : theVertexList(4), + theCurrentVertex(0), + theOrderingType(OSSIM_CLOCKWISE_ORDER) +{ + theVertexList[0] = rect.ul(); + theVertexList[1] = rect.ur(); + theVertexList[2] = rect.lr(); + theVertexList[3] = rect.ll(); +} + +ossimPolygon::ossimPolygon(const ossimDrect& rect) + : theVertexList(4), + theCurrentVertex(0), + theOrderingType(OSSIM_CLOCKWISE_ORDER) +{ + theVertexList[0] = rect.ul(); + theVertexList[1] = rect.ur(); + theVertexList[2] = rect.lr(); + theVertexList[3] = rect.ll(); +} + + +//***************************************************************************** +// DESTRUCTOR: ~ossimPolygon +// +//***************************************************************************** +ossimPolygon::~ossimPolygon() +{ +} + + +double ossimPolygon::area()const +{ + double area = 0; + int i=0; + int j=0; + int size = theVertexList.size(); + + for (i=0;i<(int)size;i++) + { + j = (i + 1) % (int)size; + area += theVertexList[i].x * theVertexList[j].y; + area -= theVertexList[i].y * theVertexList[j].x; + } + + area /= 2; + + return area; +} + +void ossimPolygon::roundToIntegerBounds(bool compress) +{ + int i = 0; + for(i = 0; i < (int)theVertexList.size(); ++i) + { + theVertexList[i] = ossimIpt(theVertexList[i]); + } + + if(compress&&theVertexList.size()) + { + vector<ossimDpt> polyLine; + + polyLine.push_back(theVertexList[0]); + ossimDpt testPt = theVertexList[0]; + for(i=1; i < (int)theVertexList.size(); ++i) + { + if(testPt!=theVertexList[i]) + { + testPt = theVertexList[i]; + polyLine.push_back(testPt); + } + } + if(polyLine.size() == 1) + { + polyLine.push_back(polyLine[0]); + } + + if(theVertexList.size() == 1) + { + polyLine.push_back(testPt); + } + theVertexList = polyLine; + theCurrentVertex = 0; + } +} + +ossimDpt ossimPolygon::midPoint()const +{ + int upper = (int)theVertexList.size(); + ossimDpt result(0.0, 0.0); + int i = 0; + + if(!upper) + { + result.makeNan(); + } + else + { + for(i = 0; i < upper; ++upper) + { + result.x+=theVertexList[i].x; + result.y+=theVertexList[i].y; + } + result.x/=(double)upper; + result.y/=(double)upper; + } + + return result; +} + +bool ossimPolygon::hasNans()const +{ + int upper = (int)theVertexList.size(); + int i = 0; + + for(i = 0; i < upper; ++i) + { + if(theVertexList[i].hasNans()) + { + return true; + } + } + + return false; +} + +void ossimPolygon::getIntegerBounds(ossim_int32& minX, + ossim_int32& minY, + ossim_int32& maxX, + ossim_int32& maxY)const +{ + ossim_int32 npoly = (ossim_int32)theVertexList.size(); + int i = 0; + + if(npoly) + { + minX = (ossim_int32)floor(theVertexList[0].x); + maxX = (ossim_int32)ceil(theVertexList[0].x); + minY = (ossim_int32)floor(theVertexList[0].y); + maxY = (ossim_int32)ceil(theVertexList[0].y); + + for(i =1; i < npoly; ++i) + { + minX = std::min((ossim_int32)floor(theVertexList[i].x), + (ossim_int32)minX); + maxX = std::max((ossim_int32)ceil(theVertexList[i].x), + (ossim_int32)maxX); + minY = std::min((ossim_int32)floor(theVertexList[i].y), + (ossim_int32)minY); + maxY = std::max((ossim_int32)ceil(theVertexList[i].y), + (ossim_int32)maxY); + } + } + else + { + minX = OSSIM_INT_NAN; + minY = OSSIM_INT_NAN; + maxX = OSSIM_INT_NAN; + maxY = OSSIM_INT_NAN; + } +} + +bool ossimPolygon::clipToRect(vector<ossimPolygon>& result, + const ossimDrect& rect)const +{ + result.clear(); + ossimPolyArea2d p1(*this); + ossimPolyArea2d p2(rect.ul(), rect.ur(), rect.lr(), rect.ll()); + + p1&=p2; + + p1.getAllVisiblePolygons(result); + + return (result.size() > 0); +} + +//***************************************************************************** +// METHOD: ossimPolygon::clipLineSegment(p1, p2) +// +// Implements Cyrus-Beck clipping algorithm as described in: +// http://www.daimi.au.dk/~mbl/cgcourse/wiki/cyrus-beck_line-clipping_.html +// +// Clips the line segment defined by the two endpoints provided. The +// endpoints are modified as needed to represent the clipped line. Returns +// true if intersection present. +// +//***************************************************************************** +bool ossimPolygon::clipLineSegment(ossimDpt& P, ossimDpt& Q) const +{ + ossimDpt PQ (Q - P); + double tE = 0.0; + double tL = 1.0; + ossimLine edge, edgeE, edgeL; + bool intersected=false; + double num, denom, t; + int npol = theVertexList.size(); + + checkOrdering(); + //*** + // clip the segment against each edge of the polygon + //*** + int i = 0; + int j = 0; + for(i = 0, j = 1; i < npol;) + { + edge = ossimLine(theVertexList[i], + theVertexList[j]); + + ossimDpt normal = edge.normal(); + + // Fix from CChuah@observera.com for counter clockwise polygons. (drb) + if (theOrderingType == OSSIM_COUNTERCLOCKWISE_ORDER) + { + normal.x = -normal.x; + normal.y = -normal.y; + } + + denom = normal.x*PQ.x + normal.y*PQ.y; + + num = normal.x*(edge.theP1.x - P.x) + normal.y*(edge.theP1.y - P.y); + + if (denom < 0) + { + //*** + // Appears to be entering: + //*** + t = num / denom; + if (t > tE) + { + tE = t; //+ FLT_EPSILON; + edgeE = edge; + } + } + else if (denom > 0) + { + //*** + // Appears to be leaving: + //*** + t = num / denom; + if (t < tL) + { + tL = t;// - FLT_EPSILON; + edgeL = edge; + } + } + + ++i; + ++j; + j%=npol; + } + + //*** + // Compute clipped end points: + //*** + if(tL >= tE) + { + Q.x = P.x + tL*PQ.x; + Q.y = P.y + tL*PQ.y; + P.x += tE*PQ.x; + P.y += tE*PQ.y; + intersected = true; + } + + return intersected; +} + + +//***************************************************************************** +// METHOD: ossimPolygon::pointWithin(const ossimDpt& point) +// +// Returns TRUE if point is inside polygon. +// +//***************************************************************************** +bool ossimPolygon::isPointWithin(const ossimDpt& point) const +{ + + int i, j, c = 0; + int npol = (int)theVertexList.size(); + + for (i = 0, j = npol-1; i < npol; j = i++) + { + if ((((theVertexList[i].y <= point.y) && (point.y < theVertexList[j].y)) || + ((theVertexList[j].y <= point.y) && (point.y < theVertexList[i].y))) && + (point.x < (theVertexList[j].x - theVertexList[i].x) * (point.y - theVertexList[i].y) / + (theVertexList[j].y - theVertexList[i].y) + theVertexList[i].x)) + { + c = !c; + } + } + + if(!c) // check if on if not within + { + for (i = 0, j = npol-1; i < npol; j = i++) + { + if(ossimLine(theVertexList[i], theVertexList[j]).isPointWithin(point)) + { + return true; + } + } + } + + return (c!=0); +} + +//***************************************************************************** +// METHOD: ossimPolygon::vertex(int) +// +// Returns the ossimDpt vertex given the index. Also initializes the current +// edge (theCurrentEdge) to the edge corresponding to the index. +// +//***************************************************************************** +bool ossimPolygon::vertex(int index, ossimDpt& tbd_vertex) const +{ + if((index >= (int)theVertexList.size()) || + (index < 0)) + { + return false; + } + + tbd_vertex = theVertexList[index]; + theCurrentVertex = index; + + return true; +} + +//***************************************************************************** +// METHOD: ossimPolygon::nextVertex() +// +// Assigns the ossimDpt tbd_vertex following the current vertex. The current +// vertex is initialized with a call to vertex(int), or after the last +// vertex is reached (initialized to theFirstEdge. Returns false if no vertex +// defined. +// +//***************************************************************************** +bool ossimPolygon::nextVertex(ossimDpt& tbd_vertex) const +{ + ++theCurrentVertex; + if(theCurrentVertex >= (ossim_int32)theVertexList.size()) + { + return false; + } + tbd_vertex = theVertexList[theCurrentVertex]; + + return true; +} + +//***************************************************************************** +// METHOD: operator=() +// +//***************************************************************************** +const ossimPolygon& ossimPolygon::operator= (const ossimIrect& rect) +{ + theCurrentVertex = 0; + theVertexList.resize(4); + theVertexList[0] = rect.ul(); + theVertexList[1] = rect.ur(); + theVertexList[2] = rect.lr(); + theVertexList[3] = rect.ll(); + + return *this; +} + +const ossimPolygon& ossimPolygon::operator= (const ossimDrect& rect) +{ + theCurrentVertex = 0; + theVertexList.resize(4); + theVertexList[0] = rect.ul(); + theVertexList[1] = rect.ur(); + theVertexList[2] = rect.lr(); + theVertexList[3] = rect.ll(); + + return *this; +} + +const ossimPolygon& ossimPolygon::operator=(const ossimPolygon& polygon) +{ + theVertexList = polygon.theVertexList; + theCurrentVertex = polygon.theCurrentVertex; + theOrderingType = polygon.theOrderingType; + + return *this; +} + +const ossimPolygon& ossimPolygon::operator= (const vector<ossimDpt>& vertexList) +{ + theVertexList = vertexList; + theCurrentVertex = 0; + theOrderingType = OSSIM_VERTEX_ORDER_UNKNOWN; + + return *this; +} + +const ossimPolygon& ossimPolygon::operator= (const vector<ossimIpt>& vertexList) +{ + theVertexList.clear(); + theVertexList.insert(theVertexList.end(), + vertexList.begin(), + vertexList.end()); + + theCurrentVertex = 0; + theOrderingType = OSSIM_VERTEX_ORDER_UNKNOWN; + + return *this; +} + +//***************************************************************************** +// METHOD: operator==() +// +//***************************************************************************** +bool ossimPolygon::operator==(const ossimPolygon& polygon) const +{ + if( (theVertexList.size() != polygon.theVertexList.size())) + { + return false; + } + if(!theVertexList.size() && polygon.theVertexList.size()) + { + return true; + } + + return (theVertexList == polygon.theVertexList); +} + +const ossimPolygon& ossimPolygon::operator *=(const ossimDpt& scale) +{ + int upper = theVertexList.size(); + int i = 0; + for(i = 0; i < upper; ++i) + { + theVertexList[i].x*=scale.x; + theVertexList[i].y*=scale.y; + } + + return *this; +} + +ossimPolygon ossimPolygon::operator *(const ossimDpt& scale)const +{ + ossimPolygon result(*this); + + int upper = theVertexList.size(); + int i = 0; + for(i = 0; i < upper; ++i) + { + result.theVertexList[i].x*=scale.x; + result.theVertexList[i].y*=scale.y; + } + + return result; +} + + +void ossimPolygon::reverseOrder() +{ + std::reverse(theVertexList.begin(), theVertexList.end()); + + if(theOrderingType == OSSIM_COUNTERCLOCKWISE_ORDER) + { + theOrderingType = OSSIM_CLOCKWISE_ORDER; + } + else if(theOrderingType == OSSIM_CLOCKWISE_ORDER) + { + theOrderingType = OSSIM_COUNTERCLOCKWISE_ORDER; + } + +} + +//***************************************************************************** +// METHOD: ossimPolygon::print(ostream) +// +//***************************************************************************** +void ossimPolygon::print(ostream& os) const +{ + copy(theVertexList.begin(), + theVertexList.end(), + ostream_iterator<ossimDpt>(os, "\n")); +} + + +void ossimPolygon::checkOrdering()const +{ + if(theOrderingType == OSSIM_VERTEX_ORDER_UNKNOWN) + { + double areaValue = area(); + if(areaValue > 0) + { + theOrderingType = OSSIM_COUNTERCLOCKWISE_ORDER; + } + else if(areaValue <= 0) + { + theOrderingType = OSSIM_CLOCKWISE_ORDER; + } + } +} + +void ossimPolygon::intersectEdge(ossimDpt& result, + const ossimLine& segment, + const ossimDrect& rect, + int edge) +{ + ossimLine edgeLine; + switch(edge) + { + case RECT_LEFT_EDGE: + { + edgeLine.theP1 = rect.ll(); + edgeLine.theP2 = rect.ul(); + break; + } + case RECT_TOP_EDGE: + { + edgeLine.theP1 = rect.ul(); + edgeLine.theP2 = rect.ur(); + break; + } + case RECT_RIGHT_EDGE: + { + edgeLine.theP1 = rect.ur(); + edgeLine.theP2 = rect.lr(); + break; + } + case RECT_BOTTOM_EDGE: + { + edgeLine.theP1 = rect.lr(); + edgeLine.theP2 = rect.ll(); + break; + } + } + + result = segment.intersectInfinite(edgeLine); +} + +bool ossimPolygon::isInsideEdge(const ossimDpt& pt, + const ossimDrect& rect, + int edge)const +{ + switch(edge) + { + case RECT_LEFT_EDGE: + { + return (pt.x>rect.ul().x); + break; + } + case RECT_TOP_EDGE: + { + if(rect.orientMode() == OSSIM_LEFT_HANDED) + { + return (pt.y > rect.ul().y); + } + else + { + return (pt.y < rect.ul().y); + } + break; + } + case RECT_RIGHT_EDGE: + { + return (pt.x<rect.lr().x); + + break; + } + case RECT_BOTTOM_EDGE: + { + if(rect.orientMode() == OSSIM_LEFT_HANDED) + { + return (pt.y < rect.lr().y); + } + else + { + return (pt.y > rect.lr().y); + } + break; + } + } + return false; +} + + +bool ossimPolygon::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + ossimKeywordNames::TYPE_KW, + "ossimPolygon", + true); + kwl.add(prefix, + NUMBER_VERTICES_KW, + (int)theVertexList.size(), + true); + int i = 0; + for(i = 0; i < (int)theVertexList.size();++i) + { + ossimString vert = "v"+ossimString::toString(i);; + ossimString value = (ossimString::toString(theVertexList[i].x) + " " + + ossimString::toString(theVertexList[i].y) ); + kwl.add(prefix, + vert.c_str(), + value.c_str(), + true); + } + ossimString order = ""; + + switch(theOrderingType) + { + case OSSIM_VERTEX_ORDER_UNKNOWN: + { + order = "unknown"; + break; + } + case OSSIM_CLOCKWISE_ORDER: + { + order = "clockwise"; + break; + } + case OSSIM_COUNTERCLOCKWISE_ORDER: + { + order = "counter_clockwise"; + break; + } + } + kwl.add(prefix, + VERTEX_ORDER_KW, + order, + true); + + return true; +} + +bool ossimPolygon::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimString order = kwl.find(prefix, VERTEX_ORDER_KW); + const char* number_vertices = kwl.find(prefix, NUMBER_VERTICES_KW); + + if(order=="unknown") + { + theOrderingType = OSSIM_VERTEX_ORDER_UNKNOWN; + } + else if(order =="clockwise") + { + theOrderingType = OSSIM_CLOCKWISE_ORDER; + } + else if(order =="counter_clockwise") + { + theOrderingType = OSSIM_COUNTERCLOCKWISE_ORDER; + } + + theVertexList.clear(); + int vertexCount = ossimString(number_vertices).toLong(); + double x = 0.0, y =0.0; + int i = 0; + for(i = 0; i < vertexCount; ++i) + { + ossimString v = kwl.find(prefix, (ossimString("v")+ossimString::toString(i)).c_str()); + v = v.trim(); + + istringstream vStream(v); + vStream >> x >> y; + theVertexList.push_back(ossimDpt(x,y)); + } + + return true; +} + +void ossimPolygon::getMinimumBoundingRect(ossimPolygon& minRect) const +{ + static const double MIN_STEP = (0.5)*M_PI/180.0; + double angle_step = M_PI/8.0; // initial rotation step size for min area search = 22.5 deg + double theta; + double best_theta = M_PI/4.0; // Initial guess is 45 deg orientation + double center_theta; + double cos_theta, sin_theta; + ossimPolygon rotatedPolygon(*this); + ossimDpt xlatedVertex; + ossimDpt rotatedVertex(0.0, 0.0); + double min_x, min_y, max_x, max_y; + double area; + double min_area = OSSIM_INFINITY; + rotatedPolygon.theVertexList[0] = ossimDpt(0, 0); // first vertex always at origin + bool first_time = true; + ossimDrect best_rect; + static const bool TESTING = false; + + //*** + // Loop to converge on best orientation angle for bounding polygon: + //*** + while (angle_step > MIN_STEP) + { + //*** + // Try four different rotations evenly centered about the current best guess: + //*** + center_theta = best_theta; + for (int i=0; i<5; i++) + { + //*** + // Check for i=2 (center angle) since already computed quantities for this in last iteration + // unless this is first time through: + //*** + if ((i != 2) || (first_time)) + { + theta = center_theta + (i - 2.0)*angle_step; + cos_theta = cos(theta); + sin_theta = sin(theta); + min_x = rotatedPolygon.theVertexList[0].x; + min_y = rotatedPolygon.theVertexList[0].y; + max_x = min_x; + max_y = min_y; + + //*** + // Translate polygon to origin and rotate all vertices by current theta: + //*** + for (unsigned int vertex=1; vertex < theVertexList.size(); vertex++) + { + xlatedVertex.x = theVertexList[vertex].x - theVertexList[0].x; + xlatedVertex.y = theVertexList[vertex].y - theVertexList[0].y; + rotatedVertex.x = cos_theta*xlatedVertex.x + sin_theta*xlatedVertex.y; + rotatedVertex.y = cos_theta*xlatedVertex.y - sin_theta*xlatedVertex.x; + rotatedPolygon.theVertexList[vertex] = rotatedVertex; + + //*** + // Latch max and mins of bounding rect: + //*** + if (min_x > rotatedVertex.x) min_x = rotatedVertex.x; + if (min_y > rotatedVertex.y) min_y = rotatedVertex.y; + if (max_x < rotatedVertex.x) max_x = rotatedVertex.x; + if (max_y < rotatedVertex.y) max_y = rotatedVertex.y; + } + + if (TESTING) + { + ossimDpt v1 (cos_theta*min_x - sin_theta*max_y + theVertexList[0].x, + cos_theta*max_y + sin_theta*min_x + theVertexList[0].y); + ossimDpt v2 (cos_theta*max_x - sin_theta*max_y + theVertexList[0].x, + cos_theta*max_y + sin_theta*max_x + theVertexList[0].y); + ossimDpt v3 (cos_theta*max_x - sin_theta*min_y + theVertexList[0].x, + cos_theta*min_y + sin_theta*max_x + theVertexList[0].y); + ossimDpt v4 (cos_theta*min_x - sin_theta*min_y + theVertexList[0].x, + cos_theta*min_y + sin_theta*min_x + theVertexList[0].y); + cout << v1.x << "\t" << v1.y << endl; + cout << v2.x << "\t" << v2.y << endl; + cout << v3.x << "\t" << v3.y << endl; + cout << v4.x << "\t" << v4.y << endl << endl; + } + + //*** + // Establish bounding rect and area about rotated polygon: + //*** + area = (max_x - min_x) * (max_y - min_y); + if (area < min_area) + { + best_theta = theta; + min_area = area; + best_rect = ossimDrect(min_x, max_y, max_x, min_y, OSSIM_RIGHT_HANDED); + } + } // end if (i != 2 || first_time) + } // end for-loop over surrounding rotations + + //*** + // Adjust step size by half to repeat process: + //*** + angle_step /= 2.0; + first_time = false; + + } // end while loop for convergence + + //*** + // best_theta now contains optimum rotation of bounding rect. Need to apply reverse + // rotation and translation of best_rect: + //*** + cos_theta = cos(best_theta); + sin_theta = sin(best_theta); + ossimDpt v1 (cos_theta*best_rect.ul().x - sin_theta*best_rect.ul().y + theVertexList[0].x, + cos_theta*best_rect.ul().y + sin_theta*best_rect.ul().x + theVertexList[0].y); + ossimDpt v2 (cos_theta*best_rect.ur().x - sin_theta*best_rect.ur().y + theVertexList[0].x, + cos_theta*best_rect.ur().y + sin_theta*best_rect.ur().x + theVertexList[0].y); + ossimDpt v3 (cos_theta*best_rect.lr().x - sin_theta*best_rect.lr().y + theVertexList[0].x, + cos_theta*best_rect.lr().y + sin_theta*best_rect.lr().x + theVertexList[0].y); + ossimDpt v4 (cos_theta*best_rect.ll().x - sin_theta*best_rect.ll().y + theVertexList[0].x, + cos_theta*best_rect.ll().y + sin_theta*best_rect.ll().x + theVertexList[0].y); + + if (TESTING) + { + cout << v1.x << "\t" << v1.y << endl; + cout << v2.x << "\t" << v2.y << endl; + cout << v3.x << "\t" << v3.y << endl; + cout << v4.x << "\t" << v4.y << endl << endl; + } + + //*** + // Assign return value rect: + //*** + minRect.clear(); + minRect.addPoint(v1); + minRect.addPoint(v2); + minRect.addPoint(v3); + minRect.addPoint(v4); + + return; +} + +ossimDpt& ossimPolygon::operator[](int index) +{ + return theVertexList[index]; +} + +const ossimDpt& ossimPolygon::operator[](int index)const +{ + return theVertexList[index]; +} + +ossim_uint32 ossimPolygon::getVertexCount()const +{ + return getNumberOfVertices(); +} + +ossim_uint32 ossimPolygon::getNumberOfVertices()const +{ + return theVertexList.size(); +} + +void ossimPolygon::getBoundingRect(ossimIrect& rect)const +{ + ossim_int32 minX; + ossim_int32 minY; + ossim_int32 maxX; + ossim_int32 maxY; + getIntegerBounds(minX, minY, maxX, maxY); + rect = ossimIrect(minX, minY, maxX, maxY); +} + +void ossimPolygon::clear() +{ + theVertexList.clear(); + theOrderingType = OSSIM_VERTEX_ORDER_UNKNOWN; +} + +void ossimPolygon::addPoint(const ossimDpt& pt) +{ + theVertexList.push_back(pt); + theOrderingType = OSSIM_VERTEX_ORDER_UNKNOWN; +} + +void ossimPolygon::addPoint(double x, double y) +{ + theVertexList.push_back(ossimDpt(x, y)); + theOrderingType = OSSIM_VERTEX_ORDER_UNKNOWN; +} + +const vector<ossimDpt>& ossimPolygon::getVertexList()const +{ + return theVertexList; +} + + bool ossimPolygon::pointWithin(const ossimDpt& point) const +{ + return isPointWithin(point); +} + +const ossimPolygon& ossimPolygon::operator *=(double scale) +{ + return ((*this)*=ossimDpt(scale, scale)); +} + +ossimPolygon ossimPolygon::operator *(double scale)const +{ + return ((*this)*ossimDpt(scale, scale)); +} + +void ossimPolygon::resize(ossim_uint32 newSize) +{ + theVertexList.resize(newSize); + theOrderingType = OSSIM_VERTEX_ORDER_UNKNOWN; + theCurrentVertex = 0; +} + +ossimVertexOrdering ossimPolygon::getOrdering()const +{ + return theOrderingType; +} + +bool ossimPolygon::operator!=(const ossimPolygon& compare_this) const +{ + return !(*this == compare_this); +} + +ostream& operator<<(ostream& os, const ossimPolygon& polygon) +{ + polygon.print(os); + return os; +} + diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimPolygon.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimPolygon.h new file mode 100644 index 0000000000..7aea4698e3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimPolygon.h @@ -0,0 +1,209 @@ +//***************************************************************************** +// FILE: ossimPolygon.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// AUTHOR: Oscar Kramer +// +// DESCRIPTION: Contains declaration of class ossimPolygon. +// This class provides utilities associated with N-vertex, convex +// (i.e., only two intersections for any line passing through the polygon). +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimPolygon.h,v 1.36 2005/01/14 20:43:55 dburken Exp $ + +#ifndef ossimPolygon_HEADER +#define ossimPolygon_HEADER +#include <iostream> +#include <vector> +using namespace std; + +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimDrect.h> +#include <base/data_types/ossimIrect.h> + +class OSSIMDLLEXPORT ossimLine; + +/****************************************************************************** + * + * CLASS: ossimPolygon + * + *****************************************************************************/ +class OSSIMDLLEXPORT ossimPolygon +{ +public: + ossimPolygon(); + ossimPolygon(const vector<ossimIpt>& polygon); + ossimPolygon(const vector<ossimDpt>& polygon); + ossimPolygon(int numVertices, const ossimDpt* vertex_array); + + ossimPolygon(const ossimPolygon& copy_this); + + /** + * CONSTRUCTOR: Provided for convenience. Does not imply the polygon is + * limited to four vertices: + */ + ossimPolygon(ossimDpt v1, + ossimDpt v2, + ossimDpt v3, + ossimDpt v4); + + ossimPolygon(const ossimIrect& rect); + ossimPolygon(const ossimDrect& rect); + + ~ossimPolygon(); + + ossimDpt& operator[](int index); + + const ossimDpt& operator[](int index)const; + + ossim_uint32 getVertexCount()const; + + ossim_uint32 getNumberOfVertices()const; + + double area()const; + + void getIntegerBounds(ossim_int32& minX, + ossim_int32& minY, + ossim_int32& maxX, + ossim_int32& maxY)const; + + void getBoundingRect(ossimIrect& rect)const; + + /** + * Initializes minRect with the minimum area rect (not-necessarily + * aligned with axes) that bounds this polygon. + * + * @param minRect Polygon to initialize with the minimum rect. + */ + void getMinimumBoundingRect(ossimPolygon& minRect) const; + + void roundToIntegerBounds(bool compress=false); + + void clear(); + + void addPoint(const ossimDpt& pt); + void addPoint(double x, double y); + + ossimDpt midPoint()const; + + /** + * will sequence through the polygon and check to see if any values are NAN + */ + bool hasNans()const; + + const vector<ossimDpt>& getVertexList()const; + + /** + * Uses the ossimPolyArea2d class for the intersection + */ + bool clipToRect(vector<ossimPolygon>& result, + const ossimDrect& rect)const; + + + /** + * METHOD: clipLineSegment(p1, p2) + * Implements Cyrus-Beck clipping algorithm as described in: + * http://www.daimi.au.dk/~mbl/cgcourse/wiki/cyrus-beck_line-clipping_.html + * Clips the line segment defined by thw two endpoints provided. The + * endpoints are modified as needed to represent the clipped line. Returnes + * true if intersection present. + */ + bool clipLineSegment(ossimDpt& p1, ossimDpt& p2) const; + + /** + * METHOD: pointWithin(ossimDpt) + * Returns TRUE if point is inside polygon. + */ + bool pointWithin(const ossimDpt& point) const; + + bool isPointWithin(const ossimDpt& point) const; + + /** + * METHOD: vertex(index) + * Returns the ossimDpt vertex given the index. Returns false if no vertex + * defined. + */ + bool vertex(int index, ossimDpt& tbd_vertex) const; + + /** + * METHOD: nextVertex() + * Assigns the ossimDpt tbd_vertex following the current vertex. The current + * vertex is initialized with a call to vertex(int), or after the last + * vertex is reached. Returns false if no vertex defined. Intended to be + * when cycling through all vertices. + */ + bool nextVertex(ossimDpt& tbd_vertex) const; + + void reverseOrder(); + /** + * OPERATORS: (Some are inlined at bottom) + */ + const ossimPolygon& operator= (const ossimPolygon& copy_this); + const ossimPolygon& operator= (const vector<ossimDpt>& vertexList); + const ossimPolygon& operator= (const vector<ossimIpt>& vertexList); + const ossimPolygon& operator= (const ossimIrect& rect); + const ossimPolygon& operator= (const ossimDrect& rect); + bool operator==(const ossimPolygon& compare_this) const; + bool operator!=(const ossimPolygon& compare_this) const; + + const ossimPolygon& operator *=(const ossimDpt& scale); + const ossimPolygon& operator *=(double scale); + + ossimPolygon operator *(const ossimDpt& scale)const; + ossimPolygon operator *(double scale)const; + + void resize(ossim_uint32 newSize); + + /** + * METHOD: print() + */ + void print(ostream& os) const; + friend ostream& operator<<(ostream&, const ossimPolygon&); + + + bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + void checkOrdering()const; + + ossimVertexOrdering getOrdering()const; + +protected: + /** + * EMBEDDED CLASS: PolygonEdge + * A polygon consists of an ordered list of edges. The ordering corresponds + * to the ordering of the vertices. Each edge has a precomputed normal. + * The normals point towards the exterior. + */ + vector<ossimDpt> theVertexList; + + + mutable ossim_int32 theCurrentVertex; + + /** + * This enumeration is found in ossimConstants.h + */ + mutable ossimVertexOrdering theOrderingType; + + + void intersectEdge(ossimDpt& result, + const ossimLine& segment, + const ossimDrect& rect, + int edge); + + bool isInsideEdge(const ossimDpt& pt, + const ossimDrect& rect, + int edge)const; +}; + +#endif /* End of "#ifndef ossimPolygon_HEADER" */ diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimRationalNumber.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimRationalNumber.cpp new file mode 100644 index 0000000000..8e832d4fa2 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimRationalNumber.cpp @@ -0,0 +1,233 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//******************************************************************* +// $Id: ossimRationalNumber.cpp,v 1.4 2004/09/15 03:15:55 gpotts Exp $ +#include "base/data_types/ossimRationalNumber.h" + +// Normalisation +void ossimRationalNumber::normalize() +{ + if (theDen == 0) + { + return; + } + + // Handle the case of zero separately, to avoid division by zero + if (theNum == 0) + { + theDen = 1; + return; + } + + ossim_int32 g = ossimGcd(theNum, theDen); + + theNum /= g; + theDen /= g; + + // Ensure that the denominator is positive + if (theDen < 0) + { + theNum = -theNum; + theDen = -theDen; + } +} + +const ossimRationalNumber& ossimRationalNumber::assign(double value, long precision) +{ + ossim_sint32 s = 1; + if(value <= 0.0) + { + s = -1; + value *= -1.0; + } + ossim_int32 integerPart = (ossim_int32)std::floor(value); + ossim_int32 decimalPart = (ossim_int32)((value - integerPart)*precision); + ossimRationalNumber temp(integerPart); + ossimRationalNumber temp2(decimalPart, precision); + temp2.normalize(); + *this = (temp + temp2); + theNum *= s; + normalize(); + return *this; +} + +const ossimRationalNumber& ossimRationalNumber::operator+= (const ossimRationalNumber& r) +{ + // This calculation avoids overflow, and minimises the number of expensive + // calculations. Thanks to Nickolay Mladenov for this algorithm. + // + // Proof: + // We have to compute a/b + c/d, where gcd(a,b)=1 and gcd(b,c)=1. + // Let g = gcd(b,d), and b = b1*g, d=d1*g. Then gcd(b1,d1)=1 + // + // The result is (a*d1 + c*b1) / (b1*d1*g). + // Now we have to normalize this ratio. + // Let's assume h | gcd((a*d1 + c*b1), (b1*d1*g)), and h > 1 + // If h | b1 then gcd(h,d1)=1 and hence h|(a*d1+c*b1) => h|a. + // But since gcd(a,b1)=1 we have h=1. + // Similarly h|d1 leads to h=1. + // So we have that h | gcd((a*d1 + c*b1) , (b1*d1*g)) => h|g + // Finally we have gcd((a*d1 + c*b1), (b1*d1*g)) = gcd((a*d1 + c*b1), g) + // Which proves that instead of normalizing the result, it is better to + // divide num and den by gcd((a*d1 + c*b1), g) + + ossim_int32 g = ossimGcd(theDen, r.theDen); + theDen /= g; // = b1 from the calculations above + theNum = theNum * (r.theDen / g) + r.theNum * theDen; + g = ossimGcd(theNum, g); + theNum /= g; + theDen *= r.theDen/g; + + return *this; +} + +const ossimRationalNumber& ossimRationalNumber::operator-= (const ossimRationalNumber& r) +{ + // This calculation avoids overflow, and minimises the number of expensive + // calculations. It corresponds exactly to the += case above + ossim_int32 g = ossimGcd(theDen, r.theDen); + theDen /= g; + theNum = theNum * (r.theDen / g) - r.theNum * theDen; + g = ossimGcd(theNum, g); + theNum /= g; + theDen *= r.theDen/g; + + return *this; +} + +const ossimRationalNumber& ossimRationalNumber::operator*= (const ossimRationalNumber& r) +{ + // Avoid overflow and preserve normalization + ossim_int32 gcd1 = ossimGcd(theNum, r.theDen); + ossim_int32 gcd2 = ossimGcd(r.theNum, theDen); + theNum = (theNum/gcd1) * (r.theNum/gcd2); + theDen = (theDen/gcd2) * (r.theDen/gcd1); + + return *this; +} + +const ossimRationalNumber& ossimRationalNumber::operator/= (const ossimRationalNumber& r) +{ + ossim_int32 zero(0); + + if (r.theNum == zero) + { + theNum = OSSIM_INT_NAN; + theDen = OSSIM_INT_NAN; + + return *this; + } + *this = (*this)*(ossimRationalNumber(r.theDen, r.theNum)); + + return *this; +} + +// Mixed-mode operators +const ossimRationalNumber& ossimRationalNumber::operator+= (ossim_int32 i) +{ + return operator += (ossimRationalNumber(i)); +} + +const ossimRationalNumber& ossimRationalNumber::operator-= (ossim_int32 i) +{ + return operator -= (ossimRationalNumber(i)); +} + +const ossimRationalNumber& ossimRationalNumber::operator*= (ossim_int32 i) +{ + return operator *= (ossimRationalNumber(i)); +} + +const ossimRationalNumber& ossimRationalNumber::operator/= (ossim_int32 i) +{ + return operator /= (ossimRationalNumber(i)); +} + +ossimRationalNumber ossimRationalNumber::operator+ (const ossimRationalNumber& r)const +{ + // This calculation avoids overflow, and minimises the number of expensive + // calculations. Thanks to Nickolay Mladenov for this algorithm. + // + // Proof: + // We have to compute a/b + c/d, where gcd(a,b)=1 and gcd(b,c)=1. + // Let g = gcd(b,d), and b = b1*g, d=d1*g. Then gcd(b1,d1)=1 + // + // The result is (a*d1 + c*b1) / (b1*d1*g). + // Now we have to normalize this ratio. + // Let's assume h | gcd((a*d1 + c*b1), (b1*d1*g)), and h > 1 + // If h | b1 then gcd(h,d1)=1 and hence h|(a*d1+c*b1) => h|a. + // But since gcd(a,b1)=1 we have h=1. + // Similarly h|d1 leads to h=1. + // So we have that h | gcd((a*d1 + c*b1) , (b1*d1*g)) => h|g + // Finally we have gcd((a*d1 + c*b1), (b1*d1*g)) = gcd((a*d1 + c*b1), g) + // Which proves that instead of normalizing the result, it is better to + // divide num and den by gcd((a*d1 + c*b1), g) + + ossim_int32 g = ossimGcd(theDen, r.theDen); + ossim_int32 den = theDen; + ossim_int32 num = theNum; + den /= g; // = b1 from the calculations above + num = num * (r.theDen / g) + r.theNum * den; + g = ossimGcd(num, g); + num /= g; + den *= r.theDen/g; + + return ossimRationalNumber(num, den); +} + +ossimRationalNumber ossimRationalNumber::operator-(const ossimRationalNumber& r)const +{ + ossimRationalNumber result = *this; + // This calculation avoids overflow, and minimises the number of expensive + // calculations. It corresponds exactly to the += case above + ossim_int32 g = ossimGcd(result.theDen, r.theDen); + result.theDen /= g; + result.theNum = result.theNum * (r.theDen / g) - r.theNum * result.theDen; + g = ossimGcd(result.theNum, g); + result.theNum /= g; + result.theDen *= r.theDen/g; + + return result; +} + +ossimRationalNumber ossimRationalNumber::operator*(const ossimRationalNumber& r)const +{ + ossimRationalNumber result = *this; + // Avoid overflow and preserve normalization + ossim_int32 gcd1 = ossimGcd(result.theNum, r.theDen); + ossim_int32 gcd2 = ossimGcd(r.theNum, result.theDen); + result.theNum = (result.theNum/gcd1) * (r.theNum/gcd2); + result.theDen = (result.theDen/gcd2) * (r.theDen/gcd1); + + return result; +} + +ossimRationalNumber ossimRationalNumber::operator/(const ossimRationalNumber& r)const +{ + ossim_int32 zero(0); + + if (r.theNum == zero) + { + return ossimRationalNumber(OSSIM_INT_NAN, OSSIM_INT_NAN);; + } + + return (*this)*(ossimRationalNumber(r.theDen, r.theNum)); +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimRationalNumber.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimRationalNumber.h new file mode 100644 index 0000000000..9d511fbca4 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimRationalNumber.h @@ -0,0 +1,210 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//******************************************************************* +// $Id: ossimRationalNumber.h,v 1.14 2003/09/14 18:49:42 dburken Exp $ +#ifndef ossimRationalNumber_HEADER +#define ossimRationalNumber_HEADER +#include "base/common/ossimCommon.h" +#include "base/common/ossimConstants.h" +#include <iostream> + +class OSSIMDLLEXPORT ossimRationalNumber +{ +public: + + friend std::ostream& operator<<(std::ostream& out, const ossimRationalNumber& rhs) + { + out<<rhs.theNum << "/" << rhs.theDen; + + return out; + } + ossimRationalNumber() + :theNum(1), + theDen(1) + { + } + ossimRationalNumber(ossim_int32 num, + ossim_int32 den) + :theNum(num), + theDen(den) + { + } + ossimRationalNumber(ossim_int32 num) + :theNum(num), + theDen(1) + {} + double toDouble()const + { + return (static_cast<double>(theNum)/ + static_cast<double>(theDen)); + } + float toFloat()const + { + return (static_cast<float>(theNum)/ + static_cast<float>(theDen)); + } + + void normalize(); + + const ossimRationalNumber& operator=(ossim_int32 n) + { + return assign(n, 1); + } + + const ossimRationalNumber& operator=(double n) + { + return assign(n); + } + + ossimRationalNumber operator-()const + { + return ossimRationalNumber(-theNum, theDen); + } + const ossimRationalNumber& operator+= (const ossimRationalNumber& r); + const ossimRationalNumber& operator-= (const ossimRationalNumber& r); + const ossimRationalNumber& operator*= (const ossimRationalNumber& r); + const ossimRationalNumber& operator/= (const ossimRationalNumber& r); + + inline const ossimRationalNumber& operator+= (ossim_int32 i); + inline const ossimRationalNumber& operator-= (ossim_int32 i); + inline const ossimRationalNumber& operator*= (ossim_int32 i); + inline const ossimRationalNumber& operator/= (ossim_int32 i); + + ossimRationalNumber operator+ (const ossimRationalNumber& r)const; + ossimRationalNumber operator- (const ossimRationalNumber& r)const; + ossimRationalNumber operator* (const ossimRationalNumber& r)const; + ossimRationalNumber operator/ (const ossimRationalNumber& r)const; + + inline ossimRationalNumber operator+ (ossim_int32 i)const; + inline ossimRationalNumber operator- (ossim_int32 i)const; + inline ossimRationalNumber operator* (ossim_int32 i)const; + inline ossimRationalNumber operator/ (ossim_int32 i)const; + + friend inline ossimRationalNumber operator+ (ossim_int32 i, ossimRationalNumber& r); + friend inline ossimRationalNumber operator- (ossim_int32 i, ossimRationalNumber& r); + friend inline ossimRationalNumber operator* (ossim_int32 i, ossimRationalNumber& r); + friend inline ossimRationalNumber operator/ (ossim_int32 i, ossimRationalNumber& r); + + // Comparison operators +// inline bool operator< (const ossimRationalNumber& r) const; + inline bool operator== (const ossimRationalNumber& r) const; + + inline bool operator== (ossim_int32 i) const; + + // Increment and decrement + inline const ossimRationalNumber& operator++(); + inline const ossimRationalNumber& operator--(); + + // Assign in place + inline const ossimRationalNumber& assign(ossim_int32 n, ossim_int32 d); + /*! + * default estimation is out to the 10000 place. Will set this + * rational to a value that is close to the passed in number. + */ + const ossimRationalNumber& assign(double value, long precision=10000); + + /*! + * Holds the value of the numberator. + */ + ossim_int32 theNum; + + /*! + * Holds the value of the denominator. + */ + ossim_int32 theDen; + +}; + +inline const ossimRationalNumber& ossimRationalNumber::assign(ossim_int32 n, ossim_int32 d) +{ + theNum = n; + theDen = d; + normalize(); + + return *this; +} + +// Mixed-mode operators +inline ossimRationalNumber ossimRationalNumber::operator+(ossim_int32 i)const +{ + return operator + (ossimRationalNumber(i)); +} + +inline ossimRationalNumber ossimRationalNumber::operator-(ossim_int32 i)const +{ + return operator - (ossimRationalNumber(i)); +} + +inline ossimRationalNumber ossimRationalNumber::operator*(ossim_int32 i)const +{ + return operator * (ossimRationalNumber(i)); +} + +inline ossimRationalNumber ossimRationalNumber::operator/(ossim_int32 i)const +{ + return operator / (ossimRationalNumber(i)); +} + +inline ossimRationalNumber operator+ (ossim_int32 i, ossimRationalNumber& r) +{ + return ossimRationalNumber(i)+r; +} + +inline ossimRationalNumber operator- (ossim_int32 i, ossimRationalNumber& r) +{ + return ossimRationalNumber(i)-r; +} + +inline ossimRationalNumber operator* (ossim_int32 i, ossimRationalNumber& r) +{ + return ossimRationalNumber(i)*r; +} + +inline ossimRationalNumber operator/ (ossim_int32 i, ossimRationalNumber& r) +{ + return ossimRationalNumber(i)/r; +} + +inline const ossimRationalNumber& ossimRationalNumber::operator++() +{ + theNum += theDen; + + return *this; +} + +inline const ossimRationalNumber& ossimRationalNumber::operator--() +{ + theNum -= theDen; + + return *this; +} + +inline bool ossimRationalNumber::operator== (const ossimRationalNumber& r)const +{ + return ((theNum == r.theNum) && (theDen == r.theDen)); +} + +inline bool ossimRationalNumber::operator== (ossim_int32 i) const +{ + return ((theDen == ossim_int32(1)) && (theNum == i)); +} + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimRegExp.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimRegExp.cpp new file mode 100644 index 0000000000..4e5584ef2e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimRegExp.cpp @@ -0,0 +1,1276 @@ + +// +// Copyright (C) 1991 Texas Instruments Incorporated. +// +// Permission is granted to any individual or institution to use, copy, modify, +// and distribute this software, provided that this complete copyright and +// permission notice is maintained, intact, in all copies and supporting +// documentation. +// +// Texas Instruments Incorporated provides this software "as is" without +// express or implied warranty. +// +// +// Created: MNF 06/13/89 Initial Design and Implementation +// Updated: LGO 08/09/89 Inherit from Generic +// Updated: MBN 09/07/89 Added conditional exception handling +// Updated: MBN 12/15/89 Sprinkled "const" qualifiers all over the place! +// Updated: DLS 03/22/91 New lite version +// +// This is the header file for the regular expression class. An object of +// this class contains a regular expression, in a special "compiled" format. +// This compiled format consists of several slots all kept as the objects +// private data. The RegExp class provides a convenient way to represent +// regular expressions. It makes it easy to search for the same regular +// expression in many different strings without having to compile a string to +// regular expression format more than necessary. +// +// A regular expression allows a programmer to specify complex patterns that +// can be searched for and matched against the character string of a String +// object. In its simplest case, a regular expression is a sequence of +// characters with which you can search for exact character matches. However, +// many times you may not know the exact sequence you want to find, or you may +// only want to find a match at the beginning or end of a String. The RegExp +// object allows specification of such patterns by utilizing the following +// regular expression meta-characters (note that more one of these +// meta-characters can be used in a single regular expression in order to +// create complex search patterns): +// +// ^ Match at beginning of line +// $ Match at end of line +// . Match any single character +// [ ] Match any one character inside the brackets +// [^ ] Match any character NOT inside the brackets +// - Match any character in range on either side of dash +// * Match preceding pattern zero or more times +// + Match preceding pattern one or more times +// ? Match preceding pattern zero or once only +// () Save a matched expression and use it in a further match. +// +// There are three constructors for RegExp. One just creates an empty RegExp +// object. Another creates a RegExp object and initializes it with a regular +// expression that is given in the form of a char*. The third takes a +// reference to a RegExp object as an argument and creates an object +// initialized with the information from the given RegExp object. +// +// The find member function finds the first occurence of the regualr +// expression of that object in the string given to find as an argument. Find +// returns a boolean, and if true, mutates the private data appropriately. +// Find sets pointers to the beginning and end of the thing last found, they +// are pointers into the actual string that was searched. The start and end +// member functions return indicies into the searched string that correspond +// to the beginning and end pointers respectively. The compile member +// function takes a char* and puts the compiled version of the char* argument +// into the object's private data fields. The == and != operators only check +// the to see if the compiled regular expression is the same, and the +// deep_equal functions also checks to see if the start and end pointers are +// the same. The is_valid function returns false if program is set to NULL, +// (i.e. there is no valid compiled exression). The set_invalid function sets +// the program to NULL (Warning: this deletes the compiled expression). The +// following examples may help clarify regular expression usage: +// +// * The regular expression "^hello" matches a "hello" only at the +// beginning of a line. It would match "hello there" but not "hi, +// hello there". +// +// * The regular expression "long$" matches a "long" only at the end +// of a line. It would match "so long\0", but not "long ago". +// +// * The regular expression "t..t..g" will match anything that has a +// "t" then any two characters, another "t", any two characters and +// then a "g". It will match "testing", or "test again" but would +// not match "toasting" +// +// * The regular expression "[1-9ab]" matches any number one through +// nine, and the characters "a" and "b". It would match "hello 1" +// or "begin", but would not match "no-match". +// +// * The regular expression "[^1-9ab]" matches any character that is +// not a number one through nine, or an "a" or "b". It would NOT +// match "hello 1" or "begin", but would match "no-match". +// +// * The regular expression "br* " matches something that begins with +// a "b", is followed by zero or more "r"s, and ends in a space. It +// would match "brrrrr ", and "b ", but would not match "brrh ". +// +// * The regular expression "br+ " matches something that begins with +// a "b", is followed by one or more "r"s, and ends in a space. It +// would match "brrrrr ", and "br ", but would not match "b " or +// "brrh ". +// +// * The regular expression "br? " matches something that begins with +// a "b", is followed by zero or one "r"s, and ends in a space. It +// would match "br ", and "b ", but would not match "brrrr " or +// "brrh ". +// +// * The regular expression "(..p)b" matches something ending with pb +// and beginning with whatever the two characters before the first p +// encounterd in the line were. It would find "repb" in "rep drepa +// qrepb". The regular expression "(..p)a" would find "repa qrepb" +// in "rep drepa qrepb" +// +// * The regular expression "d(..p)" matches something ending with p, +// beginning with d, and having two characters in between that are +// the same as the two characters before the first p encounterd in +// the line. It would match "drepa qrepb" in "rep drepa qrepb". +// + +#include <stdlib.h> +#include <stdio.h> +#include "ossimRegExp.h" // Include class specification + +// ossimRegExp -- Copies the given regular expression. + +ossimRegExp::ossimRegExp (const ossimRegExp& rxp) { + int ind; + this->progsize = rxp.progsize; // Copy regular expression size + this->program = new char[this->progsize]; // Allocate storage + for(ind=this->progsize; ind-- != 0;) // Copy regular expresion + this->program[ind] = rxp.program[ind]; + this->startp[0] = rxp.startp[0]; // Copy pointers into last + this->endp[0] = rxp.endp[0]; // Successful "find" operation + this->regmust = rxp.regmust; // Copy field + if (rxp.regmust != NULL) { + char* dum = rxp.program; + ind = 0; + while (dum != rxp.regmust) { + ++dum; + ++ind; + } + this->regmust = this->program + ind; + } + this->regstart = rxp.regstart; // Copy starting index + this->reganch = rxp.reganch; // Copy remaining private data + this->regmlen = rxp.regmlen; // Copy remaining private data +} + + +// operator== -- Returns true if two regular expressions have the same +// compiled program for pattern matching. + +bool ossimRegExp::operator== (const ossimRegExp& rxp) const { + if (this != &rxp) { // Same address? + ossim_uint32 ind = this->progsize; // Get regular expression size + if (ind != rxp.progsize) // If different size regexp + return false; // Return failure + while(ind-- != 0) // Else while still characters + if(this->program[ind] != rxp.program[ind]) // If regexp are different + return false; // Return failure + } + return true; // Else same, return success +} + + +// deep_equal -- Returns true if have the same compiled regular expressions +// and the same start and end pointers. + +bool ossimRegExp::deep_equal (const ossimRegExp& rxp) const { + ossim_uint32 ind = this->progsize; // Get regular expression size + if (ind != rxp.progsize) // If different size regexp + return false; // Return failure + while(ind-- != 0) // Else while still characters + if(this->program[ind] != rxp.program[ind]) // If regexp are different + return false; // Return failure + return (this->startp[0] == rxp.startp[0] && // Else if same start/end ptrs, + this->endp[0] == rxp.endp[0]); // Return true +} + +// The remaining code in this file is derived from the regular expression code +// whose copyright statement appears below. It has been changed to work +// with the class concepts of C++ and COOL. + +/* + * compile and find + * + * Copyright (c) 1986 by University of Toronto. + * Written by Henry Spencer. Not derived from licensed software. + * + * Permission is granted to anyone to use this software for any + * purpose on any computer system, and to redistribute it freely, + * subject to the following restrictions: + * + * 1. The author is not responsible for the consequences of use of + * this software, no matter how awful, even if they arise + * from defects in it. + * + * 2. The origin of this software must not be misrepresented, either + * by explicit claim or by omission. + * + * 3. Altered versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * + * Beware that some of this code is subtly aware of the way operator + * precedence is structured in regular expressions. Serious changes in + * regular-expression syntax might require a total rethink. + */ + +/* + * The "internal use only" fields in regexp.h are present to pass info from + * compile to execute that permits the execute phase to run lots faster on + * simple cases. They are: + * + * regstart char that must begin a match; '\0' if none obvious + * reganch is the match anchored (at beginning-of-line only)? + * regmust string (pointer into program) that match must include, or NULL + * regmlen length of regmust string + * + * Regstart and reganch permit very fast decisions on suitable starting points + * for a match, cutting down the work a lot. Regmust permits fast rejection + * of lines that cannot possibly match. The regmust tests are costly enough + * that compile() supplies a regmust only if the r.e. contains something + * potentially expensive (at present, the only such thing detected is * or + + * at the start of the r.e., which can involve a lot of backup). Regmlen is + * supplied because the test in find() needs it and compile() is computing + * it anyway. + */ + +/* + * Structure for regexp "program". This is essentially a linear encoding + * of a nondeterministic finite-state machine (aka syntax charts or + * "railroad normal form" in parsing technology). Each node is an opcode + * plus a "next" pointer, possibly plus an operand. "Next" pointers of + * all nodes except BRANCH implement concatenation; a "next" pointer with + * a BRANCH on both ends of it is connecting two alternatives. (Here we + * have one of the subtle syntax dependencies: an individual BRANCH (as + * opposed to a collection of them) is never concatenated with anything + * because of operator precedence.) The operand of some types of node is + * a literal string; for others, it is a node leading into a sub-FSM. In + * particular, the operand of a BRANCH node is the first node of the branch. + * (NB this is *not* a tree structure: the tail of the branch connects + * to the thing following the set of BRANCHes.) The opcodes are: + */ + +// definition number opnd? meaning +#define END 0 // no End of program. +#define BOL 1 // no Match "" at beginning of line. +#define EOL 2 // no Match "" at end of line. +#define ANY 3 // no Match any one character. +#define ANYOF 4 // str Match any character in this string. +#define ANYBUT 5 // str Match any character not in this + // string. +#define BRANCH 6 // node Match this alternative, or the + // next... +#define BACK 7 // no Match "", "next" ptr points backward. +#define EXACTLY 8 // str Match this string. +#define NOTHING 9 // no Match empty string. +#define STAR 10 // node Match this (simple) thing 0 or more + // times. +#define PLUS 11 // node Match this (simple) thing 1 or more + // times. +#define OPEN 20 // no Mark this point in input as start of + // #n. +// OPEN+1 is number 1, etc. +#define CLOSE 30 // no Analogous to OPEN. + +/* + * Opcode notes: + * + * BRANCH The set of branches constituting a single choice are hooked + * together with their "next" pointers, since precedence prevents + * anything being concatenated to any individual branch. The + * "next" pointer of the last BRANCH in a choice points to the + * thing following the whole choice. This is also where the + * final "next" pointer of each individual branch points; each + * branch starts with the operand node of a BRANCH node. + * + * BACK Normal "next" pointers all implicitly point forward; BACK + * exists to make loop structures possible. + * + * STAR,PLUS '?', and complex '*' and '+', are implemented as circular + * BRANCH structures using BACK. Simple cases (one character + * per match) are implemented with STAR and PLUS for speed + * and to minimize recursive plunges. + * + * OPEN,CLOSE ...are numbered at compile time. + */ + +/* + * A node is one char of opcode followed by two chars of "next" pointer. + * "Next" pointers are stored as two 8-bit pieces, high order first. The + * value is a positive offset from the opcode of the node containing it. + * An operand, if any, simply follows the node. (Note that much of the + * code generation knows about this implicit relationship.) + * + * Using two bytes for the "next" pointer is vast overkill for most things, + * but allows patterns to get big without disasters. + */ + +#define OP(p) (*(p)) +#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377)) +#define OPERAND(p) ((p) + 3) + +const unsigned char MAGIC = 0234; +/* + * Utility definitions. + */ + +#define UCHARAT(p) ((const unsigned char*)(p))[0] + + +#define FAIL(m) { regerror(m); return(NULL); } +#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?') +#define META "^$.[()|?+*\\" + + +/* + * Flags to be passed up and down. + */ +#define HASWIDTH 01 // Known never to match null string. +#define SIMPLE 02 // Simple enough to be STAR/PLUS operand. +#define SPSTART 04 // Starts with * or +. +#define WORST 0 // Worst case. + + + +///////////////////////////////////////////////////////////////////////// +// +// COMPILE AND ASSOCIATED FUNCTIONS +// +///////////////////////////////////////////////////////////////////////// + + +/* + * Global work variables for compile(). + */ +// static const char* regparse; // Input-scan pointer. +// static int regnpar; // () count. +// static char regdummy; +// static char* regcode; // Code-emit pointer; ®dummy = don't. +// static long regsize; // Code size. + +/* + * Forward declarations for compile()'s friends. + */ +// #ifndef static +// #define static static +// #endif +// static char* reg (int, int*); +// static char* regbranch (int*); +// static char* regpiece (int*); +// static char* regatom (int*); +// static char* regnode (char); +// static const char* regnext (register const char*); +// static char* regnext (register char*); +// static void regc (unsigned char); +// static void reginsert (char, char*); +// static void regtail (char*, const char*); +// static void regoptail (char*, const char*); + +// #ifdef STRCSPN +// static int strcspn (); +// #endif + + + +/* + * We can't allocate space until we know how big the compiled form will be, + * but we can't compile it (and thus know how big it is) until we've got a + * place to put the code. So we cheat: we compile it twice, once with code + * generation turned off and size counting turned on, and once "for real". + * This also means that we don't allocate space until we are sure that the + * thing really will compile successfully, and we never have to move the + * code and thus invalidate pointers into it. (Note that it has to be in + * one piece because free() must be able to free it all.) + * + * Beware that the optimization-preparation code in here knows about some + * of the structure of the compiled regexp. + */ + + +// compile -- compile a regular expression into internal code +// for later pattern matching. + +void ossimRegExp::compile (const char* exp) { + register const char* scan; + register const char* longest; + register unsigned long len; + int flags; + + if (exp == NULL) { + //RAISE Error, SYM(ossimRegExp), SYM(No_Expr), + printf ("ossimRegExp::compile(): No expression supplied.\n"); + return; + } + + // First pass: determine size, legality. + regparse = exp; + regnpar = 1; + regsize = 0L; + regcode = ®dummy; + regc(MAGIC); + if(!reg(0, &flags)) + { + printf ("ossimRegExp::compile(): Error in compile.\n"); + return; + } + this->startp[0] = this->endp[0] = this->searchstring = NULL; + + // Small enough for pointer-storage convention? + if (regsize >= 32767L) { // Probably could be 65535L. + //RAISE Error, SYM(ossimRegExp), SYM(Expr_Too_Big), + printf ("ossimRegExp::compile(): Expression too big.\n"); + return; + } + + // Allocate space. +//#ifndef WIN32 + if (this->program != NULL) delete [] this->program; +//#endif + this->program = new char[regsize]; + this->progsize = (int) regsize; + + if (this->program == NULL) { + //RAISE Error, SYM(ossimRegExp), SYM(Out_Of_Memory), + printf ("ossimRegExp::compile(): Out of memory.\n"); + return; + } + + // Second pass: emit code. + regparse = exp; + regnpar = 1; + regcode = this->program; + regc(MAGIC); + reg(0, &flags); + + // Dig out information for optimizations. + this->regstart = '\0'; // Worst-case defaults. + this->reganch = 0; + this->regmust = NULL; + this->regmlen = 0; + scan = this->program + 1; // First BRANCH. + if (OP(regnext(scan)) == END) { // Only one top-level choice. + scan = OPERAND(scan); + + // Starting-point info. + if (OP(scan) == EXACTLY) + this->regstart = *OPERAND(scan); + else if (OP(scan) == BOL) + this->reganch++; + + // + // If there's something expensive in the r.e., find the longest + // literal string that must appear and make it the regmust. Resolve + // ties in favor of later strings, since the regstart check works + // with the beginning of the r.e. and avoiding duplication + // strengthens checking. Not a strong reason, but sufficient in the + // absence of others. + // + if (flags & SPSTART) { + longest = NULL; + len = 0; + for (; scan != NULL; scan = regnext(scan)) + if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) { + longest = OPERAND(scan); + len = strlen(OPERAND(scan)); + } + this->regmust = longest; + this->regmlen = len; + } + } +} + + +/* + - reg - regular expression, i.e. main body or parenthesized thing + * + * Caller must absorb opening parenthesis. + * + * Combining parenthesis handling with the base level of regular expression + * is a trifle forced, but the need to tie the tails of the branches to what + * follows makes it hard to avoid. + */ +char* ossimRegExp::reg (int paren, int *flagp) { + register char* ret; + register char* br; + register char* ender; + register int parno =0; + int flags; + + *flagp = HASWIDTH; // Tentatively. + + // Make an OPEN node, if parenthesized. + if (paren) { + if (regnpar >= NSUBEXP) { + //RAISE Error, SYM(ossimRegExp), SYM(Too_Many_Parens), + printf ("ossimRegExp::compile(): Too many parentheses.\n"); + return 0; + } + parno = regnpar; + regnpar++; + ret = regnode(OPEN + parno); + } + else + ret = NULL; + + // Pick up the branches, linking them together. + br = regbranch(&flags); + if (br == NULL) + return (NULL); + if (ret != NULL) + regtail(ret, br); // OPEN -> first. + else + ret = br; + if (!(flags & HASWIDTH)) + *flagp &= ~HASWIDTH; + *flagp |= flags & SPSTART; + while (*regparse == '|') { + regparse++; + br = regbranch(&flags); + if (br == NULL) + return (NULL); + regtail(ret, br); // BRANCH -> BRANCH. + if (!(flags & HASWIDTH)) + *flagp &= ~HASWIDTH; + *flagp |= flags & SPSTART; + } + + // Make a closing node, and hook it on the end. + ender = regnode((paren) ? CLOSE + parno : END); + regtail(ret, ender); + + // Hook the tails of the branches to the closing node. + for (br = ret; br != NULL; br = regnext(br)) + regoptail(br, ender); + + // Check for proper termination. + if (paren && *regparse++ != ')') { + //RAISE Error, SYM(ossimRegExp), SYM(Unmatched_Parens), + printf ("ossimRegExp::compile(): Unmatched parentheses.\n"); + return 0; + } + else if (!paren && *regparse != '\0') { + if (*regparse == ')') { + //RAISE Error, SYM(ossimRegExp), SYM(Unmatched_Parens), + printf ("ossimRegExp::compile(): Unmatched parentheses.\n"); + return 0; + } + else { + //RAISE Error, SYM(ossimRegExp), SYM(Internal_Error), + printf ("ossimRegExp::compile(): Internal error.\n"); + return 0; + } + // NOTREACHED + } + return (ret); +} + + +/* + - regbranch - one alternative of an | operator + * + * Implements the concatenation operator. + */ +char* ossimRegExp::regbranch (int *flagp) { + register char* ret; + register char* chain; + register char* latest; + int flags; + + *flagp = WORST; // Tentatively. + + ret = regnode(BRANCH); + chain = NULL; + while (*regparse != '\0' && *regparse != '|' && *regparse != ')') { + latest = regpiece(&flags); + if (latest == NULL) + return (NULL); + *flagp |= flags & HASWIDTH; + if (chain == NULL) // First piece. + *flagp |= flags & SPSTART; + else + regtail(chain, latest); + chain = latest; + } + if (chain == NULL) // Loop ran zero times. + regnode(NOTHING); + + return (ret); +} + + +/* + - regpiece - something followed by possible [*+?] + * + * Note that the branching code sequences used for ? and the general cases + * of * and + are somewhat optimized: they use the same NOTHING node as + * both the endmarker for their branch list and the body of the last branch. + * It might seem that this node could be dispensed with entirely, but the + * endmarker role is not redundant. + */ +char* ossimRegExp::regpiece (int *flagp) { + register char* ret; + register char op; + register char* next; + int flags; + + ret = regatom(&flags); + if (ret == NULL) + return (NULL); + + op = *regparse; + if (!ISMULT(op)) { + *flagp = flags; + return (ret); + } + + if (!(flags & HASWIDTH) && op != '?') { + //RAISE Error, SYM(ossimRegExp), SYM(Empty_Operand), + printf ("ossimRegExp::compile() : *+ operand could be empty.\n"); + return 0; + } + *flagp = (op != '+') ? (WORST | SPSTART) : (WORST | HASWIDTH); + + if (op == '*' && (flags & SIMPLE)) + reginsert(STAR, ret); + else if (op == '*') { + // Emit x* as (x&|), where & means "self". + reginsert(BRANCH, ret); // Either x + regoptail(ret, regnode(BACK)); // and loop + regoptail(ret, ret); // back + regtail(ret, regnode(BRANCH)); // or + regtail(ret, regnode(NOTHING)); // null. + } + else if (op == '+' && (flags & SIMPLE)) + reginsert(PLUS, ret); + else if (op == '+') { + // Emit x+ as x(&|), where & means "self". + next = regnode(BRANCH); // Either + regtail(ret, next); + regtail(regnode(BACK), ret); // loop back + regtail(next, regnode(BRANCH)); // or + regtail(ret, regnode(NOTHING)); // null. + } + else if (op == '?') { + // Emit x? as (x|) + reginsert(BRANCH, ret); // Either x + regtail(ret, regnode(BRANCH)); // or + next = regnode(NOTHING);// null. + regtail(ret, next); + regoptail(ret, next); + } + regparse++; + if (ISMULT(*regparse)) { + //RAISE Error, SYM(ossimRegExp), SYM(Nested_Operand), + printf ("ossimRegExp::compile(): Nested *?+.\n"); + return 0; + } + return (ret); +} + + +/* + - regatom - the lowest level + * + * Optimization: gobbles an entire sequence of ordinary characters so that + * it can turn them into a single node, which is smaller to store and + * faster to run. Backslashed characters are exceptions, each becoming a + * separate node; the code is simpler that way and it's not worth fixing. + */ +char* ossimRegExp::regatom (int *flagp) { + register char* ret; + int flags; + + *flagp = WORST; // Tentatively. + + switch (*regparse++) { + case '^': + ret = regnode(BOL); + break; + case '$': + ret = regnode(EOL); + break; + case '.': + ret = regnode(ANY); + *flagp |= HASWIDTH | SIMPLE; + break; + case '[':{ + register int rxpclass; + register int rxpclassend; + + if (*regparse == '^') { // Complement of range. + ret = regnode(ANYBUT); + regparse++; + } + else + ret = regnode(ANYOF); + if (*regparse == ']' || *regparse == '-') + regc(*regparse++); + while (*regparse != '\0' && *regparse != ']') { + if (*regparse == '-') { + regparse++; + if (*regparse == ']' || *regparse == '\0') + regc('-'); + else { + rxpclass = UCHARAT(regparse - 2) + 1; + rxpclassend = UCHARAT(regparse); + if (rxpclass > rxpclassend + 1) { + //RAISE Error, SYM(ossimRegExp), SYM(Invalid_Range), + printf ("ossimRegExp::compile(): Invalid range in [].\n"); + return 0; + } + for (; rxpclass <= rxpclassend; rxpclass++) + regc(rxpclass); + regparse++; + } + } + else + regc(*regparse++); + } + regc('\0'); + if (*regparse != ']') { + //RAISE Error, SYM(ossimRegExp), SYM(Unmatched_Bracket), + printf ("ossimRegExp::compile(): Unmatched [].\n"); + return 0; + } + regparse++; + *flagp |= HASWIDTH | SIMPLE; + } + break; + case '(': + ret = reg(1, &flags); + if (ret == NULL) + return (NULL); + *flagp |= flags & (HASWIDTH | SPSTART); + break; + case '\0': + case '|': + case ')': + //RAISE Error, SYM(ossimRegExp), SYM(Internal_Error), + printf ("ossimRegExp::compile(): Internal error.\n"); // Never here + return 0; + case '?': + case '+': + case '*': + //RAISE Error, SYM(ossimRegExp), SYM(No_Operand), + printf ("ossimRegExp::compile(): ?+* follows nothing.\n"); + return 0; + case '\\': + if (*regparse == '\0') { + //RAISE Error, SYM(ossimRegExp), SYM(Trailing_Backslash), + printf ("ossimRegExp::compile(): Trailing backslash.\n"); + return 0; + } + ret = regnode(EXACTLY); + regc(*regparse++); + regc('\0'); + *flagp |= HASWIDTH | SIMPLE; + break; + default:{ + register int len; + register char ender; + + regparse--; + len = strcspn(regparse, META); + if (len <= 0) { + //RAISE Error, SYM(ossimRegExp), SYM(Internal_Error), + printf ("ossimRegExp::compile(): Internal error.\n"); + return 0; + } + ender = *(regparse + len); + if (len > 1 && ISMULT(ender)) + len--; // Back off clear of ?+* operand. + *flagp |= HASWIDTH; + if (len == 1) + *flagp |= SIMPLE; + ret = regnode(EXACTLY); + while (len > 0) { + regc(*regparse++); + len--; + } + regc('\0'); + } + break; + } + return (ret); +} + + +/* + - regnode - emit a node + Location. + */ +char* ossimRegExp::regnode (char op) { + register char* ret; + register char* ptr; + + ret = regcode; + if (ret == ®dummy) { + regsize += 3; + return (ret); + } + + ptr = ret; + *ptr++ = op; + *ptr++ = '\0'; // Null "next" pointer. + *ptr++ = '\0'; + regcode = ptr; + + return (ret); +} + + +/* + - regc - emit (if appropriate) a byte of code + */ +void ossimRegExp::regc (unsigned char b) { + if (regcode != ®dummy) + *regcode++ = b; + else + regsize++; +} + + +/* + - reginsert - insert an operator in front of already-emitted operand + * + * Means relocating the operand. + */ +void ossimRegExp::reginsert (char op, char* opnd) { + register char* src; + register char* dst; + register char* place; + + if (regcode == ®dummy) { + regsize += 3; + return; + } + + src = regcode; + regcode += 3; + dst = regcode; + while (src > opnd) + *--dst = *--src; + + place = opnd; // Op node, where operand used to be. + *place++ = op; + *place++ = '\0'; + *place++ = '\0'; +} + + +/* + - regtail - set the next-pointer at the end of a node chain + */ +void ossimRegExp::regtail (char* p, const char* val) { + register char* scan; + register char* temp; + register int offset; + + if (p == ®dummy) + return; + + // Find last node. + scan = p; + for (;;) { + temp = regnext(scan); + if (temp == NULL) + break; + scan = temp; + } + + if (OP(scan) == BACK) + offset = (const char*)scan - val; + else + offset = val - scan; + *(scan + 1) = (offset >> 8) & 0377; + *(scan + 2) = offset & 0377; +} + + +/* + - regoptail - regtail on operand of first argument; nop if operandless + */ +void ossimRegExp::regoptail (char* p, const char* val) { + // "Operandless" and "op != BRANCH" are synonymous in practice. + if (p == NULL || p == ®dummy || OP(p) != BRANCH) + return; + regtail(OPERAND(p), val); +} + + + +//////////////////////////////////////////////////////////////////////// +// +// find and friends +// +//////////////////////////////////////////////////////////////////////// + + +/* + * Global work variables for find(). + */ +// static const char* reginput; // String-input pointer. +// static const char* regbol; // Beginning of input, for ^ check. +// static const char* *regstartp; // Pointer to startp array. +// static const char* *regendp; // Ditto for endp. + +/* + * Forwards. + */ +// static int regtry (const char*, const char* *, +// const char* *, const char*); +// static int regmatch (const char*); +// static int regrepeat (const char*); + +// #ifdef DEBUG +// int regnarrate = 0; +// void regdump (); +// static char* regprop (); +// #endif + + + +// find -- Matches the regular expression to the given string. +// Returns true if found, and sets start and end indexes accordingly. + +bool ossimRegExp::find (const char* string) { + register const char* s; + + this->searchstring = string; + + // Check validity of program. + if (!this->program || UCHARAT(this->program) != MAGIC) { + //RAISE Error, SYM(ossimRegExp), SYM(Internal_Error), + printf ("ossimRegExp::find(): Compiled regular expression corrupted.\n"); + return 0; + } + + // If there is a "must appear" string, look for it. + if (this->regmust != NULL) { + s = string; + while ((s = strchr(s, this->regmust[0])) != NULL) { + if (strncmp(s, this->regmust, this->regmlen) == 0) + break; // Found it. + s++; + } + if (s == NULL) // Not present. + return (0); + } + + // Mark beginning of line for ^ . + regbol = string; + + // Simplest case: anchored match need be tried only once. + if (this->reganch) + return (regtry(string, this->startp, this->endp, this->program)); + + // Messy cases: unanchored match. + s = string; + if (this->regstart != '\0') + // We know what char it must start with. + while ((s = strchr(s, this->regstart)) != NULL) { + if (regtry(s, this->startp, this->endp, this->program)) + return (1); + s++; + + } + else + // We don't -- general case. + do { + if (regtry(s, this->startp, this->endp, this->program)) + return (1); + } while (*s++ != '\0'); + + // Failure. + return (0); +} + + +/* + - regtry - try match at specific point + 0 failure, 1 success + */ +int ossimRegExp::regtry (const char* string, const char* *start, + const char* *end, const char* prog) { + register int i; + register const char* *sp1; + register const char* *ep; + + reginput = string; + regstartp = start; + regendp = end; + + sp1 = start; + ep = end; + for (i = NSUBEXP; i > 0; i--) { + *sp1++ = NULL; + *ep++ = NULL; + } + if (regmatch(prog + 1)) { + start[0] = string; + end[0] = reginput; + return (1); + } + else + return (0); +} + + +/* + - regmatch - main matching routine + * + * Conceptually the strategy is simple: check to see whether the current + * node matches, call self recursively to see whether the rest matches, + * and then act accordingly. In practice we make some effort to avoid + * recursion, in particular by going through "ordinary" nodes (that don't + * need to know whether the rest of the match failed) by a loop instead of + * by recursion. + * 0 failure, 1 success + */ +int ossimRegExp::regmatch (const char* prog) { + register const char* scan; // Current node. + const char* next; // Next node. + + scan = prog; + + while (scan != NULL) { + + next = regnext(scan); + + switch (OP(scan)) { + case BOL: + if (reginput != regbol) + return (0); + break; + case EOL: + if (*reginput != '\0') + return (0); + break; + case ANY: + if (*reginput == '\0') + return (0); + reginput++; + break; + case EXACTLY:{ + register int len; + register const char* opnd; + + opnd = OPERAND(scan); + // Inline the first character, for speed. + if (*opnd != *reginput) + return (0); + len = strlen(opnd); + if (len > 1 && strncmp(opnd, reginput, len) != 0) + return (0); + reginput += len; + } + break; + case ANYOF: + if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL) + return (0); + reginput++; + break; + case ANYBUT: + if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL) + return (0); + reginput++; + break; + case NOTHING: + break; + case BACK: + break; + case OPEN + 1: + case OPEN + 2: + case OPEN + 3: + case OPEN + 4: + case OPEN + 5: + case OPEN + 6: + case OPEN + 7: + case OPEN + 8: + case OPEN + 9:{ + register int no; + register const char* save; + + no = OP(scan) - OPEN; + save = reginput; + + if (regmatch(next)) { + + // + // Don't set startp if some later invocation of the + // same parentheses already has. + // + if (regstartp[no] == NULL) + regstartp[no] = save; + return (1); + } + else + return (0); + } +// break; + case CLOSE + 1: + case CLOSE + 2: + case CLOSE + 3: + case CLOSE + 4: + case CLOSE + 5: + case CLOSE + 6: + case CLOSE + 7: + case CLOSE + 8: + case CLOSE + 9:{ + register int no; + register const char* save; + + no = OP(scan) - CLOSE; + save = reginput; + + if (regmatch(next)) { + + // + // Don't set endp if some later invocation of the + // same parentheses already has. + // + if (regendp[no] == NULL) + regendp[no] = save; + return (1); + } + else + return (0); + } +// break; + case BRANCH:{ + + register const char* save; + + if (OP(next) != BRANCH) // No choice. + next = OPERAND(scan); // Avoid recursion. + else { + do { + save = reginput; + if (regmatch(OPERAND(scan))) + return (1); + reginput = save; + scan = regnext(scan); + } while (scan != NULL && OP(scan) == BRANCH); + return (0); + // NOTREACHED + } + } + break; + case STAR: + case PLUS:{ + register char nextch; + register int no; + register const char* save; + register int min_no; + + // + // Lookahead to avoid useless match attempts when we know + // what character comes next. + // + nextch = '\0'; + if (OP(next) == EXACTLY) + nextch = *OPERAND(next); + min_no = (OP(scan) == STAR) ? 0 : 1; + save = reginput; + no = regrepeat(OPERAND(scan)); + while (no >= min_no) { + // If it could work, try it. + if (nextch == '\0' || *reginput == nextch) + if (regmatch(next)) + return (1); + // Couldn't or didn't -- back up. + no--; + reginput = save + no; + } + return (0); + } +// break; + case END: + return (1); // Success! + + default: + //RAISE Error, SYM(ossimRegExp), SYM(Internal_Error), + printf ("ossimRegExp::find(): Internal error -- memory corrupted.\n"); + return 0; + } + scan = next; + } + + // + // We get here only if there's trouble -- normally "case END" is the + // terminating point. + // + //RAISE Error, SYM(ossimRegExp), SYM(Internal_Error), + printf ("ossimRegExp::find(): Internal error -- corrupted pointers.\n"); + return (0); +} + + +/* + - regrepeat - repeatedly match something simple, report how many + */ +int ossimRegExp::regrepeat (const char* p) { + register int count = 0; + register const char* scan; + register const char* opnd; + + scan = reginput; + opnd = OPERAND(p); + switch (OP(p)) { + case ANY: + count = strlen(scan); + scan += count; + break; + case EXACTLY: + while (*opnd == *scan) { + count++; + scan++; + } + break; + case ANYOF: + while (*scan != '\0' && strchr(opnd, *scan) != NULL) { + count++; + scan++; + } + break; + case ANYBUT: + while (*scan != '\0' && strchr(opnd, *scan) == NULL) { + count++; + scan++; + } + break; + default: // Oh dear. Called inappropriately. + //RAISE Error, SYM(ossimRegExp), SYM(Internal_Error), + printf ("ossimRegExp::find(): Internal error.\n"); + return 0; + } + reginput = scan; + return (count); +} + + +/* + - regnext - dig the "next" pointer out of a node + */ +const char* ossimRegExp::regnext (register const char* p) { + register int offset; + + if (p == ®dummy) + return (NULL); + + offset = NEXT(p); + if (offset == 0) + return (NULL); + + if (OP(p) == BACK) + return (p - offset); + else + return (p + offset); +} + + +char* ossimRegExp::regnext (register char* p) { + register int offset; + + if (p == ®dummy) + return (NULL); + + offset = NEXT(p); + if (offset == 0) + return (NULL); + + if (OP(p) == BACK) + return (p - offset); + else + return (p + offset); +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimRegExp.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimRegExp.h new file mode 100644 index 0000000000..37ad40740a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimRegExp.h @@ -0,0 +1,223 @@ +// +// Copyright (C) 1991 Texas Instruments Incorporated. +// +// Permission is granted to any individual or institution to use, copy, modify, +// and distribute this software, provided that this complete copyright and +// permission notice is maintained, intact, in all copies and supporting +// documentation. +// +// Texas Instruments Incorporated provides this software "as is" without +// express or implied warranty. +// +// .NAME CoolRegExp - Pattern matching with regular expressions. +// .LIBRARY cool +// .HEADER String Classes +// .INCLUDE cool/RegExp.h +// .FILE cool/RegExp.C +// .FILE cool/RegExp.h +// .EXAMPLE examples/ex_RegExp.C +// +// +// .SECTION Description +// A regular expression allows a programmer to specify complex +// patterns that can be searched for and matched against the +// character string of a string object. In its simplest form, a +// regular expression is a sequence of characters used to +// search for exact character matches. However, many times the +// exact sequence to be found is not known, or only a match at +// the beginning or end of a string is desired. The cool regu- +// lar expression class implements regular expression pattern +// matching as is found and implemented in many UNIX commands +// and utilities. +// +// The regular expression class provides a convenient mechanism +// for specifying and manipulating regular expressions. The +// regular expression object allows specification of such pat- +// terns by using the following regular expression metacharac- +// ters: +// +// ^ 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 +// +// Note that more than one of these metacharacters can be used +// in a single regular expression in order to create complex +// search patterns. For example, the pattern [^ab1-9] says to +// match any character sequence that does not begin with the +// characters "ab" followed by numbers in the series one +// through nine. + + +#ifndef ossimRegExph +#define ossimRegExph + +#include "ossimString.h" + +const int NSUBEXP = 10; + + +class OSSIMDLLEXPORT ossimRegExp { +public: + inline ossimRegExp (); // ossimRegExp with program=NULL + inline ossimRegExp (const char*); // ossimRegExp with compiled char* + ossimRegExp (const ossimRegExp&); // Copy constructor + inline ~ossimRegExp(); // Destructor + + void compile (const char*); // Compiles char* --> regexp + bool find (const char*); // true if regexp in char* arg + inline ossim_uint32 start() const; // Index to start of first find + inline ossim_uint32 end() const; // Index to end of first find + + bool operator== (const ossimRegExp&) const; // Equality operator + inline bool operator!= (const ossimRegExp&) const; // Inequality operator + bool deep_equal (const ossimRegExp&) const; // Same regexp and state? + + inline bool is_valid() const; // true if compiled regexp + inline void set_invalid(); // Invalidates regexp + + // awf added + ossim_uint32 start(ossim_uint32 n) const; + ossim_uint32 end(ossim_uint32 n) const; + std::string match(ossim_uint32 n) const; + +private: + const char* startp[NSUBEXP]; + const char* endp[NSUBEXP]; + char regstart; // Internal use only + char reganch; // Internal use only + const char* regmust; // Internal use only + ossim_uint32 regmlen; // Internal use only + char* program; + ossim_uint32 progsize; + const char* searchstring; + + // work variables + mutable const char* regparse; + mutable int regnpar; // () count. + mutable char regdummy; + mutable char* regcode; // Code-emit pointer; ®dummy = don't. + mutable long regsize; // Code size. + const char* reginput; // String-input pointer. + const char* regbol; // Beginning of input, for ^ check. + const char* *regstartp; // Pointer to startp array. + const char* *regendp; // Ditto for endp. + + char* reg (int, int*); + char* regbranch (int*); + char* regpiece (int*); + char* regatom (int*); + char* regnode (char); + const char* regnext (register const char*); + char* regnext (register char*); + void regc (unsigned char); + void reginsert (char, char*); + void regtail (char*, const char*); + void regoptail (char*, const char*); + int regtry (const char*, const char* *, + const char* *, const char*); + int regmatch (const char*); + int regrepeat (const char*); +#ifdef STRCSPN + int strcspn (); +#endif + +}; + +// ossimRegExp -- Creates an empty regular expression. + +inline ossimRegExp::ossimRegExp () { + this->program = NULL; +} + + +// ossimRegExp -- Creates a regular expression from string s, and +// compiles s. + + +inline ossimRegExp::ossimRegExp (const char* s) { + this->program = NULL; + compile(s); +} + +// ~ossimRegExp -- Frees space allocated for regular expression. + +inline ossimRegExp::~ossimRegExp () { +//#ifndef WIN32 + delete [] this->program; +//#endif +} + +// Start -- + +inline ossim_uint32 ossimRegExp::start () const { + return(this->startp[0] - searchstring); +} + + +// End -- Returns the start/end index of the last item found. + + +inline ossim_uint32 ossimRegExp::end () const { + return(this->endp[0] - searchstring); +} + + +// operator!= // + +inline bool ossimRegExp::operator!= (const ossimRegExp& r) const { + return(!(*this == r)); +} + + +// is_valid -- Returns true if a valid regular expression is compiled +// and ready for pattern matching. + +inline bool ossimRegExp::is_valid () const { + return (this->program != NULL); +} + + +// set_invalid -- Invalidates regular expression. + +inline void ossimRegExp::set_invalid () { +//#ifndef WIN32 + delete [] this->program; +//#endif + this->program = NULL; +} + +// -- Return start index of nth submatch. start(0) is the start of the full match. +inline ossim_uint32 ossimRegExp::start(ossim_uint32 n) const +{ + return this->startp[n] - searchstring; +} + +// -- Return end index of nth submatch. end(0) is the end of the full match. +inline ossim_uint32 ossimRegExp::end(ossim_uint32 n) const +{ + return this->endp[n] - searchstring; +} + +// -- Return nth submatch as a string. +inline std::string ossimRegExp::match(ossim_uint32 n) const +{ + return std::string(this->startp[n], this->endp[n] - this->startp[n]); +} + +#endif // CoolRegExph diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimString.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimString.cpp new file mode 100644 index 0000000000..763af52bbc --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimString.cpp @@ -0,0 +1,743 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. All rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// Description: This class extends the stl's string class. +// +//******************************************************************** +// $Id: ossimString.cpp,v 1.52 2005/10/17 18:37:16 gpotts Exp $ + +#include <sstream> +#include <algorithm> +#include <base/data_types/ossimString.h> +#include <base/data_types/ossimRegExp.h> +#include <base/common/ossimConstants.h> +#include <base/common/ossimTrace.h> + +static ossimTrace traceDebug("ossimString:debug"); + +#ifdef OSSIM_ID_ENABLED +static char OSSIM_ID[] = "$Id: ossimString.cpp,v 1.52 2005/10/17 18:37:16 gpotts Exp $"; +#endif + +ossimString::ossimString(char aChar) + : + std::string() +{ + char tmp[2]; + tmp[0] = aChar; + tmp[1] = '\0'; + append(tmp); +} + +ossimString::ossimString(size_type n, char c) +: std::string(n, c) +{ +} + +ossimString ossimString::upcase(const ossimString& aString) +{ + ossimString s(aString); + + ossimString::iterator eachCharacter = s.begin(); + while(eachCharacter != s.end()) + { + *eachCharacter = toupper(*eachCharacter); + eachCharacter++; + } + + return s; +} + +ossimString ossimString::downcase(const ossimString& aString) +{ + ossimString s(aString); + + ossimString::iterator eachCharacter = s.begin(); + while(eachCharacter != s.end()) + { + *eachCharacter = tolower(*eachCharacter); + eachCharacter++; + } + + return s; +} + +ossimString& ossimString::upcase() +{ + ossimString::iterator eachCharacter = begin(); + while(eachCharacter != end()) + { + *eachCharacter = toupper(*eachCharacter); + eachCharacter++; + } + + return *this; +} + +ossimString& ossimString::downcase() +{ + ossimString::iterator eachCharacter=begin(); + while(eachCharacter != end()) + { + *eachCharacter = tolower(*eachCharacter); + eachCharacter++; + } + + return *this; +} + +char* ossimString::stringDup()const +{ + char *result = 0; + + if(length() == 0) + { + result = new char; + result[0] = '\0'; + } + else + { + long index = 0; + long len = length(); + result = new char[len+1]; + const char* sourceString = c_str(); + + while(index < len) + { + result[index] = sourceString[index]; + index++; + } + result[len] = '\0'; + } + return result; +} + +ossimString ossimString::stripLeading(const ossimString &value, char characterToStrip) +{ + ossimString result; + ossimString::const_iterator stringIter = value.begin(); + + while((*stringIter == characterToStrip)&&(stringIter!=value.end())) + { + ++stringIter; + } + + while(stringIter != value.end()) + { + result += *stringIter; + ++stringIter; + } + + return result; +} + +ossimString ossimString::substitute(const ossimString &searchKey, + const ossimString &replacementValue, + bool replaceAll)const +{ + ossimString result = *this; + + size_type pos = result.find(searchKey); + + if (pos == npos) return result; // Search key not found. + + if(replaceAll) + { + while(pos != npos) + { + result.replace(pos, searchKey.size(), replacementValue.c_str()); + pos = result.find(searchKey, pos+replacementValue.size()); + } + } + else // Replace only the first instance. + { + result.replace(pos, searchKey.size(), replacementValue.c_str()); + } + + return result; +} + +ossimString& ossimString::gsub(const ossimString &searchKey, + const ossimString &replacementValue, + bool replaceAll) +{ + size_type pos = find(searchKey); + + if (pos == npos) return *this; // Search key not found. + + if(replaceAll) + { + while(pos < size()) + { + replace(pos, searchKey.size(), replacementValue.c_str()); + pos = find(searchKey, pos+replacementValue.size()); + } + } + else // Replace only the first instance. + { + replace(pos, searchKey.size(), replacementValue.c_str()); + } + + return *this; +} + +ossimString ossimString::trim(const ossimString& valueToTrim) const +{ + ossimString tempString(*this); + + return tempString.trim(valueToTrim); +} + +ossimString& ossimString::trim(const ossimString& valueToTrim) +{ + iterator startPos = (*this).begin(); + iterator endPos = (*this).end(); + + --endPos; + + while( (std::find(valueToTrim.begin(), + valueToTrim.end(), + *startPos)!=valueToTrim.end()) && + (startPos != (*this).end())) ++startPos; + + if(startPos == (*this).end()) + { + *this = ""; + return *this; + } + + while( (endPos!=startPos)&& (std::find(valueToTrim.begin(), + valueToTrim.end(), + *endPos)!=valueToTrim.end())) --endPos; + + *this = ossimString(startPos, endPos+1); + + return *this; +} + +ossimString ossimString::beforePos(ossim_uint32 pos)const +{ + ossimString result = *this; + + if(pos < length()) + { + result.erase(pos, npos); + } + + return result; +} + +ossimString ossimString::afterPos(ossim_uint32 pos)const +{ + ossimString result = *this; + + if(pos < length()) + { + result.erase(0, pos+1); + } + else + { + return ""; + } + + return result; + +} + +std::vector<ossimString> ossimString::explode(const ossimString& delimeter) const +{ + ossimString exp_str = *this; + std::vector<ossimString> result; + char* tokenPtr; + + tokenPtr = strtok((char*)exp_str.chars(), (char*)delimeter.chars()); + + while(tokenPtr != NULL) + { + result.push_back(tokenPtr); + tokenPtr = strtok(NULL, delimeter.chars()); + } + + return result; +} + +//--- +// Regular expression pattern utilities +//--- + +ossimString ossimString::beforeRegExp(const char *regularExpressionPattern) const +{ + ossimRegExp anExpression; + + anExpression.compile(regularExpressionPattern); + + if(anExpression.find(c_str())) + { + if (anExpression.start() > 0) + { + return substr(0, anExpression.start()); + } + } + + return ossimString(""); +} + +ossimString ossimString::fromRegExp(const char *regularExpressionPattern) const +{ + ossimRegExp anExpression; + + anExpression.compile(regularExpressionPattern); + + if(anExpression.find(c_str())) + { + if (anExpression.start() < size()) + { + return substr(anExpression.start(), (size()-anExpression.start())); + } + } + + return ossimString(""); +} + +ossimString ossimString::afterRegExp(const char *regularExpressionPattern) const +{ + ossimRegExp anExpression; + + anExpression.compile(regularExpressionPattern); + + if(anExpression.find(c_str())) + { + if (anExpression.end() < size()) + { + return substr(anExpression.end(), (size()-anExpression.end())); + } + } + + return ossimString(""); +} + +ossimString ossimString::match(const char *regularExpressionPattern) const +{ + ossimRegExp anExpression; + + anExpression.compile(regularExpressionPattern); + + if((anExpression.find(this->c_str())) && + (anExpression.start() !=anExpression.end())) + { + return this->substr(anExpression.start(), + anExpression.end() - anExpression.start() ); + } + + + return ossimString(""); +} + +ossimString ossimString::replaceAllThatMatch(const char *regularExpressionPattern, + const char *value) const +{ + ossimString result = *this; + ossimRegExp anExpression; + ossim_uint32 offset = 0; + ossim_uint32 valueLength = ossimString(value).length(); + anExpression.compile(regularExpressionPattern); + if(!anExpression.is_valid()) + { + return *this; + } + while(anExpression.find(result.c_str()+offset)) + { + if(anExpression.start() < anExpression.end()) + { + result.replace(anExpression.start() + offset, + anExpression.end()-anExpression.start(), + value); + offset += anExpression.start() + valueLength; + } + else + { + break; + } + } + + return result; +} + +ossimString ossimString::replaceStrThatMatch(const char *regularExpressionPattern, + const char *value) const +{ + ossimString result = *this; + ossimRegExp anExpression; + anExpression.compile(regularExpressionPattern); + if(!anExpression.is_valid()) + { + return *this; + } + if(anExpression.find(result.c_str())) + { + if(anExpression.start() < anExpression.end()) + { + result.replace(anExpression.start(), + anExpression.end()-anExpression.start(), + value); + } + } + + return result; +} + +double ossimString::toDouble()const +{ + if(contains("nan")) + { + return OSSIM_DBL_NAN; + } + + return atof(c_str()); +} + +double ossimString::toDouble(const ossimString& aString) +{ + if(aString.contains("nan")) + { + return OSSIM_DBL_NAN; + } + return atof(aString.c_str()); +} + +int ossimString::toInt()const +{ + return atoi(c_str()); +} + +int ossimString::toInt(const ossimString& aString) +{ + return (int)atoi(aString.c_str()); +} + +ossim_int32 ossimString::toInt32()const +{ + return (ossim_int32)atoi(c_str()); +} + +ossim_int32 ossimString::toInt32(const ossimString& aString) +{ + return (ossim_int32)atoi(aString.c_str()); +} + +ossim_uint32 ossimString::toUInt32()const +{ + return static_cast<ossim_uint32>(atoi(c_str())); +} + +ossim_uint32 ossimString::toUInt32(const ossimString& aString) +{ + return static_cast<ossim_uint32>(atoi(aString.c_str())); +} + +long ossimString::toLong()const +{ + return atol(c_str()); +} + +long ossimString::toLong(const ossimString& aString) +{ + return atol(aString.c_str()); +} + +unsigned long ossimString::toULong()const +{ + return static_cast<unsigned long>(atol(c_str())); +} + +unsigned long ossimString::toULong(const ossimString& aString) +{ + return static_cast<unsigned long>(atol(aString.c_str())); +} + +bool ossimString::toBool()const +{ + ossimString s = c_str(); + s = s.trim().downcase(); + if ( (s == "true") || + (s == "yes") || + (s == "y") || + (s == "1") ) + { + return true; + } + else if ( (s == "false") || + (s == "no") || + (s == "n") || + (s == "0") ) + { + return false; + + } + else if (toULong()) + { + return true; + } + + return false; +} + +bool ossimString::toBool(const ossimString& aString) +{ + // Check for true or false, yes or no, y or n, and 1 or 0... + ossimString s = aString; + s.downcase(); + if ( (s == "true") || + (s == "yes") || + (s == "y") || + (s == "1") ) + { + return true; + } + else if ( (s == "false") || + (s == "no") || + (s == "n") || + (s == "0") ) + { + return false; + + } + else if (aString.toULong()) + { + return true; + } + + return false; +} + +ossimString ossimString::toString(bool aValue) +{ + std::ostringstream s; + + s << aValue; + + ossimString result(s.str()); + + return result; +} + +ossimString ossimString::toString(ossim_int16 aValue) +{ + std::ostringstream s; + + s << aValue; + + ossimString result(s.str()); + + return result; +} + +ossimString ossimString::toString(ossim_uint16 aValue) +{ + std::ostringstream s; + + s << aValue; + + ossimString result(s.str()); + + return result; +} + +ossimString ossimString::toString(ossim_int32 aValue) +{ + std::ostringstream s; + + s << aValue; + + ossimString result(s.str()); + + return result; +} + +ossimString ossimString::toString(ossim_uint32 aValue) +{ + std::ostringstream s; + + s << aValue; + + ossimString result(s.str()); + + return result; +} + +ossimString ossimString::toString(long aValue) +{ + std::ostringstream s; + + s << aValue; + + ossimString result(s.str()); + + return result; +} + +ossimString ossimString::toString(unsigned long aValue) +{ + std::ostringstream s; + + s << aValue; + + ossimString result(s.str()); + + return result; +} + +ossimString ossimString::toString(ossim_float32 aValue, + int precision, + bool trimZeroFlag, + bool scientific) +{ + if (aValue == OSSIM_FLT_NAN) + { + return ossimString("nan"); + } + + std::ostringstream s; + + if (!scientific) + { + s << setiosflags(std::ios::fixed); + } + else + { + s << setiosflags(std::ios::scientific); + } + + s << std::setprecision(precision) << aValue; + + ossimString result(s.str()); + + if( trimZeroFlag && result.contains(".") ) + { + result = result.trim('0'); + result = result.trim('.'); + } + return result; +} + +ossimString ossimString::toString(ossim_float64 aValue, + int precision, + bool trimZeroFlag, + bool scientific) +{ + if (aValue == OSSIM_DBL_NAN) + { + return ossimString("nan"); + } + + std::ostringstream s; + + if (!scientific) + { + s << setiosflags(std::ios::fixed); + } + else + { + s << setiosflags(std::ios::scientific); + } + + s << std::setprecision(precision) << aValue; + + ossimString result(s.str()); + + if( trimZeroFlag && result.contains(".") ) + { + result = result.trim('0'); + result = result.trim('.'); + } + + return result; +} + +ossimString ossimString::before(const ossimString& str, ossim_uint32 pos) +{ + if(*this == "") return ossimString(); + + ossim_uint32 last = find(str.c_str(), pos); + if(last >= npos) return *this; + + return substr(0, last); +} + +ossimString ossimString::after(const ossimString& str, ossim_uint32 pos) +{ + size_t last = find(str.c_str(), pos); + if (last >= npos) return ossimString(); + + return substr(last+str.length()); +} + +void ossimString::split(std::vector<ossimString>& result, + const ossimString& separatorList)const +{ +// result = split(separatorList); + ossimString copyString = *this; + + char* s = strtok(const_cast<char*>(copyString.c_str()), + separatorList.c_str()); + + for(ossim_uint32 i = 0; i < separatorList.size(); ++ i) + { + if((*(this->begin())) == separatorList.c_str()[i]) + { + result.push_back(""); + } + } + while(s) + { + result.push_back(ossimString(s)); + s = strtok(NULL, + separatorList.c_str()); + } + for(ossim_uint32 i = 0; i < separatorList.size(); ++ i) + { + if((*(this->end()-1)) == separatorList.c_str()[i]) + { + result.push_back(""); + } + } +} + +std::vector<ossimString> ossimString:: split(const ossimString& separatorList)const +{ + std::vector<ossimString> result; + + split(result, separatorList); + + return result; +} + +const ossimString& ossimString::join(const std::vector<ossimString>& stringList, + const ossimString& separator) +{ + *this = ""; + if(stringList.size()) + { + for(long i = 0; i < ((long)stringList.size()-1); ++i) + { + *this += stringList[i]; + *this += separator; + } + *this += stringList[stringList.size()-1]; + } + + return *this; +} + +ossimString ossimString::getOssimId() const +{ +#ifdef OSSIM_ID_ENABLED + return ossimString(OSSIM_ID); +#endif + return ossimString(""); +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimString.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimString.h new file mode 100644 index 0000000000..6fa67e321d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimString.h @@ -0,0 +1,307 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// Description: This class extends the stl's string class. +// +//******************************************************************** +// $Id: ossimString.h,v 1.42 2005/10/17 18:37:16 gpotts Exp $ +#ifndef ossimString_HEADER +#define ossimString_HEADER +#include <string> +#include <cstring> +#include <cstdlib> +#include <iomanip> +#include <vector> +#include <base/common/ossimConstants.h> + +class OSSIM_DLL ossimString : public std::string +{ +public: + ossimString():std::string(){} + ossimString(const std::string& aString):std::string(aString){} + ossimString(const char *aString):std::string(aString?aString:""){} + ossimString(const ossimString& aString):std::string(aString.c_str()){} + ossimString(char aChar); + + /** + * Create a string with n copies of c. + */ + ossimString(size_type n, char c); + + template <class Iter> + ossimString(Iter start, Iter end):std::string(start, end){} + + + bool contains(const ossimString& aString) const {return find(aString)!=npos;} + bool contains(const char* aString) const {return find(aString)!=npos;} + + const ossimString& operator =(const char* s) + { + return (*this = ossimString(s)); + + } + const ossimString& operator =(char c) + { + return (*this = ossimString(c)); + + } + const ossimString& operator =(const ossimString& s) + { + std::string::operator =(s.c_str()); + return *this; + } + const ossimString& operator +=(const ossimString& s) + { + append(s.c_str()); + return *this; + } + const ossimString& operator +=(const char* s) + { + append(ossimString(s).c_str()); + return *this; + } + const ossimString& operator +=(char c) + { + append(ossimString(c).c_str()); + return *this; + } + ossimString operator +(const ossimString& s)const + { + ossimString returnS(*this); + + returnS.append(s.c_str()); + + return returnS; + } + ossimString operator +(const char* s)const + { + ossimString returnS(*this); + + returnS.append(ossimString(s).c_str()); + + return returnS; + } + ossimString operator +(char c)const + { + ossimString returnS(*this); + + returnS.append(ossimString(c).c_str()); + + return returnS; + } + bool operator==(const ossimString& s) const {return (strcmp(this->c_str(),s.c_str())==0);} + bool operator==(const char* s) const {return (strcmp(this->c_str(),s)==0);} + bool operator!=(const ossimString& s) const {return (strcmp(this->c_str(),s.c_str())!=0);} + bool operator!=(const char* s) const {return (strcmp(this->c_str(),s)!=0);} + + char& operator[](int i) + { + return *( const_cast<char*>(c_str())+i); + } + const char& operator[](int i)const + { + return *(c_str()+i); + } + /** + * this will strip lead and trailing character passed in. + * So if you want to remove blanks: + * ossimString temp(" asdfasdf "); + * ossimString trimmedString = temp.trim(" \n\t\r"); + * + * this will now contain "asdfasdf" without the blanks. + * + */ + ossimString trim(const ossimString& valueToTrim= ossimString(" \t\n\r"))const; + ossimString& trim(const ossimString& valueToTrim= ossimString(" \t\n\r")); + + ossimString beforePos(ossim_uint32 pos)const; + ossimString afterPos(ossim_uint32 pos)const; + + /** + * Substitudes searchKey string with replacementValue and returns a + * string. Will replace all occurrances found if "replaceAll" is true. + */ + ossimString substitute(const ossimString &searchKey, + const ossimString &replacementValue, + bool replaceAll=false)const; + + /** + * Substitudes searchKey string with replacementValue and returns a + * reference to *this. Will replace all occurrances found if + * "replaceAll" is true. (like substitute only works on "this") + */ + ossimString& gsub(const ossimString &searchKey, + const ossimString &replacementValue, + bool replaceAll=false); + + std::vector<ossimString> explode(const ossimString& delimeter) const; + + /** + * @param aString String to make an upcased copy of. + * + * @return An upcased version of aString. + */ + static ossimString upcase(const ossimString& aString); + + /** + * @param aString String to make an downcased copy of. + * + * @return A downcased version of aString. + */ + static ossimString downcase(const ossimString& aString); + + /** + * Upcases this string. + * + * @return Reference to this. + */ + ossimString& upcase(); + + /** + * Downcases this string. + * + * @return Reference to this. + */ + ossimString& downcase(); + + operator const char*()const{return c_str();} + const char* chars()const{return c_str();} + + /** + * METHOD: before(str, pos) + * Returns string beginning at pos and ending one before the token str + * If string not found or pos out of range the whole string will be + * returned. + */ + ossimString before(const ossimString& str, ossim_uint32 pos=0); + + /** + * METHOD: after(str, pos) + * Returns string immediately after the token str. The search for str + * begins at pos. Returns an emptry string if not found or pos out of + * range. + */ + ossimString after (const ossimString& str, ossim_uint32 pos=0); + + char* stringDup()const; + + /** + * String to numeric methods. + */ + bool toBool()const; + static bool toBool(const ossimString& aString); + int toInt()const; + static int toInt(const ossimString& aString); + ossim_int32 toInt32()const; + static ossim_int32 toInt32(const ossimString& aString); + ossim_uint32 toUInt32()const; + static ossim_uint32 toUInt32(const ossimString& aString); + long toLong()const; + static long toLong(const ossimString& aString); + unsigned long toULong()const; + static unsigned long toULong(const ossimString& aString); + double toDouble()const; + static double toDouble(const ossimString& aString); + + /** + * Numeric to string methods. + */ + static ossimString toString(bool aValue); + static ossimString toString(ossim_int16 aValue); + static ossimString toString(ossim_uint16 aValue); + static ossimString toString(ossim_int32 aValue); + static ossimString toString(ossim_uint32 aValue); + static ossimString toString(long aValue); + static ossimString toString(unsigned long aValue); + + /** + * @param aValue Value to convert to string. + * + * @param precision Decimal point precision of the output. + * + * @param trimZeroFlag If true trailing '0's and any trailing '.' will + * be trimmed. + * + * @param scientific If true output will be in scientific notation else + * fixed is used. + */ + static ossimString toString(ossim_float32 aValue, + int precision = 8, + bool trimZeroFlag = false, + bool scientific = false ); + + /** + * @param aValue Value to convert to string. + * + * @param precision Decimal point precision of the output. + * + * @param trimZeroFlag If true trailing '0's and any trailing '.' will + * be trimmed. + * + * @param scientific If true output will be in scientific notation else + * fixed is used. + */ + static ossimString toString(ossim_float64 aValue, + int precision = 15, + bool trimZeroFlag = false, + bool scientific = false); + + static ossimString stripLeading(const ossimString &value, + char characterToStrip); + + + void split(std::vector<ossimString>& result, + const ossimString& separatorList)const; + + std::vector<ossimString> split(const ossimString& separatorList)const; + + const ossimString& join(const std::vector<ossimString>& stringList, + const ossimString& separator); + + //--- + // Regular expression pattern utilities + //--- + + /** + * Returns from start of string up to but not including found pattern. + * Returns "" if pattern not found. + */ + ossimString beforeRegExp(const char *regularExpressionPattern) const; + + /** + * Returns from position of found pattern to end of string. + * Returns "" if pattern not found. + */ + ossimString fromRegExp(const char *regularExpressionPattern) const; + + /** + * Returns from position after found pattern to end of string. + * Returns "" if pattern not found. + */ + ossimString afterRegExp(const char *regularExpressionPattern) const; + + /** + * Returns from found pattern to end of pattern. + * Returns "" if pattern not found. + */ + ossimString match(const char *regularExpressionPattern) const; + + ossimString replaceAllThatMatch(const char *regularExpressionPattern, + const char *value="") const; + + ossimString replaceStrThatMatch(const char *regularExpressionPattern, + const char *value="") const; + + /** + * If OSSIM_ID_ENABLED returns the OSSIM_ID which currently is the + * expanded cvs $Id: ossimString.h,v 1.42 2005/10/17 18:37:16 gpotts Exp $ macro; else, an empty string. + */ + ossimString getOssimId() const; +}; + +#endif /* #ifndef ossimString_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimTempFilename.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimTempFilename.cpp new file mode 100644 index 0000000000..8e92c8ad66 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimTempFilename.cpp @@ -0,0 +1,114 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// Description: This is a tmeporary filename class it will create a temporary +// file and will also delete it upon destruction +// +//************************************************************************* +// $Id: ossimTempFilename.cpp,v 1.5 2005/10/04 15:10:35 gpotts Exp $ +#include <stdlib.h> +#include <fstream> +#include "ossimTempFilename.h" +#include <time.h> + +ossimTempFilename::ossimTempFilename(const ossimString& tempDir, + const ossimString& prefix, + const ossimString& extension, + bool autodelete, + bool useWildcardDelete) + :theTempDir(tempDir), + thePrefix(prefix), + theExtension(extension), + theAutoDeleteFlag(autodelete), + theWildCardDeleteFlag(useWildcardDelete) +{ +} + +ossimTempFilename::~ossimTempFilename() +{ + if(*((ossimFilename*)this) != "") + { + + if(theAutoDeleteFlag) + { + if(theWildCardDeleteFlag) + { + wildcardRemove(*this + ".*"); + } + else + { + remove(); + } + } + } +} + +void ossimTempFilename::generateRandomFile() +{ + generate(false); +} + +void ossimTempFilename::generateRandomDir() +{ + generate(true); +} + +void ossimTempFilename::generate(bool createAsDirectoryFlag) +{ + srand(time(0)); + ossimString tempDirCopy = theTempDir; + + if(tempDirCopy == "") + { + tempDirCopy = ossimString(getenv("TEMP")); + if(tempDirCopy=="") + { + tempDirCopy = ossimString(getenv("TMP")); + } + if(tempDirCopy == "") + { + if(ossimFilename("/tmp").exists()) + { + tempDirCopy = "/tmp"; + } + } + } + + int count = 0; + int randNumber1 = rand(); + ossimFilename prefixDir = ossimFilename(tempDirCopy); + ossimFilename result = prefixDir.dirCat(thePrefix+ + ossimString::toString(randNumber1)); + + while((count < RAND_MAX)&&result.exists()) + { + randNumber1 = rand(); + result = prefixDir.dirCat(thePrefix+ + ossimString::toString(randNumber1)); + + ++count; + } + + if(theExtension != "") + { + result = result.setExtension(theExtension); + } + *((ossimFilename*)this) = result; + if(result != "") + { + if(createAsDirectoryFlag) + { + createDirectory(); + } + else + { + std::ofstream out(result.c_str()); + out.close(); + } + } +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimTempFilename.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimTempFilename.h new file mode 100644 index 0000000000..5fc2a1d6c3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimTempFilename.h @@ -0,0 +1,42 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// Description: This is a tmeporary filename class it will create a temporary +// file and will also delete it upon destruction +// +//************************************************************************* +// $Id: ossimTempFilename.h,v 1.3 2005/10/03 13:20:24 gpotts Exp $ +#ifndef ossimTempFilename_HEADER +#define ossimTempFilename_HEADER +#include <base/data_types/ossimFilename.h> + +class OSSIM_DLL ossimTempFilename : public ossimFilename +{ +public: + ossimTempFilename(const ossimString& tempDir="", + const ossimString& prefix = "", + const ossimString& extension = "", + bool autodelete=true, + bool useWildcardDelete=true); + + void generateRandomFile(); + void generateRandomDir(); + + ~ossimTempFilename(); + +protected: + ossimString theTempDir; + ossimString thePrefix; + ossimString theExtension; + bool theAutoDeleteFlag; + bool theWildCardDeleteFlag; + + + void generate(bool createAsDirectoryFlag); +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimVrect.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimVrect.cpp new file mode 100644 index 0000000000..976e00c206 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimVrect.cpp @@ -0,0 +1,41 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +// Contains class declaration for vrect. +// Container class for four double points representing a rectangle +// where y is up +// +//******************************************************************* +// $Id: ossimVrect.cpp,v 1.3 2005/07/15 18:51:25 dburken Exp $ + +#include "ossimVrect.h" + +//******************************************************************* +// Public Method: +//******************************************************************* +void ossimVrect::print(std::ostream& os) const +{ + os << theUlCorner << theLrCorner; +} + +//******************************************************************* +// friend function: +//******************************************************************* +std::ostream& operator<<(std::ostream& os, const ossimVrect& rect) +{ + rect.print(os); + + return os; +} + +ossimVrect::~ossimVrect() +{ +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimVrect.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimVrect.h new file mode 100644 index 0000000000..72f5a38538 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimVrect.h @@ -0,0 +1,162 @@ +//******************************************************************* +// +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +// Contains class declaration for vrect. +// Container class for four double points representing a rectangle +// where y is up +// +//******************************************************************* +// $Id: ossimVrect.h,v 1.5 2005/07/15 18:51:25 dburken Exp $ +#ifndef ossimVrect_HEADER +#define ossimVrect_HEADER +#include <iostream> + +#include <base/data_types/ossimDpt.h> + +class OSSIMDLLEXPORT ossimVrect +{ +public: + ossimVrect() + :theUlCorner(0.0, 0.0), + theLlCorner(0.0, 0.0), + theLrCorner(0.0, 0.0), + theUrCorner(0.0, 0.0) + {} + ossimVrect(const ossimDpt &ul, + const ossimDpt &lr) + :theUlCorner(ul), + theLlCorner(ul.x, lr.y), + theLrCorner(lr), + theUrCorner(lr.x, ul.y) + {} + ossimVrect(double ul_corner_x, + double ul_corner_y, + double lr_corner_x, + double lr_corner_y) + : + theUlCorner(ul_corner_x, ul_corner_y), + theLlCorner(ul_corner_x, lr_corner_y), + theLrCorner(lr_corner_x, lr_corner_y), + theUrCorner(lr_corner_x, ul_corner_y) + {} + ossimVrect(const ossimVrect& rect) + : + theUlCorner(rect.ul()), + theLlCorner(rect.ll()), + theLrCorner(rect.lr()), + theUrCorner(rect.ur()) + {} + + ~ossimVrect(); + + const ossimVrect& operator= (const ossimVrect& rect); + bool operator!= (const ossimVrect& rect) const; + bool operator== (const ossimVrect& rect) const; + + const ossimDpt &ul() const { return theUlCorner; } + const ossimDpt &ur() const { return theUrCorner; } + const ossimDpt &lr() const { return theLrCorner; } + const ossimDpt &ll() const { return theLlCorner; } + /*! + * Returns the height of a rectangle. + */ + ossim_float64 height() const + { return fabs(theLlCorner.y - theUlCorner.y) + 1.0; } + + /*! + * Returns the width of a rectangle. + */ + ossim_float64 width() const + { return fabs(theLrCorner.x - theLlCorner.x) + 1.0; } + + inline ossimDpt midPoint()const; + void print(std::ostream& os) const; + + ossimVrect combine(const ossimVrect& rect)const; + inline ossimVrect clipToRect(const ossimVrect& rect)const; + + friend std::ostream& operator<<(std::ostream& os, const ossimVrect& rect); + +private: + ossimDpt theUlCorner; + ossimDpt theLlCorner; + ossimDpt theLrCorner; + ossimDpt theUrCorner; +}; + +inline const ossimVrect& ossimVrect::operator=(const ossimVrect& rect) +{ + if (this != &rect) + { + theUlCorner = rect.ul(); + theUrCorner = rect.ur(); + theLrCorner = rect.lr(); + theLlCorner = rect.ll(); + } + + return *this; +} + +inline bool ossimVrect::operator!=(const ossimVrect& rect) const +{ + return ( (theUlCorner != rect.ul()) || + (theUrCorner != rect.ur()) || + (theLrCorner != rect.lr()) || + (theLlCorner != rect.ll()) ); +} + +inline bool ossimVrect::operator==(const ossimVrect& rect) const +{ + return ( (theUlCorner == rect.ul()) && + (theUrCorner == rect.ur()) && + (theLrCorner == rect.lr()) && + (theLlCorner == rect.ll()) ); +} + +#define d_MIN(a,b) (((a)<(b)) ? a : b) +#define d_MAX(a,b) (((a)>(b)) ? a : b) + +inline ossimVrect ossimVrect::clipToRect(const ossimVrect& rect)const +{ + ossim_float64 ulx, uly, lrx, lry; + + ulx = d_MAX(rect.ul().x,ul().x); + uly = d_MAX(rect.ul().y,ul().y); + lrx = d_MIN(rect.lr().x,lr().x); + lry = d_MIN(rect.lr().y,lr().y); + + if( lrx <= ulx || lry <= uly ) + return ossimVrect(ossimDpt(0,0),ossimDpt(0,0)); + else + return ossimVrect(ulx,uly,lrx,lry); +} + +inline ossimDpt ossimVrect::midPoint()const +{ + return ossimDpt( (ul().x + ur().x + ll().x + lr().x)*.25, + (ul().y + ur().y + ll().y + lr().y)*.25); +} + +inline ossimVrect ossimVrect::combine(const ossimVrect& rect)const +{ + ossimDpt ulCombine; + ossimDpt lrCombine; + + ulCombine.x = ((ul().x <= rect.ul().x)?ul().x:rect.ul().x); + ulCombine.y = ((ul().y >= rect.ul().y)?ul().y:rect.ul().y); + lrCombine.x = ((lr().x >= rect.lr().x)?lr().x:rect.lr().x); + lrCombine.y = ((lr().y <= rect.lr().y)?lr().y:rect.lr().y); + + return ossimVrect(ulCombine, lrCombine); +} + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimXmlAttribute.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimXmlAttribute.cpp new file mode 100644 index 0000000000..e0d6b50294 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimXmlAttribute.cpp @@ -0,0 +1,236 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. All rights reserved. +// +// License: See top level LICENSE.txt file. +// +// Author: Oscar Kramer (ossim port by D. Burken) +// +// Description: +// +// Contains definition of class ossimXmlAttribute. +// +//***************************************************************************** +// $Id: ossimXmlAttribute.cpp,v 1.6 2005/12/16 14:26:21 dburken Exp $ + +#include <iostream> +#include <sstream> + +#include <base/data_types/ossimXmlAttribute.h> +#include <base/context/ossimNotifyContext.h> + +RTTI_DEF2(ossimXmlAttribute, "ossimXmlAttribute", ossimObject, ossimErrorStatusInterface) + +static std::istream& xmlskipws(std::istream& in) +{ + int c = in.peek(); + while((c == ' ') || + (c == '\t') || + (c == '\n')) + { + in.ignore(1); + c = in.peek(); + } + + return in; +} + +ossimXmlAttribute::ossimXmlAttribute(ossimString& spec) +{ + std::stringstream in(spec); + + read(in); +} + +ossimXmlAttribute::ossimXmlAttribute(const ossimXmlAttribute& src) + :theName(src.theName), + theValue(src.theValue) +{ +} + +bool ossimXmlAttribute::read(std::istream& in) +{ + in >> xmlskipws; + if(readName(in)) + { + in >> xmlskipws; + if(in.peek() != '=') + { + setErrorStatus(); + return false; + } + in.ignore(1); + if(readValue(in)) + { + return true; + } + else + { + setErrorStatus(); + return false; + } + } + return false; + +#if 0 + // + // Pull out name: + // + theName = spec.before('='); + theName = theName.trim(); + if (theName.empty()) + { + ossimNotify(ossimNotifyLevel_FATAL) << "ossimXmlAttribute::ossimXmlAttribute \n" + << "Bad attribute format encountered near:\n\""<< spec<<"\"\n" + << "Parsing aborted...\n"; + setErrorStatus(); + + return; + } + spec = spec.after('='); + + //*** + // Read value: + //*** + char quote_char = spec[0]; + spec = spec.after(quote_char); // after first quote + theValue = spec.before(quote_char); // before second quote + + // + // Reposition attribute specification to the start of next attribute or end + // of tag: + // + spec = spec.after(quote_char); // after second quote + ossimString next_entry ("-?[+0-9A-Za-z<>]+"); + spec = spec.fromRegExp(next_entry.c_str()); +#endif +} + +ossimXmlAttribute::~ossimXmlAttribute() +{ +} + +ossimXmlAttribute::ossimXmlAttribute() +{ +} + +ossimXmlAttribute::ossimXmlAttribute(const ossimString& name, + const ossimString& value) +{ + setNameValue(name, value); +} + +ossimString ossimXmlAttribute::getName() const +{ + return theName; +} + +ossimString ossimXmlAttribute::getValue() const +{ + return theValue; +} + +void ossimXmlAttribute::setNameValue(const ossimString& name, + const ossimString& value) +{ + theName = name; + theValue = value; +} + +void ossimXmlAttribute::setName(const ossimString& name) +{ + theName = name; +} + +void ossimXmlAttribute::setValue(const ossimString& value) +{ + theValue = value; +} + +std::ostream& operator << (std::ostream& os, const ossimXmlAttribute* xml_attr) +{ + os << " " << xml_attr->theName << "=\"" << xml_attr->theValue << "\""; + + return os; +} + + +bool ossimXmlAttribute::readName(std::istream& in) +{ + in >>xmlskipws; + theName = ""; + char c = in.peek(); + while((c != ' ')&& + (c != '\n')&& + (c != '\t')&& + (c != '=')&& + (c != '<')&& + (c != '/')&& + (c != '>')&& + (!in.bad())) + { + theName += (char)in.get(); + c = in.peek(); + } + + return ((!in.bad())&& + (theName != "")); +} + +bool ossimXmlAttribute::readValue(std::istream& in) +{ + in >>xmlskipws; + theValue = ""; + char c = in.peek(); + bool done = false; + + if((c == '\'')|| + (c == '"')) + { + theValue += in.get(); + while(!done&&!in.bad()) + { + c = in.peek(); + if((c == '\'')|| + (c == '"')) + { + theValue += c; + done = true; + in.ignore(1); + + } + else if(c == '\n') + { + done = true; + } + else + { + theValue += in.get(); + } + } + } + + if(theValue != "") + { + ossimString::iterator startIter = theValue.begin(); + ossimString::iterator endIter = --theValue.end(); + if((*startIter == '\'')|| + (*startIter == '"')) + { + ++startIter; + } + else + { + return false; + setErrorStatus(); + } + if((*endIter != '\'')&& + (*endIter != '"')) + { + return false; + setErrorStatus(); + } + theValue = ossimString(startIter, endIter); + } + return ((!in.bad())&& + (theValue !="")); +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimXmlAttribute.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimXmlAttribute.h new file mode 100644 index 0000000000..45b54e877f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimXmlAttribute.h @@ -0,0 +1,52 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. All rights reserved. +// +// License: See top level LICENSE.txt file. +// +// Author: Oscar Kramer (ossim port by D. Burken) +// +// Description: +// +// Contains declaration of class ossimAttribute. +// +//***************************************************************************** +// $Id: ossimXmlAttribute.h,v 1.6 2005/12/16 14:26:21 dburken Exp $ +#ifndef ossimXmlAttribute_HEADER +#define ossimXmlAttribute_HEADER + +#include <base/common/ossimErrorStatusInterface.h> +#include "ossimString.h" +#include <base/common/ossimObject.h> + +class OSSIMDLLEXPORT ossimXmlAttribute : public ossimObject, + public ossimErrorStatusInterface +{ +public: + ossimXmlAttribute(ossimString& spec); // attribute removed from spec string + ossimXmlAttribute(); + ossimXmlAttribute(const ossimXmlAttribute& src); + ossimXmlAttribute(const ossimString& name, + const ossimString& value); + ~ossimXmlAttribute(); + + bool read(std::istream& in); + ossimString getName() const; + ossimString getValue() const; + void setNameValue(const ossimString& name, + const ossimString& value); + void setName(const ossimString& name); + void setValue(const ossimString& value); + + OSSIMDLLEXPORT friend std::ostream& operator<<( + std::ostream& os, const ossimXmlAttribute* xml_attr); + +protected: + ossimString theName; + ossimString theValue; + + bool readName(std::istream& in); + bool readValue(std::istream& in); +TYPE_DATA +}; + +#endif /* #ifndef ossimXmlAttribute_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimXmlDocument.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimXmlDocument.cpp new file mode 100644 index 0000000000..8accdb476c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimXmlDocument.cpp @@ -0,0 +1,409 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. All rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Oscar Kramer (ossim port by D. Burken) +// +// Description: +// +// Contains definition of class ossimXmlDocument. This class provides read-only +// parsing and accessing of an XML document file. +//***************************************************************************** +// $Id: ossimXmlDocument.cpp,v 1.7 2005/06/13 18:53:37 gpotts Exp $ + +#include <stack> +#include <iostream> +#include <fstream> +using namespace std; + +#include <base/data_types/ossimXmlDocument.h> +#include <base/data_types/ossimXmlAttribute.h> +#include <base/data_types/ossimXmlNode.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimRegExp.h> +#include <base/context/ossimNotifyContext.h> +#include <base/common/ossimKeywordNames.h> + +// +// Static trace for debugging +// +#include "base/common/ossimTrace.h" +static ossimTrace traceDebug("ossimXmlDocument:debug"); + +static std::istream& xmlskipws(std::istream& in) +{ + int c = in.peek(); + while((c == ' ') || + (c == '\t') || + (c == '\n')) + { + in.ignore(1); + c = in.peek(); + } + + return in; +} + +static const int BUFFER_MAX_LEN = 1000; +static const ossimString XPATH_DELIM ("/"); + +RTTI_DEF1(ossimXmlDocument, "ossimXmlDocument", ossimObject) +ossimXmlDocument::ossimXmlDocument(const ossimFilename& xmlFileName) + : + theRootNode (0), + theXmlHeader("<?xml version='1.0'?>") +{ + + if(xmlFileName != "") + { + openFile(xmlFileName); + } +} + +ossimXmlDocument::~ossimXmlDocument() +{ +} + +bool ossimXmlDocument::write(const ossimFilename& file) +{ + std::ofstream out(file); + + if(out) + { + out << *this << std::endl; + } + else + { + return false; + } + + return true; +} + +bool ossimXmlDocument::openFile(const ossimFilename& filename) +{ + + theFilename = filename; + + if(theFilename == "") + { + return false; + } + + // + // Open XML File: + // Note: Opening text document binary to overcome an apparent windows bug. + // + ifstream xml_stream (filename.c_str(), ios::binary); + if (!xml_stream) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG: ossimXmlDocument::ossimXmlDocument\n" + << "encountered opening file <" << filename << "> for " + << "reading. Aborting..." << endl; + } + return false; + } + + return read(xml_stream); +} + +bool ossimXmlDocument::read(std::istream& in) +{ +// char buffer[BUFFER_MAX_LEN]; +// streampos file_pos; +// bool readingHeader = true; + bool startTagCharacterFound = false; + char c = in.peek(); + + + // initially we will do our own skipping to make sure we ar not binary + // + while(!in.bad()&& + (c != '<')&& + (c >= 0x20)&&(c <= 0x7e)) + { + in.ignore(1); + c = in.peek(); + } + + if (in.bad()|| + (c!='<')) + { + setErrorStatus(); + return false; + } + startTagCharacterFound = true; + + theXmlHeader = ""; + if(readHeader(in)) + { + if(theXmlHeader=="") + { + if(startTagCharacterFound) + { + theXmlHeader = "<?xml version='1.0'?>"; + } + else + { + setErrorStatus(); + return false; + } + } + } + if((!theXmlHeader.contains("xml version"))&& + (!startTagCharacterFound)) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "FATAL: ossimXmlDocument::ossimXmlDocument" + << "encountered parsing XML file <" << theFilename + << ">. The file does not appear to be XML v1.0. \n" + << "Header = \n" << theXmlHeader <<"\n" + << endl; + } + setErrorStatus(); + return false; + } + theRootNode = new ossimXmlNode(in, 0); + setErrorStatus(theRootNode->getErrorStatus()); + return (getErrorStatus()==ossimErrorCodes::OSSIM_OK); +} + +void ossimXmlDocument::findNodes(const ossimString& arg_xpath, + vector<ossimRefPtr<ossimXmlNode> >& result) const +{ + // + // First verify the root node exists: + // + if (!theRootNode.valid()) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "WARNING: ossimXmlDocument::findNodes,\n" + << "No root node has been instantiated. Returning null " + << "node list..." << endl; + } + return; + } + + // + // Make a copy to manipulate: + // + ossimString xpath (arg_xpath); + if (xpath.empty()) + return; + + // + // Check if absolute path: + // + if (xpath[0] != XPATH_DELIM[0]) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "WARNING: ossimXmlDocument::findNodes\n" + << "Only absolute XPaths are supported. Returning null " + << "node list..." << endl; + } + return; + } + + // + // Check that root tag matches path root: + // + ossimString rel_xpath (xpath.after(XPATH_DELIM)); + ossimString root_tag (rel_xpath); + if (root_tag.contains(XPATH_DELIM)) + root_tag = rel_xpath.before(XPATH_DELIM); + + if (root_tag != theRootNode->getTag()) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "WARNING: ossimXmlDocument::findNodes\n" + << "XPath's root node <"<<root_tag<<"> does not match the " + << "stored root node's tag <" << theRootNode->getTag() << ">. " + << "Returning null node list..." << endl; + } + return; + } + + // + // If the root node was the requested node, return it alone: + // + rel_xpath = rel_xpath.after(XPATH_DELIM); + if (rel_xpath.empty()) + { + result.push_back(theRootNode); + return; + } + + // + // Pass the node request on to the root node with the relative path: + // + theRootNode->findChildNodes(rel_xpath, result); +} + +ostream& operator << (ostream& os, const ossimXmlDocument& xml_doc) +{ + os << xml_doc.theXmlHeader << endl; + if (xml_doc.theRootNode.valid()) + { + os << (xml_doc.theRootNode.get()) << endl; + } +// else +// os << "-- no root node assigned -- " << endl; + + return os; +} + +void ossimXmlDocument::initRoot(ossimRefPtr<ossimXmlNode> node) +{ + theRootNode = node; +} + +ossimRefPtr<ossimXmlNode> ossimXmlDocument::getRoot() +{ + return theRootNode; +} + +const ossimRefPtr<ossimXmlNode> ossimXmlDocument::getRoot()const +{ + return theRootNode; +} + +ossimRefPtr<ossimXmlNode> ossimXmlDocument::removeRoot() +{ + ossimRefPtr<ossimXmlNode> root = theRootNode; + + theRootNode = 0; + + return root; +} + + +void ossimXmlDocument::fromKwl(const ossimKeywordlist& kwlToConvert) +{ + + ossimKeywordlist kwl = kwlToConvert; + theRootNode = 0; + theRootNode = new ossimXmlNode; + + + ossimString prefix = ""; + ossimKeywordlist::KeywordMap& map = kwl.getMap(); + ossimKeywordlist::KeywordMap::iterator mapIter = map.begin(); + + while(mapIter != map.end()) + { + ossimString key = mapIter->first; + key = key.substitute(".", "/", true); + theRootNode->addNode(key, mapIter->second); + ++mapIter; + } + + // now collapse all keywordlist styles to the XML style + // + std::stack<ossimRefPtr<ossimXmlNode> > tempStack; + tempStack.push(theRootNode); + while(!tempStack.empty()) + { + + ossimRefPtr<ossimXmlNode> node = tempStack.top(); + tempStack.pop(); + vector<ossimRefPtr<ossimXmlNode> >& childNodes = node->getChildNodes(); + ossim_uint32 idx = 0; + for(idx = 0; idx < childNodes.size(); ++idx) + { + tempStack.push(childNodes[idx]); + } + if(node->getChildNodes().size() > 0) + { + if(node->getTag()!="") + { + node->addAttribute("name", node->getTag()); + } + node->setTag("object"); + } + + if(node->getTag() == "type") + { + if(node->getParentNode()) + { + node->getParentNode()->removeChild("type"); + node->getParentNode()->addAttribute("type", node->getText()); + } + } + else if(node->getChildNodes().size() < 1) + { + if(node->getTag()!="") + { + node->addAttribute("name", node->getTag()); + } + if(!node->getText().contains("\n")) + { + if(node->getText()!="") + { + node->addAttribute("value", node->getText()); + node->setText(""); + } + } + node->setTag("property"); + } + } +} + +void ossimXmlDocument::toKwl(ossimKeywordlist& kwl , + const ossimString& prefix)const +{ + +// const std::vector<ossimRefPtr<ossimXmlNode> >& children = theRootNode->getChildNodes(); + +// ossim_uint32 idx = 0; + +// for(idx = 0; idx < children.size(); ++idx) +// { +// children[idx]->toKwl(kwl, prefix); +// } + theRootNode->toKwl(kwl, prefix); +} + +bool ossimXmlDocument::readHeader(std::istream& in) +{ + char c; + in>>xmlskipws; + + while(in.peek() == '<') + { + in.ignore(1); + c = in.peek(); + if((c == '?')|| + (c == '!')) + { + theXmlHeader += "<"; + theXmlHeader += (char)in.get(); + + while((in.peek() != '>')&& + (!in.bad())) + { + theXmlHeader += (char)in.get(); + } + if(!in.bad()) + { + theXmlHeader += (char)in.get(); + } + in>>xmlskipws; + } + } + + return (!in.bad()); +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimXmlDocument.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimXmlDocument.h new file mode 100644 index 0000000000..3ea409963f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimXmlDocument.h @@ -0,0 +1,74 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. All rights reserved. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Oscar Kramer <okramer@imagelinks.com> (ossim port by D. Burken) +// +// Description: +// +// Contains declaration of class ossimXmlDocument. This class provides read-only +// parsing and accessing of an XML document file. +// +//***************************************************************************** +// $Id: ossimXmlDocument.h,v 1.4 2005/06/17 13:35:57 gpotts Exp $ +#ifndef ossimXmlDocument_HEADER +#define ossimXmlDocument_HEADER + +#include <vector> +#include <base/common/ossimObject.h> +#include <base/common/ossimErrorStatusInterface.h> +#include <base/common/ossimRefPtr.h> +#include "ossimFilename.h" + +class ossimXmlNode; + +class OSSIMDLLEXPORT ossimXmlDocument : public ossimObject, + public ossimErrorStatusInterface +{ +public: + ossimXmlDocument(const ossimFilename& xmlFileName=""); + ~ossimXmlDocument(); + + bool write(const ossimFilename& file); + bool openFile(const ossimFilename& filename); + bool read(std::istream& in); + /** + * Appends any matching nodes to the list supplied (should be empty): + */ + void findNodes(const ossimString& xpath, + std::vector<ossimRefPtr<ossimXmlNode> >& nodelist) const; + + OSSIMDLLEXPORT friend std::ostream& operator << (std::ostream& os, const ossimXmlDocument& xml_doc); + + void initRoot(ossimRefPtr<ossimXmlNode> node); + + ossimRefPtr<ossimXmlNode> getRoot(); + const ossimRefPtr<ossimXmlNode> getRoot()const; + ossimRefPtr<ossimXmlNode> removeRoot(); + void fromKwl(const ossimKeywordlist& kwl); + void toKwl(ossimKeywordlist& kwl, const ossimString& prefix = "")const; + +private: + ossimRefPtr<ossimXmlNode> theRootNode; + ossimString theXmlHeader; + ossimFilename theFilename; + + bool readHeader(std::istream& in); +TYPE_DATA +}; + +#endif /* #ifndef ossimXmlDocument_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimXmlNode.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimXmlNode.cpp new file mode 100644 index 0000000000..c163acac95 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimXmlNode.cpp @@ -0,0 +1,840 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. All rights reserved. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Oscar Kramer <okramer@imagelinks.com> (ossim port by D. Burken) +// +// Description: +// +// Contains definition of class ossimXmlNode. +// +//***************************************************************************** +// $Id: ossimXmlNode.cpp,v 1.12 2005/06/07 17:43:37 gpotts Exp $ + +#include <iostream> +using namespace std; + +#include <base/data_types/ossimXmlNode.h> +#include <base/data_types/ossimXmlAttribute.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/context/ossimNotifyContext.h> + +static const ossimString XPATH_DELIM ("/"); + +RTTI_DEF2(ossimXmlNode, "ossimXmlNode", ossimObject, ossimErrorStatusInterface); + +static std::istream& xmlskipws(std::istream& in) +{ + int c = in.peek(); + while((c == ' ') || + (c == '\t') || + (c == '\n')) + { + in.ignore(1); + c = in.peek(); + } + + return in; +} + + +ossimXmlNode::ossimXmlNode(istream& xml_stream, ossimXmlNode* parent) + : + theParentNode (parent) +{ + read(xml_stream); +} + +ossimXmlNode::ossimXmlNode() + :theParentNode(0) +{ +} + +ossimXmlNode::~ossimXmlNode() +{ +} + +void ossimXmlNode::setParent(ossimXmlNode* parent) +{ + theParentNode = parent; +} + +bool ossimXmlNode::read(std::istream& in) +{ + + in >> xmlskipws; + if(in.peek() == '<') + { + in.ignore(1); + } + streampos file_pos = in.tellg(); + ossimString endTag; + + + readTag(in, theTag); + char c = in.peek(); + + if(readEndTag(in, endTag)) + { + if((endTag == "")|| + (endTag == theTag)) + { + return true; + } + else + { + setErrorStatus(); + return false; + } + } + // now parse attributes + ossimRefPtr<ossimXmlAttribute> attribute = new ossimXmlAttribute; + while(attribute->read(in)) + { + theAttributes.push_back(new ossimXmlAttribute(*attribute)); + } + // skip white space characters + // + in >> xmlskipws; + + c = in.peek(); + + if(readEndTag(in, endTag)) + { + if((endTag == "")|| + (endTag == theTag)) + { + return true; + } + else + { + setErrorStatus(); + return false; + } + } + c = in.peek(); + // make sure the attribute is closed + // + if(c != '>') + { + setErrorStatus(); + return false; + } + + in.ignore(1); + c = in.peek(); + // now do the text portion + // + theText = ""; + + readTextContent(in, theText); + in >> xmlskipws; + c = in.peek(); + + c = in.peek(); + + if(c != '<') + { + setErrorStatus(); + return false; + } + in.ignore(1); + if(readEndTag(in, endTag)) + { + if((endTag == "")|| + (endTag == theTag)) + { + return true; + } + else + { + setErrorStatus(); + return false; + } + } + c = in.peek(); + // now if it's not an endtag then it must be a tag starting the new child node + // + bool done = false; + + ossimRefPtr<ossimXmlNode> childNode; + do + { + childNode = new ossimXmlNode; + childNode->setParent(this); + if(childNode->read(in)) + { + theChildNodes.push_back(childNode); + } + else + { + setErrorStatus(); + return false; + } + in >> xmlskipws; + + c = in.peek(); + if(c != '<') + { + setErrorStatus(); + return false; + } + in.ignore(1); + if(readEndTag(in, endTag)) + { + if((endTag == "")|| + (endTag == theTag)) + { + return true; + } + else + { + setErrorStatus(); + return false; + } + } + }while((!done)&&(!in.bad())); + + return true; +} + + +void ossimXmlNode::findChildNodes(const ossimString& xpath, + vector<ossimRefPtr<ossimXmlNode> >& result)const +{ + //*** + // Scan for trivial result (no children owned): + //*** + if (theChildNodes.size() == 0) + return; + + //*** + // Make a copy to manipulate: + //*** + ossimString rel_xpath (xpath); + if (rel_xpath.empty()) + return; + + //*** + // First verify that this is not an absolute path: + //*** + if (rel_xpath[0] == XPATH_DELIM[0]) + { + ossimNotify(ossimNotifyLevel_WARN) << "WARNING: ossimXmlNode::findChildNodes\n" + << "Only relative XPaths can be searched from a node. " + << "Returning null list...\n"; + return; + } + + //*** + // Read the desired tag from the relative xpath + //*** + ossimString desired_tag (rel_xpath); + if (rel_xpath.contains(XPATH_DELIM)) + desired_tag = rel_xpath.before(XPATH_DELIM); + ossimString sub_xpath (rel_xpath.after(XPATH_DELIM)); + + //*** + // Loop over all child nodes for match: + //*** + vector<ossimRefPtr<ossimXmlNode> >::const_iterator child_iter = theChildNodes.begin(); + while(child_iter != theChildNodes.end()) + { + if ((*child_iter)->getTag() == desired_tag) + { + if (sub_xpath.empty()) + { + //*** + // This was the final target node, simply append to the result: + //*** + result.push_back(*child_iter); + } + else + { + //*** + // This match identifies a possible tree to search given the + // remaining xpath (sub_xpath). Query this child node to search + // its tree for the remaining xpath: + //*** + (*child_iter)->findChildNodes(sub_xpath, result); + } + } + + //*** + // Proceed to next child: + //*** + child_iter++; + } +} + +const ossimRefPtr<ossimXmlNode> ossimXmlNode::findFirstNode(const ossimString& xpath)const +{ + if(theChildNodes.size() < 1) return 0; + // + // Make a copy to manipulate: + // + ossimString rel_xpath (xpath); + if (rel_xpath.empty()) + return 0; + + // + // First verify that this is not an absolute path: + // + if (rel_xpath[0] == XPATH_DELIM[0]) + { + ossimNotify(ossimNotifyLevel_WARN) << "WARNING: ossimXmlNode::findChildNodes\n" + << "Only relative XPaths can be searched from a node. " + << "Returning null list...\n"; + return 0; + } + + // + // Read the desired tag from the relative xpath + // + ossimString desired_tag (rel_xpath); + if (rel_xpath.contains(XPATH_DELIM)) + desired_tag = rel_xpath.before(XPATH_DELIM); + ossimString sub_xpath (rel_xpath.after(XPATH_DELIM)); + + ossimRefPtr<ossimXmlNode> result = 0; + + // + // Loop over all child nodes for match: + // + vector<ossimRefPtr<ossimXmlNode> >::const_iterator child_iter = theChildNodes.begin(); + while((child_iter != theChildNodes.end())&& + (!result.valid())) + { + if ((*child_iter)->getTag() == desired_tag) + { + if (sub_xpath.empty()) + { + return *child_iter; + } + else + { + // + // This match identifies a possible tree to search given the + // remaining xpath (sub_xpath). Query this child node to search + // its tree for the remaining xpath: + // + result = (*child_iter)->findFirstNode(sub_xpath); + } + } + + // + // Proceed to next child: + // + ++child_iter; + } + + return result; +} + +ossimRefPtr<ossimXmlNode> ossimXmlNode::findFirstNode(const ossimString& xpath) +{ + if(theChildNodes.size() < 1) return 0; + // + // Make a copy to manipulate: + // + ossimString rel_xpath (xpath); + if (rel_xpath.empty()) + return 0; + + // + // First verify that this is not an absolute path: + // + if (rel_xpath[0] == XPATH_DELIM[0]) + { + ossimNotify(ossimNotifyLevel_WARN) << "WARNING: ossimXmlNode::findChildNodes\n" + << "Only relative XPaths can be searched from a node. " + << "Returning null list...\n"; + return 0; + } + + // + // Read the desired tag from the relative xpath + // + ossimString desired_tag (rel_xpath); + if (rel_xpath.contains(XPATH_DELIM)) + desired_tag = rel_xpath.before(XPATH_DELIM); + ossimString sub_xpath (rel_xpath.after(XPATH_DELIM)); + + ossimRefPtr<ossimXmlNode> result = 0; + + // + // Loop over all child nodes for match: + // + vector<ossimRefPtr<ossimXmlNode> >::iterator child_iter = theChildNodes.begin(); + while((child_iter != theChildNodes.end())&& + (!result.valid())) + { + if ((*child_iter)->getTag() == desired_tag) + { + if (sub_xpath.empty()) + { + return *child_iter; + } + else + { + // + // This match identifies a possible tree to search given the + // remaining xpath (sub_xpath). Query this child node to search + // its tree for the remaining xpath: + // + result = (*child_iter)->findFirstNode(sub_xpath); + } + } + + // + // Proceed to next child: + // + ++child_iter; + } + + return result; +} + +ossimRefPtr<ossimXmlAttribute> ossimXmlNode::findAttribute(const ossimString& name) +{ + ossim_uint32 idx = 0; + + for(idx = 0; idx < theAttributes.size();++idx) + { + if(theAttributes[idx]->getName() == name) + { + return theAttributes[idx]; + } + } + + return 0; +} + +const ossimRefPtr<ossimXmlAttribute> ossimXmlNode::findAttribute(const ossimString& name)const +{ + ossim_uint32 idx = 0; + + for(idx = 0; idx < theAttributes.size();++idx) + { + if(theAttributes[idx]->getName() == name) + { + return theAttributes[idx]; + } + } + + return 0; +} + +void ossimXmlNode::setTag(const ossimString& tag) +{ + theTag = tag; +} + +ossimString ossimXmlNode::getTag() const +{ + return theTag; +} + +const ossimXmlNode* ossimXmlNode::getParentNode() const +{ + return theParentNode; +} + +ossimXmlNode* ossimXmlNode::getParentNode() +{ + return theParentNode; +} + +const vector<ossimRefPtr<ossimXmlNode> >& ossimXmlNode::getChildNodes() const +{ + return theChildNodes; +} + +vector<ossimRefPtr<ossimXmlNode> >& ossimXmlNode::getChildNodes() +{ + return theChildNodes; +} + +const vector<ossimRefPtr<ossimXmlAttribute> >& ossimXmlNode::getAttributes() const +{ + return theAttributes; +} + +void ossimXmlNode::setText(const ossimString& text) +{ + theText = text; +} + +ossimString ossimXmlNode::getText() const +{ + return theText; +} + +ostream& operator << (ostream& os, const ossimXmlNode& xml_node) +{ + return operator <<(os, &xml_node); +} + +//************************************************************************** +// FRIEND OPERATOR +//************************************************************************** +ostream& operator << (ostream& os, const ossimXmlNode* xml_node) +{ + // + // Determine the indentation level: + // + ossimString indent (""); + const ossimXmlNode* parent = xml_node->theParentNode; + while (parent) + { + indent += " "; + parent = parent->theParentNode; + } + + // + // Dump the tag opening: + // + os << "\n" << indent << "<" << xml_node->theTag; + + // + // Dump any attributes: + // + if (xml_node->theAttributes.size()) + { + vector<ossimRefPtr<ossimXmlAttribute> >::const_iterator attr = + xml_node->theAttributes.begin(); + while (attr != xml_node->theAttributes.end()) + { + os << attr->get(); + attr++; + } + } + + if((xml_node->theChildNodes.size() == 0)&& + (xml_node->theText == "")) + { + os << "/>"; + } + else + { + os << ">"; + + // + // Dump any text: + // + os << xml_node->theText; + + // + // Dump any child nodes: + // + if (xml_node->theChildNodes.size()) + { + vector<ossimRefPtr<ossimXmlNode> >::const_iterator nodes = xml_node->theChildNodes.begin(); + while (nodes != xml_node->theChildNodes.end()) + { + os << (*nodes).get(); + nodes++; + } + os << "\n" << indent; + } + + // + // Dump the tag closing: + // + os << "</" << xml_node->theTag << ">"; + } + + return os; +} + +void ossimXmlNode::addAttribute(ossimRefPtr<ossimXmlAttribute> attribute) +{ + theAttributes.push_back(attribute); +} + +void ossimXmlNode::addAttribute(const ossimString& name, + const ossimString& value) +{ + theAttributes.push_back(new ossimXmlAttribute(name, value)); +} + +ossimRefPtr<ossimXmlNode> ossimXmlNode::addNode(const ossimString& relPath, + const ossimString& text) +{ + // + // Make a copy to manipulate: + // + ossimString relXpath (relPath); + if (relXpath.empty()) + return 0; + + // + // First verify that this is not an absolute path: + // + if (relXpath[0] == XPATH_DELIM[0]) + { + ossimNotify(ossimNotifyLevel_WARN) << "WARNING: ossimXmlNode::findChildNodes\n" + << "Only relative XPaths can be searched from a node. " + << "Returning null list...\n"; + return 0; + } + + // + // Read the desired tag from the relative xpath + // + ossimString desiredTag (relXpath); + if (relXpath.contains(XPATH_DELIM)) + { + desiredTag = relXpath.before(XPATH_DELIM); + } + ossimString subPath (relXpath.after(XPATH_DELIM)); + + ossimRefPtr<ossimXmlNode> node = findFirstNode(desiredTag); + + if(!node.valid()) + { + if(subPath.empty()) + { + node = addChildNode(desiredTag, text); + } + else + { + node = addChildNode(desiredTag, ""); + } + } + if(!subPath.empty()) + { + return node->addNode(subPath, text); + } + + return node; +} + +ossimRefPtr<ossimXmlNode> ossimXmlNode::addOrSetNode(const ossimString& relPath, + const ossimString& text) +{ + + ossimRefPtr<ossimXmlNode> result = addNode(relPath, text); + + result->setText(text); + + return result; +} + +void ossimXmlNode::addChildNode(ossimRefPtr<ossimXmlNode> node) +{ + if(node->theParentNode) + { + node->theParentNode->removeChild(node); + } + node->theParentNode = this; + theChildNodes.push_back(node); +} + +ossimRefPtr<ossimXmlNode> ossimXmlNode::addChildNode(const ossimString& tagName, + const ossimString& text) +{ + ossimRefPtr<ossimXmlNode> node = new ossimXmlNode(); + node->setParent(this); + node->theTag = tagName; + node->theText = text; + theChildNodes.push_back(node); + + return node; +} + +ossimRefPtr<ossimXmlNode> ossimXmlNode::removeChild(ossimRefPtr<ossimXmlNode> node) +{ + vector<ossimRefPtr<ossimXmlNode> >::iterator iter = theChildNodes.begin(); + while(iter != theChildNodes.end()) + { + + if(node.get() == iter->get()) + { + ossimRefPtr<ossimXmlNode> temp = *iter; + + theChildNodes.erase(iter); + + return temp; + } + ++iter; + } + + return 0; +} + +ossimRefPtr<ossimXmlNode> ossimXmlNode::removeChild(const ossimString& tag) +{ + vector<ossimRefPtr<ossimXmlNode> >::iterator iter = theChildNodes.begin(); + while(iter != theChildNodes.end()) + { + if(tag == iter->get()->theTag) + { + ossimRefPtr<ossimXmlNode> temp = *iter; + + theChildNodes.erase(iter); + + return temp; + } + ++iter; + } + + return 0; +} + +void ossimXmlNode::toKwl(ossimKeywordlist& kwl, + const ossimString& prefix)const +{ + ossimRefPtr<ossimXmlAttribute> nameAtt = findAttribute("name"); + ossimRefPtr<ossimXmlAttribute> valueAtt = findAttribute("value"); + ossimRefPtr<ossimXmlAttribute> typeAtt = findAttribute("type"); + + ossimString name; + ossimString value; + ossimString type; + if(nameAtt.valid()) + { + name = nameAtt->getValue(); + } + if(valueAtt.valid()) + { + value = valueAtt->getValue(); + } + else + { + value = theText; + } + + if(typeAtt.valid()) + { + type = typeAtt->getValue(); + } + ossimString copyPrefix = prefix; + + if(name != "") + { + copyPrefix += (name+"."); + } + if(type!= "") + { + kwl.add(copyPrefix, + "type", + typeAtt->getValue(), + true); + } + + if(theChildNodes.size() < 1) + { + kwl.add(prefix+name, + value, + true); + } + else + { + ossim_uint32 idx=0; + + for(idx = 0; idx < theChildNodes.size();++idx) + { + theChildNodes[idx]->toKwl(kwl, + copyPrefix); + } + } +} + +bool ossimXmlNode::readTag(std::istream& in, + ossimString& tag) +{ + in >> xmlskipws; + + tag = ""; + int c = in.peek(); + + while( (c != ' ')&& + (c != '\n')&& + (c != '\t')&& + (c != '<')&& + (c != '>')&& + (c != '/')&& + (!in.bad())) + { + tag += (char)c; + in.ignore(1); + c = in.peek(); + } + + return ((tag != "")&&(!in.bad())); +} + +bool ossimXmlNode::readTextContent(std::istream& in, + ossimString& text) +{ + in >> xmlskipws; + + text = ""; + char c = in.peek(); + bool done = false; + + do + { + if(c == '<') + { + done = true; + } + else + { + text += (char)in.get(); + c = in.peek(); + } + }while((!in.bad())&& + (!done)); + + return (text != ""); +} + +bool ossimXmlNode::readEndTag(std::istream& in, + ossimString& endTag) +{ + bool result = false; + char c = in.peek(); + endTag = ""; + + // check end tag + // + if(c == '/') + { + in.ignore(); + readTag(in, endTag); + in >> xmlskipws; + c = in.peek(); + result = true; + } + else + { + return false; + } + if(c != '>') + { + setErrorStatus(); + return false; + } + else + { + in.ignore(1); + } + + return result; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimXmlNode.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimXmlNode.h new file mode 100644 index 0000000000..a37e04c688 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimXmlNode.h @@ -0,0 +1,103 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. All rights reserved. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Oscar Kramer <okramer@imagelinks.com> (ossim port by D. Burken) +// +// Description: +// +// Contains declaration of class ossimXmlNode. +// +//***************************************************************************** +// $Id: ossimXmlNode.h,v 1.9 2005/06/17 13:35:57 gpotts Exp $ +#ifndef ossimXmlNode_HEADER +#define ossimXmlNode_HEADER + +#include <vector> +using namespace std; + +#include "base/common/ossimObject.h" +#include "base/common/ossimRefPtr.h" +#include "base/common/ossimErrorStatusInterface.h" +#include "ossimXmlAttribute.h" +#include "ossimString.h" + + +class OSSIMDLLEXPORT ossimXmlNode : public ossimObject, + public ossimErrorStatusInterface +{ +public: + ossimXmlNode(istream& xml_stream, ossimXmlNode* parent=0); + ossimXmlNode(); + + bool read(std::istream& in); + // Appends any matching nodes to the list supplied + void findChildNodes(const ossimString& rel_xpath, + vector<ossimRefPtr<ossimXmlNode> >& nodelist)const; + const ossimRefPtr<ossimXmlNode> findFirstNode(const ossimString& rel_xpath)const; + ossimRefPtr<ossimXmlNode> findFirstNode(const ossimString& rel_xpath); + + ossimRefPtr<ossimXmlAttribute> findAttribute(const ossimString& name); + const ossimRefPtr<ossimXmlAttribute> findAttribute(const ossimString& name)const; + void setTag(const ossimString& tag); + ossimString getTag() const; + const ossimXmlNode* getParentNode() const; + ossimXmlNode* getParentNode(); + void setParent(ossimXmlNode* parent); + const vector<ossimRefPtr<ossimXmlNode> >& getChildNodes() const; + vector<ossimRefPtr<ossimXmlNode> >& getChildNodes(); + const vector<ossimRefPtr<ossimXmlAttribute> >& getAttributes() const; + void addAttribute(ossimRefPtr<ossimXmlAttribute> attribute); + void addAttribute(const ossimString& name, const ossimString& value); + ossimRefPtr<ossimXmlNode> addNode(const ossimString& relPath, + const ossimString& text = ""); + ossimRefPtr<ossimXmlNode> addOrSetNode(const ossimString& relPath, + const ossimString& text = ""); + void addChildNode(ossimRefPtr<ossimXmlNode> node); + ossimRefPtr<ossimXmlNode> addChildNode(const ossimString& tagName, + const ossimString& text=""); + void setText(const ossimString& text); + ossimString getText() const; + + OSSIMDLLEXPORT friend ostream& operator << (ostream& os, const ossimXmlNode* xml_node); + OSSIMDLLEXPORT friend ostream& operator << (ostream& os, const ossimXmlNode& xml_node); + + ossimRefPtr<ossimXmlNode> removeChild(ossimRefPtr<ossimXmlNode> node); + ossimRefPtr<ossimXmlNode> removeChild(const ossimString& tag); + + void toKwl(ossimKeywordlist& kwl, + const ossimString& prefix="")const; + void fromKwl(const ossimKeywordlist& kwlToConvert); + +protected: + ~ossimXmlNode(); + ossimString theTag; + ossimXmlNode* theParentNode; + vector<ossimRefPtr<ossimXmlNode> > theChildNodes; + vector<ossimRefPtr<ossimXmlAttribute> > theAttributes; + ossimString theText; + + bool readTag(std::istream& in, + ossimString& tag); + bool readTextContent(std::istream& in, + ossimString& text); + bool readEndTag(std::istream& in, + ossimString& endTag); +TYPE_DATA +}; + +#endif /* #ifndef ossimXmlNode_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimXmlString.cpp b/Utilities/OSSIM/ossim_core/base/data_types/ossimXmlString.cpp new file mode 100644 index 0000000000..4f904c38b2 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimXmlString.cpp @@ -0,0 +1,72 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// 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. +// +// 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. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Ken Melero (kmelero@remotesensing.org) +// Description: This class provides manipulation of filenames. +// +//************************************************************************* +// $Id: ossimXmlString.cpp,v 1.1 2002/06/12 20:39:30 gpotts Exp $ +#include "ossimXmlString.h" + +const ossimXmlString& ossimXmlString::assign(const ossimString& s) +{ + ossimString result = s; + + size_type pos = 0; + + pos = result.find("&"); + // do ampersand first + // + while(pos != npos) + { + ossimString s1(result.begin() + pos, + result.begin()+pos+5); + ossimString s2(result.begin() + pos, + result.begin()+pos+4); + ossimString s3(result.begin() + pos, + result.begin()+pos+3); + + if((s2 != "&")&& + (s1 != """)&& + (s3 != ">")&& + (s3 != "<")&& + (s1 != "&apos")) + { + result.replace(pos, 1, "&"); + } + + pos = result.find("&", pos+4); + } + + result = result.substitute("\"", + """, + true); + result = result.substitute("<", + "<", + true); + result = result.substitute(">", + ">", + true); + result = result.substitute("'", + "&apos", + true); + + *((ossimString*)this) = result; + + return *this; +} diff --git a/Utilities/OSSIM/ossim_core/base/data_types/ossimXmlString.h b/Utilities/OSSIM/ossim_core/base/data_types/ossimXmlString.h new file mode 100644 index 0000000000..e37bedbbde --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/data_types/ossimXmlString.h @@ -0,0 +1,79 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// 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. +// +// 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. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Ken Melero (kmelero@remotesensing.org) +// Description: This class provides manipulation of filenames. +// +//************************************************************************* +// $Id: ossimXmlString.h,v 1.3 2005/10/17 18:37:16 gpotts Exp $ + +#ifndef ossimXmlString_HEADER +#define ossimXmlString_HEADER + +#include "base/common/ossimConstants.h" +#include "ossimString.h" + +class OSSIM_DLL ossimXmlString : public ossimString +{ +public: + ossimXmlString() + : + ossimString() + {} + ossimXmlString(const ossimXmlString& src) + : + ossimString(src) + {} + ossimXmlString(const ossimString& src) + : + ossimString("") + { + assign(src); + + } + ossimXmlString(const char* src) + : + ossimString("") + { + assign(src); + } + + template <class Iter> + ossimXmlString(Iter s, Iter e) + :ossimString("") + { + assign(ossimString(s, e)); + } + + const ossimXmlString& operator =(const char* s) + { + return assign(ossimString(s)); + } + const ossimXmlString& operator =(const ossimString& s) + { + return assign(ossimString(s)); + } + const ossimXmlString& operator =(const std::string& s) + { + return assign(ossimString(s)); + } + + const ossimXmlString& assign(const ossimString& s); +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/factory/.cvsignore b/Utilities/OSSIM/ossim_core/base/factory/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/factory/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/base/factory/ossimBaseObjectFactory.cpp b/Utilities/OSSIM/ossim_core/base/factory/ossimBaseObjectFactory.cpp new file mode 100644 index 0000000000..f1b2d11a0b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/factory/ossimBaseObjectFactory.cpp @@ -0,0 +1,74 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimBaseObjectFactory.cpp,v 1.2 2002/03/26 19:05:22 gpotts Exp $ +#include "base/factory/ossimBaseObjectFactory.h" +#include "base/common/ossimConnectableContainer.h" +#include "base/common/ossimKeywordNames.h" +#include "base/data_types/ossimKeywordlist.h" + +RTTI_DEF1(ossimBaseObjectFactory, "ossimBaseObjectFactory", ossimObjectFactory); + +ossimBaseObjectFactory* ossimBaseObjectFactory::theInstance = NULL; + +ossimBaseObjectFactory* ossimBaseObjectFactory::instance() +{ + if(!theInstance) + { + theInstance = new ossimBaseObjectFactory; + } + + return theInstance; +} + +ossimObject* ossimBaseObjectFactory::createObject(const ossimString& typeName)const +{ + if(typeName == STATIC_TYPE_NAME(ossimConnectableContainer)) + { + return new ossimConnectableContainer; + } + + return (ossimObject*)NULL; +} + +ossimObject* ossimBaseObjectFactory::createObject(const ossimKeywordlist& kwl, + const char* prefix)const +{ + const char* type = kwl.find(prefix, + ossimKeywordNames::TYPE_KW); + ossimString copyPrefix = prefix; + if(type) + { + ossimObject* object = createObject(ossimString(type)); + if(object) + { + object->loadState(kwl, copyPrefix.c_str()); + } + return object; + } + return NULL; +} + +void ossimBaseObjectFactory::getTypeNameList(std::vector<ossimString>& typeList)const +{ + typeList.push_back(STATIC_TYPE_NAME(ossimConnectableContainer)); +} diff --git a/Utilities/OSSIM/ossim_core/base/factory/ossimBaseObjectFactory.h b/Utilities/OSSIM/ossim_core/base/factory/ossimBaseObjectFactory.h new file mode 100644 index 0000000000..a7bd7405b0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/factory/ossimBaseObjectFactory.h @@ -0,0 +1,49 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimBaseObjectFactory.h,v 1.5 2002/11/25 19:16:28 gpotts Exp $ +#ifndef ossimBaseObjectFactory_HEADER +#define ossimBaseObjectFactory_HEADER +#include "base/factory/ossimObjectFactory.h" + +class OSSIMDLLEXPORT ossimBaseObjectFactory : public ossimObjectFactory +{ +public: + virtual ~ossimBaseObjectFactory(){theInstance = NULL;} + + static ossimBaseObjectFactory* instance(); + virtual ossimObject* createObject(const ossimString& typeName)const; + virtual ossimObject* createObject(const ossimKeywordlist& kwl, + const char* prefix=0)const; + /*! + * This should return the type name of all objects in all factories. + * This is the name used to construct the objects dynamially and this + * name must be unique. + */ + virtual void getTypeNameList(std::vector<ossimString>& typeList)const; + +protected: + static ossimBaseObjectFactory* theInstance; + +TYPE_DATA +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/base/factory/ossimCustomEditorWindowFactoryBase.cpp b/Utilities/OSSIM/ossim_core/base/factory/ossimCustomEditorWindowFactoryBase.cpp new file mode 100644 index 0000000000..e17f18a8da --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/factory/ossimCustomEditorWindowFactoryBase.cpp @@ -0,0 +1,25 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimCustomEditorWindowFactoryBase.cpp,v 1.2 2002/04/02 13:06:53 gpotts Exp $ +#include "base/factory/ossimCustomEditorWindowFactoryBase.h" +RTTI_DEF1(ossimCustomEditorWindowFactoryBase, "ossimCustomEditorWindowFactoryBase", ossimObjectFactory); diff --git a/Utilities/OSSIM/ossim_core/base/factory/ossimCustomEditorWindowFactoryBase.h b/Utilities/OSSIM/ossim_core/base/factory/ossimCustomEditorWindowFactoryBase.h new file mode 100644 index 0000000000..3a2f865e97 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/factory/ossimCustomEditorWindowFactoryBase.h @@ -0,0 +1,52 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimCustomEditorWindowFactoryBase.h,v 1.7 2003/02/07 13:54:55 gpotts Exp $ +#ifndef ossimCustomEditorWindowFactoryBase_HEADER +#define ossimCustomEditorWindowFactoryBase_HEADER +#include "base/factory/ossimObjectFactory.h" + +class OSSIMDLLEXPORT ossimCustomEditorWindow; + +class OSSIMDLLEXPORT ossimCustomEditorWindowFactoryBase : public ossimObjectFactory +{ +public: + virtual ossimCustomEditorWindow* createCustomEditor(ossimObject* obj, + void* parent=NULL)const=0; + virtual ossimCustomEditorWindow* createCustomEditor(const ossimString& classType, + void* parent=NULL)const=0; + + /*! + * Returns a native GUI Editor with popup + */ + virtual void* createPopupEditor(ossimObject* obj, + void* parent=NULL)const=0; + + /*! + * Returns a native GUI child window without a popup. + */ + virtual void* createPanelEditor(ossimObject* obj, + void* parent=NULL)const=0; +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/factory/ossimCustomEditorWindowRegistry.cpp b/Utilities/OSSIM/ossim_core/base/factory/ossimCustomEditorWindowRegistry.cpp new file mode 100644 index 0000000000..10a91b1e3a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/factory/ossimCustomEditorWindowRegistry.cpp @@ -0,0 +1,168 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimCustomEditorWindowRegistry.cpp,v 1.8 2005/10/17 18:37:16 gpotts Exp $ +#include "ossimCustomEditorWindowRegistry.h" +#include "base/factory/ossimCustomEditorWindowFactoryBase.h" +ossimCustomEditorWindowRegistry* ossimCustomEditorWindowRegistry::theInstance=0; + +RTTI_DEF(ossimCustomEditorWindowRegistry, "ossimCustomEditorWindowRegistry"); + +ossimCustomEditorWindowRegistry::~ossimCustomEditorWindowRegistry() +{ + theInstance = NULL; +} + +ossimCustomEditorWindowRegistry* ossimCustomEditorWindowRegistry::instance() +{ + if(!theInstance) + { + theInstance = new ossimCustomEditorWindowRegistry; + } + + return theInstance; +} + +bool ossimCustomEditorWindowRegistry::registerFactory(ossimCustomEditorWindowFactoryBase* factory) +{ + bool result = false; + if(factory) + { + theFactoryList.push_back(factory); + result = true; + } + + return result; +} + +ossimCustomEditorWindow* ossimCustomEditorWindowRegistry::createCustomEditor(ossimObject* obj, + void* parent)const +{ + ossimCustomEditorWindow* result = NULL; + int i = 0; + + for(i = 0; (i < (int)theFactoryList.size())&&(!result); ++i) + { + result = theFactoryList[i]->createCustomEditor(obj, parent); + } + + return result; +} +ossimCustomEditorWindow* ossimCustomEditorWindowRegistry::createCustomEditor(const ossimString& classType, + void* parent)const +{ + ossimCustomEditorWindow* result = NULL; + int i = 0; + + for(i = 0; (i < (int)theFactoryList.size())&&(!result); ++i) + { + result = theFactoryList[i]->createCustomEditor(classType, parent); + } + + return result; +} + +ossimObject* ossimCustomEditorWindowRegistry::createObject(const ossimString& typeName)const +{ + ossimObject* result = NULL; + unsigned long index = 0; + + while((index < theFactoryList.size()) &&(!result)) + { + result = theFactoryList[index]->createObject(typeName); + ++index; + } + return result; +} + +ossimObject* ossimCustomEditorWindowRegistry::createObject(const ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimObject* result = NULL; + unsigned long index = 0; + + while((index < theFactoryList.size()) &&(!result)) + { + result = theFactoryList[index]->createObject(kwl, + prefix); + ++index; + } + + return result; +} + +void* ossimCustomEditorWindowRegistry::createPopupEditor(ossimObject* obj, + void* parent)const +{ + void* result = NULL; + unsigned long index = 0; + + while((index < theFactoryList.size()) &&(!result)) + { + result = theFactoryList[index]->createPopupEditor(obj, + parent); + ++index; + } + + return result; +} + +void* ossimCustomEditorWindowRegistry::createPanelEditor(ossimObject* obj, + void* parent)const +{ + void* result = NULL; + unsigned long index = 0; + + while((index < theFactoryList.size()) &&(!result)) + { + result = theFactoryList[index]->createPanelEditor(obj, + parent); + ++index; + } + + return result; +} + +void ossimCustomEditorWindowRegistry::getTypeNameList(std::vector<ossimString>& typeList)const +{ + std::vector<ossimCustomEditorWindowFactoryBase*>::const_iterator iter = theFactoryList.begin(); + std::vector<ossimString> result; + + while(iter != theFactoryList.end()) + { + result.clear(); + (*iter)->getTypeNameList(result); + + typeList.insert(typeList.end(), + result.begin(), + result.end()); + ++iter; + } +} + +extern "C" +{ + void* ossimCustomEditorWindowRegistryGetInstance() + { + return ossimCustomEditorWindowRegistry::instance(); + } +} diff --git a/Utilities/OSSIM/ossim_core/base/factory/ossimCustomEditorWindowRegistry.h b/Utilities/OSSIM/ossim_core/base/factory/ossimCustomEditorWindowRegistry.h new file mode 100644 index 0000000000..e1f74f6290 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/factory/ossimCustomEditorWindowRegistry.h @@ -0,0 +1,78 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimCustomEditorWindowRegistry.h,v 1.8 2003/04/09 15:48:46 gpotts Exp $ +#ifndef ossimCustomEditorWindowRegistry_HEADER +#define ossimCustomEditorWindowRegistry_HEADER +#include "base/common/ossimObject.h" +#include "base/common/ossimCustomEditorWindow.h" +#include "base/factory/ossimCustomEditorWindowFactoryBase.h" + +#include <vector> +class OSSIMDLLEXPORT ossimCustomEditorWindowFactoryBase; + +class OSSIMDLLEXPORT ossimCustomEditorWindowRegistry : public ossimCustomEditorWindowFactoryBase +{ +public: + virtual ~ossimCustomEditorWindowRegistry(); + static ossimCustomEditorWindowRegistry* instance(); + bool registerFactory(ossimCustomEditorWindowFactoryBase* factory); + + virtual ossimCustomEditorWindow* createCustomEditor(ossimObject* obj, + void* parent=NULL)const; + virtual ossimCustomEditorWindow* createCustomEditor(const ossimString& classType, + void* parent=NULL)const; + + virtual ossimObject* createObject(const ossimString& typeName)const; + virtual ossimObject* createObject(const ossimKeywordlist& kwl, + const char* prefix=0)const; + /*! + * Returns a native GUI Editor with popup + */ + virtual void* createPopupEditor(ossimObject* obj, + void* parent=NULL)const; + + /*! + * Returns a native GUI child window without a popup. + */ + virtual void* createPanelEditor(ossimObject* obj, + void* parent=NULL)const; + + virtual void getTypeNameList(std::vector<ossimString>& typeList)const; + +protected: + ossimCustomEditorWindowRegistry(){} + ossimCustomEditorWindowRegistry(const ossimCustomEditorWindowRegistry&){} + void operator =(const ossimCustomEditorWindowRegistry& rhs){} + + std::vector<ossimCustomEditorWindowFactoryBase*> theFactoryList; + + static ossimCustomEditorWindowRegistry* theInstance; + +TYPE_DATA +}; + +extern "C" +{ + OSSIMDLLEXPORT void* ossimCustomEditorWindowRegistryGetInstance(); +} +#endif diff --git a/Utilities/OSSIM/ossim_core/base/factory/ossimDatumFactory.cpp b/Utilities/OSSIM/ossim_core/base/factory/ossimDatumFactory.cpp new file mode 100644 index 0000000000..d1c5d01192 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/factory/ossimDatumFactory.cpp @@ -0,0 +1,340 @@ + +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// This holds the class definition of DatumFactory. +//******************************************************************* +// $Id: ossimDatumFactory.cpp,v 1.8 2004/05/14 13:45:56 gpotts Exp $ + +#include "ossimDatumFactory.h" +#include "ossimEllipsoidFactory.h" +#include "base/data_types/datum/ossimDatum.h" +#include "base/data_types/datum/ossimThreeParamDatum.h" +#include "base/data_types/datum/ossimSevenParamDatum.h" +#include "base/data_types/datum/ossimWgs84Datum.h" +#include "base/data_types/datum/ossimWgs72Datum.h" +#include "base/data_types/datum/ossimNadconNarDatum.h" +#include "base/data_types/datum/ossimNadconNasDatum.h" +#include "base/common/ossimPreferences.h" +#include <base/factory/ossimDatumFactory.inc> + +ossimDatumFactory* ossimDatumFactory::theInstance = 0; +map<ossimString, ossimDatum*> ossimDatumFactory::theDatumTable; + +ossimDatumFactory::~ossimDatumFactory() +{ + deleteAll(); + theInstance = 0; +} + + +ossimDatumFactory* ossimDatumFactory::instance() +{ + if(!theInstance) + { + theInstance = new ossimDatumFactory; + + // datum depends on the creation of an ellipsoid factory + // so make sure an instance exists + ossimEllipsoidFactory::instance(); + theInstance->initializeDefaults(); + theInstance->theWgs84Datum = theInstance->create("WGE"); + theInstance->theWgs72Datum = theInstance->create("WGD"); + } + return theInstance; +} + + +void ossimDatumFactory::writeCStructure(const ossimFilename& file) +{ +#if 0 + std::ofstream out(file.c_str()); + + if(!out) return; + + out << "typedef struct ossimSevenParamDatumType" << std::endl + << "{" << std::endl + << " ossimString theCode;\n" + << " ossimString theName;\n" + << " ossimString theEllipsoidCode;\n" + << " ossim_float64 theSigmaX;\n" + << " ossim_float64 theSigmaY;\n" + << " ossim_float64 theSigmaZ;\n" + << " ossim_float64 theWestLongitude;\n" + << " ossim_float64 theEastLongitude;\n" + << " ossim_float64 theSouthLatitude;\n" + << " ossim_float64 theNorthLatitude;\n" + << " ossim_float64 theParam1;\n" + << " ossim_float64 theParam2;\n" + << " ossim_float64 theParam3;\n" + << " ossim_float64 theParam4;\n" + << " ossim_float64 theParam5;\n" + << " ossim_float64 theParam6;\n" + << " ossim_float64 theParam7;\n" + << "};\n"; + + out << "typedef struct ossimThreeParamDatumType" << std::endl + << "{" << std::endl + << " ossimString theCode;\n" + << " ossimString theName;\n" + << " ossimString theEllipsoidCode;\n" + << " ossim_float64 theSigmaX;\n" + << " ossim_float64 theSigmaY;\n" + << " ossim_float64 theSigmaZ;\n" + << " ossim_float64 theWestLongitude;\n" + << " ossim_float64 theEastLongitude;\n" + << " ossim_float64 theSouthLatitude;\n" + << " ossim_float64 theNorthLatitude;\n" + << " ossim_float64 theParam1;\n" + << " ossim_float64 theParam2;\n" + << " ossim_float64 theParam3;\n" + << "};\n"; + out << "#define NUMBER_OF_SEVEN_PARAM_DATUMS " << 2 << std::endl; + if(out) + { + map<ossimString, ossimDatum*>::iterator datum; + out << "static ossimThreeParamDatumType threeParamDatum[] = {\n"; + datum = theDatumTable.begin(); + ossim_uint32 datumCount = 0; + while(datum != theDatumTable.end()) + { + bool written = false; + if( ((*datum).first != "NAS") && + ((*datum).first != "NAR")&& + ((*datum).first != "EUR-7")&& + ((*datum).first != "OGB-7")) + { + written = true; + const ossimDatum* d = (*datum).second; + + out << "{\"" << d->code() << "\", " + << "\"" << d->name() << "\", " + << "\"" << d->ellipsoid()->code() << "\", " + << d->sigmaX() << ", " + << d->sigmaY() << ", " + << d->sigmaZ() << ", " + << d->westLongitude()*DEG_PER_RAD << ", " + << d->eastLongitude()*DEG_PER_RAD << ", " + << d->southLatitude()*DEG_PER_RAD << ", " + << d->northLatitude()*DEG_PER_RAD << ", " + << d->param1() << ", " + << d->param2() << ", " + << d->param3() << "}"; + ++datumCount; + } + ++datum; + if(datum != theDatumTable.end()&&written) + { + + out << "," << std::endl; + } + else if(datum == theDatumTable.end()) + { + out << std::endl; + } + } + out << "};" << std::endl; + + out << "#define NUMBER_OF_THREE_PARAM_DATUMS " << datumCount << std::endl; + out << "static ossimSevenParamDatumType sevenParamDatum[] = {\n"; + const ossimDatum* d = create("EUR-7"); + if(d) + { + out << "{\"" << d->code() << "\", " + << "\"" << d->name() << "\", " + << "\"" << d->ellipsoid()->code() << "\", " + << d->sigmaX() << ", " + << d->sigmaY() << ", " + << d->sigmaZ() << ", " + << d->westLongitude()*DEG_PER_RAD << ", " + << d->eastLongitude()*DEG_PER_RAD << ", " + << d->southLatitude()*DEG_PER_RAD << ", " + << d->northLatitude()*DEG_PER_RAD << ", " + << d->param1() << ", " + << d->param2() << ", " + << d->param3() << ", " + << d->param4() << ", " + << d->param5() << ", " + << d->param6() << ", " + << d->param7() << "},\n"; + } + d = create("OGB-7"); + if(d) + { + out << "{\"" << d->code() << "\", " + << "\"" << d->name() << "\", " + << "\"" << d->ellipsoid()->code() << "\", " + << d->sigmaX() << ", " + << d->sigmaY() << ", " + << d->sigmaZ() << ", " + << d->westLongitude()*DEG_PER_RAD << ", " + << d->eastLongitude()*DEG_PER_RAD << ", " + << d->southLatitude()*DEG_PER_RAD << ", " + << d->northLatitude()*DEG_PER_RAD << ", " + << d->param1() << ", " + << d->param2() << ", " + << d->param3() << ", " + << d->param4() << ", " + << d->param5() << ", " + << d->param6() << ", " + << d->param7() << "}\n"; + } + out << "};" << std::endl; + } +#endif +} + + +const ossimDatum* ossimDatumFactory::create(const ossimString &code)const +{ + map<ossimString, ossimDatum*>::const_iterator + datum = theDatumTable.find(code); + + if(datum != theDatumTable.end()) + { + return (*datum).second; + } + else + { + if(code == "NAR") + { + map<ossimString, ossimDatum*>::const_iterator + datum = theDatumTable.find("NAR-C"); + if(datum != theDatumTable.end()) + { + return (*datum).second; + } + } + else if(code == "NAS") + { + map<ossimString, ossimDatum*>::const_iterator + datum = theDatumTable.find("NAS-C"); + if(datum != theDatumTable.end()) + { + return (*datum).second; + } + } + return NULL; + } +} + +const ossimDatum* ossimDatumFactory::create(const ossimDatum* aDatum)const +{ + if (aDatum) + return create (aDatum->code()); + else + return NULL; +} + +list<ossimString> ossimDatumFactory::getList()const +{ + map<ossimString, ossimDatum*>::const_iterator datum = theDatumTable.begin(); + list<ossimString> result; + + while(datum != theDatumTable.end()) + { + result.push_back((*datum).first); + ++datum; + } + return result; +} + +void ossimDatumFactory::deleteAll() +{ + map<ossimString, ossimDatum*>::iterator datum; + + datum = theDatumTable.begin(); + while(datum != theDatumTable.end()) + { + delete ((*datum).second); + + ++datum; + } + + theDatumTable.clear(); + +} + +void ossimDatumFactory::initializeDefaults() +{ + //make the standards + theDatumTable.insert(make_pair(ossimString("WGE"), new ossimWgs84Datum)); + theDatumTable.insert(make_pair(ossimString("WGD"), new ossimWgs72Datum)); + + ossim_uint32 idx = 0; + + for(idx = 0; idx < NUMBER_OF_THREE_PARAM_DATUMS; ++idx) + { + if((threeParamDatum[idx].theCode != "WGE")&& + (threeParamDatum[idx].theCode != "WGD")) + { + theDatumTable.insert(make_pair(threeParamDatum[idx].theCode, + new ossimThreeParamDatum(threeParamDatum[idx].theCode, threeParamDatum[idx].theName, + ossimEllipsoidFactory::instance()->create(ossimString(threeParamDatum[idx].theEllipsoidCode)), + threeParamDatum[idx].theSigmaX, threeParamDatum[idx].theSigmaY, threeParamDatum[idx].theSigmaZ, + threeParamDatum[idx].theWestLongitude, threeParamDatum[idx].theEastLongitude, threeParamDatum[idx].theSouthLatitude, + threeParamDatum[idx].theNorthLatitude, threeParamDatum[idx].theParam1, threeParamDatum[idx].theParam2, + threeParamDatum[idx].theParam3))); + } + } + for(idx = 0; idx < NUMBER_OF_SEVEN_PARAM_DATUMS; ++idx) + { + if((threeParamDatum[idx].theCode != "WGE")&& + (threeParamDatum[idx].theCode != "WGD")) + { + theDatumTable.insert(make_pair(sevenParamDatum[idx].theCode, + new ossimSevenParamDatum(sevenParamDatum[idx].theCode, sevenParamDatum[idx].theName, + ossimEllipsoidFactory::instance()->create(ossimString(sevenParamDatum[idx].theEllipsoidCode)), + sevenParamDatum[idx].theSigmaX, sevenParamDatum[idx].theSigmaY, sevenParamDatum[idx].theSigmaZ, + sevenParamDatum[idx].theWestLongitude, sevenParamDatum[idx].theEastLongitude, sevenParamDatum[idx].theSouthLatitude, + sevenParamDatum[idx].theNorthLatitude, + sevenParamDatum[idx].theParam1, + sevenParamDatum[idx].theParam2, + sevenParamDatum[idx].theParam3, + sevenParamDatum[idx].theParam4, + sevenParamDatum[idx].theParam5, + sevenParamDatum[idx].theParam6, + sevenParamDatum[idx].theParam7))); + } + } + ossimFilename file = ossimPreferences::instance()->findPreference("datum_grids"); + + if(file != "") + { + if(!file.isDir()) + { + file = file.path(); + } + + ossimFilename fileTest1 = file.dirCat("conus.las"); + ossimFilename fileTest2 = file.dirCat("conus.los"); + + if(fileTest1.exists()&& + fileTest2.exists()) + { + theDatumTable.insert(std::make_pair(ossimString("NAS"), + new ossimNadconNasDatum(file))); + theDatumTable.insert(std::make_pair(ossimString("NAR"), + new ossimNadconNarDatum(file))); + } + } +} diff --git a/Utilities/OSSIM/ossim_core/base/factory/ossimDatumFactory.h b/Utilities/OSSIM/ossim_core/base/factory/ossimDatumFactory.h new file mode 100644 index 0000000000..a6278dd07b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/factory/ossimDatumFactory.h @@ -0,0 +1,67 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// This is the DatumFactory class. You give it a code and it will +// construct a Datum class. It returns NULL if no code was found. +//******************************************************************* +// $Id: ossimDatumFactory.h,v 1.4 2004/05/14 13:45:56 gpotts Exp $ + +#ifndef ossimDatumFactory_HEADER +#define ossimDatumFactory_HEADER +#include <list> +#include <map> +using namespace std; +#include "base/data_types/ossimString.h" +#include "ossimEllipsoidFactory.h" +class ossimFilename; +class ossimDatum; +class ossimWgs84Datum; +class ossimWgs72Datum; + +class OSSIMDLLEXPORT ossimDatumFactory +{ +public: + ~ossimDatumFactory(); + const ossimDatum* create(const ossimString &code)const; + const ossimDatum* create(const ossimDatum* copy) const; + + static ossimDatumFactory* instance(); + const ossimDatum* wgs84()const{return theWgs84Datum;} + const ossimDatum* wgs72()const{return theWgs72Datum;} + list<ossimString> getList()const; + void writeCStructure(const ossimFilename& file); +protected: + static ossimDatumFactory* theInstance; + const ossimDatum* theWgs84Datum; + const ossimDatum* theWgs72Datum; + static map<ossimString, ossimDatum*> theDatumTable; + + + ossimDatumFactory() + :theWgs84Datum(0), + theWgs72Datum(0) + {} + ossimDatumFactory(const ossimDatumFactory&){} + void deleteAll(); + void initializeDefaults(); +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/base/factory/ossimDatumFactory.inc b/Utilities/OSSIM/ossim_core/base/factory/ossimDatumFactory.inc new file mode 100644 index 0000000000..e14ba1070a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/factory/ossimDatumFactory.inc @@ -0,0 +1,299 @@ +//************************************************************************* +// Copyright (C) 2004 Intelligence Data Sytems, Inc. All rights reserved. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts +// +//************************************************************************** +// $Id: ossimDatumFactory.inc,v 1.5 2005/12/15 12:07:19 gpotts Exp $ + +struct ossimSevenParamDatumType +{ + const char* theCode; + const char* theName; + const char* theEllipsoidCode; + ossim_float64 theSigmaX; + ossim_float64 theSigmaY; + ossim_float64 theSigmaZ; + ossim_float64 theWestLongitude; + ossim_float64 theEastLongitude; + ossim_float64 theSouthLatitude; + ossim_float64 theNorthLatitude; + ossim_float64 theParam1; + ossim_float64 theParam2; + ossim_float64 theParam3; + ossim_float64 theParam4; + ossim_float64 theParam5; + ossim_float64 theParam6; + ossim_float64 theParam7; +}; + +struct ossimThreeParamDatumType +{ +public: + const char* theCode; + const char* theName; + const char* theEllipsoidCode; + ossim_float64 theSigmaX; + ossim_float64 theSigmaY; + ossim_float64 theSigmaZ; + ossim_float64 theWestLongitude; + ossim_float64 theEastLongitude; + ossim_float64 theSouthLatitude; + ossim_float64 theNorthLatitude; + ossim_float64 theParam1; + ossim_float64 theParam2; + ossim_float64 theParam3; +}; + +#define NUMBER_OF_SEVEN_PARAM_DATUMS 2 +#define NUMBER_OF_THREE_PARAM_DATUMS 226 + +static ossimThreeParamDatumType threeParamDatum[] = { +{"ADI-A", "ADINDAN, Ethiopia", "CD", 3, 3, 3, 26, 50, -3, 25, -165, -11, 206}, +{"ADI-B", "ADINDAN, Sudan", "CD", 3, 5, 3, 15, 45, -3, 31, -161, -14, 205}, +{"ADI-C", "ADINDAN, Mali", "CD", 25, 25, 25, -20, 11, 3, 31, -123, -20, 220}, +{"ADI-D", "ADINDAN, Senegal", "CD", 25, 25, 25, -24, -5, 5, 23, -128, -18, 224}, +{"ADI-E", "ADINDAN, Burkina Faso", "CD", 25, 25, 25, -5, 8, 4, 22, -118, -14, 218}, +{"ADI-F", "ADINDAN, Cameroon", "CD", 25, 25, 25, 3, 23, -4, 19, -134, -2, 210}, +{"ADI-M", "ADINDAN, Mean", "CD", 5, 5, 3, 15, 55, -5, 31, -166, -15, 204}, +{"AFG", "AFGOOYE, Somalia", "KA", 25, 25, 25, 35, 60, -8, 19, -43, -163, 45}, +{"AIA", "ANTIGUA ISLAND ASTRO 1943", "CD", 25, 25, 25, -65, -61, 16, 20, -270, 13, 62}, +{"AIN-A", "AIN EL ABD 1970, Bahrain", "IN", 25, 25, 25, 49, 53, 24, 28, -150, -250, -1}, +{"AIN-B", "AIN EL ABD 1970, Saudi Arabia", "IN", 10, 10, 10, 28, 62, 8, 38, -143, -236, 7}, +{"AMA", "AMERICAN SAMOA 1962", "CC", 25, 25, 25, -174, -165, -19, -9, -115, 118, 426}, +{"ANO", "ANNA 1 ASTRO 1965, Cocos Is.", "AN", 25, 25, 25, 94, 99, -14, -10, -491, -22, 435}, +{"ARF-A", "ARC 1950, Botswana", "CD", 3, 5, 3, 13, 36, -33, -13, -138, -105, -289}, +{"ARF-B", "ARC 1950, Lesotho", "CD", 3, 3, 8, 21, 35, -36, -23, -125, -108, -295}, +{"ARF-C", "ARC 1950, Malawi", "CD", 9, 24, 8, 26, 42, -21, -3, -161, -73, -317}, +{"ARF-D", "ARC 1950, Swaziland", "CD", 15, 15, 15, 25, 40, -33, -20, -134, -105, -295}, +{"ARF-E", "ARC 1950, Zaire", "CD", 25, 25, 25, 4, 38, -21, 10, -169, -19, -278}, +{"ARF-F", "ARC 1950, Zambia", "CD", 21, 21, 27, 15, 40, -24, -1, -147, -74, -283}, +{"ARF-G", "ARC 1950, Zimbabwe", "CD", 5, 8, 11, 19, 39, -29, -9, -142, -96, -293}, +{"ARF-H", "ARC 1950, Burundi", "CD", 20, 20, 20, 21, 37, -11, 4, -153, -5, -292}, +{"ARF-M", "ARC 1950, Mean", "CD", 20, 33, 20, 4, 42, -36, 10, -143, -90, -294}, +{"ARS-A", "ARC 1960, Kenya", "CD", 4, 3, 3, 28, 47, -11, 8, -157, -2, -299}, +{"ARS-B", "ARC 1960, Tanzania", "CD", 6, 9, 10, 23, 47, -18, 5, -175, -23, -303}, +{"ARS-M", "ARC 1960, Kenya & Tanzania", "CD", 20, 20, 20, 23, 47, -18, 8, -160, -6, -302}, +{"ASC", "ASCENSION ISLAND 1958", "IN", 25, 25, 25, -16, -13, -9, -6, -205, 107, 53}, +{"ASM", "MONTSERRAT ISLAND ASTRO 1958", "CD", 25, 25, 25, -64, -61, 15, 18, 174, 359, 365}, +{"ASQ", "ASTRO STATION 1952, Marcus Is.", "IN", 25, 25, 25, 152, 156, 22, 26, 124, -234, -25}, +{"ATF", "ASTRO BEACON E 1845, Iwo Jima", "IN", 25, 25, 25, 140, 144, 22, 26, 145, 75, -272}, +{"AUA", "AUSTRALIAN GEODETIC 1966", "AN", 3, 3, 3, 109, 161, -46, -4, -133, -48, 148}, +{"AUG", "AUSTRALIAN GEODETIC 1984", "AN", 2, 2, 2, 109, 161, -46, -4, -134, -48, 149}, +{"BAT", "DJAKARTA, INDONESIA", "BR", 3, 3, 3, 89, 146, -16, 11, -377, 681, -50}, +{"BER", "BERMUDA 1957, Bermuda Islands", "CC", 20, 20, 20, -66, -63, 31, 34, -73, 213, 296}, +{"BID", "BISSAU, Guinea-Bissau", "IN", 25, 25, 25, -23, -7, 5, 19, -173, 253, 27}, +{"BOO", "BOGOTA OBSERVATORY, Columbia", "IN", 6, 5, 6, -85, -61, -10, 16, 307, 304, -318}, +{"BUR", "BUKIT RIMPAH, Banka & Belitung", "BR", -1, -1, -1, 103, 110, -6, 0, -384, 664, -48}, +{"CAC", "CAPE CANAVERAL, Fla & Bahamas", "CC", 3, 3, 3, -94, -12, 15, 38, -2, 151, 181}, +{"CAI", "CAMPO INCHAUSPE 1969, Arg.", "IN", 5, 5, 5, -72, -51, -58, -27, -148, 136, 90}, +{"CAO", "CANTON ASTRO 1966, Phoenix Is.", "IN", 15, 15, 15, -180, -165, -13, 3, 298, -304, -375}, +{"CAP", "CAPE, South Africa", "CD", 3, 6, 6, 10, 40, -43, -15, -136, -108, -292}, +{"CAZ", "CAMP AREA ASTRO, Camp McMurdo", "IN", -1, -1, -1, 135, 180, -85, -70, -104, -129, 239}, +{"CCD", "S-JTSK, Czech Republic", "BR", 4, 2, 3, 6, 28, 43, 56, 589, 76, 480}, +{"CGE", "CARTHAGE, Tunisia", "CD", 6, 9, 8, 2, 18, 24, 43, -263, 6, 431}, +{"CHI", "CHATHAM ISLAND ASTRO 1971, NZ", "IN", 15, 15, 15, -180, -174, -46, -42, 175, -38, 113}, +{"CHU", "CHUA ASTRO, Paraguay", "IN", 6, 9, 5, -69, -49, -33, -14, -134, 229, -29}, +{"COA", "CORREGO ALEGRE, Brazil", "IN", 5, 3, 5, -80, -29, -39, -2, -206, 172, -6}, +{"DAL", "DABOLA, Guinea", "CD", 15, 15, 15, 12, 11, 1, 19, -83, 37, 124}, +{"DID", "DECEPTION ISLAND", "CD", 20, 20, 20, 58, 62, -65, -62, 260, 12, -147}, +{"DOB", "GUX 1 ASTRO, Guadalcanal Is.", "IN", 25, 25, 25, 158, 163, -12, -8, 252, -209, -751}, +{"EAS", "EASTER ISLAND 1967", "IN", 25, 25, 25, -111, -108, -29, -26, 211, 147, 111}, +{"ENW", "WAKE-ENIWETOK 1960", "HO", 3, 3, 3, 159, 175, 1, 16, 102, 52, -38}, +{"EST", "ESTONIA, 1937", "BR", 2, 3, 3, 16, 34, 52, 65, 374, 150, 588}, +{"EUR-A", "EUROPEAN 1950, Western Europe", "IN", 3, 3, 3, -15, 25, 30, 78, -87, -96, -120}, +{"EUR-B", "EUROPEAN 1950, Greece", "IN", 25, 25, 25, 14, 34, 30, 48, -84, -95, -130}, +{"EUR-C", "EUROPEAN 1950, Norway & Finland", "IN", 3, 5, 3, -2, 38, 52, 80, -87, -95, -120}, +{"EUR-D", "EUROPEAN 1950, Portugal & Spain", "IN", 5, 6, 3, -15, 10, 30, 49, -84, -107, -120}, +{"EUR-E", "EUROPEAN 1950, Cyprus", "IN", 15, 15, 15, 31, 36, 33, 37, -104, -101, -140}, +{"EUR-F", "EUROPEAN 1950, Egypt", "IN", 6, 8, 8, 19, 42, 16, 38, -130, -117, -151}, +{"EUR-G", "EUROPEAN 1950, England, Channel", "IN", 3, 3, 3, -10, 3, 48, 62, -86, -96, -120}, +{"EUR-H", "EUROPEAN 1950, Iran", "IN", 9, 12, 11, 37, 69, 19, 47, -117, -132, -164}, +{"EUR-I", "EUROPEAN 1950, Sardinia(Italy)", "IN", 25, 25, 25, 6, 12, 37, 43, -97, -103, -120}, +{"EUR-J", "EUROPEAN 1950, Sicily(Italy)", "IN", 20, 20, 20, 10, 17, 35, 40, -97, -88, -135}, +{"EUR-K", "EUROPEAN 1950, England, Ireland", "IN", 3, 3, 3, -12, 3, 48, 62, -86, -96, -120}, +{"EUR-L", "EUROPEAN 1950, Malta", "IN", 25, 25, 25, 12, 16, 34, 38, -107, -88, -149}, +{"EUR-M", "EUROPEAN 1950, Mean (3 Param)", "IN", 3, 8, 5, 5, 33, 30, 80, -87, -98, -121}, +{"EUR-S", "EUROPEAN 1950, Iraq, Israel", "IN", -1, -1, -1, 36, 57, -38, -4, -103, -106, -141}, +{"EUR-T", "EUROPEAN 1950, Tunisia", "IN", 25, 25, 25, 2, 18, 24, 43, -112, -77, -145}, +{"EUS", "EUROPEAN 1979", "IN", 3, 3, 3, -15, 24, 30, 80, -86, -98, -119}, +{"FAH", "OMAN", "CD", 3, 3, 9, 46, 65, 10, 32, -346, -1, 224}, +{"FLO", "OBSERVATORIO MET. 1939, Flores", "IN", 20, 20, 20, -33, -30, 38, 41, -425, -169, 81}, +{"FOT", "FORT THOMAS 1955, Leeward Is.", "CD", 25, 25, 25, -64, -61, 16, 19, -7, 215, 225}, +{"GAA", "GAN 1970, Rep. of Maldives", "IN", 25, 25, 25, 71, 75, -2, 9, -133, -321, 50}, +{"GEO", "GEODETIC DATUM 1949, NZ", "IN", 5, 3, 5, 165, 180, -48, -33, 84, -22, 209}, +{"GIZ", "DOS 1968, Gizo Island", "IN", 25, 25, 25, 155, 158, -10, -7, 230, -199, -752}, +{"GRA", "GRACIOSA BASE SW 1948, Azores", "IN", 3, 3, 3, -30, -26, 37, 41, -104, 167, -38}, +{"GSE", "GUNUNG SEGARA, Indonesia", "BR", -1, -1, -1, 106, 121, -6, 9, -403, 684, 41}, +{"GUA", "GUAM 1963", "CC", 3, 3, 3, 143, 146, 12, 15, -100, -248, 259}, +{"HEN", "HERAT NORTH, Afghanistan", "IN", -1, -1, -1, 55, 81, 23, 44, -333, -222, 114}, +{"HER", "HERMANNSKOGEL, old Yugoslavia", "BR", -1, -1, -1, 7, 29, 35, 52, 682, -203, 480}, +{"HIT", "PROVISIONAL SOUTH CHILEAN 1963", "IN", 25, 25, 25, -83, -60, -64, -25, 16, 196, 93}, +{"HJO", "HJORSEY 1955, Iceland", "IN", 3, 3, 6, -24, -11, 61, 69, -73, 46, -86}, +{"HKD", "HONG KONG 1963", "IN", 25, 25, 25, 112, 116, 21, 24, -156, -271, -189}, +{"HTN", "HU-TZU-SHAN, Taiwan", "IN", 15, 15, 15, 117, 124, 20, 28, -637, -549, -203}, +{"IBE", "BELLEVUE (IGN), Efate Is.", "IN", 20, 20, 20, 167, 171, -20, -16, -127, -769, 472}, +{"IDN", "INDONESIAN 1974", "ID", 25, 25, 25, 89, 146, -16, 11, -24, -15, 5}, +{"IND-B", "INDIAN, Bangladesh", "EA", 10, 8, 12, 80, 100, 15, 33, 282, 726, 254}, +{"IND-I", "INDIAN, India & Nepal", "EC", 12, 10, 15, 62, 105, 2, 44, 295, 736, 257}, +{"IND-P", "INDIAN, Pakistan", "EA", -1, -1, -1, 55, 81, 17, 44, 283, 682, 231}, +{"INF-A", "INDIAN 1954, Thailand", "EA", 15, 6, 12, 91, 111, 0, 27, 217, 823, 299}, +{"ING-A", "INDIAN 1960, Vietnam 16N", "EA", 25, 25, 25, 101, 115, 11, 23, 198, 881, 317}, +{"ING-B", "INDIAN 1960, Con Son Island", "EA", 25, 25, 25, 104, 109, 6, 11, 182, 915, 344}, +{"INH-A", "INDIAN 1975, Thailand", "EA", 12, 10, 12, 91, 111, 0, 27, 209, 818, 290}, +{"INH-A1", "INDIAN 1975, Thailand", "EA", 3, 2, 3, 91, 111, 0, 27, 210, 814, 289}, +{"IRL", "IRELAND 1965", "AM", 3, 3, 3, -12, -4, 50, 57, 506, -122, 611}, +{"ISG", "ISTS 061 ASTRO 1968, S Georgia", "IN", 25, 25, 25, -38, -34, -56, -52, -794, 119, -298}, +{"IST", "ISTS 073 ASTRO 1969, Diego Garc", "IN", 25, 25, 25, 69, 75, -10, -4, 208, -435, -229}, +{"JOH", "JOHNSTON ISLAND 1961", "IN", 25, 25, 25, -76, -73, -46, -43, 189, -79, -202}, +{"KAN", "KANDAWALA, Sri Lanka", "EA", 20, 20, 20, 77, 85, 4, 12, -97, 787, 86}, +{"KEA", "KERTAU 1948, W Malaysia & Sing.", "EE", 10, 8, 6, 94, 112, -5, 12, -11, 851, 5}, +{"KEG", "KERGUELEN ISLAND 1949", "IN", 25, 25, 25, 139, 180, -81, -74, 145, -187, 103}, +{"KUS", "KUSAIE ASTRO 1951, Caroline Is.", "IN", 25, 25, 25, 134, 167, -1, 12, 647, 1777, -1124}, +{"LCF", "L.C. 5 ASTRO 1961, Cayman Brac", "CC", 25, 25, 25, -81, -78, 18, 21, 42, 124, 147}, +{"LEH", "LEIGON, Ghana", "CD", 2, 3, 2, -9, 7, -1, 17, -130, 29, 364}, +{"LIB", "LIBERIA 1964", "CD", 15, 15, 15, -17, -1, -1, 14, -90, 40, 88}, +{"LUZ-A", "LUZON, Phillipines", "CC", 8, 11, 9, 115, 128, 3, 23, -133, -77, -51}, +{"LUZ-B", "LUZON, Mindanao Island", "CC", 25, 25, 25, 120, 128, 4, 12, -133, -79, -72}, +{"MAS", "MASSAWA, Ethiopia", "BR", 25, 25, 25, 37, 53, 7, 25, 639, 405, 60}, +{"MER", "MERCHICH, Morocco", "CD", 5, 3, 3, -19, 5, 22, 42, 31, 146, 47}, +{"MID", "MIDWAY ASTRO 1961, Midway Is.", "IN", 25, 25, 25, -180, -169, 25, 30, 912, -58, 1227}, +{"MIK", "MAHE 1971, Mahe Is.", "CD", 25, 25, 25, 54, 57, -6, -3, 41, -220, -134}, +{"MIN-A", "MINNA, Cameroon", "CD", 25, 25, 25, 3, 23, -4, 19, -81, -84, 115}, +{"MIN-B", "MINNA, Nigeria", "CD", 3, 6, 5, -4, 20, -1, 21, -92, -93, 122}, +{"MOD", "ROME 1940, Sardinia", "IN", 25, 25, 25, 6, 12, 37, 43, -225, -65, 9}, +{"MPO", "M'PORALOKO, Gabon", "CD", 25, 25, 25, 3, 20, -10, 8, -74, -130, 42}, +{"MVS", "VITI LEVU 1916, Viti Levu Is.", "CD", 25, 25, 25, 176, 180, -20, -16, 51, 391, -36}, +{"NAH-A", "NAHRWAN, Masirah Island (Oman)", "CD", 25, 25, 25, 57, 60, 19, 22, -247, -148, 369}, +{"NAH-B", "NAHRWAN, United Arab Emirates", "CD", 25, 25, 25, 45, 62, 17, 32, -249, -156, 381}, +{"NAH-C", "NAHRWAN, Saudi Arabia", "CD", 25, 25, 20, 28, 62, 8, 38, -243, -192, 477}, +{"NAP", "NAPARIMA, Trinidad & Tobago", "IN", 15, 15, 15, -64, -59, 8, 13, -10, 375, 165}, +{"NAR-A", "NORTH AMERICAN 1983, Alaska", "RF", 2, 2, 2, -175, -135, 48, 78, 0, 0, 0}, +{"NAR-B", "NORTH AMERICAN 1983, Canada", "RF", 2, 2, 2, -150, -50, 36, 90, 0, 0, 0}, +{"NAR-C", "NORTH AMERICAN 1983, CONUS", "RF", 2, 2, 2, -135, -60, 15, 60, 0, 0, 0}, +{"NAR-D", "NORTH AMERICAN 1983, Mexico", "RF", 2, 2, 2, -122, -72, 11, 35, 0, 0, 0}, +{"NAR-E", "NORTH AMERICAN 1983, Aleutian", "RF", 5, 2, 5, -180, 180, 51, 74, -2, 0, 4}, +{"NAR-H", "NORTH AMERICAN 1983, Hawai'i", "RF", 2, 2, 2, -164, -153, 17, 24, 1, 1, -1}, +{"NAS-A", "NORTH AMERICAN 1927, Eastern US", "CC", 5, 5, 8, -102, -60, 18, 55, -9, 161, 179}, +{"NAS-B", "NORTH AMERICAN 1927, Western US", "CC", 5, 3, 3, -132, -87, 19, 55, -8, 159, 175}, +{"NAS-C", "NORTH AMERICAN 1927, CONUS", "CC", 5, 5, 6, -135, -60, 15, 60, -8, 160, 176}, +{"NAS-D", "NORTH AMERICAN 1927, Alaska", "CC", 5, 9, 5, -175, -130, 47, 78, -5, 135, 172}, +{"NAS-E", "NORTH AMERICAN 1927, Canada", "CC", 15, 11, 6, -150, -50, 36, 90, -10, 158, 187}, +{"NAS-F", "NORTH AMERICAN 1927, Alberta/BC", "CC", 8, 8, 6, -145, -105, 43, 65, -7, 162, 188}, +{"NAS-G", "NORTH AMERICAN 1927, E. Canada", "CC", 6, 6, 3, -85, -45, 38, 68, -22, 160, 190}, +{"NAS-H", "NORTH AMERICAN 1927, Man/Ont", "CC", 9, 5, 5, -108, -69, 36, 63, -9, 157, 184}, +{"NAS-I", "NORTH AMERICAN 1927, NW Terr.", "CC", 5, 5, 3, -144, -55, 43, 90, 4, 159, 188}, +{"NAS-J", "NORTH AMERICAN 1927, Yukon", "CC", 5, 8, 3, -147, -117, 53, 75, -7, 139, 181}, +{"NAS-L", "NORTH AMERICAN 1927, Mexico", "CC", 8, 6, 6, -122, -80, 10, 38, -12, 130, 190}, +{"NAS-N", "NORTH AMERICAN 1927, C. America", "CC", 8, 3, 5, -98, -77, 3, 25, 0, 125, 194}, +{"NAS-O", "NORTH AMERICAN 1927, Canal Zone", "CC", 20, 20, 20, -86, -74, 3, 15, 0, 125, 201}, +{"NAS-P", "NORTH AMERICAN 1927, Caribbean", "CC", 3, 9, 12, -87, -58, 8, 29, -3, 142, 183}, +{"NAS-Q", "NORTH AMERICAN 1927, Bahamas", "CC", 5, 3, 5, -83, -71, 19, 29, -4, 154, 178}, +{"NAS-R", "NORTH AMERICAN 1927, San Salv.", "CC", 25, 25, 25, -75, -74, 23, 26, 1, 140, 165}, +{"NAS-T", "NORTH AMERICAN 1927, Cuba", "CC", 25, 25, 25, -87, -72, 18, 25, -9, 152, 178}, +{"NAS-U", "NORTH AMERICAN 1927, Greenland", "CC", 25, 25, 25, 74, 56, 74, 81, 11, 114, 195}, +{"NAS-V", "NORTH AMERICAN 1927, Aleutian E", "CC", 6, 8, 10, -180, -161, 50, 58, -2, 152, 149}, +{"NAS-W", "NORTH AMERICAN 1927, Aleutian W", "CC", 10, 10, 10, 169, 180, 50, 58, 2, 204, 105}, +{"NSD", "NORTH SAHARA 1959, Algeria", "CD", 25, 25, 25, -15, 11, 13, 43, -186, -93, 310}, +{"NTF", "NOUVELLE TRIANGULATION DE LA FRANCE, FRANCE", "CE", 0, 0, 0, -6, 12, 41, 51, -168, -60, 320}, +{"OEG", "OLD EGYPTIAN 1907", "HE", 3, 6, 8, 19, 42, 16, 38, -130, 110, -13}, +{"OGB-A", "ORDNANCE GB 1936, England", "AA", 5, 5, 6, -12, 7, 44, 61, 371, -112, 434}, +{"OGB-B", "ORDNANCE GB 1936, Eng., Wales", "AA", 10, 10, 15, -12, 7, 44, 61, 371, -111, 434}, +{"OGB-C", "ORDNANCE GB 1936, Scotland", "AA", 10, 10, 10, -14, 4, 49, 66, 384, -111, 425}, +{"OGB-D", "ORDNANCE GB 1936, Wales", "AA", 20, 20, 20, -11, 3, 46, 59, 370, -108, 434}, +{"OGB-M", "ORDNANCE GB 1936, Mean (3 Para)", "AA", 10, 10, 15, -14, 7, 44, 66, 375, -111, 431}, +{"OHA-A", "OLD HAWAI'IAN (CC), Hawai'i", "CC", 25, 25, 25, -158, -153, 17, 22, 89, -279, -183}, +{"OHA-B", "OLD HAWAI'IAN (CC), Kauai", "CC", 20, 20, 20, -161, -158, 20, 24, 45, -290, -172}, +{"OHA-C", "OLD HAWAI'IAN (CC), Maui", "CC", 25, 25, 25, -158, -154, 19, 23, 65, -290, -190}, +{"OHA-D", "OLD HAWAI'IAN (CC), Oahu", "CC", 10, 6, 6, -160, -156, 20, 23, 58, -283, -182}, +{"OHA-M", "OLD HAWAI'IAN (CC), Mean", "CC", 25, 20, 20, -164, -153, 17, 24, 61, -285, -181}, +{"OHI-A", "OLD HAWAI'IAN (IN), Hawai'i", "IN", 25, 25, 25, -158, -153, 17, 22, 229, -222, -348}, +{"OHI-B", "OLD HAWAI'IAN (IN), Kauai", "IN", 20, 20, 20, -161, -158, 20, 24, 185, -233, -337}, +{"OHI-C", "OLD HAWAI'IAN (IN), Maui", "IN", 25, 25, 25, -158, -154, 19, 23, 205, -233, -355}, +{"OHI-D", "OLD HAWAI'IAN (IN), Oahu", "IN", 10, 6, 6, -160, -156, 20, 23, 198, -226, -347}, +{"OHI-M", "OLD HAWAI'IAN (IN), Mean", "IN", 25, 20, 20, -164, -153, 17, 24, 201, -228, -346}, +{"PHA", "AYABELLA LIGHTHOUSE, Bjibouti", "CD", 25, 25, 25, 36, 49, 5, 20, -79, -129, 145}, +{"PIT", "PITCAIRN ASTRO 1967", "IN", 25, 25, 25, -134, -119, -27, -21, 185, 165, 42}, +{"PLN", "PICO DE LAS NIEVES, Canary Is.", "IN", 25, 25, 25, -20, -12, 26, 31, -307, -92, 127}, +{"POS", "PORTO SANTO 1936, Madeira Is.", "IN", 25, 25, 25, -18, -15, 31, 35, -499, -249, 314}, +{"PRP-A", "PROV. S AMERICAN 1956, Bolivia", "IN", 5, 11, 14, -75, -51, -28, -4, -270, 188, -388}, +{"PRP-B", "PROV. S AMERICAN 1956, N Chile", "IN", 25, 25, 25, -83, -60, -45, -12, -270, 183, -390}, +{"PRP-C", "PROV. S AMERICAN 1956, S Chile", "IN", 20, 20, 20, -83, -60, -64, -20, -305, 243, -442}, +{"PRP-D", "PROV. S AMERICAN 1956, Colombia", "IN", 15, 15, 15, -85, -61, -10, 16, -282, 169, -371}, +{"PRP-E", "PROV. S AMERICAN 1956, Ecuador", "IN", 3, 5, 3, -85, -70, -11, 7, -278, 171, -367}, +{"PRP-F", "PROV. S AMERICAN 1956, Guyana", "IN", 6, 14, 5, -67, -51, -4, 14, -298, 159, -369}, +{"PRP-G", "PROV. S AMERICAN 1956, Peru", "IN", 6, 8, 12, -87, -63, -24, 5, -279, 175, -379}, +{"PRP-H", "PROV. S AMERICAN 1956, Venez", "IN", 9, 14, 15, -79, -54, -5, 18, -295, 173, -371}, +{"PRP-M", "PROV. S AMERICAN 1956, Mean", "IN", 17, 27, 27, -87, -51, -64, 18, -288, 175, -376}, +{"PTB", "POINT 58, Burkina Faso & Niger", "CD", 25, 25, 25, -15, 25, 0, 10, -106, -129, 165}, +{"PTN", "POINT NOIRE 1948", "CD", 25, 25, 25, 5, 25, -11, 10, -148, 51, -291}, +{"PUK", "PULKOVO 1942, Russia", "KA", -1, -1, -1, -180, 180, 36, 89, 28, -130, -95}, +{"PUR", "PUERTO RICO & Virgin Is.", "CC", 3, 3, 3, -69, -63, 16, 20, 11, 72, -101}, +{"QAT", "QATAR NATIONAL", "IN", 20, 20, 20, 45, 57, 19, 32, -128, -283, 22}, +{"QUO", "QORNOQ, South Greenland", "IN", 25, 25, 32, -77, -7, 57, 85, 164, 138, -189}, +{"REU", "REUNION, Mascarene Is.", "IN", 25, 25, 25, 47, 65, -27, -12, 94, -948, -1262}, +{"SAE", "SANTO (DOS) 1965", "IN", 22, 25, 25, 160, 169, -17, -13, 170, 42, 84}, +{"SAN-A", "SOUTH AMERICAN 1969, Argentina", "SA", 5, 5, 5, -76, -47, -62, -23, -62, -1, -37}, +{"SAN-B", "SOUTH AMERICAN 1969, Bolivia", "SA", 15, 15, 15, -75, -51, -28, -4, -61, 2, -48}, +{"SAN-C", "SOUTH AMERICAN 1969, Brazil", "SA", 3, 5, 5, -80, -29, -39, -2, -60, -2, -41}, +{"SAN-D", "SOUTH AMERICAN 1969, Chile", "SA", 15, 8, 11, -83, -60, -64, -12, -75, -1, -44}, +{"SAN-E", "SOUTH AMERICAN 1969, Colombia", "SA", 6, 6, 5, -85, -61, -10, 16, -44, 6, -36}, +{"SAN-F", "SOUTH AMERICAN 1969, Ecuador", "SA", 3, 3, 3, -85, -70, -11, 7, -48, 3, -44}, +{"SAN-G", "SOUTH AMERICAN 1969, Guyana", "SA", 9, 5, 5, -67, -51, -4, 14, -53, 3, -47}, +{"SAN-H", "SOUTH AMERICAN 1969, Paraguay", "SA", 15, 15, 15, -69, -49, -33, -14, -61, 2, -33}, +{"SAN-I", "SOUTH AMERICAN 1969, Peru", "SA", 5, 5, 5, -87, -63, -24, 5, -58, 0, -44}, +{"SAN-J", "SOUTH AMERICAN 1969, Baltra", "SA", 25, 25, 25, -92, -89, -2, 1, -47, 26, -42}, +{"SAN-K", "SOUTH AMERICAN 1969, Trinidad", "SA", 25, 25, 25, -68, -55, 4, 17, -45, 12, -33}, +{"SAN-L", "SOUTH AMERICAN 1969, Venezuela", "SA", 3, 6, 3, -79, -54, -5, 18, -45, 8, -33}, +{"SAN-M", "SOUTH AMERICAN 1969, Mean", "SA", 15, 6, 9, -90, -25, -65, -50, -57, 1, -41}, +{"SAO", "SAO BRAZ, Santa Maria Is.", "IN", 25, 25, 25, -27, -23, 35, 39, -203, 141, 53}, +{"SAP", "SAPPER HILL 1943, E Falkland Is", "IN", 1, 1, 1, -61, -56, -54, -50, -355, 21, 72}, +{"SCK", "SCHWARZECK, Namibia", "BN", 20, 20, 20, 5, 31, -35, -11, 616, 97, -251}, +{"SGM", "SELVAGEM GRADE 1938, Salvage Is", "IN", 25, 25, 25, -18, -14, 28, 32, -289, -124, 60}, +{"SHB", "ASTRO DOS 71/4, St. Helena Is.", "IN", 25, 25, 25, -7, -4, -18, -14, -320, 550, -494}, +{"SOA", "SOUTH ASIA, Singapore", "FA", 25, 25, 25, 102, 106, 0, 3, 7, -10, -26}, +{"SPK-A", "S-42 (PULKOVO 1942), Hungary", "KA", 2, 2, 2, 11, 29, 40, 54, 28, -121, -77}, +{"SPK-B", "S-42 (PULKOVO 1942), Poland", "KA", 4, 2, 4, 8, 30, 43, 60, 23, -124, -82}, +{"SPK-C", "S-42 (PK42) Former Czechoslov.", "KA", 3, 3, 2, 6, 28, 42, 57, 26, -121, -78}, +{"SPK-D", "S-42 (PULKOVO 1942), Latvia", "KA", 2, 2, 2, 15, 34, 50, 64, 24, -124, -82}, +{"SPK-E", "S-42 (PK 1942), Kazakhstan", "KA", 25, 25, 25, 41, 93, 35, 62, 15, -130, -84}, +{"SPK-F", "S-42 (PULKOVO 1942), Albania", "KA", 3, 3, 3, 14, 26, 34, 48, 24, -130, -92}, +{"SPK-G", "S-42 (PULKOVO 1942), Romania", "KA", 3, 5, 3, 15, 35, 38, 54, 28, -121, -77}, +{"SRL", "SIERRA LEONE 1960", "CD", 15, 15, 15, -19, -4, 1, 16, -88, 4, 101}, +{"TAN", "TANANARIVE OBSERVATORY 1925", "IN", -1, -1, -1, 40, 53, -34, -8, -189, -242, -91}, +{"TDC", "TRISTAN ASTRO 1968", "IN", 25, 25, 25, -14, -11, -39, -36, -632, 438, -609}, +{"TIL", "TIMBALAI 1948, Brunei & E Malay", "EA", 10, 10, 12, 101, 125, -5, 15, -679, 669, -48}, +{"TOY-A", "TOKYO, Japan", "BR", 8, 5, 8, 119, 156, 19, 51, -148, 507, 685}, +{"TOY-B", "TOKYO, South Korea", "BR", 8, 5, 8, 120, 139, 27, 45, -146, 507, 687}, +{"TOY-B1", "TOKYO, South Korea", "BR", 2, 2, 2, 120, 139, 27, 45, -147, 506, 687}, +{"TOY-C", "TOKYO, Okinawa", "BR", 20, 5, 20, 119, 134, 19, 31, -158, 507, 676}, +{"TOY-M", "TOKYO, Mean", "BR", 20, 5, 20, 120, 155, 23, 53, -148, 507, 685}, +{"TRN", "ASTRO TERN ISLAND (FRIG) 1961", "IN", 25, 25, 25, -166, -166, 22, 26, 114, -116, -333}, +{"VOI", "VOIROL 1874, Algeria", "CD", -1, -1, -1, -15, 11, 13, 43, -73, -247, 227}, +{"VOR", "VOIROL 1960, Algeria", "CD", 25, 25, 25, -15, 11, 13, 43, -123, -206, 219}, +{"WAK", "WAKE ISLAND ASTRO 1952", "IN", 25, 25, 25, -176, -171, 17, 21, 276, -57, 149}, +{"WGD", "World Geodetic System 1972", "WD", 0, 0, 0, -180.0, 180.0, -90, 90, 0, 0, 0}, +{"WGE", "World Geodetic System 1984", "WE", 0, 0, 0, -180.0, 180.0, -90, 90, 0, 0, 0}, +{"YAC", "YACARE, Uruguay", "IN", -1, -1, -1, -65, -47, -40, -25, -155, 171, 37}, +{"ZAN", "ZANDERIJ, Suriname", "IN", 5, 5, 8, -76, -47, -10, 20, -265, 120, -358} +}; + +static ossimSevenParamDatumType sevenParamDatum[] = { +{"EUR-7", "EUROPEAN 1950, Mean (7 Param)", "IN", 0, 0, 0, -180, 180, -90, 90, -102, -102, -129, 2.00228e-06, -8.92057e-07, 1.86653e-06, 2.4664e-06}, +{"OGB-7", "ORDNANCE GB 1936, Mean (7 Para)", "AA", 0, 0, 0, -180, 180, -90, 90, 446, -99, 544, -4.58149e-06, -1.26536e-06, -2.10894e-06, -2.08927e-05} +}; diff --git a/Utilities/OSSIM/ossim_core/base/factory/ossimEllipsoidFactory.cpp b/Utilities/OSSIM/ossim_core/base/factory/ossimEllipsoidFactory.cpp new file mode 100644 index 0000000000..8edbb94daa --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/factory/ossimEllipsoidFactory.cpp @@ -0,0 +1,187 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// +//******************************************************************* +// $Id: ossimEllipsoidFactory.cpp,v 1.5 2005/12/15 12:38:08 gpotts Exp $ +#include "ossimEllipsoidFactory.h" +#include "base/data_types/ellipse/ossimEllipsoid.h" + +ossimEllipsoidFactory* ossimEllipsoidFactory::theInstance = 0; + +ossimEllipsoidFactory* ossimEllipsoidFactory::instance() +{ + if(!theInstance) + { + theInstance = new ossimEllipsoidFactory; + theInstance->initializeTable(); + } + + return theInstance; +} + +ossimEllipsoidFactory::ossimEllipsoidFactory() +{ +} + +ossimEllipsoidFactory::~ossimEllipsoidFactory() +{ + deleteAll(); + theInstance = NULL; +} + + +const ossimEllipsoid* ossimEllipsoidFactory::create(const ossimString &code)const +{ + TableType::const_iterator ellipsoid = theEllipsoidTable.find(code); + + if(ellipsoid != theEllipsoidTable.end()) + { + return (*ellipsoid).second; + } + + return NULL; +} + +void ossimEllipsoidFactory::initializeTable() +{ + if(theEllipsoidTable.size()<1) + { + theEllipsoidTable.insert(make_pair(ossimString("AA"), + new ossimEllipsoid(ossimString("Airy"), ossimString("AA"), 6377563.396, 6356256.9090))); + theEllipsoidTable.insert(make_pair(ossimString("AM"), + new ossimEllipsoid(ossimString("Modified Airy"), ossimString("AM"), 6377340.189, 6356034.448))); + theEllipsoidTable.insert(make_pair(ossimString("AN"), + new ossimEllipsoid(ossimString("Australian National"), ossimString("AN"), 6378160.000, 6356774.7190))); + theEllipsoidTable.insert(make_pair(ossimString("BR"), + new ossimEllipsoid(ossimString("Bessel 1841"), ossimString("BR"), 6377397.155, 6356078.9630))); + theEllipsoidTable.insert(make_pair(ossimString("BN"), + new ossimEllipsoid(ossimString("Bessel 1841(Namibia)"), ossimString("BN"), 6377483.865, 6356165.3830))); + theEllipsoidTable.insert(make_pair(ossimString("CC"), + new ossimEllipsoid(ossimString("Clarke 1866"), ossimString("CC"), 6378206.400, 6356583.8000))); + theEllipsoidTable.insert(make_pair(ossimString("CD"), + new ossimEllipsoid(ossimString("Clarke 1880"), ossimString("CD"), 6378249.145, 6356514.8700))); + theEllipsoidTable.insert(make_pair(ossimString("CE"), + new ossimEllipsoid(ossimString("Clarke 1880 (IGN)EPSG 7011"), ossimString("CE"), 6378249.200, 6356515.0000))); + theEllipsoidTable.insert(make_pair(ossimString("EA"), + new ossimEllipsoid(ossimString("Everest"), ossimString("EA"), 6377276.345, 6356075.4130))); + theEllipsoidTable.insert(make_pair(ossimString("EB"), + new ossimEllipsoid(ossimString("Everest (E. Malasia, Brunei)"), ossimString("EB"), 6377298.556, 6356097.55))); + theEllipsoidTable.insert(make_pair(ossimString("EC"), + new ossimEllipsoid(ossimString("Everest 1956 (India)"), ossimString("EC"), 6377301.243, 6356100.228))); + theEllipsoidTable.insert(make_pair(ossimString("ED"), + new ossimEllipsoid(ossimString("Everest 1969 (West Malasia)"), ossimString("ED"), 6377295.664, 6356094.668))); + theEllipsoidTable.insert(make_pair(ossimString("EE"), + new ossimEllipsoid(ossimString("Everest 1948(W.Mals. & Sing.)"), ossimString("EE"), 6377304.063, 6356103.039))); + theEllipsoidTable.insert(make_pair(ossimString("EF"), + new ossimEllipsoid(ossimString("Everest (Pakistan)"), ossimString("EF"), 6377309.613, 6356109.571))); + theEllipsoidTable.insert(make_pair(ossimString("FA"), + new ossimEllipsoid(ossimString("Mod. Fischer 1960(South Asia)"), ossimString("FA"), 6378155.0, 6356773.32))); + theEllipsoidTable.insert(make_pair(ossimString("RF"), + new ossimEllipsoid(ossimString("GRS 80"), ossimString("RF"), 6378137.0, 6356752.3141))); + theEllipsoidTable.insert(make_pair(ossimString("HE"), + new ossimEllipsoid(ossimString("Helmert 1906"), ossimString("HE"), 6378200.0, 6356818.17))); + theEllipsoidTable.insert(make_pair(ossimString("HO"), + new ossimEllipsoid(ossimString("Hough"), ossimString("HO"), 6378270.0, 6356794.3430))); + theEllipsoidTable.insert(make_pair(ossimString("ID"), + new ossimEllipsoid(ossimString("Indonesian 1974"), ossimString("ID"), 6378160.0, 6356774.504))); + theEllipsoidTable.insert(make_pair(ossimString("IN"), + new ossimEllipsoid(ossimString("International"), ossimString("IN"), 6378388.0, 6356911.946))); + theEllipsoidTable.insert(make_pair(ossimString("KA"), + new ossimEllipsoid(ossimString("Krassovsky"), ossimString("KA"), 6378245.0, 6356863.0190))); + theEllipsoidTable.insert(make_pair(ossimString("SA"), + new ossimEllipsoid(ossimString("South American 1969"),ossimString("SA"), 6378160.0, 6356774.719))); + theEllipsoidTable.insert(make_pair(ossimString("WD"), + new ossimEllipsoid(ossimString("WGS 72"), ossimString("WD"), 6378135.000, 6356750.5200))); + theEllipsoidTable.insert(make_pair(ossimString("WE"), + new ossimEllipsoid(ossimString("WGS 84"), ossimString("WE"), 6378137.000, 6356752.3142))); + theWgs84Ellipsoid = new ossimEllipsoid(ossimString("WGS 84"), ossimString("WE"), 6378137.000, 6356752.3142); + theWgs72Ellipsoid = new ossimEllipsoid(ossimString("WGS 72"), ossimString("WD"), 6378135.000, 6356750.5200); + } + +#if 0 + if(theEllipsoidTable.size()<1) + { + theEllipsoidTable.insert(make_pair(ossimString("AA"), + new ossimEllipsoid(ossimString("Airy"), ossimString("AA"), 6377563.396, 6356256.9090, 299.3249646))); + theEllipsoidTable.insert(make_pair(ossimString("AM"), + new ossimEllipsoid(ossimString("Modified Airy"), ossimString("AM"), 6377340.189, 6356034.448, 299.3249646))); + theEllipsoidTable.insert(make_pair(ossimString("AN"), + new ossimEllipsoid(ossimString("Australian National"), ossimString("AN"), 6378160.000, 6356774.7190, 298.25))); + theEllipsoidTable.insert(make_pair(ossimString("BR"), + new ossimEllipsoid(ossimString("Bessel 1841"), ossimString("BR"), 6377397.155, 6356078.9630, 299.1528128))); + theEllipsoidTable.insert(make_pair(ossimString("BN"), + new ossimEllipsoid(ossimString("Bessel 1841(Namibia)"), ossimString("BN"), 6377483.865, 6356165.3830, 299.1528128))); + theEllipsoidTable.insert(make_pair(ossimString("CC"), + new ossimEllipsoid(ossimString("Clarke 1866"), ossimString("CC"), 6378206.400, 6356583.8000, 294.9786982))); + theEllipsoidTable.insert(make_pair(ossimString("CD"), + new ossimEllipsoid(ossimString("Clarke 1880"), ossimString("CD"), 6378249.145, 6356514.8700, 293.465))); + theEllipsoidTable.insert(make_pair(ossimString("EA"), + new ossimEllipsoid(ossimString("Everest"), ossimString("EA"), 6377276.345, 6356075.4130, 300.8017))); + theEllipsoidTable.insert(make_pair(ossimString("EB"), + new ossimEllipsoid(ossimString("Everest (E. Malasia, Brunei)"), ossimString("EB"), 6377298.556, 6356097.55, 300.8017))); + theEllipsoidTable.insert(make_pair(ossimString("EC"), + new ossimEllipsoid(ossimString("Everest 1956 (India)"), ossimString("EC"), 6377301.243, 6356100.228, 300.8017))); + theEllipsoidTable.insert(make_pair(ossimString("ED"), + new ossimEllipsoid(ossimString("Everest 1969 (West Malasia)"), ossimString("ED"), 6377295.664, 6356094.668, 300.8017))); + theEllipsoidTable.insert(make_pair(ossimString("EE"), + new ossimEllipsoid(ossimString("Everest 1948(W.Mals. & Sing.)"), ossimString("EE"), 6377304.063, 6356103.039, 300.8017))); + theEllipsoidTable.insert(make_pair(ossimString("EF"), + new ossimEllipsoid(ossimString("Everest (Pakistan)"), ossimString("EF"), 6377309.613, 6356109.571, 300.8017))); + theEllipsoidTable.insert(make_pair(ossimString("FA"), + new ossimEllipsoid(ossimString("Mod. Fischer 1960(South Asia)"), ossimString("FA"), 6378155.0, 6356773.32, 298.3))); + theEllipsoidTable.insert(make_pair(ossimString("RF"), + new ossimEllipsoid(ossimString("GRS 80"), ossimString("RF"), 6378137.0, 6356752.3141, 298.257222101))); + theEllipsoidTable.insert(make_pair(ossimString("HE"), + new ossimEllipsoid(ossimString("Helmert 1906"), ossimString("HE"), 6378200.0, 6356818.17, 298.3))); + theEllipsoidTable.insert(make_pair(ossimString("HO"), + new ossimEllipsoid(ossimString("Hough"), ossimString("HO"), 6378270.0, 6356794.3430, 297.0))); + theEllipsoidTable.insert(make_pair(ossimString("ID"), + new ossimEllipsoid(ossimString("Indonesian 1974"), ossimString("ID"), 6378160.0, 6356774.504, 298.247))); + theEllipsoidTable.insert(make_pair(ossimString("IN"), + new ossimEllipsoid(ossimString("International"), ossimString("IN"), 6378388.0, 6356911.946, 297.0))); + theEllipsoidTable.insert(make_pair(ossimString("KA"), + new ossimEllipsoid(ossimString("Krassovsky"), ossimString("KA"), 6378245.0, 6356863.0190, 298.3))); + theEllipsoidTable.insert(make_pair(ossimString("SA"), + new ossimEllipsoid(ossimString("South American 1969"),ossimString("SA"), 6378160.0, 6356774.719, 298.25))); + theEllipsoidTable.insert(make_pair(ossimString("WD"), + new ossimEllipsoid(ossimString("WGS 72"), ossimString("WD"), 6378135.000, 6356750.5200, 298.26))); + theEllipsoidTable.insert(make_pair(ossimString("WE"), + new ossimEllipsoid(ossimString("WGS 84"), ossimString("WE"), 6378137.000, 6356752.3142, 298.257223563))); + theWgs84Ellipsoid = new ossimEllipsoid(ossimString("WGS 84"), ossimString("WE"), 6378137.000, 6356752.3142, 298.257223563); + theWgs72Ellipsoid = new ossimEllipsoid(ossimString("WGS 72"), ossimString("WD"), 6378135.000, 6356750.5200, 298.26); + } +#endif +} + +void ossimEllipsoidFactory::deleteAll() +{ + TableType::const_iterator ellipsoid = theEllipsoidTable.begin(); + + while(ellipsoid != theEllipsoidTable.end()) + { + delete (*ellipsoid).second; + ++ellipsoid; + } + + theEllipsoidTable.clear(); +} diff --git a/Utilities/OSSIM/ossim_core/base/factory/ossimEllipsoidFactory.h b/Utilities/OSSIM/ossim_core/base/factory/ossimEllipsoidFactory.h new file mode 100644 index 0000000000..0c5ef83855 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/factory/ossimEllipsoidFactory.h @@ -0,0 +1,58 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Thie file contains the ossimEllipsoidFactory. +//******************************************************************* +// $Id: ossimEllipsoidFactory.h,v 1.2 2002/11/25 19:16:28 gpotts Exp $ + +#ifndef ossimEllipsoidFactory_HEADER +#define ossimEllipsoidFactory_HEADER +#include <map> +using namespace std; +#include "base/data_types/ossimString.h" +class OSSIMDLLEXPORT ossimString; +class OSSIMDLLEXPORT ossimEllipsoid; +class OSSIMDLLEXPORT ossimWgs84Ellipsoid; +class OSSIMDLLEXPORT ossimWgs72Ellipsoid; + +class OSSIMDLLEXPORT ossimEllipsoidFactory +{ +public: + typedef map<ossimString, ossimEllipsoid*> TableType; + virtual ~ossimEllipsoidFactory(); + const ossimEllipsoid* create(const ossimString &code)const; + const ossimEllipsoid* wgs84()const{return theWgs84Ellipsoid;} + const ossimEllipsoid* wgs72()const{return theWgs72Ellipsoid;} + + static ossimEllipsoidFactory* instance(); + +private: + static ossimEllipsoidFactory* theInstance; + ossimEllipsoid* theWgs84Ellipsoid; + ossimEllipsoid* theWgs72Ellipsoid; + TableType theEllipsoidTable; + ossimEllipsoidFactory(); + void initializeTable(); + void deleteAll(); +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/factory/ossimObjectFactory.cpp b/Utilities/OSSIM/ossim_core/base/factory/ossimObjectFactory.cpp new file mode 100644 index 0000000000..c6915453ff --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/factory/ossimObjectFactory.cpp @@ -0,0 +1,4 @@ +#include "ossimObjectFactory.h" + +RTTI_DEF1(ossimObjectFactory, "ossimObjectFactory", ossimObject); + diff --git a/Utilities/OSSIM/ossim_core/base/factory/ossimObjectFactory.h b/Utilities/OSSIM/ossim_core/base/factory/ossimObjectFactory.h new file mode 100644 index 0000000000..225da5adc1 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/factory/ossimObjectFactory.h @@ -0,0 +1,58 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimObjectFactory.h,v 1.5 2002/11/25 19:16:28 gpotts Exp $ +#ifndef ossimObjectFactory_HEADER +#define ossimObjectFactory_HEADER + +#include "base/common/ossimObject.h" + +class OSSIMDLLEXPORT ossimObjectFactory : public ossimObject +{ +public: + virtual ~ossimObjectFactory(){} + + /*! + * Creates an object given a type name. + */ + virtual ossimObject* createObject(const ossimString& typeName)const=0; + + /*! + * Creates and object given a keyword list. + */ + virtual ossimObject* createObject(const ossimKeywordlist& kwl, + const char* prefix=0)const=0; + + /*! + * This should return the type name of all objects in all factories. + * This is the name used to construct the objects dynamially and this + * name must be unique. + */ + virtual void getTypeNameList(std::vector<ossimString>& typeList)const=0; + +protected: + + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/factory/ossimObjectFactoryRegistry.cpp b/Utilities/OSSIM/ossim_core/base/factory/ossimObjectFactoryRegistry.cpp new file mode 100644 index 0000000000..f6c83c72bc --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/factory/ossimObjectFactoryRegistry.cpp @@ -0,0 +1,187 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimObjectFactoryRegistry.cpp,v 1.10 2003/03/27 18:31:43 gpotts Exp $ + +#include "ossimObjectFactoryRegistry.h" + +RTTI_DEF1(ossimObjectFactoryRegistry, "ossimObjectFactoryRegistry", ossimObject); +#include "ossimObjectFactoryRegistry.h" +#include "ossimObjectFactory.h" +#include "ossimBaseObjectFactory.h" +using namespace std; + +ossimObjectFactoryRegistry* ossimObjectFactoryRegistry::theInstance=NULL; + +ossimObjectFactoryRegistry::~ossimObjectFactoryRegistry() +{ + theInstance = NULL; +} + +ossimObjectFactoryRegistry* ossimObjectFactoryRegistry::instance() +{ + if(!theInstance) + { + theInstance = new ossimObjectFactoryRegistry; + } + + return theInstance; +} + +bool ossimObjectFactoryRegistry::addFactory(ossimObjectFactory* factory) +{ + return registerFactory(factory); +} + +bool ossimObjectFactoryRegistry::registerFactory(ossimObjectFactory* factory) +{ + if(factory) + { + if(!findFactory(factory)) + { + theFactoryList.push_back(factory); + return true; + } + else + { + return true; + } + } + + return false; +} + +void ossimObjectFactoryRegistry::unregisterFactory(ossimObjectFactory* factory) +{ + vector<ossimObjectFactory*>::iterator iter = theFactoryList.begin(); + + while(iter != theFactoryList.end()) + { + if( (*iter) == factory) + { + theFactoryList.erase(iter); + return; + } + ++iter; + } +} + +ossimObject* ossimObjectFactoryRegistry::createObject(const ossimString& name)const +{ + ossimObject* result = NULL; + unsigned long index = 0; + + while((index < theFactoryList.size()) &&(!result)) + { + result = theFactoryList[index]->createObject(name); + ++index; + } + return result; +} + +ossimObject* ossimObjectFactoryRegistry::createObject(const ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimObject* result = NULL; + unsigned long index = 0; + + while((index < theFactoryList.size()) &&(!result)) + { + result = theFactoryList[index]->createObject(kwl, + prefix); + ++index; + } + + return result; +} + +void ossimObjectFactoryRegistry::getTypeNameList(std::vector<ossimString>& typeList)const +{ + vector<ossimString> result; + vector<ossimObjectFactory*>::const_iterator iter = theFactoryList.begin(); + + while(iter != theFactoryList.end()) + { + result.clear(); + (*iter)->getTypeNameList(result); + + typeList.insert(typeList.end(), + result.begin(), + result.end()); + ++iter; + } +} + +ossimObjectFactory* ossimObjectFactoryRegistry::findFactory(ossimObjectFactory* factory)const +{ + vector<ossimObjectFactory*>::const_iterator iter = theFactoryList.begin(); + + while(iter != theFactoryList.end()) + { + if( (*iter) == factory) + { + return factory; + } + ++iter; + } + + return NULL; +} + +void ossimObjectFactoryRegistry::getTypeNameList(std::vector<ossimString>& typeList, + const ossimString& baseType)const +{ + vector<ossimString> allTypeList; + + getTypeNameList(allTypeList); + + if(baseType == "") + { + typeList.insert(typeList.end(), + allTypeList.begin(), + allTypeList.end()); + } + else + { + int i = 0; + ossimObject* obj = (ossimObject*)NULL; + for(i = 0; i < (int)allTypeList.size(); ++i) + { + obj = createObject(allTypeList[i]); + if(obj) + { + if(obj->canCastTo(baseType)) + { + typeList.push_back(allTypeList[i]); + } + delete obj; + obj = (ossimObject*)NULL; + } + } + } +} + + +void* ossimObjectFactoryRegistryGetInstance() +{ + return ossimObjectFactoryRegistry::instance(); +} diff --git a/Utilities/OSSIM/ossim_core/base/factory/ossimObjectFactoryRegistry.h b/Utilities/OSSIM/ossim_core/base/factory/ossimObjectFactoryRegistry.h new file mode 100644 index 0000000000..ee5f59f56a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/factory/ossimObjectFactoryRegistry.h @@ -0,0 +1,90 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimObjectFactoryRegistry.h,v 1.10 2003/07/07 16:34:45 gpotts Exp $ +#ifndef ossimObjectFactoryRegistry_HEADER +#define ossimObjectFactoryRegistry_HEADER +#include <vector> + +#include "base/common/ossimObject.h" +#include "base/data_types/ossimString.h" + +class OSSIMDLLEXPORT ossimObjectFactory; +class OSSIMDLLEXPORT ossimKeywordlist; + +class OSSIMDLLEXPORT ossimObjectFactoryRegistry : public ossimObject +{ +public: + virtual ~ossimObjectFactoryRegistry(); + static ossimObjectFactoryRegistry* instance(); + /*! + * Should use the registerFactory to add a factory to the list. + * This method will call registerFactory. + */ + bool addFactory(ossimObjectFactory* factory); + + /*! + * Registers a factory to the list. + */ + bool registerFactory(ossimObjectFactory* factory); + void unregisterFactory(ossimObjectFactory* factory); + + virtual ossimObject* createObject(const ossimString& name)const; + virtual ossimObject* createObject(const ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Returns a type list of all objects that can be instantiated + * through the createObjectMethods above. + */ + virtual void getTypeNameList(std::vector<ossimString>& typeList)const; + + /*! + * returns a list of objects that are of the passed in + * base type. for example: + * + * If I want all ossimImageSource objects then I call: + * + * ossimObjectFactoryRegistry::instance()->getTypeNameList(l, + * "ossimImageSource"); + */ + virtual void getTypeNameList(std::vector<ossimString>& typeList, + const ossimString& baseType)const; + +protected: + ossimObjectFactoryRegistry(){}//hide + ossimObjectFactoryRegistry(const ossimObjectFactoryRegistry&):ossimObject(){}//hide + void operator =(const ossimObjectFactoryRegistry&){}//hide + + static ossimObjectFactoryRegistry* theInstance; + std::vector<ossimObjectFactory*> theFactoryList; + + ossimObjectFactory* findFactory(ossimObjectFactory* factory)const; + +TYPE_DATA +}; + +extern "C" +{ + OSSIMDLLEXPORT void* ossimObjectFactoryRegistryGetInstance(); +} +#endif diff --git a/Utilities/OSSIM/ossim_core/base/factory/ossimPropertyInterfaceFactory.cpp b/Utilities/OSSIM/ossim_core/base/factory/ossimPropertyInterfaceFactory.cpp new file mode 100644 index 0000000000..85bffd0d04 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/factory/ossimPropertyInterfaceFactory.cpp @@ -0,0 +1,5 @@ +#include "base/factory/ossimPropertyInterfaceFactory.h" + +RTTI_DEF1( ossimPropertyInterfaceFactory, "ossimPropertyInterfaceFactory", ossimObject ); + + diff --git a/Utilities/OSSIM/ossim_core/base/factory/ossimPropertyInterfaceFactory.h b/Utilities/OSSIM/ossim_core/base/factory/ossimPropertyInterfaceFactory.h new file mode 100644 index 0000000000..df7587193d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/factory/ossimPropertyInterfaceFactory.h @@ -0,0 +1,48 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimPropertyInterfaceFactory.h,v 1.6 2002/11/25 19:16:28 gpotts Exp $ +#ifndef ossimPropertyInterfaceFactory_HEADER +#define ossimPropertyInterfaceFactory_HEADER + + +#include "base/common/ossimRtti.h" +#include "base/factory/ossimObjectFactory.h" +class OSSIMDLLEXPORT ossimObject; +class OSSIMDLLEXPORT ossimPropertyInterface; + +class OSSIMDLLEXPORT ossimPropertyInterfaceFactory : public ossimObjectFactory +{ +public: + ossimPropertyInterfaceFactory() + :ossimObjectFactory() + {} + virtual ~ossimPropertyInterfaceFactory() + {} + + virtual ossimPropertyInterface* createInterface( const ossimObject* obj ) const = 0; + + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/factory/ossimPropertyInterfaceRegistry.cpp b/Utilities/OSSIM/ossim_core/base/factory/ossimPropertyInterfaceRegistry.cpp new file mode 100644 index 0000000000..f755fa630d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/factory/ossimPropertyInterfaceRegistry.cpp @@ -0,0 +1,112 @@ +#include "base/factory/ossimPropertyInterfaceRegistry.h" +#include "base/factory/ossimPropertyInterfaceFactory.h" + +using namespace std; + +RTTI_DEF1( ossimPropertyInterfaceRegistry, "ossimPropertyInterfaceRegistry", ossimObject ); + +ossimPropertyInterfaceRegistry* ossimPropertyInterfaceRegistry::theInstance = NULL; + +ossimPropertyInterfaceRegistry::~ossimPropertyInterfaceRegistry() +{ + theInstance = NULL; +} + +ossimPropertyInterface* ossimPropertyInterfaceRegistry::createInterface( const ossimObject* obj ) const +{ + vector<ossimPropertyInterfaceFactory*>::const_iterator i = theFactoryList.begin(); + ossimPropertyInterface* result = NULL; + + while ( ( i != theFactoryList.end() ) && ( ! result ) ) + { + result = (*i)->createInterface( obj ); + + ++i; + } + + return result; +} + +ossimPropertyInterfaceRegistry* ossimPropertyInterfaceRegistry::instance() +{ + if ( !theInstance) + { + theInstance = new ossimPropertyInterfaceRegistry; + } + + return theInstance; +} + +ossimObject* ossimPropertyInterfaceRegistry::createObject(const ossimString& typeName)const +{ + ossimObject* result = (ossimObject*)NULL; + vector<ossimPropertyInterfaceFactory*>::const_iterator i = theFactoryList.begin(); + + while ( ( i != theFactoryList.end() ) && ( ! result ) ) + { + result = (*i)->createObject(typeName); + + ++i; + } + + return result; +} + +ossimObject* ossimPropertyInterfaceRegistry::createObject(const ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimObject* result = (ossimObject*)NULL; + vector<ossimPropertyInterfaceFactory*>::const_iterator i = theFactoryList.begin(); + + while ( ( i != theFactoryList.end() ) && ( ! result ) ) + { + result = (*i)->createObject(kwl, prefix); + + ++i; + } + + return result; +} + +void ossimPropertyInterfaceRegistry::getTypeNameList(std::vector<ossimString>& typeList)const +{ + vector<ossimPropertyInterfaceFactory*>::const_iterator i = theFactoryList.begin(); + + while ( i != theFactoryList.end() ) + { + std::vector<ossimString> tempTypeList; + + (*i)->getTypeNameList(tempTypeList); + typeList.insert(typeList.end(), + tempTypeList.begin(), + tempTypeList.end()); + ++i; + } + +} + +bool ossimPropertyInterfaceRegistry::addFactory( ossimPropertyInterfaceFactory* factory ) +{ + return registerFactory(factory); +} + +bool ossimPropertyInterfaceRegistry::registerFactory(ossimPropertyInterfaceFactory* factory) +{ + bool result = false; + + if ( factory ) + { + theFactoryList.push_back( factory ); + result = true; + } + + return result; +} + +extern "C" +{ + void* ossimPropertyInterfaceRegistryGetInstance() + { + return ossimPropertyInterfaceRegistry::instance(); + } +} diff --git a/Utilities/OSSIM/ossim_core/base/factory/ossimPropertyInterfaceRegistry.h b/Utilities/OSSIM/ossim_core/base/factory/ossimPropertyInterfaceRegistry.h new file mode 100644 index 0000000000..695cc8a8a6 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/factory/ossimPropertyInterfaceRegistry.h @@ -0,0 +1,62 @@ +#ifndef ossimPropertyInterfaceRegistry_HEADER +#define ossimPropertyInterfaceRegistry_HEADER +#include "base/factory/ossimObjectFactory.h" + +class OSSIMDLLEXPORT ossimPropertyInterfaceFactory; +class OSSIMDLLEXPORT ossimPropertyInterface; + +#include "base/common/ossimRtti.h" + +#include <vector> +using namespace std; + +class OSSIMDLLEXPORT ossimPropertyInterfaceRegistry : public ossimObjectFactory +{ +public: + virtual ~ossimPropertyInterfaceRegistry(); + + static ossimPropertyInterfaceRegistry* instance(); + + virtual ossimPropertyInterface* createInterface( const ossimObject* obj ) const; + + /*! + * Creates an object given a type name. + */ + virtual ossimObject* createObject(const ossimString& typeName)const; + + /*! + * Creates and object given a keyword list. + */ + virtual ossimObject* createObject(const ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * This should return the type name of all objects in all factories. + * This is the name used to construct the objects dynamially and this + * name must be unique. + */ + virtual void getTypeNameList(std::vector<ossimString>& typeList)const; + + bool addFactory( ossimPropertyInterfaceFactory* factory ); + bool registerFactory(ossimPropertyInterfaceFactory* factory); + +protected: + ossimPropertyInterfaceRegistry() + :ossimObjectFactory() + {} + + ossimPropertyInterfaceRegistry( const ossimPropertyInterfaceRegistry& rhs ) + :ossimObjectFactory(rhs) + {} + void operator =(const ossimPropertyInterfaceRegistry&){} + static ossimPropertyInterfaceRegistry* theInstance; + vector<ossimPropertyInterfaceFactory*> theFactoryList; + +TYPE_DATA +}; + +extern "C" +{ + OSSIMDLLEXPORT void* ossimPropertyInterfaceRegistryGetInstance(); +} +#endif diff --git a/Utilities/OSSIM/ossim_core/base/factory/ossimStreamFactory.cpp b/Utilities/OSSIM/ossim_core/base/factory/ossimStreamFactory.cpp new file mode 100644 index 0000000000..afa602fbe5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/factory/ossimStreamFactory.cpp @@ -0,0 +1,82 @@ +//******************************************************************* +// Copyright (C) 2005 Garrett Potts +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// +//******************************************************************* +// $Id: ossimStreamFactory.cpp,v 1.4 2005/11/14 13:47:01 gpotts Exp $ +// +#include "ossimStreamFactory.h" +#include <fstream> +#include <ossimConfig.h> +#if OSSIM_HAS_LIBZ +#include <base/common/ossimGzStream.h> +#endif + +ossimStreamFactory* ossimStreamFactory::theInstance = 0; + +ossimStreamFactory::ossimStreamFactory() +{ +} + +ossimStreamFactory::~ossimStreamFactory() +{ +} + +ossimStreamFactory* ossimStreamFactory::instance() +{ + if(!theInstance) + { + theInstance = new ossimStreamFactory; + } + + return theInstance; +} + +ossimRefPtr<ossimIStream> ossimStreamFactory::createNewInputStream(const ossimFilename& file, + std::ios::openmode openMode) +{ +#if OSSIM_HAS_LIBZ + ossimFilename copyFile = file; + + if(!copyFile.exists()) + { + ossimString ext = copyFile.ext(); + copyFile.setExtension("gz"); + if(!copyFile.exists()) + { + copyFile.setExtension(ext); + copyFile += ".gz"; + + if(!copyFile.exists()) + { + return false; + } + } + } + + std::ifstream in(copyFile.c_str(), std::ios::in|std::ios::binary); + + if(!in) return 0; + + unsigned char buf[2]; + + in.read((char*)buf, 2); + in.close(); + // check for gzip magic number + // + if((buf[0] == 0x1F) && + (buf[1] == 0x8B)) + { + return new ossimIgzStream(copyFile.c_str(), + openMode); + } +#endif + return 0; +} + diff --git a/Utilities/OSSIM/ossim_core/base/factory/ossimStreamFactory.h b/Utilities/OSSIM/ossim_core/base/factory/ossimStreamFactory.h new file mode 100644 index 0000000000..844ee4cc6a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/factory/ossimStreamFactory.h @@ -0,0 +1,35 @@ +//******************************************************************* +// Copyright (C) 2005 Garrett Potts +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// +//******************************************************************* +// $Id: ossimStreamFactory.h,v 1.3 2005/11/14 13:47:01 gpotts Exp $ +// +#ifndef ossimStreamFactory_HEADER +#define ossimStreamFactory_HEADER +#include "ossimStreamFactoryBase.h" + +class OSSIM_DLL ossimStreamFactory : public ossimStreamFactoryBase +{ +public: + static ossimStreamFactory* instance(); + virtual ~ossimStreamFactory(); + + virtual ossimRefPtr<ossimIStream> createNewInputStream(const ossimFilename& file, + std::ios::openmode openMode); + + +protected: + ossimStreamFactory(); + ossimStreamFactory(const ossimStreamFactory&){} + static ossimStreamFactory* theInstance; + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/factory/ossimStreamFactoryBase.h b/Utilities/OSSIM/ossim_core/base/factory/ossimStreamFactoryBase.h new file mode 100644 index 0000000000..d6d1be7d73 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/factory/ossimStreamFactoryBase.h @@ -0,0 +1,32 @@ +//******************************************************************* +// Copyright (C) 2005 Garrett Potts +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// +//******************************************************************* +// $Id: ossimStreamFactoryBase.h,v 1.5 2005/11/14 13:47:01 gpotts Exp $ +// +#ifndef ossimStreamFactoryBase_HEADER +#define ossimStreamFactoryBase_HEADER +#include <iostream> +#include <base/common/ossimIoStream.h> +#include <base/common/ossimConstants.h> +#include <base/common/ossimRefPtr.h> +#include <base/data_types/ossimFilename.h> + +class OSSIM_DLL ossimStreamFactoryBase +{ +public: + virtual ~ossimStreamFactoryBase(){} + + virtual ossimRefPtr<ossimIStream> createNewInputStream( + const ossimFilename& file, + std::ios::openmode openMode)=0; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/factory/ossimStreamFactoryRegistry.cpp b/Utilities/OSSIM/ossim_core/base/factory/ossimStreamFactoryRegistry.cpp new file mode 100644 index 0000000000..0e78e69f45 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/factory/ossimStreamFactoryRegistry.cpp @@ -0,0 +1,71 @@ +//******************************************************************* +// Copyright (C) 2005 Garrett Potts +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// +//******************************************************************* +// $Id: ossimStreamFactoryRegistry.cpp,v 1.3 2005/11/14 13:47:01 gpotts Exp $ +// +#include "ossimStreamFactoryRegistry.h" +#include "ossimStreamFactory.h" +#include <fstream> +#include <algorithm> + +ossimStreamFactoryRegistry* ossimStreamFactoryRegistry::theInstance = 0; + +ossimStreamFactoryRegistry::ossimStreamFactoryRegistry() +{ +} + +ossimStreamFactoryRegistry::~ossimStreamFactoryRegistry() +{ +} + +ossimStreamFactoryRegistry* ossimStreamFactoryRegistry::instance() +{ + if(!theInstance) + { + theInstance = new ossimStreamFactoryRegistry; + theInstance->registerFactory(ossimStreamFactory::instance()); + } + + return theInstance; +} + +ossimRefPtr<ossimIStream> ossimStreamFactoryRegistry::createNewInputStream(const ossimFilename& file, + std::ios::openmode openMode) +{ + ossim_uint32 idx = 0; + ossimRefPtr<ossimIStream> result = 0; + for(idx = 0; ((idx < theFactoryList.size())&&(!result)); ++idx) + { + result = theFactoryList[idx]->createNewInputStream(file, openMode); + } + + if(!result) + { + result = new ossimIFStream(file.c_str(), + openMode); +// result = new std::ifstream(file.c_str(), +// openMode); + } + + return result; +} + + +void ossimStreamFactoryRegistry::registerFactory(ossimStreamFactoryBase* factory) +{ + std::vector<ossimStreamFactoryBase*>::iterator iter = std::find(theFactoryList.begin(), + theFactoryList.end(), + factory); + if(iter == theFactoryList.end()) + { + theFactoryList.push_back(factory); + } +} diff --git a/Utilities/OSSIM/ossim_core/base/factory/ossimStreamFactoryRegistry.h b/Utilities/OSSIM/ossim_core/base/factory/ossimStreamFactoryRegistry.h new file mode 100644 index 0000000000..be064fed19 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/factory/ossimStreamFactoryRegistry.h @@ -0,0 +1,38 @@ +//******************************************************************* +// Copyright (C) 2005 Garrett Potts +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// +//******************************************************************* +// $Id: ossimStreamFactoryRegistry.h,v 1.3 2005/11/14 13:47:01 gpotts Exp $ +// +#ifndef ossimStreamFactoryRegistry_HEADER +#define ossimStreamFactoryRegistry_HEADER +#include "ossimStreamFactoryBase.h" +#include <vector> + +class OSSIM_DLL ossimStreamFactoryRegistry : public ossimStreamFactoryBase +{ +public: + static ossimStreamFactoryRegistry* instance(); + virtual ~ossimStreamFactoryRegistry(); + + void registerFactory(ossimStreamFactoryBase* factory); + + virtual ossimRefPtr<ossimIStream> createNewInputStream(const ossimFilename& file, + std::ios::openmode openMode); + +protected: + ossimStreamFactoryRegistry(); +private: + ossimStreamFactoryRegistry(const ossimStreamFactoryRegistry&){} + std::vector<ossimStreamFactoryBase*> theFactoryList; + static ossimStreamFactoryRegistry* theInstance; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/misc/.cvsignore b/Utilities/OSSIM/ossim_core/base/misc/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/base/misc/FlexLexer.h b/Utilities/OSSIM/ossim_core/base/misc/FlexLexer.h new file mode 100644 index 0000000000..8c1defd17c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/FlexLexer.h @@ -0,0 +1,188 @@ +// $Header: /cvs/ossim/src/ossim_core/base/misc/FlexLexer.h,v 1.4 2004/03/19 18:31:47 gpotts Exp $ + +// FlexLexer.h -- define interfaces for lexical analyzer classes generated +// by flex + +// Copyright (c) 1993 The Regents of the University of California. +// All rights reserved. +// +// This code is derived from software contributed to Berkeley by +// Kent Williams and Tom Epperly. +// +// Redistribution and use in source and binary forms with or without +// modification are permitted provided that: (1) source distributions retain +// this entire copyright notice and comment, and (2) distributions including +// binaries display the following acknowledgement: ``This product includes +// software developed by the University of California, Berkeley and its +// contributors'' in the documentation or other materials provided with the +// distribution and in all advertising materials mentioning features or use +// of this software. Neither the name of the University nor the names of +// its contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. + +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +// This file defines FlexLexer, an abstract class which specifies the +// external interface provided to flex C++ lexer objects, and yyFlexLexer, +// which defines a particular lexer class. +// +// If you want to create multiple lexer classes, you use the -P flag +// to rename each yyFlexLexer to some other xxFlexLexer. You then +// include <FlexLexer.h> in your other sources once per lexer class: +// +// #undef yyFlexLexer +// #define yyFlexLexer xxFlexLexer +// #include <FlexLexer.h> +// +// #undef yyFlexLexer +// #define yyFlexLexer zzFlexLexer +// #include <FlexLexer.h> +// ... + +#ifndef __FLEX_LEXER_H +// Never included before - need to define base class. +#define __FLEX_LEXER_H +#include <iostream> +#include "base/common/ossimConstants.h" +using namespace std; + +extern "C++" { + +struct yy_buffer_state; +typedef int yy_state_type; + +class OSSIMDLLEXPORT FlexLexer { +public: + virtual ~FlexLexer() { } + + const char* YYText() { return yytext; } + int YYLeng() { return yyleng; } + + virtual void + yy_switch_to_buffer( struct yy_buffer_state* new_buffer ) = 0; + virtual struct yy_buffer_state* + yy_create_buffer( istream* s, int size ) = 0; + virtual void yy_delete_buffer( struct yy_buffer_state* b ) = 0; + virtual void yyrestart( istream* s ) = 0; + + virtual int yylex() = 0; + + // Call yylex with new input/output sources. + int yylex( istream* new_in, ostream* new_out = 0 ) + { + switch_streams( new_in, new_out ); + return yylex(); + } + + // Switch to new input/output streams. A nil stream pointer + // indicates "keep the current one". + virtual void switch_streams( istream* new_in = 0, + ostream* new_out = 0 ) = 0; + + int lineno() const { return yylineno; } + + int debug() const { return yy_flex_debug; } + void set_debug( int flag ) { yy_flex_debug = flag; } + +protected: + char* yytext; + int yyleng; + int yylineno; // only maintained if you use %option yylineno + int yy_flex_debug; // only has effect with -d or "%option debug" +}; + +} +#endif + +#if defined(yyFlexLexer) || ! defined(yyFlexLexerOnce) +// Either this is the first time through (yyFlexLexerOnce not defined), +// or this is a repeated include to define a different flavor of +// yyFlexLexer, as discussed in the flex man page. +#define yyFlexLexerOnce + +class OSSIMDLLEXPORT yyFlexLexer : public FlexLexer { +public: + // arg_yyin and arg_yyout default to the cin and cout, but we + // only make that assignment when initializing in yylex(). + yyFlexLexer( istream* arg_yyin = 0, ostream* arg_yyout = 0 ); + + virtual ~yyFlexLexer(); + + void yy_switch_to_buffer( struct yy_buffer_state* new_buffer ); + struct yy_buffer_state* yy_create_buffer( istream* s, int size ); + void yy_delete_buffer( struct yy_buffer_state* b ); + void yyrestart( istream* s ); + + virtual int yylex(); + virtual void switch_streams( istream* new_in, ostream* new_out ); + +protected: + virtual int LexerInput( char* buf, int max_size ); + virtual void LexerOutput( const char* buf, int size ); + virtual void LexerError( const char* msg ); + + void yyunput( int c, char* buf_ptr ); + int yyinput(); + + void yy_load_buffer_state(); + void yy_init_buffer( struct yy_buffer_state* b, istream* s ); + void yy_flush_buffer( struct yy_buffer_state* b ); + + int yy_start_stack_ptr; + int yy_start_stack_depth; + int* yy_start_stack; + + void yy_push_state( int new_state ); + void yy_pop_state(); + int yy_top_state(); + + yy_state_type yy_get_previous_state(); + yy_state_type yy_try_NUL_trans( yy_state_type current_state ); + int yy_get_next_buffer(); + + istream* yyin; // input source for default LexerInput + ostream* yyout; // output sink for default LexerOutput + + struct yy_buffer_state* yy_current_buffer; + + // yy_hold_char holds the character lost when yytext is formed. + char yy_hold_char; + + // Number of characters read into yy_ch_buf. + int yy_n_chars; + + // Points to current character in buffer. + char* yy_c_buf_p; + + int yy_init; // whether we need to initialize + int yy_start; // start state number + + // Flag which is used to allow yywrap()'s to do buffer switches + // instead of setting up a fresh yyin. A bit of a hack ... + int yy_did_buffer_switch_on_eof; + + // The following are not always needed, but may be depending + // on use of certain flex features (like REJECT or yymore()). + + yy_state_type yy_last_accepting_state; + char* yy_last_accepting_cpos; + + yy_state_type* yy_state_buf; + yy_state_type* yy_state_ptr; + + char* yy_full_match; + int* yy_full_state; + int yy_full_lp; + + int yy_lp; + int yy_looking_for_trail_begin; + + int yy_more_flag; + int yy_more_len; + int yy_more_offset; + int yy_prev_more_offset; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/misc/hash/.cvsignore b/Utilities/OSSIM/ossim_core/base/misc/hash/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/hash/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/base/misc/hash/ossimPointHash.h b/Utilities/OSSIM/ossim_core/base/misc/hash/ossimPointHash.h new file mode 100644 index 0000000000..f478836595 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/hash/ossimPointHash.h @@ -0,0 +1,28 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: Point Hash is a base for hashing functions +// +//******************************************************************* +// $Id: ossimPointHash.h,v 1.3 2005/07/15 19:16:59 dburken Exp $ + +#ifndef ossimPointHash_HEADER +#define ossimPointHash_HEADER +#include "base/data_types/ossimDpt.h" +#include "base/data_types/ossimFpt.h" + +class OSSIMDLLEXPORT ossimPointHash +{ +public: + virtual ~ossimPointHash(){} + virtual long operator ()(const ossimDpt &aPoint)=0; + virtual long operator ()(const ossimFpt &aPoint)=0; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/misc/hash/ossimTileHash.cpp b/Utilities/OSSIM/ossim_core/base/misc/hash/ossimTileHash.cpp new file mode 100644 index 0000000000..53151502a9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/hash/ossimTileHash.cpp @@ -0,0 +1,123 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken Copied from TiledImageHash. +// +// Description: Hashing function for tiled rectangles. WIll hash a +// dpt or a to a single index value. +// +// NOTE: This works with rectangles that are positive in the line up +// (y) direction. +// +//******************************************************************* +// $Id: ossimTileHash.cpp,v 1.3 2005/07/15 19:25:10 dburken Exp $ + +#include <cfloat> // for FLT_EPSILON + +#include <base/misc/hash/ossimTileHash.h> + +ossimTileHash::ossimTileHash(const ossimDrect& imageRect, + double tileWidth, + double tileHeight) + : + ossimPointHash(), + theImageRect(imageRect) +{ + // make sure that the width of the tile is not larger than + // the width of the image rectangle. + if(theImageRect.width() <= tileWidth) + { + theTileWidth = theImageRect.width(); + theNumberOfHorizTiles = 1; + } + else + { + theTileWidth = tileWidth; + double tempDiv = theImageRect.width()/theTileWidth; + double overFlow = tempDiv - static_cast<long>(tempDiv); + theNumberOfHorizTiles = static_cast<long>(tempDiv); + + if(fabs(overFlow) > FLT_EPSILON) // if the extent went beyond a tile + { + theNumberOfHorizTiles ++; // we must say it has another tile + } + } + + // make sure the height of the tile is not larger than the + // height of the image rectangle. + if(theImageRect.height() <= tileHeight) + { + theTileHeight = theImageRect.height(); + theNumberOfVertTiles = 1; + } + else + { + theTileHeight = tileHeight; + double tempDiv = theImageRect.height()/theTileHeight; + double overFlow = tempDiv - static_cast<long>(tempDiv); + theNumberOfVertTiles = static_cast<long>(tempDiv); + + if(fabs(overFlow) > FLT_EPSILON) // if the extent went beyond a tile + { + theNumberOfVertTiles ++; // we must say it has another tile + } + } +} + +ossimTileHash::~ossimTileHash() +{ +} + +long ossimTileHash::operator()(const ossimFpt& aPoint) +{ + if ( (aPoint.x >= theImageRect.ul().x) && + (aPoint.x <= theImageRect.lr().x) && + (aPoint.y <= theImageRect.ul().y) && + (aPoint.y >= theImageRect.lr().y) ) + { + // how far is the point horizontally from the upper left corner + double deltaWidth = aPoint.x - theImageRect.ul().x; + + // how far is the point vertically from the upper left point + double deltaHeight = theImageRect.ul().y - aPoint.y; + + // solve the horizontal and vertical index numbers + long indexWidth = static_cast<long>(deltaWidth / theTileWidth); + long indexHeight = static_cast<long>(deltaHeight / theTileHeight); + + // Map to a linear array. + // Just like you would index a 2-D array in memory + return static_cast<long>(theNumberOfHorizTiles*indexHeight + indexWidth); + } + + return -1; +} + +long ossimTileHash::operator()(const ossimDpt& aPoint) +{ + if ( (aPoint.x >= theImageRect.ul().x) && + (aPoint.x <= theImageRect.lr().x) && + (aPoint.y <= theImageRect.ul().y) && + (aPoint.y >= theImageRect.lr().y) ) + { + // how far is the point horizontally from the upper left corner + double deltaWidth = aPoint.x - theImageRect.ul().x; + + // how far is the point vertically from the upper left point + double deltaHeight = theImageRect.ul().y - aPoint.y; + + // solve the horizontal and vertical index numbers + long indexWidth = static_cast<long>(deltaWidth / theTileWidth); + long indexHeight = static_cast<long>(deltaHeight / theTileHeight); + + // Map to a linear array. + // Just like you would index a 2-D array in memory + return static_cast<long>(theNumberOfHorizTiles*indexHeight + indexWidth); + } + + return -1; +} diff --git a/Utilities/OSSIM/ossim_core/base/misc/hash/ossimTileHash.h b/Utilities/OSSIM/ossim_core/base/misc/hash/ossimTileHash.h new file mode 100644 index 0000000000..456f509e0a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/hash/ossimTileHash.h @@ -0,0 +1,46 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken Copied from TiledImageHash. +// +// Description: Hashing function for tiled rectangles. Will hash a +// dpt or fpt to a single index value. +// +// NOTE: Works on rectangles that are positive in the line up (y) +// direction. Use TiledImageHash for rectangles that are positive +// in the line down direction. +// +//******************************************************************* +// $Id: ossimTileHash.h,v 1.4 2005/07/15 19:25:46 dburken Exp $ + +#ifndef TileHash_HEADER +#define TileHash_HEADER + +#include <base/data_types/ossimDrect.h> +#include <base/misc/hash/ossimPointHash.h> + +class OSSIMDLLEXPORT ossimTileHash : public ossimPointHash +{ +public: + ossimTileHash(const ossimDrect &imageRect, + double tileWidth, + double tileHeight); + + virtual ~ossimTileHash(); + + virtual long operator()(const ossimDpt &aPoint); + virtual long operator()(const ossimFpt &aPoint); + +private: + ossimDrect theImageRect; + double theTileWidth; + double theTileHeight; + long theNumberOfHorizTiles; + long theNumberOfVertTiles; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/misc/hash/ossimTiledImageHash.cpp b/Utilities/OSSIM/ossim_core/base/misc/hash/ossimTiledImageHash.cpp new file mode 100644 index 0000000000..d07fdd56ae --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/hash/ossimTiledImageHash.cpp @@ -0,0 +1,140 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: Hashing function for tiled rectangles. WIll hash a +// dpt to a single index value. +// +//******************************************************************* +// $Id: ossimTiledImageHash.cpp,v 1.2 2005/07/15 19:16:59 dburken Exp $ + +#include <cfloat> // for FLT_EPSILON + +#include <base/misc/hash/ossimTiledImageHash.h> + + +ossimTiledImageHash::ossimTiledImageHash(const ossimDrect &imageRect, + double tileWidth, + double tileHeight) + :ossimPointHash(), + theImageRect(imageRect) +{ + // make sure that the width of the tile is not larger than + // the width of the image rectangle. + if(theImageRect.width() < tileWidth) + { + theTileWidth = theImageRect.width(); + theNumberOfHorizTiles = 1; + } + else + { + theTileWidth = tileWidth; + double tempDiv = theImageRect.width()/theTileWidth; + double overFlow = tempDiv - static_cast<long>(tempDiv); + theNumberOfHorizTiles = static_cast<long>(tempDiv); + + if(fabs(overFlow) >= FLT_EPSILON) // if the extent went beyond a tile + { + theNumberOfHorizTiles ++; // we must say it has another tile + } + } + + // make sure the height of the tile is not larger than the + // height of the image rectangle. + if(theImageRect.height() < tileHeight) + { + theTileHeight = theImageRect.height(); + theNumberOfVertTiles = 1; + } + else + { + theTileHeight = tileHeight; + double tempDiv = theImageRect.height()/theTileHeight; + double overFlow = tempDiv - static_cast<long>(tempDiv); + theNumberOfVertTiles = static_cast<long>(tempDiv); + + if(fabs(overFlow) >= FLT_EPSILON) // if the extent went beyond a tile + { + theNumberOfVertTiles ++; // we must say it has another tile + } + } + +} + +ossimTiledImageHash::~ossimTiledImageHash() +{ +} + +long ossimTiledImageHash::operator()(const ossimDpt &aPoint) +{ + if(aPoint.x >= theImageRect.ul().x && aPoint.y >= theImageRect.ul().y) + { + // how far is the point horizontally from the upper left corner + double deltaWidth = aPoint.x - theImageRect.ul().x; + + // how far is the point vertically from the upper left point + double deltaHeight = aPoint.y - theImageRect.ul().y; + + // if deltas are negative then we are outside the + // bounds + if((deltaWidth < 0) || (deltaHeight < 0)) + { + return -1; + } + + // check if outside the rectangle + if( (deltaWidth > theNumberOfHorizTiles*theTileWidth)|| + (deltaHeight > theNumberOfVertTiles*theTileHeight)) + { + return -1; + } + // solve the horizontal and vertical index numbers + long indexWidth = static_cast<long>(deltaWidth / theTileWidth); + long indexHeight = static_cast<long>(deltaHeight / theTileHeight); + + // map to a linear array. Just like you would index a 2-D array in memory + return static_cast<long>(theNumberOfHorizTiles*indexHeight + indexWidth); + } + + return -1; +} + +long ossimTiledImageHash::operator()(const ossimFpt &aPoint) +{ + if(aPoint.x >= theImageRect.ul().x && aPoint.y >= theImageRect.ul().y) + { + // how far is the point horizontally from the upper left corner + double deltaWidth = aPoint.x - theImageRect.ul().x; + + // how far is the point vertically from the upper left point + double deltaHeight = aPoint.y - theImageRect.ul().y; + + // if deltas are negative then we are outside the + // bounds + if((deltaWidth < 0) || (deltaHeight < 0)) + { + return -1; + } + + // check if outside the rectangle + if( (deltaWidth > theNumberOfHorizTiles*theTileWidth)|| + (deltaHeight > theNumberOfVertTiles*theTileHeight)) + { + return -1; + } + // solve the horizontal and vertical index numbers + long indexWidth = static_cast<long>(deltaWidth / theTileWidth); + long indexHeight = static_cast<long>(deltaHeight / theTileHeight); + + // map to a linear array. Just like you would index a 2-D array in memory + return static_cast<long>(theNumberOfHorizTiles*indexHeight + indexWidth); + } + + return -1; +} + diff --git a/Utilities/OSSIM/ossim_core/base/misc/hash/ossimTiledImageHash.h b/Utilities/OSSIM/ossim_core/base/misc/hash/ossimTiledImageHash.h new file mode 100644 index 0000000000..b142a4e042 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/hash/ossimTiledImageHash.h @@ -0,0 +1,40 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: Hashing function for tiled rectangles. Will hash a +// dpt to a single index value. +// +//******************************************************************* +// $Id: ossimTiledImageHash.h,v 1.3 2005/07/15 19:16:59 dburken Exp $ +#ifndef ossimTiledImageHash_HEADER +#define ossimTiledImageHash_HEADER +#include "base/data_types/ossimDrect.h" +#include "ossimPointHash.h" + +class OSSIMDLLEXPORT ossimTiledImageHash : public ossimPointHash +{ +public: + ossimTiledImageHash(const ossimDrect &imageRect, + double tileWidth, + double tileHeight); + + virtual ~ossimTiledImageHash(); + + virtual long operator()(const ossimDpt &aPoint); + virtual long operator()(const ossimFpt &aPoint); + +private: + ossimDrect theImageRect; + double theTileWidth; + double theTileHeight; + long theNumberOfHorizTiles; + long theNumberOfVertTiles; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/.cvsignore b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimGeoTiffCoordTransformsLut.cpp b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimGeoTiffCoordTransformsLut.cpp new file mode 100644 index 0000000000..de0b0a2981 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimGeoTiffCoordTransformsLut.cpp @@ -0,0 +1,97 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// +// Description: +// +// Contains class definition for ossimGeoTiffCoordTransformsLut. +//******************************************************************* +// $Id: ossimGeoTiffCoordTransformsLut.cpp,v 1.2 2001/06/29 21:01:26 dburken Exp $ + +#include "ossimGeoTiffCoordTransformsLut.h" +#include "base/data_types/ossimString.h" + +static const int TABLE_SIZE = 27; + +//******************************************************************* +// Public Constructor: +//******************************************************************* +ossimGeoTiffCoordTransformsLut::ossimGeoTiffCoordTransformsLut() + : + ossimLookUpTable(TABLE_SIZE) +{ + //*** + // Complete initialization of data member "theTable". + // Note: Scalar types defined in constants.h file. + //*** + theTable[0].theKey = CT_TransverseMercator; + theTable[0].theValue = "ossimTransMercatorProjection"; + theTable[1].theKey = CT_TransvMercator_Modified_Alaska; + theTable[1].theValue = "unknown"; + theTable[2].theKey = CT_ObliqueMercator; + theTable[2].theValue = "unknown"; + theTable[3].theKey = CT_ObliqueMercator_Laborde; + theTable[3].theValue = "unknown"; + theTable[4].theKey = CT_ObliqueMercator_Rosenmund; + theTable[4].theValue = "unknown"; + theTable[5].theKey = CT_ObliqueMercator_Spherical; + theTable[5].theValue = "unknown"; + theTable[6].theKey = CT_Mercator; + theTable[6].theValue = "ossimMercatorProjection"; + theTable[7].theKey = CT_LambertConfConic_2SP; + theTable[7].theValue = "ossimLambertConformalConicProjection"; + theTable[8].theKey = CT_LambertConfConic_Helmert; + theTable[8].theValue = "unknown"; + theTable[9].theKey = CT_LambertAzimEqualArea; + theTable[9].theValue = "unknown"; + theTable[10].theKey = CT_AlbersEqualArea; + theTable[10].theValue = "ossimAlbersProjection"; + theTable[11].theKey = CT_AzimuthalEquidistant; + theTable[11].theValue = "unknown"; + theTable[12].theKey = CT_EquidistantConic; + theTable[12].theValue = "unknown"; + theTable[13].theKey = CT_Stereographic; + theTable[13].theValue = "unknown"; + theTable[14].theKey = CT_PolarStereographic; + theTable[14].theValue = "ossimPolarStereoProjection"; + theTable[15].theKey = CT_ObliqueStereographic; + theTable[15].theValue = "ossimPolarStereoProjection"; + theTable[16].theKey = CT_Equirectangular; + theTable[16].theValue = "ossimEquDistCylProjection"; + theTable[17].theKey = CT_CassiniSoldner; + theTable[17].theValue = "ossimCassiniProjection"; + theTable[18].theKey = CT_Gnomonic; + theTable[18].theValue = "unknown"; + theTable[19].theKey = CT_MillerCylindrical; + theTable[19].theValue = "ossimMillerProjection"; + theTable[20].theKey = CT_Orthographic; + theTable[20].theValue = "ossimOrthoGraphicProjection"; + theTable[21].theKey = CT_Polyconic; + theTable[21].theValue = "ossimPolyconicrojection"; + theTable[22].theKey = CT_Robinson; + theTable[22].theValue = "unkknown"; + theTable[23].theKey = CT_Sinusoidal; + theTable[23].theValue = "ossimSinusoidalProjection"; + theTable[24].theKey = CT_VanDerGrinten; + theTable[24].theValue = "ossimVanDerGrintenProjection"; + theTable[25].theKey = CT_NewZealandMapGrid; + theTable[25].theValue = "unknown"; + theTable[26].theKey = CT_TransvMercator_SouthOriented; + theTable[26].theValue = "unknown"; +} diff --git a/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimGeoTiffCoordTransformsLut.h b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimGeoTiffCoordTransformsLut.h new file mode 100644 index 0000000000..cbb2799618 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimGeoTiffCoordTransformsLut.h @@ -0,0 +1,81 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// +// Description: +// +// Contains class declaration for GeoTiffCoordTransformsLut. Used to map a +// geotiff coordinate transformation code to an ossim projection. +//******************************************************************* +// $Id: ossimGeoTiffCoordTransformsLut.h,v 1.2 2002/11/25 19:16:28 gpotts Exp $ + +#ifndef ossimGeoTiffCoordTransformsLut_HEADER +#define ossimGeoTiffCoordTransformsLut_HEADER + +#include "ossimLookUpTable.h" +#include "base/common/ossimKeywordNames.h" + +class OSSIMDLLEXPORT ossimGeoTiffCoordTransformsLut : public ossimLookUpTable +{ +public: + + enum + { + //*** + // Coordinate Transformation Codes cut from geotiff specification + // section 6.3.3.3. + //*** + CT_TransverseMercator = 1, + CT_TransvMercator_Modified_Alaska = 2, + CT_ObliqueMercator = 3, + CT_ObliqueMercator_Laborde = 4, + CT_ObliqueMercator_Rosenmund = 5, + CT_ObliqueMercator_Spherical = 6, + CT_Mercator = 7, + CT_LambertConfConic_2SP = 8, + CT_LambertConfConic_Helmert = 9, + CT_LambertAzimEqualArea = 10, + CT_AlbersEqualArea = 11, + CT_AzimuthalEquidistant = 12, + CT_EquidistantConic = 13, + CT_Stereographic = 14, + CT_PolarStereographic = 15, + CT_ObliqueStereographic = 16, + CT_Equirectangular = 17, + CT_CassiniSoldner = 18, + CT_Gnomonic = 19, + CT_MillerCylindrical = 20, + CT_Orthographic = 21, + CT_Polyconic = 22, + CT_Robinson = 23, + CT_Sinusoidal = 24, + CT_VanDerGrinten = 25, + CT_NewZealandMapGrid = 26, + CT_TransvMercator_SouthOriented = 27 + }; + + ossimGeoTiffCoordTransformsLut(); + + virtual ~ossimGeoTiffCoordTransformsLut(){} + + virtual ossimKeyword getKeyword() const + { return ossimKeyword("geotiff_coordinate_transform_code", ""); } +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimGeoTiffDatumLut.cpp b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimGeoTiffDatumLut.cpp new file mode 100644 index 0000000000..666cf55513 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimGeoTiffDatumLut.cpp @@ -0,0 +1,116 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class definition for ossimGeoTiffDatumLut. +//******************************************************************* +// $Id: ossimGeoTiffDatumLut.cpp,v 1.4 2005/01/21 18:55:19 dburken Exp $ + +#include "ossimGeoTiffDatumLut.h" +#include "base/data_types/ossimString.h" + +static const int TABLE_SIZE = 24; + +//******************************************************************* +// Public Constructor: +//******************************************************************* +ossimGeoTiffDatumLut::ossimGeoTiffDatumLut() + : + ossimLookUpTable(TABLE_SIZE) +{ + //*** + // Complete initialization of data member "theTable". + // Note: Scalar types defined in constants.h file. + //*** + theTable[0].theKey = GCS_Adindan; + theTable[0].theValue = "ADI-M"; + + theTable[1].theKey = GCS_Arc_1950; + theTable[1].theValue = "ARF-M"; + + theTable[2].theKey = GCS_Arc_1960; + theTable[2].theValue = "ARS-M"; + + theTable[3].theKey = GCS_ED50; + theTable[3].theValue = "EUR-M"; + + theTable[4].theKey = GCS_NAD27; + theTable[4].theValue = "NAS-C"; + + theTable[5].theKey = GCS_NAD83; + theTable[5].theValue = "NAR-C"; + + theTable[6].theKey = GCS_OSGB_1936; + theTable[6].theValue = "OGB-M"; + + theTable[7].theKey = GCS_WGS_72; + theTable[7].theValue = "WGD"; + + theTable[8].theKey = GCS_WGS_84; + theTable[8].theValue = "WGE"; + + theTable[9].theKey = GCS_Tokyo; + theTable[9].theValue = "TOY-M"; + + theTable[10].theKey = DatumE_WGS84; + theTable[10].theValue = "WGE"; + + theTable[11].theKey = Datum_Adindan; + theTable[11].theValue = "ADI-M"; + + theTable[12].theKey = Datum_Arc_1950; + theTable[12].theValue = "ARF-M"; + + theTable[13].theKey = Datum_Arc_1960; + theTable[13].theValue = "ARS-M"; + + theTable[14].theKey = Datum_European_Datum_1950; + theTable[14].theValue = "EUR-M"; + + theTable[15].theKey = Datum_North_American_Datum_1927; + theTable[15].theValue = "NAS-C"; + + theTable[16].theKey = Datum_North_American_Datum_1983; + theTable[16].theValue = "NAR-C"; + + theTable[17].theKey = Datum_OSGB_1936; + theTable[17].theValue = "OGB-M"; + + theTable[18].theKey = Datum_Tokyo; + theTable[18].theValue = "TOY-M"; + + theTable[19].theKey = Datum_WGS72; + theTable[19].theValue = "WGD"; + + theTable[20].theKey = Datum_WGS84; + theTable[20].theValue = "WGE"; + + theTable[21].theKey = Datum_NAD83_HARN; + theTable[21].theValue = "NAR"; + + theTable[22].theKey = GCS_NAD83_HARN; + theTable[22].theValue = "NAR"; + + //--- + // Note: This code implies a Clark 1866 ellipse with no datum. + // NAS-C used as work around for poor tag setting out of Erdas Imagine. + //--- + theTable[23].theKey = GCS_Clark_1866; + theTable[23].theValue = "NAS-C"; +} + +ossimGeoTiffDatumLut::~ossimGeoTiffDatumLut() +{ +} + +ossimKeyword ossimGeoTiffDatumLut::getKeyword() const +{ + return ossimKeyword("geotiff_datum_code", ""); +} diff --git a/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimGeoTiffDatumLut.h b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimGeoTiffDatumLut.h new file mode 100644 index 0000000000..fe5b1973b5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimGeoTiffDatumLut.h @@ -0,0 +1,74 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class declaration for GeoTiffDatumLut. Used to map a +// geotiff coordinate transformation code to an ossim projection. +//******************************************************************* +// $Id: ossimGeoTiffDatumLut.h,v 1.5 2005/01/21 18:55:19 dburken Exp $ + +#ifndef ossimGeoTiffDatumLut_HEADER +#define ossimGeoTiffDatumLut_HEADER + +#include "ossimLookUpTable.h" +#include "base/common/ossimKeywordNames.h" + +class OSSIMDLLEXPORT ossimGeoTiffDatumLut : public ossimLookUpTable +{ +public: + + enum + { + //--- + // Datum codes cut from geotiff specification section 6.3.2.1. + //--- + GCS_Adindan = 4201, + GCS_Arc_1950 = 4209, + GCS_Arc_1960 = 4210, + GCS_ED50 = 4230, + GCS_NAD27 = 4267, + GCS_NAD83 = 4269, + GCS_OSGB_1936 = 4277, + GCS_WGS_72 = 4322, + GCS_WGS_84 = 4326, + GCS_Tokyo = 4301, + GCS_NAD83_HARN = 4152, + + //--- + // Datum codes cut from geotiff specification section 6.3.2.1. + // NOTE: These codes imply an ellipsoid only! + //--- + GCS_Clark_1866 = 4008, + + //--- + // Datum codes cut from geotiff specification section 6.3.2.2. + //--- + DatumE_WGS84 = 6030, + Datum_Adindan = 6201, + Datum_Arc_1950 = 6209, + Datum_Arc_1960 = 6210, + Datum_European_Datum_1950 = 6230, + Datum_North_American_Datum_1927 = 6267, + Datum_North_American_Datum_1983 = 6269, + Datum_OSGB_1936 = 6277, + Datum_Tokyo = 6301, + Datum_WGS72 = 6322, + Datum_WGS84 = 6326, + Datum_NAD83_HARN = 6152 + }; + + ossimGeoTiffDatumLut(); + + virtual ~ossimGeoTiffDatumLut(); + + virtual ossimKeyword getKeyword() const; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimImageTypeLut.cpp b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimImageTypeLut.cpp new file mode 100644 index 0000000000..9010890f5d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimImageTypeLut.cpp @@ -0,0 +1,68 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// +// Description: +// +// Contains class definition for ImageTypeLUT. Currently has mapping of +// ouput image writes from enumeration to string and string to +// enumeration. +// +//******************************************************************* +// $Id: ossimImageTypeLut.cpp,v 1.3 2002/03/04 12:32:29 dburken Exp $ + +#include "ossimImageTypeLut.h" + +//*** +// Pixel type keyword to use for getState/saveState methods. +//*** +const ossimKeyword ossimImageTypeLut::IMAGE_TYPE_KW("image_type", + "Image type.\n\ +Valid types are: ccf, tiff, tiled_tiff, jpeg, and general_raster."); + +static const int TABLE_SIZE = 8; + +//******************************************************************* +// Public Constructor: +//******************************************************************* +ossimImageTypeLut::ossimImageTypeLut() + : + ossimLookUpTable(TABLE_SIZE) +{ + //*** + // Complete initialization of data member "theImageTypeTable". + // Note: Output type enumerations defined in constants.h file. + //*** + theTable[0].theKey = OSSIM_TIFF_STRIP; + theTable[0].theValue = "tiff_strip"; + theTable[1].theKey = OSSIM_TIFF_STRIP_BAND_SEPARATE; + theTable[1].theValue = "tiff_strip_band_separate"; + theTable[2].theKey = OSSIM_TIFF_TILED; + theTable[2].theValue = "tiff_tiled"; + theTable[3].theKey = OSSIM_TIFF_TILED_BAND_SEPARATE; + theTable[3].theValue = "tiff_tiled_band_separate"; + theTable[4].theKey = OSSIM_GENERAL_RASTER_BIP; + theTable[4].theValue = "general_raster_bip"; + theTable[5].theKey = OSSIM_GENERAL_RASTER_BIL; + theTable[5].theValue = "general_raster_bil"; + theTable[6].theKey = OSSIM_GENERAL_RASTER_BSQ; + theTable[6].theValue = "general_raster_bsq"; + theTable[7].theKey = OSSIM_JPEG; + theTable[7].theValue = "jpeg"; +} diff --git a/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimImageTypeLut.h b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimImageTypeLut.h new file mode 100644 index 0000000000..77fe3eeb54 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimImageTypeLut.h @@ -0,0 +1,47 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// +// Description: +// +// Contains class declaration for ImageTypeLut. Currently has mapping of +// ouput image writes from enumeration to string and string to +// enumeration. +// +//******************************************************************* +// $Id: ossimImageTypeLut.h,v 1.3 2002/11/25 19:16:28 gpotts Exp $ + +#ifndef ImageTypeLUT_HEADER +#define ImageTypeLUT_HEADER + +#include "ossimLookUpTable.h" + +class OSSIMDLLEXPORT ossimImageTypeLut : public ossimLookUpTable +{ +public: + + ossimImageTypeLut(); + + virtual ~ossimImageTypeLut(){} + + virtual ossimKeyword getKeyword() const { return IMAGE_TYPE_KW; } + + static const ossimKeyword IMAGE_TYPE_KW; +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimInterleaveTypeLut.cpp b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimInterleaveTypeLut.cpp new file mode 100644 index 0000000000..8ae20dfc16 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimInterleaveTypeLut.cpp @@ -0,0 +1,50 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// +// Description: +// +// Contains class definition for InterleaveTypeLUT. +//******************************************************************* +// $Id: ossimInterleaveTypeLut.cpp,v 1.1.1.1 2001/02/05 20:13:25 dburken Exp $ + +#include "ossimInterleaveTypeLut.h" + +static const int TABLE_SIZE = 4; + +//******************************************************************* +// Public Constructor: +//******************************************************************* +ossimInterleaveTypeLut::ossimInterleaveTypeLut() + : + ossimLookUpTable(TABLE_SIZE) +{ + //*** + // Complete initialization of data member "theTable". + // Note: Interleave types defined in constants.h file. + //*** + theTable[0].theKey = OSSIM_BIL; + theTable[0].theValue = "bil"; + theTable[1].theKey = OSSIM_BIP; + theTable[1].theValue = "bip"; + theTable[2].theKey = OSSIM_BSQ; + theTable[2].theValue = "bsq"; + theTable[3].theKey = OSSIM_BSQ_MULTI_FILE; + theTable[3].theValue = "bsq_multi_file"; +} diff --git a/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimInterleaveTypeLut.h b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimInterleaveTypeLut.h new file mode 100644 index 0000000000..70ffd5d0fe --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimInterleaveTypeLut.h @@ -0,0 +1,45 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// +// Description: +// +// Contains class declaration for InterleaveTypeLUT. +//******************************************************************* +// $Id: ossimInterleaveTypeLut.h,v 1.2 2002/11/25 19:16:28 gpotts Exp $ + +#ifndef ossimInterleaveTypeLUT_HEADER +#define ossimInterleaveTypeLUT_HEADER + +#include "ossimLookUpTable.h" +#include "base/common/ossimKeywordNames.h" + +class OSSIMDLLEXPORT ossimInterleaveTypeLut : public ossimLookUpTable +{ +public: + + ossimInterleaveTypeLut(); + + virtual ~ossimInterleaveTypeLut(){} + + virtual ossimKeyword getKeyword() const + { return ossimKeyword(ossimKeywordNames::INTERLEAVE_TYPE_KW, ""); } +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimLookUpTable.cpp b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimLookUpTable.cpp new file mode 100644 index 0000000000..f403d2d697 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimLookUpTable.cpp @@ -0,0 +1,147 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// +// Description: +// +// Contains class declaration for +//******************************************************************* +// $Id: ossimLookUpTable.cpp,v 1.9 2004/06/04 14:28:46 dburken Exp $ + +#include <iostream> +using namespace std; + +#include "ossimLookUpTable.h" +#include "base/data_types/ossimKeywordlist.h" + +//******************************************************************* +// Protected Constructor: +//******************************************************************* +ossimLookUpTable::ossimLookUpTable(ossim_int32 table_size) + : + theTable(table_size) +{} + +ossimLookUpTable::~ossimLookUpTable() +{ +} + +//******************************************************************* +// Public Method: +//******************************************************************* +ossimString ossimLookUpTable::getEntryString(ossim_int32 entry_number) const +{ + for (ossim_uint32 i=0; i<theTable.size(); ++i) + { + if (theTable[i].theKey == entry_number) + { + return theTable[i].theValue; + } + } + + return ossimString(); // Entry number not found. +} + +//******************************************************************* +// Public Method: +//******************************************************************* +ossimString ossimLookUpTable::getTableIndexString(ossim_uint32 table_index) const +{ + if (table_index < theTable.size()) + { + return theTable[table_index].theValue; + } + + return ossimString(); // Index out of range. +} + +ossimString ossimLookUpTable::operator[](ossim_int32 entry_number) const +{ + return getEntryString(entry_number); +} + +//******************************************************************* +// Public Method: +//******************************************************************* +ossimString ossimLookUpTable::getEntryString(const ossimKeywordlist& kwl, + const char* prefix) const +{ + ossimString s = kwl.find(prefix, getKeyword()); + return s; +} + +//******************************************************************* +// Public Method: +//******************************************************************* +ossim_int32 ossimLookUpTable::getEntryNumber(const char* entry_string, + bool case_insensitive) const +{ + ossimString s1 = entry_string; + s1 = s1.trim(); + for (ossim_uint32 i=0; i<theTable.size(); i++) + { + ossimString s2 = theTable[i].theValue; + + if (case_insensitive == true) + { + s1.downcase(); + s2.downcase(); + } + + if (s1 == s2) + { + return theTable[i].theKey; + } + } + + return ossimLookUpTable::NOT_FOUND; // Entry number not found. +} + +//******************************************************************* +// Public Method: +//******************************************************************* +ossim_int32 ossimLookUpTable::getEntryNumber(const ossimKeywordlist& kwl, + const char* prefix, + bool case_insensitive) const +{ + const char* lookup = kwl.find(prefix, getKeyword()); + + if (lookup) + { + return getEntryNumber(lookup, case_insensitive); + } + + return ossimLookUpTable::NOT_FOUND; // Entry number not found. +} + +ossim_uint32 ossimLookUpTable::getTableSize() const +{ + return theTable.size(); +} + +void ossimLookUpTable::dumpValues(std::ostream& out)const +{ + ossim_uint32 tableSize = getTableSize(); + ossim_uint32 i = 0; + + for(i = 0; i < tableSize; ++i) + { + out << theTable[0].theValue << std::endl; + } +} diff --git a/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimLookUpTable.h b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimLookUpTable.h new file mode 100644 index 0000000000..6e63c97dcf --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimLookUpTable.h @@ -0,0 +1,116 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class declaration for LookUpTable. +//******************************************************************* +// $Id: ossimLookUpTable.h,v 1.12 2005/05/13 18:57:48 dburken Exp $ + +#ifndef ossimLookUpTable_HEADER +#define ossimLookUpTable_HEADER + +#include <vector> + +#include "base/common/ossimConstants.h" +#include "base/data_types/ossimString.h" +#include "base/data_types/ossimKeyword.h" + +class OSSIMDLLEXPORT ossimKeywordlist; + +//******************************************************************* +// CLASS: LookUpTable +//******************************************************************* +class OSSIMDLLEXPORT ossimLookUpTable +{ +public: + + enum + { + NOT_FOUND = -1 + }; + + virtual ~ossimLookUpTable(); + + /*! + * @return + * Returns the entry string associated with the entry number (key) passed + * in. Returns empty string if entry number is not in the list. + */ + virtual ossimString getEntryString(ossim_int32 entry_number) const; + + /*! + * @param table_index Index into the table + * Note: This is not the key mapped to the but the index into the table. + * @return + * Returns the entry string associated with the table index passed in. + * Returns empty string if index is out of range. + */ + virtual ossimString getTableIndexString(ossim_uint32 table_index) const; + + /*! + * Returns the entry string associated with the entry number passed in. + * Returns empty string if entry number is not in the list. + */ + virtual ossimString operator[](ossim_int32 entry_number) const; + + /*! + * Returns the entry string associated with lookup table keyword entry + * in the Keywordlist passed in. + * Returns empty string if keyword entry is not in the Keywordlist. + */ + virtual ossimString getEntryString(const ossimKeywordlist& kwl, + const char* prefix=0) const; + + /*! + * Returns the entry number associated with the entry string passed in. + * Returns NOT_FOUND(-1) if entry string is not in the list. + * If case_insensitive == true(default), the test is case insensitive; + * else, the test will be case sensitive. + */ + virtual ossim_int32 getEntryNumber(const char* entry_string, + bool case_insensitive = true) const; + + /*! + * Returns the entry number associated with the lookup table keyword + * entry in the Keywordlist passed in. Returns NOT_FOUND(-1) if no + * matching entry. + * If case_insensitive == true(default), the test is case insensitive; + * else, the test will be case sensitive. + */ + virtual ossim_int32 getEntryNumber(const ossimKeywordlist& kwl, + const char* prefix=0, + bool case_insensitive = true) const; + + /*! + * Returns keyword for lookups from a Keywordlist. + */ + virtual ossimKeyword getKeyword() const=0; + + virtual ossim_uint32 getTableSize() const; + + void dumpValues(std::ostream& out)const; +protected: + + ossimLookUpTable(ossim_int32 table_size); + + class ossimKeyValueMap + { + public: + ossim_int32 theKey; + ossimString theValue; + }; + + std::vector<ossimKeyValueMap> theTable; + +private: + ossimLookUpTable(){} // disallow... +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimScalarTypeLut.cpp b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimScalarTypeLut.cpp new file mode 100644 index 0000000000..3a76e0d4da --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimScalarTypeLut.cpp @@ -0,0 +1,126 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class definition for ossimScalarTypeLUT. +// +//******************************************************************* +// $Id: ossimScalarTypeLut.cpp,v 1.6 2005/05/09 12:30:30 dburken Exp $ + +#include <base/misc/lookup_tables/ossimScalarTypeLut.h> +#include <base/data_types/ossimString.h> + +ossimScalarTypeLut* ossimScalarTypeLut::theInstance = NULL; + +static const int TABLE_SIZE = 21; + +ossimScalarTypeLut* ossimScalarTypeLut::instance() +{ + if (!theInstance) + { + theInstance = new ossimScalarTypeLut; + } + return theInstance; +} + +ossimScalarTypeLut::ossimScalarTypeLut() + : + ossimLookUpTable(TABLE_SIZE) +{ + //--- + // Complete initialization of data member "theTable". + // Note: Scalar types defined in constants.h file. + //--- + theTable[0].theKey = OSSIM_SCALAR_UNKNOWN; + theTable[0].theValue = "unknown"; + + theTable[1].theKey = OSSIM_UINT8; + theTable[1].theValue = "ossim_uint8"; + + theTable[2].theKey = OSSIM_SINT8; + theTable[2].theValue = "ossim_sint8"; + + theTable[3].theKey = OSSIM_UINT16; + theTable[3].theValue = "ossim_uint16"; + + theTable[4].theKey = OSSIM_SINT16; + theTable[4].theValue = "ossim_sint16"; + + theTable[5].theKey = OSSIM_UINT32; + theTable[5].theValue = "ossim_uint32"; + + theTable[6].theKey = OSSIM_SINT32; + theTable[6].theValue = "ossim_sint32"; + + theTable[7].theKey = OSSIM_FLOAT32; + theTable[7].theValue = "ossim_float32"; + + theTable[8].theKey = OSSIM_FLOAT64; + theTable[8].theValue = "ossim_float64"; + + theTable[9].theKey = OSSIM_CINT16; + theTable[9].theValue = "ossim_cint16"; + + theTable[10].theKey = OSSIM_CINT32; + theTable[10].theValue = "ossim_cint32"; + + theTable[11].theKey = OSSIM_CFLOAT32; + theTable[11].theValue = "ossim_cfloat32"; + + theTable[12].theKey = OSSIM_CFLOAT64; + theTable[12].theValue = "ossim_cfloat64"; + + theTable[13].theKey = OSSIM_UCHAR; + theTable[13].theValue = "uchar"; + + theTable[14].theKey = OSSIM_USHORT16; + theTable[14].theValue = "ushort16"; + + theTable[15].theKey = OSSIM_SSHORT16; + theTable[15].theValue = "sshort16"; + + theTable[16].theKey = OSSIM_USHORT11; + theTable[16].theValue = "ushort11"; + + theTable[17].theKey = OSSIM_FLOAT; + theTable[17].theValue = "float"; + + theTable[18].theKey = OSSIM_NORMALIZED_FLOAT; + theTable[18].theValue = "normalized_float"; + + theTable[19].theKey = OSSIM_NORMALIZED_DOUBLE; + theTable[19].theValue = "normalized_double"; + + theTable[20].theKey = OSSIM_DOUBLE; + theTable[20].theValue = "double"; +} + +ossimScalarTypeLut::~ossimScalarTypeLut() +{ + theInstance = NULL; +} + +ossimScalarType +ossimScalarTypeLut::getScalarTypeFromString(const ossimString& s) const +{ + int scalar_type = getEntryNumber(s.c_str()); + + if (scalar_type == -1) + { + return OSSIM_SCALAR_UNKNOWN; + } + + return static_cast<ossimScalarType>(scalar_type); +} + +ossimKeyword ossimScalarTypeLut::getKeyword() const +{ + return ossimKeyword((ossimKeywordNames::SCALAR_TYPE_KW), ""); +} diff --git a/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimScalarTypeLut.h b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimScalarTypeLut.h new file mode 100644 index 0000000000..3644958118 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimScalarTypeLut.h @@ -0,0 +1,53 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class declaration for ossimScalarTypeLut. +// +//******************************************************************* +// $Id: ossimScalarTypeLut.h,v 1.4 2005/05/09 12:30:30 dburken Exp $ + +#ifndef ossimScalarTypeLut_HEADER +#define ossimScalarTypeLut_HEADER + +#include <base/misc/lookup_tables/ossimLookUpTable.h> +#include <base/common/ossimKeywordNames.h> + +/** + * Used to convert from scalar type enumeration to strings and vice versa. + * See ossimConstants.h for a complete list of enumerations. This class is + * a singleton, only one of them so all callers must go through the + * instance method like: + * ossimScalarTypeLut::instance()->getEntryString(scalar); + */ +class OSSIMDLLEXPORT ossimScalarTypeLut : public ossimLookUpTable +{ +public: + + /** + * Returns the static instance of an ossimScalarTypeLut object. + */ + static ossimScalarTypeLut* instance(); + + virtual ~ossimScalarTypeLut(); + + ossimScalarType getScalarTypeFromString(const ossimString& s) const; + + virtual ossimKeyword getKeyword() const; + +protected: + ossimScalarTypeLut(); + +private: + + static ossimScalarTypeLut* theInstance; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimUnitTypeLut.cpp b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimUnitTypeLut.cpp new file mode 100644 index 0000000000..c3e5307d3e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimUnitTypeLut.cpp @@ -0,0 +1,54 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//******************************************************************* +// $Id: ossimUnitTypeLut.cpp,v 1.5 2005/06/15 14:15:22 gpotts Exp $ +#include "ossimUnitTypeLut.h" +static const int TABLE_SIZE = 13; +ossimUnitTypeLut::ossimUnitTypeLut() + :ossimLookUpTable(TABLE_SIZE) +{ + theTable[0].theKey = OSSIM_UNIT_UNKNOWN; + theTable[0].theValue = "unknown"; + theTable[1].theKey = OSSIM_METERS; + theTable[1].theValue = "meters"; + theTable[2].theKey = OSSIM_FEET; + theTable[2].theValue = "feet"; + theTable[3].theKey = OSSIM_US_SURVEY_FEET; + theTable[3].theValue = "us_survey_feet"; + theTable[4].theKey = OSSIM_DEGREES; + theTable[4].theValue = "degrees"; + theTable[5].theKey = OSSIM_RADIANS; + theTable[5].theValue = "radians"; + theTable[6].theKey = OSSIM_NAUTICAL_MILES; + theTable[6].theValue = "nautical_miles"; + theTable[7].theKey = OSSIM_SECONDS; + theTable[7].theValue = "seconds"; + theTable[8].theKey = OSSIM_MINUTES; + theTable[8].theValue = "minutes"; + theTable[9].theKey = OSSIM_PIXEL; + theTable[9].theValue = "pixel"; + theTable[10].theKey = OSSIM_MILES; + theTable[10].theValue = "miles"; + theTable[11].theKey = OSSIM_MILLIMETERS; + theTable[11].theValue = "millimeters"; + theTable[12].theKey = OSSIM_MICRONS; + theTable[12].theValue = "microns"; +} diff --git a/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimUnitTypeLut.h b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimUnitTypeLut.h new file mode 100644 index 0000000000..5f87dde43b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/lookup_tables/ossimUnitTypeLut.h @@ -0,0 +1,80 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//******************************************************************* +// $Id: ossimUnitTypeLut.h,v 1.4 2003/05/13 11:31:03 dburken Exp $ +#ifndef ossimUnitTypeLut_HEADER +#define ossimUnitTypeLut_HEADER + +#include "ossimLookUpTable.h" +#include "base/common/ossimKeywordNames.h" + +class OSSIMDLLEXPORT ossimUnitTypeLut : public ossimLookUpTable +{ +public: + + ossimUnitTypeLut(); + + virtual ~ossimUnitTypeLut(){} + + /*! + * Returns the entry number associated with the entry string passed in. + * Returns OSSIM_UNIT_UNKNOWN if entry string is not in the list. + * If case_insensitive == true(default), the test is case insensitive; + * else, the test will be case sensitive. + */ + virtual ossim_int32 getEntryNumber(const char* entry_string, + bool case_insensitive = true) const + { + ossim_int32 result + = ossimLookUpTable::getEntryNumber(entry_string, case_insensitive); + if(result < 0) + { + return (ossim_int32)OSSIM_UNIT_UNKNOWN; + } + + return result; + } + + /*! + * Returns the entry number associated with the lookup table keyword + * entry in the Keywordlist passed in. Returns NOT_FOUND(-1) if no + * matching entry. + * If case_insensitive == true(default), the test is case insensitive; + * else, the test will be case sensitive. + */ + virtual ossim_int32 getEntryNumber(const ossimKeywordlist& kwl, + const char* prefix=NULL, + bool case_insensitive = true) const + { + ossim_int32 result = + ossimLookUpTable::getEntryNumber(kwl, prefix, case_insensitive); + if(result < 0) + { + return (ossim_int32)OSSIM_UNIT_UNKNOWN; + } + return result; + } + + virtual ossimKeyword getKeyword() const + { return ossimKeyword(ossimKeywordNames::UNITS_KW, ""); } +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossim2dLinearRegression.cpp b/Utilities/OSSIM/ossim_core/base/misc/ossim2dLinearRegression.cpp new file mode 100644 index 0000000000..d688b80b9b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossim2dLinearRegression.cpp @@ -0,0 +1,73 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossim2dLinearRegression.cpp,v 1.3 2005/12/07 20:24:17 gpotts Exp $ +#include "ossim2dLinearRegression.h" + +ossim2dLinearRegression::ossim2dLinearRegression() +{ + clear(); +} + +void ossim2dLinearRegression::solve() +{ + +// theSumX = 0.0; +// theSumXX = 0.0; +// theSumY = 0.0; +// theSumYY = 0.0; +// theIntercept = 0.0; +// theSlope = 0.0; +// theSumXY = 0.0; +// ossim_uint32 idx = 0; +// for(idx = 0; idx < thePoints.size(); ++idx) +// { +// theSumX += thePoints[idx].x; +// theSumY += thePoints[idx].y; +// theSumXX += thePoints[idx].x*thePoints[idx].x; +// theSumYY += thePoints[idx].y*thePoints[idx].y; +// theSumXY += thePoints[idx].x*thePoints[idx].y; + +// } + + double numberOfPoints = (double)theNumberOfPoints; + + if(numberOfPoints < 1) + { + theSlope = 0.0; + theIntercept = 0.0; + return; + } + double Sxx = theSumXX - ((theSumX*theSumX)/numberOfPoints); + double Sxy = theSumXY - ((theSumX*theSumY)/numberOfPoints); + + if(fabs(Sxx) < FLT_EPSILON) + { + theSlope = 0.0; + theIntercept = 0.0; + return; + } + + theSlope = Sxy/Sxx; + theIntercept = (theSumY - theSlope*theSumX)/numberOfPoints; + + theSolvedFlag = true; +} diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossim2dLinearRegression.h b/Utilities/OSSIM/ossim_core/base/misc/ossim2dLinearRegression.h new file mode 100644 index 0000000000..e6cb2dd878 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossim2dLinearRegression.h @@ -0,0 +1,89 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossim2dLinearRegression.h,v 1.5 2005/12/07 20:24:17 gpotts Exp $ +#ifndef ossim2dLinearRegression_HEADER +#define ossim2dLinearRegression_HEADER +#include "base/data_types/ossimDpt.h" +#include <vector> +#include <iostream> + +class ossim2dLinearRegression +{ +public: + friend std::ostream& operator <<(std::ostream& out, const ossim2dLinearRegression& data) + { + out << "y = " << data.theSlope << "*x + " << data.theIntercept; + + return out; + } + ossim2dLinearRegression(); + void getEquation(double& slope, + double& intercept) + { + slope = theSlope; + intercept = theIntercept; + } + void addPoint(const ossimDpt& pt) + { +// thePoints.push_back(pt); + ++theNumberOfPoints; + theSumX += pt.x; + theSumY += pt.y; + theSumXX += pt.x*pt.x; + theSumYY += pt.y*pt.y; + theSumXY += pt.x*pt.y; + theSolvedFlag = false; + } + void clear() + { +// thePoints.clear(); + theNumberOfPoints = 0; + theSumX = 0.0; + theSumXX = 0.0; + theSumY = 0.0; + theSumYY = 0.0; + theIntercept = 0.0; + theSlope = 0.0; + theSumXY = 0.0; + theSolvedFlag = false; + } + void solve(); + ossim_uint32 getNumberOfPoints()const + { + return theNumberOfPoints; +// return thePoints.size(); + } +protected: +// std::vector<ossimDpt> thePoints; + ossim_uint32 theNumberOfPoints; + double theSumX; + double theSumY; + double theSumXX; + double theSumYY; + double theSumXY; + + double theIntercept; + double theSlope; + bool theSolvedFlag; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossim2dTo2dTransform.cpp b/Utilities/OSSIM/ossim_core/base/misc/ossim2dTo2dTransform.cpp new file mode 100644 index 0000000000..a87350486a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossim2dTo2dTransform.cpp @@ -0,0 +1,242 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossim2dTo2dTransform.cpp,v 1.16 2005/05/17 19:05:14 gpotts Exp $ +#include <base/misc/ossim2dTo2dTransform.h> +#include <sstream> + +RTTI_DEF1(ossim2dTo2dTransform, "ossim2dTo2dTransform", ossimObject); + +#include <base/common/ossimKeywordNames.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/context/ossimNotifyContext.h> + +//*** +// Define Trace flags for use within this file: +//*** +#include <base/common/ossimTrace.h> +static ossimTrace traceExec ("ossim2dTo2dTransform:exec"); +static ossimTrace traceDebug ("ossim2dTo2dTransform:debug"); + +static const double DEFAULT_THRESHOLD = 1000.0*DBL_EPSILON; +static const int DEFAULT_MAX_ITERATIONS = 10; + +//***************************************************************************** +// CONSTRUCTOR: +//***************************************************************************** +ossim2dTo2dTransform::ossim2dTo2dTransform() + : + theConvergenceThreshold (DEFAULT_THRESHOLD), + theMaxIterations (DEFAULT_MAX_ITERATIONS), + theDxDy(1.0, 1.0) +{ +} + +//***************************************************************************** +// METHOD: +//***************************************************************************** +void ossim2dTo2dTransform::inverse(const ossimDpt& input, + ossimDpt& output) const +{ + static const char MODULE[] = "ossim2dTo2dTransform::inverse"; + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG: " << MODULE << ", entering...\n"; + + //*** + // Begin with guess. Forward transform is defined as trasforming left to + // right. We are therefore solving for left: + //*** + ossimDpt left = getOrigin(); + ossimDpt left_dx; + ossimDpt left_dy; + ossimDpt right; + ossimDpt right_dx; + ossimDpt right_dy; + ossimDpt dr_dx; + ossimDpt dr_dy; + ossimDpt r_diff; + ossimDpt l_diff; + double inverse_norm; + int iters=0; + //*** + // Begin iterations: + //*** + do + { + //*** + // establish perturbed image points about the guessed point: + //*** + left_dx.x = left.x + theDxDy.x; + left_dx.y = left.y; + left_dy.x = left.x; + left_dy.y = left.y + theDxDy.y; + + //*** + // Compute numerical partials at current guessed point: + //*** + forward(left, right); + forward(left_dx, right_dx); + forward(left_dy, right_dy); + + dr_dx.x = (right_dx.x - right.x)/theDxDy.x; //e + dr_dx.y = (right_dx.y - right.y)/theDxDy.y; //g + dr_dy.x = (right_dy.x - right.x)/theDxDy.x; //f + dr_dy.y = (right_dy.y - right.y)/theDxDy.y; //h + + //*** + // Test for convergence: + //*** + r_diff = input - right; + + //*** + // Compute linearized estimate of image point given gp delta: + //*** + inverse_norm = dr_dy.x*dr_dx.y - dr_dx.x*dr_dy.y; // fg-eh + + if (inverse_norm != 0) + { + l_diff.x = (-dr_dy.y*r_diff.x + dr_dy.x*r_diff.y)/inverse_norm; + l_diff.y = ( dr_dx.y*r_diff.x - dr_dx.x*r_diff.y)/inverse_norm; + + left += l_diff; + } + else + { + l_diff.x = 0; + l_diff.y = 0; + } + + iters++; + + } while (((fabs(l_diff.x) > theConvergenceThreshold) || + (fabs(l_diff.y) > theConvergenceThreshold)) && + (iters < theMaxIterations)); + + //*** + // Note that this error mesage appears only if max count was reached while + // iterating. A linear (no iteration) solution would finish with iters = + // MAX_NUM_ITERATIONS + 1: + //*** + if (iters == theMaxIterations) + { + ossimNotify(ossimNotifyLevel_WARN) << "WARNING: " << MODULE << ", exceeded max number of iterations computing inverse " + << "transform for point: " << input << "\n"; + } + + output = left; + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG: " << MODULE << ", returning...\n"; + return; + +} + +//***************************************************************************** +// METHOD: +//***************************************************************************** +bool ossim2dTo2dTransform::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + kwl.add(prefix, + ossimKeywordNames::CONVERGENCE_THRESHOLD_KW, + theConvergenceThreshold, + true); + kwl.add(prefix, + ossimKeywordNames::MAX_ITERATIONS_KW, + theMaxIterations, + true); + kwl.add(prefix, + "dxdy", + ossimString::toString(theDxDy.x) + " " + + ossimString::toString(theDxDy.y), + true); + + return ossimObject::saveState(kwl, prefix); +} + +//***************************************************************************** +// METHOD: +//***************************************************************************** +bool ossim2dTo2dTransform::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + bool result = true; + + const char* buf; + + buf= kwl.find(prefix, ossimKeywordNames::CONVERGENCE_THRESHOLD_KW); + + if (buf) + { + theConvergenceThreshold = atof(buf); + } + else + { + theConvergenceThreshold = .00000000000002; + } + + buf= kwl.find(prefix, ossimKeywordNames::MAX_ITERATIONS_KW); + if(buf) + { + theMaxIterations = atoi(buf); + } + else + { + theMaxIterations = 10; + } + const char* dxdy = kwl.find(prefix, "dxdy"); + if(dxdy) + { + std::istringstream in(dxdy); + in>>theDxDy.x >> theDxDy.y; + } + if(result) + { + ossimObject::loadState(kwl, prefix); + } + + return result; +} + +void ossim2dTo2dTransform::forward(ossimDpt& modify_this) const +{ + ossimDpt output; + forward(modify_this, output); + modify_this = output; +} + +void ossim2dTo2dTransform::inverse(ossimDpt& modify_this) const +{ + ossimDpt output; + inverse(modify_this, output); + modify_this = output; +} + +ossimDpt ossim2dTo2dTransform::getOrigin()const +{ + return ossimDpt(0,0); +} + +void ossim2dTo2dTransform::setConvergenceThreshold(const double& new_threshold) +{ + theConvergenceThreshold = new_threshold; +} + +void ossim2dTo2dTransform::setMaxIterations(int new_max_iters) +{ + theMaxIterations = new_max_iters; +} + +void ossim2dTo2dTransform::setDxDy(const ossimDpt& dxdy) +{ + theDxDy.x = dxdy.x; + theDxDy.y = dxdy.y; +} + +void ossim2dTo2dTransform::operator=(const ossim2dTo2dTransform& /* rhs */ ) +{ +} diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossim2dTo2dTransform.h b/Utilities/OSSIM/ossim_core/base/misc/ossim2dTo2dTransform.h new file mode 100644 index 0000000000..a96401daee --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossim2dTo2dTransform.h @@ -0,0 +1,62 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossim2dTo2dTransform.h,v 1.8 2004/08/17 21:09:57 dburken Exp $ +#ifndef ossim2dTo2dTransform_HEADER +#define ossim2dTo2dTransform_HEADER +#include "base/common/ossimObject.h" +#include "base/data_types/ossimDpt.h" + +class OSSIMDLLEXPORT ossim2dTo2dTransform : public ossimObject +{ +public: + virtual void forward(const ossimDpt& input, + ossimDpt& output) const=0; + + virtual void forward(ossimDpt& modify_this) const; + + virtual void inverse(const ossimDpt& input, + ossimDpt& output) const; + + virtual void inverse(ossimDpt& modify_this) const; + + /*! + * Used by the inverse iterator. This will give it a good initial value + * that is within the input transforms + */ + virtual ossimDpt getOrigin() const; + + virtual std::ostream& print(std::ostream& out) const = 0; + + bool saveState(ossimKeywordlist& kwl, + const char* prefix = 0)const; + + bool loadState(const ossimKeywordlist& kwl, + const char* prefix = 0); + + void setConvergenceThreshold(const double& new_threshold); + + void setMaxIterations(int new_max_iters); + + void setDxDy(const ossimDpt& dxdy); + +protected: + ossim2dTo2dTransform(); + void operator =(const ossim2dTo2dTransform& rhs); + + double theConvergenceThreshold; + int theMaxIterations; + + ossimDpt theDxDy; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimAdjustableParameterInfo.cpp b/Utilities/OSSIM/ossim_core/base/misc/ossimAdjustableParameterInfo.cpp new file mode 100644 index 0000000000..af098eab97 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimAdjustableParameterInfo.cpp @@ -0,0 +1,126 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimAdjustableParameterInfo.cpp,v 1.8 2004/01/09 18:32:00 gpotts Exp $ +#include <sstream> +#include <algorithm> +#include "ossimAdjustableParameterInfo.h" +#include "base/misc/lookup_tables/ossimUnitTypeLut.h" +#include "base/common/ossimKeywordNames.h" + +// static const char* PARAM_NAME_KW = "name"; +// static const char* PARAM_UNITS_KW = "units"; +static const char* PARAM_KW = "parameter"; +static const char* PARAM_SIGMA_KW = "sigma"; +static const char* PARAM_CENTER_KW = "center"; + +std::ostream& operator <<(std::ostream& out, const ossimAdjustableParameterInfo& data) +{ + out << "description: " << data.theDescription << std::endl + << "center: " << data.theCenter << std::endl + << "parameter: " << data.theParameter << std::endl + << "sigma: " << data.theSigma << std::endl + << "units: " << ossimUnitTypeLut().getEntryString(data.theUnit) << endl; + + return out; +} + + +ossimString ossimAdjustableParameterInfo::getUnitAsString()const +{ + return ossimUnitTypeLut().getEntryString((int)theUnit); +} + +void ossimAdjustableParameterInfo::setCenter(double center) +{ + theCenter = center; +} + +double ossimAdjustableParameterInfo::getCenter()const +{ + return theCenter; +} + +double ossimAdjustableParameterInfo::computeOffset()const +{ + return theCenter + theSigma*theParameter; +} + +bool ossimAdjustableParameterInfo::loadState(const ossimKeywordlist& kwl, + const ossimString& prefix) +{ + const char* param = kwl.find(prefix, PARAM_KW); + const char* sigma = kwl.find(prefix, PARAM_SIGMA_KW); + const char* center = kwl.find(prefix, PARAM_CENTER_KW); + const char* unit = kwl.find(prefix, ossimKeywordNames::UNITS_KW); + + theDescription = kwl.find(prefix, ossimKeywordNames::DESCRIPTION_KW); + + if(param) + { + theParameter = ossimString(param).toDouble(); + } + else + { + theParameter = 0.0; + } + if(unit) + { + theUnit = (ossimUnitType)(ossimUnitTypeLut().getEntryNumber(unit)); + } + else + { + theUnit = OSSIM_UNIT_UNKNOWN; + } + if(sigma) + { + theSigma = ossimString(sigma).toDouble(); + } + else + { + theSigma = 0.0; + } + if(center) + { + theCenter = ossimString(center).toDouble(); + } + else + { + theCenter = 0.0; + } + + return true; +} + +bool ossimAdjustableParameterInfo::saveState(ossimKeywordlist& kwl, + const ossimString& prefix)const +{ + kwl.add(prefix, + ossimKeywordNames::DESCRIPTION_KW, + theDescription, + true); + kwl.add(prefix, ossimKeywordNames::UNITS_KW, ossimUnitTypeLut().getEntryString(theUnit), true); + kwl.add(prefix, PARAM_KW, theParameter, true); + kwl.add(prefix, PARAM_SIGMA_KW, theSigma, true); + kwl.add(prefix, PARAM_CENTER_KW, theCenter, true); + + return true; +} diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimAdjustableParameterInfo.h b/Utilities/OSSIM/ossim_core/base/misc/ossimAdjustableParameterInfo.h new file mode 100644 index 0000000000..a3982587ba --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimAdjustableParameterInfo.h @@ -0,0 +1,97 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimAdjustableParameterInfo.h,v 1.6 2004/01/09 18:32:00 gpotts Exp $ +#ifndef ossimAdjustableParameterInfo_HEADER +#define ossimAdjustableParameterInfo_HEADER +#include <iostream> +#include "base/common/ossimConstants.h" +#include "base/data_types/ossimString.h" +#include "base/data_types/ossimKeywordlist.h" + +class ossimAdjustableParameterInfo +{ +public: + friend std::ostream& operator <<(std::ostream& out, const ossimAdjustableParameterInfo& data); + + ossimAdjustableParameterInfo() + : theParameter(0.0), + theSigma(0.0), + theCenter(0.0), + theUnit(OSSIM_UNIT_UNKNOWN), + theDescription("") + { + } + double getParameter()const + { + return theParameter; + } + void setParameter(double parameter) + { + theParameter = parameter; + } + double getSigma()const + { + return theSigma; + } + void setSigma(double sigma) + { + theSigma = sigma; + } + const ossimString& getDescription()const + { + return theDescription; + } + void setDescription(const ossimString& description) + { + theDescription = description; + } + ossimUnitType getUnit()const + { + return theUnit; + } + void setUnit(ossimUnitType unit) + { + theUnit = unit; + } + ossimString getUnitAsString()const; + + void setCenter(double center); + double getCenter()const; + + /*! + * will return theCenter + theSigma*theParameter + */ + double computeOffset()const; + + bool loadState(const ossimKeywordlist& kwl, + const ossimString& prefix=ossimString("")); + bool saveState(ossimKeywordlist& kwl, + const ossimString& prefix=ossimString(""))const; +protected: + double theParameter; + double theSigma; + double theCenter; + ossimUnitType theUnit; + ossimString theDescription; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimAdjustableParameterInterface.cpp b/Utilities/OSSIM/ossim_core/base/misc/ossimAdjustableParameterInterface.cpp new file mode 100644 index 0000000000..e683f248af --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimAdjustableParameterInterface.cpp @@ -0,0 +1,617 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimAdjustableParameterInterface.cpp,v 1.29 2005/12/09 17:02:51 gpotts Exp $ +#include <algorithm> +#include "ossimAdjustableParameterInterface.h" +#include "base/common/ossimKeywordNames.h" +#include "base/misc/lookup_tables/ossimUnitTypeLut.h" + +RTTI_DEF(ossimAdjustableParameterInterface, "ossimAdjustableParameterInterface"); + +static const char* NUMBER_OF_ADJUSTMENTS_KW = "number_of_adjustments"; +static const char* NUMBER_OF_ADJUSTMENTS_OLD_KW = "number_of_adjustements"; +static const char* CURRENT_ADJUSTMENT_OLD_KW = "current_adjustement"; +static const char* CURRENT_ADJUSTMENT_KW = "current_adjustment"; +static const char* ADJUSTMENT_PREFIX = "adjustment_"; + +ossimAdjustableParameterInterface::ossimAdjustableParameterInterface() +{ + theCurrentAdjustment = 0; +} + +void ossimAdjustableParameterInterface::newAdjustment(ossim_uint32 numberOfParameters) +{ + theAdjustmentList.push_back(ossimAdjustmentInfo()); + if(numberOfParameters > 0) + { + theAdjustmentList[theAdjustmentList.size()-1].setNumberOfAdjustableParameters(numberOfParameters); + theAdjustmentList[theAdjustmentList.size()-1].setDescription("Initial adjustment"); + } + + theCurrentAdjustment = theAdjustmentList.size() - 1; + +} + +void ossimAdjustableParameterInterface::setAdjustmentDescription(const ossimString& description) +{ + if(!theAdjustmentList.size()) + { + return; + } + theAdjustmentList[theCurrentAdjustment].setDescription(description); +} + +ossimString ossimAdjustableParameterInterface::getAdjustmentDescription()const +{ + if(theAdjustmentList.size()) + { + return theAdjustmentList[theCurrentAdjustment].getDescription(); + } + + return ""; +} + +void ossimAdjustableParameterInterface::setCurrentAdjustment(ossim_uint32 adjustmentIdx, bool notify) +{ + if(adjustmentIdx < theAdjustmentList.size()) + { + theCurrentAdjustment = adjustmentIdx; + if(notify) + { + adjustableParametersChanged(); + } + } +} + + +void ossimAdjustableParameterInterface::initAdjustableParameters() +{ +} + +void ossimAdjustableParameterInterface::resetAdjustableParameters(bool notify) +{ + if(!theAdjustmentList.size()) + { + return; + } + + ossim_uint32 saveCurrent = theCurrentAdjustment; + copyAdjustment(); + initAdjustableParameters(); + ossim_uint32 numberOfAdjustables = getNumberOfAdjustableParameters(); + ossim_uint32 idx = 0; + + for(idx = 0; idx < numberOfAdjustables; ++idx) + { + theAdjustmentList[saveCurrent].getParameterList()[idx].setParameter(theAdjustmentList[theAdjustmentList.size()-1].getParameterList()[idx].getParameter()); + } + + setCurrentAdjustment(saveCurrent); + + eraseAdjustment(theAdjustmentList.size()-1, false); + + if(notify) + { + adjustableParametersChanged(); + } +} + +void ossimAdjustableParameterInterface::copyAdjustment(ossim_uint32 idx, bool notify) +{ + if(!theAdjustmentList.size()) + { + return; + } + if((idx >=0)&&(idx < theAdjustmentList.size())) + { + theAdjustmentList.push_back(theAdjustmentList[idx]); + + if(idx == theCurrentAdjustment) + { + theCurrentAdjustment = theAdjustmentList.size() - 1; + } + if(notify) + { + adjustableParametersChanged(); + } + } + +} + +void ossimAdjustableParameterInterface::copyAdjustment(bool notify) +{ + copyAdjustment(theCurrentAdjustment, notify); +} + +void ossimAdjustableParameterInterface::keepAdjustment(ossim_uint32 idx, + bool createCopy) +{ + if(!theAdjustmentList.size()) + { + return; + } + if((idx >=0)&&(idx < theAdjustmentList.size())) + { + if(createCopy) + { + copyAdjustment(idx); + } + theAdjustmentList[theCurrentAdjustment].keep(); + } +} + +void ossimAdjustableParameterInterface::keepAdjustment(bool createCopy) +{ + keepAdjustment(theCurrentAdjustment, createCopy); +} + +void ossimAdjustableParameterInterface::removeAllAdjustments() +{ + theAdjustmentList.clear(); + theCurrentAdjustment = 0; +} + +ossim_uint32 ossimAdjustableParameterInterface::getNumberOfAdjustableParameters()const +{ + if(theAdjustmentList.size()) + { + return theAdjustmentList[theCurrentAdjustment].getNumberOfAdjustableParameters(); + } + + return 0; +} + +void ossimAdjustableParameterInterface::eraseAdjustment(bool notify) +{ + eraseAdjustment(theCurrentAdjustment, notify); +} + +void ossimAdjustableParameterInterface::eraseAdjustment(ossim_uint32 idx, bool notify) +{ + if(!theAdjustmentList.size()) + { + return; + } + + if(theCurrentAdjustment == idx) + { + theAdjustmentList.erase(theAdjustmentList.begin() + theCurrentAdjustment); + if(theCurrentAdjustment >= theAdjustmentList.size()) + { + if(theAdjustmentList.size() < 1) + { + theCurrentAdjustment = 0; + } + else + { + theCurrentAdjustment = theAdjustmentList.size() - 1; + } + + } + + if(notify) + { + adjustableParametersChanged(); + } + } + else if(idx < theAdjustmentList.size()) + { + theAdjustmentList.erase(theAdjustmentList.begin() + idx); + if(theAdjustmentList.size() < 1) + { + theCurrentAdjustment = 0; + } + else + { + if(theCurrentAdjustment > idx) + { + --theCurrentAdjustment; + if(notify) + { + adjustableParametersChanged(); + } + } + } + if(notify) + { + adjustableParametersChanged(); + } + } +} + +double ossimAdjustableParameterInterface::getAdjustableParameter(ossim_uint32 idx)const +{ + if(theAdjustmentList.size()) + { + if(idx < theAdjustmentList[theCurrentAdjustment].getNumberOfAdjustableParameters()) + { + return theAdjustmentList[theCurrentAdjustment].getParameterList()[idx].getParameter(); + } + } + + return 0.0; +} + +void ossimAdjustableParameterInterface::setAdjustableParameter(ossim_uint32 idx, double value, double sigma, bool notify) +{ + if(!theAdjustmentList.size()) + { + return; + } + if(idx < theAdjustmentList[theCurrentAdjustment].getNumberOfAdjustableParameters()) + { + theAdjustmentList[theCurrentAdjustment].getParameterList()[idx].setParameter(value); + theAdjustmentList[theCurrentAdjustment].getParameterList()[idx].setSigma(sigma); + if(notify) + { + adjustableParametersChanged(); + } + } + +} + +void ossimAdjustableParameterInterface::setAdjustableParameter(ossim_uint32 idx, double value, bool notify) +{ + if(!theAdjustmentList.size()) + { + return; + } + if(idx < theAdjustmentList[theCurrentAdjustment].getNumberOfAdjustableParameters()) + { + theAdjustmentList[theCurrentAdjustment].getParameterList()[idx].setParameter(value); + + if(notify) + { + adjustableParametersChanged(); + } + } +} + +double ossimAdjustableParameterInterface::getParameterSigma(ossim_uint32 idx)const +{ + if(theAdjustmentList.size()) + { + if(idx < theAdjustmentList[theCurrentAdjustment].getNumberOfAdjustableParameters()) + { + return theAdjustmentList[theCurrentAdjustment].getParameterList()[idx].getSigma(); + } + } + + return 0.0; +} + +void ossimAdjustableParameterInterface::setParameterSigma(ossim_uint32 idx, double value, bool notify) +{ + if(!theAdjustmentList.size()) + { + return; + } + if(idx < theAdjustmentList[theCurrentAdjustment].getNumberOfAdjustableParameters()) + { + theAdjustmentList[theCurrentAdjustment].getParameterList()[idx].setSigma(value); + if(notify) + { + adjustableParametersChanged(); + } + } +} + +ossimUnitType ossimAdjustableParameterInterface::getParameterUnit(ossim_uint32 idx)const +{ + if(theAdjustmentList.size()) + { + if(idx < theAdjustmentList[theCurrentAdjustment].getNumberOfAdjustableParameters()) + { + return theAdjustmentList[theCurrentAdjustment].getParameterList()[idx].getUnit(); + } + } + + return OSSIM_UNIT_UNKNOWN; +} + +void ossimAdjustableParameterInterface::setParameterUnit(ossim_uint32 idx, ossimUnitType unit) +{ + if(theAdjustmentList.size()) + { + if(idx < theAdjustmentList[theCurrentAdjustment].getNumberOfAdjustableParameters()) + { + theAdjustmentList[theCurrentAdjustment].getParameterList()[idx].setUnit(unit); + } + } +} + +void ossimAdjustableParameterInterface::setParameterUnit(ossim_uint32 idx, const ossimString& unit) +{ + if(theAdjustmentList.size()) + { + if(idx < theAdjustmentList[theCurrentAdjustment].getNumberOfAdjustableParameters()) + { + theAdjustmentList[theCurrentAdjustment].getParameterList()[idx].setUnit((ossimUnitType)ossimUnitTypeLut().getEntryNumber(unit)); + } + } +} + + +ossimString ossimAdjustableParameterInterface::getParameterDescription(ossim_uint32 idx)const +{ + if(theAdjustmentList.size()) + { + if(idx < theAdjustmentList[theCurrentAdjustment].getNumberOfAdjustableParameters()) + { + return theAdjustmentList[theCurrentAdjustment].getParameterList()[idx].getDescription(); + } + } + + return ossimString(""); +} + +void ossimAdjustableParameterInterface::setParameterDescription(ossim_uint32 idx, + const ossimString& description) +{ + if(!theAdjustmentList.size()) + { + return; + } + if(idx < theAdjustmentList[theCurrentAdjustment].getNumberOfAdjustableParameters()) + { + theAdjustmentList[theCurrentAdjustment].getParameterList()[idx].setDescription(description); + } +} + +void ossimAdjustableParameterInterface::setParameterCenter(ossim_uint32 idx, double center, bool notify) +{ + if(!theAdjustmentList.size()) + { + return; + } + + if(idx < theAdjustmentList[theCurrentAdjustment].getNumberOfAdjustableParameters()) + { + theAdjustmentList[theCurrentAdjustment].getParameterList()[idx].setCenter(center); + + if(notify) + { + adjustableParametersChanged(); + } + } +} + +double ossimAdjustableParameterInterface::getParameterCenter(ossim_uint32 idx)const +{ + if(!theAdjustmentList.size()) + { + return 0.0; + } + if(idx < theAdjustmentList[theCurrentAdjustment].getNumberOfAdjustableParameters()) + { + return theAdjustmentList[theCurrentAdjustment].getParameterList()[idx].getCenter(); + } + + return 0.0; +} + +double ossimAdjustableParameterInterface::computeParameterOffset(ossim_uint32 idx)const +{ + if(!theAdjustmentList.size()) + { + return 0.0; + } + if(idx < theAdjustmentList[theCurrentAdjustment].getNumberOfAdjustableParameters()) + { + return theAdjustmentList[theCurrentAdjustment].getParameterList()[idx].computeOffset(); + } + + return 0.0; +} + +void ossimAdjustableParameterInterface::setParameterOffset(ossim_uint32 idx, + ossim_float64 value, + bool notify) +{ + double center = getParameterCenter(idx); + double sigma = getParameterSigma(idx); + double minValue = center - sigma; + double maxValue = center + sigma; + double x = 0.0; + + if(sigma != 0.0) + { + x = (value - center)/sigma; + + value = center + x*sigma; + + if(value < minValue) + { + x = -1; + } + else if(value >maxValue) + { + x = 1.0; + } + setAdjustableParameter(idx, x, false); + } + if(notify) + { + adjustableParametersChanged(); + } +} + +void ossimAdjustableParameterInterface::resizeAdjustableParameterArray(ossim_uint32 numberOfParameters) +{ + if(!theAdjustmentList.size()) + { + newAdjustment(numberOfParameters); + return; + } + + theAdjustmentList[theCurrentAdjustment].setNumberOfAdjustableParameters(numberOfParameters); +} + +void ossimAdjustableParameterInterface::setAdjustment(const ossimAdjustmentInfo& adj, bool notify) +{ + setAdjustment(theCurrentAdjustment, adj, notify); +} + +void ossimAdjustableParameterInterface::setAdjustment(ossim_uint32 idx, const ossimAdjustmentInfo& adj, bool notify) +{ + if(idx < getNumberOfAdjustments()) + { + theAdjustmentList[(int)idx] = adj; + if(notify) + { + adjustableParametersChanged(); + } + } +} + + +void ossimAdjustableParameterInterface::addAdjustment(const ossimAdjustmentInfo& adj, bool notify) +{ + theAdjustmentList.push_back(adj); + if(notify) + { + adjustableParametersChanged(); + } +} + +void ossimAdjustableParameterInterface::getAdjustment(ossimAdjustmentInfo& adj) +{ + getAdjustment(theCurrentAdjustment, adj); +} + +void ossimAdjustableParameterInterface::getAdjustment(ossim_uint32 idx, ossimAdjustmentInfo& adj) +{ + adj.setNumberOfAdjustableParameters(0); + + if(idx < getNumberOfAdjustments()) + { + adj = theAdjustmentList[(int)idx]; + } +} + +ossim_uint32 ossimAdjustableParameterInterface::getNumberOfAdjustments()const +{ + return theAdjustmentList.size(); +} + +ossim_uint32 ossimAdjustableParameterInterface::getCurrentAdjustmentIdx()const +{ + return theCurrentAdjustment; +} + +void ossimAdjustableParameterInterface::setDirtyFlag(bool flag) +{ + if(theAdjustmentList.size() > 0) + { + theAdjustmentList[theCurrentAdjustment].setDirtyFlag(flag); + } +} + +void ossimAdjustableParameterInterface::setAllDirtyFlag(bool flag) +{ + ossim_uint32 idx = 0; + + for(idx = 0; idx < theAdjustmentList.size(); ++idx) + { + theAdjustmentList[idx].setDirtyFlag(flag); + } +} + +bool ossimAdjustableParameterInterface::hasDirtyAdjustments()const +{ + ossim_uint32 idx = 0; + + for(idx = 0; idx < theAdjustmentList.size(); ++idx) + { + if(theAdjustmentList[idx].isDirty()) + { + return true; + } + } + + return false; +} + +bool ossimAdjustableParameterInterface::saveAdjustments(ossimKeywordlist& kwl, + const ossimString& prefix)const +{ + kwl.add(prefix, + NUMBER_OF_ADJUSTMENTS_KW, + theAdjustmentList.size(), + true); + kwl.add(prefix, + CURRENT_ADJUSTMENT_KW, + (int)theCurrentAdjustment, + true); + + for(ossim_uint32 adjIdx = 0; adjIdx < theAdjustmentList.size(); ++adjIdx) + { + ossimString adjPrefix = prefix + (ossimString(ADJUSTMENT_PREFIX) + ossimString::toString(adjIdx)+"."); + + theAdjustmentList[adjIdx].saveState(kwl, + adjPrefix); + } + + return true; +} + +bool ossimAdjustableParameterInterface::loadAdjustments(const ossimKeywordlist& kwl, + const ossimString& prefix) +{ + theAdjustmentList.clear(); + theCurrentAdjustment = 0; + + const char* numberOfAdjustments = kwl.find(prefix, NUMBER_OF_ADJUSTMENTS_KW); + const char* currentAdjustment = kwl.find(prefix, CURRENT_ADJUSTMENT_KW); + + if(!numberOfAdjustments) + { + numberOfAdjustments = kwl.find(prefix, NUMBER_OF_ADJUSTMENTS_OLD_KW); + } + if(!currentAdjustment) + { + currentAdjustment = kwl.find(prefix, CURRENT_ADJUSTMENT_OLD_KW); + } + if(!numberOfAdjustments) return false; + + int maxdjustments = ossimString(numberOfAdjustments).toInt(); + + for(int adjIdx = 0; adjIdx <maxdjustments; ++adjIdx) + { + ossimAdjustmentInfo info; + ossimString adjPrefix = prefix + (ossimString(ADJUSTMENT_PREFIX) + ossimString::toString(adjIdx)+"."); + + if(!info.loadState(kwl, adjPrefix)) + { + return false; + } + theAdjustmentList.push_back(info); + } + + theCurrentAdjustment = ossimString(currentAdjustment).toUInt32(); + + return true; +} + +void ossimAdjustableParameterInterface::adjustableParametersChanged() +{ +} diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimAdjustableParameterInterface.h b/Utilities/OSSIM/ossim_core/base/misc/ossimAdjustableParameterInterface.h new file mode 100644 index 0000000000..fa239af00c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimAdjustableParameterInterface.h @@ -0,0 +1,121 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimAdjustableParameterInterface.h,v 1.29 2005/12/09 17:02:30 gpotts Exp $ +#ifndef ossimAdjustableParameterInterface_HEADER +#define ossimAdjustableParameterInterface_HEADER +#include "base/common/ossimRtti.h" +#include <vector> +#include "ossimAdjustmentInfo.h" +#include "base/data_types/ossimKeywordlist.h" +#include "base/common/ossimObject.h" + +class OSSIMDLLEXPORT ossimAdjustableParameterInterface +{ +public: + ossimAdjustableParameterInterface(); + virtual ~ossimAdjustableParameterInterface(){} + void newAdjustment(ossim_uint32 numberOfParameters=0); + void setAdjustmentDescription(const ossimString& description); + ossimString getAdjustmentDescription()const; + void setCurrentAdjustment(ossim_uint32 adjustmentIndex, bool notify=false); + void eraseAdjustment(bool notify); + void eraseAdjustment(ossim_uint32 idx, bool notify); + virtual void initAdjustableParameters(); + void resetAdjustableParameters(bool notify=false); + void copyAdjustment(ossim_uint32 idx, bool notify); + void copyAdjustment(bool notify = false); + + virtual ossimObject* getBaseObject()=0; + virtual const ossimObject* getBaseObject()const=0; + + /*! + * Will copy the adjustment but will set the new center to the + * applied current center plus the application of the adjustment + * + */ + void keepAdjustment(ossim_uint32 idx, bool createCopy); + void keepAdjustment(bool createCopy=true); + + + void removeAllAdjustments(); + ossim_uint32 getNumberOfAdjustableParameters()const; + double getAdjustableParameter(ossim_uint32 idx)const; + void setAdjustableParameter(ossim_uint32 idx, double value, + bool notify=false); + void setAdjustableParameter(ossim_uint32 idx, + double value, + double sigma, + bool notify=false); + double getParameterSigma(ossim_uint32 idx)const; + void setParameterSigma(ossim_uint32 idx, + double value, + bool notify=false); + ossimUnitType getParameterUnit(ossim_uint32 idx)const; + void setParameterUnit(ossim_uint32 idx, ossimUnitType unit); + void setParameterUnit(ossim_uint32 idx, const ossimString& unit); + + void setParameterCenter(ossim_uint32 idx, + double center, + bool notify = false); + double getParameterCenter(ossim_uint32 idx)const; + double computeParameterOffset(ossim_uint32 idx)const; + void setParameterOffset(ossim_uint32 idx, + ossim_float64 value, + bool notify = false); + + ossimString getParameterDescription(ossim_uint32 idx)const; + void setParameterDescription(ossim_uint32 idx, + const ossimString& descrption); + + void resizeAdjustableParameterArray(ossim_uint32 numberOfParameters); + + void setAdjustment(const ossimAdjustmentInfo& adj, bool notify=false); + void setAdjustment(ossim_uint32 idx, const ossimAdjustmentInfo& adj, bool notify=false); + + void addAdjustment(const ossimAdjustmentInfo& adj, bool notify); + void getAdjustment(ossimAdjustmentInfo& adj); + void getAdjustment(ossim_uint32 idx, ossimAdjustmentInfo& adj); + + ossim_uint32 getNumberOfAdjustments()const; + ossim_uint32 getCurrentAdjustmentIdx()const; + + + + void setDirtyFlag(bool flag=true); + void setAllDirtyFlag(bool flag = true); + bool hasDirtyAdjustments()const; + + bool saveAdjustments(ossimKeywordlist& kwl, + const ossimString& prefix=ossimString(""))const; + bool loadAdjustments(const ossimKeywordlist& kwl, + const ossimString& prefix=ossimString("")); +private: + std::vector<ossimAdjustmentInfo> theAdjustmentList; + ossim_uint32 theCurrentAdjustment; + +public: + virtual void adjustableParametersChanged(); + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimAdjustmentInfo.cpp b/Utilities/OSSIM/ossim_core/base/misc/ossimAdjustmentInfo.cpp new file mode 100644 index 0000000000..f86b7ccc5e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimAdjustmentInfo.cpp @@ -0,0 +1,188 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimAdjustmentInfo.cpp,v 1.5 2004/09/08 21:58:00 gpotts Exp $ +#include "ossimAdjustmentInfo.h" +#include "base/common/ossimKeywordNames.h" + +static const char* PARAM_PREFIX = "adj_param_"; +static const char* NUMBER_OF_PARAMS_KW = "number_of_params"; +static const char* DIRTY_FLAG_KW = "dirty_flag"; + + +std::ostream& operator <<(std::ostream& out, const ossimAdjustmentInfo& data) +{ + ossim_int32 idx = 0; + + out << "Description: " << data.getDescription() << endl + << "Number of Params: " << data.theParameterList.size()<< endl + << "Dirty flag: " << data.theDirtyFlag << endl; + + for(idx = 0; idx < (int)data.getNumberOfAdjustableParameters(); ++idx) + { + out << "Param " << idx << endl; + out << data.theParameterList[idx] << endl; + } + + return out; +} + + +ossimAdjustmentInfo::ossimAdjustmentInfo(int numberOfAdjustableParameters) + :theParameterList(numberOfAdjustableParameters), + theDescription(""), + theDirtyFlag(false) +{ +} + +ossimAdjustmentInfo::ossimAdjustmentInfo(const ossimAdjustmentInfo& rhs) + :theParameterList(rhs.theParameterList), + theDescription(rhs.theDescription), + theDirtyFlag(rhs.theDirtyFlag) +{ +} + +void ossimAdjustmentInfo::setNumberOfAdjustableParameters(ossim_uint32 numberOfAdjustableParameters) +{ + std::vector<ossimAdjustableParameterInfo> temp = theParameterList; + + theParameterList.resize(numberOfAdjustableParameters); + if(temp.size() < numberOfAdjustableParameters) + { + std::copy(temp.begin(), + temp.end(), + theParameterList.begin()); + } + else if(temp.size() > numberOfAdjustableParameters) + { + if(numberOfAdjustableParameters > 0) + { + std::copy(temp.begin(), + temp.begin()+numberOfAdjustableParameters, + theParameterList.begin()); + } + } +} + +ossim_uint32 ossimAdjustmentInfo::getNumberOfAdjustableParameters()const +{ + return theParameterList.size(); +} + +ossimString ossimAdjustmentInfo::getDescription()const +{ + return theDescription; +} + +void ossimAdjustmentInfo::setDescription(const ossimString& description) +{ + theDescription = description; +} + +bool ossimAdjustmentInfo::isDirty()const +{ + return theDirtyFlag; +} + +void ossimAdjustmentInfo::setDirtyFlag(bool flag) +{ + theDirtyFlag = flag; +} + +void ossimAdjustmentInfo::keep() +{ + ossim_uint32 idx = 0; + + for(idx = 0; idx < theParameterList.size();++idx) + { + double center = theParameterList[idx].computeOffset(); + theParameterList[idx].setParameter(0.0); + theParameterList[idx].setCenter(center); + } +} + + +std::vector<ossimAdjustableParameterInfo>& ossimAdjustmentInfo::getParameterList() +{ + return theParameterList; +} + +const std::vector<ossimAdjustableParameterInfo>& ossimAdjustmentInfo::getParameterList()const +{ + return theParameterList; +} + + +bool ossimAdjustmentInfo::saveState(ossimKeywordlist& kwl, + const ossimString& prefix)const +{ + kwl.add(prefix, + ossimKeywordNames::DESCRIPTION_KW, + getDescription(), + true); + kwl.add(prefix.c_str(), + NUMBER_OF_PARAMS_KW, + theParameterList.size(), + true); + + kwl.add(prefix, + DIRTY_FLAG_KW, + (short)theDirtyFlag, + true); + + ossimString value; + for(ossim_uint32 idx = 0; idx < theParameterList.size();++idx) + { + ossimString newPrefix = ossimString(prefix) + (ossimString(PARAM_PREFIX) + ossimString::toString(idx)+"."); + theParameterList[idx].saveState(kwl, newPrefix.c_str()); + } + + return true; +} + +bool ossimAdjustmentInfo::loadState(const ossimKeywordlist& kwl, + const ossimString& prefix) +{ + setDescription(kwl.find(prefix, ossimKeywordNames::DESCRIPTION_KW)); + setNumberOfAdjustableParameters(ossimString(kwl.find(prefix, NUMBER_OF_PARAMS_KW)).toUInt32()); + const char *dirtyFlag = kwl.find(prefix, DIRTY_FLAG_KW); + ossimString value; + + if(dirtyFlag) + { + theDirtyFlag = ossimString(dirtyFlag).toBool(); + } + else + { + theDirtyFlag = false; + } + + for(ossim_uint32 idx = 0; idx < theParameterList.size();++idx) + { + ossimString newPrefix = ossimString(prefix) + (ossimString(PARAM_PREFIX) + ossimString::toString(idx)+"."); + if(!theParameterList[idx].loadState(kwl, newPrefix.c_str())) + { + return false; + } + } + + return true; +} diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimAdjustmentInfo.h b/Utilities/OSSIM/ossim_core/base/misc/ossimAdjustmentInfo.h new file mode 100644 index 0000000000..8aa7aa9b9c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimAdjustmentInfo.h @@ -0,0 +1,62 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimAdjustmentInfo.h,v 1.2 2004/01/09 19:10:09 gpotts Exp $ +#ifndef ossimAdjustmentInfo_HEADER +#define ossimAdjustmentInfo_HEADER +#include <vector> +#include "base/common/ossimConstants.h" +#include "base/data_types/ossimString.h" +#include "ossimAdjustableParameterInfo.h" + +class ossimAdjustmentInfo +{ +public: + friend std::ostream& operator <<(std::ostream& out, const ossimAdjustmentInfo& data); + + + ossimAdjustmentInfo(int numberOfAdjustableParameters=0); + ossimAdjustmentInfo(const ossimAdjustmentInfo& rhs); + + void setNumberOfAdjustableParameters(ossim_uint32 numberOfAdjustableParameters); + ossim_uint32 getNumberOfAdjustableParameters()const; + ossimString getDescription()const; + void setDescription(const ossimString& description); + bool isDirty()const; + void setDirtyFlag(bool flag=true); + + void keep(); + + std::vector<ossimAdjustableParameterInfo>& getParameterList(); + const std::vector<ossimAdjustableParameterInfo>& getParameterList()const; + + bool saveState(ossimKeywordlist& kwl, + const ossimString& prefix=ossimString(""))const; + bool loadState(const ossimKeywordlist& kwl, + const ossimString& prefix=ossimString("")); + +private: + std::vector<ossimAdjustableParameterInfo> theParameterList; + ossimString theDescription; + mutable bool theDirtyFlag; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimAdrData.cpp b/Utilities/OSSIM/ossim_core/base/misc/ossimAdrData.cpp new file mode 100644 index 0000000000..cf6945f21e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimAdrData.cpp @@ -0,0 +1,422 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// +// Description: +// +// Contains class definition for ADR_Data. +//******************************************************************* +// $Id: ossimAdrData.cpp,v 1.3 2004/04/02 22:03:54 gpotts Exp $ + + +#include <stdlib.h> +#include <iostream> +#include <iomanip> +using namespace std; + + +#include <base/misc/ossimAdrData.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimKeyword.h> +#include <base/context/ossimNotifyContext.h> +//! Specifies the longitude of the ul corner of image in degrees +static const ossimKeyword UL_LONGITUDE("ul_longitude", + "\ +Specifies the longitude of the ul corner of image in degrees."); + +//! Specifies the latitude of the ul corner of image in degrees +static const ossimKeyword UL_LATITUDE("ul_latitude", + "\ +Specifies the latitude of the ul corner of image in degrees."); + +//! Specifies the longitude of the ur corner of image in degrees +static const ossimKeyword UR_LONGITUDE("ur_longitude", + "\ +Specifies the longitude of the ur corner of image in degrees."); + +//! Specifies the latitude of the ur corner of image in degrees +static const ossimKeyword UR_LATITUDE("ur_latitude", + "\ +Specifies the latitude of the ur corner of image in degrees."); + +//! Specifies the longitude of the lr corner of image in degrees +static const ossimKeyword LR_LONGITUDE("lr_longitude", + "\ +Specifies the longitude of the lr corner of image in degrees."); + +//! Specifies the latitude of the lr corner of image in degrees +static const ossimKeyword LR_LATITUDE("lr_latitude", + "\ +Specifies the latitude of the lr corner of image in degrees."); + +//! Specifies the longitude of the ll corner of image in degrees +static const ossimKeyword LL_LONGITUDE("ll_longitude", + "\ +Specifies the longitude of the ll corner of image in degrees."); + +//! Specifies the latitude of the ll corner of image in degrees +static const ossimKeyword LL_LATITUDE("ll_latitude", + "\ +Specifies the latitude of the ll corner of image in degrees."); + +//! Number of lines in the raster image +static const ossimKeyword NUMBER_LINES("number_lines", + "\ + Number of lines in the raster image."); + +//! Number of samples in the raster image +static const ossimKeyword NUMBER_SAMPLES("number_samples", + "\ + Number of samples in the raster image."); + +//! Upper left latitude of the image +static const ossimKeyword UPPER_LAT("Upper Lat", + "Upper left latitude of the image."); + +//! Upper left longitude of the image +static const ossimKeyword LEFT_LON("Left Lon", + "Upper left longitude of the image."); + +//! Lower right latitude of the image +static const ossimKeyword LOWER_LAT("Lower Lat", + "Lower right latitude of the image."); + +//! Lower Right longitude of the image +static const ossimKeyword RIGHT_LON("Right Lon", + "Lower Right longitude of the image."); + +//! Number of samples of the image +static const ossimKeyword SAMPLES("Width", + "Number of samples of the image."); + +//! Number of lines of the image +static const ossimKeyword LINES("Height", + "Number of lines of the image."); + +//! One sigma of position error in meters +static const ossimKeyword +POSITION_ERROR("position_error", + "One sigma of position error in meters."); + +//*************************************************************************** +//! Public Constructor: +//*************************************************************************** +ossimAdrData::ossimAdrData() + : + theLines(0), + theSamples(0), + theUlLon(0.0), + theUlLat(0.0), + theUrLon(0.0), + theUrLat(0.0), + theLrLon(0.0), + theLrLat(0.0), + theLlLon(0.0), + theLlLat(0.0), + thePositionError(0.0), + theErrorStatus(ossimErrorCodes::OSSIM_OK) +{} +//*************************************************************************** +// !Public Constructor: +//*************************************************************************** +ossimAdrData::ossimAdrData(const ossimKeywordlist& kwl) + : + theLines(0), + theSamples(0), + theUlLon(0.0), + theUlLat(0.0), + theUrLon(0.0), + theUrLat(0.0), + theLrLon(0.0), + theLrLat(0.0), + theLlLon(0.0), + theLlLat(0.0), + thePositionError(0.0), + theErrorStatus(ossimErrorCodes::OSSIM_OK) +{ + static const char MODULE[] = "ossimAdrData::ossimAdrData"; + + if (kwl.getErrorStatus()) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_FATAL) << MODULE << " ERROR:\n" + << "Detected an error in the keywordlist.\n"; + return; + } + + const char* kwlLookup = 0; + + kwlLookup = kwl.find(UL_LONGITUDE); + if(kwlLookup) + { + theUlLon = atof(kwlLookup); + } + else + { + kwlLookup = kwl.find(LEFT_LON); + if (kwlLookup) + { + theUlLon = atof(kwlLookup); + } + else + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_FATAL) << MODULE << " ERROR:\n" + << "Error looking up upper left longitude keyword.\n" + << "Could not find: " << UL_LONGITUDE << " or: " << LEFT_LON + << " keyword.\n"; + } + } + + kwlLookup = kwl.find(UL_LATITUDE); + if(kwlLookup) + { + theUlLat = atof(kwlLookup); + } + else + { + kwlLookup = kwl.find(UPPER_LAT); + if (kwlLookup) + { + theUlLat = atof(kwlLookup); + } + else + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_FATAL) << MODULE << " ERROR:\n" + << "Error looking up upper left latitude keyword.\n" + << "Could not find: " << UL_LATITUDE << " or: " << UPPER_LAT + << " keyword.\n"; + } + } + + kwlLookup = kwl.find(UR_LONGITUDE); + if(kwlLookup) + { + theUrLon = atof(kwlLookup); + } + else + { + kwlLookup = kwl.find(RIGHT_LON); + if (kwlLookup) + { + theUrLon = atof(kwlLookup); + } + else + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_FATAL) << MODULE << " ERROR:\n" + << "Error looking up upper right longitude keyword.\n" + << "Could not find: " << UR_LONGITUDE << " or: " << RIGHT_LON + << " keyword.\n"; + } + } + + kwlLookup = kwl.find(UR_LATITUDE); + if(kwlLookup) + { + theUrLat = atof(kwlLookup); + } + else + { + kwlLookup = kwl.find(UPPER_LAT); + if (kwlLookup) + { + theUrLat = atof(kwlLookup); + } + else + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_FATAL) << MODULE << " ERROR:\n" + << "Error looking up upper right latitude keyword.\n" + << "Could not find: " << UR_LATITUDE << " or: " << UPPER_LAT + << " keyword.\n"; + } + } + + kwlLookup = kwl.find(LR_LONGITUDE); + if(kwlLookup) + { + theLrLon = atof(kwlLookup); + } + else + { + kwlLookup = kwl.find(RIGHT_LON); + if (kwlLookup) + { + theLrLon = atof(kwlLookup); + } + else + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_FATAL)<< MODULE << " ERROR:\n" + << "Error looking up lower right longitude keyword.\n" + << "Could not find: " << LR_LONGITUDE << " or: " << RIGHT_LON + << " keyword.\n"; + } + } + + kwlLookup = kwl.find(LR_LATITUDE); + if(kwlLookup) + { + theLrLat = atof(kwlLookup); + } + else + { + kwlLookup = kwl.find(LOWER_LAT); + if (kwlLookup) + { + theLrLat = atof(kwlLookup); + } + else + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_FATAL) << MODULE << " ERROR:\n" + << "Error looking up lower right latitude keyword.\n" + << "Could not find: " << LR_LATITUDE << " or: " << LOWER_LAT + << " keyword.\n"; + } + } + + kwlLookup = kwl.find(LL_LONGITUDE); + if(kwlLookup) + { + theLlLon = atof(kwlLookup); + } + else + { + kwlLookup = kwl.find(LEFT_LON); + if (kwlLookup) + { + theLlLon = atof(kwlLookup); + } + else + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_FATAL) << MODULE << " ERROR:\n" + << "Error looking up lower left longitude keyword.\n" + << "Could not find: " << LL_LONGITUDE << " or: " << LEFT_LON + << " keyword.\n"; + } + } + + kwlLookup = kwl.find(LL_LATITUDE); + if(kwlLookup) + { + theLlLat = atof(kwlLookup); + } + else + { + kwlLookup = kwl.find(LOWER_LAT); + if (kwlLookup) + { + theLlLat = atof(kwlLookup); + } + else + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_FATAL) << MODULE << " ERROR:\n" + << "Error looking up lower left latitude keyword.\n" + << "Could not find: " << LL_LATITUDE << " or: " << LOWER_LAT + << " keyword.\n"; + } + } + + kwlLookup = kwl.find(NUMBER_LINES); + if(kwlLookup) + { + theLines = atoi(kwlLookup); + } + else + { + kwlLookup = kwl.find(LINES); + if (kwlLookup) + { + theLines = atoi(kwlLookup); + } + else + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_FATAL) << MODULE << " ERROR:\n" + << "Error looking up lines keyword.\n" + << "Could not find: " << NUMBER_LINES << " or: " << LINES + << " kwyword.\n"; + } + } + + kwlLookup = kwl.find(NUMBER_SAMPLES); + if(kwlLookup) + { + theSamples = atoi(kwlLookup); + } + else + { + kwlLookup = kwl.find(SAMPLES); + if (kwlLookup) + { + theSamples = atoi(kwlLookup); + } + else + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_FATAL) << MODULE << " ERROR:\n" + << "Error looking up lines keyword.\n" + << "Could not find: " << NUMBER_SAMPLES << " or: " << SAMPLES + << " kwyword.\n"; + } + } + + kwlLookup = kwl.find(POSITION_ERROR); + if(kwlLookup) + { + thePositionError = atof(kwlLookup); + } +} + +//*************************************************************************** +// Public Method: +//*************************************************************************** +//! Prints a list of keywords and respective values + +void ossimAdrData::print(ostream& os) const +{ + os << setiosflags(ios::fixed) << setprecision(10) + << "number_lines: " << theLines << "\n" + << "number_samples: " << theSamples << "\n" + << "ul_longitude: " << theUlLon << "\n" + << "ul_latitude: " << theUlLat << "\n" + << "ur_longitude: " << theUrLon << "\n" + << "ur_latitude: " << theUrLat << "\n" + << "lr_longitude: " << theLrLon << "\n" + << "lr_latitude: " << theLrLat << "\n" + << "ll_longitude: " << theLlLon << "\n" + << "ll_latitude: " << theLlLat << "\n" + << "position_error: " << thePositionError << "\n" + << "\n"; +} + +//*************************************************************************** +// Function: +//*************************************************************************** +ostream& operator<<(ostream& os, const ossimAdrData& ad) +{ + ad.print(os); + + return os; +} diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimAdrData.h b/Utilities/OSSIM/ossim_core/base/misc/ossimAdrData.h new file mode 100644 index 0000000000..6ccebd8110 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimAdrData.h @@ -0,0 +1,63 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// +// Description: +// +// Contains class declaration for ossimAdrData. +//******************************************************************* +// $Id: ossimAdrData.h,v 1.5 2003/05/13 11:31:03 dburken Exp $ + +#ifndef ossimAdrData_HEADER +#define ossimAdrData_HEADER + +#include "base/common/ossimConstants.h" + +class OSSIMDLLEXPORT ossimKeywordlist; + +//******************************************************************* +// CLASS: ossimAdrData +//******************************************************************* +class OSSIMDLLEXPORT ossimAdrData +{ +public: + ossimAdrData (); + ossimAdrData (const ossimKeywordlist& kwl); + ~ossimAdrData (){}; + + ossim_int32 getErrorStatus() const { return theErrorStatus; } + + void print(ostream& os) const; + + friend ostream& operator<<(ostream& os, const ossimAdrData& ad); + + ossim_sint32 theLines; + ossim_sint32 theSamples; + ossim_float64 theUlLon; + ossim_float64 theUlLat; + ossim_float64 theUrLon; + ossim_float64 theUrLat; + ossim_float64 theLrLon; + ossim_float64 theLrLat; + ossim_float64 theLlLon; + ossim_float64 theLlLat; + ossim_float64 thePositionError; + ossim_int32 theErrorStatus; +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimAffineTransform.cpp b/Utilities/OSSIM/ossim_core/base/misc/ossimAffineTransform.cpp new file mode 100644 index 0000000000..96b76510e3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimAffineTransform.cpp @@ -0,0 +1,219 @@ +//***************************************************************************** +// FILE: ossimAffineTransform.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// AUTHOR: Oscar Kramer (okramer@imagelinks.com) +// +// DESCRIPTION: Contains implementation of class ossimAffineTransform +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimAffineTransform.cpp,v 1.5 2003/12/22 18:48:32 dburken Exp $ + +#include "ossimAffineTransform.h" +RTTI_DEF1(ossimAffineTransform, "ossimAffineTransform", ossim2dTo2dTransform); + +#include "base/common/ossimKeywordNames.h" +#include "base/data_types/ossimKeywordlist.h" +#include "base/data_types/ossimMatrix3x3.h" + +//***************************************************************************** +// CONSTRUCTOR: +//***************************************************************************** +ossimAffineTransform::ossimAffineTransform() + : + theForwardXform(3, 3), + theInverseXform(3, 3), + theAffineEnabledFlag(true) +{ + setIdentity(); +} + +//***************************************************************************** +// METHOD: +//***************************************************************************** +void ossimAffineTransform::forward(const ossimDpt& input, + ossimDpt& output) const +{ + if(theAffineEnabledFlag) + { + output.x = theForwardXform[0][0]*input.x+ + theForwardXform[0][1]*input.y+ + theForwardXform[0][2]; + output.y = theForwardXform[1][0]*input.x+ + theForwardXform[1][1]*input.y+ + theForwardXform[1][2]; + } + else + { + output = input; + } +} + +//***************************************************************************** +// METHOD: +//***************************************************************************** +void ossimAffineTransform::inverse(const ossimDpt& input, + ossimDpt& output) const +{ + if(theAffineEnabledFlag) + { + output.x = theInverseXform[0][0]*input.x+ + theInverseXform[0][1]*input.y+ + theInverseXform[0][2]; + output.y = theInverseXform[1][0]*input.x+ + theInverseXform[1][1]*input.y+ + theInverseXform[1][2]; + } + else + { + output = input; + } +} + +//***************************************************************************** +// METHOD: +//***************************************************************************** +bool ossimAffineTransform::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + kwl.add(prefix, + ossimKeywordNames::SCALE_X_KW, + theScale.x, + true); + kwl.add(prefix, + ossimKeywordNames::SCALE_Y_KW, + theScale.y, + true); + kwl.add(prefix, + ossimKeywordNames::TRANSLATION_X_KW, + theTranslation.x, + true); + kwl.add(prefix, + ossimKeywordNames::TRANSLATION_Y_KW, + theTranslation.y, + true); + kwl.add(prefix, + ossimKeywordNames::ROTATION_KW, + theRotation, + true); + + ossim2dTo2dTransform::saveState(kwl, prefix); + + return true; +} + +//***************************************************************************** +// METHOD: +//***************************************************************************** +bool ossimAffineTransform::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* buf; + + if (!ossim2dTo2dTransform::loadState(kwl, prefix)) + goto BAD_KEYWORD; + + buf= kwl.find(prefix, ossimKeywordNames::SCALE_X_KW); + if (!buf) goto BAD_KEYWORD; + theScale.x = atof(buf); + + buf= kwl.find(prefix, ossimKeywordNames::SCALE_Y_KW); + if (!buf) goto BAD_KEYWORD; + theScale.y = atof(buf); + + buf= kwl.find(prefix, ossimKeywordNames::TRANSLATION_X_KW); + if (!buf) goto BAD_KEYWORD; + theTranslation.x = atof(buf); + + buf= kwl.find(prefix, ossimKeywordNames::TRANSLATION_Y_KW); + if (!buf) goto BAD_KEYWORD; + theTranslation.y = atof(buf); + + buf= kwl.find(prefix, ossimKeywordNames::ROTATION_KW); + if (!buf) goto BAD_KEYWORD; + theRotation = atof(buf); + + computeMatrix(); + return true; + + BAD_KEYWORD: + return false; +} + +//***************************************************************************** +// METHOD: +//***************************************************************************** +void ossimAffineTransform::setMatrix(double rotation, + const ossimDpt& scale, + const ossimDpt& translation) +{ + theScale = scale; + theRotation = rotation; + theTranslation = translation; + + computeMatrix(); +} + +//***************************************************************************** +// METHOD: +//***************************************************************************** +void ossimAffineTransform::setIdentity() +{ + theScale.x = 1; + theScale.y = 1; + theTranslation.x = 0; + theTranslation.y = 0; + theRotation = 0.0; + + computeMatrix(); +} + +//***************************************************************************** +// METHOD: +//***************************************************************************** +void ossimAffineTransform::computeMatrix() +{ + theForwardXform = + ossimMatrix3x3::createTranslationMatrix(theTranslation.x, + theTranslation.y)* + ossimMatrix3x3::createRotationZMatrix(theRotation)* + ossimMatrix3x3::createScaleMatrix(theScale.x, + theScale.y, + 1.0); + + //*** + // The inverse transform is just the matrix inverse: + //*** + theInverseXform = theForwardXform.i(); +} + + +//***************************************************************************** +// METHOD: +//***************************************************************************** +std::ostream& ossimAffineTransform::print(std::ostream& os) const +{ + os << "ossimAffineTransform:" + << "\n theScale = " << theScale + << "\n theTranslation = " << theTranslation + << "\n theRotation = " << theRotation << endl; + return os; +} diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimAffineTransform.h b/Utilities/OSSIM/ossim_core/base/misc/ossimAffineTransform.h new file mode 100644 index 0000000000..e0df1dddb6 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimAffineTransform.h @@ -0,0 +1,110 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// 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. +// +// 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. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimAffineTransform.h,v 1.4 2003/12/22 18:48:32 dburken Exp $ + +#ifndef ossimAffineTransform_HEADER +#define ossimAffineTransform_HEADER + +#include "ossim2dTo2dTransform.h" +#include "matrix/newmat.h" + +class OSSIMDLLEXPORT ossimAffineTransform : public ossim2dTo2dTransform +{ +public: + ossimAffineTransform(); + + virtual void forward(const ossimDpt& input, + ossimDpt& output)const; + virtual void inverse(const ossimDpt& input, + ossimDpt& output)const; + + /*! + * Used by the inverse iterator. This will give it a good initial value + * that is within the input transforms + */ + virtual ossimDpt getOrigin()const + { + return ossimDpt(0,0); + } + + bool saveState(ossimKeywordlist& kwl, + const char* prefix = 0)const; + + bool loadState(const ossimKeywordlist& kwl, + const char* prefix = 0); + + void setMatrix(double rotation, + const ossimDpt& scale, + const ossimDpt& translation); + + void setScale(const ossimDpt& scale) + { + theScale = scale; + computeMatrix(); + } + + void setRotation(double rotation) + { + theRotation = rotation; + computeMatrix(); + } + + void setTranslation(const ossimDpt& translation) + { + theTranslation = translation; + computeMatrix(); + } + ossimDpt getScale()const + { + return theScale; + } + ossimDpt getTranslation()const + { + return theTranslation; + } + double getRotation()const + { + return theRotation; + } + void setIdentity(); + + void setAffineEnabledFlag(bool flag) + { + theAffineEnabledFlag = flag; + } + virtual std::ostream& print(std::ostream& out) const; + +protected: + void computeMatrix(); + + NEWMAT::Matrix theForwardXform; + NEWMAT::Matrix theInverseXform; + + ossimDpt theScale; + double theRotation; + ossimDpt theTranslation; + bool theAffineEnabledFlag; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimBilSplitter.cpp b/Utilities/OSSIM/ossim_core/base/misc/ossimBilSplitter.cpp new file mode 100644 index 0000000000..c46dca0c39 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimBilSplitter.cpp @@ -0,0 +1,184 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// +// Description: +// +// Contains class definition for ossimBilSplitter. +// +// Utility class for splitting an image that is band interleaved by line into +// separate files. +//******************************************************************* +// $Id: ossimBilSplitter.cpp,v 1.6 2004/04/02 22:03:54 gpotts Exp $ + +#include <iomanip> +#include <iostream> +using namespace std; + +#include <base/misc/ossimBilSplitter.h> +#include <base/data_types/ossimFilename.h> +#include <base/context/ossimNotifyContext.h> + +ossimBilSplitter::ossimBilSplitter(const char* file_to_split, + ossim_uint32 header_size_in_bytes, + ossim_uint32 bytes_per_pixel, + ossim_uint32 samples_per_line, + ossim_uint32 number_of_channels) + : + theSourceFileStr(), + theHeaderSizeInBytes(header_size_in_bytes), + theBytesPerLine(bytes_per_pixel * samples_per_line), + theLinesToWrite(0), + theNumberOfChannels(number_of_channels), + theErrorStatus(OSSIM_OK) +{ + static const char MODULE[] = "ossimBilSplitter::ossimBilSplitter"; + + //*** + // Open up the source bil file and check for a good descriptor. + //*** + theSourceFileStr.open(file_to_split, ios::in | ios::binary); + if (!theSourceFileStr) + { + theErrorStatus = OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_FATAL) << MODULE << ":\nCould not open file: " << file_to_split + << "\n"; + + return; + } + + //*** + // Get the file size to make sure that the ( size - header ) / byte per line + // come out even; if not, consider this an error. + //*** + ossimFilename f(file_to_split); + ossim_uint32 size = f.fileSize(); + + if ( (size-theHeaderSizeInBytes) % (theBytesPerLine * theNumberOfChannels) ) + { + theErrorStatus = OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_FATAL) << MODULE << ":" + << "\nFile size error..." + << "\nbytes_per_pixel * samples_per_line * " + << "number_of_channels should" + << "\ndivide evenly into total file size in bytes." + << "\nHeader size in bytes: " << header_size_in_bytes + << "\nBytes per pixel: " << bytes_per_pixel + << "\nSamples per line: " << samples_per_line + << "\nBytes per line: " << theBytesPerLine + << "\nNumber of channels: " << theNumberOfChannels + << "\nFile size in bytes: " << size + << "\nthe file size in bytes. Returning with error." + << "\n"; + return; + } + + theLinesToWrite = (size-theHeaderSizeInBytes) / + (theBytesPerLine * theNumberOfChannels); + + ossimNotify(ossimNotifyLevel_INFO) << "\nFile to split: " << file_to_split + << "\nHeader size in bytes: " << header_size_in_bytes + << "\nBytes per pixel: " << bytes_per_pixel + << "\nSamples per line: " << samples_per_line + << "\nBytes per line: " << theBytesPerLine + << "\nNumber of channels: " << theNumberOfChannels + << "\nLines to write per channel: " << theLinesToWrite + << "\n"; +} + +ossimBilSplitter::~ossimBilSplitter() +{ + theSourceFileStr.close(); +} + +bool ossimBilSplitter::output_multi_files(const char* output_dir) +{ + static const char MODULE[] = "ossimBilSplitter::output_multi_files"; + + if (theErrorStatus) + { + ossimNotify(ossimNotifyLevel_FATAL) << MODULE << " :" + << "\nError status has been set. Cannot split file." << "\n"; + return false; + } + + // Open up all the FILE pointers needed. + ossimFilename outDir = output_dir; + ossimString base("channel_"); + ossimString ext(".ras"); + ofstream* os = new ofstream[theNumberOfChannels]; + + ossim_uint32 i = 0; + for(i = 0; i < theNumberOfChannels; i++) + { + ossimString file_basename = base + ossimString::toString(int(i+1)) + ext; + ossimFilename tmpFile = outDir.dirCat(file_basename); + + os[i].open(tmpFile.c_str(), ios::out | ios::binary); + + if (!os) + { + ossimNotify(ossimNotifyLevel_FATAL) << MODULE << ":\n" + << "Cannot open: " << tmpFile.c_str() + << "\nReturning from application." << "\n"; + return false; + } + } + + char* lineBuffer = new char[theBytesPerLine]; + + // Move the source pointer past the header. + theSourceFileStr.seekg(theHeaderSizeInBytes, ios::beg); + + // Write the lines out to the individual files. + ossimNotify(ossimNotifyLevel_INFO) << "\nOutputting to separate files to: " << output_dir << "\n"; + + for (i=0; i<theLinesToWrite; ++i) + { + for(ossim_uint32 j=0; j < theNumberOfChannels; ++j) + { + // Read a line. + theSourceFileStr.read(lineBuffer, theBytesPerLine); + + // Write the line to the channel file. + os[j].write(lineBuffer, theBytesPerLine); + + } // End of loop through the channels. + + //*** + // Output some status info. + //*** + ossim_float64 totalLines = theLinesToWrite; + ossim_float64 linesWritten = i + 1; + ossimNotify(ossimNotifyLevel_INFO) << setiosflags(ios::fixed) + << setprecision(0) << setw(3) + << linesWritten / totalLines * 100.0 << " % \r" + << flush; + + } // End of loop through lines. + + ossimNotify(ossimNotifyLevel_INFO) << "100 %\nFinished...\n"; + + // Cleanup. + for(i = 0; i < theNumberOfChannels; i++) os[i].close(); + delete [] os; + delete [] lineBuffer; + + return true; +} diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimBilSplitter.h b/Utilities/OSSIM/ossim_core/base/misc/ossimBilSplitter.h new file mode 100644 index 0000000000..26f41d27c1 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimBilSplitter.h @@ -0,0 +1,74 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// +// Description: +// +// Contains class declaration for ossimBilSplitter. +// +// Utility class for splitting an image that is band interleaved by line into +// separate files. +//******************************************************************* +// $Id: ossimBilSplitter.h,v 1.3 2003/05/13 11:31:03 dburken Exp $ + +#ifndef ossimBilSplitter_HEADER +#define ossimBilSplitter_HEADER + +#include <fstream> +using namespace std; + +#include "base/common/ossimConstants.h" + +class OSSIMDLLEXPORT ossimBilSplitter +{ +public: + ossimBilSplitter(const char* file_to_split, + ossim_uint32 header_size_in_bytes, + ossim_uint32 bytes_per_pixel, + ossim_uint32 samples_per_line, + ossim_uint32 number_of_channels); + + ~ossimBilSplitter(); + + enum ossimStatus + { + OSSIM_OK = 0, + OSSIM_ERROR = 1 + }; + + /*! + * Splits source image into separate bands and writes to output + * directory as channel_1.ras, channel_2.ras, ... + * Returns true on success, false on error. + */ + bool output_multi_files(const char* output_dir); + + int errorStatus() const { return theErrorStatus; } + +private: + + ifstream theSourceFileStr; + ossim_uint32 theHeaderSizeInBytes; + ossim_uint32 theBytesPerLine; + ossim_uint32 theLinesToWrite; + ossim_uint32 theNumberOfChannels; + ossimStatus theErrorStatus; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimEndian.cpp b/Utilities/OSSIM/ossim_core/base/misc/ossimEndian.cpp new file mode 100644 index 0000000000..c42ae282e1 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimEndian.cpp @@ -0,0 +1,213 @@ +//****************************************************************** +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: This file contains the implementation of the +// endian byte swap routines. +// +//*********************************** +// $Id: ossimEndian.cpp,v 1.6 2005/02/09 15:16:58 dburken Exp $ + +#include <base/misc/ossimEndian.h> + +ossimEndian::ossimEndian() +{ + ossim_uint16 test; + ossim_uint8 *testPtr=NULL; + test = 0x0001; + + testPtr = reinterpret_cast<unsigned char*>(&test); + theSystemEndianType = testPtr[0] ? OSSIM_LITTLE_ENDIAN : OSSIM_BIG_ENDIAN; +} + +ossimByteOrder ossimEndian::getSystemEndianType() const +{ + return theSystemEndianType; +} + +void ossimEndian::swap(ossim_int16 &data) const +{ + swapTwoBytes(reinterpret_cast<void*>(&data)); +} + +void ossimEndian::swap(ossim_uint16 &data) const +{ + swapTwoBytes(reinterpret_cast<void*>(&data)); +} + +void ossimEndian::swap(ossim_int32 &data) const +{ + swapFourBytes(reinterpret_cast<void*>(&data)); +} + +void ossimEndian::swap(ossim_uint32 &data) const +{ + swapFourBytes(reinterpret_cast<void*>(&data)); +} + +void ossimEndian::swap(ossim_float32 &data) const +{ + swapFourBytes(reinterpret_cast<void*>(&data)); +} + +void ossimEndian::swap(ossim_float64 &data) const +{ + swapEightBytes(reinterpret_cast<void*>(&data)); +} + +void ossimEndian::swapTwoBytes(void *data) const +{ + unsigned char *c = reinterpret_cast<unsigned char*>(data); + + swap(&c[0], &c[1]); +} + +void ossimEndian::swapFourBytes(void* data) const +{ + unsigned char *c = reinterpret_cast<unsigned char*>(data); + + swap(&c[0], &c[3]); + swap(&c[1], &c[2]); +} + +void ossimEndian::swapEightBytes(void* data) const +{ + unsigned char *c = reinterpret_cast<unsigned char*>(data); + + swap(&c[0], &c[7]); + swap(&c[1], &c[6]); + swap(&c[2], &c[5]); + swap(&c[3], &c[4]); +} + +void ossimEndian::swap(ossim_uint8 *c1, + ossim_uint8 *c2) const +{ + ossim_uint8 temp_c = *c1; + *c1 = *c2; + *c2 = temp_c; +} + +void ossimEndian::swap(ossimScalarType scalar, + void* data, ossim_uint32 size) const +{ + switch (scalar) + { + case OSSIM_USHORT16: + case OSSIM_SSHORT16: + case OSSIM_USHORT11: + swapTwoBytes(data, size); + return; + + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + swapFourBytes(data, size); + return; + + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + swapEightBytes(data, size); + break; + + default: + return; + } +} + +void ossimEndian::swap(ossim_int16* data, ossim_uint32 size) const +{ + swapTwoBytes(data, size); +} + +void ossimEndian::swap(ossim_uint16* data, ossim_uint32 size) const +{ + swapTwoBytes(data, size); +} + +void ossimEndian::swap(ossim_int32* data, ossim_uint32 size) const +{ + swapFourBytes(data, size); +} + +void ossimEndian::swap(ossim_uint32* data, ossim_uint32 size) const +{ + swapFourBytes(data, size); +} + +#ifdef HAS_LONG_LONG + +void ossimEndian::swap(ossim_int64* data, ossim_uint32 size) const +{ + swapEightBytes(data, size); +} + +void ossimEndian::swap(ossim_uint64* data, ossim_uint32 size) const +{ + swapEightBytes(data, size); +} + +#endif /* End of #ifdef HAS_LONG_LONG */ + +void ossimEndian::swap(ossim_float32* data, ossim_uint32 size) const +{ + swapFourBytes(data, size); +} + +void ossimEndian::swap(ossim_float64* data, ossim_uint32 size) const +{ + swapEightBytes(data, size); +} + +void ossimEndian::swapTwoBytes(void* data, ossim_uint32 size) const +{ + ossim_uint16* buf = reinterpret_cast<ossim_uint16*>(data); + for (ossim_uint32 i=0; i<size; ++i) + { + buf[i] = (buf[i] << 8) | (buf[i] >> 8); + } +} + +void ossimEndian::swapFourBytes(void* data, ossim_uint32 size) const +{ + ossim_uint32* buf = reinterpret_cast<ossim_uint32*>(data); + for (ossim_uint32 i=0; i<size; ++i) + { + buf[i] + = ( ((buf[i] & 0xff000000) >> 24) + | ((buf[i] & 0x00ff0000) >> 8) + | ((buf[i] & 0x0000ff00) << 8) + | ((buf[i] & 0x000000ff) << 24)); + } +} + +void ossimEndian::swapEightBytes(void* data, ossim_uint32 size) const +{ +#ifdef HAS_LONG_LONG + uint64* buf = reinterpret_cast<ossim_uint64*>(data); + for (uint32 i=0; i<size; ++i) + { + buf[i] + = ( ((buf[i] & 0xff00000000000000ull) >> 56) + | ((buf[i] & 0x00ff000000000000ull) >> 40) + | ((buf[i] & 0x0000ff0000000000ull) >> 24) + | ((buf[i] & 0x000000ff00000000ull) >> 8) + | ((buf[i] & 0x00000000ff000000ull) << 8) + | ((buf[i] & 0x0000000000ff0000ull) << 24) + | ((buf[i] & 0x000000000000ff00ull) << 40) + | ((buf[i] & 0x00000000000000ffull) << 56)); + } +#else + ossim_float64* buf = reinterpret_cast<ossim_float64*>(data); + for (ossim_uint32 i=0; i<size; ++i) + { + swapEightBytes(buf+i); + } + +#endif + +} diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimEndian.h b/Utilities/OSSIM/ossim_core/base/misc/ossimEndian.h new file mode 100644 index 0000000000..d329d9c2be --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimEndian.h @@ -0,0 +1,77 @@ +//****************************************************************** +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: This file contains the interface to the +// endian byte swap +// +//*********************************** +// $ID$ +#ifndef ossimEndian_HEADER +#define ossimEndian_HEADER +#include <iostream> +using namespace std; + +// for OSSIM_LITTLE_ENDIAN AND BIG_ENDIAN +#include <base/common/ossimConstants.h> + +class OSSIMDLLEXPORT ossimEndian +{ +public: + ossimEndian(); + + /*! + * Swap bytes methods that work on a single pixel. + */ + void swap(ossim_int16 &data) const; + void swap(ossim_uint16 &data) const; + void swap(ossim_int32 &data) const; + void swap(ossim_uint32 &data) const; + void swap(ossim_float32 &data) const; + void swap(ossim_float64 &data) const; + + /*! + * Swap bytes methods that work on arrays of pixels. + * + * @note size is number of pixels, not number of bytes. + */ + void swap(ossimScalarType scalar, void* data, ossim_uint32 size) const; + + void swap(ossim_int16* data, ossim_uint32 size) const; + void swap(ossim_uint16* data, ossim_uint32 size) const; + + void swap(ossim_int32* data, ossim_uint32 size) const; + void swap(ossim_uint32* data, ossim_uint32 size) const; + +#ifdef HAS_LONG_LONG + void swap(ossim_int64* data, ossim_uint32 size) const; + void swap(ossim_uint64* data, ossim_uint32 size) const; +#endif + + void swap(ossim_float32* data, ossim_uint32 size) const; + void swap(ossim_float64* data, ossim_uint32 size) const; + + void swapTwoBytes(void* data, ossim_uint32 size) const; + void swapFourBytes(void* data, ossim_uint32 size) const; + void swapEightBytes(void* data, ossim_uint32 size) const; + ossimByteOrder getSystemEndianType() const; + +private: + + // Holds the Endian of the architecture that you are running on. + ossimByteOrder theSystemEndianType; + + void swapTwoBytes(void *data) const; + void swapFourBytes(void *data) const; + void swapEightBytes(void *data) const; + + void swap(ossim_uint8 *c1, + ossim_uint8 *c2) const; +}; + +#endif /* End of #ifndef ossimEndian_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimEquTokenDefines.h b/Utilities/OSSIM/ossim_core/base/misc/ossimEquTokenDefines.h new file mode 100644 index 0000000000..24e6b6badc --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimEquTokenDefines.h @@ -0,0 +1,54 @@ +#ifndef ossimEquTokenDefines_HEADER +#define ossimEquTokenDefines_HEADER + +#define OSSIM_EQU_TOKEN_LEFT_PAREN 1 +#define OSSIM_EQU_TOKEN_RIGHT_PAREN 2 +#define OSSIM_EQU_TOKEN_LOG 3 +#define OSSIM_EQU_TOKEN_MULT 4 +#define OSSIM_EQU_TOKEN_DIV 5 +#define OSSIM_EQU_TOKEN_MINUS 6 +#define OSSIM_EQU_TOKEN_PLUS 7 +#define OSSIM_EQU_TOKEN_IMAGE_VARIABLE 8 +#define OSSIM_EQU_TOKEN_CONSTANT 9 +#define OSSIM_EQU_TOKEN_EXP 10 +#define OSSIM_EQU_TOKEN_LOG10 11 +#define OSSIM_EQU_TOKEN_PI 12 +#define OSSIM_EQU_TOKEN_POWER 13 +#define OSSIM_EQU_TOKEN_SIN 14 +#define OSSIM_EQU_TOKEN_SIND 15 +#define OSSIM_EQU_TOKEN_COS 16 +#define OSSIM_EQU_TOKEN_COSD 17 +#define OSSIM_EQU_TOKEN_ABS 18 +#define OSSIM_EQU_TOKEN_MIN 19 +#define OSSIM_EQU_TOKEN_MAX 20 +#define OSSIM_EQU_TOKEN_SQRT 21 +#define OSSIM_EQU_TOKEN_COMMA 22 +#define OSSIM_EQU_TOKEN_BLURR 23 +#define OSSIM_EQU_TOKEN_SHIFT 24 +#define OSSIM_EQU_TOKEN_CONV 25 +#define OSSIM_EQU_TOKEN_BAND 26 +#define OSSIM_EQU_TOKEN_ASSIGN_BAND 27 +#define OSSIM_EQU_TOKEN_MOD 28 +#define OSSIM_EQU_TOKEN_ASIN 29 +#define OSSIM_EQU_TOKEN_ASIND 30 +#define OSSIM_EQU_TOKEN_ACOS 31 +#define OSSIM_EQU_TOKEN_ACOSD 32 +#define OSSIM_EQU_TOKEN_TAN 33 +#define OSSIM_EQU_TOKEN_TAND 34 +#define OSSIM_EQU_TOKEN_ATAN 35 +#define OSSIM_EQU_TOKEN_ATAND 36 +#define OSSIM_EQU_TOKEN_LEFT_ARRAY_BRACKET 37 +#define OSSIM_EQU_TOKEN_RIGHT_ARRAY_BRACKET 38 +#define OSSIM_EQU_TOKEN_AMPERSAND 39 +#define OSSIM_EQU_TOKEN_OR_BAR 40 +#define OSSIM_EQU_TOKEN_TILDE 41 +#define OSSIM_EQU_TOKEN_XOR 42 +#define OSSIM_EQU_TOKEN_CLAMP 43 +#define OSSIM_EQU_TOKEN_CLIP 44 +#define OSSIM_EQU_TOKEN_BEQUAL 45 +#define OSSIM_EQU_TOKEN_BGREATER 46 +#define OSSIM_EQU_TOKEN_BGREATEROREQUAL 47 +#define OSSIM_EQU_TOKEN_BLESS 48 +#define OSSIM_EQU_TOKEN_BLESSOREQUAL 49 +#define OSSIM_EQU_TOKEN_BDIFFERENT 50 +#endif diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimEquTokenizer.cpp b/Utilities/OSSIM/ossim_core/base/misc/ossimEquTokenizer.cpp new file mode 100644 index 0000000000..4683568e1a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimEquTokenizer.cpp @@ -0,0 +1,1795 @@ +#define yyFlexLexer ossimEquTokenizerFlexLexer +#define yywrap ossimEquTokenizerwrap + +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: /cvs/ossim/src/ossim_core/base/misc/ossimEquTokenizer.cpp,v 1.20 2005/07/12 15:41:56 gpotts Exp $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include <stdlib.h> +#include <iostream> +using namespace std; + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include <io.h> +#include <stdlib.h> +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + istream* yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + +typedef unsigned char YY_CHAR; +#define yytext_ptr yytext +#define YY_INTERACTIVE + +#include <base/misc/FlexLexer.h> + + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 52 +#define YY_END_OF_BUFFER 53 +static yyconst short int yy_accept[119] = + { 0, + 0, 0, 53, 52, 1, 11, 7, 14, 15, 5, + 9, 3, 10, 52, 4, 2, 49, 52, 47, 52, + 12, 13, 16, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 6, 8, 1, 2, 2, 2, 0, + 50, 51, 46, 48, 19, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 35, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 27, 22, 20, 38, + 37, 0, 23, 0, 31, 17, 0, 2, 29, 25, + 0, 33, 42, 0, 0, 44, 39, 28, 0, 0, + + 24, 36, 32, 30, 26, 0, 34, 41, 45, 21, + 40, 0, 0, 0, 0, 0, 43, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 1, 1, 3, 4, 1, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 15, 15, 15, 15, 15, 15, 15, 1, 1, 16, + 17, 18, 1, 1, 1, 1, 1, 1, 19, 1, + 1, 1, 20, 1, 1, 1, 1, 1, 1, 21, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 22, 1, 23, 24, 25, 1, 26, 27, 28, 29, + + 30, 31, 32, 33, 34, 1, 1, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 1, 46, + 1, 1, 1, 47, 1, 48, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[49] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1 + } ; + +static yyconst short int yy_base[119] = + { 0, + 0, 0, 170, 171, 167, 171, 171, 171, 171, 171, + 171, 171, 171, 36, 171, 41, 40, 151, 150, 146, + 171, 171, 171, 34, 33, 28, 119, 127, 125, 38, + 40, 136, 123, 171, 171, 158, 68, 71, 78, 92, + 171, 171, 171, 171, 171, 117, 120, 33, 131, 119, + 111, 44, 57, 115, 171, 121, 106, 114, 116, 112, + 107, 110, 105, 101, 104, 107, 171, 103, 107, 109, + 105, 112, 99, 103, 99, 92, 107, 171, 121, 171, + 171, 103, 104, 89, 102, 171, 110, 113, 101, 100, + 81, 83, 171, 69, 65, 171, 171, 171, 90, 53, + + 171, 171, 171, 171, 171, 58, 171, 171, 171, 171, + 171, 63, 52, 43, 28, 24, 171, 171 + } ; + +static yyconst short int yy_def[119] = + { 0, + 118, 1, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 0 + } ; + +static yyconst short int yy_nxt[220] = + { 0, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 16, 16, 17, 18, 19, 4, 4, + 20, 21, 22, 23, 4, 24, 25, 26, 4, 27, + 4, 4, 4, 28, 29, 30, 4, 4, 4, 4, + 4, 31, 32, 4, 4, 33, 34, 35, 37, 37, + 37, 38, 117, 39, 39, 39, 41, 42, 50, 40, + 46, 47, 52, 57, 116, 53, 69, 51, 115, 74, + 40, 58, 59, 60, 70, 48, 49, 75, 114, 61, + 37, 37, 37, 37, 37, 37, 64, 113, 38, 40, + 39, 39, 39, 76, 112, 111, 40, 64, 77, 65, + + 40, 65, 110, 109, 66, 66, 66, 40, 87, 108, + 87, 107, 106, 88, 88, 88, 66, 66, 66, 66, + 66, 66, 88, 88, 88, 88, 88, 88, 105, 104, + 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, + 93, 92, 91, 90, 89, 86, 85, 84, 83, 82, + 81, 80, 79, 78, 73, 72, 71, 68, 67, 36, + 63, 62, 56, 55, 54, 45, 44, 43, 36, 118, + 3, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118 + } ; + +static yyconst short int yy_chk[220] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 14, 14, + 14, 16, 116, 16, 16, 16, 17, 17, 25, 16, + 24, 24, 26, 30, 115, 26, 48, 25, 114, 52, + 16, 30, 31, 31, 48, 24, 24, 52, 113, 31, + 37, 37, 37, 38, 38, 38, 37, 112, 39, 38, + 39, 39, 39, 53, 106, 100, 39, 37, 53, 40, + + 38, 40, 99, 95, 40, 40, 40, 39, 64, 94, + 64, 92, 91, 64, 64, 64, 65, 65, 65, 66, + 66, 66, 87, 87, 87, 88, 88, 88, 90, 89, + 85, 84, 83, 82, 79, 77, 76, 75, 74, 73, + 72, 71, 70, 69, 68, 63, 62, 61, 60, 59, + 58, 57, 56, 54, 51, 50, 49, 47, 46, 36, + 33, 32, 29, 28, 27, 20, 19, 18, 5, 3, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118 + } ; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +#line 1 "ossimEquTokenizer.l" +#define INITIAL 0 +#line 2 "ossimEquTokenizer.l" +#include "ossimEquTokenDefines.h" +#line 413 "lex.ossimEquTokenizer.cc" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen YY_PROTO(( yyconst char * )); +#endif + +#ifndef YY_NO_INPUT +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include <stdlib.h> +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +#define ECHO LexerOutput( yytext, yyleng ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( (result = LexerInput( (char *) buf, max_size )) < 0 ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) LexerError( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yyFlexLexer::yylex() +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp = NULL, *yy_bp = NULL; + register int yy_act; + +#line 15 "ossimEquTokenizer.l" + + +#line 543 "lex.ossimEquTokenizer.cc" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = &cin; + + if ( ! yyout ) + yyout = &cout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 119 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 171 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 17 "ossimEquTokenizer.l" +/* skip blanks and tabs */ + YY_BREAK +case 2: +YY_RULE_SETUP +#line 19 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_CONSTANT; + } + YY_BREAK +case 3: +YY_RULE_SETUP +#line 22 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_COMMA; + } + YY_BREAK +case 4: +YY_RULE_SETUP +#line 25 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_DIV; + } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 29 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_MULT; + } + YY_BREAK +case 6: +YY_RULE_SETUP +#line 33 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_OR_BAR; + } + YY_BREAK +case 7: +YY_RULE_SETUP +#line 37 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_AMPERSAND; + } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 40 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_TILDE; + } + YY_BREAK +case 9: +YY_RULE_SETUP +#line 44 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_PLUS; + } + YY_BREAK +case 10: +YY_RULE_SETUP +#line 47 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_MINUS; + } + YY_BREAK +case 11: +YY_RULE_SETUP +#line 50 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_MOD; + } + YY_BREAK +case 12: +YY_RULE_SETUP +#line 53 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_LEFT_ARRAY_BRACKET; + } + YY_BREAK +case 13: +YY_RULE_SETUP +#line 56 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_RIGHT_ARRAY_BRACKET; + } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 59 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_LEFT_PAREN; + } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 62 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_RIGHT_PAREN; + } + YY_BREAK +case 16: +YY_RULE_SETUP +#line 65 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_POWER; + } + YY_BREAK +case 17: +YY_RULE_SETUP +#line 68 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_XOR; + } + YY_BREAK +case 18: +YY_RULE_SETUP +#line 72 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_IMAGE_VARIABLE; + } + YY_BREAK +case 19: +YY_RULE_SETUP +#line 75 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_PI; + } + YY_BREAK +case 20: +YY_RULE_SETUP +#line 78 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_LOG; + } + YY_BREAK +case 21: +YY_RULE_SETUP +#line 81 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_LOG10; + } + YY_BREAK +case 22: +YY_RULE_SETUP +#line 84 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_EXP; + } + YY_BREAK +case 23: +YY_RULE_SETUP +#line 87 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_SIN; + } + YY_BREAK +case 24: +YY_RULE_SETUP +#line 90 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_SIND; + } + YY_BREAK +case 25: +YY_RULE_SETUP +#line 93 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_ASIN; + } + YY_BREAK +case 26: +YY_RULE_SETUP +#line 96 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_ASIND; + } + YY_BREAK +case 27: +YY_RULE_SETUP +#line 99 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_COS; + } + YY_BREAK +case 28: +YY_RULE_SETUP +#line 102 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_COSD; + } + YY_BREAK +case 29: +YY_RULE_SETUP +#line 105 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_ACOS; + } + YY_BREAK +case 30: +YY_RULE_SETUP +#line 108 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_ACOSD; + } + YY_BREAK +case 31: +YY_RULE_SETUP +#line 111 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_TAN; + } + YY_BREAK +case 32: +YY_RULE_SETUP +#line 114 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_TAND; + } + YY_BREAK +case 33: +YY_RULE_SETUP +#line 117 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_ATAN; + } + YY_BREAK +case 34: +YY_RULE_SETUP +#line 120 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_ATAND; + } + YY_BREAK +case 35: +YY_RULE_SETUP +#line 123 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_ABS; + } + YY_BREAK +case 36: +YY_RULE_SETUP +#line 126 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_SQRT; + } + YY_BREAK +case 37: +YY_RULE_SETUP +#line 129 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_MIN; + } + YY_BREAK +case 38: +YY_RULE_SETUP +#line 132 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_MAX; + } + YY_BREAK +case 39: +YY_RULE_SETUP +#line 135 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_CONV; + } + YY_BREAK +case 40: +YY_RULE_SETUP +#line 138 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_SHIFT; + } + YY_BREAK +case 41: +YY_RULE_SETUP +#line 141 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_BLURR; + } + YY_BREAK +case 42: +YY_RULE_SETUP +#line 144 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_BAND; + } + YY_BREAK +case 43: +YY_RULE_SETUP +#line 147 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_ASSIGN_BAND; + } + YY_BREAK +case 44: +YY_RULE_SETUP +#line 150 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_CLIP; + } + YY_BREAK +case 45: +YY_RULE_SETUP +#line 153 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_CLAMP; + } + YY_BREAK +case 46: +YY_RULE_SETUP +#line 156 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_BEQUAL; +} + YY_BREAK +case 47: +YY_RULE_SETUP +#line 159 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_BGREATER; +} + YY_BREAK +case 48: +YY_RULE_SETUP +#line 162 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_BGREATEROREQUAL; +} + YY_BREAK +case 49: +YY_RULE_SETUP +#line 165 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_BLESS; +} + YY_BREAK +case 50: +YY_RULE_SETUP +#line 168 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_BLESSOREQUAL; +} + YY_BREAK +case 51: +YY_RULE_SETUP +#line 171 "ossimEquTokenizer.l" +{ + return OSSIM_EQU_TOKEN_BDIFFERENT; +} + YY_BREAK +case 52: +YY_RULE_SETUP +#line 175 "ossimEquTokenizer.l" +ECHO; + YY_BREAK +#line 986 "lex.ossimEquTokenizer.cc" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + +yyFlexLexer::yyFlexLexer( istream* arg_yyin, ostream* arg_yyout ) + { + yyin = arg_yyin; + yyout = arg_yyout; + yy_c_buf_p = 0; + yy_init = 1; + yy_start = 0; + yy_flex_debug = 0; + yylineno = 1; // this will only get updated if %option yylineno + + yy_did_buffer_switch_on_eof = 0; + + yy_looking_for_trail_begin = 0; + yy_more_flag = 0; + yy_more_len = 0; + yy_more_offset = yy_prev_more_offset = 0; + + yy_start_stack_ptr = yy_start_stack_depth = 0; + yy_start_stack = 0; + + yy_current_buffer = 0; + +#ifdef YY_USES_REJECT + yy_state_buf = new yy_state_type[YY_BUF_SIZE + 2]; +#else + yy_state_buf = 0; +#endif + } + +yyFlexLexer::~yyFlexLexer() + { + delete yy_state_buf; + yy_delete_buffer( yy_current_buffer ); + } + +void yyFlexLexer::switch_streams( istream* new_in, ostream* new_out ) + { + if ( new_in ) + { + yy_delete_buffer( yy_current_buffer ); + yy_switch_to_buffer( yy_create_buffer( new_in, YY_BUF_SIZE ) ); + } + + if ( new_out ) + yyout = new_out; + } + +#ifdef YY_INTERACTIVE +int yyFlexLexer::LexerInput( char* buf, int /* max_size */ ) +#else +int yyFlexLexer::LexerInput( char* buf, int max_size ) +#endif + { + if ( yyin->eof() || yyin->fail() ) + return 0; + +#ifdef YY_INTERACTIVE + yyin->get( buf[0] ); + + if ( yyin->eof() ) + return 0; + + if ( yyin->bad() ) + return -1; + + return 1; + +#else + (void) yyin->read( buf, max_size ); + + if ( yyin->bad() ) + return -1; + else + return yyin->gcount(); +#endif + } + +void yyFlexLexer::LexerOutput( const char* buf, int size ) + { + (void) yyout->write( buf, size ); + } + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +int yyFlexLexer::yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_current_buffer->yy_n_chars = yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +yy_state_type yyFlexLexer::yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 119 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +yy_state_type yyFlexLexer::yy_try_NUL_trans( yy_state_type yy_current_state ) + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 119 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 118); + + return yy_is_jam ? 0 : yy_current_state; + } + + +void yyFlexLexer::yyunput( int c, register char* yy_bp ) + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_current_buffer->yy_n_chars = + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } + + +int yyFlexLexer::yyinput() + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yy_c_buf_p - yytext_ptr; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin ); + + /* fall through */ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + return EOF; + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + + return c; + } + +void yyFlexLexer::yyrestart( istream* input_file ) + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +void yyFlexLexer::yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +void yyFlexLexer::yy_load_buffer_state() + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +YY_BUFFER_STATE yyFlexLexer::yy_create_buffer( istream* file, int size ) + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +void yyFlexLexer::yy_delete_buffer( YY_BUFFER_STATE b ) + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +void yyFlexLexer::yy_init_buffer( YY_BUFFER_STATE b, istream* file ) + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + b->yy_is_interactive = 0; + } + + +void yyFlexLexer::yy_flush_buffer( YY_BUFFER_STATE b ) + { + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#endif + + +#ifndef YY_NO_SCAN_STRING +#endif + + +#ifndef YY_NO_SCAN_BYTES +#endif + + +#ifndef YY_NO_PUSH_STATE +void yyFlexLexer::yy_push_state( int new_state ) + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +void yyFlexLexer::yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +int yyFlexLexer::yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + + +void yyFlexLexer::LexerError( yyconst char msg[] ) + { + cerr << msg << '\n'; + exit( YY_EXIT_FAILURE ); + } + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + +#ifdef YY_NEED_STRLEN +#ifdef YY_USE_PROTOS +static int yy_flex_strlen( yyconst char *s ) +#else +static int yy_flex_strlen( s ) +yyconst char *s; +#endif + { + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 175 "ossimEquTokenizer.l" + +int yywrap() +{ + return 1; +} diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimEquTokenizer.h b/Utilities/OSSIM/ossim_core/base/misc/ossimEquTokenizer.h new file mode 100644 index 0000000000..c3e2f4ab36 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimEquTokenizer.h @@ -0,0 +1,9 @@ +#ifndef ossimEquTokenizer_HEADER +#define ossimEquTokenizer_HEADER +#define yyFlexLexer ossimEquTokenizerFlexLexer + +#include "base/misc/ossimEquTokenDefines.h" +#include "base/misc/FlexLexer.h" +typedef ossimEquTokenizerFlexLexer ossimEquTokenizer; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimEquTokenizer.l b/Utilities/OSSIM/ossim_core/base/misc/ossimEquTokenizer.l new file mode 100644 index 0000000000..c74c1b81a5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimEquTokenizer.l @@ -0,0 +1,179 @@ +%{ +#include "ossimEquTokenDefines.h" +%} + +string \"[^\n"]+\" + +ws [ \t]+ + +alpha [A-Za-z] +dig [0-9] +num1 {dig}+\.?([eE][-+]?{dig}+)? +num2 {dig}*\.{dig}+([eE][-+]?{dig}+)? +number {num1}|{num2} + +%% + +{ws} /* skip blanks and tabs */ + +{number} { + return OSSIM_EQU_TOKEN_CONSTANT; + } +"," { + return OSSIM_EQU_TOKEN_COMMA; + } +"/" { + return OSSIM_EQU_TOKEN_DIV; + } + +"*" { + return OSSIM_EQU_TOKEN_MULT; + } + +"|" { + return OSSIM_EQU_TOKEN_OR_BAR; + } + +"&" { + return OSSIM_EQU_TOKEN_AMPERSAND; + } +"~" { + return OSSIM_EQU_TOKEN_TILDE; + } + +"+" { + return OSSIM_EQU_TOKEN_PLUS; + } +"-" { + return OSSIM_EQU_TOKEN_MINUS; + } +"%" { + return OSSIM_EQU_TOKEN_MOD; + } +"[" { + return OSSIM_EQU_TOKEN_LEFT_ARRAY_BRACKET; + } +"]" { + return OSSIM_EQU_TOKEN_RIGHT_ARRAY_BRACKET; + } +"(" { + return OSSIM_EQU_TOKEN_LEFT_PAREN; + } +")" { + return OSSIM_EQU_TOKEN_RIGHT_PAREN; + } +"\^" { + return OSSIM_EQU_TOKEN_POWER; + } +"xor" { + return OSSIM_EQU_TOKEN_XOR; + } + +"in" { + return OSSIM_EQU_TOKEN_IMAGE_VARIABLE; + } +"PI" { + return OSSIM_EQU_TOKEN_PI; + } +"log" { + return OSSIM_EQU_TOKEN_LOG; + } +"log10" { + return OSSIM_EQU_TOKEN_LOG10; + } +"exp" { + return OSSIM_EQU_TOKEN_EXP; + } +"sin" { + return OSSIM_EQU_TOKEN_SIN; + } +"sind" { + return OSSIM_EQU_TOKEN_SIND; + } +"asin" { + return OSSIM_EQU_TOKEN_ASIN; + } +"asind" { + return OSSIM_EQU_TOKEN_ASIND; + } +"cos" { + return OSSIM_EQU_TOKEN_COS; + } +"cosd" { + return OSSIM_EQU_TOKEN_COSD; + } +"acos" { + return OSSIM_EQU_TOKEN_ACOS; + } +"acosd" { + return OSSIM_EQU_TOKEN_ACOSD; + } +"tan" { + return OSSIM_EQU_TOKEN_TAN; + } +"tand" { + return OSSIM_EQU_TOKEN_TAND; + } +"atan" { + return OSSIM_EQU_TOKEN_ATAN; + } +"atand" { + return OSSIM_EQU_TOKEN_ATAND; + } +"abs" { + return OSSIM_EQU_TOKEN_ABS; + } +"sqrt" { + return OSSIM_EQU_TOKEN_SQRT; + } +"min" { + return OSSIM_EQU_TOKEN_MIN; + } +"max" { + return OSSIM_EQU_TOKEN_MAX; + } +"conv" { + return OSSIM_EQU_TOKEN_CONV; + } +"shift" { + return OSSIM_EQU_TOKEN_SHIFT; + } +"blurr" { + return OSSIM_EQU_TOKEN_BLURR; + } +"band" { + return OSSIM_EQU_TOKEN_BAND; + } +"assign_band" { + return OSSIM_EQU_TOKEN_ASSIGN_BAND; + } +"clip" { + return OSSIM_EQU_TOKEN_CLIP; + } +"clamp" { + return OSSIM_EQU_TOKEN_CLAMP; + } +"==" { + return OSSIM_EQU_TOKEN_BEQUAL; +} +"\>" { + return OSSIM_EQU_TOKEN_BGREATER; +} +"\>=" { + return OSSIM_EQU_TOKEN_BGREATEROREQUAL; +} +"\<" { + return OSSIM_EQU_TOKEN_BLESS; +} +"\<=" { + return OSSIM_EQU_TOKEN_BLESSOREQUAL; +} +"\<\>" { + return OSSIM_EQU_TOKEN_BDIFFERENT; +} + +%% +int yywrap() +{ + return 1; +} diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimQuadTreeWarp.cpp b/Utilities/OSSIM/ossim_core/base/misc/ossimQuadTreeWarp.cpp new file mode 100644 index 0000000000..6302a1a8f4 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimQuadTreeWarp.cpp @@ -0,0 +1,1426 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// 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. +// +// 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. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@remotesensing.org) +// +//************************************************************************* +// $Id: ossimQuadTreeWarp.cpp,v 1.36 2004/04/05 13:31:35 gpotts Exp $ + +#include <base/misc/ossimQuadTreeWarp.h> +#include <algorithm> +#include <stack> +using namespace std; + +#include <base/common/ossimTrace.h> +#include <base/context/ossimNotifyContext.h> + +static ossimTrace traceExec ("ossimQuadTreeWarp:exec"); +static ossimTrace traceDebug ("ossimQuadTreeWarp:debug"); + +RTTI_DEF1(ossimQuadTreeWarp, "ossimQuadTreeWarp", ossim2dTo2dTransform); + + +void ossimQuadTreeWarpVertex::removeNode(ossimQuadTreeWarpNode* node) +{ + vector<ossimQuadTreeWarpNode*>::iterator iter = theSharedNodeList.begin(); + bool found = false; + ossimQuadTreeWarpNode* removedNode = NULL; + while((iter != theSharedNodeList.end())&&!found) + { + if(*iter == node) + { + removedNode = *iter; + iter = theSharedNodeList.erase(iter); + found = true; + } + else + { + ++iter; + } + } + + if(removedNode) + { + removedNode->removeVertex(this); + } +} + +ossimQuadTreeWarpVertex::~ossimQuadTreeWarpVertex() +{ + for(ossim_uint32 i = 0;i< theSharedNodeList.size();++i) + { + theSharedNodeList[i]->removeVertex(this); + } + +} + +bool ossimQuadTreeWarpVertex::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + "x", + thePosition.x, + true); + kwl.add(prefix, + "y", + thePosition.y, + true); + kwl.add(prefix, + "dx", + theDelta.x, + true); + kwl.add(prefix, + "dy", + theDelta.y, + true); + kwl.add(prefix, + "lock_flag", + (int)theLockedFlag, + true); + + return true; +} + +bool ossimQuadTreeWarpVertex::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* x = kwl.find(prefix, + "x"); + const char* y = kwl.find(prefix, + "y"); + const char* dx = kwl.find(prefix, + "dx"); + const char* dy = kwl.find(prefix, + "dy"); + const char* lockedFlag = kwl.find(prefix, + "lock_flag"); + if(x&&y&&dx&&dy&&lockedFlag) + { + thePosition.x = ossimString(x).toDouble(); + thePosition.y = ossimString(y).toDouble(); + theDelta.x = ossimString(dx).toDouble(); + theDelta.y = ossimString(dy).toDouble(); + theLockedFlag = ossimString(lockedFlag).toBool(); + + return true; + } + + return false; +} + + + +ossimQuadTreeWarpNode::~ossimQuadTreeWarpNode() +{ + removeVertices(); + + theUlVertex = NULL; + theUrVertex = NULL; + theLrVertex = NULL; + theLlVertex = NULL; + +} + +void ossimQuadTreeWarpNode::removeChild(ossimQuadTreeWarpNode* node) +{ + vector<ossimQuadTreeWarpNode*>::iterator iter = theChildren.begin(); + + while(iter != theChildren.end()) + { + if(*iter == node) + { + theChildren.erase(iter); + return; + } + ++iter; + } +} + +bool ossimQuadTreeWarpNode::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + ossimKeywordNames::UL_X_KW, + theBoundingRect.ul().x, + true); + kwl.add(prefix, + ossimKeywordNames::UL_Y_KW, + theBoundingRect.ul().y, + true); + kwl.add(prefix, + ossimKeywordNames::LR_X_KW, + theBoundingRect.lr().x, + true); + kwl.add(prefix, + ossimKeywordNames::LR_Y_KW, + theBoundingRect.lr().y, + true); + + return true; +} + +bool ossimQuadTreeWarpNode::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* ul_x = kwl.find(prefix, ossimKeywordNames::UL_X_KW); + const char* ul_y = kwl.find(prefix, ossimKeywordNames::UL_Y_KW); + const char* lr_x = kwl.find(prefix, ossimKeywordNames::LR_X_KW); + const char* lr_y = kwl.find(prefix, ossimKeywordNames::LR_Y_KW); + + if(ul_x&&ul_y&&lr_x&&lr_y) + { + theBoundingRect = ossimDrect(ossimString(ul_x).toDouble(), + ossimString(ul_y).toDouble(), + ossimString(lr_x).toDouble(), + ossimString(lr_y).toDouble()); + return true; + } + + return false; +} + + +ossimQuadTreeWarp::ossimQuadTreeWarp(const ossimQuadTreeWarp& rhs) + :ossim2dTo2dTransform(), + theWarpEnabledFlag(true), + theTree(NULL) +{ + ossimKeywordlist kwl; + + rhs.saveState(kwl); + + loadState(kwl); +} + + +void ossimQuadTreeWarp::create(const ossimDrect& boundingRect, + const ossimDpt& ulShift, + const ossimDpt& urShift, + const ossimDpt& lrShift, + const ossimDpt& llShift) +{ + clear(); + + theTree = new ossimQuadTreeWarpNode(boundingRect); + + ossimQuadTreeWarpVertex* ul = new ossimQuadTreeWarpVertex(boundingRect.ul(), + ulShift); + ossimQuadTreeWarpVertex* ur = new ossimQuadTreeWarpVertex(boundingRect.ur(), + urShift); + ossimQuadTreeWarpVertex* lr = new ossimQuadTreeWarpVertex(boundingRect.lr(), + lrShift); + ossimQuadTreeWarpVertex* ll = new ossimQuadTreeWarpVertex(boundingRect.ll(), + llShift); + ul->addSharedNode(theTree); + ur->addSharedNode(theTree); + lr->addSharedNode(theTree); + ll->addSharedNode(theTree); + + theVertexList.push_back(ul); + theVertexList.push_back(ur); + theVertexList.push_back(lr); + theVertexList.push_back(ll); + + theTree->theUlVertex = ul; + theTree->theUrVertex = ur; + theTree->theLrVertex = lr; + theTree->theLlVertex = ll; + +} + +void ossimQuadTreeWarp::printVertices(std::ostream& out)const +{ + for(ossim_uint32 i = 0; i < theVertexList.size();++i) + { + out << *theVertexList[i] << "\n"; + } +} + +std::ostream& ossimQuadTreeWarp::print(std::ostream& out) const +{ + if(!isEmpty()) + { + out << "___________VERTEX LIST____________________\n"; + printVertices(out); + out << "___________TREE LIST____________________\n"; + + recursivePrint(out, theTree); + } + else + { + out << "<empty tree>\n"; + } + return out; +} + +ossimQuadTreeWarpVertex* ossimQuadTreeWarp::findClosestVertex(ossimDpt& position) +{ + if(position.hasNans()) return (ossimQuadTreeWarpVertex*)NULL; + + double dist = 1.0/DBL_EPSILON; + ossimQuadTreeWarpVertex* result = (ossimQuadTreeWarpVertex*)NULL; + for(ossim_uint32 i = 0; i < theVertexList.size(); ++i) + { + double d = (position-theVertexList[i]->thePosition).length(); + if( d < dist) + { + result = theVertexList[i]; + dist = d; + } + } + + return result; +// ossimQuadTreeWarpNode* node = findNode(position); + +// if(node&&node->hasValidVertices()) +// { +// double ulDist = (position-node->theUlVertex->thePosition).length(); +// double urDist = (position-node->theUrVertex->thePosition).length(); +// double lrDist = (position-node->theLrVertex->thePosition).length(); +// double llDist = (position-node->theLlVertex->thePosition).length(); + +// double minDist = std::min(ulDist, std::min(urDist, std::min(lrDist, llDist))); + +// if(minDist == ulDist) +// { +// return node->theUlVertex; +// } +// else if(minDist == urDist) +// { +// return node->theUrVertex; +// } +// else if(minDist == lrDist) +// { +// return node->theLrVertex; +// } +// else if(minDist == llDist) +// { +// return node->theLlVertex; +// } +// } + +// return ((ossimQuadTreeWarpVertex*)NULL); +} + + +ossimQuadTreeWarpVertex* ossimQuadTreeWarp::findVertex(const ossimDpt& position) +{ + ossim_uint32 i = 0; + ossimQuadTreeWarpVertex* result = (ossimQuadTreeWarpVertex*)NULL; + ossimQuadTreeWarpNode* currentNode = theTree; + + if((currentNode)&& + (currentNode->theBoundingRect.pointWithin(position))) + { + while((currentNode)&& + (!currentNode->isLeaf())) + { + for(i = 0; i < currentNode->theChildren.size(); ++i) + { + if(currentNode->theChildren[i]->theBoundingRect.pointWithin(position)) + { + currentNode = currentNode->theChildren[i]; + break; + } + } + } + + if(currentNode&¤tNode->hasValidVertices()) + { + if(currentNode->theUlVertex->thePosition == position) + { + result = currentNode->theUlVertex; + } + else if(currentNode->theUrVertex->thePosition == position) + { + result = currentNode->theUrVertex; + } + else if(currentNode->theLrVertex->thePosition == position) + { + result = currentNode->theLrVertex; + } + else if(currentNode->theLlVertex->thePosition == position) + { + result = currentNode->theLlVertex; + } + } + + } + + return result; +} + +ossimQuadTreeWarpVertex* ossimQuadTreeWarp::getVertex(const ossimDpt& position) +{ + std::vector<ossimQuadTreeWarpVertex*>::iterator iter = theVertexList.begin(); + + while(iter != theVertexList.end()) + { + if(position == (*iter)->getPosition()) + { + return (*iter); + } + ++iter; + } + + return (ossimQuadTreeWarpVertex*)NULL; +} + +void ossimQuadTreeWarp::clear() +{ + if(theTree) + { + recursiveDelete(theTree); + theTree = NULL; + } + + for(ossim_uint32 i = 0; i < theVertexList.size(); ++i) + { + delete theVertexList[i]; + } + + theVertexList.clear(); +} + +void ossimQuadTreeWarp::forward(const ossimDpt& pt, + ossimDpt& result)const +{ + if(theWarpEnabledFlag) + { + ossimDpt shift; + + getShift(shift, + pt); + + result = pt + shift; + } + else + { + result = pt; + } +} + +void ossimQuadTreeWarp::forward(ossimDpt& pt)const +{ + if(theWarpEnabledFlag) + { + ossimDpt shift; + + getShift(shift, + pt); + + pt += shift; + } +} + +void ossimQuadTreeWarp::getShift(ossimDpt& result, + const ossimDpt& pt)const +{ + getShift(result, + findNode(pt), + pt); +} + +void ossimQuadTreeWarp::split(const ossimDpt& point, + double splitHoriCoefficient, + double splitVertCoefficient) +{ + ossimQuadTreeWarpNode* node = findNode(point); + + if(node) + { + if(splitHoriCoefficient == 0.0) + { + splitHoriCoefficient = (point.x - node->theBoundingRect.ul().x)/ + node->theBoundingRect.width(); + } + if(splitVertCoefficient == 0.0) + { + splitVertCoefficient = (point.y - node->theBoundingRect.ul().y)/ + node->theBoundingRect.height(); + } + split(node, + splitHoriCoefficient, + splitVertCoefficient); + } +} + + +void ossimQuadTreeWarp::split(ossimQuadTreeWarpNode* node, + double splitHoriCoefficient, + double splitVertCoefficient) +{ + if(!node) return; + + splitHoriCoefficient = splitHoriCoefficient>1?1:splitHoriCoefficient; + splitHoriCoefficient = splitHoriCoefficient<0?0:splitHoriCoefficient; + splitVertCoefficient = splitVertCoefficient>1?1:splitVertCoefficient; + splitVertCoefficient = splitVertCoefficient<0?0:splitVertCoefficient; + + if( ((splitHoriCoefficient == 0)&&(splitVertCoefficient == 0)) || + ((splitHoriCoefficient == 1)&&(splitVertCoefficient == 1))) + { + return; + } + + if(node->isLeaf()) + { + if(node->theBoundingRect.hasNans()) + { + ossimNotify(ossimNotifyLevel_WARN) << "WARNING: " << "ossimQuadTreeWarp::split, Node has nans for the rect and can't split\n"; + } + else + { + ossimDpt ul = node->theBoundingRect.ul(); + ossimDpt ur = node->theBoundingRect.ur(); + ossimDpt lr = node->theBoundingRect.lr(); + ossimDpt ll = node->theBoundingRect.lr(); + + + double xmid = ul.x + (ur.x - ul.x)*splitHoriCoefficient; + double ymid = ul.y + (ll.y - ul.y)*splitVertCoefficient; + + ossimDpt left(ul.x, ymid); + + ossimDpt right(ur.x, + ymid); + + ossimDpt top(xmid, + ul.y); + + ossimDpt bottom(xmid, + lr.y); + + + ossimDrect ulRect(ul.x, + ul.y, + xmid, + ymid); + + ossimDrect urRect(top.x, + top.y, + right.x, + right.y); + + ossimDrect lrRect(xmid, + ymid, + lr.x, + lr.y); + + ossimDrect llRect(left.x, + left.y, + bottom.x, + bottom.y); + + ossimQuadTreeWarpNode* ulNode=(ossimQuadTreeWarpNode*)NULL; + ossimQuadTreeWarpNode* urNode=(ossimQuadTreeWarpNode*)NULL; + ossimQuadTreeWarpNode* lrNode=(ossimQuadTreeWarpNode*)NULL; + ossimQuadTreeWarpNode* llNode=(ossimQuadTreeWarpNode*)NULL; + + getNewQuads(node, + ulRect, + urRect, + lrRect, + llRect, + ulNode, + urNode, + lrNode, + llNode); + + if(ulNode&&urNode&&lrNode&&llNode) + { + node->theChildren.push_back(ulNode); + node->theChildren.push_back(urNode); + node->theChildren.push_back(lrNode); + node->theChildren.push_back(llNode); + + // it's no longer a leaf so remove the vertices + // from the list + node->removeVertex(node->theUlVertex); + node->removeVertex(node->theUrVertex); + node->removeVertex(node->theLrVertex); + node->removeVertex(node->theLlVertex); + } + } + } + else + { + ossimNotify(ossimNotifyLevel_WARN) << "WARNING: " << "ossimQuadTreeWarp::split, can only split leaf nodes\n"; + } + + updateAllVericeLockFlags(); +} + +void ossimQuadTreeWarp::getNewQuads(ossimQuadTreeWarpNode* parent, + const ossimDrect& ul, + const ossimDrect& ur, + const ossimDrect& lr, + const ossimDrect& ll, + ossimQuadTreeWarpNode*& ulNode, + ossimQuadTreeWarpNode*& urNode, + ossimQuadTreeWarpNode*& lrNode, + ossimQuadTreeWarpNode*& llNode) +{ + ossimDpt midShift; + getShift(midShift, + parent, + ul.lr()); + + ossimQuadTreeWarpVertex* midV = new ossimQuadTreeWarpVertex(ul.lr(), + midShift); + + ulNode = new ossimQuadTreeWarpNode(ul, + parent); + urNode = new ossimQuadTreeWarpNode(ur, + parent); + lrNode = new ossimQuadTreeWarpNode(lr, + parent); + llNode = new ossimQuadTreeWarpNode(ll, + parent); + + midV->addSharedNode(ulNode); + midV->addSharedNode(urNode); + midV->addSharedNode(lrNode); + midV->addSharedNode(llNode); + + // get the shared vertices first. We will add ourself + // to the pointer list. when we construct + // the quad nodes. Note the mid point will be shared + // by all quads and will be marked as adjustable + // + ossimQuadTreeWarpVertex* ulSharedV = getVertex(ul.ul()); + ossimQuadTreeWarpVertex* urSharedV = getVertex(ur.ur()); + ossimQuadTreeWarpVertex* lrSharedV = getVertex(lr.lr()); + ossimQuadTreeWarpVertex* llSharedV = getVertex(ll.ll()); + + if(!ulSharedV|| + !urSharedV|| + !lrSharedV|| + !llSharedV) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL: " << "ossimQuadTreeWarp::split, can't locating shared vertices. This Shouldn't happen!!!\n"; + return; + } + + // we know that the midpoint is new and is shared by all quads + // so we have 2 more to check + ossimQuadTreeWarpVertex* topSharedV = getVertex(ul.ur()); + ossimQuadTreeWarpVertex* bottomSharedV = getVertex(lr.ll()); + + ossimQuadTreeWarpVertex* leftSharedV = getVertex(ul.ll()); + ossimQuadTreeWarpVertex* rightSharedV = getVertex(ur.lr()); + + ossimDpt tempShift; + + if(!topSharedV) + { + getShift(tempShift, parent, ul.ur()); + topSharedV = new ossimQuadTreeWarpVertex(ul.ur(), + tempShift); + theVertexList.push_back(topSharedV); + } + if(!bottomSharedV) + { + getShift(tempShift, parent, ll.lr()); + bottomSharedV = new ossimQuadTreeWarpVertex(ll.lr(), + tempShift); + + theVertexList.push_back(bottomSharedV); + } + if(!leftSharedV) + { + getShift(tempShift, parent, ul.ll()); + leftSharedV = new ossimQuadTreeWarpVertex(ul.ll(), + tempShift); + theVertexList.push_back(leftSharedV); + } + if(!rightSharedV) + { + getShift(tempShift, parent, ur.lr()); + rightSharedV = new ossimQuadTreeWarpVertex(ur.lr(), + tempShift); + theVertexList.push_back(rightSharedV); + } + theVertexList.push_back(midV); + + topSharedV->addSharedNode(ulNode); + topSharedV->addSharedNode(urNode); + + bottomSharedV->addSharedNode(llNode); + bottomSharedV->addSharedNode(lrNode); + leftSharedV->addSharedNode(ulNode); + leftSharedV->addSharedNode(llNode); + rightSharedV->addSharedNode(urNode); + rightSharedV->addSharedNode(lrNode); + + ulSharedV->addSharedNode(ulNode); + urSharedV->addSharedNode(urNode); + lrSharedV->addSharedNode(lrNode); + llSharedV->addSharedNode(llNode); + + ulNode->theUlVertex = ulSharedV; + ulNode->theUrVertex = topSharedV; + ulNode->theLrVertex = midV; + ulNode->theLlVertex = leftSharedV; + + urNode->theUlVertex = topSharedV; + urNode->theUrVertex = urSharedV; + urNode->theLrVertex = rightSharedV; + urNode->theLlVertex = midV; + + lrNode->theUlVertex = midV; + lrNode->theUrVertex = rightSharedV; + lrNode->theLrVertex = lrSharedV; + lrNode->theLlVertex = bottomSharedV; + + llNode->theUlVertex = leftSharedV; + llNode->theUrVertex = midV; + llNode->theLrVertex = bottomSharedV; + llNode->theLlVertex = llSharedV; +} + +void ossimQuadTreeWarp::getShift(ossimDpt& result, + const ossimQuadTreeWarpNode* node, + const ossimDpt& pt)const +{ + result.x = 0.0; + result.y = 0.0; + + if(!node) + { + return; + } + if(!node->isLeaf()) + { + return; + } + + if(node->hasValidVertices()) + { + ossimDpt ulShift = node->theUlVertex->getDelta(); + ossimDpt urShift = node->theUrVertex->getDelta(); + ossimDpt lrShift = node->theLrVertex->getDelta(); + ossimDpt llShift = node->theLlVertex->getDelta(); + + ossimDpt ul = node->theBoundingRect.ul(); + ossimDpt ur = node->theBoundingRect.ur(); + ossimDpt ll = node->theBoundingRect.ll(); + + double horizontalPercent = fabs((pt.x-ul.x))/ + (ur.x-ul.x); + + double verticalPercent = fabs((pt.y - ul.y))/ + (ll.y-ul.y); + + ossimDpt upper = ulShift + (urShift - ulShift)*horizontalPercent; + ossimDpt lower = llShift + (lrShift - llShift)*horizontalPercent; + + result = upper + (lower - upper)*verticalPercent; + } + else + { + ossimNotify(ossimNotifyLevel_WARN) << "WARNING: ossimQuadTreeWarp::getShift, " << "Node does not have valid vertices in ossimQuadTreeWarp::getShift\n"; + } +} + +void ossimQuadTreeWarp::pruneTree(ossimQuadTreeWarpNode* node) +{ + if(node&& + !node->isLeaf()) + { + ossimQuadTreeWarpVertex* ulV = getVertex(node->theBoundingRect.ul()); + ossimQuadTreeWarpVertex* urV = getVertex(node->theBoundingRect.ur()); + ossimQuadTreeWarpVertex* lrV = getVertex(node->theBoundingRect.lr()); + ossimQuadTreeWarpVertex* llV = getVertex(node->theBoundingRect.ll()); + + recursivePruneTree(node); + + if(ulV&&urV&&lrV&&llV) + { + node->theUlVertex = ulV; + node->theUrVertex = urV; + node->theLrVertex = lrV; + node->theLlVertex = llV; + + ulV->addSharedNode(node); + urV->addSharedNode(node); + lrV->addSharedNode(node); + llV->addSharedNode(node); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) << "WARNING: ossimQuadTreeWarp::pruneTree, invlaid vertex find\n"; + } + pruneSharedVertices(); + updateAllVericeLockFlags(); + } +} + +void ossimQuadTreeWarp::recursivePruneTree(ossimQuadTreeWarpNode* node) +{ + if(!node||node->isLeaf()) return; + + for(ossim_uint32 i = 0; i < node->theChildren.size(); ++i) + { + recursivePruneTree(node->theChildren[i]); + delete node->theChildren[i]; + node->theChildren[i] = NULL; + } + node->theChildren.clear(); +} + + +ossimQuadTreeWarpNode* ossimQuadTreeWarp::findNode(const ossimDpt& pt) +{ + if((!pt.hasNans())&&(!isEmpty())) + { + if(theTree->theBoundingRect.pointWithin(pt)) + { + return findNode(theTree, + pt); + } + } + + return (ossimQuadTreeWarpNode*)NULL; +} + +const ossimQuadTreeWarpNode* ossimQuadTreeWarp::findNode(const ossimDpt& pt)const +{ + if((!pt.hasNans())&&(!isEmpty())) + { + if(theTree->theBoundingRect.pointWithin(pt)) + { + return findNode(theTree, + pt); + } + } + + return (const ossimQuadTreeWarpNode*)NULL; +} + +ossimQuadTreeWarpNode* ossimQuadTreeWarp::findNode(ossimQuadTreeWarpNode* node, + const ossimDpt& pt) +{ + ossimQuadTreeWarpNode* result = (ossimQuadTreeWarpNode*)NULL; + + if(!node) + { + return result; + } + if(node->isLeaf()) + { + result = node; + } + else + { + bool found = false; + for(ossim_uint32 i = 0; (i < node->theChildren.size())&&(!found); ++i) + { + if(node->theChildren[i]->theBoundingRect.pointWithin(pt)) + { + result = findNode(node->theChildren[i], + pt); + found = true; + } + } + } + + return result; +} + +void ossimQuadTreeWarp::findAllNodes(std::vector<ossimQuadTreeWarpNode*>& result, + const ossimDpt& pt) +{ + if((!pt.hasNans())&&(!isEmpty())) + { + if(theTree->theBoundingRect.pointWithin(pt)) + { + findAllNodes(result, + theTree, + pt); + } + } + +} + +void ossimQuadTreeWarp::findAllNodes(std::vector<const ossimQuadTreeWarpNode*>& result, + const ossimDpt& pt)const +{ + if(!pt.hasNans()&&(!isEmpty())) + { + if(theTree->theBoundingRect.pointWithin(pt)) + { + findAllNodes(result, + theTree, + pt); + } + } + +} + +const ossimQuadTreeWarpNode* ossimQuadTreeWarp::findNode(const ossimQuadTreeWarpNode* node, + const ossimDpt& pt)const +{ + const ossimQuadTreeWarpNode* result = (const ossimQuadTreeWarpNode*)NULL; + + if(!node) + { + return result; + } + if(node->isLeaf()) + { + result = node; + } + else + { + bool found = false; + for(ossim_uint32 i = 0; (i < node->theChildren.size())&&(!found); ++i) + { + if(node->theChildren[i]->theBoundingRect.pointWithin(pt)) + { + result = findNode(node->theChildren[i], + pt); + found = true; + } + } + } + + return result; +} + +void ossimQuadTreeWarp::findAllNodes(std::vector<ossimQuadTreeWarpNode*>& result, + ossimQuadTreeWarpNode* node, + const ossimDpt& pt) +{ + if(node->isLeaf()) + { + result.push_back(node); + } + else + { + for(ossim_uint32 i = 0; + i < node->theChildren.size(); + ++i) + { + if(node->theChildren[i]->theBoundingRect.pointWithin(pt)) + { + findAllNodes(result, + node->theChildren[i], + pt); + } + } + } +} + +void ossimQuadTreeWarp::findAllNodes(std::vector<const ossimQuadTreeWarpNode*>& result, + ossimQuadTreeWarpNode* node, + const ossimDpt& pt)const +{ + if(!node) return; + if(node->isLeaf()) + { + result.push_back(node); + } + else + { + for(ossim_uint32 i = 0; + i < node->theChildren.size(); + ++i) + { + if(node->theChildren[i]->theBoundingRect.pointWithin(pt)) + { + findAllNodes(result, + node->theChildren[i], + pt); + } + } + } +} +void ossimQuadTreeWarp::pruneSharedVertices() +{ + std::vector<ossimQuadTreeWarpVertex*>::iterator iter = theVertexList.begin(); + + while(iter != theVertexList.end()) + { + if( !(*iter)->isShared()) + { + delete (*iter); + iter = theVertexList.erase(iter); + } + else + { + ++iter; + } + } +} + +void ossimQuadTreeWarp::removeSharedVertex(ossimQuadTreeWarpVertex* v) +{ + std::vector<ossimQuadTreeWarpVertex*>::iterator iter = std::find(theVertexList.begin(), + theVertexList.end(), + v); + if(iter != theVertexList.end()) + { + delete (*iter); + iter = theVertexList.erase(iter); + } +} + + +void ossimQuadTreeWarp::recursivePrint(std::ostream& out, + ossimQuadTreeWarpNode* node)const +{ + if(node) + { + out << (*node) << "\n"; + } + + if(!node->isLeaf()) + { + for(ossim_uint32 i =0; i < node->theChildren.size();++i) + { + recursivePrint(out, node->theChildren[i]); + } + } +} + +void ossimQuadTreeWarp::recursiveDelete(ossimQuadTreeWarpNode* node) +{ + if(node->isLeaf()) + { + delete node; + } + else + { + for(ossim_uint32 i = 0; i < node->theChildren.size(); ++ i) + { + recursiveDelete(node->theChildren[i]); + } + + delete node; + } +} + +bool ossimQuadTreeWarp::isOnEdge(ossimQuadTreeWarpNode* node, + const ossimDpt& point)const +{ + if(!node) return false; + + if(node->theBoundingRect.pointWithin(point)) + { + double minx, maxx; + double miny, maxy; + node->theBoundingRect.getBounds(minx, miny, maxx, maxy); + + return ( (point.x == minx) || + (point.x == miny) || + (point.y == miny) || + (point.y == maxy) ); + } + + return false; +} + +bool ossimQuadTreeWarp::isOnPoint(ossimQuadTreeWarpNode* node, + const ossimDpt& point)const +{ + if(!node) return false; + + return ( (point == node->theBoundingRect.ul())|| + (point == node->theBoundingRect.ur())|| + (point == node->theBoundingRect.lr())|| + (point == node->theBoundingRect.ll()) ); +} + +void ossimQuadTreeWarp::updateLockFlag(ossimQuadTreeWarpVertex* v) +{ + std::vector<ossimQuadTreeWarpNode*> nodeList; + + findAllNodes(nodeList, + v->getPosition()); + + if(nodeList.size() != v->theSharedNodeList.size()) + { + if(isOnEdge(theTree, v->getPosition())) + { + v->theLockedFlag = false; + } + else + { + v->theLockedFlag = true; + } + } + else + { + v->theLockedFlag = false; + } + + // if the original was not locked + // then we need to make sure we change the delta + // along the locked edge so to produce no artifacts + // + if(v->theLockedFlag) + { + updateDelta(v); + } +} + +void ossimQuadTreeWarp::updateDelta(ossimQuadTreeWarpVertex* v) +{ + ossimQuadTreeWarpVertex* top = NULL; + ossimQuadTreeWarpVertex* bottom = NULL; + ossimQuadTreeWarpVertex* left = NULL; + ossimQuadTreeWarpVertex* right = NULL; + + std::vector<ossimQuadTreeWarpVertex*>::iterator iter = theVertexList.begin(); + + while(iter != theVertexList.end()) + { + ossimQuadTreeWarpVertex* testV = (*iter); + + // test along the vertical + if( (testV->thePosition.x == v->thePosition.x)&& + (testV->thePosition.y != v->thePosition.y)&& + (!testV->theLockedFlag)) + { + if(testV->thePosition.y > v->thePosition.y) + { + if(bottom) + { + if(bottom->thePosition.y > testV->thePosition.y) + { + bottom = testV; + } + } + else + { + bottom = testV; + } + } + else + { + if(top) + { + if(top->thePosition.y < testV->thePosition.y) + { + top = testV; + } + } + else + { + top = testV; + } + } + } + + if( (testV->thePosition.y == v->thePosition.y)&& + (testV->thePosition.x != v->thePosition.x)&& + (!testV->theLockedFlag)) + { + if(testV->thePosition.x > v->thePosition.x) + { + if(right) + { + if(right->thePosition.x > testV->thePosition.x) + { + right = testV; + } + } + else + { + right = testV; + } + } + else + { + if(left) + { + if(left->thePosition.x < testV->thePosition.x) + { + left = testV; + } + } + else + { + left = testV; + } + } + } + + ++iter; + } + ossimDpt topBottomDelta; + ossimDpt leftRightDelta; + + topBottomDelta.makeNan(); + leftRightDelta.makeNan(); + + if(top&&bottom) + { + double t = (v->thePosition.y - top->thePosition.y)/ + (bottom->thePosition.y - top->thePosition.y); + + topBottomDelta = top->theDelta + (bottom->theDelta-top->theDelta)*t; + v->theDelta = topBottomDelta; + + } + if(left&&right) + { + double t = (v->thePosition.x - left->thePosition.x)/ + (right->thePosition.x - left->thePosition.x); + + leftRightDelta = left->theDelta + (right->theDelta-left->theDelta)*t; + v->theDelta = leftRightDelta; + } + + if(top&&bottom&&left&&right) + { + v->theDelta = (topBottomDelta+leftRightDelta)*.5; + } +} + +void ossimQuadTreeWarp::updateAllVericeLockFlags() +{ + std::vector<ossimQuadTreeWarpVertex*>::iterator iter = theVertexList.begin(); + + while(iter != theVertexList.end()) + { + if(*iter) + { + updateLockFlag(*iter); + } + + ++iter; + } +} + +void ossimQuadTreeWarp::setToIdentity() +{ + for(ossim_uint32 i = 0; i < theVertexList.size(); ++i) + { + theVertexList[i]->theDelta = ossimDpt(0,0); + } +} + +bool ossimQuadTreeWarp::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + for(ossim_uint32 i = 0; i < theVertexList.size(); ++i) + { + ossimString newPrefix = ossimString(prefix)+ "v" + ossimString::toString(i) +"."; + + theVertexList[i]->saveState(kwl, newPrefix.c_str()); + } + + recursiveSave(theTree, kwl, prefix); + + return ossim2dTo2dTransform::saveState(kwl, prefix); +} + +bool ossimQuadTreeWarp::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + clear(); + ossimString newPrefix = ossimString(prefix); + + // load the vertices first + // + ossimString regExpression = ossimString("^(") + newPrefix + "v[0-9]+\\.)"; + + ossim_uint32 result = kwl.getNumberOfSubstringKeys(regExpression); + + ossim_uint32 numberOfMatches = 0; + ossim_uint32 count = 0; + while(numberOfMatches < result) + { + ossimString newPrefix = ossimString(prefix)+ossimString("v") + ossimString::toString(count) +"."; + + ossimQuadTreeWarpVertex* vert = new ossimQuadTreeWarpVertex; + + if(!vert->loadState(kwl, newPrefix.c_str())) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL: "<< " ossimQuadTreeWarp::loadState, invalid load on vertex\n"; + delete vert; + clear(); + + return false; + } + else + { + ++numberOfMatches; + theVertexList.push_back(vert); + } + + ++count; + } + + theTree = new ossimQuadTreeWarpNode; + + if(!theTree->loadState(kwl, prefix)) + { + clear(); + return false; + } + if(!recursiveLoad(theTree, kwl, prefix)) + { + clear(); + return false; + } + + if(!ossim2dTo2dTransform::loadState(kwl, prefix)) + { + clear(); + return false; + } + + return true; +} + +bool ossimQuadTreeWarp::recursiveSave(ossimQuadTreeWarpNode* node, + ossimKeywordlist& kwl, + const char* prefix)const +{ + if(!node) return false; + + if(!node->saveState(kwl, + prefix)) + { + return false; + } + + if(node->isLeaf()) + { + return true; + } + else + { + for(ossim_uint32 i = 0; i < node->theChildren.size(); ++ i) + { + ossimString newPrefix = ossimString(prefix) + ossimString::toString(i) + "."; + + if(!recursiveSave(node->theChildren[i], + kwl, + newPrefix.c_str())) + { + return false; + } + } + } + + return true; +} + +bool ossimQuadTreeWarp::recursiveLoad(ossimQuadTreeWarpNode* node, + const ossimKeywordlist& kwl, + const char* prefix) +{ + if(!node) return false; + ossimString copyPrefix = prefix; + + ossimQuadTreeWarpNode* ul = new ossimQuadTreeWarpNode; + ossimQuadTreeWarpNode* ur = new ossimQuadTreeWarpNode; + ossimQuadTreeWarpNode* lr = new ossimQuadTreeWarpNode; + ossimQuadTreeWarpNode* ll = new ossimQuadTreeWarpNode; + + ossimString ulPre = copyPrefix + "0."; + ossimString urPre = copyPrefix + "1."; + ossimString lrPre = copyPrefix + "2."; + ossimString llPre = copyPrefix + "3."; + + if(ul->loadState(kwl, + ulPre.c_str())) + { + ul->theParent = node; + node->theChildren.push_back(ul); + recursiveLoad(ul, + kwl, + ulPre.c_str()); + } + else + { + delete ul; + ul = NULL; + } + + if(ur->loadState(kwl, + urPre.c_str())) + { + ur->theParent = node; + node->theChildren.push_back(ur); + recursiveLoad(ur, + kwl, + urPre.c_str()); + } + else + { + delete ur; + ur = NULL; + } + + if(lr->loadState(kwl, + lrPre.c_str())) + { + lr->theParent = node; + node->theChildren.push_back(lr); + recursiveLoad(lr, + kwl, + lrPre.c_str()); + } + else + { + delete lr; + lr = NULL; + } + + if(ll->loadState(kwl, + llPre.c_str())) + { + ll->theParent = node; + node->theChildren.push_back(ll); + recursiveLoad(ll, + kwl, + llPre.c_str()); + } + else + { + delete ll; + ll = NULL; + } + + if(node->isLeaf()) + { + node->theUlVertex = getVertex(node->theBoundingRect.ul()); + node->theUrVertex = getVertex(node->theBoundingRect.ur()); + node->theLrVertex = getVertex(node->theBoundingRect.lr()); + node->theLlVertex = getVertex(node->theBoundingRect.ll()); + + if(node->hasValidVertices()) + { + node->theUlVertex->addSharedNode(node); + node->theUrVertex->addSharedNode(node); + node->theLrVertex->addSharedNode(node); + node->theLlVertex->addSharedNode(node); + } + else + { + return false; + } + } + + return true; +} diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimQuadTreeWarp.h b/Utilities/OSSIM/ossim_core/base/misc/ossimQuadTreeWarp.h new file mode 100644 index 0000000000..5ee14ae3fc --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimQuadTreeWarp.h @@ -0,0 +1,461 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// 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. +// +// 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. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimQuadTreeWarp.h,v 1.23 2003/12/22 18:48:32 dburken Exp $ +#ifndef ossimQuadTreeWarp_HEADER +#define ossimQuadTreeWarp_HEADER +#include "base/data_types/ossimDpt.h" +#include "base/data_types/ossimDrect.h" +#include "base/common/ossimConstants.h" +#include "base/data_types/ossimKeywordlist.h" +#include "base/common/ossimKeywordNames.h" +#include "base/misc/ossim2dTo2dTransform.h" +#include <vector> +#include <iostream> + +class OSSIMDLLEXPORT ossimQuadTreeWarpNode; + +class OSSIMDLLEXPORT ossimQuadTreeWarpVertex +{ +public: + friend ostream& operator<<(ostream& out, + const ossimQuadTreeWarpVertex& rhs) + { + out << "Position: " << rhs.thePosition << endl + << "Delta: " << rhs.theDelta << endl + << "Locked flag: " << rhs.theLockedFlag << endl + << "Shared nodes: " << rhs.theSharedNodeList.size(); + + return out; + } + + ossimQuadTreeWarpVertex(const ossimDpt& position=ossimDpt(0,0), + const ossimDpt& delta=ossimDpt(0,0)) + :thePosition(position), + theDelta(delta), + theLockedFlag(false) + { + } + ~ossimQuadTreeWarpVertex(); + + void setPosition(const ossimDpt& position) + { + thePosition = position; + } + void setDelta(const ossimDpt& delta) + { + theDelta = delta; + } + const ossimDpt& getDelta()const + { + return theDelta; + } + const ossimDpt& getPosition()const + { + return thePosition; + } + void addSharedNode(ossimQuadTreeWarpNode* node) + { + if(node) + { + theSharedNodeList.push_back(node); + } + } + void removeNode(ossimQuadTreeWarpNode* node); + bool isShared()const + { + return (theSharedNodeList.size() > 0); + } + + bool saveState(ossimKeywordlist& kwl, + const char* prefix)const; + + bool loadState(const ossimKeywordlist& kwl, + const char* prefix); + + vector<ossimQuadTreeWarpNode*> theSharedNodeList; + + ossimDpt thePosition; + ossimDpt theDelta; + bool theLockedFlag; + +}; + +class ossimQuadTreeWarpNode +{ +public: + friend std::ostream& operator <<(std::ostream& out, + const ossimQuadTreeWarpNode& rhs) + { + out << "Bounding rect: " << rhs.theBoundingRect << endl; + + if(rhs.theUlVertex) + { + out << "ulVertex:\n" << *rhs.theUlVertex<< endl; + } + if(rhs.theUrVertex) + { + out << "urVertex:\n" << *rhs.theUrVertex<< endl; + } + if(rhs.theLrVertex) + { + out << "lrVertex:\n" << *rhs.theLrVertex<< endl; + } + if(rhs.theLlVertex) + { + out << "llVertex:\n" << *rhs.theLlVertex; + } + + return out; + } + ~ossimQuadTreeWarpNode(); + ossimQuadTreeWarpNode() + : + theUlVertex(NULL), + theUrVertex(NULL), + theLrVertex(NULL), + theLlVertex(NULL), + theParent(NULL) + { + theBoundingRect.makeNan(); + } + + ossimQuadTreeWarpNode(const ossimDrect& bounds, + ossimQuadTreeWarpNode* parent=NULL, + ossimQuadTreeWarpVertex* ulVertex=(ossimQuadTreeWarpVertex*)NULL, + ossimQuadTreeWarpVertex* urVertex=(ossimQuadTreeWarpVertex*)NULL, + ossimQuadTreeWarpVertex* lrVertex=(ossimQuadTreeWarpVertex*)NULL, + ossimQuadTreeWarpVertex* llVertex=(ossimQuadTreeWarpVertex*)NULL) + : theBoundingRect(bounds), + theUlVertex(ulVertex), + theUrVertex(urVertex), + theLrVertex(lrVertex), + theLlVertex(llVertex), + theParent(parent) + { + } + + bool hasValidVertices()const + { + return (theUlVertex&&theUrVertex&&theLrVertex&&theLlVertex); + } + + void removeVertex(ossimQuadTreeWarpVertex* v) + { + if(!v) return; + + if(theUlVertex == v) + { + theUlVertex = NULL; + v->removeNode(this); + } + if(theUrVertex == v) + { + theUrVertex = NULL; + v->removeNode(this); + } + if(theLrVertex == v) + { + theLrVertex = NULL; + v->removeNode(this); + } + if(theLlVertex == v) + { + theLlVertex = NULL; + v->removeNode(this); + } + + } + void removeVertices() + { + removeVertex(theUlVertex); + removeVertex(theUrVertex); + removeVertex(theLrVertex); + removeVertex(theLlVertex); + } + + bool isLeaf()const + { + return (theChildren.size() == 0); + } + void clear() + { + theBoundingRect.makeNan(); + theChildren.clear(); + theParent = NULL; + removeVertex(theUlVertex); + removeVertex(theUrVertex); + removeVertex(theLrVertex); + removeVertex(theLlVertex); + } + void removeChild(ossimQuadTreeWarpNode* node); + bool saveState(ossimKeywordlist& kwl, + const char* prefix = 0)const; + + bool loadState(const ossimKeywordlist& kwl, + const char* prefix = 0); + + ossimDrect theBoundingRect; + ossimQuadTreeWarpVertex* theUlVertex; + ossimQuadTreeWarpVertex* theUrVertex; + ossimQuadTreeWarpVertex* theLrVertex; + ossimQuadTreeWarpVertex* theLlVertex; + ossimQuadTreeWarpNode* theParent; + + vector<ossimQuadTreeWarpNode*> theChildren; +}; + +class ossimQuadTreeWarp : public ossim2dTo2dTransform +{ +public: + friend std::ostream& operator<<(std::ostream& out, + const ossimQuadTreeWarp& rhs) + { + rhs.print(out); + + return out; + } + + ossimQuadTreeWarp() + :theTree(NULL) + { + } + + ossimQuadTreeWarp(const ossimDrect& boundingRect, + const ossimDpt& ulShift=ossimDpt(0,0), + const ossimDpt& urShift=ossimDpt(0,0), + const ossimDpt& lrShift=ossimDpt(0,0), + const ossimDpt& llShift=ossimDpt(0,0)) + :theTree(NULL) + { + create(boundingRect, ulShift, urShift, lrShift, llShift); + } + + ossimQuadTreeWarp::ossimQuadTreeWarp(const ossimQuadTreeWarp& rhs); + virtual ossimObject* dup()const + { + return new ossimQuadTreeWarp(*this); + } + + virtual ~ossimQuadTreeWarp() + { + clear(); + } + + virtual ossimDpt getOrigin()const + { + if(!isEmpty()) + { + if(!theTree->theBoundingRect.hasNans()) + { + return theTree->theBoundingRect.midPoint(); + } + + } + + return ossimDpt(0,0); + } + + void create(const ossimDrect& boundingRect, + const ossimDpt& ulShift=ossimDpt(0,0), + const ossimDpt& urShift=ossimDpt(0,0), + const ossimDpt& lrShift=ossimDpt(0,0), + const ossimDpt& llShift=ossimDpt(0,0)); + + /*! + * Will warp the passed in point and placed the warped value in result + */ + virtual void forward(const ossimDpt& pt, + ossimDpt& result)const; + /*! + * Will warp the passed in point and overwrite it + */ + virtual void forward(ossimDpt& pt)const; + +// void inverse(const ossimDpt& input, +// ossimDpt& output) const; + + virtual std::ostream& print(std::ostream& out) const; + virtual void printVertices(std::ostream& out)const; + + ossimQuadTreeWarpNode* getRoot() + { + return theTree; + } + const ossimQuadTreeWarpNode* getRoot()const + { + return theTree; + } + + bool isEmpty()const + { + return (theTree==NULL); + } + + ossimQuadTreeWarpVertex* findClosestVertex(ossimDpt& position); + + /*! + * This method will go through the tree and try to locate the + * vertex. This is faster sine the tree is sorted. Use + * the getVertex to just search the internal shared vertex list. + */ + ossimQuadTreeWarpVertex* findVertex(const ossimDpt& position); + + /*! + * Searches the shared vetex list. This will not go through the tree. + * this is needed for load states to perform correctly. + */ + ossimQuadTreeWarpVertex* getVertex(const ossimDpt& position); + + /*! + * Will get the shift or delta value for the passed in pt. + */ + void getShift(ossimDpt& result, + const ossimDpt& pt)const; + + /*! + * The initial passed in node must not be a leaf. It will + * turn the passed in node into a leaf by recursively + * pruning its children. + */ + void pruneTree(ossimQuadTreeWarpNode* node); + + // Search methods + ossimQuadTreeWarpNode* findNode(const ossimDpt& pt); + + const ossimQuadTreeWarpNode* findNode(const ossimDpt& pt)const; + + /*! + * Will get the shift or delta value for the passed in pt. + */ + ossimDpt getShift(const ossimDpt& pt)const + { + ossimDpt result; + + getShift(result, pt); + + return result; + } + + + void clear(); + + void split(const ossimDpt& point, + double splitHoriCoefficient=0.0, + double splitVertCoefficient=0.0); + + /*! + * The passed in node is suppose to be a leaf node. + * it splits the leaf node horizontally and vertically + * by the passed in percentage. Use find node to + * find the leaf node of a given point + */ + void split(ossimQuadTreeWarpNode* node, + double splitHoriCoefficient=.5, + double splitVertCoefficient=.5); + + + const ossimQuadTreeWarpNode* findNode(const ossimQuadTreeWarpNode* node, + const ossimDpt& pt)const; + + ossimQuadTreeWarpNode* findNode(ossimQuadTreeWarpNode* node, + const ossimDpt& pt); + + void findAllNodes(std::vector<ossimQuadTreeWarpNode*>& result, + const ossimDpt& pt); + void findAllNodes(std::vector<const ossimQuadTreeWarpNode*>& result, + const ossimDpt& pt)const; + void findAllNodes(std::vector<ossimQuadTreeWarpNode*>& result, + ossimQuadTreeWarpNode* node, + const ossimDpt& pt); + void findAllNodes(std::vector<const ossimQuadTreeWarpNode*>& result, + ossimQuadTreeWarpNode* node, + const ossimDpt& pt)const; + + bool isOnEdge(ossimQuadTreeWarpNode* node, + const ossimDpt& point)const; + + bool isOnPoint(ossimQuadTreeWarpNode* node, + const ossimDpt& point)const; + + void updateAllVericeLockFlags(); + + const std::vector<ossimQuadTreeWarpVertex*>& getVertices()const + { + return theVertexList; + } + void setWarpEnabledFlag(bool flag) + { + theWarpEnabledFlag = flag; + } + void setToIdentity(); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + +protected: + bool theWarpEnabledFlag; + ossimQuadTreeWarpNode* theTree; + std::vector<ossimQuadTreeWarpVertex*> theVertexList; + + void getShift(ossimDpt& result, + const ossimQuadTreeWarpNode* node, + const ossimDpt& pt)const; + + void recursivePruneTree(ossimQuadTreeWarpNode* node); + void pruneSharedVertices(); + void removeSharedVertex(ossimQuadTreeWarpVertex* v); + + void recursivePrint(std::ostream& out, + ossimQuadTreeWarpNode* node)const; + void recursiveDelete(ossimQuadTreeWarpNode* node); + + void getNewQuads(ossimQuadTreeWarpNode* parent, + const ossimDrect& ul, + const ossimDrect& ur, + const ossimDrect& lr, + const ossimDrect& ll, + ossimQuadTreeWarpNode*& ulNode, + ossimQuadTreeWarpNode*& urNode, + ossimQuadTreeWarpNode*& lrNode, + ossimQuadTreeWarpNode*& llNode); + + void updateLockFlag(ossimQuadTreeWarpVertex* v); + void updateDelta(ossimQuadTreeWarpVertex* v); + + bool recursiveSave(ossimQuadTreeWarpNode* node, + ossimKeywordlist& kwl, + const char* prefix)const; + + bool recursiveLoad(ossimQuadTreeWarpNode* node, + const ossimKeywordlist& kwl, + const char* prefix); + +// bool resetAllSharedLists(); + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimRectanglePartitioner.cpp b/Utilities/OSSIM/ossim_core/base/misc/ossimRectanglePartitioner.cpp new file mode 100644 index 0000000000..6620c69e59 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimRectanglePartitioner.cpp @@ -0,0 +1,248 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2004 David Burken, all rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// Utility class to partition up a rectangle. +// +// $Id: ossimRectanglePartitioner.cpp,v 1.3 2005/01/28 21:12:27 dburken Exp $ +//---------------------------------------------------------------------------- + +#include <base/misc/ossimRectanglePartitioner.h> +#include <base/data_types/ossimIrect.h> +#include <base/context/ossimNotifyContext.h> +#include <base/common/ossimTrace.h> +using namespace std; + +static ossimTrace traceDebug("ossimRectanglePartitioner:degug"); + +ossimRectanglePartitioner::ossimRectanglePartitioner() +{ +} + +ossimRectanglePartitioner::~ossimRectanglePartitioner() +{ +} + +void ossimRectanglePartitioner::binaryPartition( + const ossimIrect& inputRectangle, + vector<ossimIrect>& result, + ossim_uint64 maxSizeInBytes, + ossim_uint32 bands, + ossim_uint32 bytesPerPixel, + ossim_uint32 internalOverlapPixels) const +{ + // Clear the result rect for starters. + result.clear(); + + // Some sanity checks. + if (maxSizeInBytes == 0) + { + ossimNotify(ossimNotifyLevel_WARN) + << "Waning: 0 passed for max size in bytes. Returning..." + << endl; + return; + } + if (bands == 0) + { + ossimNotify(ossimNotifyLevel_WARN) + << "Waning: 0 passed for number of bands. Returning..." + << endl; + return; + } + if (bytesPerPixel == 0) + { + ossimNotify(ossimNotifyLevel_WARN) + << "Waning: 0 passed for bytes per pixel. Returning..." + << endl; + return; + } + if (inputRectangle.hasNans()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "Waning: Input rectangle has nans in it! Returning..." + << endl; + return; + } + if ( (maxSizeInBytes / (bands*bytesPerPixel)) < 4) + { + // Come on now you have to have at least four pixels. + ossimNotify(ossimNotifyLevel_WARN) + << "Waning: Max size in bytes too small. Returning..." + << endl; + return; + } + // End of sanity checks... + + // Check the size... We could already be there. + if (getSize(inputRectangle, bands, bytesPerPixel) <= maxSizeInBytes) + { + result.push_back(inputRectangle); + + if (traceDebug()) + { + trace(inputRectangle, result, maxSizeInBytes, bands, bytesPerPixel); + } + + return; + } + + // OK, find the rectangle size that gets that will fit the max size. + ossimIrect tileRect = inputRectangle; + + splitUntilLessThanMax(tileRect, + maxSizeInBytes, + bands, + bytesPerPixel, + internalOverlapPixels); + + ossim_int32 input_width = static_cast<ossim_int32>(inputRectangle.width()); + ossim_int32 input_height = static_cast<ossim_int32>(inputRectangle.height()); + + ossim_int32 tile_width = static_cast<ossim_int32>(tileRect.width()); + ossim_int32 tile_height = static_cast<ossim_int32>(tileRect.height()); + + ossim_int32 tiles_wide = (input_width % tile_width) ? + ( (input_width/tile_width)+1) : (input_width/tile_width); + ossim_int32 tiles_high = (input_height % tile_height) ? + ( (input_height/tile_height)+1) : (input_height/tile_height); + + ossim_int32 y_start = inputRectangle.ul().y; + ossim_int32 y_stop = y_start + tile_height - 1 + internalOverlapPixels; + + for (ossim_int32 y = 0; y < tiles_high; ++y) + { + // Clip to bottom if needed. + if (y_stop > inputRectangle.lr().y) + { + y_stop = inputRectangle.lr().y; + } + + ossim_int32 x_start = inputRectangle.ul().x; + ossim_int32 x_stop = x_start + tile_width - 1 + internalOverlapPixels; + + for (ossim_int32 x = 0; x < tiles_wide; ++x) + { + // Clip to right edge is needed. + if (x_stop > inputRectangle.lr().x) + { + x_stop = inputRectangle.lr().x; + } + + ossimIrect r(x_start, y_start, x_stop, y_stop); + + // Add it to the result. + result.push_back(r); + + if( 0 == x ) + { + x_start += tile_width - internalOverlapPixels; + } + else + { + x_start += tile_width; + } + x_stop += tile_width; + + } // End of tiles_wide loop. + + if( 0 == y ) + { + y_start += tile_height - internalOverlapPixels; + } + else + { + y_start += tile_height; + } + y_stop += tile_height; + + } // End of tiles_high loop. + + if (traceDebug()) + { + trace(inputRectangle, result, maxSizeInBytes, bands, bytesPerPixel); + } +} + +void ossimRectanglePartitioner::splitUntilLessThanMax( + ossimIrect& rect, + ossim_uint64 maxSizeInBytes, + ossim_uint32 bands, + ossim_uint32 bytesPerPixel, + ossim_uint32 internalOverlapPixels) const +{ + do + { + splitRect(rect); + + } while ( getSize(rect, + bands, + bytesPerPixel, + internalOverlapPixels) > maxSizeInBytes ); +} + +void ossimRectanglePartitioner::splitRect(ossimIrect& rect) const +{ + ossim_int32 width = static_cast<ossim_int32>(rect.width()); + ossim_int32 height = static_cast<ossim_int32>(rect.height()); + ossim_int32 new_width; + ossim_int32 new_height; + + if (height > width) + { + new_width = width; + new_height = (height % 2) ? ( (height/2) + 1 ) : (height/2); + } + else + { + new_width = (width % 2) ? ( (width/2) + 1) : (width/2); + new_height = height; + } + + rect = ossimIrect(0, 0, new_width-1, new_height-1); +} + +ossim_uint64 ossimRectanglePartitioner::getSize( + const ossimIrect& rect, + ossim_uint32 bands, + ossim_uint32 bytesPerPixel, + ossim_uint32 internalOverlapPixels) const +{ + return( ( rect.width() + 2 * internalOverlapPixels ) * + ( rect.height() + 2 * internalOverlapPixels ) * + bands * bytesPerPixel ); +} + +void ossimRectanglePartitioner::trace(const ossimIrect& r, + const std::vector<ossimIrect>& v, + ossim_uint64 maxSizeInBytes, + ossim_uint32 bands, + ossim_uint32 bytesPerPixel) const +{ + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimRectanglePartitioner DEBUG:" + << "\nInput rectangle: " << r + << "\nInput rectangle byte size: " << getSize(r, bands, bytesPerPixel) + << "\nTile max size in bytes: " << maxSizeInBytes + << "\nbands: " << bands + << "\nbytesPerPixel: " << bytesPerPixel + << "\nNumber of output tiles: " << v.size() + << "\nTiled rectangles:\n"; + + int index = 0; + vector<ossimIrect>::const_iterator i = v.begin(); + while(i != v.end()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "tile[" << index << "]: " << *i + << "\nsize in bytes: " << getSize(*i, bands, bytesPerPixel) + << endl; + ++i; + ++index; + } +} diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimRectanglePartitioner.h b/Utilities/OSSIM/ossim_core/base/misc/ossimRectanglePartitioner.h new file mode 100644 index 0000000000..585cc2c2a7 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimRectanglePartitioner.h @@ -0,0 +1,147 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2004 David Burken, all rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// Utility class to partition up a rectangle. +// +// $Id: ossimRectanglePartitioner.h,v 1.3 2005/01/28 21:12:27 dburken Exp $ +//---------------------------------------------------------------------------- +#ifndef ossimRectanglePartitioner_HEADER +#define ossimRectanglePartitioner_HEADER + +#include <base/common/ossimConstants.h> +#include <vector> + +class ossimIrect; + +/** + * class ossimRectanglePartitioner + * Utility class to partition up a rectangle. + */ +class OSSIMDLLEXPORT ossimRectanglePartitioner +{ +public: + + /** default construtor */ + ossimRectanglePartitioner(); + + /** destructor */ + ~ossimRectanglePartitioner(); + + /** + * Partitions the rectangle doing a binary split on the longest dimension + * until the total size is less than or equal to the "maxSizeInBytes". + * Initializes "result" with the resulting rectangles starting at the + * upper left corner. + * + * @param inputRectangle The source rectangle usually the bounding rectangle + * of a scene. + * + * @param result The vector of ossimIrects to hold the result. + * + * @param maxSizeInBytes Maximum size of the resulting rectangle partitions + * in bytes. + * + * @param bands The number of bands in the image. + * + * @param bytesPerPixel. The number of bytes per pixel for a single band. + * + * @param internalOverlapPixels Overlap in pixels for desired partitions. + * (default = 0) This is added to all four sides of the rectangle so + * + * @note The result rectangle passed in will be cleared for starters. + * + * @note Edge rectangles will be clipped to the inputRectangle. + */ + void binaryPartition(const ossimIrect& inputRectangle, + std::vector<ossimIrect>& result, + ossim_uint64 maxSizeInBytes, + ossim_uint32 bands, + ossim_uint32 bytesPerPixel, + ossim_uint32 internalOverlapPixels = 0) const; + +private: + + /** + * Recursively splits the input rectangle until the size is less than + * or equal to maxSizeInBytes. + * + * @param rect Input rectangle to split. + * + * @param maxSizeInBytes Maximum size of the resulting rectangle partitions + * in bytes. + * + * @param bands The number of bands in the image. + * + * @param bytesPerPixel. The number of bytes per pixel for a single band. + * + * @param internalOverlapPixels Overlap in pixels for desired partitions. + * (default = 0) + * + * @note Will split the longest dimension. If square will split in the + * lengthwise direction. + */ + void splitUntilLessThanMax(ossimIrect& rect, + ossim_uint64 maxSizeInBytes, + ossim_uint32 bands, + ossim_uint32 bytesPerPixel, + ossim_uint32 internalOverlapPixels = 0) const; + + /** + * Splits rectangle in half rounding up if needed. + * + * @param input Rectangle to split. + * + * @note output will be a zero base rect. + * + * @notes Will split the longest dimension. If square will split in the + * lengthwise direction. + */ + void splitRect(ossimIrect& rect) const; + + /** + * @param rect Rectangle to give size for in bytes. + * + * @param bands The number of bands in the image. + * + * @param bytesPerPixel. The number of bytes per pixel for a single band. + * + * @param internalOverlapPixels Overlap in pixels. + * (default = 0) + * + * @return size of rectangle in bytes. + */ + ossim_uint64 getSize(const ossimIrect& rect, + ossim_uint32 bands, + ossim_uint32 bytesPerPixel, + ossim_uint32 internalOverlapPixels = 0) const; + + /** + * Convenience trace method. + * + * @param r Input rectangle. + * + * @param v Vector of resulting partitioned rectangles. + * + * @param maxSizeInBytes Maximum size of the resulting rectangle partitions + * in bytes. + * + * @param bands The number of bands in the image. + * + * @param bytesPerPixel. The number of bytes per pixel for a single band. + */ + void trace(const ossimIrect& r, + const std::vector<ossimIrect>& v, + ossim_uint64 maxSizeInBytes, + ossim_uint32 bands, + ossim_uint32 bytesPerPixel) const; + +}; + +#endif /* End of "#ifndef ossimRectanglePartitioner_HEADER" */ diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimUnitConversionTool.cpp b/Utilities/OSSIM/ossim_core/base/misc/ossimUnitConversionTool.cpp new file mode 100644 index 0000000000..519a5e1449 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimUnitConversionTool.cpp @@ -0,0 +1,349 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimUnitConversionTool.cpp,v 1.12 2005/08/02 17:24:17 dburken Exp $ +#include <base/misc/ossimUnitConversionTool.h> +#include <base/data_types/ossimGpt.h> + +std::ostream& operator<<(std::ostream& out, + const ossimUnitConversionTool& data) +{ + out << setprecision(15) << setiosflags(ios::fixed) + << "Meters: " << data.getMeters() << endl + << "Feet: " << data.getFeet() << endl + << "U.S. Survey Feet: " << data.getUsSurveyFeet() << endl + << "Nautical miles: " << data.getNauticalMiles() << endl + << "Degrees: " << data.getDegrees() << endl + << "Minutes: " << data.getMinutes() << endl + << "Seconds: " << data.getSeconds() << endl; + + return out; +} + +ossimUnitConversionTool::ossimUnitConversionTool(double value, + ossimUnitType unitType) + : theValue(value), + theUnitType(unitType), + theOrigin() +{ +} + +ossimUnitConversionTool::ossimUnitConversionTool(const ossimGpt& origin, + double value, + ossimUnitType unitType) + : theValue(value), + theUnitType(unitType), + theOrigin(origin) +{ +} + +void ossimUnitConversionTool::setOrigin(const ossimGpt& gpt) +{ + theOrigin = gpt; +} + +ossimGpt ossimUnitConversionTool::getOrigin()const +{ + return theOrigin; +} + +void ossimUnitConversionTool::getOrigin(ossimGpt& result)const +{ + result = theOrigin; +} + +void ossimUnitConversionTool::setValue(double value, + ossimUnitType unitType) +{ + theValue = value; + theUnitType = unitType; +} + +double ossimUnitConversionTool::getValue(ossimUnitType unitType) const +{ + switch(unitType) + { + case OSSIM_METERS: + { + return getMeters(); + } + case OSSIM_RADIANS: + { + return getRadians(); + } + case OSSIM_DEGREES: + { + return getDegrees(); + } + case OSSIM_US_SURVEY_FEET: + { + return getUsSurveyFeet(); + } + case OSSIM_FEET: + { + return getFeet(); + } + case OSSIM_SECONDS: + { + return getSeconds(); + } + case OSSIM_MINUTES: + { + return getMinutes(); + } + case OSSIM_NAUTICAL_MILES: + { + return getNauticalMiles(); + } + case OSSIM_MILES: + { + return getMiles(); + } + default: + break; + } + + return OSSIM_DBL_NAN; +} + +void ossimUnitConversionTool::setMeters(double value) +{ + setValue(value, OSSIM_METERS); +} + +void ossimUnitConversionTool::setRadians(double value) +{ + setValue(value, OSSIM_RADIANS); +} + +void ossimUnitConversionTool::setDegrees(double value) +{ + setValue(value, OSSIM_DEGREES); +} + +void ossimUnitConversionTool::setMinutes(double value) +{ + setValue(value, OSSIM_MINUTES); +} + +void ossimUnitConversionTool::setSeconds(double value) +{ + setValue(value, OSSIM_SECONDS); +} + +void ossimUnitConversionTool::setUsSurveyFeet(double value) +{ + setValue(value, OSSIM_US_SURVEY_FEET); +} + +void ossimUnitConversionTool::setFeet(double value) +{ + setValue(value, OSSIM_FEET); +} + +void ossimUnitConversionTool::setNauticalMiles(double value) +{ + setValue(value, OSSIM_NAUTICAL_MILES); +} + +void ossimUnitConversionTool::setMiles(double value) +{ + setValue(value, OSSIM_MILES); +} + +void ossimUnitConversionTool::setMillimeters(double value) +{ + setValue(value, OSSIM_MILLIMETERS); +} + +void ossimUnitConversionTool::setMicrons(double value) +{ + setValue(value, OSSIM_MICRONS); +} + +double ossimUnitConversionTool::getMeters()const +{ + if(theUnitType == OSSIM_METERS) + { + return theValue; + } + + return computeMeters(); +} + +double ossimUnitConversionTool::getRadians()const +{ + if(theUnitType == OSSIM_RADIANS) + { + return theValue; + } + return getDegrees()*RAD_PER_DEG; +} + +double ossimUnitConversionTool::getDegrees()const +{ + switch (theUnitType) + { + case OSSIM_DEGREES: + { + return theValue; + } + case OSSIM_MINUTES: + { + return (theValue / 60.0); + } + case OSSIM_SECONDS: + { + return (theValue / 3600.0); + } + case OSSIM_RADIANS: + { + return (theValue * DEG_PER_RAD); + } + default: + break; + } + + ossimDpt pt = theOrigin.metersPerDegree(); + return (computeMeters() /((pt.x+pt.y)*.5)); +} + +double ossimUnitConversionTool::getMinutes()const +{ + if(theUnitType == OSSIM_MINUTES) + { + return theValue; + } + return (getDegrees()*60.0); +} + +double ossimUnitConversionTool::getSeconds()const +{ + if(theUnitType == OSSIM_SECONDS) + { + return theValue; + } + return (getDegrees()*3600.0); +} + +double ossimUnitConversionTool::getUsSurveyFeet()const +{ + if(theUnitType == OSSIM_US_SURVEY_FEET) + { + return theValue; + } + return (computeMeters()/US_METERS_PER_FT); +} + +double ossimUnitConversionTool::getFeet()const +{ + if(theUnitType == OSSIM_FEET) + { + return theValue; + } + return (computeMeters()*FT_PER_MTRS); +} + +double ossimUnitConversionTool::getNauticalMiles()const +{ + if(theUnitType == OSSIM_NAUTICAL_MILES) + { + return theValue; + } + + return (computeMeters()/(theOrigin.metersPerDegree().y/60.0)); +} + +double ossimUnitConversionTool::getMiles()const +{ + if(theUnitType == OSSIM_MILES) + { + return theValue; + } + return ((computeMeters()*FT_PER_MTRS)/FT_PER_MILE); +} + +double ossimUnitConversionTool::getMillimeters()const +{ + if(theUnitType == OSSIM_MILLIMETERS) + { + return theValue; + } + return ((computeMeters()*1e3)); +} + +double ossimUnitConversionTool::getMicrons()const +{ + if(theUnitType == OSSIM_MICRONS) + { + return theValue; + } + return ((computeMeters()*1e6)); +} + +double ossimUnitConversionTool::computeMeters()const +{ + switch(theUnitType) + { + case OSSIM_METERS: + { + return theValue; + break; + } + case OSSIM_RADIANS: + { + ossimDpt pt = theOrigin.metersPerDegree(); + return (theValue*DEG_PER_RAD)*((pt.x+pt.y)*.5); + } + case OSSIM_DEGREES: + { + ossimDpt pt = theOrigin.metersPerDegree(); + return theValue*((pt.x+pt.y)*.5); + } + case OSSIM_US_SURVEY_FEET: + { + return US_METERS_PER_FT*theValue; + } + case OSSIM_FEET: + { + return MTRS_PER_FT*theValue; + } + case OSSIM_SECONDS: + { + ossimDpt pt = theOrigin.metersPerDegree(); + return (theValue/3600.0)*((pt.x+pt.y)*.5); + } + case OSSIM_MINUTES: + { + ossimDpt pt = theOrigin.metersPerDegree(); + return (theValue/60.0)*((pt.x+pt.y)*.5); + } + case OSSIM_NAUTICAL_MILES: + { + return (theOrigin.metersPerDegree().y/60.0)*theValue; + } + case OSSIM_MILES: + { + return MTRS_PER_FT*FT_PER_MILE*theValue; + } + case OSSIM_MILLIMETERS: + { + return (theValue/(1e3)); + } + case OSSIM_MICRONS: + { + return (theValue/(1e6)); + } + default: + break; + } + + return OSSIM_DBL_NAN; +} diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimUnitConversionTool.h b/Utilities/OSSIM/ossim_core/base/misc/ossimUnitConversionTool.h new file mode 100644 index 0000000000..1eade17b0d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimUnitConversionTool.h @@ -0,0 +1,93 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimUnitConversionTool.h,v 1.13 2005/08/02 17:24:17 dburken Exp $ +#ifndef ossimUnitConversionTool_HEADER +#define ossimUnitConversionTool_HEADER +#include <iostream> +#include <base/common/ossimConstants.h> +#include <base/data_types/ossimGpt.h> + +class OSSIM_DLL ossimUnitConversionTool +{ +public: + friend std::ostream& operator<<(std::ostream& out, + const ossimUnitConversionTool& data); + + ossimUnitConversionTool(double value=1.0, + ossimUnitType unitType=OSSIM_METERS); + + ossimUnitConversionTool(const ossimGpt& origin, + double value, + ossimUnitType unitType=OSSIM_METERS); + + void setOrigin(const ossimGpt& gpt); + + ossimGpt getOrigin()const; + + void getOrigin(ossimGpt& result)const; + + void setValue(double value, ossimUnitType unitType=OSSIM_METERS); + + double getValue(ossimUnitType unitType=OSSIM_METERS) const; + + void setMeters(double value); + + void setRadians(double value); + + void setDegrees(double value); + + void setMinutes(double value); + + void setSeconds(double value); + + void setUsSurveyFeet(double value); + + void setFeet(double value); + + void setNauticalMiles(double value); + + void setMiles(double value); + + void setMillimeters(double value); + + void setMicrons(double value); + + double getMeters()const; + + double getRadians()const; + + double getDegrees()const; + + double getMinutes()const; + + double getSeconds()const; + + double getUsSurveyFeet()const; + + double getFeet()const; + + double getNauticalMiles()const; + + double getMiles()const; + + double getMillimeters()const; + + double getMicrons()const; + +protected: + double theValue; + ossimUnitType theUnitType; + ossimGpt theOrigin; + + double computeMeters()const; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimUsgsQuad.cpp b/Utilities/OSSIM/ossim_core/base/misc/ossimUsgsQuad.cpp new file mode 100644 index 0000000000..181f2f14f3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimUsgsQuad.cpp @@ -0,0 +1,730 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimUsgsQuad.cpp,v 1.7 2004/04/05 13:31:35 gpotts Exp $ +#include <sstream> +#include <iomanip> + +#include <base/misc/ossimUsgsQuad.h> +#include <base/data_types/datum/ossimDatum.h> +#include <base/common/ossimTrace.h> +#include <base/context/ossimNotifyContext.h> + +using namespace std; + +static const +double QUARTER_QUAD_SEG_SIZE_IN_DEGREES = 0.03125; // 3.75 minutes/60.0/2.0 +static const double QUARTER_QUAD_SIZE_IN_DEGREES = 0.0625; // 3.75 minutes/60.0 +static const double QUAD_SIZE_IN_DEGREES = 0.125; // 7.5 minutes/60 + + +//*** +// Static trace for debugging +//*** +static ossimTrace traceDebug("USGS_quad::debug"); + + +ossimUsgsQuad::ossimUsgsQuad(const ossimGpt& lrGpt) + : + theQuadLowerRightCorner(0.0, 0.0, 0.0, lrGpt.datum()), + theQuarterQuadLowerRightCorner(0.0, 0.0, 0.0, lrGpt.datum()) +// thePaddingInDegrees(0.0, 0.0), + +{ + const char* MODULE = "ImgOutput::quadBasename"; + + //*** + // NOTE: + // This method computes a file name from the lower right corner of the + // image. The format is derived from USGS Digital Raster Graphic(DRG) + // program for standardized data set names for DRG products. Due to + // customer requirements there is one deviation: The first digit of the + // name is converted to a letter with 1 being = A, 2 being = B, + // 3 being = C, .... + // This was done to allow the name to be used on a pc. + //*** + + const double QUAD_SIZE_IN_DEGREES = 0.125; + + ossimString baseString; + int tmpInt; + double tmpDbl; + char quadChar = 'A'; + char quadNum = '1'; + + ostringstream os; + os << setiosflags(ios::right) + << setiosflags(ios::fixed) + << setfill('0'); + + tmpInt = abs(static_cast<int>(lrGpt.lat)); // Cast away the fractional part. + os << tmpInt; // latitude + + //*** + // Get the quadrant charactor in the latitude direction. (A - H) + //*** + tmpDbl = fabs(lrGpt.lat) - (double)tmpInt; + quadChar += static_cast<int>(tmpDbl / QUAD_SIZE_IN_DEGREES); + + tmpInt = abs(static_cast<int>(lrGpt.lon)); // longitude + os << setw(3) << tmpInt; + + tmpDbl = fabs(lrGpt.lon) - (double)tmpInt; + + quadNum += static_cast<char>(tmpDbl / QUAD_SIZE_IN_DEGREES); + + os << quadChar << quadNum; + + double latFraction = (lrGpt.lat / QUAD_SIZE_IN_DEGREES) - + irint((lrGpt.lat) / QUAD_SIZE_IN_DEGREES); + double lonFraction = (lrGpt.lon / QUAD_SIZE_IN_DEGREES) - + irint((lrGpt.lon) / QUAD_SIZE_IN_DEGREES); + + // Black & White +// if(theRectsStandardFlag && +// theChipSource->radiometry().numberOfBands() == 1) +// { +// char quarterQuadChar = '4'; +// if (latFraction && lonFraction) +// { +// quarterQuadChar = '1'; +// } +// else if (latFraction && !lonFraction) +// { +// quarterQuadChar = '2'; +// } +// else if (!latFraction && lonFraction) +// { +// quarterQuadChar = '3'; +// } +// os << quarterQuadChar << ends; +// } +// // Color +// else if(theRectsStandardFlag && +// theChipSource->radiometry().numberOfBands() > 1) +// { +// char quarterQuadChar = '8'; +// if (latFraction && lonFraction) +// { +// quarterQuadChar = '5'; +// } +// else if (latFraction && !lonFraction) +// { +// quarterQuadChar = '6'; +// } +// else if (!latFraction && lonFraction) +// { +// quarterQuadChar = '7'; +// } +// os << quarterQuadChar << ends; +// } +// else +// { + char quarterQuadChar = 'D'; + if (latFraction && lonFraction) + { + quarterQuadChar = 'A'; + } + else if (latFraction && !lonFraction) + { + quarterQuadChar = 'B'; + } + else if (!latFraction && lonFraction) + { + quarterQuadChar = 'C'; + } + os << quarterQuadChar << ends; +// } + + + baseString = os.str().c_str(); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << " DEBUG: " << MODULE + << "\nbaseString: " << baseString << "\n"; + } + + setQuadName(baseString); +} + + +//*************************************************************************** +// USGS_quad::USGS_quad(const String& name) +//*************************************************************************** +ossimUsgsQuad::ossimUsgsQuad(const ossimString& name, + const ossimDatum* datum) +// double paddingInMeters) + : + theQuadLowerRightCorner(0.0, 0.0, 0.0, datum), + theQuarterQuadLowerRightCorner(0.0, 0.0, 0.0, datum) +// thePaddingInDegrees(0.0, 0.0), +{ + static const char MODULE[] = "ossimUsgsQuad::ossimUsgsQuad"; + + setQuadName(name); + if (!datum) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL: " << MODULE << "\n" + << "ossimDatum pointer passed in is null. Returning...\n"; + return; + } + + + //*** + // Initialize the padding. + //*** +// ossimGpt metersPerDegree = theQuadLowerRightCorner.metersPerDegree(); + +// thePaddingInDegrees.u = paddingInMeters / metersPerDegree.u; +// thePaddingInDegrees.v = paddingInMeters / metersPerDegree.v; + +} + +void ossimUsgsQuad::setQuadName(const ossimString& name) +{ + const char* MODULE = "ossimUsgsQuad::setQuadName"; + ossimString qqName = name; + + //*** + // Check the length of "name" to see if it's correct. + //*** + if (name.length() < 7) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL: " << MODULE << "\n" + << "Quarder quad name length incorrect.\n" + << "Name: " << name << "\n" + << "Expected length: 7 or 8 Name length: " << name.length() + << "\nExample of valid quad: 30089C6B\n" + << "Represents lower right corner of " + << "30 deg. 15 min. N., 89 deg. 37.5 min. W.\n" + << "Breakdown:\n" + << "30 = latitude on even degree boundary " + << "(Northern Hemisphere implied)\n" + << "089 = longitude on even degree boundary " + << "(Western Hemisphere implied)\n" + << "C = Third quad section in latitude direction\n" + << "6 = Sixth quad section in longitude direction\n" + << "B = Quarter quad segment within the quad\n" + << " (A=upper left, B=upper right, C=lower left, D=lower right)\n" + << "Quad size 7.5 minute square, quarter quad size 3.75 " + << "minute square.\n"; + + + return; + } + + qqName.upcase(); + + char latChars[3]; + char lonChars[4]; + char latQuad; + char lonQuad; +// char segment; + + //*** + // Get the latitude. + //*** + latChars[0] = qqName.c_str()[0]; + latChars[1] = qqName.c_str()[1]; + latChars[2] = '\0'; + + //*** + // Get the longitude. + //*** + lonChars[0] = qqName.c_str()[2]; + lonChars[1] = qqName.c_str()[3]; + lonChars[2] = qqName.c_str()[4]; + lonChars[3] = '\0'; + + //*** + // Get the latitude quad. + //*** + latQuad = qqName.c_str()[5]; + + //*** + // Get the longitude quad. + //*** + lonQuad = qqName.c_str()[6]; + + //*** + // Get the segment within the quad. + //*** + if (name.length() == 8) + { + theQuarterQuadSegment = qqName.c_str()[7]; + } + else + { + theQuarterQuadSegment = 'D'; + ossimNotify(ossimNotifyLevel_NOTICE) << MODULE << ":\n" + << "No quarter quad segment entered. Defaulting to D segment." + << "\n"; + } + + //*** + // Build up the lower right corner from the extracted parts. + //*** + + //*** + // Get the latitude and check the range. + //*** + double lat = atof(latChars); + if ( (lat < 0.0) || (lat > 90.0) ) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL: " << MODULE << "\n" + << "Latitude range error. Latitude extracted: " << lat + << "\nRange: 0 to 90\n"; + return; + } + + //*** + // Get the longitude and check the range. + //*** + double lon = atof(lonChars); + if ( (lon < 0.0) || (lon > 180) ) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL: " << MODULE << "\n" + << "Longitud range error. Longitude extracted: " << lon + << "\nRange: 0 to 180\n"; + return; + } + + //*** + // Get the latitude quad and add this to "lat". The quad are letters from + // A - H with A being on an even degree boundary, B being 7.5 minute up + // and so on. + //*** + double tmp = latQuad - 65; // Ascii decimal value for A = 65. + + if (tmp) + { + //*** + // Check the range. The are eight quads within one degree. + //*** + if (tmp > 7.0) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL:" << MODULE << "\n" + << "Latitude quad range error. Quad extracted: " << latQuad + << "\nRange: A to H\n"; + return; + } + + tmp *= 7.5; // Convert the quad to minutes. + + lat += tmp/60.0; // Conver minutes to degrees and add to "lat". + } + + //*** + // Get the longitude quad and add this to "lat". The quad are letters from + // A - H with A being on an even degree boundary, B being 7.5 minute up + // and so on. + //*** + tmp = lonQuad - 49; // Ascii decimal value for 1 = 49. + + if (tmp) + { + //*** + // Check the range. The are eight quads within one degree. + //*** + if (tmp > 7.0) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL:" << MODULE << "\n" + << "Longitude quad range error. Quad extracted: " << latQuad + << "\nRange: 1 to 8\n"; + return; + } + + tmp *= 7.5; // Convert the quad to minutes. + + lon += tmp/60.0; // Conver minutes to degrees and add to "lon". + } + + //*** + // Currently this naming convention assumes Northern and Western hemisphere. + //*** + lon = -lon; // Make negative for Western hemisphere. + + //*** + // Initialize "theQuadLowerRightCorner". + //*** + theQuadLowerRightCorner.lat = lat; + theQuadLowerRightCorner.lon = lon; + + //*** + // Get the segment and add to "lat" and "lon". + //*** + switch (theQuarterQuadSegment) + { + case 'A': + lat += QUARTER_QUAD_SIZE_IN_DEGREES; + lon -= QUARTER_QUAD_SIZE_IN_DEGREES; + break; + + case 'B': + lat += QUARTER_QUAD_SIZE_IN_DEGREES; + break; + + case 'C': + lon -= QUARTER_QUAD_SIZE_IN_DEGREES; + break; + + case 'D': + break; // At the corner of a quad so nothing to do here. + + default: + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL:" << MODULE << "\n" + << "Quarter quad segment range error.\n" + << "Quarter quad segment extracted: " << theQuarterQuadSegment + << "Range: A to D\n"; + return; + } + + //*** + // Initialize "theQuarterQuadLowerRightCorner". + //*** + theQuarterQuadLowerRightCorner.lat = lat; + theQuarterQuadLowerRightCorner.lon = lon; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG: " << MODULE << ", " + << qqName << " lower right quad corner: " + << theQuadLowerRightCorner << "\n" + << "Quarter quad segment: " << theQuarterQuadSegment << "\n" + << qqName << " lower right quarter quad corner: " + << theQuarterQuadLowerRightCorner << "\n"; + } + theName = qqName; +} + +void ossimUsgsQuad::getQuadList(vector<ossimUsgsQuad>& result, + const ossimGrect& rect) +{ + result.clear(); +// QUAD_SIZE_IN_DEGREES; + + ossimGpt point = rect.ul(); + + while(rect.pointWithin(point)) + { + while(rect.pointWithin(point)) + { + result.push_back(ossimUsgsQuad(point)); + + point.lond(point.lond()+QUAD_SIZE_IN_DEGREES); + } + point.lond(rect.ul().lond()); + point.latd(point.latd()-QUAD_SIZE_IN_DEGREES); + } +} + + +//*************************************************************************** +// ossimUsgsQuad::quarterQuadSegRect() +//*************************************************************************** +ossimGrect ossimUsgsQuad::quarterQuadSegRect(char seg) +{ + static const char MODULE[] = "ossimUsgsQuad::quarterQuadSegRect"; + + double startLat=0.0; + double startLon=0.0; + double stopLat=0.0; + double stopLon=0.0; + + //*** + // Get the segment and add to "lat" and "lon". + //*** + switch (seg) + { + case 'A': // Upper left segment of quarter quad. + startLat = theQuarterQuadLowerRightCorner.lat + + QUARTER_QUAD_SEG_SIZE_IN_DEGREES;// - +// thePaddingInDegrees.u; + + startLon = theQuarterQuadLowerRightCorner.lon - + QUARTER_QUAD_SIZE_IN_DEGREES;// - + //thePaddingInDegrees.v; + + stopLat = theQuarterQuadLowerRightCorner.lat + + QUARTER_QUAD_SIZE_IN_DEGREES;// + + //thePaddingInDegrees.u; + + stopLon = theQuarterQuadLowerRightCorner.lon - + QUARTER_QUAD_SEG_SIZE_IN_DEGREES; // + + //thePaddingInDegrees.v; + break; + + case 'B': // Upper right segment of the quarter quad. + startLat = theQuarterQuadLowerRightCorner.lat + + QUARTER_QUAD_SEG_SIZE_IN_DEGREES; //- +// thePaddingInDegrees.u; + + startLon = theQuarterQuadLowerRightCorner.lon - + QUARTER_QUAD_SEG_SIZE_IN_DEGREES;// - +// thePaddingInDegrees.v; + + stopLat = theQuarterQuadLowerRightCorner.lat + + QUARTER_QUAD_SIZE_IN_DEGREES;// + +// thePaddingInDegrees.u; + + stopLon = theQuarterQuadLowerRightCorner.lon;// + +// thePaddingInDegrees.v; + break; + + case 'C': // Lower left segment of the quarter quad. + startLat = theQuarterQuadLowerRightCorner.lat;// - +// thePaddingInDegrees.u; + + startLon = theQuarterQuadLowerRightCorner.lon - + QUARTER_QUAD_SIZE_IN_DEGREES;// - +// thePaddingInDegrees.v; + + stopLat = theQuarterQuadLowerRightCorner.lat + + QUARTER_QUAD_SEG_SIZE_IN_DEGREES;// + +// thePaddingInDegrees.u; + + stopLon = theQuarterQuadLowerRightCorner.lon - + QUARTER_QUAD_SEG_SIZE_IN_DEGREES;// + +// thePaddingInDegrees.v; + + break; + + case 'D': + startLat = theQuarterQuadLowerRightCorner.lat;// - +// thePaddingInDegrees.u; + + startLon = theQuarterQuadLowerRightCorner.lon - + QUARTER_QUAD_SEG_SIZE_IN_DEGREES;// - +// thePaddingInDegrees.v; + + stopLat = theQuarterQuadLowerRightCorner.lat + + QUARTER_QUAD_SEG_SIZE_IN_DEGREES;// + +// thePaddingInDegrees.u; + + stopLon = theQuarterQuadLowerRightCorner.lon;// + +// thePaddingInDegrees.v; + break; // At the corner of a quad so nothing to do here. + + default: + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL:" << MODULE << "\n" + << "Quarter quad segment range error.\n" + << "Quarter quad segment extracted: " << seg + << "Range: A to D\n"; + break; + } + + ossimGrect + rect(ossimGpt(startLat, + startLon, + theQuarterQuadLowerRightCorner.height(), + theQuarterQuadLowerRightCorner.datum()), + ossimGpt(stopLat, + stopLon, + theQuarterQuadLowerRightCorner.height(), + theQuarterQuadLowerRightCorner.datum())); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG: " << MODULE + << "\nQuarter quad segment " << seg << " rect: " << rect << "\n"; + } + + + return rect; +} + +//*************************************************************************** +// ossimUsgsQuad::quarterQuadRect() +//*************************************************************************** +ossimGrect ossimUsgsQuad::quarterQuadRect() const +{ + static const char MODULE[] = "ossimUsgsQuad::quarterQuadRect"; + + double startLat = theQuarterQuadLowerRightCorner.lat;// - +// thePaddingInDegrees.u; // SouthWest corner lat. + + double startLon = theQuarterQuadLowerRightCorner.lon - + QUARTER_QUAD_SIZE_IN_DEGREES;// - +// thePaddingInDegrees.v; // SouthWest corner lon. + + double stopLat = theQuarterQuadLowerRightCorner.lat + + QUARTER_QUAD_SIZE_IN_DEGREES;// + +// thePaddingInDegrees.u; // NorthEast corner lat. + + double stopLon = theQuarterQuadLowerRightCorner.lon;// + +// thePaddingInDegrees.v; // NorthEast corner lon. + + ossimGrect + rect(ossimGpt(startLat, + startLon, + theQuarterQuadLowerRightCorner.height(), + theQuarterQuadLowerRightCorner.datum()), + ossimGpt(stopLat, + stopLon, + theQuarterQuadLowerRightCorner.height(), + theQuarterQuadLowerRightCorner.datum())); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG: " << MODULE + << "\nQuarter quad rect: " << rect <<"\n"; + } + + + return rect; +} + +//*************************************************************************** +// ossimUsgsQuad::quadRect() +//*************************************************************************** +ossimGrect ossimUsgsQuad::quadRect() const +{ + static const char MODULE[] = "ossimUsgsQuad::quadRect"; + + double startLat = theQuadLowerRightCorner.lat;// - +// thePaddingInDegrees.u; // SouthWest corner lat. + + double startLon = theQuadLowerRightCorner.lon - + QUAD_SIZE_IN_DEGREES;// - +// thePaddingInDegrees.v; // SouthWest corner lon. + + double stopLat = theQuadLowerRightCorner.lat + + QUAD_SIZE_IN_DEGREES;// + +// thePaddingInDegrees.u; // NorthEast corner lat. + + double stopLon = theQuadLowerRightCorner.lon;// + +// thePaddingInDegrees.v; // NorthEast corner lon. + + ossimGrect + rect(ossimGpt(startLat, + startLon, + theQuarterQuadLowerRightCorner.height(), + theQuarterQuadLowerRightCorner.datum()), + ossimGpt(stopLat, + stopLon, + theQuarterQuadLowerRightCorner.height(), + theQuarterQuadLowerRightCorner.datum())); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG: " << MODULE + << "\nQuarter quad rect: " << rect << "\n"; + } + + return rect; +} + +//*************************************************************************** +// ossimUsgsQuad::quarterQuadSegKwRect(char seg) +//*************************************************************************** +ossimString ossimUsgsQuad::quarterQuadSegKwRect(char seg) +{ + static const char MODULE[] = "ossimUsgsQuad::quarterQuadSegKwRect"; + + ossimString tmp; + + //*** + // Check the range of the segment, must be A, B, C or D. + //*** + if ( (seg < 65) || (seg > 68) ) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL:" << MODULE << "\n" + << seg << " out of range!\n" + << "Possible values: A, B, C, or D\n"; + return tmp; + } + + ossimGrect rect = quarterQuadSegRect(seg); + + ostringstream os; + + os << setprecision(12) + << rect.ll().lat << " " + << rect.ul().lon << " " + << rect.ul().lat << " " + << rect.ur().lon << ends; +// << rect.stop.lat << " " +// << rect.start.lon << " " +// << rect.start.lat << " " +// << rect.stop.lon << ends; + + tmp = os.str().c_str(); + + return tmp; +} + +//*************************************************************************** +// ossimUsgsQuad::quarterQuadKwRect() +//*************************************************************************** +ossimString ossimUsgsQuad::quarterQuadKwRect() const +{ +// static const char MODULE[] = "ossimUsgsQuad::quarterQuadKwRect"; + + ossimGrect rect = quarterQuadRect(); + + ostringstream os; + + os << setprecision(12) + << rect.ll().lat << " " + << rect.ul().lon << " " + << rect.ul().lat << " " + << rect.ur().lon << ends; +// os << setprecision(12) +// << rect.stop.lat << " " +// << rect.start.lon << " " +// << rect.start.lat << " " +// << rect.stop.lon << ends; + + ossimString tmp = os.str().c_str(); + + + + return tmp; +} + +//*************************************************************************** +// ossimUsgsQuad::quadKwRect() +//*************************************************************************** +ossimString ossimUsgsQuad::quadKwRect() const +{ +// static const char MODULE[] = "ossimUsgsQuad::quadKwRect"; + + ossimGrect rect = quadRect(); + + ostringstream os; + + os << setprecision(12) + << rect.ll().lat << " " + << rect.ul().lon << " " + << rect.ul().lat << " " + << rect.ur().lon << ends; +// os << setprecision(12) +// << rect.stop.lat << " " +// << rect.start.lon << " " +// << rect.start.lat << " " +// << rect.stop.lon << ends; + + ossimString tmp = os.str().c_str(); + + return tmp; +} diff --git a/Utilities/OSSIM/ossim_core/base/misc/ossimUsgsQuad.h b/Utilities/OSSIM/ossim_core/base/misc/ossimUsgsQuad.h new file mode 100644 index 0000000000..f75fd6ace9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/misc/ossimUsgsQuad.h @@ -0,0 +1,118 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimUsgsQuad.h,v 1.4 2003/01/27 15:24:34 gpotts Exp $ +#ifndef ossimUsgsQuad_HEADER +#define ossimUsgsQuad_HEADER +#include "base/data_types/ossimGpt.h" +#include "base/data_types/ossimGrect.h" +#include "base/data_types/ossimString.h" +#include "base/common/ossimCommon.h" +#include "base/common/ossimErrorStatusInterface.h" + +#include <vector> + +class OSSIMDLLEXPORT ossimUsgsQuad +{ +public: + ossimUsgsQuad(const ossimGpt& lrGpt); + ossimUsgsQuad(const ossimString& name, + const ossimDatum* datum); +// double paddingInMeters = 100); + + void setQuadName(const ossimString& name); + /*! Returns the bounding rectangle of the quarter quad segment. + * A segment is 1/4 of a quarter quad. + * Segment assingments: upper_left=A, upper_right=B, lower_left=C, + * lower_right=D NOTE: padding is added in. + */ + ossimGrect quarterQuadSegRect(char seg); + + /*! Returns the bounding rectangle of the quarter quad segment + * in the "area.lat_lon" keyword format: + * start_lat, start_lon, stop_lat, stop_lon + * NOTE: padding is added in. + */ + ossimString quarterQuadSegKwRect(char seg); + + /*! Returns the bounding rectangle of the quarter quad (3.75 minutes). + * NOTE: padding is added in. + */ + ossimGrect quarterQuadRect() const; + + /*! Returns the bounding rectangle of the quarter quad (3.75 minutes) + * in the "area.lat_lon" keyword format: + * start_lat, start_lon, stop_lat, stop_lon + * NOTE: padding is added in. + */ + ossimString quarterQuadKwRect() const; + + /*! Returns the bounding rectangle of the quarter quad (7.5 minutes). + * NOTE: padding is added in. + */ + ossimGrect quadRect() const; + + /*! Returns the bounding rectangle of the quarter quad (7.5 minutes) + * in the "area.lat_lon" keyword format: + * start_lat, start_lon, stop_lat, stop_lon + * NOTE: padding is added in. + */ + ossimString quadKwRect() const; + + /*! + * Returns the USGS quarter quad name. + */ + ossimString quarterQuadName() const + { + return ossimString(theName.begin(), + theName.begin()+7); + } + + ossimString quarterQuadSegName() const + { + return theName; + } + + + /*! + * Returns the lower right hand corner of quad with no padding. + */ + ossimGpt lrQuadCorner() const { return theQuadLowerRightCorner ; } + + /*! + * Returns the lower right hand corner of quarter quad with no padding. + */ + ossimGpt lrQuarterQuadCorner() const + { return theQuarterQuadLowerRightCorner; } + + static void getQuadList(std::vector<ossimUsgsQuad>& result, + const ossimGrect& rect); + +protected: + ossimString theName; + ossimGpt theQuadLowerRightCorner; // Lower right corner of quad. + ossimGpt theQuarterQuadLowerRightCorner;// quarter quad lr corner. +// ossimDpt thePaddingInDegrees; + char theQuarterQuadSegment; // A, B, C, D +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/property/.cvsignore b/Utilities/OSSIM/ossim_core/base/property/.cvsignore new file mode 100644 index 0000000000..7d50165874 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/.cvsignore @@ -0,0 +1,7 @@ +*.~* +*.o +Makefile +core.* +*.d +.libs +*.lo diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimBooleanProperty.cpp b/Utilities/OSSIM/ossim_core/base/property/ossimBooleanProperty.cpp new file mode 100644 index 0000000000..6492c2a5cb --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimBooleanProperty.cpp @@ -0,0 +1,82 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimBooleanProperty.cpp,v 1.6 2004/01/29 13:29:31 gpotts Exp $ +#include "ossimBooleanProperty.h" + +RTTI_DEF1(ossimBooleanProperty, "ossimBooleanProperty", ossimProperty); + +ossimBooleanProperty::ossimBooleanProperty(const ossimString& name, + bool value) + :ossimProperty(name), + theValue(value) +{ +} + +ossimBooleanProperty::ossimBooleanProperty(const ossimBooleanProperty& rhs) + :ossimProperty(rhs), + theValue(rhs.theValue) +{ +} + +ossimObject* ossimBooleanProperty::dup()const +{ + return new ossimBooleanProperty(*this); +} + +const ossimProperty& ossimBooleanProperty::assign(const ossimProperty& rhs) +{ + ossimProperty::assign(rhs); + + ossimBooleanProperty* property = PTR_CAST(ossimBooleanProperty, + &rhs); + if(property) + { + theValue = property->theValue; + } + + return *this; +} + +bool ossimBooleanProperty::setValue(const ossimString& value) +{ + theValue = value.toBool(); + + return true; +} + +bool ossimBooleanProperty::setBooleanValue(bool value, + ossimString& msg) +{ + theValue = value; + + return true; +} + +void ossimBooleanProperty::valueToString(ossimString& valueResult)const +{ + valueResult = theValue?"1":"0"; +} + +bool ossimBooleanProperty::getBoolean()const +{ + return theValue; +} diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimBooleanProperty.h b/Utilities/OSSIM/ossim_core/base/property/ossimBooleanProperty.h new file mode 100644 index 0000000000..ae23f2b7eb --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimBooleanProperty.h @@ -0,0 +1,47 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimBooleanProperty.h,v 1.6 2004/05/19 18:29:38 dburken Exp $ +#ifndef ossimBoolenaProperty_HEADER +#define ossimBoolenaProperty_HEADER +#include "ossimProperty.h" + +class OSSIMDLLEXPORT ossimBooleanProperty : public ossimProperty +{ +public: + ossimBooleanProperty(const ossimString& name=ossimString(""), + bool value = false); + ossimBooleanProperty(const ossimBooleanProperty& rhs); + virtual ossimObject* dup()const; + virtual const ossimProperty& assign(const ossimProperty& rhs); + virtual bool setValue(const ossimString& value); + bool setBooleanValue(bool value, + ossimString& msg); + void valueToString(ossimString& valueResult)const; + bool getBoolean()const; + +protected: + bool theValue; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimColorProperty.cpp b/Utilities/OSSIM/ossim_core/base/property/ossimColorProperty.cpp new file mode 100644 index 0000000000..e8852120cf --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimColorProperty.cpp @@ -0,0 +1,128 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimColorProperty.cpp,v 1.5 2005/05/23 17:52:23 gpotts Exp $ +#include <sstream> +#include "ossimColorProperty.h" + +RTTI_DEF1(ossimColorProperty, "ossimColorProperty", ossimProperty); + +ossimColorProperty::ossimColorProperty(const ossimString& name, + const ossimRgbVector& value) + :ossimProperty(name), + theValue(value) +{ +} + +ossimColorProperty::ossimColorProperty(const ossimColorProperty& rhs) + :ossimProperty(rhs), + theValue(rhs.theValue) +{ +} + +ossimColorProperty::~ossimColorProperty() +{ +} + +ossimObject* ossimColorProperty::dup()const +{ + return new ossimColorProperty(*this); +} + +const ossimProperty& ossimColorProperty::assign(const ossimProperty& rhs) +{ + ossimProperty::assign(rhs); + + ossimColorProperty* rhsPtr = PTR_CAST(ossimColorProperty, &rhs); + + if(rhsPtr) + { + theValue = rhsPtr->theValue; + } + else + { + setValue(rhs.valueToString()); + } + + return *this; +} + +bool ossimColorProperty::setValue(const ossimString& value) +{ + istringstream in(value); + + int r,g,b; + + in >> r >> g >> b; + + theValue = ossimRgbVector(r,g,b); + + return in.good(); +} + +void ossimColorProperty::valueToString(ossimString& valueResult)const +{ + ostringstream out; + + out << (int)theValue.getR() << " " << (int)theValue.getG() << " " << (int)theValue.getB() << endl; + + valueResult = out.str().c_str(); +} + +const ossimRgbVector& ossimColorProperty::getColor()const +{ + return theValue; +} + +void ossimColorProperty::setColor(const ossimRgbVector& value) +{ + theValue = value; +} + +ossim_uint8 ossimColorProperty::getRed()const +{ + return theValue.getR(); +} + +ossim_uint8 ossimColorProperty::getGreen()const +{ + return theValue.getG(); +} + +ossim_uint8 ossimColorProperty::getBlue()const +{ + return theValue.getB(); +} + +void ossimColorProperty::setRed(ossim_uint8 r) +{ + theValue.setR(r); +} + +void ossimColorProperty::setGreen(ossim_uint8 g) +{ + theValue.setG(g); +} + +void ossimColorProperty::setBlue(ossim_uint8 b) +{ + theValue.setB(b); +} diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimColorProperty.h b/Utilities/OSSIM/ossim_core/base/property/ossimColorProperty.h new file mode 100644 index 0000000000..57fbc76321 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimColorProperty.h @@ -0,0 +1,54 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimColorProperty.h,v 1.6 2004/09/22 15:32:24 gpotts Exp $ +#ifndef ossimColorProperty_HEADER +#define ossimColorProperty_HEADER +#include <base/property/ossimProperty.h> +#include <base/common/ossimRtti.h> +#include <base/data_types/color_space/ossimRgbVector.h> + +class OSSIMDLLEXPORT ossimColorProperty : public ossimProperty +{ +public: + ossimColorProperty(const ossimString& name=ossimString(""), + const ossimRgbVector& value = ossimRgbVector(0,0,0)); + ossimColorProperty(const ossimColorProperty& rhs); + virtual ~ossimColorProperty(); + virtual ossimObject* dup()const; + virtual const ossimProperty& assign(const ossimProperty& rhs); + virtual bool setValue(const ossimString& value); + virtual void valueToString(ossimString& valueResult)const; + const ossimRgbVector& getColor()const; + void setColor(const ossimRgbVector& value); + ossim_uint8 getRed()const; + ossim_uint8 getGreen()const; + ossim_uint8 getBlue()const; + void setRed(ossim_uint8 r); + void setGreen(ossim_uint8 r); + void setBlue(ossim_uint8 r); +protected: + ossimRgbVector theValue; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimContainerProperty.cpp b/Utilities/OSSIM/ossim_core/base/property/ossimContainerProperty.cpp new file mode 100644 index 0000000000..162221f055 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimContainerProperty.cpp @@ -0,0 +1,172 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimContainerProperty.cpp,v 1.6 2004/09/23 17:18:27 gpotts Exp $ +#include "ossimContainerProperty.h" + +RTTI_DEF1(ossimContainerProperty, "ossimContainerProperty", ossimProperty); + +ossimContainerProperty::ossimContainerProperty(const ossimString& name) + :ossimProperty(name) +{ +} + +ossimContainerProperty::ossimContainerProperty(const ossimContainerProperty& rhs) + :ossimProperty(rhs) +{ + copyList(rhs); +} + +ossimContainerProperty::~ossimContainerProperty() +{ + deleteChildren(); +} + +ossimObject* ossimContainerProperty::dup()const +{ + return new ossimContainerProperty(*this); +} + +const ossimProperty& ossimContainerProperty::assign(const ossimProperty& rhs) +{ + ossimContainerProperty* rhsContainer = PTR_CAST(ossimContainerProperty, + &rhs); + ossimProperty::assign(rhs); + + if(rhsContainer) + { + copyList(*rhsContainer); + } + + return *this; +} + +void ossimContainerProperty::copyList(const ossimContainerProperty& rhs) +{ + deleteChildren(); + + for(ossim_uint32 idx = 0; idx < rhs.theChildPropertyList.size();++idx) + { + if(rhs.theChildPropertyList[idx].valid()) + { + theChildPropertyList.push_back((ossimProperty*)(rhs.theChildPropertyList[idx]->dup())); + } + else + { + theChildPropertyList.push_back((ossimProperty*)NULL); + } + } +} + +void ossimContainerProperty::addChildren(std::vector<ossimRefPtr<ossimProperty> >& propertyList) +{ + for(ossim_uint32 idx = 0; idx < propertyList.size(); ++idx) + { + if(propertyList[idx].valid()) + { + theChildPropertyList.push_back(propertyList[idx]); + } + } +} + +void ossimContainerProperty::addChild(ossimProperty* property) +{ + theChildPropertyList.push_back(property); +} + +ossimRefPtr<ossimProperty> ossimContainerProperty::getProperty(const ossimString& name, + bool recurse) +{ + ossim_uint32 idx = 0; + std::vector<ossimRefPtr<ossimContainerProperty> > containers; + + for(idx = 0; idx < theChildPropertyList.size(); ++idx) + { + if(theChildPropertyList[idx].valid()) + { + if(theChildPropertyList[idx]->getName() == name) + { + return theChildPropertyList[idx]; + } + if(PTR_CAST(ossimContainerProperty, theChildPropertyList[idx].get())&&recurse) + { + containers.push_back(PTR_CAST(ossimContainerProperty, theChildPropertyList[idx].get())); + } + } + } + + if(containers.size()) + { + for(idx = 0; idx < containers.size();++idx) + { + ossimRefPtr<ossimProperty> prop = containers[idx]->getProperty(name, recurse); + if(prop.valid()) + { + return prop; + } + } + } + + return (ossimProperty*)NULL; +} + +void ossimContainerProperty::deleteChildren() +{ +// for(ossim_uint32 idx = 0; idx < theChildPropertyList.size(); ++idx) +// { +// if(theChildPropertyList[idx]) +// { +// delete theChildPropertyList[idx]; +// theChildPropertyList[idx] = (ossimProperty*)NULL; +// } +// } + theChildPropertyList.clear(); +} + + +bool ossimContainerProperty::setValue(const ossimString& value) +{ + return false; +} + +void ossimContainerProperty::valueToString(ossimString& valueResult)const +{ +} + +ossim_uint32 ossimContainerProperty::getNumberOfProperties()const +{ + return theChildPropertyList.size(); +} + +ossimRefPtr<ossimProperty> ossimContainerProperty::getProperty(ossim_uint32 idx) +{ + if(idx < theChildPropertyList.size()) + { + return theChildPropertyList[idx]; + } + + return (ossimProperty*)NULL; +} + +void ossimContainerProperty::getPropertyList(std::vector<ossimRefPtr<ossimProperty> >& children) +{ + children = theChildPropertyList; +} diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimContainerProperty.h b/Utilities/OSSIM/ossim_core/base/property/ossimContainerProperty.h new file mode 100644 index 0000000000..8610156bb7 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimContainerProperty.h @@ -0,0 +1,56 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// LICENSE: LGPL see top level LICENSE.txt +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimContainerProperty.h,v 1.7 2004/09/23 17:18:27 gpotts Exp $ +#ifndef ossimContainerProperty_HEADER +#define ossimContainerProperty_HEADER +#include <vector> +#include <base/common/ossimRefPtr.h> +#include "ossimProperty.h" + +class OSSIMDLLEXPORT ossimContainerProperty : public ossimProperty +{ +public: + ossimContainerProperty(const ossimString& name=ossimString("")); + ossimContainerProperty(const ossimContainerProperty& rhs); + virtual ~ossimContainerProperty(); + + virtual ossimObject* dup()const; + + virtual const ossimProperty& assign(const ossimProperty& rhs); + /*! + * Note: the container will own the properties passed in. + */ + virtual void addChildren(std::vector<ossimRefPtr<ossimProperty> >& propertyList); + + /*! + * Will add the child to the list and take ownership + */ + virtual void addChild(ossimProperty* propery); + + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name, + bool recurse=false); + virtual void deleteChildren(); + virtual bool setValue(const ossimString& value); + virtual void valueToString(ossimString& valueResult)const; + + virtual ossim_uint32 getNumberOfProperties()const; + virtual ossimRefPtr<ossimProperty> getProperty(ossim_uint32 idx); + + virtual void getPropertyList(std::vector<ossimRefPtr<ossimProperty> >& children); + +protected: + std::vector<ossimRefPtr<ossimProperty> > theChildPropertyList; + + virtual void copyList(const ossimContainerProperty& rhs); + + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimDateProperty.cpp b/Utilities/OSSIM/ossim_core/base/property/ossimDateProperty.cpp new file mode 100644 index 0000000000..016b46ce4d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimDateProperty.cpp @@ -0,0 +1,142 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// LICENSE: LGPL see top level license.txt +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimDateProperty.cpp,v 1.3 2005/10/17 18:37:16 gpotts Exp $ +// +#include <base/property/ossimDateProperty.h> +#include <sstream> + +RTTI_DEF1(ossimDateProperty, "ossimDateProperty", ossimProperty); + +ossimDateProperty::ossimDateProperty() + :ossimProperty("") +{ + setDate(ossimDate()); +} + +ossimDateProperty::ossimDateProperty(const ossimString& name, + const ossimString& value) + :ossimProperty(name) +{ + setValue(value); +} + +ossimDateProperty::ossimDateProperty(const ossimString& name, + const ossimLocalTm& value) + :ossimProperty(name), + theValue(value) +{ +} + +ossimDateProperty::ossimDateProperty(const ossimDateProperty& src) + :ossimProperty(src), + theValue(src.theValue) +{ +} + +ossimObject* ossimDateProperty::dup()const +{ + return new ossimDateProperty(*this); +} + +void ossimDateProperty::setDate(const ossimLocalTm& localTm) +{ + theValue = localTm; +} + +const ossimLocalTm& ossimDateProperty::getDate()const +{ + return theValue; +} + +bool ossimDateProperty::setValue(const ossimString& value) +{ + if(value.trim() == "") + { + theValue = ossimDate(); + return true; + } + bool result = value.size() == 14; + + ossimString year; + ossimString month; + ossimString day; + ossimString hour; + ossimString min; + ossimString sec; + + if(value.size() == 14) + { + year = ossimString(value.begin(), + value.begin()+4); + month = ossimString(value.begin()+4, + value.begin()+6); + day = ossimString(value.begin()+6, + value.begin()+8); + hour = ossimString(value.begin()+8, + value.begin()+10); + min = ossimString(value.begin()+10, + value.begin()+12); + sec = ossimString(value.begin()+12, + value.begin()+14); + + theValue.setYear(year.toUInt32()); + theValue.setMonth(month.toUInt32()); + theValue.setDay(day.toUInt32()); + theValue.setHour(hour.toUInt32()); + theValue.setMin(min.toUInt32()); + theValue.setSec(sec.toUInt32()); + } + + return result; +} + +void ossimDateProperty::valueToString(ossimString& valueResult)const +{ + std::ostringstream out; + + out << std::setw(4) + << std::setfill('0') + << theValue.getYear() + << std::setw(2) + << std::setfill('0') + << theValue.getMonth() + << std::setw(2) + << std::setfill('0') + << theValue.getDay() + << std::setw(2) + << std::setfill('0') + << theValue.getHour() + << std::setw(2) + << std::setfill('0') + << theValue.getMin() + << std::setw(2) + << std::setfill('0') + << theValue.getSec(); + + valueResult = out.str(); + +} + +const ossimProperty& ossimDateProperty::assign(const ossimProperty& rhs) +{ + ossimProperty::assign(rhs); + + ossimDateProperty* rhsPtr = PTR_CAST(ossimDateProperty, &rhs); + + if(rhsPtr) + { + theValue = rhsPtr->theValue; + } + else + { + setValue(rhs.valueToString()); + } + + return *this; +} diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimDateProperty.h b/Utilities/OSSIM/ossim_core/base/property/ossimDateProperty.h new file mode 100644 index 0000000000..fe1733c5fd --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimDateProperty.h @@ -0,0 +1,29 @@ +#ifndef ossimDateProperty_HEADER +#define ossimDateProperty_HEADER +#include "ossimProperty.h" +#include <base/common/ossimDate.h> + +class OSSIM_DLL ossimDateProperty : public ossimProperty +{ +public: + ossimDateProperty(); + ossimDateProperty(const ossimString& name, + const ossimString& value); + ossimDateProperty(const ossimString& name, + const ossimLocalTm& value); + ossimDateProperty(const ossimDateProperty& src); + virtual ossimObject* dup()const; + + void setDate(const ossimLocalTm& localTm); + const ossimLocalTm& getDate()const; + virtual bool setValue(const ossimString& value); + virtual void valueToString(ossimString& valueResult)const; + virtual const ossimProperty& ossimDateProperty::assign(const ossimProperty& rhs); + +protected: + ossimLocalTm theValue; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimDoubleGridProperty.cpp b/Utilities/OSSIM/ossim_core/base/property/ossimDoubleGridProperty.cpp new file mode 100644 index 0000000000..dc8801d6c3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimDoubleGridProperty.cpp @@ -0,0 +1,159 @@ +#include <sstream> +#include "ossimDoubleGridProperty.h" + +RTTI_DEF1(ossimDoubleGridProperty, "ossimDoubleGridProperty", ossimProperty); + +ossimDoubleGridProperty::ossimDoubleGridProperty(const ossimString& name, + int numberOfRows, + int numberOfCols, + const std::vector<double>& values) + :ossimProperty(name), + theMinNumberOfCols(-1), + theMaxNumberOfCols(-1), + theMinNumberOfRows(-1), + theMaxNumberOfRows(-1) +{ + +} + +ossimDoubleGridProperty::ossimDoubleGridProperty(const ossimDoubleGridProperty& rhs) + :ossimProperty(rhs), + theMinNumberOfCols(rhs.theMinNumberOfCols), + theMaxNumberOfCols(rhs.theMaxNumberOfCols), + theMinNumberOfRows(rhs.theMinNumberOfRows), + theMaxNumberOfRows(rhs.theMaxNumberOfRows), + theValues(rhs.theValues) +{ +} + +ossimDoubleGridProperty::~ossimDoubleGridProperty() +{ +} + +ossimObject* ossimDoubleGridProperty::dup()const +{ + return new ossimDoubleGridProperty(*this); +} + +const ossimProperty& ossimDoubleGridProperty::assign(const ossimProperty& rhs) +{ + ossimProperty::assign(rhs); + ossimDoubleGridProperty* rhsPtr = PTR_CAST(ossimDoubleGridProperty, &rhs); + + if(rhsPtr) + { + theMinNumberOfCols = rhsPtr->theMinNumberOfCols; + theMaxNumberOfCols = rhsPtr->theMaxNumberOfCols; + theMinNumberOfRows = rhsPtr->theMinNumberOfRows; + theMaxNumberOfRows = rhsPtr->theMaxNumberOfRows; + theValues = rhsPtr->theValues; + } + else + { + setValue(rhs.valueToString()); + + } + + return *this; +} + + +bool ossimDoubleGridProperty::setValue(const ossimString& value) +{ + std::istringstream in(value.c_str()); + + int numberOfRows; + int numberOfCols; + int rowIdx = 0; + int colIdx = 0; + in >> numberOfRows >> numberOfCols; + + theValues.resize(numberOfRows); + + for(rowIdx = 0; rowIdx < numberOfRows; ++rowIdx) + { + theValues[rowIdx].resize(numberOfCols); + for(colIdx = 0; colIdx < numberOfCols; ++ colIdx) + { + in >> theValues[rowIdx][colIdx]; + } + } + + return true; +} + +void ossimDoubleGridProperty::valueToString(ossimString& valueResult)const +{ + std::ostringstream out; + int rowIdx = 0; + int colIdx = 0; + out << getNumberOfRows() << " " << getNumberOfCols() << " "; + + for(rowIdx = 0; rowIdx < (int)getNumberOfRows(); ++rowIdx) + { + for(colIdx = 0; colIdx < (int)getNumberOfCols(); ++colIdx) + { + out << ossimString::toString(getValue(rowIdx, colIdx)) << " "; + } + } + valueResult = out.str(); +} + +void ossimDoubleGridProperty::clearConstraints() +{ + theMinNumberOfCols = -1; + theMaxNumberOfCols = -1; + theMinNumberOfRows = -1; + theMaxNumberOfRows = -1; +} + +void ossimDoubleGridProperty::setColConstraints(int minNumberOfCols, + int maxNumberOfCols) +{ + theMinNumberOfCols = minNumberOfCols; + theMaxNumberOfCols = maxNumberOfCols; +} + +void ossimDoubleGridProperty::setRowConstraints(int minNumberOfRows, + int maxNumberOfRows) +{ + theMinNumberOfRows = minNumberOfRows; + theMaxNumberOfRows = maxNumberOfRows; +} + +void ossimDoubleGridProperty::setContraints(int minNumberOfRows, + int maxNumberOfRows, + int minNumberOfCols, + int maxNumberOfCols) +{ + theMinNumberOfRows = minNumberOfRows; + theMaxNumberOfRows = maxNumberOfRows; + theMinNumberOfCols = minNumberOfCols; + theMaxNumberOfCols = maxNumberOfCols; +} + +ossim_uint32 ossimDoubleGridProperty::getNumberOfRows()const +{ + return ((int)theValues.size()); +} + +ossim_uint32 ossimDoubleGridProperty::getNumberOfCols()const +{ + if(getNumberOfRows()) + { + return theValues[0].size(); + } + return 0; +} + +double ossimDoubleGridProperty::getValue(ossim_uint32 row, + ossim_uint32 col)const +{ + if((row < getNumberOfRows())&& + (col < getNumberOfCols())) + { + return theValues[(int)row][(int)col]; + } + + return 0.0; +} diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimDoubleGridProperty.h b/Utilities/OSSIM/ossim_core/base/property/ossimDoubleGridProperty.h new file mode 100644 index 0000000000..460987cee9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimDoubleGridProperty.h @@ -0,0 +1,79 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimDoubleGridProperty.h,v 1.4 2004/05/19 18:29:38 dburken Exp $ +#ifndef ossimDoubleGridProperty_HEADER +#define ossimDoubleGridProperty_HEADER +#include "ossimProperty.h" + +class OSSIMDLLEXPORT ossimDoubleGridProperty : public ossimProperty +{ +public: + ossimDoubleGridProperty(const ossimString& name = ossimString(""), + int numberOfRows = 0, + int numberOfCols = 0, + const std::vector<double>& values = std::vector<double>()); + ossimDoubleGridProperty(const ossimDoubleGridProperty& rhs); + + virtual ~ossimDoubleGridProperty(); + + ossimObject* dup()const; + + virtual const ossimProperty& assign(const ossimProperty& rhs); + + virtual bool setValue(const ossimString& value); + virtual void valueToString(ossimString& valueResult)const; + + void clearConstraints(); + /*! + * Setting both values to -1 will say no constraints. + * if min is constrained and max not then it will not allow + * the cols to grow any larger than the passed in max. + * + * If the min is -1 and max not then it will not exceed the + * max number of cols + */ + void setColConstraints(int minNumberOfCols, + int maxNumberOfCols); + + void setRowConstraints(int minNumberOfRows, + int maxNumberOfRows); + + void setContraints(int minNumberOfRows, + int maxNumberOfRows, + int minNumberOfCols, + int maxNumberOfCols); + + ossim_uint32 getNumberOfRows()const; + ossim_uint32 getNumberOfCols()const; + + double getValue(ossim_uint32 row, ossim_uint32 col)const; +protected: + int theMinNumberOfCols; + int theMaxNumberOfCols; + int theMinNumberOfRows; + int theMaxNumberOfRows; + std::vector< std::vector<double> > theValues; + + +TYPE_DATA +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimFilenameProperty.cpp b/Utilities/OSSIM/ossim_core/base/property/ossimFilenameProperty.cpp new file mode 100644 index 0000000000..2a28ef0a74 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimFilenameProperty.cpp @@ -0,0 +1,168 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimFilenameProperty.cpp,v 1.5 2004/01/29 13:29:31 gpotts Exp $ +#include "ossimFilenameProperty.h" + +RTTI_DEF1(ossimFilenameProperty, "ossimFilenameProperty", ossimProperty); + +ossimFilenameProperty::ossimFilenameProperty(const ossimString& name, + const ossimFilename& value, + const std::vector<ossimString>& filterList) + :ossimProperty(name), + theValue(value), + theFilterList(filterList), + theIoType(ossimFilenamePropertyIoType_NOT_SPECIFIED) +{ +} + +ossimFilenameProperty::ossimFilenameProperty(const ossimFilenameProperty& rhs) + :ossimProperty(rhs), + theValue(rhs.theValue), + theFilterList(rhs.theFilterList), + theIoType(rhs.theIoType) +{ +} + +ossimFilenameProperty::~ossimFilenameProperty() +{ +} + +ossimObject* ossimFilenameProperty::dup()const +{ + return new ossimFilenameProperty(*this); +} + +void ossimFilenameProperty::valueToString(ossimString& valueResult)const +{ + valueResult = theValue; +} + +bool ossimFilenameProperty::setValue(const ossimString& value) +{ + theValue = value; + + return true; +} + +const ossimFilenameProperty& ossimFilenameProperty::operator = (ossimFilenameProperty& rhs) +{ + assign(rhs); + + return *this; +} + +const ossimProperty& ossimFilenameProperty::assign(const ossimProperty& rhs) +{ + ossimProperty::assign(rhs); + theValue = rhs.valueToString(); + + ossimFilenameProperty* rhsPtr = PTR_CAST(ossimFilenameProperty, + &rhs); + + if(rhsPtr) + { + theFilterList = rhsPtr->theFilterList; + theIoType = rhsPtr->theIoType; + } + + return *this; +} + +void ossimFilenameProperty::clearFilterList() +{ + theFilterList.clear(); +} + +ossim_uint32 ossimFilenameProperty::getNumberOfFilters()const +{ + return theFilterList.size(); +} + +void ossimFilenameProperty::setFilter(ossim_uint32 idx, + const ossimString& filterValue) +{ + if(idx < getNumberOfFilters()) + { + theFilterList[idx] = filterValue; + } +} + +ossimString ossimFilenameProperty::getFilter(ossim_uint32 idx)const +{ + if(idx < getNumberOfFilters()) + { + return theFilterList[idx]; + } + + return ossimString(""); +} + + +ossimString ossimFilenameProperty::getFilterListAsString(const ossimString& separator)const +{ + ossimString result; + ossim_uint32 idx = 0; + + if(getNumberOfFilters() > 0) + { + for(idx = 0; idx < getNumberOfFilters()-1;++idx) + { + result += getFilter(idx); + result += separator; + } + result += getFilter(getNumberOfFilters()-1); + } + + return result; +} + + +const std::vector<ossimString>& ossimFilenameProperty::getFilterList()const +{ + return theFilterList; +} + +void ossimFilenameProperty::addFilter(const ossimString& filter) +{ + theFilterList.push_back(filter); +} + + +void ossimFilenameProperty::setIoType(ossimFilenamePropertyIoType ioType) +{ + theIoType = ioType; +} + +ossimFilenameProperty::ossimFilenamePropertyIoType ossimFilenameProperty::getIoType()const +{ + return theIoType; +} + +bool ossimFilenameProperty::isIoTypeInput()const +{ + return (theIoType==ossimFilenamePropertyIoType_INPUT); +} + +bool ossimFilenameProperty::isIoTypeOutput()const +{ + return (theIoType==ossimFilenamePropertyIoType_OUTPUT); +} diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimFilenameProperty.h b/Utilities/OSSIM/ossim_core/base/property/ossimFilenameProperty.h new file mode 100644 index 0000000000..225d187c37 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimFilenameProperty.h @@ -0,0 +1,75 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimFilenameProperty.h,v 1.5 2004/05/19 18:29:38 dburken Exp $ +#ifndef ossimFilenameProperty_HEADER +#define ossimFilenameProperty_HEADER +#include <vector> +#include "ossimProperty.h" +#include "base/data_types/ossimFilename.h" +#include "base/data_types/ossimString.h" + +class OSSIMDLLEXPORT ossimFilenameProperty : public ossimProperty +{ +public: + + enum ossimFilenamePropertyIoType + { + ossimFilenamePropertyIoType_NOT_SPECIFIED = 0, + ossimFilenamePropertyIoType_INPUT = 1, + ossimFilenamePropertyIoType_OUTPUT = 2 + }; + + ossimFilenameProperty(const ossimString& name = ossimString(""), + const ossimFilename& value = ossimFilename(""), + const std::vector<ossimString>& filterList = std::vector<ossimString>()); + + ossimFilenameProperty(const ossimFilenameProperty& rhs); + virtual ~ossimFilenameProperty(); + ossimObject* dup()const; + virtual void valueToString(ossimString& valueResult)const; + virtual bool setValue(const ossimString& value); + const ossimFilenameProperty& operator = (ossimFilenameProperty& rhs); + virtual const ossimProperty& assign(const ossimProperty& rhs); + + void clearFilterList(); + ossim_uint32 getNumberOfFilters()const; + void setFilter(ossim_uint32 idx, + const ossimString& filterValue); + ossimString getFilter(ossim_uint32 idx)const; + ossimString getFilterListAsString(const ossimString& separator=ossimString("\n"))const; + const std::vector<ossimString>& getFilterList()const; + void addFilter(const ossimString& filter); + + void setIoType(ossimFilenamePropertyIoType ioType); + ossimFilenamePropertyIoType getIoType()const; + bool isIoTypeInput()const; + bool isIoTypeOutput()const; + +protected: + ossimFilename theValue; + std::vector<ossimString> theFilterList; + ossimFilenamePropertyIoType theIoType; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimFontProperty.cpp b/Utilities/OSSIM/ossim_core/base/property/ossimFontProperty.cpp new file mode 100644 index 0000000000..7fdb47c07a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimFontProperty.cpp @@ -0,0 +1,103 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimFontProperty.cpp,v 1.4 2004/01/29 13:29:31 gpotts Exp $ +#include <sstream> +#include "ossimFontProperty.h" +#include "base/data_types/ossimKeywordlist.h" + + +RTTI_DEF1(ossimFontProperty, "ossimFontProperty", ossimProperty); + +ossimFontProperty::ossimFontProperty(const ossimString& name, + const ossimFontInformation& value) + :ossimProperty(name), + theValue(value) +{ + +} + +ossimFontProperty::ossimFontProperty(const ossimFontProperty& rhs) + :ossimProperty(rhs), + theValue(rhs.theValue) +{ +} + +ossimFontProperty::~ossimFontProperty() +{ +} + +ossimObject* ossimFontProperty::dup()const +{ + return new ossimFontProperty(*this); +} + +const ossimProperty& ossimFontProperty::assign(const ossimProperty& rhs) +{ + ossimProperty::assign(rhs); + + ossimFontProperty* rhsPtr = PTR_CAST(ossimFontProperty, + &rhs); + + if(rhsPtr) + { + theValue = rhsPtr->theValue; + } + + return *this; +} + +bool ossimFontProperty::setValue(const ossimString& value) +{ + bool result = true; + ossimKeywordlist kwl; + + istringstream in(value); + + result = kwl.parseStream(in); + if(result) + { + theValue.loadState(kwl); + } + + return result; +} + +void ossimFontProperty::valueToString(ossimString& valueResult)const +{ + ostringstream out; + ossimKeywordlist kwl; + + theValue.saveState(kwl); + + kwl.writeToStream(out); + valueResult = kwl.toString(); +} + +void ossimFontProperty::setFontInformation(ossimFontInformation& fontInfo) +{ + theValue = fontInfo; +} + +const ossimFontInformation& ossimFontProperty::getFontInformation()const +{ + return theValue; +} diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimFontProperty.h b/Utilities/OSSIM/ossim_core/base/property/ossimFontProperty.h new file mode 100644 index 0000000000..38552de3c9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimFontProperty.h @@ -0,0 +1,48 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimFontProperty.h,v 1.4 2004/01/29 13:29:31 gpotts Exp $ +#ifndef ossimFontProperty_HEADER +#define ossimFontProperty_HEADER +#include "ossimProperty.h" +#include "base/common/ossimFontInformation.h" + +class OSSIMDLLEXPORT ossimFontProperty : public ossimProperty +{ +public: + ossimFontProperty(const ossimString& name, + const ossimFontInformation& value); + ossimFontProperty(const ossimFontProperty& rhs); + virtual ~ossimFontProperty(); + virtual ossimObject* dup()const; + virtual const ossimProperty& assign(const ossimProperty& rhs); + virtual bool setValue(const ossimString& value); + virtual void valueToString(ossimString& valueResult)const; + + void setFontInformation(ossimFontInformation& fontInfo); + const ossimFontInformation& getFontInformation()const; +protected: + ossimFontInformation theValue; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimMatrixProperty.cpp b/Utilities/OSSIM/ossim_core/base/property/ossimMatrixProperty.cpp new file mode 100644 index 0000000000..a065a976c2 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimMatrixProperty.cpp @@ -0,0 +1,331 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimMatrixProperty.cpp,v 1.7 2005/10/17 18:37:16 gpotts Exp $ +#include <sstream> +#include "ossimMatrixProperty.h" +#include "base/common/ossimCommon.h" + +RTTI_DEF1(ossimMatrixProperty, "ossimMatrixProperty", ossimProperty); + +ossimMatrixProperty::ossimMatrixProperty(const ossimString& name, + const std::vector<double>& values, + int numberOfRows, + int numberOfCols) + :ossimProperty(name), + theMinNumberOfCols(-1), + theMaxNumberOfCols(-1), + theMinNumberOfRows(-1), + theMaxNumberOfRows(-1) +{ + resize(numberOfRows, numberOfCols); + + if((int)values.size() == numberOfRows*numberOfCols) + { + int rowIdx = 0; + int colIdx = 0; + int linearIdx = 0; + for(rowIdx = 0; rowIdx < getNumberOfRows(); ++rowIdx) + { + for(colIdx = 0; colIdx < getNumberOfCols(); ++colIdx) + { + theValueArray[rowIdx][colIdx] = values[linearIdx]; + ++linearIdx; + } + } + } +} + + +ossimMatrixProperty::ossimMatrixProperty(const ossimMatrixProperty& rhs) + :ossimProperty(rhs), + theValueArray(rhs.theValueArray), + theMinNumberOfCols(rhs.theMinNumberOfCols), + theMaxNumberOfCols(rhs.theMaxNumberOfCols), + theMinNumberOfRows(rhs.theMaxNumberOfCols), + theMaxNumberOfRows(rhs.theMaxNumberOfRows) +{ +} + +ossimMatrixProperty::~ossimMatrixProperty() +{ + +} + +ossimObject* ossimMatrixProperty::dup()const +{ + return new ossimMatrixProperty(*this); +} + + +const ossimProperty& ossimMatrixProperty::assign(const ossimProperty& rhs) +{ + ossimMatrixProperty* rhsPtr = PTR_CAST(ossimMatrixProperty, + &rhs); + if(rhsPtr) + { + theValueArray = rhsPtr->theValueArray; + theMinNumberOfCols = rhsPtr->theMinNumberOfCols; + theMaxNumberOfCols = rhsPtr->theMaxNumberOfCols; + theMinNumberOfRows = rhsPtr->theMinNumberOfRows; + theMaxNumberOfRows = rhsPtr->theMaxNumberOfRows; + } + + return ossimProperty::assign(rhs); +} + +bool ossimMatrixProperty::setValue(const ossimString& value) +{ + std::istringstream in(value); + + int numberOfRows; + int numberOfCols; + double tempValue; + + in>>numberOfRows >> numberOfCols; + + if(!in.bad()) + { + resize(numberOfRows, numberOfCols); + + int rowIdx = 0; + int colIdx = 0; + for(rowIdx = 0; ((rowIdx < getNumberOfRows())&&(!in.bad())); ++rowIdx) + { + for(colIdx = 0; ((colIdx < getNumberOfCols())&&(!in.bad()));++ colIdx) + { + in >> tempValue; + + theValueArray[rowIdx][colIdx] = tempValue; + } + } + } + + return !in.bad(); +} + +void ossimMatrixProperty::valueToString(ossimString& valueResult)const +{ + if(theValueArray.size()>0) + { + if(theValueArray[0].size() > 0) + { + valueResult = ""; + + int rowIdx = 0; + int colIdx = 0; + valueResult += ossimString::toString(getNumberOfRows()) + " " + + ossimString::toString(getNumberOfCols()) + " "; + for(rowIdx = 0; rowIdx < getNumberOfRows();++rowIdx) + { + for(colIdx = 0; colIdx < getNumberOfCols(); ++colIdx) + { + valueResult += ossimString::toString(theValueArray[rowIdx][colIdx]); + valueResult += " "; + } + } + } + } +} + +void ossimMatrixProperty::resize(int numberOfRows, + int numberOfCols) +{ + int tempNumberOfRows = numberOfRows; + int tempNumberOfCols = numberOfCols; + + if(theMinNumberOfCols > 0) + { + if(tempNumberOfCols < theMinNumberOfCols) + { + tempNumberOfCols = theMinNumberOfCols; + } + } + if(theMinNumberOfRows > 0) + { + if(tempNumberOfRows < theMinNumberOfRows) + { + tempNumberOfRows = theMinNumberOfRows; + } + } + if(theMaxNumberOfCols > 0) + { + if(tempNumberOfCols > theMaxNumberOfCols) + { + tempNumberOfCols = theMaxNumberOfCols; + } + } + if(theMaxNumberOfRows > 0) + { + if(tempNumberOfRows > theMaxNumberOfRows) + { + tempNumberOfRows = theMaxNumberOfRows; + } + } + + int currentNumberOfRows = getNumberOfRows(); + int currentNumberOfCols = getNumberOfCols(); + + if((currentNumberOfRows != tempNumberOfRows) || + (currentNumberOfCols != tempNumberOfCols)) + { + std::vector< std::vector<double> > tempValue = theValueArray; + + theValueArray.resize(tempNumberOfRows); + + int minCols = ossimMin((int)currentNumberOfCols, + (int)tempNumberOfCols); + int rowIdx = 0; + int colIdx = 0; + + for(rowIdx = 0 ; rowIdx < tempNumberOfRows; ++rowIdx) + { + theValueArray[rowIdx].resize(tempNumberOfCols); + std::fill(theValueArray[rowIdx].begin(), theValueArray[rowIdx].end(), 0); + + if(tempNumberOfRows < currentNumberOfRows) + { + for(colIdx = 0 ; colIdx < minCols; ++colIdx) + { + theValueArray[rowIdx][colIdx] = tempValue[rowIdx][colIdx]; + } + } + } + } +} + +double& ossimMatrixProperty::operator()(int rowIdx, + int colIdx) +{ + return theValueArray[rowIdx][colIdx]; +} + +const double& ossimMatrixProperty::operator()(int rowIdx, + int colIdx)const +{ + return theValueArray[rowIdx][colIdx]; +} + +int ossimMatrixProperty::getNumberOfRows()const +{ + return (int)theValueArray.size(); +} + +int ossimMatrixProperty::getNumberOfCols()const +{ + if(getNumberOfRows()) + { + return theValueArray[0].size(); + } + + return 0; +} + +void ossimMatrixProperty::clearConstraints() +{ + theMinNumberOfCols = -1; + theMaxNumberOfCols = -1; + theMinNumberOfRows = -1; + theMaxNumberOfRows = -1; +} + +void ossimMatrixProperty::setColContraints(int minNumberOfCols, + int maxNumberOfCols) +{ + theMinNumberOfCols = minNumberOfCols; + theMaxNumberOfCols = theMaxNumberOfCols; +} + +void ossimMatrixProperty::setRowContraints(int minNumberOfRows, + int maxNumberOfRows) +{ + theMinNumberOfRows = minNumberOfRows; + theMaxNumberOfRows = theMaxNumberOfRows; +} + +void ossimMatrixProperty::getColContraints(int& minNumberOfCols, + int& maxNumberOfCols) +{ + minNumberOfCols = theMinNumberOfCols; + maxNumberOfCols = theMaxNumberOfCols; +} + +void ossimMatrixProperty::getRowContraints(int& minNumberOfRows, + int& maxNumberOfRows) +{ + minNumberOfRows = theMinNumberOfRows; + maxNumberOfRows = theMaxNumberOfRows; +} + +void ossimMatrixProperty::normalize() +{ + double densityValue = density(); + + if(fabs(densityValue) <= DBL_EPSILON) + { + return; + } + int rowIdx = 0; + int colIdx = 0; + for(rowIdx = 0 ; rowIdx < (int)theValueArray.size(); ++rowIdx) + { + for(colIdx = 0 ; colIdx < (int)theValueArray[rowIdx].size(); ++colIdx) + { + theValueArray[rowIdx][colIdx]/=densityValue; + } + } + +} + +void ossimMatrixProperty::zero() +{ + int rowIdx = 0; + int colIdx = 0; + for(rowIdx = 0 ; rowIdx < (int)theValueArray.size(); ++rowIdx) + { + for(colIdx = 0 ; colIdx < (int)theValueArray[rowIdx].size(); ++colIdx) + { + theValueArray[rowIdx][colIdx] = 0.0; + } + } +} + +double ossimMatrixProperty::density()const +{ + double result = 0.0; + + if((getNumberOfRows() > 0)&& + (getNumberOfCols() > 0)) + { + int rowIdx = 0; + int colIdx = 0; + + for(rowIdx = 0 ; rowIdx < (int)theValueArray.size(); ++rowIdx) + { + for(colIdx = 0 ; colIdx < (int)theValueArray[rowIdx].size(); ++colIdx) + { + result += theValueArray[rowIdx][colIdx]; + } + } + } + + return result; +} diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimMatrixProperty.h b/Utilities/OSSIM/ossim_core/base/property/ossimMatrixProperty.h new file mode 100644 index 0000000000..916005a568 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimMatrixProperty.h @@ -0,0 +1,96 @@ +#ifndef ossimMatrixProperty_HEADER +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimMatrixProperty.h,v 1.6 2004/05/19 18:29:38 dburken Exp $ +#define ossimMatrixProperty_HEADER +#include <vector> +#include "ossimProperty.h" + + +class OSSIMDLLEXPORT ossimMatrixProperty : public ossimProperty +{ +public: + ossimMatrixProperty(const ossimString& name=ossimString(""), + const std::vector<double>& values = std::vector<double>(), + int numberOfRows = 0, + int numberOfColumns = 0); + ossimMatrixProperty(const ossimMatrixProperty& rhs); + + virtual ~ossimMatrixProperty(); + + virtual ossimObject* dup()const; + virtual const ossimProperty& assign(const ossimProperty& rhs); + virtual bool setValue(const ossimString& value); + virtual void valueToString(ossimString& valueResult)const; + + void resize(int numberOfRows, + int numberOfColumns); + + double& operator ()(int rowIdx, + int colIdx); + + const double& operator()(int rowIdx, + int colIdx)const; + + int getNumberOfRows()const; + int getNumberOfCols()const; + + void clearConstraints(); + + /*! + * If any of the contraints are set to something < 0 then it means there + * isn't a constraint for that value. So if you give a min value of -1 + * and a max value of 10 then the column can grow from 10 downto 0. + */ + void setColContraints(int minNumberOfColumns, + int maxNumberOfColumns); + + /*! + * If any of the contraints are set to something < 0 then it means there + * isn't a constraint for that value. So if you give a min value of -1 + * and a max value of 10 then the row can grow from 10 downto 0. + */ + void setRowContraints(int minNumberOfRows, + int maxNumberOfRows); + + void getColContraints(int& minNumberOfColumns, + int& maxNumberOfColumns); + + void getRowContraints(int& minNumberOfRows, + int& maxNumberOfRows); + + + void normalize(); + void zero(); + +protected: + std::vector< std::vector<double> > theValueArray; + int theMinNumberOfCols; + int theMaxNumberOfCols; + int theMinNumberOfRows; + int theMaxNumberOfRows; + + double density()const; +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimNumericProperty.cpp b/Utilities/OSSIM/ossim_core/base/property/ossimNumericProperty.cpp new file mode 100644 index 0000000000..af9be4f2d4 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimNumericProperty.cpp @@ -0,0 +1,224 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimNumericProperty.cpp,v 1.5 2004/01/29 13:29:31 gpotts Exp $ +#include <algorithm> +#include "ossimNumericProperty.h" + + +RTTI_DEF1(ossimNumericProperty, "ossimNumericProperty", ossimProperty); + +ossimNumericProperty::ossimNumericProperty(const ossimString& name, + const ossimString& value) + :ossimProperty(name), + theValue(value), + theType(ossimNumericPropertyType_FLOAT64) +{ +} + +ossimNumericProperty::ossimNumericProperty(const ossimString& name, + const ossimString& value, + double minValue, + double maxValue) + :ossimProperty(name), + theValue(value), + theType(ossimNumericPropertyType_FLOAT64) +{ + setConstraints(minValue, + maxValue); +} + +ossimNumericProperty::ossimNumericProperty(const ossimNumericProperty& rhs) + :ossimProperty(rhs), + theValue(rhs.theValue), + theType(rhs.theType), + theRangeConstraint(rhs.theRangeConstraint) +{ +} + +ossimObject* ossimNumericProperty::dup()const +{ + return new ossimNumericProperty(*this); +} + +const ossimProperty& ossimNumericProperty::assign(const ossimProperty& rhs) +{ + ossimProperty::assign(rhs); + + ossimNumericProperty* numericProperty = PTR_CAST(ossimNumericProperty, + &rhs); + if(numericProperty) + { + theValue = numericProperty->theValue; + theType = numericProperty->theType; + theRangeConstraint = numericProperty->theRangeConstraint; + } + else + { + ossimString value; + rhs.valueToString(value); + setValue(value); + } + return *this; +} + +bool ossimNumericProperty::hasConstraints()const +{ + return (theRangeConstraint.size() == 2); +} + +double ossimNumericProperty::getMinValue()const +{ + if(hasConstraints()) + { + return theRangeConstraint[0]; + } + + return 0.0; +} + +double ossimNumericProperty::getMaxValue()const +{ + if(hasConstraints()) + { + return theRangeConstraint[1]; + } + + return 0.0; +} + +void ossimNumericProperty::clearConstraints() +{ + theRangeConstraint.clear(); +} + +void ossimNumericProperty::setConstraints(double minValue, + double maxValue) +{ + theRangeConstraint.resize(2); + theRangeConstraint[0] = minValue; + theRangeConstraint[1] = maxValue; + + if(minValue > maxValue) + { + std::swap(theRangeConstraint[0], + theRangeConstraint[1]); + } +} + +bool ossimNumericProperty::setValue(const ossimString& value) +{ + bool result = true; + if(hasConstraints()) + { + ossim_float64 tempV = (ossim_float64)value.toDouble(); + if((tempV >= theRangeConstraint[0])&& + (tempV <= theRangeConstraint[1])) + { + theValue = value; + } + } + else + { + theValue = value; + } + + return result; +} + +void ossimNumericProperty::valueToString(ossimString& valueResult)const +{ + switch(theType) + { + case ossimNumericPropertyType_INT: + { + valueResult = ossimString::toString(asInt32()); + break; + } + case ossimNumericPropertyType_UINT: + { + valueResult = ossimString::toString(asUInt32()); + break; + } + case ossimNumericPropertyType_FLOAT32: + { + valueResult = ossimString::toString(asFloat32()); + + break; + } + case ossimNumericPropertyType_FLOAT64: + { + valueResult = ossimString::toString(asFloat64()); + break; + } + }; +} + + +ossimNumericProperty::ossimNumericPropertyType ossimNumericProperty::getNumericType()const +{ + return theType; +} + +void ossimNumericProperty::setNumericType(ossimNumericPropertyType type) +{ + theType = type; +} + +ossim_float64 ossimNumericProperty::asFloat64()const +{ + return (ossim_float64)theValue.toDouble(); +} + +ossim_float32 ossimNumericProperty::asFloat32()const +{ + return (ossim_float32)theValue.toDouble(); +} + +ossim_uint32 ossimNumericProperty::asUInt32()const +{ + return theValue.toUInt32(); +} + +ossim_uint16 ossimNumericProperty::asUInt16()const +{ + return (ossim_uint16)theValue.toUInt32(); +} + +ossim_uint8 ossimNumericProperty::asUInt8()const +{ + return (ossim_uint8)theValue.toUInt32(); +} + +ossim_sint32 ossimNumericProperty::asInt32()const +{ + return (ossim_int32)theValue.toInt32(); +} + +ossim_sint16 ossimNumericProperty::asInt16()const +{ + return (ossim_int16)theValue.toInt32(); +} + +ossim_sint8 ossimNumericProperty::asInt8()const +{ + return (ossim_int8)theValue.toInt32(); +} diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimNumericProperty.h b/Utilities/OSSIM/ossim_core/base/property/ossimNumericProperty.h new file mode 100644 index 0000000000..a005a4af3c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimNumericProperty.h @@ -0,0 +1,78 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimNumericProperty.h,v 1.7 2004/05/19 18:29:38 dburken Exp $ +#ifndef ossimNumericProperty_HEADER +#define ossimNumericProperty_HEADER +#include "ossimProperty.h" + +class OSSIMDLLEXPORT ossimNumericProperty : public ossimProperty +{ +public: + enum ossimNumericPropertyType + { + ossimNumericPropertyType_INT = 0, + ossimNumericPropertyType_UINT, + ossimNumericPropertyType_FLOAT32, + ossimNumericPropertyType_FLOAT64 + }; + + ossimNumericProperty(const ossimString& name=ossimString(""), + const ossimString& value=ossimString("0")); + ossimNumericProperty(const ossimString& name, + const ossimString& value, + double minValue, + double maxValue); + ossimNumericProperty(const ossimNumericProperty& rhs); + virtual ossimObject* dup()const; + virtual const ossimProperty& assign(const ossimProperty& rhs); + + virtual bool hasConstraints()const; + double getMinValue()const; + double getMaxValue()const; + + virtual void clearConstraints(); + virtual void setConstraints(double minValue, + double maxValue); + virtual bool setValue(const ossimString& value); + virtual void valueToString(ossimString& valueResult)const; + + virtual ossimNumericPropertyType getNumericType()const; + virtual void setNumericType(ossimNumericPropertyType type); + + virtual ossim_float64 asFloat64()const; + virtual ossim_float32 asFloat32()const; + virtual ossim_uint32 asUInt32()const; + virtual ossim_uint16 asUInt16()const; + virtual ossim_uint8 asUInt8()const; + virtual ossim_sint32 asInt32()const; + virtual ossim_sint16 asInt16()const; + virtual ossim_sint8 asInt8()const; + +protected: + ossimString theValue; + ossimNumericPropertyType theType; + std::vector<double> theRangeConstraint; +TYPE_DATA +}; + + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimProperty.cpp b/Utilities/OSSIM/ossim_core/base/property/ossimProperty.cpp new file mode 100644 index 0000000000..1d299a4d07 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimProperty.cpp @@ -0,0 +1,168 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimProperty.cpp,v 1.14 2005/06/09 11:25:35 gpotts Exp $ +#include "ossimProperty.h" + + +RTTI_DEF1(ossimProperty, "ossimProperty", ossimObject); + +const ossimProperty& ossimProperty::operator = (const ossimProperty& rhs) +{ + this->assign(rhs); + + return *this; +} + +ossimProperty::ossimProperty(const ossimString& name) + :theName(name), + theReadOnlyFlag(false), + theChangeType(ossimPropertyChangeType_NOTSPECIFIED), + theModifiedFlag(false) +{ +} + +ossimProperty::ossimProperty(const ossimProperty& rhs) + :theName(rhs.theName), + theReadOnlyFlag(rhs.theReadOnlyFlag), + theChangeType(rhs.theChangeType), + theModifiedFlag(rhs.theModifiedFlag) +{ +} + +ossimProperty::~ossimProperty() +{ +} + +const ossimString& ossimProperty::getName()const +{ + return theName; +} + +void ossimProperty::setName(const ossimString& name) +{ + theName = name; +} + +const ossimProperty& ossimProperty::assign(const ossimProperty& rhs) +{ + theName = rhs.theName; + theReadOnlyFlag = rhs.theReadOnlyFlag; + theChangeType = rhs.theChangeType; + theModifiedFlag = rhs.theModifiedFlag; + + return *this; +} + +ossimString ossimProperty::valueToString()const +{ + ossimString result; + + valueToString(result); + + return result; + +} + +void ossimProperty::clearChangeType() +{ + theChangeType = ossimPropertyChangeType_NOTSPECIFIED; +} + +void ossimProperty::setChangeType(ossimPropertyChangeType type) +{ + theChangeType = type; +} + +void ossimProperty::setFullRefreshBit() +{ + theChangeType = (ossimPropertyChangeType)(theChangeType | ossimPropertyChangeType_FULL_REFRESH); +} + +void ossimProperty::setCacheRefreshBit() +{ + theChangeType = (ossimPropertyChangeType)(theChangeType | ossimPropertyChangeType_CACHE_REFRESH); +} + +ossimProperty::ossimPropertyChangeType ossimProperty::getChangeType()const +{ + return theChangeType; +} + +bool ossimProperty::isFullRefresh()const +{ + return ((theChangeType & ossimPropertyChangeType_FULL_REFRESH) != 0); +} + +bool ossimProperty::isCacheRefresh()const +{ + return ((theChangeType & ossimPropertyChangeType_CACHE_REFRESH) != 0); +} + +bool ossimProperty::isChangeTypeSpecified()const +{ + return (theChangeType != ossimPropertyChangeType_NOTSPECIFIED); +} + +void ossimProperty::setReadOnlyFlag(bool flag) +{ + theReadOnlyFlag = flag; +} + +bool ossimProperty::getReadOnlyFlag()const +{ + return theReadOnlyFlag; +} + +bool ossimProperty::isReadOnly()const +{ + return (getReadOnlyFlag()); +} + +void ossimProperty::setModifiedFlag(bool flag) +{ + theModifiedFlag = flag; +} + +bool ossimProperty::getModifiedFlag()const +{ + return theModifiedFlag; +} + +bool ossimProperty::isModified()const +{ + return (theModifiedFlag == true); +} + +void ossimProperty::clearModifiedFlag() +{ + theModifiedFlag = false; +} + +void ossimProperty::setDescription(const ossimString& description) +{ + theDescription = description; +} + +ossimString ossimProperty::getDescription()const +{ + return theDescription; +} diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimProperty.h b/Utilities/OSSIM/ossim_core/base/property/ossimProperty.h new file mode 100644 index 0000000000..0b434d9229 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimProperty.h @@ -0,0 +1,89 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimProperty.h,v 1.15 2005/06/09 11:25:35 gpotts Exp $ +#ifndef ossimProperty_HEADER +#define ossimProperty_HEADER +#include "base/common/ossimObject.h" +#include "base/data_types/ossimString.h" + +class OSSIMDLLEXPORT ossimProperty : public ossimObject +{ +public: + /*! + * This are bitwise and can be ored together + * The change type is very important and + * it determines how things are refreshed. + */ + enum ossimPropertyChangeType + { + ossimPropertyChangeType_NOTSPECIFIED = 0, + ossimPropertyChangeType_CACHE_REFRESH = 1, + ossimPropertyChangeType_FULL_REFRESH = 2 + }; + ossimProperty(const ossimString& name=ossimString("")); + ossimProperty(const ossimProperty& rhs); + virtual ~ossimProperty(); + + const ossimProperty& operator = (const ossimProperty& rhs); + virtual const ossimProperty& assign(const ossimProperty& rhs); + + const ossimString& getName()const; + void setName(const ossimString& name); + + virtual bool setValue(const ossimString& value)=0; + virtual void valueToString(ossimString& valueResult)const=0; + virtual ossimString valueToString()const; + + void clearChangeType(); + void setChangeType(ossimPropertyChangeType type); + void setFullRefreshBit(); + void setCacheRefreshBit(); + + ossimPropertyChangeType getChangeType()const; + bool isFullRefresh()const; + bool isCacheRefresh()const; + bool isChangeTypeSpecified()const; + + void setReadOnlyFlag(bool flag); + bool getReadOnlyFlag()const; + bool isReadOnly()const; + + void setModifiedFlag(bool flag); + bool getModifiedFlag()const; + bool isModified()const; + void clearModifiedFlag(); + + void setDescription(const ossimString& description); + + virtual ossimString getDescription()const; + +protected: + ossimString theName; + ossimString theDescription; + bool theReadOnlyFlag; + ossimPropertyChangeType theChangeType; + bool theModifiedFlag; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimStringListProperty.cpp b/Utilities/OSSIM/ossim_core/base/property/ossimStringListProperty.cpp new file mode 100644 index 0000000000..aa271e98ba --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimStringListProperty.cpp @@ -0,0 +1,272 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimStringListProperty.cpp,v 1.8 2004/01/29 13:29:31 gpotts Exp $ +// +#include <sstream> +#include <algorithm> +#include "ossimStringListProperty.h" +#include "base/data_types/ossimKeywordlist.h" +RTTI_DEF1(ossimStringListProperty, "ossimStringListProperty", ossimProperty); + +ossimStringListProperty::ossimStringListProperty(const ossimString& name, + const std::vector<ossimString>& value) + :ossimProperty(name), + theValueList(value), + theUniqueFlag(false), + theOrderMattersFlag(false) +{ +} + +ossimStringListProperty::ossimStringListProperty(const ossimStringListProperty& rhs) + :ossimProperty(rhs), + theValueList(rhs.theValueList), + theConstraintList(rhs.theConstraintList), + theUniqueFlag(rhs.theUniqueFlag), + theOrderMattersFlag(rhs.theOrderMattersFlag), + theMinNumberOfValues(rhs.theMinNumberOfValues), + theMaxNumberOfValues(rhs.theMaxNumberOfValues) +{ +} + +ossimObject* ossimStringListProperty::dup()const +{ + return new ossimStringListProperty(*this); +} + +const ossimProperty& ossimStringListProperty::assign(const ossimProperty& rhs) +{ + ossimProperty::assign(rhs); + + ossimStringListProperty *rhsPtr = PTR_CAST(ossimStringListProperty, + &rhs); + + if(rhsPtr) + { + theValueList = rhsPtr->theValueList; + theConstraintList = rhsPtr->theConstraintList; + theUniqueFlag = rhsPtr->theUniqueFlag; + theOrderMattersFlag = rhsPtr->theOrderMattersFlag; + theMinNumberOfValues = rhsPtr->theMinNumberOfValues; + theMaxNumberOfValues = rhsPtr->theMaxNumberOfValues; + } + + return *this; +} + +bool ossimStringListProperty::setValue(const ossimString& value) +{ + ossimKeywordlist kwl; + istringstream in(value); + bool result = true; + + if(kwl.parseStream(in)) + { + int idx = 0; + vector<ossimString> keys = + kwl.getSubstringKeyList( "^([0-9]*" ); + + std::vector<int> theNumberList(keys.size()); + for(idx = 0; idx < (int)theNumberList.size();++idx) + { + theNumberList[idx] = keys[idx].toInt(); + } + std::sort(theNumberList.begin(), theNumberList.end()); + clearValueList(); + for(idx = 0; idx < (int)theNumberList.size(); ++idx) + { + const char* temp = kwl.find(ossimString::toString(theNumberList[idx])); + + if(temp) + { + addValue(temp); + } + } + } + else + { + result = false; + } + + return result; +} + +void ossimStringListProperty::valueToString(ossimString& valueResult)const +{ + ossimKeywordlist kwl; + int idx = 0; + + for(idx = 0; idx < (int)theValueList.size(); ++idx) + { + kwl.add(ossimString::toString(idx), + theValueList[idx], + true); + } + + valueResult = kwl.toString(); +} + + +void ossimStringListProperty::clearValueList() +{ + theValueList.clear(); +} + +ossimString ossimStringListProperty::getValueAt(int idx)const +{ + if((idx >= 0)&& + (idx < (int)getNumberOfValues())) + { + return theValueList[idx]; + } + + return ossimString("");; +} + +bool ossimStringListProperty::setValueAt(int idx, + const ossimString& value) +{ + bool result = true; + + if(canAddValue(value)) + { + if((idx < (int)getNumberOfValues())&& + (idx >= 0)) + { + theValueList[idx] = value; + } + } + else + { + result = false; + } + return result; + +} + +bool ossimStringListProperty::addValue(const ossimString& value) +{ + bool result = true; + + if(canAddValue(value)) + { + theValueList.push_back(value); + } + else + { + result = false; + } + + return result; +} + +ossim_uint32 ossimStringListProperty::getNumberOfValues()const +{ + return (int)theValueList.size(); +} + +ossim_uint32 ossimStringListProperty::getNumberOfContraints()const +{ + return theConstraintList.size(); +} + +ossimString ossimStringListProperty::getConstraintAt(ossim_uint32 idx)const +{ + if(idx < theConstraintList.size()) + { + return theConstraintList[(int)idx]; + } + + return ossimString(""); +} + +void ossimStringListProperty::setConstraints(const std::vector<ossimString>& constraints) +{ + theConstraintList = constraints; +} + +bool ossimStringListProperty::hasConstraints()const +{ + return (theConstraintList.size()>0); +} + +void ossimStringListProperty::setUniqueFlag(bool flag) +{ + theUniqueFlag = flag; +} + +void ossimStringListProperty::setOrderMattersFlag(bool flag) +{ + theOrderMattersFlag = flag; +} + +void ossimStringListProperty::setNumberOfValuesBounds(int minNumber, + int maxNumber) +{ + theMinNumberOfValues = minNumber; + theMaxNumberOfValues = maxNumber; +} + +void ossimStringListProperty::getNumberofValuesBounds(int& minNumber, + int& maxNumber)const +{ + minNumber = theMinNumberOfValues; + maxNumber = theMaxNumberOfValues; +} + +bool ossimStringListProperty::findValueInConstraintList(const ossimString& value)const +{ + return (std::find(theConstraintList.begin(), + theConstraintList.end(), + value)!=theConstraintList.end()); +} + +bool ossimStringListProperty::findValueInValueList(const ossimString& value)const +{ + return (std::find(theValueList.begin(), + theValueList.end(), + value)!=theConstraintList.end()); +} + +bool ossimStringListProperty::canAddValue(const ossimString& value)const +{ + bool result = true; + + if(hasConstraints()) + { + if(findValueInConstraintList(value)) + { + if(theUniqueFlag) + { + if(findValueInValueList(value)) + { + result = false; + } + } + } + else + { + result = false; + } + } + + return result; +} diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimStringListProperty.h b/Utilities/OSSIM/ossim_core/base/property/ossimStringListProperty.h new file mode 100644 index 0000000000..5f877b4714 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimStringListProperty.h @@ -0,0 +1,80 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimStringListProperty.h,v 1.7 2004/05/19 18:29:38 dburken Exp $ +// +#ifndef ossimStringListProperty_HEADER +#define ossimStringListProperty_HEADER +#include "ossimProperty.h" + +class OSSIMDLLEXPORT ossimStringListProperty : public ossimProperty +{ +public: + ossimStringListProperty(const ossimString& name=ossimString(""), + const std::vector<ossimString>& value = std::vector<ossimString>()); + ossimStringListProperty(const ossimStringListProperty& rhs); + + ossimObject* dup()const; + virtual const ossimProperty& assign(const ossimProperty& rhs); + virtual bool setValue(const ossimString& value); + virtual void valueToString(ossimString& valueResult)const; + + void clearValueList(); + ossimString getValueAt(int idx)const; + bool setValueAt(int idx, + const ossimString& value); + bool addValue(const ossimString& value); + ossim_uint32 getNumberOfValues()const; + + ossim_uint32 getNumberOfContraints()const; + ossimString getConstraintAt(ossim_uint32 idx)const; + + void setConstraints(const std::vector<ossimString>& constraints); + bool hasConstraints()const; + void setUniqueFlag(bool flag); + void setOrderMattersFlag(bool flag); + + /*! + * You can specify how many values are allowed in the value list + * If any of the values are less than 0 then now constraints are + * placed on that value. So if the min was < 0 then there is + * no minumum number of values. If the max is < 0 then there is + * no maximum number of values. + */ + void setNumberOfValuesBounds(int minNumber, + int maxNumber); + void getNumberofValuesBounds(int& minNumber, + int& maxNumber)const; +protected: + std::vector<ossimString> theValueList; + std::vector<ossimString> theConstraintList; + bool theUniqueFlag; + bool theOrderMattersFlag; + int theMinNumberOfValues; + int theMaxNumberOfValues; + + bool findValueInConstraintList(const ossimString& value)const; + bool findValueInValueList(const ossimString& value)const; + bool canAddValue(const ossimString& value)const; +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimStringProperty.cpp b/Utilities/OSSIM/ossim_core/base/property/ossimStringProperty.cpp new file mode 100644 index 0000000000..92311b636b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimStringProperty.cpp @@ -0,0 +1,127 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// LICENSE: LGPL see top level license.txt +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimStringProperty.cpp,v 1.11 2004/09/22 16:31:08 gpotts Exp $ +#include "ossimStringProperty.h" +#include <algorithm> +RTTI_DEF1(ossimStringProperty, "ossimStringProperty", ossimProperty); + +ossimStringProperty::ossimStringProperty(const ossimString& name, + const ossimString& value, + bool editableFlag, + const std::vector<ossimString>& constraintList) + :ossimProperty(name), + theValue(value), + theEditableFlag(editableFlag), + theConstraints(constraintList) +{ +} + +ossimStringProperty::ossimStringProperty(const ossimStringProperty& rhs) + :ossimProperty(rhs), + theValue(rhs.theValue), + theEditableFlag(rhs.theEditableFlag), + theConstraints(rhs.theConstraints) +{ +} + +ossimObject* ossimStringProperty::dup()const +{ + return new ossimStringProperty(*this); +} + +const ossimProperty& ossimStringProperty::assign(const ossimProperty& rhs) +{ + ossimProperty::assign(rhs); + + ossimStringProperty* rhsPtr = PTR_CAST(ossimStringProperty, + &rhs); + + theValue = rhs.valueToString(); + + if(rhsPtr) + { + theEditableFlag = rhsPtr->theEditableFlag; + theConstraints = rhsPtr->theConstraints; + } + + return *this; +} + + +void ossimStringProperty::setEditableFlag(bool flag) +{ + theEditableFlag = flag; +} + +bool ossimStringProperty::getEditableFlag()const +{ + return theEditableFlag; +} + +bool ossimStringProperty::isEditable()const +{ + return (getEditableFlag() == true); +} + + +void ossimStringProperty::clearConstraints() +{ + theConstraints.clear(); +} + +void ossimStringProperty::setConstraints(const std::vector<ossimString>& constraintList) +{ + theConstraints = constraintList; +} + +void ossimStringProperty::addConstraint(const ossimString& value) +{ + theConstraints.push_back(value); +} + +const std::vector<ossimString>& ossimStringProperty::getConstraints()const +{ + return theConstraints; +} + +bool ossimStringProperty::hasConstraints()const +{ + return (theConstraints.size() > 0); +} + +bool ossimStringProperty::setValue(const ossimString& value) +{ + bool result = true; + + if(theConstraints.size() > 0) + { + if(std::find(theConstraints.begin(), + theConstraints.end(), + value) + != theConstraints.end()) + { + theValue = value; + } + else + { + result = false; + } + } + else + { + theValue = value; + } + + return result; +} + +void ossimStringProperty::valueToString(ossimString& valueResult)const +{ + valueResult = theValue; +} diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimStringProperty.h b/Utilities/OSSIM/ossim_core/base/property/ossimStringProperty.h new file mode 100644 index 0000000000..8506d2205a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimStringProperty.h @@ -0,0 +1,73 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// LICENSE: LGPL see top level license.txt +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimStringProperty.h,v 1.11 2004/09/22 16:31:08 gpotts Exp $ +#ifndef ossimStringProperty_HEADER +#define ossimStringProperty_HEADER +#include "ossimProperty.h" +#include <vector> + +class OSSIMDLLEXPORT ossimStringProperty : public ossimProperty +{ +public: + ossimStringProperty(const ossimString& name = ossimString(""), + const ossimString& value = ossimString(""), + bool editableFlag = true, + const std::vector<ossimString>& constraintList = std::vector<ossimString>()); + + ossimStringProperty(const ossimStringProperty& rhs); + + /*! + * Duplicates the object and returns a new one + */ + virtual ossimObject* dup()const; + + virtual const ossimProperty& assign(const ossimProperty& rhs); + + void setEditableFlag(bool flag); + bool getEditableFlag()const; + bool isEditable()const; + + /*! + * Clears the constraints for this string. You can constrain + * it to a string list by calling setConstraints. + */ + void clearConstraints(); + + /*! + * Sets the constraints for this property. If the editable + * flag is present then this says the editing is not readonly + * and one can hand type the value in without only selecting + * from a choice list. + */ + void setConstraints(const std::vector<ossimString>& constraintList); + + void addConstraint(const ossimString& value); + const std::vector<ossimString>& getConstraints()const; + + bool hasConstraints()const; + + /*! + * will try to set the value. If the constraints are set + * it will make sure that the value is in the list and + * if its not then it will return false + */ + virtual bool setValue(const ossimString& value); + + virtual void valueToString(ossimString& valueResult)const; + + +protected: + ossimString theValue; + bool theEditableFlag; + std::vector<ossimString> theConstraints; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimTextProperty.cpp b/Utilities/OSSIM/ossim_core/base/property/ossimTextProperty.cpp new file mode 100644 index 0000000000..7a9b4273e4 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimTextProperty.cpp @@ -0,0 +1,76 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimTextProperty.cpp,v 1.6 2004/01/29 13:29:31 gpotts Exp $ +#include "ossimTextProperty.h" + +RTTI_DEF1(ossimTextProperty, "ossimTextProperty", ossimProperty); + +ossimTextProperty::ossimTextProperty(const ossimString& name, + const ossimString& value, + bool multiLineFlag) + :ossimProperty(name), + theValue(value), + theMultiLineFlag(multiLineFlag) +{ +} + +ossimTextProperty::ossimTextProperty(const ossimTextProperty& rhs) + :ossimProperty(rhs), + theValue(rhs.theValue), + theMultiLineFlag(rhs.theMultiLineFlag) +{ +} + +ossimObject* ossimTextProperty::dup()const +{ + return new ossimTextProperty(*this); +} + +bool ossimTextProperty::isMulitLine()const +{ + return theMultiLineFlag; +} + +void ossimTextProperty::setMultiLineFlag(bool flag) +{ + theMultiLineFlag = flag; +} + +bool ossimTextProperty::setValue(const ossimString& value) +{ + theValue = value; + + return true; +} + +void ossimTextProperty::valueToString(ossimString& valueResult)const +{ + valueResult = theValue; +} + +const ossimProperty& ossimTextProperty::assign(const ossimProperty& rhs) +{ + theValue = rhs.valueToString(); + + return *this; +} + diff --git a/Utilities/OSSIM/ossim_core/base/property/ossimTextProperty.h b/Utilities/OSSIM/ossim_core/base/property/ossimTextProperty.h new file mode 100644 index 0000000000..004bb3e584 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/base/property/ossimTextProperty.h @@ -0,0 +1,50 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimTextProperty.h,v 1.7 2004/05/19 18:29:38 dburken Exp $ +#ifndef ossimTextProperty_HEADER +#define ossimTextProperty_HEADER +#include "ossimProperty.h" + +class OSSIMDLLEXPORT ossimTextProperty : public ossimProperty +{ +public: + ossimTextProperty(const ossimString& name = ossimString(""), + const ossimString& value = ossimString(""), + bool isMultiLine = false); + ossimTextProperty(const ossimTextProperty& rhs); + virtual ossimObject* dup()const; + + bool isMulitLine()const; + void setMultiLineFlag(bool flag); + + virtual void valueToString(ossimString& valueResult)const; + virtual bool setValue(const ossimString& value); + virtual const ossimProperty& assign(const ossimProperty& rhs); + +protected: + ossimString theValue; + bool theMultiLineFlag; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/dll_main/Makefile b/Utilities/OSSIM/ossim_core/dll_main/Makefile new file mode 100644 index 0000000000..fcb07e56e3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/dll_main/Makefile @@ -0,0 +1,10 @@ +### +# $Id: Makefile,v 1.1 2005/08/01 14:59:59 dburken Exp $ +# Intentionally left blank for unix build. +### + +all: + +depends: + +clean: diff --git a/Utilities/OSSIM/ossim_core/dll_main/ossimDllMain.cpp b/Utilities/OSSIM/ossim_core/dll_main/ossimDllMain.cpp new file mode 100644 index 0000000000..04881d0d28 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/dll_main/ossimDllMain.cpp @@ -0,0 +1,13 @@ +// This is the main DLL file. +#include <windows.h> +#include "ossimDllMain.h" + +extern "C" +BOOL WINAPI DllMain(HINSTANCE hInstance, /* handle to DLL module */ + DWORD dwReason, /* reason for calling function */ + LPVOID lpReserved )/* reserved */ +{ + /* Nothing to do here yet. */ + return TRUE; +} + diff --git a/Utilities/OSSIM/ossim_core/dll_main/ossimDllMain.h b/Utilities/OSSIM/ossim_core/dll_main/ossimDllMain.h new file mode 100644 index 0000000000..224e4d101c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/dll_main/ossimDllMain.h @@ -0,0 +1,7 @@ +// ossim_core_project.h + + +namespace ossim_core_project +{ + +} diff --git a/Utilities/OSSIM/ossim_core/elevation/.cvsignore b/Utilities/OSSIM/ossim_core/elevation/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/elevation/CMakeLists.txt b/Utilities/OSSIM/ossim_core/elevation/CMakeLists.txt new file mode 100644 index 0000000000..0b5f0dd2cb --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/CMakeLists.txt @@ -0,0 +1,6 @@ +FILE(GLOB_RECURSE ossim_elevation_SRCS "*.cpp") +FILE(GLOB_RECURSE ossim_elevation_HDRS "*.h") +ADD_LIBRARY(ossim_elevation ${ossim_elevation_SRCS}) + +INSTALL_TARGETS(/lib/otb/ ossim_elevation) +INSTALL_FILES(/include/otb/Utilities/OSSIM/ossim_core/ "\\.h$" ${ossim_elevation_HRDS}) diff --git a/Utilities/OSSIM/ossim_core/elevation/formats/.cvsignore b/Utilities/OSSIM/ossim_core/elevation/formats/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/formats/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/elevation/formats/dted_cell/.cvsignore b/Utilities/OSSIM/ossim_core/elevation/formats/dted_cell/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/formats/dted_cell/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/elevation/formats/dted_cell/ossimDtedFactory.cpp b/Utilities/OSSIM/ossim_core/elevation/formats/dted_cell/ossimDtedFactory.cpp new file mode 100644 index 0000000000..c95559b084 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/formats/dted_cell/ossimDtedFactory.cpp @@ -0,0 +1,168 @@ +//************************************************************************** +// FILE: ossimDtedFactory.cc +// +// Copyright (C) 2002 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Class definition for ossimDtedFactory. +// +// This is the base class interface for elevation source factories. Contains +// pure virtual methods that all elevation source factories must implement. +// +//************************************************************************** +// $Id: ossimDtedFactory.cpp,v 1.13 2005/11/18 20:24:49 gpotts Exp $ + +#include <sstream> +#include <iomanip> +#include <elevation/formats/dted_cell/ossimDtedFactory.h> +#include <elevation/formats/dted_cell/ossimDtedHandler.h> +#include <base/common/ossimTrace.h> +#include <base/data_types/ossimGpt.h> +#include <elevation/ossimElevManager.h> +#include <base/context/ossimNotifyContext.h> + +static ossimTrace traceDebug ("ossimDtedFactory:debug"); + +RTTI_DEF1(ossimDtedFactory, "ossimDtedFactory", ossimElevSourceFactory) + +ossimDtedFactory::ossimDtedFactory() + : ossimElevSourceFactory() +{} + +ossimDtedFactory::ossimDtedFactory(const ossimFilename& dir) + : ossimElevSourceFactory() +{ + theDirectory = dir; +} + +ossimDtedFactory::~ossimDtedFactory() +{} + +ossimElevSource* ossimDtedFactory::getNewElevSource(const ossimGpt& gpt) const +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimDtedFactory::getNewElevSource: Entered..." + << std::endl; + } + + ossimElevManager* mgr = ossimElevManager::instance(); + + ossimElevSource* dted_ptr = NULL; + + if (theDirectory == ossimFilename::NIL) + { + ossimNotify(ossimNotifyLevel_FATAL) + << "FATAL ossimDtedFactory::getNewElevSource: " + << "DTED directory has not been set!" + << "\nReturning null elevation source..." + << std::endl; + return dted_ptr; + } + + // Build up a dted file name. + ossimFilename dted_file_base; + + int ilon = static_cast<int>(floor(gpt.lond())); + + if (ilon < 0) + { + dted_file_base = "w"; + } + else + { + dted_file_base = "e"; + } + + ilon = abs(ilon); + ostringstream s1; + s1<< setfill('0')<<setw(3)<< ilon; + + dted_file_base += s1.str().c_str();//ossimString::toString(ilon); + dted_file_base += "/"; + + int ilat = static_cast<int>(floor(gpt.latd())); + if (ilat < 0) + { + dted_file_base += "s"; + } + else + { + dted_file_base += "n"; + } + + ilat = abs(ilat); + ostringstream s2; + + s2<< setfill('0')<<setw(2)<<ilat; + + dted_file_base += s2.str().c_str(); + + // Look for a dted file with a level 2 extension first. + ossimFilename dted_name = theDirectory.dirCat(dted_file_base); + dted_name += ".dt2"; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimDtedFactory::getNewElevSource:" + << "\nSearching for file: " << dted_name + << std::endl; + } + + if (dted_name.exists() && !(mgr->isCellOpen(dted_name)) ) + { + dted_ptr = new ossimDtedHandler(dted_name); + if ( (!(dted_ptr->getErrorStatus())) && + dted_ptr->pointHasCoverage(gpt) ) + { + return dted_ptr; + } + else + { + delete dted_ptr; + dted_ptr = NULL; + } + } + + // Look for a dted file with a level 1 extension next. + dted_name = theDirectory.dirCat(dted_file_base); + dted_name += ".dt1"; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimDtedFactory::getNewElevSource:" + << "\nSearching for file: " << dted_name + << std::endl; + } + + if (dted_name.exists() && !(mgr->isCellOpen(dted_name)) ) + { + dted_ptr = new ossimDtedHandler(dted_name); + if ( (!(dted_ptr->getErrorStatus())) && + dted_ptr->pointHasCoverage(gpt) ) + { + return dted_ptr; + } + else + { + delete dted_ptr; + dted_ptr = NULL; + } + } + + return dted_ptr; +} + +void ossimDtedFactory::createIndex() +{ +} diff --git a/Utilities/OSSIM/ossim_core/elevation/formats/dted_cell/ossimDtedFactory.h b/Utilities/OSSIM/ossim_core/elevation/formats/dted_cell/ossimDtedFactory.h new file mode 100644 index 0000000000..ddd795f0cd --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/formats/dted_cell/ossimDtedFactory.h @@ -0,0 +1,38 @@ +//***************************************************************************** +// FILE: ossimDtedFactory.cc +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Class declaration for ossimDtedFactory. +// This is the base class interface for elevation cell factories. +//***************************************************************************** +// $Id: ossimDtedFactory.h,v 1.6 2005/11/18 20:24:49 gpotts Exp $ +#ifndef ossimDtedFactory_HEADER +#define ossimDtedFactory_HEADER + +#include <elevation/ossimElevSourceFactory.h> + +/** CLASS: ossimDtedFactory */ +class OSSIM_DLL ossimDtedFactory : public ossimElevSourceFactory +{ +public: + + ossimDtedFactory(); + ossimDtedFactory(const ossimFilename& dir); + + virtual ~ossimDtedFactory(); + + virtual ossimElevSource* getNewElevSource(const ossimGpt& gpt) const; + virtual void createIndex(); +protected: + +TYPE_DATA +}; + +#endif /* End of "#ifndef ossimDtedFactory_HEADER" */ diff --git a/Utilities/OSSIM/ossim_core/elevation/formats/dted_cell/ossimDtedHandler.cpp b/Utilities/OSSIM/ossim_core/elevation/formats/dted_cell/ossimDtedHandler.cpp new file mode 100644 index 0000000000..90f76ca609 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/formats/dted_cell/ossimDtedHandler.cpp @@ -0,0 +1,460 @@ +//***************************************************************************** +// FILE: ossimDtedHandler.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// DESCRIPTION: +// Contains implementation of class ossimDtedHandler. This class derives from +// ossimElevHandler. It is responsible for loading an individual DTED cell +// from disk. This elevation files are memory mapped. +// +//***************************************************************************** +// $Id: ossimDtedHandler.cpp,v 1.31 2005/03/04 13:35:53 gpotts Exp $ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <elevation/formats/dted_cell/ossimDtedHandler.h> +#include <support_data/dted/ossimDtedVol.h> +#include <support_data/dted/ossimDtedHdr.h> +#include <support_data/dted/ossimDtedUhl.h> +#include <support_data/dted/ossimDtedDsi.h> +#include <support_data/dted/ossimDtedAcc.h> +#include <support_data/dted/ossimDtedRecord.h> +#include <base/common/ossimCommon.h> +#include <base/common/ossimKeywordNames.h> +#include <base/context/ossimNotifyContext.h> +#include <base/data_types/ossimGpt.h> +#include <base/data_types/ossimKeywordlist.h> + +RTTI_DEF1(ossimDtedHandler, "ossimDtedHandler" , ossimElevCellHandler) + +//*** +// Define Trace flags for use within this file: +//*** +#include <base/common/ossimTrace.h> +static ossimTrace traceExec ("ossimDtedHandler:exec"); +static ossimTrace traceDebug ("ossimDtedHandler:debug"); + +static const char ENABLE_STATS_KW[] = "elevation.compute_statistics.enabled"; + + +ossimDtedHandler::ossimDtedHandler(const ossimFilename& dted_file) + : + ossimElevCellHandler(dted_file), + theFileStr(), + theNumLonLines(0), + theNumLatPoints(0), + theDtedRecordSizeInBytes(0), + theEdition(), + theProductLevel(), + theCompilationDate(), + theOffsetToFirstDataRecord(0), + theLatSpacing(0.0), + theLonSpacing(0.0), + theSwCornerPost(), + theSwapBytesFlag(false) +{ + static const char MODULE[] = "ossimDtedHandler (Filename) Constructor"; + if (traceExec()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG " << MODULE <<": entering..." << std::endl; + } + + //--- + // Open the dted file for reading. + //--- + if (!open()) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_FATAL) + << "FATAL " << MODULE << ": " + << "\nCould not open file: " << dted_file.c_str() + << "\nReturning..." << std::endl; + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG " << MODULE << ": returning with error..." << std::endl; + } + return; + } + else + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG " << MODULE <<": Loading dted file: " << dted_file + << std::endl; + } + } + + // DTED is stored in big endian. + theSwapBytesFlag = ossimGetByteOrder() == OSSIM_LITTLE_ENDIAN ? true : false; + + // Attempt to parse. + ossimDtedVol vol(theFileStr, 0); + ossimDtedHdr hdr(theFileStr, vol.stopOffset()); + ossimDtedUhl uhl(theFileStr, hdr.stopOffset()); + ossimDtedDsi dsi(theFileStr, uhl.stopOffset()); + ossimDtedAcc acc(theFileStr, dsi.stopOffset()); + + //*** + // Check for errors. Must have uhl, dsi and acc records. vol and hdr + // are for magnetic tape only; hence, may or may not be there. + //*** + if (uhl.getErrorStatus() == ossimErrorCodes::OSSIM_ERROR || + dsi.getErrorStatus() == ossimErrorCodes::OSSIM_ERROR || + acc.getErrorStatus() == ossimErrorCodes::OSSIM_ERROR) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG " << MODULE << ": " + << "\nError parsing file: " << dted_file.c_str() + << "\nPossibly not a dted file." + << endl; + } + + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + theFileStr.close(); + return; + } + + theNumLonLines = uhl.numLonLines(); + theNumLatPoints = uhl.numLatPoints(); + theLatSpacing = uhl.latInterval(); + theLonSpacing = uhl.lonInterval(); + theDtedRecordSizeInBytes = theNumLatPoints*2+ossimDtedRecord::DATA_LENGTH; + + theEdition = dsi.edition(); + theProductLevel = dsi.productLevel(); + theCompilationDate = dsi.compilationDate(); + + theOffsetToFirstDataRecord = acc.stopOffset(); + + //*** + // initialize the bounding rectangle: + //*** + double south_boundary = uhl.latOrigin(); + double west_boundary = uhl.lonOrigin(); + double north_boundary = south_boundary + theLatSpacing*(theNumLatPoints-1); + double east_boundary = west_boundary + theLonSpacing*(theNumLonLines-1); + + theGroundRect = ossimGrect(ossimGpt(north_boundary, west_boundary, 0.0), + ossimGpt(south_boundary, east_boundary, 0.0)); + + theSwCornerPost.lat = south_boundary; + theSwCornerPost.lon = west_boundary; + + //*** + // Determine the mean spacing: + //*** + double center_lat = (south_boundary + north_boundary)/2.0; + theMeanSpacing = (theLatSpacing + theLonSpacing*cosd(center_lat)) + * ossimGpt().metersPerDegree().x / 2.0; + + // Initialize the accuracy values: + theAbsLE90 = (double) acc.absLE(); + theAbsCE90 = (double) acc.absCE(); + + // Set the base class null height value. + theNullHeightValue = -32767.0; + + // Get the statistics. + gatherStatistics(); + + if (traceExec()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG " << MODULE << ": returning..." << endl; + } +} + +ossimDtedHandler::~ossimDtedHandler() +{ + theFileStr.close(); +} + +double ossimDtedHandler::getHeightAboveMSL(const ossimGpt& gpt) +{ + // Establish the grid indexes: + double xi = (gpt.lon - theSwCornerPost.lon) / theLonSpacing; + double yi = (gpt.lat - theSwCornerPost.lat) / theLatSpacing; + + // Check for right edge. + int x0 = static_cast<int>(xi); + int y0 = static_cast<int>(yi); + + // Check for right edge. + if (gpt.lon == theGroundRect.lr().lon) + { + --x0; // Move over one post. + } + + // Check for top edge. + if (gpt.lat == theGroundRect.ul().lat) + { + --y0; // Move down one post. + } + + // Do some error checking. + if ( xi < 0.0 || yi < 0.0 || + x0 > (theNumLonLines - 2.0) || + y0 > (theNumLatPoints - 2.0) ) + { + return theNullHeightValue; + } + + // We need an open stream to file from here on out... + if (!open()) + { + return theNullHeightValue; + } + + double p00; + double p01; + double p10; + double p11; + + //*** + // Grab the four points from the dted cell needed. These are big endian, + // signed magnitude shorts so they must be interpreted accordingly. + //*** + int offset = theOffsetToFirstDataRecord + x0 * theDtedRecordSizeInBytes + + y0 * 2 + DATA_RECORD_OFFSET_TO_POST; + + // Put the file pointer at the start of the first elevation post. + theFileStr.seekg(offset, ios::beg); + + ossim_sint16 ss; + ossim_uint16 us; + + // Get the first post. + theFileStr.read((char*)&us, POST_SIZE); + ss = convertSignedMagnitude(us); + p00 = ss; + + // Get the second post. + theFileStr.read((char*)&us, POST_SIZE); + ss = convertSignedMagnitude(us); + p01 = ss; + + // Move over to the next column. + offset += theDtedRecordSizeInBytes; + theFileStr.seekg(offset, ios::beg); + + // Get the third post. + theFileStr.read((char*)&us, POST_SIZE); + ss = convertSignedMagnitude(us); + p10 = ss; + + // Get the fourth post. + theFileStr.read((char*)&us, POST_SIZE); + ss = convertSignedMagnitude(us); + p11 = ss; + + // Perform bilinear interpolation: + double wx1 = xi - x0; + double wy1 = yi - y0; + double wx0 = 1.0 - wx1; + double wy0 = 1.0 - wy1; + + double w00 = wx0*wy0; + double w01 = wx0*wy1; + double w10 = wx1*wy0; + double w11 = wx1*wy1; + + //*** + // Test for null posts and set the corresponding weights to 0: + //*** + if (p00 == NULL_POST) + w00 = 0.0; + if (p01 == NULL_POST) + w01 = 0.0; + if (p10 == NULL_POST) + w10 = 0.0; + if (p11 == NULL_POST) + w11 = 0.0; + +#if 0 /* Serious debug only... */ + cout << "\np00: " << p00 + << "\np01: " << p01 + << "\np10: " << p10 + << "\np11: " << p11 + << "\nw00: " << w00 + << "\nw01: " << w01 + << "\nw10: " << w10 + << "\nw11: " << w11 + << endl; +#endif + + double sum_weights = w00 + w01 + w10 + w11; + + if (sum_weights) + { + return (p00*w00 + p01*w01 + p10*w10 + p11*w11) / sum_weights; + } + + return NULL_POST; +} + +double ossimDtedHandler::getPostValue(const ossimIpt& gridPt) const +{ + static const char MODULE[] = "ossimDtedHandler::getPostValue"; + + // Do some error checking. + if ( gridPt.x < 0.0 || gridPt.y < 0.0 || + gridPt.x > (theNumLonLines - 1) || + gridPt.y > (theNumLatPoints - 1) ) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "WARNING " << MODULE << ": No intersection..." << std::endl; + } + return theNullHeightValue; + } + + if (!open()) + { + return theNullHeightValue; + } + + int offset = + theOffsetToFirstDataRecord + gridPt.x * theDtedRecordSizeInBytes + + gridPt.y * 2 + DATA_RECORD_OFFSET_TO_POST; + + // Put the file pointer at the start of the first elevation post. + theFileStr.seekg(offset, ios::beg); + + ossim_uint16 us; + + // Get the post. + theFileStr.read((char*)&us, POST_SIZE); + return double(convertSignedMagnitude(us)); +} + +void ossimDtedHandler::gatherStatistics() +{ + //*** + // Check to see if there is a statistics file already. If so; do a lookup + // for the min and max values. + //*** + ossimFilename stats_file = theFilename;//theFilename.path(); + stats_file.setExtension("statistics"); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimDtedHandler::gatherStatistics(): Looking for " + << stats_file << " statistics file..." << std::endl; + } + + ossimKeywordlist kwl; + const char* min_str = NULL; + const char* max_str = NULL; + + if (stats_file.exists()) + { + if (kwl.addFile(stats_file)) + { + // Look for the min_pixel_value keyword. + min_str = kwl.find(ossimKeywordNames::MIN_VALUE_KW); + max_str = kwl.find(ossimKeywordNames::MAX_VALUE_KW); + } + } + + if (min_str && max_str) + { + theMinHeightAboveMSL = atoi(min_str); + theMaxHeightAboveMSL = atoi(max_str); + } + else if (theComputeStatsFlag) // Scan the cell and gather the statistics... + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_NOTICE) + << "NOTICE ossimDtedHandler::gatherStatistics():" + << " scanning for min/max" + << "\nThis may take a while..." << std::endl; + } + // Start off with the min and max pegged. + theMinHeightAboveMSL = 32767; + theMaxHeightAboveMSL = -32767; + + // Put the file pointer at the start of the first elevation post. + theFileStr.seekg(theOffsetToFirstDataRecord, ios::beg); + + //--- + // Loop through all records and scan for lowest min and highest max. + // Each record contains a row of latitude points for a given longitude. + // There are eight bytes in front of the post and four checksum bytes at + // the end so ignore them. + //--- + for (ossim_int32 i=0; i<theNumLonLines; ++i) // longitude direction + { + theFileStr.seekg(DATA_RECORD_OFFSET_TO_POST, ios::cur); + + for (ossim_int32 j=0; j<theNumLatPoints; ++j) // latitude direction + { + ossim_uint16 us; + ossim_sint16 ss; + theFileStr.read((char*)&us, POST_SIZE); + ss = convertSignedMagnitude(us); + if (ss < theMinHeightAboveMSL && ss != NULL_POST) + { + theMinHeightAboveMSL = ss; + } + if (ss > theMaxHeightAboveMSL) + { + theMaxHeightAboveMSL = ss; + } + } + + theFileStr.seekg(DATA_RECORD_CHECKSUM_SIZE, ios::cur); + } + + // Add the stats to the keyword list. + kwl.add(ossimKeywordNames::MIN_VALUE_KW, theMinHeightAboveMSL); + kwl.add(ossimKeywordNames::MAX_VALUE_KW, theMaxHeightAboveMSL); + + // Write out the statistics file. + kwl.write(stats_file.c_str()); + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimDtedHandler::gatherStatistics:" + << "\ntheMinHeightAboveMSL: " << theMinHeightAboveMSL + << "\ntheMaxHeightAboveMSL: " << theMaxHeightAboveMSL + << std::endl; + } +} + +ossimIpt ossimDtedHandler::getSizeOfElevCell() const +{ + return ossimIpt(theNumLonLines, theNumLatPoints); +} + +ossimString ossimDtedHandler::edition() const +{ + return theEdition; +} + +ossimString ossimDtedHandler::productLevel() const +{ + return theProductLevel; +} + +ossimString ossimDtedHandler::compilationDate() const +{ + return theCompilationDate; +} + diff --git a/Utilities/OSSIM/ossim_core/elevation/formats/dted_cell/ossimDtedHandler.h b/Utilities/OSSIM/ossim_core/elevation/formats/dted_cell/ossimDtedHandler.h new file mode 100644 index 0000000000..0ab8a54366 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/formats/dted_cell/ossimDtedHandler.h @@ -0,0 +1,156 @@ +//***************************************************************************** +// FILE: ossimDtedHandler.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// DESCRIPTION: +// Contains declaration of class ossimDtedHandler. This class derives from +// ossimElevHandler. It is responsible for loading an individual DTED cell +// from disk. This elevation files are memory mapped. +// +// SOFTWARE HISTORY: +//> +// 05Feb2001 Ken Melero +// Initial coding of ossimDted.h +// 19Apr2001 Oscar Kramer +// Derived from ossimElevCellHandler. +//< +//***************************************************************************** +// $Id: ossimDtedHandler.h,v 1.19 2005/03/03 21:57:55 dburken Exp $ + +#ifndef ossimDtedHandler_HEADER +#define ossimDtedHandler_HEADER + +#include <fstream> + +#include <base/data_types/ossimString.h> +#include <elevation/formats/ossimElevCellHandler.h> + +class ossimDtedHandler : public ossimElevCellHandler +{ +public: + ossimDtedHandler(const ossimFilename& dted_file); + + virtual ~ossimDtedHandler(); + + enum + { + DATA_RECORD_OFFSET_TO_POST = 8, // bytes + DATA_RECORD_CHECKSUM_SIZE = 4, // bytes + POST_SIZE = 2, // bytes + NULL_POST = -32767 // Fixed by DTED specification. + }; + + /*! + * METHOD: getHeightAboveMSL + * Height access methods. + */ + virtual double getHeightAboveMSL(const ossimGpt&); + + /*! + * METHOD: getSizeOfElevCell + * Returns the number of post in the cell. Satisfies pure virtual. + * Note: x = longitude, y = latitude + */ + virtual ossimIpt getSizeOfElevCell() const; + + /*! + * METHOD: getPostValue + * Returns the value at a given grid point as a double. + * Satisfies pure virtual. + */ + virtual double getPostValue(const ossimIpt& gridPt) const; + + ossimString edition() const; + ossimString productLevel() const; + ossimString compilationDate() const; + + /** + * Opens a stream to the dted cell. + * + * @return Returns true on success, false on error. + */ + virtual bool open() const; + + /** + * Closes the stream to the file. + */ + virtual void close() const; + +private: + // Disallow operator= and copy constrution... + const ossimDtedHandler& operator=(const ossimDtedHandler& rhs) + { return rhs; } + ossimDtedHandler(const ossimDtedHandler&){} + + /*! + * If statistics file exist, stats will be initialized from that; else, + * this scans the dted cell and gets stats, then, writes new stats file. + * The statistics file will be named accordingly: + * If dted cell = n27.dt1 then the stats file = n27.statistics. + * Currently method only grabs the min and max posts value. + */ + void gatherStatistics(); + + ossim_sint16 convertSignedMagnitude(ossim_uint16& s) const; + + mutable ifstream theFileStr; + ossim_int32 theNumLonLines; // east-west dir + ossim_int32 theNumLatPoints; // north-south + ossim_int32 theDtedRecordSizeInBytes; + ossimString theEdition; + ossimString theProductLevel; + ossimString theCompilationDate; + ossim_int32 theOffsetToFirstDataRecord; + double theLatSpacing; // degrees + double theLonSpacing; // degrees + ossimDpt theSwCornerPost; // cell origin; + + // Indicates whether byte swapping is needed. + bool theSwapBytesFlag; + + TYPE_DATA +}; + +inline ossim_sint16 ossimDtedHandler::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 << 8) | (s >> 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); +} + +inline bool ossimDtedHandler::open() const +{ + if (theFileStr.is_open()) + { + return true; + } + + theFileStr.open(theFilename.c_str(), ios::in | ios::binary); + + return theFileStr.is_open(); +} + +inline void ossimDtedHandler::close() const +{ + if (theFileStr.is_open()) + { + theFileStr.close(); + } +} + +#endif diff --git a/Utilities/OSSIM/ossim_core/elevation/formats/ossimElevCellHandler.cpp b/Utilities/OSSIM/ossim_core/elevation/formats/ossimElevCellHandler.cpp new file mode 100644 index 0000000000..cfcd129212 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/formats/ossimElevCellHandler.cpp @@ -0,0 +1,88 @@ +//***************************************************************************** +// FILE: ossimElevCellHandler.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// DESCRIPTION: +// Contains implementation of class ossimElevCellHandler. This is the base +// class for all DEM file readers including DTED. Each file shall have its +// corresponding ossimElevCellHandler. When more than one file is accessed, +// an ossimElevCombiner is used which owns multiple instances of this class. +// +// SOFTWARE HISTORY: +//> +// 19Apr2001 Oscar Kramer +// Initial coding. +//< +//***************************************************************************** + +#include <elevation/formats/ossimElevCellHandler.h> +#include <base/data_types/ossimKeyword.h> +#include <base/data_types/ossimGpt.h> + +RTTI_DEF1(ossimElevCellHandler, "ossimElevCellHandler" , ossimElevSource) + +//*** +// Define Trace flags for use within this file: +//*** +#include "base/common/ossimTrace.h" +static ossimTrace traceExec ("ossimElevCellHandler:exec"); +static ossimTrace traceDebug ("ossimElevCellHandler:debug"); + +static const ossimKeyword DEM_FILENAME_KW ("dem_filename", + "Name of DEM file to load."); +static const ossimIpt ZERO_SIZE_IPT (0, 0); + +ossimElevCellHandler::ossimElevCellHandler () +{ +} + +ossimElevCellHandler::ossimElevCellHandler(const char* filename) + : + theFilename (filename) +{} + +ossimElevCellHandler::~ossimElevCellHandler() +{} + +ossimFilename ossimElevCellHandler::getFilename() const +{ + return theFilename; +} + +double ossimElevCellHandler::getMeanSpacingMeters() const +{ + return theMeanSpacing; +} + +double ossimElevCellHandler::getAccuracyLE90(const ossimGpt&) const +{ + return theAbsLE90; +} + +double ossimElevCellHandler::getAccuracyCE90(const ossimGpt&) const +{ + return theAbsCE90; +} + +bool ossimElevCellHandler::canConnectMyInputTo( + ossim_int32 inputIndex, + const ossimConnectableObject* object) const +{ + return false; +} + +// Hidden from use. +ossimElevCellHandler::ossimElevCellHandler (const ossimElevCellHandler&) +{ +} + +const ossimElevCellHandler& ossimElevCellHandler::operator=( + const ossimElevCellHandler& rhs) +{ + return rhs; +} diff --git a/Utilities/OSSIM/ossim_core/elevation/formats/ossimElevCellHandler.h b/Utilities/OSSIM/ossim_core/elevation/formats/ossimElevCellHandler.h new file mode 100644 index 0000000000..d88c83907d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/formats/ossimElevCellHandler.h @@ -0,0 +1,115 @@ +//***************************************************************************** +// FILE: ossimElevCellHandler.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// DESCRIPTION: +// Contains declaration of class osimElevHandler. This class provides a +// base-class interface for the various DEM file formats. +// +// SOFTWARE HISTORY: +//> +// 13Apr2001 Oscar Kramer +// Initial coding. +//< +//***************************************************************************** +// $Id: ossimElevCellHandler.h,v 1.14 2005/01/22 16:46:02 dburken Exp $ + + +#ifndef ossimElevCellHandler_HEADER +#define ossimElevCellHandler_HEADER + +#include <elevation/ossimElevSource.h> +#include <base/data_types/ossimFilename.h> +#include <base/data_types/ossimIpt.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimGpt.h> +#include <base/data_types/ossimDrect.h> + +// class ossimDblGrid; + +/****************************************************************************** + * + * CLASS: ossimElevCellHandler + * + *****************************************************************************/ +class ossimElevCellHandler : public ossimElevSource +{ +public: + /** + * Constructors: + */ + + ossimElevCellHandler (const char* elev_filename); + + virtual ~ossimElevCellHandler(); + + virtual ossimFilename getFilename() const; + + + /** + * METHOD: getSizeOfElevCell + * Returns the number of post in the cell. + * Note: x = longitude, y = latitude + */ + virtual ossimIpt getSizeOfElevCell() const = 0; + + /** + * METHOD: getPostValue + * Returns the value at a given grid point as a double. + */ + virtual double getPostValue(const ossimIpt& gridPt) const = 0; + + /** + * METHOD: meanSpacingMeters() + * Implements pure virtual for. This method is used for deterrming + * preferred DEM among multiple overlapping elev sources: + */ + virtual double getMeanSpacingMeters() const; + + /** + * METHOD: pointIsInsideRect() + * Method to check if the ground point elevation is defined: + */ + virtual bool pointHasCoverage(const ossimGpt&) const; + + /** + * METHODS: accuracyLE90(), accuracyCE90() + * Returns the vertical and horizontal accuracy (90% confidence): + */ + virtual double getAccuracyLE90(const ossimGpt&) const; + virtual double getAccuracyCE90(const ossimGpt&) const; + + bool canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const; + +protected: + ossimElevCellHandler (); + + /** + * Virtual method for reading + */ + ossimFilename theFilename; + double theMeanSpacing; // meters + double theAbsLE90; + double theAbsCE90; + +private: + // disallow... + ossimElevCellHandler (const ossimElevCellHandler&); + const ossimElevCellHandler& operator=(const ossimElevCellHandler& rhs); + + +TYPE_DATA +}; + +inline bool ossimElevCellHandler::pointHasCoverage(const ossimGpt& gpt) const +{ + return theGroundRect.pointWithin(gpt); +} + +#endif diff --git a/Utilities/OSSIM/ossim_core/elevation/formats/ossimElevCellHandlerFactory.cpp b/Utilities/OSSIM/ossim_core/elevation/formats/ossimElevCellHandlerFactory.cpp new file mode 100644 index 0000000000..f31a745487 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/formats/ossimElevCellHandlerFactory.cpp @@ -0,0 +1,130 @@ +//***************************************************************************** +// FILE: ossimElevCellHandlerFactory.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// DESCRIPTION: +// Contains implementation of class ossimElevCellHandlerFactory. This is +// a "super-factory" owning a list of subfactories for each particular DEM +// format class. +// +// NOT CURRENTLY UTILIZED -- USE DTED MANAGER +// +// LIMITATIONS: +// The intention of this factory is to produce individual instances of +// elevation cell handlers. Presently this is not supported since DTED is +// the only elevation source being handled. DTED is loaded via the +// ossimDtedManager class as a DB interface, and not by accessing individual +// DTED handlers. +// +// SOFTWARE HISTORY: +//> +// 01Aug2001 Oscar Kramer (okramer@imagelinks.com) +// Initial coding. +//< +//***************************************************************************** +// $Id: ossimElevCellHandlerFactory.cpp,v 1.2 2005/01/22 16:46:02 dburken Exp $ + +#include "ossimElevCellHandlerFactory.h" +#include "base/data_types/ossimString.h" + +ossimElevCellHandlerFactory* ossimElevCellHandlerFactory::theInstance = 0; + +//***************************************************************************** +// STATIC METHOD: instance() +// +//***************************************************************************** +ossimElevCellHandlerFactory* ossimElevCellHandlerFactory::instance() +{ + if(!theInstance) + theInstance = new ossimElevCellHandlerFactory; + + return (ossimElevCellHandlerFactory*) theInstance; +} + +//***************************************************************************** +// PROTECTED DEFAULT CONSTRUCTOR: ossimElevCellHandlerFactory +// +//***************************************************************************** +ossimElevCellHandlerFactory::ossimElevCellHandlerFactory() +{ + //*** + // Add default sub factories to this factory's registry list: + // NOTE: DTED handlers are managed by their own ossimDtedManager so should + // never be created individually via a factory. This will be the typical + // pattern for all but custom DEM files. + //*** +// registerFactory(ossimUsgsDemCellFactory::instance()); +} + + +//***************************************************************************** +// METHOD: ossimElevCellHandlerFactory::create(kwl, prefix) +// +//***************************************************************************** +ossimElevCellHandler* +ossimElevCellHandlerFactory::create(const ossimKeywordlist &keywordList, + const char *prefix) const +{ + list<ossimFactoryBase<ossimElevCellHandler>*>::const_iterator + elevCellFactory; + + ossimElevCellHandler* product = 0; + + elevCellFactory = theRegistry.begin(); + while((elevCellFactory != theRegistry.end()) && (!product)) + { + product = (*elevCellFactory)->create(keywordList, prefix); + elevCellFactory++; + } + + return product; +} + +//***************************************************************************** +// METHOD: ossimElevCellHandlerFactory::create(proj_name) +// +//***************************************************************************** +ossimElevCellHandler* +ossimElevCellHandlerFactory::create(const ossimString &name) const +{ + list<ossimFactoryBase<ossimElevCellHandler>*>::const_iterator + elevCellFactory; + + ossimElevCellHandler* product = 0; + + elevCellFactory = theRegistry.begin(); + while((elevCellFactory != theRegistry.end()) && (!product)) + { + product = (*elevCellFactory)->create(name); + elevCellFactory++; + } + + return product; +} + +//***************************************************************************** +// METHOD: ossimElevCellHandlerFactory::getList() +// +//***************************************************************************** +list<ossimString> ossimElevCellHandlerFactory::getList() const +{ + list<ossimString> rtn_list; + list<ossimString> sub_list; + list<ossimFactoryBase<ossimElevCellHandler>*>::const_iterator factory_iter; + + factory_iter = theRegistry.begin(); + while(factory_iter != theRegistry.end()) + { + sub_list = (*factory_iter)->getList(); + rtn_list.merge(sub_list); + factory_iter++; + } + + return rtn_list; +} + diff --git a/Utilities/OSSIM/ossim_core/elevation/formats/ossimElevCellHandlerFactory.h b/Utilities/OSSIM/ossim_core/elevation/formats/ossimElevCellHandlerFactory.h new file mode 100644 index 0000000000..888764208a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/formats/ossimElevCellHandlerFactory.h @@ -0,0 +1,63 @@ +//***************************************************************************** +// FILE: ossimElevCellHandlerFactory.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// DESCRIPTION: +// Contains declaration of class ossimElevCellHandlerFactory. This factory +// class instantiates the proper ossimElevCellHandler given a file name. +// +// SOFTWARE HISTORY: +//> +// 26Apr2001 Oscar Kramer (okramer@imagelinks.com) +// Initial coding. +//< +//***************************************************************************** + +#ifndef ossimElevCellHandlerFactory_HEADER +#define ossimElevCellHandlerFactory_HEADER + +#include "base/common/ossimFactoryBaseTemplate.h" + +class ossimElevCellHandler; +class ossimGpt; + +/*!**************************************************************************** + * + * CLASS: ossimElevCellHandlerFactory + * + *****************************************************************************/ +class ossimElevCellHandlerFactory : + public ossimFactoryBase <ossimElevCellHandler> +{ + public: + static ossimElevCellHandlerFactory* instance(); + + virtual ossimElevCellHandler* create(const ossimString&) const; + virtual ossimElevCellHandler* create(const ossimKeywordlist& kwl, + const char* prefix) const; + + virtual list<ossimString> getList() const; + + protected: + ossimElevCellHandlerFactory(); + + static ossimElevCellHandlerFactory* theInstance; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/elevation/formats/srtm/.cvsignore b/Utilities/OSSIM/ossim_core/elevation/formats/srtm/.cvsignore new file mode 100644 index 0000000000..2dc074247b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/formats/srtm/.cvsignore @@ -0,0 +1,2 @@ +*.d +Makefile diff --git a/Utilities/OSSIM/ossim_core/elevation/formats/srtm/ossimSrtmFactory.cpp b/Utilities/OSSIM/ossim_core/elevation/formats/srtm/ossimSrtmFactory.cpp new file mode 100644 index 0000000000..f62fa7d052 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/formats/srtm/ossimSrtmFactory.cpp @@ -0,0 +1,228 @@ +//---------------------------------------------------------------------------- +// Copyright (c) 2005, David Burken, all rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Shuttle Radar Topography Mission (SRTM) factory to return an +// ossimSrtmElevSource given a ground point. +// +//---------------------------------------------------------------------------- +// $Id: ossimSrtmFactory.cpp,v 1.7 2005/11/21 15:04:59 gpotts Exp $ + +#include <sstream> +#include <elevation/formats/srtm/ossimSrtmFactory.h> +#include <elevation/formats/srtm/ossimSrtmHandler.h> +#include <base/common/ossimTrace.h> +#include <base/data_types/ossimGpt.h> +#include <elevation/ossimElevManager.h> +#include <base/context/ossimNotifyContext.h> +#include <base/factory/ossimStreamFactoryRegistry.h> +#include <base/data_types/ossimDirectory.h> +#include <support_data/srtm/ossimSrtmFilename.h> +#include <support_data/srtm/ossimSrtmSupportData.h> +#include <elevation/ossimElevationShapeIdx.h> + +static ossimTrace traceDebug ("ossimSrtmFactory:debug"); + +RTTI_DEF1(ossimSrtmFactory, "ossimSrtmFactory", ossimElevSourceFactory) + +ossimSrtmFactory::ossimSrtmFactory() + : ossimElevSourceFactory() +{} + +ossimSrtmFactory::ossimSrtmFactory(const ossimFilename& dir) + : ossimElevSourceFactory() +{ + theDirectory = dir; +} + +ossimSrtmFactory::~ossimSrtmFactory() +{} + +ossimElevSource* ossimSrtmFactory::getNewElevSource(const ossimGpt& gpt) const +{ + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimSrtmFactory::getNewElevSource: Entered..." + << std::endl; + } + + ossimElevManager* mgr = ossimElevManager::instance(); + + ossimElevSource* srtmPtr = NULL; + + if (theDirectory == ossimFilename::NIL) + { + ossimNotify(ossimNotifyLevel_FATAL) + << "ossimSrtmFactory::getNewElevSource: " + << "SRTM directory has not been set!" + << "\nReturning null elevation source..." + << std::endl; + + return srtmPtr; + } + + //--- + // Build up a srtm file name. + // + // Standard for name is upper case 'N' and 'W' lower case "hgt" like: + // N27W081.hgt + //--- + ossimFilename srtmFileBasename; + + int ilat = static_cast<int>(floor(gpt.latd())); + if (ilat < 0) + { + srtmFileBasename = "S"; + } + else + { + srtmFileBasename = "N"; + } + + ilat = abs(ilat); + std::ostringstream os1; + + os1 << setfill('0') <<setw(2) <<ilat; + + srtmFileBasename += os1.str().c_str(); + + int ilon = static_cast<int>(floor(gpt.lond())); + + if (ilon < 0) + { + srtmFileBasename += "W"; + } + else + { + srtmFileBasename += "E"; + } + + ilon = abs(ilon); + std::ostringstream os2; + os2 << setfill('0') <<setw(3) << ilon; + + srtmFileBasename += os2.str().c_str(); + srtmFileBasename.setExtension(".hgt"); + + ossimFilename srtmFile = theDirectory.dirCat(srtmFileBasename); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimSrtmFactory::getNewElevSource:" + << "\nSearching for file: " << srtmFile + << std::endl; + } + + ossimRefPtr<ossimIStream> is = ossimStreamFactoryRegistry::instance()-> + createNewInputStream(srtmFile, ios::in | ios::binary); + + // Look for the file mix case, then all lower case, then all upper case. + if (is.valid()) + { + if(is->fail()) + { + // Try down casing the whole thing. + srtmFileBasename = srtmFileBasename.downcase(); + srtmFile = theDirectory.dirCat(srtmFileBasename); + + is = ossimStreamFactoryRegistry::instance()-> + createNewInputStream(srtmFile, ios::in | ios::binary); + if (is.valid()) + { + if(is->fail()) + { + // OK, try upcasing the whole thing. + srtmFileBasename = srtmFileBasename.upcase(); + srtmFile = theDirectory.dirCat(srtmFileBasename); + is = ossimStreamFactoryRegistry::instance()-> + createNewInputStream(srtmFile, ios::in | ios::binary); + } + } + } + } + + if ( is.valid() && (!is->fail())&&!(mgr->isCellOpen(srtmFile)) ) + { + is->close(); + is = 0; + srtmPtr = new ossimSrtmHandler(srtmFile); + if (srtmPtr->pointHasCoverage(gpt) ) + { + return srtmPtr; + } + else + { + delete srtmPtr; + srtmPtr = NULL; + } + } + return srtmPtr; +} + +void ossimSrtmFactory::createIndex() +{ + ossimDirectory dir; + + if(dir.open(theDirectory)) + { + ossimFilename f; + if(dir.getFirst(f, ossimDirectory::OSSIM_DIR_FILES)) + { + ossimRefPtr<ossimElevationShapeIdx> shpIdx = 0; + try + { + shpIdx = new ossimElevationShapeIdx(theDirectory, true); + } + catch(...) + { + shpIdx = 0; + return; + } + + do + { + if(f.contains(".hgt")) + { + // check and remove the gz extension if present + // + ossimFilename file = f.file(); + if(f.ext() == "gz") + { + f = f.setExtension(""); + } + ossimSrtmFilename srtmFile; + if(srtmFile.setFilename(f.file())) + { + ossimSrtmSupportData srtmSupport; + + if(srtmSupport.setFilename(f, true)) + { + shpIdx->add(f, + srtmFile.ul().lond(), + srtmFile.ll().latd(), + srtmSupport.getMinPixelValue(), + srtmFile.ur().lond(), + srtmFile.ur().latd(), + srtmSupport.getMaxPixelValue()); + } + } + } + }while(dir.getNext(f)); + shpIdx->buildQuadTree(); + } + } + else + { + ossimNotify(ossimNotifyLevel_WARN) << "ossimSrtmFactory::createIndex(): Directory can't be opened for indexing." << std::endl; + } +} diff --git a/Utilities/OSSIM/ossim_core/elevation/formats/srtm/ossimSrtmFactory.h b/Utilities/OSSIM/ossim_core/elevation/formats/srtm/ossimSrtmFactory.h new file mode 100644 index 0000000000..167251f0d3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/formats/srtm/ossimSrtmFactory.h @@ -0,0 +1,59 @@ +//---------------------------------------------------------------------------- +// Copyright (c) 2005, David Burken, all rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Shuttle Radar Topography Mission (SRTM) factory to return an +// ossimSrtmElevSource given a ground point. +// +//---------------------------------------------------------------------------- +// $Id: ossimSrtmFactory.h,v 1.4 2005/11/18 20:24:49 gpotts Exp $ +#ifndef ossimSrtmFactory_HEADER +#define ossimSrtmFactory_HEADER + +#include <elevation/ossimElevSourceFactory.h> + +/** + * @class ossimSrtmFactory Used by the elevation manager, this class returns + * an ossimSrtmElevSource given a ground point and some directory with srtm + * files in it. + */ +class OSSIM_DLL ossimSrtmFactory : public ossimElevSourceFactory +{ +public: + + /** default constructor */ + ossimSrtmFactory(); + + /** Constructor that takes a directory name. */ + ossimSrtmFactory(const ossimFilename& dir); + + /** destructor */ + virtual ~ossimSrtmFactory(); + + /** + * Open the appropriate ossimSrtmElevSource that covers given a + * ground point. + * + * @param gpt Ground point that an elevation source is need for. + * + * @return Returns a pointer to an ossimElevSource if an srtm file is found + * that can cover the ground point. Returns NULL if no cell is found + * for the point. + */ + virtual ossimElevSource* getNewElevSource(const ossimGpt& gpt) const; + + virtual void createIndex(); + +protected: + +TYPE_DATA +}; + +#endif /* End of "#ifndef ossimSrtmFactory_HEADER" */ diff --git a/Utilities/OSSIM/ossim_core/elevation/formats/srtm/ossimSrtmHandler.cpp b/Utilities/OSSIM/ossim_core/elevation/formats/srtm/ossimSrtmHandler.cpp new file mode 100644 index 0000000000..038c5ea587 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/formats/srtm/ossimSrtmHandler.cpp @@ -0,0 +1,364 @@ +//---------------------------------------------------------------------------- +// Copyright (c) 2005, David Burken, all rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Shuttle Radar Topography Mission (SRTM) elevation source. +// +//---------------------------------------------------------------------------- +// $Id: ossimSrtmHandler.cpp,v 1.7 2005/11/16 15:06:33 dburken Exp $ + +#include <elevation/formats/srtm/ossimSrtmHandler.h> +#include <support_data/srtm/ossimSrtmSupportData.h> +#include <base/common/ossimCommon.h> +#include <base/common/ossimKeywordNames.h> +#include <base/context/ossimNotifyContext.h> +#include <base/data_types/ossimGpt.h> +#include <base/misc/ossimEndian.h> +#include <base/factory/ossimStreamFactoryRegistry.h> + +RTTI_DEF1(ossimSrtmHandler, "ossimSrtmHandler" , ossimElevCellHandler) + +//*** +// Define Trace flags for use within this file: +//*** +#include <base/common/ossimTrace.h> +static ossimTrace traceDebug ("ossimSrtmElevSource:debug"); + +ossimSrtmHandler::ossimSrtmHandler(const ossimFilename& srtmFile) + : + ossimElevCellHandler(srtmFile), + theFileStr(0), + theNumberOfLines(0), + theNumberOfSamples(0), + theSrtmRecordSizeInBytes(0), + theLatSpacing(0.0), + theLonSpacing(0.0), + theNwCornerPost(), + theSwapper(NULL) +{ + ossimSrtmSupportData sd; + if ( !sd.setFilename(srtmFile, false) ) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + return; + } + + theScalarType = sd.getScalarType(); + // SRTM is stored in big endian. + if ( ossimGetByteOrder() == OSSIM_LITTLE_ENDIAN) + { + theSwapper = new ossimEndian(); + } + + theNumberOfLines = sd.getNumberOfLines(); + theNumberOfSamples = sd.getNumberOfSamples(); + theSrtmRecordSizeInBytes = theNumberOfSamples * ossimGetScalarSizeInBytes(theScalarType); + theLatSpacing = sd.getLatitudeSpacing(); + theLonSpacing = sd.getLongitudeSpacing(); + theNwCornerPost.lon = sd.getSouthwestLongitude(); + theNwCornerPost.lat = sd.getSouthwestLatitude()+1.0; + theScalarType = sd.getScalarType(); + theGroundRect = ossimGrect(ossimGpt(theNwCornerPost.lat, + theNwCornerPost.lon, + 0.0), + ossimGpt(theNwCornerPost.lat-1.0, + theNwCornerPost.lon+1.0, + 0.0)); + + //--- + // Determine the mean spacing: + //--- + // double center_lat = (south_boundary + north_boundary)/2.0; + // theMeanSpacing = (theLatSpacing + theLonSpacing*cosd(center_lat)) + // * ossimGpt().metersPerDegree().x / 2.0; + + // Initialize the accuracy values: + // theAbsLE90 = (double) acc.absLE(); + // theAbsCE90 = (double) acc.absCE(); + + // Set the base class null height value. + theNullHeightValue = -32768.0; + + // theMinHeightAboveMSL; + // theMaxHeightAboveMSL; +} + +ossimSrtmHandler::~ossimSrtmHandler() +{ + if (theSwapper) + { + delete theSwapper; + theSwapper = NULL; + } + + theFileStr = 0; +// if(theFileStr) +// { +// delete theFileStr; +// theFileStr = 0; +// } +// theFileStr.close(); +} + +double ossimSrtmHandler::getHeightAboveMSL(const ossimGpt& gpt) +{ + switch(theScalarType) + { + case OSSIM_SINT16: + { + return getHeightAboveMSLTemplate((ossim_sint16)0, + gpt); + } + case OSSIM_FLOAT32: + { + return getHeightAboveMSLTemplate((ossim_float32)0, + gpt); + } + default: + { + break; + } + } + + return NULL_POST; +} + +template <class T> +double ossimSrtmHandler::getHeightAboveMSLTemplate(T dummy, + const ossimGpt& gpt) +{ + // Establish the grid indexes: + double xi = (gpt.lon - theNwCornerPost.lon) / theLonSpacing; + double yi = (theNwCornerPost.lat - gpt.lat) / theLatSpacing; + + int x0 = static_cast<int>(xi); + int y0 = static_cast<int>(yi); + + // Check for right edge. + if (gpt.lon == theGroundRect.lr().lon) + { + --x0; // Move over one post to the left. + } + + // Check for bottom edge. + if (gpt.lat == theGroundRect.lr().lat) + { + --y0; // Move up one post. + } + + // Do some error checking. + if ( xi < 0.0 || yi < 0.0 || + x0 > (theNumberOfSamples - 2.0) || + y0 > (theNumberOfLines - 2.0) ) + { +// std::cout << "ossimSrtmHandler::getHeightAboveMSLTemplate: leaving 1" << std::endl; + return theNullHeightValue; + } + + // We need an open stream to file from here on out... + if (!open()) + { +// std::cout << "ossimSrtmHandler::getHeightAboveMSLTemplate: leaving 2" << std::endl; + return theNullHeightValue; + } + + T p[4]; + + double p00; + double p01; + double p10; + double p11; + + //--- + // Grab the four points from the srtm cell needed. + //--- + streampos offset = y0 * theSrtmRecordSizeInBytes + x0 * sizeof(T); + +// ossim_int64 currentG = theFileStr->tellg(); + // lets a seek cur + // + // Put the file pointer at the start of the first elevation post. + theFileStr->seekg(offset, ios::beg); + //theFileStr->seekg(offset-currentG, ios::cur); + // Get the first post. + theFileStr->read((char*)p, sizeof(T)); + + // Get the second post. + theFileStr->read((char*)(p+1), sizeof(T)); + + // Move over to the next column. + offset += theSrtmRecordSizeInBytes; + +// currentG = theFileStr->tellg(); +// theFileStr->seekg(offset-currentG, ios::cur); + + theFileStr->seekg(offset, ios::beg); + + // Get the third post. + theFileStr->read((char*)(p+2), sizeof(T)); + + // Get the fourth post. + theFileStr->read((char*)(p+3), sizeof(T)); + + if(theFileStr->fail()) + { + return theNullHeightValue; + } + if (theSwapper) + { + theSwapper->swap((T*)p, 4); + } + + p00 = p[0]; + p01 = p[1]; + p10 = p[2]; + p11 = p[3]; + + // Perform bilinear interpolation: +// double wx1 = xi - x0; +// double wy1 = yi - y0; +// double wx0 = 1.0 - wx1; +// double wy0 = 1.0 - wy1; + + double xt0 = xi - x0; + double yt0 = yi - y0; + double xt1 = 1-xt0; + double yt1 = 1-yt0; + +// double w00 = wx0*wy0; +// double w01 = wx0*wy1; +// double w10 = wx1*wy0; +// double w11 = wx1*wy1; + double w00 = xt1*yt1; + double w01 = xt0*yt1; + double w10 = xt1*yt0; + double w11 = xt0*yt0; + + //*** + // Test for null posts and set the corresponding weights to 0: + //*** + if (p00 == theNullHeightValue) + w00 = 0.0; + if (p01 == theNullHeightValue) + w01 = 0.0; + if (p10 == theNullHeightValue) + w10 = 0.0; + if (p11 == theNullHeightValue) + w11 = 0.0; + +#if 0 /* Serious debug only... */ + cout << "\np00: " << p00 + << "\np01: " << p01 + << "\np10: " << p10 + << "\np11: " << p11 + << "\nw00: " << w00 + << "\nw01: " << w01 + << "\nw10: " << w10 + << "\nw11: " << w11 + << endl; +#endif + + double sum_weights = w00 + w01 + w10 + w11; + + if (sum_weights) + { + return (p00*w00 + p01*w01 + p10*w10 + p11*w11) / sum_weights; + } + + return theNullHeightValue; +} + +double ossimSrtmHandler::getPostValue(const ossimIpt& gridPt) const +{ + static const char MODULE[] = "ossimSrtmHandler::getPostValue"; + + if(!theFileStr.valid()) return theNullHeightValue; + + // Do some error checking. + if ( gridPt.x < 0.0 || gridPt.y < 0.0 || + gridPt.x > (theNumberOfSamples - 1) || + gridPt.y > (theNumberOfLines - 1) ) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "WARNING " << MODULE << ": No intersection..." << std::endl; + } + return theNullHeightValue; + } + + if (!open()) + { + return theNullHeightValue; + } + + streampos offset = gridPt.y * theSrtmRecordSizeInBytes + gridPt.x * 2; + + // Put the file pointer at the start of the first elevation post. + theFileStr->seekg(offset, ios::beg); + + ossim_sint16 p; + + // Get the post. + theFileStr->read((char*)&p, 2); + if (theSwapper) + { + theSwapper->swap(p); + } + return p; +} + +ossimIpt ossimSrtmHandler::getSizeOfElevCell() const +{ + return ossimIpt(theNumberOfSamples, theNumberOfLines); +} + +const ossimSrtmHandler& +ossimSrtmHandler::operator=(const ossimSrtmHandler& rhs) +{ + return rhs; +} + +ossimSrtmHandler::ossimSrtmHandler(const ossimSrtmHandler&) +{ +} + + +bool ossimSrtmHandler::open() const +{ + if(theFileStr.valid()) + { + if(!theFileStr->fail()) + { + return true; + } + } + theFileStr = 0; + + + theFileStr = ossimStreamFactoryRegistry::instance()->createNewInputStream(theFilename, + ios::in | ios::binary); + + if(theFileStr.valid()) + { + return (!theFileStr->fail()); + } + return false; +} + +void ossimSrtmHandler::close() const +{ + if(theFileStr.valid()) + { + theFileStr->close(); + theFileStr = 0; + } + +} diff --git a/Utilities/OSSIM/ossim_core/elevation/formats/srtm/ossimSrtmHandler.h b/Utilities/OSSIM/ossim_core/elevation/formats/srtm/ossimSrtmHandler.h new file mode 100644 index 0000000000..df821e4f0b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/formats/srtm/ossimSrtmHandler.h @@ -0,0 +1,100 @@ +//---------------------------------------------------------------------------- +// Copyright (c) 2005, David Burken, all rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Shuttle Radar Topography Mission (SRTM) elevation source. +// +//---------------------------------------------------------------------------- +// $Id: ossimSrtmHandler.h,v 1.4 2005/11/10 14:15:33 gpotts Exp $ +#ifndef ossimSrtmHandler_HEADER +#define ossimSrtmHandler_HEADER + +#include <base/common/ossimIoStream.h> +//#include <fstream> + +#include <base/data_types/ossimString.h> +#include <elevation/formats/ossimElevCellHandler.h> + +class ossimEndian; + +/** + * @class ossimSrtmHandler Elevation source for an srtm file. + */ +class OSSIMDLLEXPORT ossimSrtmHandler : public ossimElevCellHandler +{ +public: + + /** Constructor that takes a file name. */ + ossimSrtmHandler(const ossimFilename& srtmFile); + + /** destructor */ + virtual ~ossimSrtmHandler(); + + enum + { + NULL_POST = -32768 // Fixed by SRTM specification. + }; + + /** + * METHOD: getHeightAboveMSL + * Height access methods. + */ + virtual double getHeightAboveMSL(const ossimGpt&); + + /** + * METHOD: getSizeOfElevCell + * Returns the number of post in the cell. Satisfies pure virtual. + * Note: x = longitude, y = latitude + */ + virtual ossimIpt getSizeOfElevCell() const; + + /** + * METHOD: getPostValue + * Returns the value at a given grid point as a double. + * Satisfies pure virtual. + */ + virtual double getPostValue(const ossimIpt& gridPt) const; + + /** + * Opens a stream to the srtm cell. + * + * @return Returns true on success, false on error. + */ + virtual bool open() const; + + /** + * Closes the stream to the file. + */ + virtual void close() const; + +private: + // Disallow operator= and copy constrution... + const ossimSrtmHandler& operator=(const ossimSrtmHandler& rhs); + ossimSrtmHandler(const ossimSrtmHandler&); + + mutable ossimRefPtr<ossimIStream> theFileStr; +// mutable std::istream* theFileStr; +// mutable ifstream theFileStr; + ossim_int32 theNumberOfLines; + ossim_int32 theNumberOfSamples; + ossim_int32 theSrtmRecordSizeInBytes; + double theLatSpacing; // degrees + double theLonSpacing; // degrees + ossimDpt theNwCornerPost; // cell origin; + ossimEndian* theSwapper; + ossimScalarType theScalarType; + + template <class T> + double getHeightAboveMSLTemplate(T dummy, + const ossimGpt& gpt); +TYPE_DATA +}; + +#endif /* End of "#ifndef ossimSrtmHandler_HEADER" */ diff --git a/Utilities/OSSIM/ossim_core/elevation/ossimElevLess.h b/Utilities/OSSIM/ossim_core/elevation/ossimElevLess.h new file mode 100644 index 0000000000..ac61385d55 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/ossimElevLess.h @@ -0,0 +1,45 @@ +//***************************************************************************** +// FILE: ossimElevLess.h +// +// Copyright (C) 2002 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// DESCRIPTION: +// Function object (functor) to for stl's sort method for sorting +// a vector of ossimElevSource* by best post spacing. +//***************************************************************************** +// $Id: ossimElevLess.h,v 1.3 2005/11/18 20:24:49 gpotts Exp $ + +#ifndef ossimElevLess_HEADER +#define ossimElevLess_HEADER + +#include <functional> + +#include "ossimElevSource.h" + +class ossimElevLess : + public std::binary_function<const ossimRefPtr<ossimElevSource>, + const ossimRefPtr<ossimElevSource>, bool> +{ +public: + bool operator() (const ossimRefPtr<ossimElevSource> a, const ossimRefPtr< ossimElevSource> b) const + { + return (a->getMeanSpacingMeters() < b->getMeanSpacingMeters()); + } +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/elevation/ossimElevManager.cpp b/Utilities/OSSIM/ossim_core/elevation/ossimElevManager.cpp new file mode 100644 index 0000000000..eb51c163c4 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/ossimElevManager.cpp @@ -0,0 +1,1538 @@ +//************************************************************************** +// FILE: ossimElevManager.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: See top level LICENSE.txt file. +// +// DESCRIPTION: +// Contains implementation of class ossimElevManager. This object +// provides a single interface for accessing multiple elevation +// sources. This object owns one or more elevation sources in an ordered +// list. When queried for an elevation at a particular point, it searches +// the available sources for the best result, instantiating new sources if +// necessary. +// +// SOFTWARE HISTORY: +//> +// 23Apr2001 Oscar Kramer +// Initial coding. +//< +//************************************************************************** +// $Id: ossimElevManager.cpp,v 1.46 2005/12/21 21:25:21 dburken Exp $ + +#include <algorithm> + +#include <elevation/ossimElevManager.h> +#include <elevation/ossimElevLess.h> +#include <elevation/formats/dted_cell/ossimDtedFactory.h> +#include <elevation/formats/dted_cell/ossimDtedHandler.h> +#include <elevation/formats/srtm/ossimSrtmFactory.h> +#include <elevation/formats/srtm/ossimSrtmHandler.h> +#include <elevation/formats/ossimElevCellHandler.h> +#include <base/data_types/geoid/ossimGeoidManager.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimKeyword.h> +#include <base/data_types/ossimDirectory.h> +#include <base/common/ossimKeywordNames.h> +#include <base/common/ossimTrace.h> +#include <base/common/ossimScopedLock.h> +#include <base/common/events/ossimElevationManagerEvent.h> +#include <base/context/ossimNotifyContext.h> + + +RTTI_DEF1(ossimElevManager, "ossimElevManager" , ossimElevSource) + +//*** +// Define Trace flags for use within this file: +//*** +static ossimTrace traceDebug ("ossimElevManager:debug"); + +#ifdef OSSIM_ID_ENABLED +static const char OSSIM_ID[] = "$Id: ossimElevManager.cpp,v 1.46 2005/12/21 21:25:21 dburken Exp $"; +#endif + +ossimElevManager* ossimElevManager::theInstance = NULL; + +ossimElevManager* ossimElevManager::instance() +{ + if (!theInstance) + theInstance = new ossimElevManager(); + + return theInstance; +} + +ossimElevManager::ossimElevManager() + : + ossimElevSource(), + theElevSourceList(0), + theElevSourceFactoryList(0), + theGeoidManager(ossimGeoidManager::instance()), + theAutoLoadFlag(true), + theAutoSortFlag(true), + theDefaultElevationPath(ossimFilename::NIL) +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimElevManager::ossimElevManager() entered..." + << std::endl; +#if OSSIM_ID_ENABLED + ossimNotify(ossimNotifyLevel_DEBUG) + << "OSSIM_ID: " + << OSSIM_ID + << std::endl; +#endif + } + + if (!theInstance) theInstance = this; +} + +ossimElevManager::~ossimElevManager() +{ + theInstance = NULL; + + // Delete the list of elevation sources and clear the list. +// vector<ossimElevSource*>::iterator s = theElevSourceList.begin(); +// while (s != theElevSourceList.end()) +// { +// delete *s; +// ++s; +// } + theElevSourceList.clear(); + + // Delete the list of elevation factories and clear the list. +// vector<const ossimElevSourceFactory*>::iterator f +// = theElevSourceFactoryList.begin(); +// while (f != theElevSourceFactoryList.end()) +// { +// delete *f; +// ++f; +// } + theElevSourceFactoryList.clear(); +} + +bool ossimElevManager::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::loadState: Entered..." + << std::endl; + } + ossimString copyPrefix = prefix; + + //--- + // Call the base class loadState. This will pick up the enabled keyword. + // Note we need to tack on the "elevation." prefix so the lookup of + // "elevation.enabled" occurs. + //--- + ossimString elev_prefix; + if (prefix) + { + elev_prefix = prefix; + } + elev_prefix += "elevation."; + ossimSource::loadState(kwl, elev_prefix); + + const char* lookup; // used throughout + + // Check for the elevation.autoload_dted.enabled keyword. + lookup = kwl.find(prefix, "elevation.auto_load_dted.enabled"); + if (lookup) + { + theAutoLoadFlag = ossimString(lookup).toBool(); + } + + // Check for the autosort_elevation keyword. + lookup = kwl.find(prefix, "elevation.auto_sort.enabled"); + if (lookup) + { + theAutoSortFlag = ossimString(lookup).toBool(); + } + + // Check for a default elevation path. + const char DEFAULT_ELEVATION_PATH_KW[] = "default_elevation_path"; + lookup = kwl.find(DEFAULT_ELEVATION_PATH_KW); + if(lookup) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::loadState: " + << DEFAULT_ELEVATION_PATH_KW + << " lookup: " << lookup << std::endl; + } + theDefaultElevationPath = lookup; + } + ossimString regExpression = ossimString("^(") + copyPrefix + "elevation_source[0-9]+.)"; + vector<ossimString> keys = + kwl.getSubstringKeyList( regExpression ); + long numberOfSources = keys.size(); + ossim_uint32 offset = (copyPrefix+"elevation_source").size(); + ossim_uint32 idx = 0; + std::vector<int> theNumberList(numberOfSources); + for(idx = 0; idx < theNumberList.size();++idx) + { + ossimString numberStr(keys[idx].begin() + offset, + keys[idx].end()); + theNumberList[idx] = numberStr.toInt(); + } + std::sort(theNumberList.begin(), theNumberList.end()); + + for(idx=0;idx < theNumberList.size();++idx) + { + ossimString newPrefix = copyPrefix; + newPrefix += ossimString("elevation_source"); + newPrefix += ossimString::toString(theNumberList[idx]); + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::loadState:" + << "\nLooking for key: " << newPrefix + << std::endl; + } + ossimString fileKey = newPrefix; + fileKey += "."; + fileKey += ossimKeywordNames::FILENAME_KW; + lookup = kwl.find(prefix, fileKey.c_str()); + if (lookup) + { + ossimFilename file = lookup; + + // Lookup the type. + ossimString typeKey = newPrefix; + typeKey += "."; + typeKey += ossimKeywordNames::TYPE_KW; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::loadState:" + << "\nLooking for key: " << typeKey + << std::endl; + } + + lookup = kwl.find(prefix, typeKey.c_str()); + if (lookup) + { + ossimString type = lookup; + if (type == "dted_cell") + { + openDtedCell(file); + } + else if (type == "srtm_cell") + { + openSrtmCell(file); + } + else if (type == "dted_directory") + { + addDtedFactory(file); + } + else if (type == "srtm_directory") + { + addSrtmFactory(file); + } + } + else // No "type" specified, try to auto detect. + { + if(!file.isDir()) + { + openCell(file); + } + else + { + if ( isDtedDirectory(file) ) + { + addDtedFactory(file); + } + + else if ( isSrtmDirectory(file) ) + { + addSrtmFactory(file); + } + } +// ossimString tempFile = file; +// if(!file.isFile()) +// { +// tempFile += ".gz"; +// } +// if (tempFile.isFile()) +// { +// if ( isSrtmFilenameFormat(tempFile) ) +// { +// openSrtmCell(file); +// } +// else if ( isDtedFilenameFormat(file) ) +// { +// openDtedCell(file); +// } +// } +// else // Directory... +// { +// if ( isDtedDirectory(file) ) +// { +// addDtedFactory(file); +// } + +// else if ( isSrtmDirectory(file) ) +// { +// addSrtmFactory(file); +// } +// } + } + } // end if lookup + } // end for loop +#if 0 + // Find any cells using "elevation_source" keyword. + count = kwl.numberOf(ossimKeywordNames::ELEVATION_SOURCE_KW); + if (count) + { + //--- + // Look for numbered keyword like "elevation_source1", + // "elevation_source2" and so on. + //--- + ossim_uint32 sourceNumber = 0; + ossim_uint32 found = 0; + while ((found < count) && (sourceNumber < 10000) ) + { + ossimString key = ossimKeywordNames::ELEVATION_SOURCE_KW; + key += ossimString::toString(sourceNumber); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::loadState:" + << "\nLooking for key: " << key + << std::endl; + } + + ossimString fileKey = key; + fileKey += "."; + fileKey += ossimKeywordNames::FILENAME_KW; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::loadState:" + << "\nLooking for key: " << fileKey + << std::endl; + } + + lookup = kwl.find(prefix, fileKey.c_str()); + if (lookup) + { + ++found; + ossimFilename file = lookup; + + // Lookup the type. + ossimString typeKey = key; + typeKey += "."; + typeKey += ossimKeywordNames::TYPE_KW; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::loadState:" + << "\nLooking for key: " << typeKey + << std::endl; + } + + lookup = kwl.find(prefix, typeKey.c_str()); + if (lookup) + { + ++found; + + ossimString type = lookup; + if (type == "dted_cell") + { + openDtedCell(file); + } + else if (type == "srtm_cell") + { + openSrtmCell(file); + } + else if (type == "dted_directory") + { + addDtedFactory(file); + } + else if (type == "srtm_directory") + { + addSrtmFactory(file); + } + } + else // No "type" specified, try to auto detect. + { + if (file.isFile()) + { + if ( isDtedFilenameFormat(file) ) + { + openSrtmCell(file); + } + else if ( isSrtmFilenameFormat(file) ) + { + openDtedCell(file); + } + } + else // Directory... + { + if ( isDtedDirectory(file) ) + { + addDtedFactory(file); + } + + else if ( isSrtmDirectory(file) ) + { + addSrtmFactory(file); + } + } + } + } + + ++sourceNumber; + + } // End of "while ((found < count) && (sourceNumber < 10000) )" + }// End of "if (count)" ELEVATION_SOURCE_KW +#endif + //--- + // Below is only here for backwards compatibility. + + //*** + // Find any dted cells. + //*** + const char DTED_CELL_KW[] = "dted_cell"; + + // int number_of_cells = kwl.numberOf(prefix, DTED_CELL_KW); + int number_of_cells = kwl.numberOf(DTED_CELL_KW); + + if (number_of_cells) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_FATAL) + << "DEBUG ossimElevManager::loadState: " + << "\nNumber of cells = " << number_of_cells + << std::endl; + } + + int count = 0; + + // Look for just the keyword "dted_cell" with no number appended to it. + lookup = kwl.find(prefix, DTED_CELL_KW); + if (lookup) + { + ++count; + ossimFilename f = lookup; + openDtedCell(f); + } + + // Look for numbered keyword like "dted_cell1". + int cell_number = 0; + while ((count < number_of_cells) && + (cell_number < 1000) ) + { + ossimString key = DTED_CELL_KW; + key += ossimString::toString(cell_number); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::loadState:" + << "\nLooking for key: " << key + << std::endl; + } + + lookup = kwl.find(prefix, key); + if (lookup) + { + ++count; + + ossimFilename f = lookup; + openDtedCell(f); + } + + ++cell_number; + + } // End of "while (count < number_of_cells)" + } + else + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::loadState:" + << "\nNo dted_cell found in the keyword list." + << std::endl; + } + } + + // Add any factories for dted_directory keyword: + addDtedFactories(kwl, prefix); + + // Add any factories for srtm_directory keyword: + addSrtmFactories(kwl, prefix); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::loadState:" + << "\nElevation is: " + << (isSourceEnabled()?"enabled":"disabled") + << "\nAuto elevation loading is: " + << (isAutoLoadEnabled()?"enabled":"disabled") + << "\nAuto sorting of elevation is: " + << (isAutoSortEnabled()?"enabled":"disabled") + << "\ntheDefaultElevationPath = " + << theDefaultElevationPath + << "DEBUG ossimElevManager::loadState: Exited..." + << std::endl; + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::loadState: Exited..." << std::endl; + } + + return true; +} + +bool ossimElevManager::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + ossim_uint32 sourceNumber = 1; + + // Save the cells. + ossimElevSourceListConstIterator s = theElevSourceList.begin(); + while (s != theElevSourceList.end()) + { + ossimString keywordBase = ossimKeywordNames::ELEVATION_SOURCE_KW; + keywordBase += ossimString::toString(sourceNumber); + + ossimString typeKw = keywordBase; + typeKw += "."; + typeKw += ossimKeywordNames::TYPE_KW; + + ossimString filenameKw = keywordBase; + filenameKw += "."; + filenameKw += ossimKeywordNames::FILENAME_KW; + + kwl.add(prefix, filenameKw.c_str(), (*s)->getFilename()); + if ((*s)->getClassName() == "ossimDtedHandler") + { + kwl.add(prefix, typeKw.c_str(), "dted_cell"); + } + else if ((*s)->getClassName() == "ossimSrtmHandler") + { + kwl.add(prefix, typeKw.c_str(), "strm_cell"); + } + ++s; + ++sourceNumber; + } + + // Save the factories. + ossimElevSourceFactoryConstIterator f = theElevSourceFactoryList.begin(); + + while (f != theElevSourceFactoryList.end()) + { + ossimString keywordBase = ossimKeywordNames::ELEVATION_SOURCE_KW; + keywordBase += ossimString::toString(sourceNumber); + + ossimString typeKw = keywordBase; + typeKw += "."; + typeKw += ossimKeywordNames::TYPE_KW; + + ossimString filenameKw = keywordBase; + filenameKw += "."; + filenameKw += ossimKeywordNames::FILENAME_KW; + + kwl.add(prefix, filenameKw.c_str(), (*f)->getDirectory()); + + if ((*f)->getClassName() == "ossimDtedFactory") + { + kwl.add(prefix, typeKw.c_str(), "dted_directory"); + } + else if ((*f)->getClassName() == "ossimSrtmFactory") + { + kwl.add(prefix, typeKw.c_str(), "strm_directory"); + } + + ++f; + ++sourceNumber; + } + + return true; +} + +void ossimElevManager::loadElevData(const ossimDrect& ground_rect) +{ + //*** + // NOT YET IMPLEMENTED. DEM Loading will occur when height is requested. + // list until + //*** +} + +double ossimElevManager::getHeightAboveMSL(const ossimGpt& gpt) +{ + + if (theEnableFlag) + { + ossimScopedLock<ossimMutex> scopedLock(theMutex); + //*** + // Search through the list of elevation sources for a valid elevation + // post. + //*** + ossimElevSourceListIterator s = theElevSourceList.begin(); + while (s != theElevSourceList.end()) + { + double d = (*s)->getHeightAboveMSL(gpt); + if (d != (*s)->getNullHeightValue()) + { + return d; + } + (*s)->close(); // Close to keep file descriptors down. + ++s; + } + + if (theAutoLoadFlag) + { + // + // If we got here there were no sources in the list that contained + // coverage so go through the list of managers and see if they have + // coverage. + // + ossimElevSourceFactoryConstIterator sf = + theElevSourceFactoryList.begin(); + + while (sf != theElevSourceFactoryList.end()) + { + ossimElevSource* source = (*sf)->getNewElevSource(gpt); + if (source) + { + theMutex.unlock(); + // Add it to the list. + addElevSource(source); + + theMutex.lock(); + + double d = source->getHeightAboveMSL(gpt); + if (d != source->getNullHeightValue()) + { + return d; + } + else + { + return theNullHeightValue; + } + } + ++sf; + } + } + + } // End of "if (isSourceEnabled())" + + // If we get here return a null height value. + return theNullHeightValue; +} + +double ossimElevManager::getHeightAboveEllipsoid(const ossimGpt& gpt) +{ + if (theEnableFlag) + { + // Fetch the geoid offset first: + double d = theGeoidManager->offsetFromEllipsoid(gpt); + + if (d != OSSIM_DBL_NAN) + { + double h = getHeightAboveMSL(gpt); + if (h != theNullHeightValue) + { + return (h + d); + } + else + { + return d; + } + } + } + + return theNullHeightValue; +} + +double ossimElevManager::getAccuracyCE90(const ossimGpt& gpt) const +{ + // return theDtedManager->getAccuracyCE90(gpt); + return 0.0; +} + +double ossimElevManager::getAccuracyLE90(const ossimGpt& gpt) const +{ + // return theDtedManager->getAccuracyLE90(gpt); + return 0.0; +} + +double ossimElevManager::getMeanSpacingMeters() const +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_FATAL) + << "FATAL ossimElevManager::getMeanSpacingMeters: not implemented..." + << std::endl; + } + return 0.0; +} + +bool ossimElevManager::pointHasCoverage(const ossimGpt& gpt) const +{ + // return theDtedManager->pointHasCoverage(gpt); + return 0.0; +} + +void ossimElevManager::addElevSource(ossimElevSource* source) +{ + // Add it to the list... + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_INFO) + << "INFO ossimElevManager::addElevSource: Opened cell " + << source->getFilename().c_str() << std::endl; + } + + theElevSourceList.push_back(source); + + if (theAutoSortFlag) + { + // Sort by highest resolution. + sort(theElevSourceList.begin(), + theElevSourceList.end(), + ossimElevLess()); + } + + // Update the min / max values. + updateMinMax(); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::addElevSource Sorted elevation sources:" + << std::endl; + + int index = 0; + ossimElevSourceListConstIterator s = theElevSourceList.begin(); + while (s != theElevSourceList.end()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "Elevation source[" << index << "]: " + << (*s)->getFilename().c_str() << std::endl; + ++s; + ++index; + } + } + + ossimElevationManagerEvent event( this ); + + fireEvent( event ); +} + +void ossimElevManager::updateMinMax() +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::updateMinMax: " + << "\nInitial min height above MSL: " << theMinHeightAboveMSL + << "\nInitial max height above MSL: " << theMaxHeightAboveMSL + << std::endl; + } + + double BOGUS_MIN = 100000.0; + double BOGUS_MAX = -100000.0; + double min_value = BOGUS_MIN; + double max_value = BOGUS_MAX; + + ossimElevSourceListConstIterator s = theElevSourceList.begin(); + while (s != theElevSourceList.end()) + { + double s_min = (*s)->getMinHeightAboveMSL(); + double s_max = (*s)->getMaxHeightAboveMSL(); + + if (s_min < min_value) min_value = s_min; + if (s_max > max_value) max_value = s_max; + ++s; + } + + // Don't asign if unless something was found... + if (min_value != BOGUS_MIN) theMinHeightAboveMSL = min_value; + if (max_value != BOGUS_MAX) theMaxHeightAboveMSL = max_value; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::updateMinMax:\n" + << "Updated min height above MSL: " << theMinHeightAboveMSL + << "\nUpdated max height above MSL: " << theMaxHeightAboveMSL + << std::endl; + } +} + +void ossimElevManager::addElevSourceFactory(ossimRefPtr<ossimElevSourceFactory> source) +{ + theElevSourceFactoryList.push_back(source); +} + +void ossimElevManager::enableAutoLoad() +{ + theAutoLoadFlag = true; +} + +void ossimElevManager::disableAutoLoad() +{ + theAutoLoadFlag = false; +} + +bool ossimElevManager::isAutoLoadEnabled() const +{ + return theAutoLoadFlag; +} + +void ossimElevManager::enableAutoSort() +{ + theAutoSortFlag = true; +} + +void ossimElevManager::disableAutoSort() +{ + theAutoSortFlag = false; +} + +bool ossimElevManager::isAutoSortEnabled() const +{ + return theAutoSortFlag; +} + +ossimRefPtr<ossimElevSourceFactory> ossimElevManager::findFactoryFromDir(const ossimFilename& dir) +{ + ossim_uint32 idx = 0; + for(idx = 0; idx < theElevSourceFactoryList.size(); ++idx) + { + if(theElevSourceFactoryList[idx]->getDirectory() == dir) + { + return theElevSourceFactoryList[idx]; + } + } + + return ossimRefPtr<ossimElevSourceFactory>(); +} + +const ossimRefPtr<ossimElevSourceFactory> ossimElevManager::findFactoryFromDir(const ossimFilename& dir)const +{ + ossim_uint32 idx = 0; + + for(idx = 0; idx < theElevSourceFactoryList.size(); ++idx) + { + if(theElevSourceFactoryList[idx]->getDirectory() == dir) + { + return theElevSourceFactoryList[idx]; + } + } + + return ossimRefPtr<ossimElevSourceFactory>(); +} + + +bool ossimElevManager::isCellOpen(const ossimFilename& cell) const +{ + bool result = false; + + if (cell == ossimFilename::NIL) return result; + + ossimElevSourceListConstIterator s = theElevSourceList.begin(); + while (s != theElevSourceList.end()) + { + if (cell == (*s)->getFilename()) + { + result = true; + break; + } + ++s; + } + + return result; +} + +bool ossimElevManager::openCell(const ossimFilename& cell) +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::openCell: Entered..." + << "\nCell: " << cell << std::endl; + } + + if (cell == ossimFilename::NIL) return false; + + ossimFilename tempFile = cell; + if(!tempFile.isFile()) + { + tempFile += ".gz"; + } + if(!tempFile.isFile()) return false; + + if (isDtedFilenameFormat(tempFile)) + { + return openDtedCell(tempFile); + } + else if (isSrtmFilenameFormat(tempFile)) + { + return openSrtmCell(tempFile); + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::openCell:\n" + << "Could not open: " << cell + << std::endl; + } + + return false; +} + +bool ossimElevManager::openDirectory(const ossimFilename& dir) +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::openDirectory Entered..." + << "\nDirectory: " << dir << std::endl; + } + + if (dir == ossimFilename::NIL || !dir.isDir()) return false; + + ossimDirectory od(dir); + + if (od.isOpened() == false) return false; + + ossimFilename f; + + bool result = false; + + if (od.getFirst(f, ossimDirectory::OSSIM_DIR_FILES)) + { + do + { + if (openCell(f) == true) + { + result = true; + } + } while (od.getNext(f)); + } + + return result; +} + +bool ossimElevManager::closeCell(const ossimFilename& cell) +{ + if (cell == ossimFilename::NIL) return false; + + ossimElevSourceListIterator s = theElevSourceList.begin(); + while (s != theElevSourceList.end()) + { + if (cell == (*s)->getFilename()) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "Closed cell: " << (*s)->getFilename().c_str() + << std::endl; + } + theElevSourceList.erase(s); + return true; + } + ++s; + } + + return false; +} + +void ossimElevManager::closeAllCells() +{ + ossimElevSourceListIterator s = theElevSourceList.begin(); + while (s != theElevSourceList.end()) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "Closed cell: " << (*s)->getFilename().c_str() << std::endl; + } + ++s; + } + + theElevSourceList.clear(); +} + +void ossimElevManager::getOpenCellList(std::vector<ossimFilename>& list) const +{ + list.clear(); + + ossimElevSourceListConstIterator s = theElevSourceList.begin(); + + while (s != theElevSourceList.end()) + { + list.push_back((*s)->getFilename()); + ++s; + } +} + +ossimFilename ossimElevManager::getDefaultElevationPath() const +{ + return theDefaultElevationPath; +} + +void ossimElevManager::setDefaultElevationPath(const ossimFilename& path) +{ + theDefaultElevationPath = path; +} + +bool ossimElevManager::moveCellUpOne(const ossimFilename& cell) +{ + if (cell == ossimFilename::NIL) return false; + + ossimElevSourceListIterator a = theElevSourceList.begin(); + ossimElevSourceListIterator b = a; + ++b; + while (b != theElevSourceList.end()) + { + if ( cell == (*b)->getFilename() ) + { + iter_swap(a, b); + return true; + } + ++a; + ++b; + } + + return false; +} + +bool ossimElevManager::moveCellDownOne(const ossimFilename& cell) +{ + if (cell == ossimFilename::NIL) return false; + + ossimElevSourceListIterator a = theElevSourceList.begin(); + ossimElevSourceListIterator b = a; + ++b; + while (b != theElevSourceList.end()) + { + if ( cell == (*a)->getFilename() ) + { + iter_swap(a, b); + return true; + } + ++a; + ++b; + } + + return false; +} + +bool ossimElevManager::moveCellToTop(const ossimFilename& cell) +{ + if (cell == ossimFilename::NIL) return false; + + ossimElevSourceListIterator a = theElevSourceList.begin(); + ossimElevSourceListIterator b = a; + ++b; + while (b != theElevSourceList.end()) + { + if ( cell == (*b)->getFilename() ) + { + ossimFilename f = (*b)->getFilename(); + while (moveCellUpOne(f) == true){} + return true; + } + ++b; + } + + return false; +} + +bool ossimElevManager::moveCellToBottom(const ossimFilename& cell) +{ + if (cell == ossimFilename::NIL) return false; + + ossimElevSourceListIterator a = theElevSourceList.begin(); + ossimElevSourceListIterator b = theElevSourceList.end(); + --b; + while (a != b) + { + if ( cell == (*a)->getFilename() ) + { + ossimFilename f = (*a)->getFilename(); + while (moveCellDownOne(f) == true){} + return true; + } + ++a; + } + + return false; +} + +void ossimElevManager::addDtedFactories(const ossimKeywordlist& kwl, + const char* prefix) +{ + //--- + // Find the dted direcories to search in. + // We'll capture these regardless of being enabled in case someone wants to + // turn on the autoload midstream in a program. + //--- + const char DTED_DIRECTORY_KW[] = "dted_directory"; + + int number_of_directories = kwl.numberOf(DTED_DIRECTORY_KW); + + if (number_of_directories) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::addDtedFactories:" + << "\nNumber of dirs = " << number_of_directories + << std::endl; + } + + int count = 0; + + //--- + // Look for just the keyword "dted_directory" with no number appended + // to it. + // + const char* lookup = kwl.find(prefix, DTED_DIRECTORY_KW); + if (lookup) + { + ++count; + ossimFilename f = lookup; + addDtedFactory(f); + } + + // Look for numbered keyword like "dted_directory1". + int dir_number = 0; + while ((count < number_of_directories) && + (dir_number < 1000) ) + { + ossimString key = DTED_DIRECTORY_KW; + key += ossimString::toString(dir_number); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::addDtedFactories:" + << "\nLooking for key: " << key + << std::endl; + } + + lookup = kwl.find(prefix, key); + if (lookup) + { + ++count; + ossimFilename f = lookup; + addDtedFactory(f); + } + + ++dir_number; + + } // End of "while (count < number_of_directories)" + + } // End of "if (number_of_directories) + else + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::addDtedFactories::" + << "\nNo dted_directories found in the keyword list." + << std::endl; + } + } + +} + +void ossimElevManager::addSrtmFactories(const ossimKeywordlist& kwl, + const char* prefix) +{ + //--- + // Find the srtm direcories to search in. + // We'll capture these regardless of being enabled in case someone wants to + // turn on the autoload midstream in a program. + //--- + const char SRTM_DIRECTORY_KW[] = "srtm_directory"; + + int number_of_directories = kwl.numberOf(SRTM_DIRECTORY_KW); + + if (number_of_directories) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::addSrtmFactories:" + << "\nNumber of dirs = " << number_of_directories + << std::endl; + } + + int count = 0; + + //--- + // Look for just the keyword "srtm_directory" with no number appended + // to it. + //--- + const char* lookup = kwl.find(prefix, SRTM_DIRECTORY_KW); + if (lookup) + { + ++count; + ossimFilename f = lookup; + + if (f.isDir()) + { + // Add a srtm factory for this directory. + ossimRefPtr<ossimElevSourceFactory> factory = new ossimSrtmFactory(f); + addElevSourceFactory(factory); + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "Added elevation factory for: " << f.c_str() + << std::endl; + } + } + } + + // Look for numbered keyword like "srtm_directory1". + int dir_number = 0; + while ((count < number_of_directories) && + (dir_number < 1000) ) + { + ossimString key = SRTM_DIRECTORY_KW; + key += ossimString::toString(dir_number); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::addSrtmFactories:" + << "\nLooking for key: " << key + << std::endl; + } + + lookup = kwl.find(prefix, key); + if (lookup) + { + ++count; + + ossimFilename f = lookup; + if (f.isDir()) + { + // Add a srtm factory for this directory. + ossimRefPtr<ossimElevSourceFactory> factory = new ossimSrtmFactory(f); + addElevSourceFactory(factory); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "Added srtm factory for: " << f.c_str() << std::endl; + } + } + } + + ++dir_number; + + } // End of "while (count < number_of_directories)" + + } // End of "if (number_of_directories) + else + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::addSrtmFactories::" + << "\nNo srtm_directories found in the keyword list." + << std::endl; + } + } +} + +bool ossimElevManager::isDtedFilenameFormat(const ossimFilename& file) const +{ + // Format example: "n32.dt2" + + // Strip any path away. + ossimFilename f = file.file(); + + // Downcase it. + f.downcase(); + + // Must be seven characters long. + if (f.size() != 7) + { + return false; + } + + // Must start with 'n' or 's'. + if ( (f[0] != 'n') && (f[0] != 's') ) + { + return false; + } + + // Fourth character must be a dot '.'. + if (f[3] != '.') + { + return false; + } + + // Fith character must be a 'd'. + if (f[4] != 'd') + { + return false; + } + + // Sixth character must be a 't'. + if (f[5] != 't') + { + return false; + } + + return true; +} + +bool ossimElevManager::isSrtmFilenameFormat(const ossimFilename& file) const +{ + // Format example: "N37W120.hgt" + // or N37W120.hgt.gz + + // Strip any path away. + ossimFilename f = file.file(); + + // Downcase it. + f.downcase(); + + // Must be eleven characters long. or if it's gzipped then + // it can be 14 characters lond with the .gz added extension + // + if ((f.size() != 11)&& + (f.size() != 14)) + { + return false; + } + + // Must start with 'n' or 's'. + if ( (f[0] != 'n') && (f[0] != 's') ) + { + return false; + } + + // Fourth character must be 'e' or 'w'. + if ( (f[3] != 'e') && (f[3] != 'w') ) + { + return false; + } + + // Eight character must be a dot '.'. + if (f[7] != '.') + { + return false; + } + + if(!f.contains(".hgt")&& + !f.contains(".hgt.gz")) + { + return false; + } + // Extension must be "hgt". +// if (f.ext() != "hgt") +// { +// return false; +// } + + return true; +} + + +bool ossimElevManager::isDtedDirectory(const ossimFilename& dir) const +{ + //--- + // Sample format + // dir + // | | + // e040 e041 + // | | | | + // n31.dt2 n32.dt2 n31.dt2 n32.dt2 + //--- + if (!dir.isDir()) + { + return false; + } + + ossimDirectory od(dir); + if (od.isOpened() == false) + { + return false; + } + + ossimFilename f; + // Get the first directory. + od.getFirst(f, ossimDirectory::OSSIM_DIR_DEFAULT); + + do + { + // Must be a directory. + if (f.isDir()) + { + + // Discard any full path. + f = f.file(); + + // Downcase it. + f.downcase(); + + // Must start with 'e' or 'w'. + if ( ((f.c_str()[0] == 'e') || ( f.c_str()[0] == 'w')) && + (f.size() == 4)) + { + return true; + } + } + }while(od.getNext(f)); + + return false; +} + +bool ossimElevManager::isSrtmDirectory(const ossimFilename& dir) const +{ + //--- + // Sample format: + // dir + // | | + // N35W121.hgt N35W121.hgt + //--- + if (!dir.isDir()) + { + return false; + } + + ossimDirectory od(dir); + if (od.isOpened() == false) + { + return false; + } + + ossimFilename f; + + if(od.getFirst(f, ossimDirectory::OSSIM_DIR_FILES)) + { + do + { + if(isSrtmFilenameFormat(f)) + { + return true; + } + }while(od.getNext(f)); + } + + + return isSrtmFilenameFormat(f); +} + +bool ossimElevManager::openDtedCell(const ossimFilename& file) +{ + if (isCellOpen(file)) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::openDtedCell:\n" + << file << " has already been opened by the manager." + << std::endl; + } + + return false; + } + + ossimElevSource* source = new ossimDtedHandler(file); + if (source->getErrorStatus() == ossimErrorCodes::OSSIM_OK) + { + // Add the source to the list. + addElevSource(source); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::openDtedCell:" + << "\nAdded dted cell: " << file << std::endl; + } + } + else + { + delete source; + return false; + } + return true; +} + +bool ossimElevManager::openSrtmCell(const ossimFilename& file) +{ + if (isCellOpen(file)) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::openSrtmCell:\n" + << file << " has already been opened by the manager." + << std::endl; + } + return false; + } + + ossimElevSource* source = new ossimSrtmHandler(file); + if (source->getErrorStatus() == ossimErrorCodes::OSSIM_OK) + { + // Add the source to the list. + addElevSource(source); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevManager::openSrtmCell:" + << "\nAdded srtm cell: " << file << std::endl; + } + } + else + { + delete source; + return false; + } + return true; +} + +void ossimElevManager::addDtedFactory(const ossimFilename& file) +{ + // Add a dted factory for this directory. + ossimRefPtr<ossimElevSourceFactory> factory = new ossimDtedFactory(file); + addElevSourceFactory(factory); + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimElevManager::addDtedFactory:" + << "\nAdded elevation factory for: " << file.c_str() + << std::endl; + } +} + +void ossimElevManager::addSrtmFactory(const ossimFilename& file) +{ + ossimRefPtr<ossimElevSourceFactory> factory = new ossimSrtmFactory(file); + addElevSourceFactory(factory); + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "Added elevation factory for: " << file.c_str() + << std::endl; + } +} + diff --git a/Utilities/OSSIM/ossim_core/elevation/ossimElevManager.h b/Utilities/OSSIM/ossim_core/elevation/ossimElevManager.h new file mode 100644 index 0000000000..3211341f0c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/ossimElevManager.h @@ -0,0 +1,331 @@ +//***************************************************************************** +// FILE: ossimElevManager.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: See top level LICENSE.txt file. +// +// DESCRIPTION: +// Contains declaration of class ossimElevManager. This object provides a +// single interface to an imaging chain for accessing multiple elevation +// sources. This object owns one or more elevation sources in an ordered +// list. When queried for an elevation at a particular point, it searches +// the available sources for the best result, instantiating new sources if +// necessary. +// +// SOFTWARE HISTORY: +//> +// 13Apr2001 Oscar Kramer +// Initial coding. +//< +//***************************************************************************** +#ifndef ossimElevManager_HEADER +#define ossimElevManager_HEADER + +#include <vector> +#include <elevation/ossimElevSource.h> +#include <base/common/ossimMutex.h> +#include <elevation/ossimElevSourceFactory.h> + +class ossimDrect; +class ossimKeywordlist; +class ossimElevHandler; +class ossimGeoidManager; + +// class ossimDtedManager; + +/*!**************************************************************************** + * CLASS: ossimElevManager + * + *****************************************************************************/ +class OSSIMDLLEXPORT ossimElevManager : public ossimElevSource +{ +public: + virtual ~ossimElevManager(); + + /*! + * METHOD: instance() + * Implements singelton pattern + */ + static ossimElevManager* instance(); + + /*! + * Height access methods: + * Return OSSIM_DBL_NAN if point is not found. + */ + virtual double getHeightAboveMSL(const ossimGpt& gpt); + virtual double getHeightAboveEllipsoid(const ossimGpt& gpt); + + /*! + * Method to check if the ground point elevation is defined: + */ + virtual bool pointHasCoverage(const ossimGpt& gpt) const; + + /*! + * Method to load new elevation data given ground rectangle: + */ + void loadElevData(const ossimDrect& ground_rect); + + /*! + * METHODS: accuracyLE90(), accuracyCE90() + * Returns the vertical and horizontal accuracy (90% confidence) in the + * region of gpt: + */ + virtual double getAccuracyLE90(const ossimGpt& gpt) const; + virtual double getAccuracyCE90(const ossimGpt& gpt) const; + + /*! + * METHOD: meanSpacingMeters() const + * Returns the mean spacing in meters between posts in the region of gpt. + */ + virtual double getMeanSpacingMeters() const; + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0) const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual void addElevSource(ossimElevSource* source); + virtual void addElevSourceFactory( + ossimRefPtr<ossimElevSourceFactory> factory); + + // Auto loading control... + virtual void enableAutoLoad(); + virtual void disableAutoLoad(); + virtual bool isAutoLoadEnabled() const; + + /*! + * Auto sorting control... + * Auto sorting sorts cell on add by mean post spacing putting cells with + * lowest(best) post spacing at the top. + */ + virtual void enableAutoSort(); + virtual void disableAutoSort(); + virtual bool isAutoSortEnabled() const; + + /*! + * METHOD: bool isCellOpen(const ossimFilename& cell) const + * Returns true if cell is currently opened(in theElevSourceList). + */ + virtual bool isCellOpen(const ossimFilename& cell) const; + + virtual ossimRefPtr<ossimElevSourceFactory> findFactoryFromDir( + const ossimFilename& dir); + virtual const ossimRefPtr<ossimElevSourceFactory> findFactoryFromDir( + const ossimFilename& dir)const; + + + /*! + * METHOD: bool openDirectory(const ossimFilename& dir) + * Method to open a directory of elevation cells. + * Returns true on success, false on error. + */ + virtual bool openDirectory(const ossimFilename& dir); + + /*! + * METHOD: bool openCell(const ossimFilename& cell) + * Method to open an elevation cell. + * Returns true on success, false on error. + */ + virtual bool openCell(const ossimFilename& cell); + + /*! + * METHOD: bool closeCell(const ossimFilename& cell) + * Method to close an elevation cell. + * Returns true on success, false on error. + */ + virtual bool closeCell(const ossimFilename& cell); + + /*! + * METHOD: void closeAllCells() + * Method to close all open elevation cells. + */ + virtual void closeAllCells(); + + /*! + * METHOD: bool moveCellUpOne(const ossimFilename& cell) + * Method to move an elevation cell on the list up by one. + * Returns true on success, false on error. + */ + virtual bool moveCellUpOne(const ossimFilename& cell); + + /*! + * METHOD: bool moveCellDownOne(const ossimFilename& cell) + * Method to move an elevation cell on the list down by one. + * Returns true on success, false on error. + */ + virtual bool moveCellDownOne(const ossimFilename& cell); + + /*! + * METHOD: bool moveCellToTop(const ossimFilename& cell) + * Method to move an elevation cell to the top of the list. + * Returns true on success, false on error. + */ + virtual bool moveCellToTop(const ossimFilename& cell); + + /*! + * METHOD: bool moveCellToBottomconst ossimFilename& cell) + * Method to move an elevation cell to the bottom of the list. + * Returns true on success, false on error. + */ + virtual bool moveCellToBottom(const ossimFilename& cell); + + /*! + * @param list List to initialize with open cells. + * + * @note list is clear prior to stuffing. + */ + void getOpenCellList(std::vector<ossimFilename>& list) const; + + ossimFilename getDefaultElevationPath() const; + + void setDefaultElevationPath(const ossimFilename& path); + +protected: + typedef std::vector<ossimRefPtr<ossimElevSourceFactory> >::iterator ossimElevSourceFactoryIterator; + typedef std::vector<ossimRefPtr<ossimElevSourceFactory> >::const_iterator ossimElevSourceFactoryConstIterator; + + typedef std::vector<ossimRefPtr<ossimElevSource> >::iterator ossimElevSourceListIterator; + typedef std::vector<ossimRefPtr<ossimElevSource> >::const_iterator ossimElevSourceListConstIterator; + + /*! Protected constructor. */ + ossimElevManager(); + + void updateMinMax(); + + /** + * Searches keyword list for "elevation_directory" keywords and adds + * factories if found. Will look for key words in this order. + * + * 1) "elevation_directory" + * 2) "elevation_directory0" + * 3) "elevation_directory1" + * ... + * ... + * Until count of all elevation_directory keywords is reached. + * + * @param kwl Keyword list to search. + * + * @prefix Prefix for keys. + */ + void addElevFactories(const ossimKeywordlist& kwl, const char* prefix=0); + + /** + * Searches keyword list for "dted_directory" keywords and adds factories + * if found. Will look for key words in this order. + * + * 1) "dted_directory" + * 2) "dted_directory0" + * 3) "dted_directory1" + * ... + * ... + * Until count of all dted_directory keywords is reached. + * + * @param kwl Keyword list to search. + * + * @prefix Prefix for keys. + */ + void addDtedFactories(const ossimKeywordlist& kwl, const char* prefix=0); + + /** + * Searches keyword list for "srtm_directory" keywords and adds factories + * if found. Will look for key words in this order. + * + * 1) "srtm_directory" + * 2) "srtm_directory0" + * 3) "srtm_directory1" + * ... + * ... + * Until count of all srtm_directory keywords is reached. + * + * @param kwl Keyword list to search. + * + * @prefix Prefix for keys. + */ + void addSrtmFactories(const ossimKeywordlist& kwl, const char* prefix=0); + + /** + * Searches keyword list for "elevation_cell" keywords and adds + * factories if found. Will look for key words in this order. + * + * 1) "elevation_cell" + * 2) "elevation_cell0" + * 3) "elevation_cell1" + * ... + * ... + * Until count of all elevation_cell keywords is reached. + * + * @param kwl Keyword list to search. + * + * @prefix Prefix for keys. + */ + void addElevCells(const ossimKeywordlist& kwl, const char* prefix=0); + + /** + * Method to determine if a file name is of dted format. + * + * @param f File to look at. + * + * @return true if dted format, false if not. + */ + bool isDtedFilenameFormat(const ossimFilename& file) const; + + /** + * Method to determine if a file name is of srtm format. + * + * @param f File to look at. + * + * @return true if dted format, false if not. + */ + bool isSrtmFilenameFormat(const ossimFilename& file) const; + + /** + * Method to determine if a directory is of dted structure. + * + * @param dir Directory to look at. + * + * @return true if dted directory structure, false if not. + */ + bool isDtedDirectory(const ossimFilename& dir) const; + + /** + * Method to determine if a directory looks like srtm. + * + * @param dir Directory to look at. + * + * @return true if srtm directory structure, false if not. + */ + bool isSrtmDirectory(const ossimFilename& dir) const; + + bool openDtedCell(const ossimFilename& file); + + bool openSrtmCell(const ossimFilename& file); + + void addDtedFactory(const ossimFilename& file); + + void addSrtmFactory(const ossimFilename& file); + + /*! + * Data members: + */ + static ossimElevManager* theInstance; + std::vector<ossimRefPtr<ossimElevSource> > theElevSourceList; + std::vector<ossimRefPtr<ossimElevSourceFactory> > theElevSourceFactoryList; + ossimGeoidManager* theGeoidManager; + bool theAutoLoadFlag; + bool theAutoSortFlag; + ossimFilename theDefaultElevationPath; + ossimMutex theMutex; +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/elevation/ossimElevSource.cpp b/Utilities/OSSIM/ossim_core/elevation/ossimElevSource.cpp new file mode 100644 index 0000000000..2bf61ee420 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/ossimElevSource.cpp @@ -0,0 +1,265 @@ +//***************************************************************************** +// FILE: ossimElevSource.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// DESCRIPTION: +// Contains implementation of class ossimElevSource. This is the base class +// for all sources of elevation data. it maintains a single common static +// instance of the geoid for use by all instances of objects derived from +// this one. +// +// SOFTWARE HISTORY: +//> +// 18Apr2001 Oscar Kramer +// Initial coding. +//< +//***************************************************************************** +// $Id: ossimElevSource.cpp,v 1.22 2005/11/17 17:22:58 gpotts Exp $ + +#include <elevation/ossimElevSource.h> +#include <base/common/ossimPreferences.h> +#include <base/data_types/ossimGpt.h> +#include <base/data_types/ossimEcefRay.h> +#include <base/data_types/datum/ossimDatum.h> +#include <base/data_types/ellipse/ossimEllipsoid.h> +#include <base/context/ossimNotifyContext.h> + +RTTI_DEF1(ossimElevSource, "ossimElevSource" , ossimSource) + +//*** +// Define Trace flags for use within this file: +//*** +#include <base/common/ossimTrace.h> +static ossimTrace traceExec ("ossimElevSource:exec"); +static ossimTrace traceDebug ("ossimElevSource:debug"); + +const double ossimElevSource::DEFAULT_NULL_HEIGHT = OSSIM_DBL_NAN; +const double ossimElevSource::DEFAULT_SEA_LEVEL = 0.0; + +static const char ENABLE_STATS_KW[] = "elevation.compute_statistics.enabled"; + +ossimElevSource::ossimElevSource() + : + theMinHeightAboveMSL (0.0), + theMaxHeightAboveMSL (0.0), + theNullHeightValue (DEFAULT_NULL_HEIGHT), + theSeaLevelValue (DEFAULT_SEA_LEVEL), + theGroundRect(), + theComputeStatsFlag(true) + +{ + if (traceExec()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevSource::ossimElevSource: entering..." + << std::endl; + } + + // User can turn on off with a keyword. + const char* lookup = + ossimPreferences::instance()->findPreference(ENABLE_STATS_KW); + if (lookup) + { + theComputeStatsFlag = ossimString(lookup).toBool(); + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG:" + << "\ntheComputeStatsFlag: " + << (theComputeStatsFlag?"true":"false") + << endl; + } + + + if (traceExec()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimElevSource::ossimElevSource: returning..." + << std::endl; + } +} + +ossimElevSource::~ossimElevSource() +{} + +double ossimElevSource::getHeightAboveEllipsoid(const ossimGpt& argGpt) +{ + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimElevSource::getHeightAboveEllipsoid Not implemented..." + << std::endl; + return theNullHeightValue; +} + +//***************************************************************************** +// METHOD: intersectRay() +// +// Service method for intersecting a ray with the elevation surface to +// arrive at a ground point. The ray is expected to originate ABOVE the +// surface and pointing down. +// +// NOTE: the gpt argument is expected to be initialized with the desired +// datum, including ellipsoid, for the proper intersection point to be +// computed. +// +// LIMITATION: This release supports only single valued solutions, i.e., it +// is possible a ray passing through one side of a mountain and out the other +// will return an intersection with the far side. Eventually, a more robust +// algorithm will be employed. +// +//***************************************************************************** +bool ossimElevSource::intersectRay(const ossimEcefRay& ray, ossimGpt& gpt) +{ + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimElevSource::intersectRay: entering..." << std::endl; + + static const double CONVERGENCE_THRESHOLD = 0.001; // meters + static const int MAX_NUM_ITERATIONS = 50; + + double h_ellips; // height above ellipsoid + bool intersected; + ossimEcefPoint prev_intersect_pt (ray.origin()); + ossimEcefPoint new_intersect_pt; + double distance; + bool done = false; + int iteration_count = 0; + + //*** + // Set the initial guess for horizontal intersect position as the ray's + // origin, and establish the datum and ellipsoid: + //*** + const ossimDatum* datum = gpt.datum(); + const ossimEllipsoid* ellipsoid = datum->ellipsoid(); +// double lat, lon, h; + +// ellipsoid->XYZToLatLonHeight(ray.origin().x(), +// ray.origin().y(), +// ray.origin().z(), +// lat, lon, h); +// ossimGpt nadirGpt(lat, lon, h); + +// std::cout << "nadir pt = " << nadirGpt << std::endl; + + gpt = ossimGpt(prev_intersect_pt, datum); + + // + // Loop to iterate on ray intersection with variable elevation surface: + // + do + { + // + // Intersect ray with ellipsoid inflated by h_ellips: + // + h_ellips = getHeightAboveEllipsoid(gpt); + if (h_ellips == theNullHeightValue) h_ellips = 0.0; + + intersected = ellipsoid->nearestIntersection(ray, + h_ellips, + new_intersect_pt); + if (!intersected) + { + // + // No intersection (looking over the horizon), so set ground point + // to NaNs: + // + gpt.makeNan(); + done = true; + } + else + { + // + // Assign the ground point to the latest iteration's intersection + // point: + // + gpt = ossimGpt(new_intersect_pt, datum); + + // + // Determine if convergence achieved: + // + distance = (new_intersect_pt - prev_intersect_pt).magnitude(); + if (distance < CONVERGENCE_THRESHOLD) + done = true; + else + { + prev_intersect_pt = new_intersect_pt; + } + } + + iteration_count++; + + } while ((!done) && (iteration_count < MAX_NUM_ITERATIONS)); + + if (iteration_count == MAX_NUM_ITERATIONS) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_WARN) << "WARNING ossimElevSource::intersectRay: Max number of iterations reached solving for ground " + << "point. Result is probably inaccurate." << std::endl; + } + } + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimElevSource::intersectRay: returning..." << std::endl; + return intersected; +} + +double ossimElevSource::getMinHeightAboveMSL() const +{ + return theMinHeightAboveMSL; +} + +double ossimElevSource::getMaxHeightAboveMSL() const +{ + return theMaxHeightAboveMSL; +} + +double ossimElevSource::getNullHeightValue() const +{ + return theNullHeightValue; +} + +double ossimElevSource::getSeaLevelValue() const +{ + return theSeaLevelValue; +} + +const ossimGrect& ossimElevSource::getBoundingGndRect() const +{ + return theGroundRect; +} + +bool ossimElevSource::canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const +{ + return false; +} + +void ossimElevSource::initialize() +{} + +ossimFilename ossimElevSource::getFilename() const +{ + return ossimFilename::NIL; +} + +bool ossimElevSource::open() const +{ + return true; +} + +void ossimElevSource::close() const +{ +} + +bool ossimElevSource::getComputeStatisticsFlag() const +{ + return theComputeStatsFlag; +} + +void ossimElevSource::setComputeStatisticsFlag(bool flag) +{ + theComputeStatsFlag = flag; +} diff --git a/Utilities/OSSIM/ossim_core/elevation/ossimElevSource.h b/Utilities/OSSIM/ossim_core/elevation/ossimElevSource.h new file mode 100644 index 0000000000..81b69382c1 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/ossimElevSource.h @@ -0,0 +1,184 @@ +//***************************************************************************** +// FILE: ossimElevSource.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// AUTHOR: Oscar Kramer +// +// DESCRIPTION: +// Contains declaration of class ossimElevSource. This is the base class for +// all objects providing height information given horizontal ground position. +// +//***************************************************************************** +// $Id: ossimElevSource.h,v 1.19 2005/03/03 21:52:30 dburken Exp $ + +#ifndef ossimElevSource_HEADER +#define ossimElevSource_HEADER + +#include <base/common/ossimSource.h> +#include <base/data_types/ossimGrect.h> +#include <base/data_types/ossimFilename.h> +#include <base/data_types/geoid/ossimGeoid.h> + +class ossimEcefRay; +class ossimKeywordlist; + +/****************************************************************************** + * CLASS: ossimElevSource + * + *****************************************************************************/ +class ossimElevSource : public ossimSource +{ +public: + + virtual ~ossimElevSource(); + + /** + * Height access methods: + */ + virtual double getHeightAboveMSL(const ossimGpt&) = 0; + virtual double getHeightAboveEllipsoid(const ossimGpt&); + + /** + * METHOD: intersectRay() + * + * Service method for intersecting a ray with the elevation surface to + * arrive at a ground point. The ray is expected to originate ABOVE the + * surface and pointing down. + * + * NOTE: the gpt argument is expected to be initialized with the desired + * datum, including ellipsoid, for the proper intersection point to be + * computed. + * + * LIMITATION: This release supports only single valued solutions, i.e., it + * is possible a ray passing through one side of a mountain and out the + * other will return an intersection with the far side. Eventually, + * a more robust algorithm will be employed. + * + * Returns true if good intersection found. + */ + bool intersectRay(const ossimEcefRay& ray, ossimGpt& gpt); + + /** + * Access methods for the bounding elevations: + */ + virtual double getMinHeightAboveMSL() const; + virtual double getMaxHeightAboveMSL() const; + + /** + * Special numeric quantities as defined by this source: + */ + double getNullHeightValue() const; + double getSeaLevelValue() const; + + /** + * METHOD: pointHasCoverage(gpt) + * Returns TRUE if coverage exists over gpt: + */ + virtual bool pointHasCoverage(const ossimGpt&) const = 0; + + /** + * METHOD: meanSpacingMeters() + * This method returns the post spacing in the region of gpt: + */ + virtual double getMeanSpacingMeters() const = 0; + + /** + * METHODS: accuracyLE90(), accuracyCE90() + * Returns the vertical and horizontal accuracy (90% confidence) in the + * region of gpt: + */ + virtual double getAccuracyLE90(const ossimGpt& gpt) const = 0; + virtual double getAccuracyCE90(const ossimGpt& gpt) const = 0; + + + /** + * METHOD: getBoundingGndRect + * + * @return The bounding geograpic rectangle in decimal degrees. + */ + virtual const ossimGrect& getBoundingGndRect() const; + + virtual bool canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const; + + /** + * Implement ossimSource base-class pure virtuals: + */ + virtual void initialize(); + + virtual ossimFilename getFilename() const; + + /** + * Opens a stream to an elevation cell. + * + * @return Returns true on success, false on error. + * + * @note This implementation always returns true. This should be + * overridden in derived classes that have streams to files. + */ + virtual bool open() const; + + /** + * Closes the stream to the file. + * + * @note This implementation does nothing. This should be + * overridden in derived classes that have streams to files. + */ + virtual void close()const; + + /** + * @return Returns the flag which controls whether or not statistics will + * be computed upon opening a cell and not finding a corresponding + * statistics file. + */ + virtual bool getComputeStatisticsFlag() const; + + /** + * Sets the flag which controls whether or not statistics will + * be computed upon opening a cell and not finding a corresponding + * statistics file. + * + * @param flag true to enable, false to disable. + * + * @note This flag can also be controlled by user via the ossim preferences + * keyword = "elevation.compute_statistics.enabled". + */ + virtual void setComputeStatisticsFlag(bool flag); + + /** + * Static, public data members: + */ + static const double DEFAULT_NULL_HEIGHT; + static const double DEFAULT_SEA_LEVEL; + +protected: + /** + * Constructors/Destructors: + */ + ossimElevSource(); + + + /** + * Data members: + */ + double theMinHeightAboveMSL; + double theMaxHeightAboveMSL; + double theNullHeightValue; + double theSeaLevelValue; + ossimGrect theGroundRect; + + //> Controls statistics gathering. Defaulted to true. + bool theComputeStatsFlag; + + +private: + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/elevation/ossimElevSourceFactory.cpp b/Utilities/OSSIM/ossim_core/elevation/ossimElevSourceFactory.cpp new file mode 100644 index 0000000000..eda0250a33 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/ossimElevSourceFactory.cpp @@ -0,0 +1,43 @@ +//---------------------------------------------------------------------------- +// FILE: ossimElevSourceFactory.cc +// +// Copyright (C) 2002 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Class definition for ossimElevSourceFactory. +// +// This is the base class interface for elevation source factories. Contains +// pure virtual methods that all elevation source factories must implement. +// +//---------------------------------------------------------------------------- +// $Id: ossimElevSourceFactory.cpp,v 1.3 2005/11/16 20:22:19 dburken Exp $ + +#include <elevation/ossimElevSourceFactory.h> + +RTTI_DEF1(ossimElevSourceFactory, "ossimElevSourceFactory" , ossimObject) + +ossimElevSourceFactory::ossimElevSourceFactory() + : theDirectory(ossimFilename::NIL) +{ +} + +ossimElevSourceFactory::~ossimElevSourceFactory() +{ +} + +ossimFilename ossimElevSourceFactory::getDirectory() const +{ + return theDirectory; +} + +void ossimElevSourceFactory::setDirectory(const ossimFilename& directory) +{ + theDirectory = directory; +} diff --git a/Utilities/OSSIM/ossim_core/elevation/ossimElevSourceFactory.h b/Utilities/OSSIM/ossim_core/elevation/ossimElevSourceFactory.h new file mode 100644 index 0000000000..253033f45b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/ossimElevSourceFactory.h @@ -0,0 +1,76 @@ +//---------------------------------------------------------------------------- +// FILE: ossimElevSourceFactory.cc +// +// Copyright (C) 2002 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Class declaration for ossimElevSourceFactory. +// +// This is the base class interface for elevation source factories which main +// function is to return an elevation source that covers the ground point +// passed to the "getElevSource" method. +// +// Note the caller of "getElevSource" is responsible for managing the memory +// new'd from the method. +// +//---------------------------------------------------------------------------- +// $Id: ossimElevSourceFactory.h,v 1.4 2005/11/18 20:24:49 gpotts Exp $ + +#ifndef ossimElevSourceFactory_HEADER +#define ossimElevSourceFactory_HEADER + +#include <base/common/ossimObject.h> +#include <base/data_types/ossimFilename.h> + +class ossimElevSource; +class ossimGpt; + +/*!**************************************************************************** + * CLASS: ossimElevSourceFactory + * + *****************************************************************************/ +class OSSIM_DLL ossimElevSourceFactory : public ossimObject +{ +public: + + /** default constructor */ + ossimElevSourceFactory(); + + /** virtual destructor */ + virtual ~ossimElevSourceFactory(); + + /** + * Pure virtual method. + * return an elevation source pointer that has elevation coverage for the + * ground point passed in. + * Note the caller of this method is responsible for managing the memory + * allocated. + */ + virtual ossimElevSource* getNewElevSource(const ossimGpt& gpt)const=0; + virtual void createIndex()=0; + + /** + * @return The directory the factory returns data from. + */ + virtual ossimFilename getDirectory() const; + + /** + * @param directory The directory to return data from. + */ + virtual void setDirectory(const ossimFilename& directory); + +protected: + + ossimFilename theDirectory; + +TYPE_DATA +}; + +#endif /* End of "#ifndef ossimElevSourceFactory_HEADER" */ diff --git a/Utilities/OSSIM/ossim_core/elevation/ossimElevationShapeIdx.cpp b/Utilities/OSSIM/ossim_core/elevation/ossimElevationShapeIdx.cpp new file mode 100644 index 0000000000..4cae3055f7 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/ossimElevationShapeIdx.cpp @@ -0,0 +1,274 @@ +#include "ossimElevationShapeIdx.h" +#include <vec/shape/shapefil.h> + +ossimString ossimElevationShapeIdx::theDefaultName = "elevation_idx.shp"; + +class ossimElevationShapeIdxPrivate : public ossimReferenced +{ +public: + ossimElevationShapeIdxPrivate() + :theShapefileHandle(0), + theDbfHandle(0) + { + } + virtual ~ossimElevationShapeIdxPrivate() + { + shpClose(); + } + SHPHandle shpOpen(const ossimFilename& file, bool overWriteFlag) + { + shpClose(); + theShapeFilename = file; + if(overWriteFlag) + { + theShapefileHandle = SHPCreate(file.c_str(), + SHPT_POLYGON); + } + else + { + theShapefileHandle = SHPOpen(file.c_str(), + "r+b"); + if(!theShapefileHandle) + { + theShapefileHandle = SHPCreate(file.c_str(), + SHPT_POLYGON); + } + } + dbfOpen(overWriteFlag); + + return theShapefileHandle; + } + void shpClose() + { + if(theShapefileHandle) + { + SHPClose(theShapefileHandle); + theShapefileHandle = 0; + } + } + SHPHandle shpHandle() + { + return theShapefileHandle; + } + + DBFHandle dbfHandle() + { + return theDbfHandle; + } + +protected: + void dbfOpen(bool overWriteFlag) + { + dbfClose(); + + if(overWriteFlag) + { + theDbfHandle = DBFCreate(theShapeFilename.c_str()); + if(theDbfHandle) + { + DBFAddField(theDbfHandle, "FILENAME", FTString, 256, 0); + DBFAddField(theDbfHandle, "MINZ", FTDouble, 32, 17); + DBFAddField(theDbfHandle, "MAXZ", FTDouble, 32, 17); + } + } + else + { + theDbfHandle = DBFOpen(theShapeFilename.c_str(), "r+b"); + if(!theDbfHandle) + { + theDbfHandle = DBFCreate(theShapeFilename.c_str()); + if(theDbfHandle) + { + DBFAddField(theDbfHandle, "FILENAME", FTString, 256, 0); + DBFAddField(theDbfHandle, "MINZ", FTDouble, 32, 17); + DBFAddField(theDbfHandle, "MAXZ", FTDouble, 32, 17); + } + } + } + } + void dbfClose() + { + if(theDbfHandle) + { + DBFClose(theDbfHandle); + theDbfHandle = 0; + } + } + ossimFilename theShapeFilename; + SHPHandle theShapefileHandle; + DBFHandle theDbfHandle; +}; + +ossimElevationShapeIdx::ossimElevationShapeIdx(const ossimFilename& shapeFilename, + bool overWriteFlag) +{ + setFilename(shapeFilename, overWriteFlag); +} + +ossimElevationShapeIdx::~ossimElevationShapeIdx() +{ + if(thePrivateData) + { + delete thePrivateData; + thePrivateData = 0; + } +} + +const ossimString& ossimElevationShapeIdx::defaultName() +{ + return theDefaultName; +} + +void ossimElevationShapeIdx::setFilename(const ossimFilename& shapeFilename, bool overWriteFlag)throw(std::exception()) +{ + if(thePrivateData) + { + delete thePrivateData; + thePrivateData = 0; + } + if(shapeFilename == "") return; + if(shapeFilename.isDir()) + { + theShapeFilename = shapeFilename.dirCat(theDefaultName); + } + else if(shapeFilename.isFile()) + { + theShapeFilename = shapeFilename; + theShapeFilename.setExtension("shp"); + } + else + { + theShapeFilename = shapeFilename.path(); + + theShapeFilename = theShapeFilename.dirCat(theDefaultName); + theShapeFilename.setExtension("shp"); + } + thePrivateData = new ossimElevationShapeIdxPrivate(); + + if(!thePrivateData->shpOpen(theShapeFilename, overWriteFlag)) + { + thePrivateData = 0; + throw(("ossimElevationShapeIdx::setFilename: Unable to setup index file " + theShapeFilename).c_str()); + } + double minBounds[4]; + double maxBounds[4]; + int nEntities = 0; + int shapeType = SHPT_NULL; + SHPGetInfo(thePrivateData->shpHandle(), + &nEntities, + &shapeType, + minBounds, + maxBounds); + if(nEntities < 0) + { + // set it up for the adds + // + theGlobalMinx = 180.0; + theGlobalMiny = 90.0; + theGlobalMaxx = -180.0; + theGlobalMaxy = -90.0; + } + else + { + theGlobalMinx = minBounds[0]; + theGlobalMiny = minBounds[1]; + theGlobalMaxx = maxBounds[0]; + theGlobalMaxy = maxBounds[1]; + } +} + +void ossimElevationShapeIdx::add(const ossimFilename& filename, + ossim_float64 minx, // decimal degrees + ossim_float64 miny, // decimal degrees + ossim_float64 minz, // meters + ossim_float64 maxx, // decimal degrees + ossim_float64 maxy, // decimal degrees + ossim_float64 maxz )// meters +{ + if(!thePrivateData) return; + int iRecord = DBFGetRecordCount(thePrivateData->dbfHandle()); + double* x = new double[8]; + double* y = new double[8]; + int nVertices = 4; + x[0] = minx; + x[1] = maxx; + x[2] = maxx; + x[3] = minx; + + y[0] = maxy; + y[1] = maxy; + y[2] = miny; + y[3] = miny; + + + if(minx < theGlobalMinx) + { + theGlobalMinx = minx; + } + if(miny < theGlobalMiny) + { + theGlobalMiny = miny; + } + if(maxx > theGlobalMaxx) + { + theGlobalMaxx = maxx; + } + if(maxy > theGlobalMaxy) + { + theGlobalMaxy = maxy; + } + SHPObject* obj = SHPCreateSimpleObject(SHPT_POLYGON, + nVertices, + x, + y, + 0); + + SHPWriteObject( thePrivateData->shpHandle(), + -1, + obj ); + DBFWriteStringAttribute(thePrivateData->dbfHandle(), + iRecord, + 0, + filename.c_str()); + DBFWriteDoubleAttribute(thePrivateData->dbfHandle(), + iRecord, + 0, + (double)minz); + DBFWriteDoubleAttribute(thePrivateData->dbfHandle(), + iRecord, + 0, + (double)maxz); +} + +void ossimElevationShapeIdx::buildQuadTree(int maxDepth) +{ + if(!thePrivateData) return; + + ossimFilename qTree = theShapeFilename; + + qTree.setExtension("qtree"); + + if(thePrivateData->shpHandle()) + { + double minBounds[4] = {0.0,0.0,0.0,0.0}; + double maxBounds[4] = {0.0,0.0,0.0,0.0}; + + minBounds[0] = theGlobalMinx; + minBounds[1] = theGlobalMiny; + maxBounds[0] = theGlobalMaxx; + maxBounds[1] = theGlobalMaxy; + + SHPTree* tree = SHPCreateTree(thePrivateData->shpHandle(), + 2, + maxDepth, + minBounds, + maxBounds); + if(tree) + { + SHPWriteTree(tree, + qTree.c_str()); + + SHPDestroyTree(tree); + } + } +} diff --git a/Utilities/OSSIM/ossim_core/elevation/ossimElevationShapeIdx.h b/Utilities/OSSIM/ossim_core/elevation/ossimElevationShapeIdx.h new file mode 100644 index 0000000000..44498b4f21 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/elevation/ossimElevationShapeIdx.h @@ -0,0 +1,41 @@ +#ifndef ossimElevationShapeIdx_HEADER +#define ossimElevationShapeIdx_HEADER +#include <exception> +#include <base/common/ossimObject.h> +#include <base/common/ossimRefPtr.h> +#include <base/data_types/ossimFilename.h> + +class ossimElevationShapeIdxPrivate; + +class ossimElevationShapeIdx : public ossimObject +{ +public: + ossimElevationShapeIdx(const ossimFilename& shapeFilename = "", + bool overWriteFlag = false); + virtual ~ossimElevationShapeIdx(); + void setFilename(const ossimFilename& file, bool overWriteFlag=false)throw(std::exception()); + + void add(const ossimFilename& filename, + ossim_float64 minx, // decimal degrees + ossim_float64 miny, // decimal degrees + ossim_float64 minz, // height in meters meters + ossim_float64 maxx, // decimal degrees + ossim_float64 maxy, // decimal degrees + ossim_float64 maxz); // height in meters meters + + void buildQuadTree(int maxDepth=0); + static const ossimString& defaultName(); + +protected: + static ossimString theDefaultName; + ossimElevationShapeIdxPrivate* thePrivateData; + + ossimFilename theShapeFilename; + ossim_float64 theGlobalMinx; + ossim_float64 theGlobalMiny; + ossim_float64 theGlobalMaxx; + ossim_float64 theGlobalMaxy; + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/fonts/.cvsignore b/Utilities/OSSIM/ossim_core/fonts/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/fonts/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/fonts/CMakeLists.txt b/Utilities/OSSIM/ossim_core/fonts/CMakeLists.txt new file mode 100644 index 0000000000..5ce7ff17a8 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/fonts/CMakeLists.txt @@ -0,0 +1,6 @@ +FILE(GLOB_RECURSE ossim_font_SRCS "*.cpp") +FILE(GLOB_RECURSE ossim_font_HDRS "*.h") +ADD_LIBRARY(ossim_font ${ossim_font_SRCS}) + +INSTALL_TARGETS(/lib/otb/ ossim_font) +INSTALL_FILES(/include/otb/Utilities/OSSIM/ossim_core/ "\\.h$" ${ossim_font_HRDS}) diff --git a/Utilities/OSSIM/ossim_core/fonts/factory/.cvsignore b/Utilities/OSSIM/ossim_core/fonts/factory/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/fonts/factory/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/fonts/factory/ossimFontFactoryBase.h b/Utilities/OSSIM/ossim_core/fonts/factory/ossimFontFactoryBase.h new file mode 100644 index 0000000000..2255c6d713 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/fonts/factory/ossimFontFactoryBase.h @@ -0,0 +1,41 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************** +// $Id: ossimFontFactoryBase.h,v 1.4 2005/07/15 19:45:48 dburken Exp $ +#ifndef ossimFontFactoryBase_HEADER +#define ossimFontFactoryBase_HEADER +#include <base/data_types/ossimString.h> +#include <base/data_types/ossimFilename.h> +#include <base/common/ossimFontInformation.h> +class ossimFont; + +class ossimFontFactoryBase +{ +public: + + virtual ~ossimFontFactoryBase(){} + + /*! + * Will find the best font for the passed in infromation. + * If none is found a default font should be returned. + */ + virtual ossimFont* createFont(const ossimFontInformation& information)const=0; + + /*! + * Usually for trutype fonts but any font stored in a file it + * will try to create a font from it. + */ + virtual ossimFont* createFont(const ossimFilename& file)const=0; + + virtual void getFontInformation(std::vector<ossimFontInformation>& informationList)const=0; + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/fonts/factory/ossimFontFactoryRegistry.cpp b/Utilities/OSSIM/ossim_core/fonts/factory/ossimFontFactoryRegistry.cpp new file mode 100644 index 0000000000..77bb93921f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/fonts/factory/ossimFontFactoryRegistry.cpp @@ -0,0 +1,191 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: Garrett Potts +// +//******************************************************************** +// $Id: ossimFontFactoryRegistry.cpp,v 1.11 2005/12/10 20:08:39 dburken Exp $ +#include <algorithm> +#include "ossimFontFactoryRegistry.h" +#include "fonts/ossimGdBitmapFont.h" + +#if OSSIM_HAS_FREETYPE +# include "fonts/factory/ossimFreeTypeFontFactory.h" +#endif + +#include "fonts/ossimGdSansBold.inc" + +ossimFontFactoryRegistry* ossimFontFactoryRegistry::theInstance = 0; + +ossimFontFactoryRegistry::ossimFontFactoryRegistry() + :theDefaultFont(NULL) +{ + theInstance = this; +} + +ossimFontFactoryRegistry* ossimFontFactoryRegistry::instance() +{ + if(!theInstance) + { + theInstance = new ossimFontFactoryRegistry; +#if OSSIM_HAS_FREETYPE + theInstance->registerFactory(ossimFreeTypeFontFactory::instance()); +#endif + } + + return theInstance; +} + +bool ossimFontFactoryRegistry::registerFactory(ossimFontFactoryBase* factory) +{ + bool result = false; + if(factory&&!findFactory(factory)) + { + theFactoryList.push_back(factory); + result = true; + } + + return result; +} + +void ossimFontFactoryRegistry::unregisterFactory(ossimFontFactoryBase* factory) +{ + std::vector<ossimFontFactoryBase*>::iterator iter = std::find(theFactoryList.begin(), + theFactoryList.end(), + factory); + if(iter != theFactoryList.end()) + { + theFactoryList.erase(iter); + } +} + +bool ossimFontFactoryRegistry::findFactory(ossimFontFactoryBase* factory)const +{ + return (std::find(theFactoryList.begin(), + theFactoryList.end(), + factory)!=theFactoryList.end()); +} + + +ossimFont* ossimFontFactoryRegistry::createFont(const ossimFontInformation& information)const +{ + ossimFont* result = (ossimFont*)NULL; + int i = 0; + + for(i= 0; ( (i < (int)theFactoryList.size()) &&(!result)); ++i) + { + result = theFactoryList[i]->createFont(information); + } + + return result; +} + +ossimFont* ossimFontFactoryRegistry::createFont(const ossimFilename& file)const +{ + ossimFont* result = (ossimFont*)NULL; + int i = 0; + + for(i= 0; ( (i < (int)theFactoryList.size()) &&(!result)); ++i) + { + result = theFactoryList[i]->createFont(file); + } + + return result; +} + +void ossimFontFactoryRegistry::getFontInformation(std::vector<ossimFontInformation>& informationList)const +{ + int i = 0; + for(i= 0; i < (int)theFactoryList.size(); ++i) + { + theFactoryList[i]->getFontInformation(informationList); + } +} + +void ossimFontFactoryRegistry::getFontInformationFamilyName(std::vector<ossimFontInformation>& informationList, + const ossimString& familyName)const +{ + vector<ossimFontInformation> info; + getFontInformation(info); + + ossimString right = familyName; + right = right.upcase().trim(); + int i = 0; + for(i = 0; i < (int)info.size(); ++i) + { + ossimString left = info[i].theFamilyName; + left = left.upcase().trim(); + + if(left == right) + { + informationList.push_back(info[i]); + } + } +} + +void ossimFontFactoryRegistry::getFontInformationContainingFamilyName(std::vector<ossimFontInformation>& informationList, + const ossimString& familyName)const +{ + vector<ossimFontInformation> info; + getFontInformation(info); + + ossimString right = familyName; + right = right.upcase().trim(); + int i = 0; + for(i = 0; i < (int)info.size(); ++i) + { + ossimString left = info[i].theFamilyName; + + left = left.upcase().trim(); + if(left.contains(right)) + { + informationList.push_back(info[i]); + } + } +} + +ossimFont* ossimFontFactoryRegistry::getDefaultFont()const +{ + if(!theDefaultFont) + { + std::vector<ossimFontInformation> infoList; + getFontInformationContainingFamilyName(infoList, + "Times"); + if(infoList.size() < 1) + { + getFontInformationContainingFamilyName(infoList, + "Roman"); + } + if(infoList.size() < 1) + { + getFontInformationContainingFamilyName(infoList, + "Sanz"); + } + if(infoList.size() < 1) + { + getFontInformation(infoList); + } + if(infoList.size()) + { + theDefaultFont = createFont(infoList[0]); + theDefaultFont->setPixelSize(12, 12); + } + else + { + theDefaultFont = new ossimGdBitmapFont("gd sans", + "bold", + ossimGdSansBold); + } + } + return theDefaultFont; +} + +ossimFontFactoryRegistry::ossimFontFactoryRegistry(const ossimFontFactoryRegistry& /* rhs */ ) +{ +} + +void ossimFontFactoryRegistry::operator=(const ossimFontFactoryRegistry& /* rhs */ ) +{ +} diff --git a/Utilities/OSSIM/ossim_core/fonts/factory/ossimFontFactoryRegistry.h b/Utilities/OSSIM/ossim_core/fonts/factory/ossimFontFactoryRegistry.h new file mode 100644 index 0000000000..85bc85290f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/fonts/factory/ossimFontFactoryRegistry.h @@ -0,0 +1,82 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// Description: +// +//******************************************************************** +// $Id: ossimFontFactoryRegistry.h,v 1.9 2004/05/19 18:35:57 dburken Exp $ +#ifndef ossimFontFactoryRegistry_HEADER +#define ossimFontFactoryRegistry_HEADER +#include <vector> +#include "base/common/ossimFontInformation.h" +#include "base/data_types/ossimFilename.h" +#include "fonts/factory/ossimFontFactoryBase.h" + + +class OSSIMDLLEXPORT ossimFontFactoryRegistry +{ +public: + static ossimFontFactoryRegistry* instance(); + + bool registerFactory(ossimFontFactoryBase* factory); + void unregisterFactory(ossimFontFactoryBase* factory); + bool findFactory(ossimFontFactoryBase* factory)const; + + ossimFont* createFont(const ossimFontInformation& information)const; + ossimFont* createFont(const ossimFilename& file)const; + + /*! + * Returns all font information. + */ + void getFontInformation(std::vector<ossimFontInformation>& informationList)const; + + /*! + * Matches the entire string. Does a case insensitive match. + */ + void getFontInformationFamilyName(std::vector<ossimFontInformation>& informationList, + const ossimString& familyName)const; + + /*! + * Matches the sub-string. Does a case insensitive match. + */ + void getFontInformationContainingFamilyName(std::vector<ossimFontInformation>& informationList, + const ossimString& familyName)const; + + /*! + * This font should not be deleted. It returns the default font. If you + * want to make a copy then just call the dup method on + * font. + */ + ossimFont* getDefaultFont()const; + +protected: + mutable ossimFont* theDefaultFont; + + static ossimFontFactoryRegistry* theInstance; + + std::vector<ossimFontFactoryBase*> theFactoryList; + + ossimFontFactoryRegistry(); + +private: + ossimFontFactoryRegistry(const ossimFontFactoryRegistry& rhs); + void operator =(const ossimFontFactoryRegistry& rhs); +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/fonts/factory/ossimFreeTypeFontFactory.cpp b/Utilities/OSSIM/ossim_core/fonts/factory/ossimFreeTypeFontFactory.cpp new file mode 100644 index 0000000000..3ae4eabcea --- /dev/null +++ b/Utilities/OSSIM/ossim_core/fonts/factory/ossimFreeTypeFontFactory.cpp @@ -0,0 +1,237 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: Garrett Potts +// +//******************************************************************** +// $Id: ossimFreeTypeFontFactory.cpp,v 1.13 2005/12/10 20:08:07 dburken Exp $ + +#include <ossimConfig.h> /* To pick up OSSIM_HAS_FREETYPE. */ + +#if OSSIM_HAS_FREETYPE +# include <fonts/factory/ossimFreeTypeFontFactory.h> +# include <fonts/ossimFreeTypeFont.h> +# include <base/common/ossimPreferences.h> +# include <base/data_types/ossimDirectory.h> +# include <base/context/ossimNotifyContext.h> + +ossimFreeTypeFontFactory* ossimFreeTypeFontFactory::theInstance=0; + +ossimFreeTypeFontFactory::ossimFreeTypeFontFactory() +{ + theInstance = this; +} + +ossimFreeTypeFontFactory::~ossimFreeTypeFontFactory() +{ + theInstance = (ossimFreeTypeFontFactory*)NULL; +} + +ossimFreeTypeFontFactory* ossimFreeTypeFontFactory::instance() +{ + if(!theInstance) + { + theInstance = new ossimFreeTypeFontFactory; + theInstance->initializeDefaults(); + } + + return theInstance; +} + + +ossimFont* ossimFreeTypeFontFactory::createFont(const ossimFontInformation& information)const + +{ + ossimFont* result = (ossimFont*)NULL; + + ossimString rightFamilyName = information.theFamilyName; + ossimString rightStyleName = information.theStyleName; + rightFamilyName = rightFamilyName.upcase().trim(); + rightStyleName = rightStyleName.upcase().trim(); + int i = 0; + + for(i = 0; ( (i < (int)theFontInformationList.size())&&(!result));++i) + { + ossimString leftFamilyName = theFontInformationList[i].theFontInformation.theFamilyName; + ossimString leftStyleName = theFontInformationList[i].theFontInformation.theStyleName; + + leftFamilyName = leftFamilyName.upcase().trim(); + leftStyleName = leftStyleName.upcase().trim(); + + if( (leftFamilyName == rightFamilyName)&& + (leftStyleName == rightStyleName)) + { + if(theFontInformationList[i].theFontInformation.theFixedFlag) + { + if(theFontInformationList[i].theFontInformation.thePointSize == + information.thePointSize) + { + result = new ossimFreeTypeFont(theFontInformationList[i].theFilename); + if(result) + { + if(result->getErrorStatus()) + { + delete result; + result = NULL; + ossimNotify(ossimNotifyLevel_WARN) <<"WARNING ossimFreeTypeFontFactory::createFont: unable to open font file " + << theFontInformationList[i].theFilename << std::endl; + } + } + } + } + else + { + result = new ossimFreeTypeFont(theFontInformationList[i].theFilename); + if(result) + { + if(result->getErrorStatus()) + { + delete result; + result = NULL; + ossimNotify(ossimNotifyLevel_WARN) << "WARNING ossimFreeTypeFontFactory::createFont: unable to open font file " + << theFontInformationList[i].theFilename << std::endl; + } + else + { + if(information.thePointSize.x&& + information.thePointSize.y) + { + result->setPixelSize(information.thePointSize.x, + information.thePointSize.y); + } + } + } + } + } + } + + if(result) + { + result->setScale(information.theScale.x, + information.theScale.y); + result->setScale(information.theScale.x, + information.theScale.y); + result->setHorizontalVerticalShear(information.theShear.x, + information.theShear.y); + result->setRotation(information.theRotation); + } + + return result; +} + +ossimFont* ossimFreeTypeFontFactory::createFont(const ossimFilename& file)const +{ + ossimFont* result = new ossimFreeTypeFont(file); + + if(result->getErrorStatus()) + { + delete result; + result = (ossimFont*)NULL; + } + + return result; +} + +void ossimFreeTypeFontFactory::getFontInformation(std::vector<ossimFontInformation>& informationList)const +{ + int i = 0; + for(i = 0; i < (int)theFontInformationList.size();++i) + { + informationList.push_back(theFontInformationList[i].theFontInformation); + } +} + +bool ossimFreeTypeFontFactory::addFile(const ossimFilename& file) +{ + ossimFreeTypeFont* font = new ossimFreeTypeFont(file); + std::vector<ossimFontInformation> fontInfoList; + + bool result = false; + int i = 0; + if(font->getFontFace()) + { + if(!font->getErrorStatus()) + { + font->getFontInformation(fontInfoList); + + for(i = 0; i < (int)fontInfoList.size();++i) + { + theFontInformationList.push_back(ossimFreeTypeFontInformation(file, + fontInfoList[i])); + } + result = true; + } + } + + return result; +} + +void ossimFreeTypeFontFactory::initializeDefaults() +{ + const ossimKeywordlist& kwl = ossimPreferences::instance()->preferencesKWL(); + ossimString regExpressionDir = ossimString("^(") + "font.dir[0-9]+)"; + ossimString regExpressionFile = ossimString("^(") + "font.file[0-9]+)"; + vector<ossimString> dirs = + kwl.getSubstringKeyList( regExpressionDir ); + vector<ossimString> files = + kwl.getSubstringKeyList( regExpressionFile ); + + int idx = 0; + for(idx = 0; idx < (int)dirs.size();++idx) + { + const char* directoryLocation = kwl.find(dirs[idx]); + if(directoryLocation) + { + ossimDirectory d; + + if(d.open(ossimFilename(directoryLocation))) + { + ossimFilename file; + + if(d.getFirst(file, ossimDirectory::OSSIM_DIR_FILES)) + { + do + { + addFile(file); + }while(d.getNext(file)); + } + } + } + } + for(idx = 0; idx < (int)files.size();++idx) + { + const char* fileName = kwl.find(files[idx]); + + if(fileName) + { + addFile(ossimFilename(fileName)); + } + } +#if 0 + if(!numberOfDirs&&!numberOfFiles) + { +#ifdef __UNIX__ + ossimFilename file("/usr/X11R6/lib/X11/fonts/Type1"); + + if(file.exists()) + { + ossimDirectory d; + if(d.open(file)) + { + if(d.getFirst(file, ossimDirectory::OSSIM_DIR_FILES)) + { + do + { + addFile(file); + }while(d.getNext(file)); + } + } + } +#endif + } +#endif +} + +#endif /* #if OSSIM_HAS_FREETYPE */ diff --git a/Utilities/OSSIM/ossim_core/fonts/factory/ossimFreeTypeFontFactory.h b/Utilities/OSSIM/ossim_core/fonts/factory/ossimFreeTypeFontFactory.h new file mode 100644 index 0000000000..ad1401603a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/fonts/factory/ossimFreeTypeFontFactory.h @@ -0,0 +1,64 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//******************************************************************** +// $Id: ossimFreeTypeFontFactory.h,v 1.1 2002/04/30 18:50:55 gpotts Exp $ +#ifndef ossimFreeTypeFontFactory_HEADER +#define ossimFreeTypeFontFactory_HEADER +#include "fonts/factory/ossimFontFactoryBase.h" + +class ossimFreeTypeFontInformation +{ +public: + ossimFreeTypeFontInformation(const ossimFilename& file, + const ossimFontInformation& info) + :theFilename(file), + theFontInformation(info) + {} + + ossimFilename theFilename; + ossimFontInformation theFontInformation; +}; + +class ossimFreeTypeFontFactory : public ossimFontFactoryBase +{ +public: + virtual ~ossimFreeTypeFontFactory(); + static ossimFreeTypeFontFactory* instance(); + virtual ossimFont* createFont(const ossimFontInformation& information)const; + virtual ossimFont* createFont(const ossimFilename& file)const; + virtual void getFontInformation(std::vector<ossimFontInformation>& informationList)const; + + bool addFile(const ossimFilename& file); + +protected: + ossimFreeTypeFontFactory(); + + static ossimFreeTypeFontFactory* theInstance; + std::vector<ossimFreeTypeFontInformation> theFontInformationList; + + void initializeDefaults(); +private: + ossimFreeTypeFontFactory(const ossimFreeTypeFontFactory& rhs){} + void operator =(const ossimFreeTypeFontFactory& rhs){} + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/fonts/ossimFont.cpp b/Utilities/OSSIM/ossim_core/fonts/ossimFont.cpp new file mode 100644 index 0000000000..c0a40bed0d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/fonts/ossimFont.cpp @@ -0,0 +1,83 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// Description: +// +//******************************************************************** +// $Id: ossimFont.cpp,v 1.9 2002/08/23 14:05:22 gpotts Exp $ +#include "ossimFont.h" +#include "math.h" +#include <iostream> +using namespace std; + +#include "matrix/newmatio.h" + +RTTI_DEF2(ossimFont, "ossimFont", ossimObject, ossimErrorStatusInterface); + +void ossimFont::setRotation(double rotationInDegrees) +{ + theRotation = rotationInDegrees; + + computeMatrix(); +} + +void ossimFont::setScale(double horizontal, + double vertical) +{ + theHorizontalScale = horizontal; + theVerticalScale = vertical; + + computeMatrix(); +} + +void ossimFont::computeMatrix() +{ + NEWMAT::Matrix r(2,2); + NEWMAT::Matrix s(2,2); + + double radRotation = theRotation*M_PI/180.0; + + r << cos(radRotation) << -sin(radRotation) + << sin(radRotation) << cos(radRotation); + + s << theHorizontalScale << theVerticalShear + << theHorizontalShear << theVerticalScale; + + theAffineTransform = s*r; + +} + +void ossimFont::getBoundingClipBox(ossimIrect& clippedBox) +{ + getBoundingBox(clippedBox); + + if(!theClippingBox.hasNans()&& + (theClippingBox.width()>1)&&(theClippingBox.height()>1) ) + { + clippedBox = clippedBox.clipToRect(theClippingBox); + } +} + +ossimIrect ossimFont::getBoundingClipBox() +{ + ossimIrect clipBox; + getBoundingClipBox(clipBox); + + return clipBox; +} diff --git a/Utilities/OSSIM/ossim_core/fonts/ossimFont.h b/Utilities/OSSIM/ossim_core/fonts/ossimFont.h new file mode 100644 index 0000000000..f86ab810e6 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/fonts/ossimFont.h @@ -0,0 +1,336 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// Description: +// +//******************************************************************** +// $Id: ossimFont.h,v 1.17 2005/09/09 19:23:58 gpotts Exp $ +#ifndef ossimFont_HEADER +#define ossimFont_HEADER +#include "base/data_types/ossimIpt.h" +#include "base/data_types/ossimIrect.h" +#include "base/data_types/ossimString.h" +#include "imaging/ossimRgbImage.h" +#include "base/common/ossimConstants.h" +#include "matrix/newmat.h" +#include "base/common/ossimObject.h" +#include "base/common/ossimErrorStatusInterface.h" +#include "base/common/ossimFontInformation.h" + +#define OSSIM_FONT_DEFAULT_SIZE_X 12 +#define OSSIM_FONT_DEFAULT_SIZE_Y 12 + +class ossimFont : public ossimObject, public ossimErrorStatusInterface +{ +public: + ossimFont() + :theStringToRasterize(""), + theFamilyName(""), + theStyleName(""), + theRotation(0), + theHorizontalShear(0.0), + theVerticalShear(0.0), + theHorizontalScale(1.0), + theVerticalScale(1.0), + theHorizontalPixelSize(8), + theVerticalPixelSize(8), + theHorizontalDeviceUnits(72), + theVerticalDeviceUnits(72), + theAffineTransform(2,2) + { + theAffineTransform << 1.0 << 0.0 + << 0.0 << 1.0; + } + + ossimFont(const ossimString& familyName, + const ossimString& styleName, + int horizontalPixelSize, + int verticalPixelSize, + int horizontalDeviceUnits=72,// 72 dpi is default, + int verticalDeviceUnits=72)// 72 dpi is default + :theStringToRasterize(""), + theFamilyName(familyName), + theStyleName(styleName), + theRotation(0), + theHorizontalShear(0.0), + theVerticalShear(0.0), + theHorizontalScale(1.0), + theVerticalScale(1.0), + theHorizontalPixelSize(horizontalPixelSize), + theVerticalPixelSize(verticalPixelSize), + theHorizontalDeviceUnits(horizontalDeviceUnits), + theVerticalDeviceUnits(horizontalDeviceUnits), + theAffineTransform(2,2) + { + theAffineTransform << 1.0 << 0.0 + << 0.0 << 1.0; + } + + ossimFont(const ossimFont& rhs) + { + theStringToRasterize = rhs.theStringToRasterize; + theFamilyName = rhs.theFamilyName; + theStyleName = rhs.theStyleName; + theRotation = rhs.theRotation; + theHorizontalShear = rhs.theHorizontalShear; + theVerticalShear = rhs.theVerticalShear; + theHorizontalScale = rhs.theHorizontalScale; + theVerticalScale = rhs.theVerticalScale; + theHorizontalPixelSize = rhs.theHorizontalPixelSize; + theHorizontalDeviceUnits = rhs.theHorizontalDeviceUnits; + theVerticalDeviceUnits = rhs.theVerticalDeviceUnits; + theAffineTransform = rhs.theAffineTransform; + theClippingBox = rhs.theClippingBox; + theLocalOrigin = rhs.theLocalOrigin; + theAffineTransform = rhs.theAffineTransform; + } + virtual ~ossimFont() + {} + virtual ossimObject* dup()const=0; + + /*! + * Returns true if this font is a fixed size font + */ + virtual bool isFixed()const=0; + + /*! + * You can get a list of fixed sizes supported by + * this font. + */ + virtual void getFixedSizes(vector<ossimIpt>& sizes)const=0; + + /*! + * Will return the previously rasterized buffer. + */ + virtual const ossim_uint8* getBuf()const=0; + + /*! + * Will return an internal buffer for rasterizing and will + * also set the width, and height arguments of the returned buffer. + */ + virtual const ossim_uint8* rasterize()=0; + + virtual const ossim_uint8* rasterize(const ossimString& s) + { + setString(s); + return rasterize(); + } + + virtual void setString(const ossimString& s) + { + theStringToRasterize = s; + } + + /*! + * Will return the bounding box of the last string that was set + * to be rasterized in pixel space + */ + virtual void getBoundingBox(ossimIrect& box)=0; + + /*! + * Specifies if its helvetica, times new roman ... etc. + */ + virtual ossimString getFamilyName()const + { + return theFamilyName; + } + + /*! + * Specifies if its bold or italic .. etc + */ + virtual ossimString getStyleName()const + { + return theStyleName; + } + + /*! + * Allow us to rotate a font. + */ + virtual void setRotation(double rotationInDegrees); + + virtual double getRotation()const + { + return theRotation; + } + + virtual void getRotation(double& rotation)const + { + rotation = theRotation; + } + + virtual void setHorizontalVerticalShear(double horizontalShear, + double verticalShear) + { + theVerticalShear = verticalShear; + theHorizontalShear = horizontalShear; + computeMatrix(); + } + virtual void setVerticalShear(double verticalShear) + { + setHorizontalVerticalShear(theHorizontalShear, + verticalShear); + } + + virtual void setHorizontalShear(double horizontalShear) + { + setHorizontalVerticalShear(horizontalShear, + theVerticalShear); + } + + virtual double getVerticalShear()const + { + return theVerticalShear; + } + + virtual double getHorizontalShear()const + { + return theHorizontalShear; + } + + /*! + * Sets the scale of the font. I'll have code in place to perform + * reflections. This can be specified with a - scale along the direction + * you wish to reflect. + */ + virtual void setScale(double horizontal, + double vertical); + + virtual void getScale(double& horizontal, + double& vertical) + { + horizontal = theHorizontalScale; + vertical = theVerticalScale; + } + + virtual void setPixelSize(int horizontalPixelSize, + int verticalPixelSize) + { + theHorizontalPixelSize = horizontalPixelSize; + theVerticalPixelSize = verticalPixelSize; + } + + virtual void setPixelSize(int pixelSize) + { + setPixelSize(pixelSize, pixelSize); + } + + virtual void getPixelSize(int& horizontal, + int& vertical) + { + horizontal = theHorizontalPixelSize; + vertical = theVerticalPixelSize; + } + + virtual long getHorizontalPixelSize()const + { + return theHorizontalPixelSize; + } + virtual ossimIpt getPixelSize()const + { + return ossimIpt(theHorizontalPixelSize, + theVerticalPixelSize); + } + virtual long getVerticalPixelSize()const + { + return theVerticalPixelSize; + } + + virtual void setDeviceDpi(int horizontalDeviceUnits, + int verticalDeviceUnits) + { + theHorizontalDeviceUnits = horizontalDeviceUnits; + theVerticalDeviceUnits = verticalDeviceUnits; + } + + /*! + * Will clip the clipping box with the bounding box of the string and this + * is the viewable information. + * + * If the clipping box is set then this should be used to get the dimensions + * of the buffer. + */ + virtual void getBufferRect(ossimIrect& bufRect) + { + getBoundingClipBox(bufRect); + } + + virtual ossimIrect getBufferRect() + { + return getBoundingClipBox(); + } + + virtual void getBoundingClipBox(ossimIrect& clippedBox); + + virtual ossimIrect getBoundingClipBox(); + + virtual void setClippingBox(const ossimIrect& clipBox=ossimIrect(0,0,0,0)) + { + theClippingBox = clipBox; + } + + virtual ossimIrect getClippingBox()const + { + return theClippingBox; + } + + bool isIdentityTransform()const + { + return ( (theAffineTransform[0][0] == 1.0) && (theAffineTransform[1][0] == 0.0)&& + (theAffineTransform[0][1] == 0.0) && (theAffineTransform[1][1] == 1.0)); + } + virtual void getFontInformation(vector<ossimFontInformation>& fontInformationList)const + { + fontInformationList.push_back(ossimFontInformation(getFamilyName(), + getStyleName(), + getPixelSize(), + isFixed())); + } + +protected: + ossimString theStringToRasterize; + ossimString theFamilyName; + ossimString theStyleName; + double theRotation; + double theHorizontalShear; + double theVerticalShear; + double theHorizontalScale; + double theVerticalScale; + int theHorizontalPixelSize; + int theVerticalPixelSize; + int theHorizontalDeviceUnits; + int theVerticalDeviceUnits; + ossimIrect theClippingBox; + /*! + * During the compution of the global bounding rect we will + * Make sure that we save off the upper left since its not really 0,0. + * We will make sure that the bounding rect is shifted to 0,0 but the + * shift will be saved. That way we can render the shape correctly + * later. + */ + mutable ossimIpt theLocalOrigin; + + NEWMAT::Matrix theAffineTransform; + + + void computeMatrix(); + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/fonts/ossimFreeTypeFont.cpp b/Utilities/OSSIM/ossim_core/fonts/ossimFreeTypeFont.cpp new file mode 100644 index 0000000000..2b6f920321 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/fonts/ossimFreeTypeFont.cpp @@ -0,0 +1,646 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: Garrett Potts +// +//******************************************************************** +// $Id: ossimFreeTypeFont.cpp,v 1.27 2005/12/10 21:21:01 dburken Exp $ + +// ossimFreeTypeFont.h should be load prior to checking for OSSIM_HAS_FREETYPE. +#include <fonts/ossimFreeTypeFont.h> + +#if OSSIM_HAS_FREETYPE +# include <matrix/newmatio.h> +# include <base/data_types/ossimFilename.h> +# include <base/context/ossimErrorContext.h> +# include <base/common/ossimTrace.h> +# include <string.h> // for memset +# ifndef NULL +# include <stddef.h> +# endif + +static ossimTrace traceDebug ("ossimFreeTypeFont:debug"); + +RTTI_DEF1(ossimFreeTypeFont, "ossimFreeTypeFont", ossimFont); + +ossimFreeTypeFont::ossimFreeTypeFont(const ossimFilename& fontFile) + :ossimFont(), + theFontFace(NULL), + theLibrary(NULL), + theFontFile(fontFile), + theOutputBuffer(NULL), + theBufferSize(0), + theKerningEnabledFlag(true), + theNeedToLayoutGlyphsFlag(true), + theBoundingRectIsValid(false) +{ + int error; + if(fontFile.exists()) + { + error = FT_Init_FreeType(&theLibrary); + if(error) + { + ossimNotify(ossimNotifyLevel_WARN) << "WARNING ossimFreeTypeFont::ossimFreeTypeFont: Can't initialize freetype" << std::endl; + setErrorStatus(); + } + if(getErrorStatus() == ossimErrorCodes::OSSIM_OK) + { + error = FT_New_Face( theLibrary, + fontFile.c_str(), + 0, + &theFontFace ); + if((error == FT_Err_Unknown_File_Format)) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "WARNING ossimFreeTypeFont::ossimFreeTypeFont: Unable to create a font face for file = " + << fontFile + << std::endl; + } + FT_Done_Library(theLibrary); + theLibrary = NULL; + setErrorStatus(); + } + else + { + setBaseClassInformation(); + } + } + } + else + { + setErrorStatus(); + } +} + +ossimFreeTypeFont::ossimFreeTypeFont(const ossimFreeTypeFont& rhs) + :ossimFont(rhs), + theMatrix(rhs.theMatrix), + theFontFile(rhs.theFontFile), + theOutputBuffer(NULL), + theBufferSize(0), + theKerningEnabledFlag(rhs.theKerningEnabledFlag), + theNeedToLayoutGlyphsFlag(rhs.theNeedToLayoutGlyphsFlag), + theStringCenter(rhs.theStringCenter), + theShift(rhs.theShift), + thePrecomputedBoundingRect(rhs.thePrecomputedBoundingRect), + theBoundingRectIsValid(rhs.theBoundingRectIsValid) +{ + if(rhs.getErrorStatus()) + { + setErrorStatus(); + } + else + { + int error; + error = FT_Init_FreeType(&theLibrary); + + if(error) + { + ossimNotify(ossimNotifyLevel_WARN) << "WARNING ossimFreeTypeFoont::ossimFreeTypeFont: Can't initialize freetype in copy constructor" <<std::endl; + setErrorStatus(); + } + if(getErrorStatus() == ossimErrorCodes::OSSIM_OK) + { + error = FT_New_Face( theLibrary, + rhs.theFontFile.c_str(), + 0, + &theFontFace ); + if((error == FT_Err_Unknown_File_Format)) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "WARNING ossimFreeTypeFoont::ossimFreeTypeFont: Unable to create a font face for file = " + << rhs.theFontFile + << std::endl; + } + + FT_Done_Library(theLibrary); + theLibrary = NULL; + setErrorStatus(); + } + else + { + if(rhs.theBufferSize) + { + theBufferSize = rhs.theBufferSize; + theOutputBuffer = new ossim_uint8[theBufferSize]; + memcpy(theOutputBuffer, rhs.theOutputBuffer, theBufferSize); + setBaseClassInformation(); + theNeedToLayoutGlyphsFlag = true; + layoutGlyphs(theStringToRasterize); + } + } + } + } +} + +ossimFreeTypeFont::~ossimFreeTypeFont() +{ + if(theOutputBuffer) + { + delete [] theOutputBuffer; + theOutputBuffer = NULL; + } + if(theFontFace) + { + FT_Done_Face(theFontFace); + theFontFace = NULL; + } + if(theLibrary) + { + FT_Done_FreeType(theLibrary); + theLibrary = NULL; + } +} + +void ossimFreeTypeFont::layoutGlyphs(const ossimString& s ) +{ + if(!theNeedToLayoutGlyphsFlag||!theFontFace) + { + return; + } + + + int n; + FT_Vector origin; + FT_Pos origin_x = 0; + FT_UInt load_flags; + FT_UInt num_grays; + FT_UInt prev_index = 0; + FT_UInt num_glyphs = s.size(); + int error = 0; + + deleteGlyphs(theStringLayout); + theStringLayout.resize(s.size()); + + theMatrix.xx = (FT_Fixed)(theAffineTransform[0][0]*0x10000); + theMatrix.xy = (FT_Fixed)(theAffineTransform[1][0]*0x10000); + theMatrix.yx = (FT_Fixed)(theAffineTransform[0][1]*0x10000); + theMatrix.yy = (FT_Fixed)(theAffineTransform[1][1]*0x10000); + + int hasKerning = FT_HAS_KERNING(theFontFace); + + load_flags = FT_LOAD_DEFAULT; + + num_grays = 256; + const char* c = s.c_str(); + for ( n = 0; n < (int)num_glyphs; n++) + { + long charOffset = c[n]; + + FT_ULong charIndex = 0; + + if(charOffset < 0) + { + charIndex = (charOffset + 256); + } + else + { + charIndex = charOffset; + } + theStringLayout[n].glyph_index = FT_Get_Char_Index( theFontFace, + charIndex ); + theStringLayout[n].image = NULL; + /* compute glyph origin */ + if (hasKerning&&theKerningEnabledFlag&&prev_index) + { + FT_Vector kern; + + + FT_Get_Kerning( theFontFace, + prev_index, + theStringLayout[n].glyph_index, + ft_kerning_default, + &kern ); + + origin_x += (kern.x); + } + + origin.x = origin_x; + origin.y = 0; + + + /* load the glyph image (in its native format); */ + /* for now, we take a monochrome glyph bitmap */ + error = FT_Load_Glyph( theFontFace, + theStringLayout[n].glyph_index, + FT_LOAD_DEFAULT); + if ( error ) + { + continue; + } + + error = FT_Get_Glyph ( theFontFace->glyph, &theStringLayout[n].image ); + + if ( error ) + { + continue; + } + + theStringLayout[n].pos = origin; + + origin_x += (theFontFace->glyph->advance.x); + prev_index = theStringLayout[n].glyph_index; + } + + theStringCenter.x = origin_x / 2; + theStringCenter.y = 0; + + FT_Vector_Transform( &theStringCenter, &theMatrix ); + theNeedToLayoutGlyphsFlag = false; +} + +const ossim_uint8* ossimFreeTypeFont::rasterize() +{ + allocateBuffer(); + setupForRasterization(); + layoutGlyphs(theStringToRasterize); + + int num_glyphs = theStringLayout.size(); + int n; + FT_Vector delta; + int error; + + /* first of all, we must compute the general delta for the glyph set */ + delta.x = -theStringCenter.x; + delta.y = 0; + + memset(theOutputBuffer, 0, theBufferSize); + for ( n = 0; n < num_glyphs; n++) + { + FT_Glyph image; + FT_Vector vec; + + + if ( !theStringLayout[n].image ) + { + continue; + } + + /* copy image */ + error = FT_Glyph_Copy( theStringLayout[n].image, &image ); + if ( error ) + continue; + + /* transform it */ + vec = theStringLayout[n].pos; + FT_Vector_Transform( &vec, &theMatrix ); + vec.x += (delta.x); + vec.y += (delta.y); + error = FT_Glyph_Transform( image, &theMatrix, &vec ); + if ( !error ) + { + FT_BBox bbox; + /* check bounding box; if it is not within the display surface, */ + /* we don't need to render it */ + + FT_Glyph_Get_CBox( image, ft_glyph_bbox_pixels, &bbox ); + + // since freetype coordinates are right handed we will + // adjust the rects so they are right handed before passing + // them to our rendering system. + // + ossimIrect box(bbox.xMin, + bbox.yMax, + bbox.xMax, + bbox.yMin, + OSSIM_RIGHT_HANDED); + ossimIrect bufRect; + ossimIrect boundingBox;; + getBufferRect(bufRect); + getBoundingBox(boundingBox); + + bufRect = ossimIrect(bufRect.ul().x, + boundingBox.lr().y - bufRect.ul().y, + bufRect.lr().x, + boundingBox.lr().y - bufRect.lr().y, + OSSIM_RIGHT_HANDED); + box += ossimIpt(-theShift.x, + -theShift.y); + if(bufRect.intersects(box)) + { + // now let's convert it to a bitmap + error = FT_Glyph_To_Bitmap( &image, + ft_render_mode_normal, + 0, + 1 ); + if ( !error ) + { + // cast it + FT_BitmapGlyph bitmap = (FT_BitmapGlyph)image; + + ossimIpt ul(bitmap->left -theShift.x, + bitmap->top -theShift.y); + + // the bounding char box does not coorespond to the + // buffer rect of rfreetype's internal sorage. + // We will need to adjust the box and then render it + // + box = ossimIrect(ul.x, + ul.y, + ul.x + bitmap->bitmap.width-1, + ul.y - (bitmap->bitmap.rows-1), + OSSIM_RIGHT_HANDED); + + // draw the sub rect within our buffer. + drawBitmap(&bitmap->bitmap, + bufRect, + box); + } + } + } + FT_Done_Glyph( image ); + } + + return theOutputBuffer; +} + +void ossimFreeTypeFont::getBoundingBox(ossimIrect& box) +{ + + if(theBoundingRectIsValid) + { + box = thePrecomputedBoundingRect; + return; + } + setupForRasterization(); + layoutGlyphs(theStringToRasterize); + + int num_glyphs = theStringLayout.size(); + int n; + FT_Vector delta; + int error; + bool firstBoxSet = false; + /* first of all, we must compute the general delta for the glyph set */ + delta.x = -theStringCenter.x; + delta.y = 0; + + for ( n = 0; n < num_glyphs; n++) + { + FT_Glyph image; + FT_Vector vec; + + + if ( !theStringLayout[n].image ) + { + continue; + } + + /* copy image */ + error = FT_Glyph_Copy( theStringLayout[n].image, &image ); + if ( error ) + continue; + + /* transform it */ + vec = theStringLayout[n].pos; + FT_Vector_Transform( &vec, &theMatrix ); + vec.x += (delta.x); + vec.y += (delta.y); + error = FT_Glyph_Transform( image, &theMatrix, &vec ); + if ( !error ) + { + FT_BBox bbox; + /* check bounding box; if it is not within the display surface, */ + /* we don't need to render it */ + + FT_Glyph_Get_CBox( image, ft_glyph_bbox_pixels, &bbox ); + ossimIrect charBox(bbox.xMin, + bbox.yMin, + bbox.xMax, + bbox.yMax); + + if(firstBoxSet) + { + box = box.combine(charBox); + } + else + { + firstBoxSet = true; + box = charBox; + } + } + FT_Done_Glyph( image ); + } + + theShift = box.ul(); + + box += ossimIpt(-theShift.x, + -theShift.y); + + thePrecomputedBoundingRect = box; +} + +void ossimFreeTypeFont::computeGlyphBox(FT_Glyph slot, + ossimIrect& box)const +{ + long yBearing = theFontFace->glyph->metrics.horiBearingY/64; + long h = theFontFace->glyph->metrics.height/64; + long w = theFontFace->glyph->metrics.width/64; + + if(h&&w) + { + box = ossimIrect(0, + yBearing-(h-1), + (w-1), + yBearing); + } + else + { + box = ossimIrect(0,0,0,0); + } +} + +void ossimFreeTypeFont::drawBitmap(FT_Bitmap* bitmap, + const ossimIrect& bufRect, + const ossimIrect& glyphBox) +{ + if(bufRect.intersects(glyphBox)) + { + unsigned char* buf = bitmap->buffer; + if(!theOutputBuffer||!buf) return; + + ossimIrect intersectionRect = bufRect.clipToRect(glyphBox); + + + long difInX = intersectionRect.ul().x - glyphBox.ul().x; + long difInY = glyphBox.ul().y - intersectionRect.ul().y; + + long difOutX = intersectionRect.ul().x - bufRect.ul().x; + long difOutY = bufRect.ul().y - intersectionRect.ul().y; + + + + long startInOffset = bitmap->width*difInY + difInX; + long startOutOffset = bufRect.width()*difOutY + difOutX; + + long outBufW = bufRect.width(); + long inBufW = bitmap->width; + + // let's just make sure that the increment will not exceed the input + // buffers width and height. + // + long height = std::min((long)intersectionRect.height(), (long)glyphBox.height()); + long width = std::min((long)intersectionRect.width(), (long)glyphBox.width()); + + for(long rows = 0 ; rows < height; ++rows) + { + for(long cols = 0; cols < width; ++cols) + { + if(buf[startInOffset+cols]) + { + theOutputBuffer[startOutOffset + cols] = buf[startInOffset+cols]; + } + } + startInOffset+=inBufW; + startOutOffset+=outBufW; + } + } +} + +void ossimFreeTypeFont::setupForRasterization() +{ + int error=0; + if(!theFontFace) return; + + if(!theFontFace->charmap) + { + error = FT_Select_Charmap(theFontFace, /* target face object */ + ft_encoding_big5 ); /* encoding.. */ + } + + error = FT_Set_Char_Size(theFontFace, + theHorizontalPixelSize*64, + theVerticalPixelSize*64, + theHorizontalDeviceUnits, + theVerticalDeviceUnits); + if(error) + { + ossimNotify(ossimNotifyLevel_WARN) << "WARNING ossimFreeTypeFont::setupForRasterization: Cant set the pixel size" <<std::endl; + } +} + +void ossimFreeTypeFont::setBaseClassInformation() +{ + if(theFontFace) + { + theFamilyName = theFontFace->family_name; + + if(isFixed()) + { + vector<ossimIpt> initialPointList; + getFixedSizes(initialPointList); + + theHorizontalPixelSize = initialPointList[0].x; + theVerticalPixelSize = initialPointList[0].y; + } + else + { + theHorizontalPixelSize = 8; + theVerticalPixelSize = 8; + } + if((theFontFace->style_flags & FT_STYLE_FLAG_BOLD) && + (theFontFace->style_flags&FT_STYLE_FLAG_ITALIC)) + { + theStyleName = "bold italic"; + } + else if(theFontFace->style_flags & FT_STYLE_FLAG_BOLD) + { + theStyleName = "bold"; + } + else if(theFontFace->style_flags & FT_STYLE_FLAG_ITALIC) + { + theStyleName = "italic"; + } + else + { + theStyleName = "normal"; + } + } +} + + +void ossimFreeTypeFont::setCurrentFace(long index) +{ + int error; + if(theFontFace) + { + if((index >0) && (index < theFontFace->num_faces)) + { + FT_Done_Face(theFontFace); + theFontFace = NULL; + + error = FT_New_Face( theLibrary, + theFontFile.c_str(), + index, + &theFontFace ); + if((error == FT_Err_Unknown_File_Format)||error) + { + setErrorStatus(); + } + else + { + setBaseClassInformation(); + } + theBoundingRectIsValid = false; + } + } +} + +void ossimFreeTypeFont::getFixedSizes(vector<ossimIpt>& sizeArray)const +{ + if(theFontFace) + { + sizeArray.clear(); + int i = 0; + + for(i = 0; i < theFontFace->num_fixed_sizes; ++i) + { + sizeArray.push_back(ossimIpt(theFontFace->available_sizes[i].width, + theFontFace->available_sizes[i].height)); + } + } +} + +void ossimFreeTypeFont::allocateBuffer() +{ + ossimIrect box; + setupForRasterization(); + getBoundingClipBox(box); + long bufferSize = box.width()*box.height(); + if(bufferSize != theBufferSize) + { + theBufferSize = bufferSize; + + if(theOutputBuffer) + { + delete theOutputBuffer; + theOutputBuffer = NULL; + } + if(!theOutputBuffer&&theBufferSize) + { + theOutputBuffer = new ossim_uint8[theBufferSize]; + } + } +} + +void ossimFreeTypeFont::deleteGlyphs(vector<TGlyph>& glyphs) +{ + int i = 0; + + for(i = 0; i < (int)glyphs.size(); ++i) + { + if(glyphs[i].image) + { + FT_Done_Glyph(glyphs[i].image); + } + } + + glyphs.clear(); +} + +#endif /* #if OSSIM_HAS_FREETYPE */ diff --git a/Utilities/OSSIM/ossim_core/fonts/ossimFreeTypeFont.h b/Utilities/OSSIM/ossim_core/fonts/ossimFreeTypeFont.h new file mode 100644 index 0000000000..1a78ddf9e7 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/fonts/ossimFreeTypeFont.h @@ -0,0 +1,199 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: Garrett Potts +// +//******************************************************************** +// $Id: ossimFreeTypeFont.h,v 1.18 2005/12/10 21:21:01 dburken Exp $ +#ifndef ossimFreeTypeFont_HEADER +#define ossimFreeTypeFont_HEADER + +#include <ossimConfig.h> /* To pick up OSSIM_HAS_FREETYPE. */ + +#if OSSIM_HAS_FREETYPE +# include "ossimFont.h" +# include <ft2build.h> +# include FT_FREETYPE_H +//#include <freetype/freetype.h> +# include FT_MODULE_H // for FT_Done_Library +# include FT_GLYPH_H + +# include "base/data_types/ossimFilename.h" + + +typedef struct TGlyph_ +{ + FT_UInt glyph_index; /* glyph index in face */ + FT_Vector pos; /* position of glyph origin */ + FT_Glyph image; /* glyph image */ + +} TGlyph, *PGlyph; + +class ossimFreeTypeFont: public ossimFont +{ +public: + ossimFreeTypeFont(const ossimFilename& fontFile); + ossimFreeTypeFont(const ossimFreeTypeFont& rhs); + + virtual ossimObject* dup()const + { + return new ossimFreeTypeFont(*this); + } + virtual ~ossimFreeTypeFont(); + + virtual const ossim_uint8* getBuf()const + { + return theOutputBuffer; + } + + void layoutGlyphs(vector<TGlyph>& glyphs, + const ossimString& s ); + + virtual const ossim_uint8* rasterize(); + void getBoundingBox(ossimIrect& box); + + long getNumberOfFaces()const + { + if(theFontFace) + { + return theFontFace->num_faces; + } + return 0; + } + void setCurrentFace(long index); + + /*! + * Fonts found in files .FNT and .PCF are fixed + */ + bool isFixed()const + { + if(theFontFace) + { + return (theFontFace->num_fixed_sizes > 0); + } + return false; + } + + virtual void getFixedSizes(vector<ossimIpt>& sizeArray)const; + + /*! + * Will enable kerning support. This is enabled + * by default. This is for true type fonts and + * if its available for the current font this + * will tell us to make sure we use it. This + * adjusts spacing between pairs of glyphs. + */ + virtual void enableKerningSupport() + { + theKerningEnabledFlag = true; + theBoundingRectIsValid = false; + } + + /*! + * Will disable kerning support. + */ + virtual void disableKerningSupport() + { + theKerningEnabledFlag = false; + theBoundingRectIsValid = false; + } + + virtual void setHorizontalVerticalShear(double horizontalShear, + double verticalShear) + { + ossimFont::setHorizontalVerticalShear(horizontalShear, + verticalShear); + theBoundingRectIsValid = false; + } + virtual void setScale(double horizontal, + double vertical) + { + ossimFont::setScale(horizontal, + vertical); + theBoundingRectIsValid = false; + } + + virtual void setPixelSize(int horizontalPixelSize, + int verticalPixelSize) + { + ossimFont::setPixelSize(horizontalPixelSize, + verticalPixelSize); + theBoundingRectIsValid = false; + } + virtual void setPixelSize(int pixelSize) + { + ossimFont::setPixelSize(pixelSize); + theBoundingRectIsValid = false; + } + + virtual void setDeviceDpi(int horizontalDeviceUnits, + int verticalDeviceUnits) + { + ossimFont::setDeviceDpi(horizontalDeviceUnits, + verticalDeviceUnits); + theBoundingRectIsValid = false; + } + virtual void setString(const ossimString& s) + { + ossimFont::setString(s); + theBoundingRectIsValid = false; + theNeedToLayoutGlyphsFlag = true; + } + + const FT_Face getFontFace()const + { + return theFontFace; + } +private: + + FT_Face theFontFace; + FT_Library theLibrary; + FT_Matrix theMatrix; + + ossimFilename theFontFile; + + ossim_uint8* theOutputBuffer; + long theBufferSize; + bool theKerningEnabledFlag; + bool theNeedToLayoutGlyphsFlag; + FT_Vector theStringCenter; + ossimIpt theShift; + /*! + * Pre-compute all glyphs but don't render it + */ + vector<TGlyph> theStringLayout; + + /*! + * We will precompute the bounding rect only when we have to. + * this will avoid re-computing on all rasterization calls. We + * will use the dirty flag to tell us if we need to re-compute. + */ + mutable ossimIrect thePrecomputedBoundingRect; + + + /*! + * Used to tell us when we need to recompute. + */ + mutable bool theBoundingRectIsValid; + void layoutGlyphs(const ossimString& s); + + void setBaseClassInformation(); + void setupForRasterization(); + void allocateBuffer(); + + void drawBitmap(FT_Bitmap* bitmap, + const ossimIrect& bufRect, + const ossimIrect& glyphBox); + + void computeGlyphBox(FT_Glyph, + ossimIrect& box)const; + void deleteGlyphs(vector<TGlyph>& glyphs); + +TYPE_DATA +}; + +#endif + +#endif diff --git a/Utilities/OSSIM/ossim_core/fonts/ossimGdBitmapFont.cpp b/Utilities/OSSIM/ossim_core/fonts/ossimGdBitmapFont.cpp new file mode 100644 index 0000000000..7fc1de3784 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/fonts/ossimGdBitmapFont.cpp @@ -0,0 +1,263 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// Description: +// +//******************************************************************** +// $Id: ossimGdBitmapFont.cpp,v 1.7 2003/05/13 11:31:03 dburken Exp $ +#include "fonts/ossimGdBitmapFont.h" +#include "string.h" + +RTTI_DEF1(ossimGdBitmapFont, "ossimGdBitmapFont", ossimFont); + +ossimGdBitmapFont::ossimGdBitmapFont(const ossimString& familyName, + const ossimString& styleName, + const ossimGdFont* gdFontPtr) + :ossimFont(familyName, + styleName, + (int)gdFontPtr->w, + (int)gdFontPtr->h), + theGdFontPtr(gdFontPtr), + theBufferSize(0), + theOutputBuffer(NULL) +{ +} + +ossimGdBitmapFont::ossimGdBitmapFont(const ossimGdBitmapFont& rhs) + :ossimFont(rhs), + theGdFontPtr(rhs.theGdFontPtr), + theBufferSize(rhs.theBufferSize), + theOutputBuffer(NULL) +{ + if(theBufferSize) + { + theOutputBuffer = new ossim_uint8[theBufferSize]; + memcpy(theOutputBuffer, rhs.theOutputBuffer, theBufferSize); + } +} + +ossimGdBitmapFont::~ossimGdBitmapFont() +{ + if(theOutputBuffer) + { + delete [] theOutputBuffer; + theOutputBuffer = NULL; + } +} + +void ossimGdBitmapFont::getBoundingBox(ossimIrect& box) +{ + if(theStringToRasterize.size()) + { + box = ossimIrect(0,0, + (int)ceil(theStringToRasterize.size()*theHorizontalPixelSize*theHorizontalScale)-1, + (int)ceil(theVerticalPixelSize*theVerticalScale)-1); + } + else + { + box = ossimIrect(0, + 0, + 0, + 0); + } + + // I currently don't support rotations and other affine operations so I will comment this + // bounding box test out and use the above. + // +#if 0 + if(theGdFontPtr) + { + if((theRotation == 0.0)&& + (theHorizontalScale == 1.0)&& + (theVerticalScale == 1.0)) + { + box = ossimIrect(0,0, theGdFontPtr->w-1, theGdFontPtr->h-1); + } + else + { + ossimIrect localBox(0,0, theGdFontPtr->w-1, theGdFontPtr->h-1); + double ulx, uly; + double llx, lly; + double lrx, lry; + double urx, ury; + + double min_x, min_y, max_x, max_y; + + ulx = 0.0; + uly = 0.0; + + llx = (theAffineTransform[0][0]*localBox.ll().x + + theAffineTransform[0][1]*localBox.ll().y); + lly = theAffineTransform[1][0]*localBox.ll().x + + theAffineTransform[1][1]*localBox.ll().y; + + lrx = (theAffineTransform[0][0]*localBox.lr().x + + theAffineTransform[0][1]*localBox.lr().y); + lry = theAffineTransform[1][0]*localBox.lr().x + + theAffineTransform[1][1]*localBox.lr().y; + urx = (theAffineTransform[0][0]*localBox.ur().x + + theAffineTransform[0][1]*localBox.ur().y); + ury = theAffineTransform[1][0]*localBox.ur().x + + theAffineTransform[1][1]*localBox.ur().y; + + + min_x = std::min(ulx, std::min(llx, (std::min(lrx, urx)))); + max_x = std::max(ulx, std::max(llx, (std::max(lrx, urx)))); + + min_y = std::min(uly, std::min(lly, (std::min(lry, ury)))); + max_y = std::max(uly, std::max(lly, (std::max(lry, ury)))); + + + + box = ossimIrect((int)floor(min_x), (int)floor(min_y), + (int)ceil(max_x), (int)ceil(max_y)); + } + } +#endif +} + +const ossim_uint8* ossimGdBitmapFont::rasterize() +{ + // make sure the buffer is allocated for the output string + allocateBuffer(); + + if(theOutputBuffer) + { + memset(theOutputBuffer, 0, theBufferSize); + rasterizeNormal(); + } + + return theOutputBuffer; +} + +void ossimGdBitmapFont::rasterizeNormal() +{ + ossimIrect outBox; + ossimIrect inBox(0,0, + theStringToRasterize.length()*theGdFontPtr->w-1, + theGdFontPtr->h-1); + + getBoundingBox(outBox); + + + long charOffset = 0; + long bufOffset = 0; + long inW = inBox.width(); + long inH = inBox.height(); + long outW = outBox.width(); + long outH = outBox.height(); + ossim_uint8* inBuf = new ossim_uint8[inBox.width()*inBox.height()]; + + for(long character = 0; + character < (long)theStringToRasterize.size(); + ++character) + { + charOffset = theStringToRasterize[(int)character]; + + // we need to shift the offset to a positive value. + // if it goes negative we just add 256 to the value. + if(charOffset < 0) + { + charOffset += 256; + } + + // which col do we start on + bufOffset = character*theGdFontPtr->w; + + // get the starting offset to the bitmap + charOffset = charOffset*theGdFontPtr->w*theGdFontPtr->h; + + for(long row = 0; row < (theGdFontPtr->h); ++row) + { + for(long col = 0; col < theGdFontPtr->w; ++col) + { + if(theGdFontPtr->data[charOffset]) + { + inBuf[bufOffset+col] = 255; + } + ++charOffset; + } + bufOffset += inW; + } + } + + if((inW == outW)&&(inH==outH)) + { + memcpy(theOutputBuffer, inBuf, inW*inH); + } + else + { + // now lets expand or contract the input buf to the output buf. + long *xLut = new long[outW]; + long *yLut = new long[outH]; + long i = 0; + for(i = 0; i < outW; ++i) + { + xLut[i] = (int)(i*((double)inW/(double)outW)); + } + for(i = 0; i < outH; ++i) + { + yLut[i] = (int)(i*((double)inH/(double)outH)); + } + + ossim_uint8* outBuf = theOutputBuffer; + for(long row= 0; row < outH; ++row) + { + long inYOffset = yLut[row]*inW; + for(long col=0; col < outW; ++col) + { + *outBuf = inBuf[inYOffset + xLut[col]]; + ++outBuf; + } + } + delete [] xLut; + delete [] yLut; + } + + delete [] inBuf; +} + +void ossimGdBitmapFont::allocateBuffer() +{ + ossimIrect box; + + getBoundingBox(box); + long bufferSize = box.width()*box.height(); + if(bufferSize != theBufferSize) + { + theBufferSize = bufferSize; + + if(theOutputBuffer) + { + delete theOutputBuffer; + theOutputBuffer = NULL; + } + if(!theOutputBuffer&&theBufferSize) + { + theOutputBuffer = new ossim_uint8[theBufferSize]; + + } + } +} + +void ossimGdBitmapFont::getFixedSizes(vector<ossimIpt>& sizes)const +{ + sizes.push_back(ossimIpt(theHorizontalPixelSize, + theVerticalPixelSize)); +} diff --git a/Utilities/OSSIM/ossim_core/fonts/ossimGdBitmapFont.h b/Utilities/OSSIM/ossim_core/fonts/ossimGdBitmapFont.h new file mode 100644 index 0000000000..96f508aba5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/fonts/ossimGdBitmapFont.h @@ -0,0 +1,101 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// Description: +// +//******************************************************************** +// $Id: ossimGdBitmapFont.h,v 1.8 2005/09/09 19:23:58 gpotts Exp $ +#ifndef ossimGdBitmapFont_HEADER +#define ossimGdBitmapFont_HEADER +#include "fonts/ossimFont.h" + +struct ossimGdFont +{ + /* # of characters in font */ + int nchars; + /* First character is numbered... (usually 32 = space) */ + int offset; + /* Character width and height */ + int w; + int h; + /* Font data; array of characters, one row after another. + Easily included in code, also easily loaded from + data files. */ + char *data; +}; +typedef ossimGdFont* ossimGdFontPtr; + +/*! + * This is a wrapper for the gd library fonts. + * Note that this class will currently only support scaling. It will not support + * any other affine operation. + */ +class ossimGdBitmapFont : public ossimFont +{ +public: + + ossimGdBitmapFont(const ossimString& familyName, + const ossimString& styleName, + const ossimGdFont* gdFontPtr); + + ossimGdBitmapFont(const ossimGdBitmapFont& rhs); + virtual ~ossimGdBitmapFont(); + + virtual ossimObject* dup()const + { + return new ossimGdBitmapFont(*this); + } + virtual const ossim_uint8* getBuf()const + { + return theOutputBuffer; + } + /*! + * Will return an internal buffer for rasterizing and will + */ + virtual const ossim_uint8* rasterize(); + virtual void getBoundingBox(ossimIrect& box); + bool isFixed()const + { + return true; + } + + virtual void getFixedSizes(vector<ossimIpt>& sizes)const; + +protected: + const ossimGdFont* theGdFontPtr; + + long theBufferSize; + ossim_uint8* theOutputBuffer; + + /*! + * This will take into consideration the point size along + * the horizontal and vertical and also the scale + * values. So the actual scale will be: + * + * Scale*(pointSize/fixedSize); + */ + void getActualScale(ossimDpt& scales)const; + + void rasterizeNormal(); + void allocateBuffer(); + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/fonts/ossimGdSansBold.inc b/Utilities/OSSIM/ossim_core/fonts/ossimGdSansBold.inc new file mode 100644 index 0000000000..e9d774ae04 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/fonts/ossimGdSansBold.inc @@ -0,0 +1,4383 @@ + +/* + This is a header file for gd font, generated using + bdftogd version 0.51 by Jan Pazdziora, adelton@fi.muni.cz + from bdf font + -Misc-Fixed-Bold-R-Normal-Sans-15-140-75-75-C-90-ISO8859-2 + at Mon Jan 26 14:45:58 1998. + The original bdf was holding following copyright: + "Libor Skarvada, libor@informatics.muni.cz" + */ + + +#include "ossimGdBitmapFont.h" + +char ossimGdSansBoldData[] = +{ +/* Char 0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 1 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 2 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 1, 0, 1, 0, + +/* Char 3 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 4 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 5 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 6 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 7 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 8 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 9 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 10 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 11 */ + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 12 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + +/* Char 13 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + +/* Char 14 */ + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 15 */ + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + +/* Char 16 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 17 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 18 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 19 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 20 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 21 */ + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + +/* Char 22 */ + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + +/* Char 23 */ + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 24 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + +/* Char 25 */ + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + +/* Char 26 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 27 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 28 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 29 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 30 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 0, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 31 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 32 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 33 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 34 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 35 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 36 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 37 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 38 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 1, 0, + 1, 1, 0, 0, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 39 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 40 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 41 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 42 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 43 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 44 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 45 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 46 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 47 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 48 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 49 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 50 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 51 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 52 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 53 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 54 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 55 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 56 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 57 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 58 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 59 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 60 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 61 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 62 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 63 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 64 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 65 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 66 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 67 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 68 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 69 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 70 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 71 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 72 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 73 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 74 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 75 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 76 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 77 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 0, 0, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 78 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 79 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 80 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 81 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 82 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 83 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 84 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 85 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 86 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 87 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 0, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 88 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 89 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 90 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 91 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 92 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 93 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 94 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 95 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 96 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 97 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 98 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 99 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 100 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 101 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 102 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 103 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + +/* Char 104 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 105 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 106 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, 0, + +/* Char 107 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 108 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 109 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 1, 0, 1, 1, 0, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 110 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 111 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 112 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + +/* Char 113 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + +/* Char 114 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 115 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 116 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 117 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 118 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 119 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 120 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 121 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, + 1, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + +/* Char 122 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 123 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 124 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 125 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 126 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 127 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 128 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 129 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 130 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 131 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 132 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 133 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 134 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 135 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 136 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 137 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 138 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 139 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 140 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 141 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 142 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 143 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 144 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 145 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 146 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 147 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 148 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 149 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 150 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 151 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 152 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 153 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 154 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 155 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 156 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 157 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 158 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 159 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 160 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 161 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + +/* Char 162 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 163 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 164 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 165 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 166 */ + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 167 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 168 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 169 */ + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 170 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, 0, + +/* Char 171 */ + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 172 */ + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 173 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 174 */ + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 175 */ + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 176 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 177 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, + +/* Char 178 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, + +/* Char 179 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 180 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 181 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 182 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 183 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 184 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + +/* Char 185 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 186 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, 0, + +/* Char 187 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 188 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 189 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 190 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 191 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 192 */ + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 193 */ + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 194 */ + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 195 */ + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 196 */ + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 197 */ + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 198 */ + 0, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 199 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + +/* Char 200 */ + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 201 */ + 0, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 202 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, + +/* Char 203 */ + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 204 */ + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 205 */ + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 206 */ + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 207 */ + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 208 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 209 */ + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 210 */ + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 211 */ + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 212 */ + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 213 */ + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 214 */ + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 215 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 216 */ + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 217 */ + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 218 */ + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 219 */ + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 220 */ + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 221 */ + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 222 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + +/* Char 223 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 224 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 225 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 226 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 227 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 228 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 229 */ + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 230 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 231 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + +/* Char 232 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 233 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 234 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, + +/* Char 235 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 236 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 237 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 238 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 239 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 240 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 241 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 242 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 243 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 244 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 245 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 246 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 247 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 248 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 249 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 250 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 251 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 252 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 253 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, + 1, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + +/* Char 254 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + +/* Char 255 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + + +}; + +ossimGdFont ossimGdSansBoldRep = +{ + 256, + 0, + 9, + 15, + ossimGdSansBoldData +}; + +ossimGdFontPtr ossimGdSansBold = &ossimGdSansBoldRep; + +/* This file has not been truncated. */ diff --git a/Utilities/OSSIM/ossim_core/imaging/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/imaging/CMakeLists.txt b/Utilities/OSSIM/ossim_core/imaging/CMakeLists.txt new file mode 100644 index 0000000000..890ea9460e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/CMakeLists.txt @@ -0,0 +1,6 @@ +FILE(GLOB_RECURSE ossim_imaging_SRCS "*.cpp") +FILE(GLOB_RECURSE ossim_imaging_HDRS "*.h") +ADD_LIBRARY(ossim_imaging ${ossim_imaging_SRCS}) + +INSTALL_TARGETS(/lib/otb/ ossim_imaging) +INSTALL_FILES(/include/otb/Utilities/OSSIM/ossim_core/ "\\.h$" ${ossim_imaging_HRDS}) diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/annotation/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/gdfontg.inc b/Utilities/OSSIM/ossim_core/imaging/annotation/gdfontg.inc new file mode 100644 index 0000000000..f14aacee90 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/gdfontg.inc @@ -0,0 +1,4384 @@ + + +/* + This is a header file for gd font, generated using + bdftogd version 0.51 by Jan Pazdziora, adelton@fi.muni.cz + from bdf font + -Misc-Fixed-Bold-R-Normal-Sans-15-140-75-75-C-90-ISO8859-2 + at Mon Jan 26 14:45:58 1998. + The original bdf was holding following copyright: + "Libor Skarvada, libor@informatics.muni.cz" + */ + + +#include "ossimGdFont.h" + +char ossimGdFontGiantData[] = +{ +/* Char 0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 1 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 2 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 1, 0, 1, 0, + +/* Char 3 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 4 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 5 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 6 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 7 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 8 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 9 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 10 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 11 */ + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 12 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + +/* Char 13 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + +/* Char 14 */ + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 15 */ + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + +/* Char 16 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 17 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 18 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 19 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 20 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 21 */ + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + +/* Char 22 */ + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + +/* Char 23 */ + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 24 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + +/* Char 25 */ + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + +/* Char 26 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 27 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 28 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 29 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 30 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 0, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 31 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 32 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 33 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 34 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 35 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 36 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 37 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 38 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 1, 0, + 1, 1, 0, 0, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 39 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 40 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 41 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 42 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 43 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 44 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 45 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 46 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 47 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 48 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 49 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 50 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 51 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 52 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 53 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 54 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 55 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 56 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 57 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 58 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 59 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 60 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 61 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 62 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 63 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 64 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 65 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 66 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 67 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 68 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 69 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 70 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 71 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 72 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 73 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 74 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 75 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 76 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 77 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 0, 0, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 78 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 79 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 80 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 81 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 82 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 83 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 84 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 85 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 86 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 87 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 0, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 88 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 89 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 90 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 91 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 92 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 93 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 94 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 95 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 96 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 97 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 98 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 99 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 100 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 101 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 102 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 103 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + +/* Char 104 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 105 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 106 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, 0, + +/* Char 107 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 108 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 109 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 1, 0, 1, 1, 0, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 110 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 111 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 112 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + +/* Char 113 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + +/* Char 114 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 115 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 116 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 117 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 118 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 119 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 120 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 121 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, + 1, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + +/* Char 122 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 123 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 124 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 125 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 126 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 127 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 128 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 129 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 130 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 131 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 132 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 133 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 134 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 135 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 136 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 137 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 138 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 139 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 140 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 141 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 142 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 143 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 144 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 145 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 146 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 147 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 148 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 149 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 150 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 151 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 152 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 153 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 154 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 155 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 156 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 157 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 158 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 159 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 160 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 161 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + +/* Char 162 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 163 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 164 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 165 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 166 */ + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 167 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 168 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 169 */ + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 170 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, 0, + +/* Char 171 */ + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 172 */ + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 173 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 174 */ + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 175 */ + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 176 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 177 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, + +/* Char 178 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, + +/* Char 179 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 180 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 181 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 182 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 183 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 184 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + +/* Char 185 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 186 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, 0, + +/* Char 187 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 188 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 189 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 190 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 191 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 192 */ + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 193 */ + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 194 */ + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 195 */ + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 196 */ + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 197 */ + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 198 */ + 0, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 199 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + +/* Char 200 */ + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 201 */ + 0, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 202 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, + +/* Char 203 */ + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 204 */ + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 205 */ + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 206 */ + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 207 */ + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 208 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 209 */ + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 210 */ + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 211 */ + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 212 */ + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 213 */ + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 214 */ + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 215 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 216 */ + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 217 */ + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 218 */ + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 219 */ + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 220 */ + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 221 */ + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 222 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + +/* Char 223 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 224 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 225 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 226 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 227 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 228 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 229 */ + 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 230 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 231 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + +/* Char 232 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 233 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 234 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, + +/* Char 235 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 236 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 237 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 238 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 239 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 240 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 241 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 242 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 243 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 244 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 245 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 246 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 247 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 248 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 249 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 250 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 251 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 252 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 253 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, + 1, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, + +/* Char 254 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, + +/* Char 255 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + + +}; + +ossimGdFont ossimGdFontGiantRep = +{ + 256, + 0, + 9, + 15, + ossimGdFontGiantData +}; + +ossimGdFontPtr ossimGdFontGiant = &ossimGdFontGiantRep; + +/* This file has not been truncated. */ diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/gdfontl.inc b/Utilities/OSSIM/ossim_core/imaging/annotation/gdfontl.inc new file mode 100644 index 0000000000..f268f7f084 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/gdfontl.inc @@ -0,0 +1,4641 @@ + + +/* + This is a header file for gd font, generated using + bdftogd version 0.5 by Jan Pazdziora, adelton@fi.muni.cz + from bdf font + -misc-fixed-medium-r-normal--16-140-75-75-c-80-iso8859-2 + at Tue Jan 6 19:39:27 1998. + + The original bdf was holding following copyright: + "Libor Skarvada, libor@informatics.muni.cz" + */ + + +#include "ossimGdFont.h" + +char ossimGdFontLargeData[] = +{ +/* Char 0 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 1 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 2 */ + 1, 0, 1, 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, 1, 0, 1, + 1, 0, 1, 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, 1, 0, 1, + 1, 0, 1, 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, 1, 0, 1, + 1, 0, 1, 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, 1, 0, 1, + 1, 0, 1, 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, 1, 0, 1, + 1, 0, 1, 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, 1, 0, 1, + 1, 0, 1, 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, 1, 0, 1, + 1, 0, 1, 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, 1, 0, 1, + +/* Char 3 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 4 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 5 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 0, 0, 1, 0, + 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 6 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 7 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 8 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 9 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 0, 0, 0, + 1, 0, 1, 0, 1, 0, 0, 0, + 1, 0, 0, 1, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 10 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 0, 0, 0, + 0, 1, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 11 */ + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 12 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + +/* Char 13 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + +/* Char 14 */ + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 15 */ + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + +/* Char 16 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 17 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 18 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 19 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 20 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 21 */ + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + +/* Char 22 */ + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + +/* Char 23 */ + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 24 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + +/* Char 25 */ + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + +/* Char 26 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 27 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 28 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 1, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 29 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 30 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 0, + 1, 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 31 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 32 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 33 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 34 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 35 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 1, 0, + 0, 0, 0, 1, 0, 0, 1, 0, + 0, 0, 0, 1, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 36 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 1, 0, 0, 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 37 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 0, + 1, 0, 0, 1, 0, 1, 0, 0, + 1, 0, 0, 1, 0, 1, 0, 0, + 0, 1, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 1, 0, 0, + 0, 1, 0, 1, 0, 0, 1, 0, + 0, 1, 0, 1, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 38 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, 1, 0, + 1, 0, 0, 0, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 39 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 40 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 41 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 42 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 1, 0, 0, 1, 0, 0, 1, 0, + 0, 1, 0, 1, 0, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 1, 0, 0, + 1, 0, 0, 1, 0, 0, 1, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 43 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 44 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 45 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 46 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 47 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 48 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 49 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 50 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 51 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 52 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 53 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 54 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 55 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 56 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 57 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 58 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 59 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 60 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 61 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 62 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 63 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 64 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, 1, 1, 0, + 0, 1, 0, 1, 0, 0, 1, 0, + 0, 1, 0, 1, 0, 0, 1, 0, + 0, 1, 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 65 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 66 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 67 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 68 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 69 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 70 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 71 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 72 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 73 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 74 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 75 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 76 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 77 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 0, 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 78 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 1, 0, 0, 1, 0, + 0, 1, 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, 1, 0, + 0, 1, 0, 0, 1, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 79 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 80 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 81 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 1, 1, 0, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 82 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 83 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 84 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 85 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 86 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 87 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 1, 0, + 1, 0, 0, 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 88 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 89 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 90 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 91 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 92 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 93 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 94 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 95 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 96 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 97 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 98 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 99 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 100 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 101 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 102 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 103 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + +/* Char 104 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 105 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 106 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, + +/* Char 107 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 108 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 109 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 110 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 111 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 112 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + +/* Char 113 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + +/* Char 114 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 115 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 116 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 1, 0, + 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 117 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 118 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 119 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 1, 0, + 1, 0, 0, 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 120 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 121 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, + +/* Char 122 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 123 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 124 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 125 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 126 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 0, + 1, 0, 0, 1, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 127 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 128 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 129 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 130 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 131 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 132 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 133 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 134 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 135 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 136 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 137 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 138 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 139 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 140 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 141 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 142 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 143 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 144 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 145 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 146 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 147 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 148 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 149 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 150 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 151 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 152 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 153 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 154 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 155 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 156 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 157 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 158 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 159 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 160 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 161 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, + +/* Char 162 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 163 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 164 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 1, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 165 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 166 */ + 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 167 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 168 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 169 */ + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 170 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + +/* Char 171 */ + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 172 */ + 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 173 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 174 */ + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 175 */ + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 176 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 177 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, + +/* Char 178 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 0, + +/* Char 179 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 180 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 181 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 1, 0, + 0, 0, 0, 1, 0, 0, 1, 0, + 0, 0, 0, 1, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 182 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 183 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 184 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, + +/* Char 185 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 186 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + +/* Char 187 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 1, 0, + 1, 1, 1, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 188 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 189 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 190 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 191 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 192 */ + 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 193 */ + 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 194 */ + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 195 */ + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 196 */ + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 197 */ + 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 198 */ + 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 199 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, + +/* Char 200 */ + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 201 */ + 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 202 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, + +/* Char 203 */ + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 204 */ + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 205 */ + 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 206 */ + 0, 0, 1, 1, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 207 */ + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 208 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 1, 1, 1, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 209 */ + 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 1, 0, 0, 1, 0, + 0, 1, 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, 1, 0, + 0, 1, 0, 0, 1, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 210 */ + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 1, 0, 0, 1, 0, + 0, 1, 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, 1, 0, + 0, 1, 0, 0, 1, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 211 */ + 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 212 */ + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 213 */ + 0, 0, 0, 1, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 214 */ + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 215 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 216 */ + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 217 */ + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 218 */ + 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 219 */ + 0, 0, 0, 1, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 220 */ + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 221 */ + 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 222 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + +/* Char 223 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 1, 1, 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 224 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 225 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 226 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 227 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 228 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 229 */ + 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 230 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 231 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, + +/* Char 232 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 233 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 234 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, + +/* Char 235 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 236 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 237 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 238 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 239 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 1, 0, 1, + 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 1, 1, 1, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 1, 0, 0, + 1, 0, 0, 0, 0, 1, 0, 0, + 1, 0, 0, 0, 0, 1, 0, 0, + 1, 0, 0, 0, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 1, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 240 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 1, 1, 1, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 1, 0, 0, + 1, 0, 0, 0, 0, 1, 0, 0, + 1, 0, 0, 0, 0, 1, 0, 0, + 1, 0, 0, 0, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 1, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 241 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 242 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 243 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 244 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 245 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 1, + 0, 0, 0, 1, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 246 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 247 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 248 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 249 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 250 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 251 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 1, + 0, 0, 0, 1, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 252 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +/* Char 253 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, + +/* Char 254 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 1, 0, + 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + +/* Char 255 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + +}; + +ossimGdFont ossimGdFontLargeRep = +{ + 256, + 0, + 8, + 16, + ossimGdFontLargeData +}; + +ossimGdFontPtr ossimGdFontLarge = &ossimGdFontLargeRep; + +/* This file has not been truncated. */ diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/gdfontmb.inc b/Utilities/OSSIM/ossim_core/imaging/annotation/gdfontmb.inc new file mode 100644 index 0000000000..4ac44cecae --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/gdfontmb.inc @@ -0,0 +1,3870 @@ + +/* + This is a header file for gd font, generated using + bdftogd version 0.5 by Jan Pazdziora, adelton@fi.muni.cz + from bdf font + -misc-fixed-bold-r-normal-sans-13-94-100-100-c-70-iso8859-2 + at Thu Jan 8 13:54:57 1998. + No copyright info was found in the original bdf. + */ + + +#include "ossimGdFont.h" + +char ossimGdFontMediumBoldData[] = +{ +/* Char 0 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 1 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 2 */ + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 3 */ + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 0, 0, + 1, 1, 0, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 1, 1, 0, 0, + 1, 1, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 4 */ + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 5 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 1, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 1, 0, + 0, 0, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 6 */ + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 7 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 8 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 9 */ + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 10 */ + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 0, 0, 1, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 11 */ + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 12 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + +/* Char 13 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + +/* Char 14 */ + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 15 */ + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + +/* Char 16 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 17 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 18 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 19 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 20 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 21 */ + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + +/* Char 22 */ + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + +/* Char 23 */ + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 24 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + +/* Char 25 */ + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + +/* Char 26 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 27 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 28 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 1, 0, + 1, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 29 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 30 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, + 1, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 31 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 32 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 33 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 34 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 35 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 1, 0, 0, + 0, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 0, 1, 0, 0, + 0, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 36 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 0, 1, 1, 0, 1, 0, + 1, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 1, 0, + 1, 0, 1, 1, 0, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 37 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 1, 0, + 1, 0, 1, 0, 1, 1, 0, + 1, 1, 1, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 0, 1, 1, 1, 0, + 1, 1, 0, 1, 0, 1, 0, + 1, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 38 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 1, 1, 0, 0, + 1, 1, 0, 1, 1, 0, 0, + 0, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 1, 0, 1, 0, + 1, 1, 0, 1, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 0, + 0, 1, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 39 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 40 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 41 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 42 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 43 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 44 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 45 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 46 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 47 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 48 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 1, 0, + 1, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 49 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, + 1, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 50 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 51 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 52 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 0, + 0, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 53 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 54 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 55 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 56 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 57 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 58 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 59 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 60 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 61 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 62 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 63 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 64 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 1, 0, + 1, 0, 1, 1, 1, 1, 0, + 1, 0, 1, 0, 1, 1, 0, + 1, 0, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 65 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 66 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 67 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 68 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 69 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 70 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 71 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 72 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 73 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 74 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 75 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 0, + 1, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 76 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 77 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 78 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 0, 1, 1, 0, + 1, 1, 1, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 1, 1, 1, 0, + 1, 1, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 79 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 80 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 81 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 82 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 83 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 84 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 85 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 86 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 1, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 87 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 88 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 0, 0, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 89 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 90 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 91 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 92 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 93 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 94 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 95 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 96 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 97 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 98 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 99 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 100 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 101 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 102 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 103 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + +/* Char 104 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 105 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 106 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + +/* Char 107 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 0, + 1, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 108 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 109 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 110 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 111 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 112 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + +/* Char 113 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + +/* Char 114 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 115 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 116 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 117 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 118 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 119 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 120 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 121 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + +/* Char 122 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 123 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 124 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 125 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 126 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 127 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 128 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 129 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 130 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 131 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 132 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 133 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 134 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 135 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 136 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 137 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 138 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 139 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 140 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 141 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 142 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 143 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 144 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 145 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 146 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 147 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 148 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 149 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 150 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 151 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 152 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 153 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 154 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 155 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 156 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 157 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 158 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 159 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 160 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 161 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + +/* Char 162 */ + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 163 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 164 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 165 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 166 */ + 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 167 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 168 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 169 */ + 0, 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 170 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + +/* Char 171 */ + 0, 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 172 */ + 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 173 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 174 */ + 0, 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 175 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 176 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 177 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + +/* Char 178 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, + +/* Char 179 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 1, 0, + 0, 0, 1, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, + 1, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 180 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 181 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, + 1, 1, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 182 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 183 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 184 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 1, 0, 0, 0, + +/* Char 185 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 186 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + +/* Char 187 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 188 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 189 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 190 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 191 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 192 */ + 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 193 */ + 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 194 */ + 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 195 */ + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 196 */ + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 197 */ + 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 198 */ + 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 199 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + +/* Char 200 */ + 0, 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 201 */ + 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 202 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + +/* Char 203 */ + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 204 */ + 0, 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 205 */ + 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 206 */ + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 207 */ + 0, 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 208 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 1, 0, + 1, 1, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 209 */ + 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 0, 1, 1, 0, + 1, 1, 1, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 1, 1, 1, 0, + 1, 1, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 210 */ + 0, 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 0, 1, 1, 0, + 1, 1, 1, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 1, 1, 1, 0, + 1, 1, 0, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 211 */ + 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 212 */ + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 213 */ + 0, 1, 1, 0, 0, 1, 1, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 214 */ + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 215 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 216 */ + 0, 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 217 */ + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 0, 0, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 218 */ + 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 219 */ + 0, 1, 1, 0, 0, 1, 1, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 220 */ + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 221 */ + 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 222 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + +/* Char 223 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 0, + 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 224 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 225 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 226 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 227 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 228 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 229 */ + 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 230 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 231 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + +/* Char 232 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 233 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 234 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, + +/* Char 235 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 236 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 237 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 238 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, + 1, 1, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 239 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, + 0, 0, 0, 1, 1, 0, 1, + 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 1, 1, 0, 0, + 1, 1, 0, 1, 1, 0, 0, + 1, 1, 0, 1, 1, 0, 0, + 1, 1, 0, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 240 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 1, 1, + 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 241 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 242 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 243 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 244 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 245 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 246 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 247 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 248 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 249 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 0, 0, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 250 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 251 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 252 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + +/* Char 253 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, + +/* Char 254 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, + +/* Char 255 */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + + +}; + +ossimGdFont ossimGdFontMediumBoldRep = +{ + 256, + 0, + 7, + 13, + ossimGdFontMediumBoldData +}; + +ossimGdFontPtr ossimGdFontMediumBold = &ossimGdFontMediumBoldRep; + +/* This file has not been truncated. */ diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/gdfonts.inc b/Utilities/OSSIM/ossim_core/imaging/annotation/gdfonts.inc new file mode 100644 index 0000000000..d2d3c0a74b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/gdfonts.inc @@ -0,0 +1,3871 @@ + + +/* + This is a header file for gd font, generated using + bdftogd version 0.5 by Jan Pazdziora, adelton@fi.muni.cz + from bdf font + -misc-fixed-medium-r-semicondensed-sans-12-116-75-75-c-60-iso8859-2 + at Thu Jan 8 14:13:20 1998. + No copyright info was found in the original bdf. + */ + + +#include "ossimGdFont.h" + +char ossimGdFontSmallData[] = +{ +/* Char 0 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 1 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 2 */ + 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 0, 1, + 1, 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, 1, + 1, 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, 1, + 1, 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, 1, + 1, 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, 1, + 1, 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, 1, + 1, 0, 1, 0, 1, 0, + +/* Char 3 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 1, 0, 0, 0, + 1, 0, 1, 0, 0, 0, + 1, 1, 1, 0, 0, 0, + 1, 0, 1, 0, 0, 0, + 1, 0, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 4 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 1, 1, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 5 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 6 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 7 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, + 1, 0, 0, 1, 0, 0, + 1, 0, 0, 1, 0, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 8 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 9 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 0, 0, 1, 0, + 1, 0, 1, 0, 1, 0, + 1, 0, 0, 1, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, + +/* Char 10 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 11 */ + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 12 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + +/* Char 13 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + +/* Char 14 */ + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 15 */ + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + +/* Char 16 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 17 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 18 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 19 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 20 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 21 */ + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 1, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + +/* Char 22 */ + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + +/* Char 23 */ + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 24 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + +/* Char 25 */ + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + +/* Char 26 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 27 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 28 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 0, + 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 29 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 30 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 0, + 1, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 31 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 32 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 33 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 34 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 35 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 1, 0, 1, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 36 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 0, + 1, 0, 1, 0, 0, 0, + 1, 0, 1, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 1, 0, 1, 0, + 0, 0, 1, 0, 1, 0, + 1, 1, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 37 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 0, + 1, 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 1, 0, 1, 0, 1, 0, + 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 38 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 1, 0, 1, 0, 0, 0, + 1, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 1, 0, 1, 0, 0, 0, + 1, 0, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 0, + 0, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 39 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 40 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 41 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 42 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 1, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 43 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 44 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 45 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 46 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 47 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 48 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 49 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, + 1, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 50 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 51 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 52 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 1, 0, 1, 0, 0, + 1, 0, 0, 1, 0, 0, + 1, 0, 0, 1, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 53 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 54 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, + 0, 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 55 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 56 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 57 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, 0, + 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 58 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 59 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 60 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 61 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 62 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 63 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 64 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 1, 1, 0, + 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, + 1, 0, 1, 1, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 65 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 66 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 67 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 68 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 69 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 70 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 71 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 1, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 72 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 73 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 74 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 1, 0, 0, 1, 0, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 75 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 1, 0, 0, + 1, 0, 1, 0, 0, 0, + 1, 1, 1, 0, 0, 0, + 1, 0, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 76 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 77 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 0, 1, 1, 0, + 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 78 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 0, 0, 1, 0, + 1, 1, 0, 0, 1, 0, + 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, + 1, 0, 0, 1, 1, 0, + 1, 0, 0, 1, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 79 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 80 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 81 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 1, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 82 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 1, 1, 0, 0, + 1, 0, 1, 0, 0, 0, + 1, 0, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 83 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 84 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 85 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 86 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 87 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, + 1, 1, 0, 1, 1, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 88 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 89 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 90 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 91 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 92 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 93 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 94 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 95 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 96 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 97 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 98 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 0, 0, 1, 0, + 1, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 99 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 100 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 1, 0, + 1, 0, 0, 1, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 101 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 102 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 103 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + +/* Char 104 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 105 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 106 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 1, 0, 0, 1, 0, 0, + 1, 0, 0, 1, 0, 0, + 0, 1, 1, 0, 0, 0, + +/* Char 107 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 1, 0, 0, + 1, 0, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 0, + 1, 0, 1, 0, 0, 0, + 1, 0, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 108 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 109 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 0, 0, + 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 110 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 111 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 112 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 0, 0, 1, 0, + 1, 0, 1, 1, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + +/* Char 113 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 0, + 1, 0, 0, 1, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 1, 0, + +/* Char 114 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 115 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 116 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 117 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 118 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 119 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 120 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 121 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, 0, + 1, 1, 1, 0, 0, 0, + +/* Char 122 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 123 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 124 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 125 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 126 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 0, + 1, 0, 1, 0, 1, 0, + 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 127 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 128 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 129 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 130 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 131 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 132 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 133 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 134 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 135 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 136 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 137 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 138 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 139 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 140 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 141 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 142 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 143 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 144 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 145 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 146 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 147 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 148 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 149 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 150 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 151 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 152 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 153 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 154 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 155 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 156 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 157 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 158 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 159 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 160 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 161 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 1, + +/* Char 162 */ + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 163 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 164 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 165 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, 0, + 1, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 166 */ + 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 167 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 168 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 169 */ + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 170 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + +/* Char 171 */ + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 172 */ + 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 173 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 174 */ + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 175 */ + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 176 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 177 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 1, + +/* Char 178 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, + +/* Char 179 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 180 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 181 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, + 0, 1, 1, 0, 0, 1, + 0, 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 182 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 183 */ + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 184 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 1, 1, 0, 0, 0, + +/* Char 185 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 186 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + +/* Char 187 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 1, 0, + 0, 1, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 188 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 189 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 1, + 0, 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 190 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 191 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 192 */ + 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 1, 1, 0, 0, + 1, 0, 1, 0, 0, 0, + 1, 0, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 193 */ + 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 194 */ + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 195 */ + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 196 */ + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 197 */ + 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 198 */ + 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 199 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 1, 1, 0, 0, 0, + +/* Char 200 */ + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 201 */ + 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 202 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, + +/* Char 203 */ + 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 204 */ + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 205 */ + 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 206 */ + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 207 */ + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 208 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 1, 1, 1, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 209 */ + 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 0, 0, 1, 0, + 1, 1, 0, 0, 1, 0, + 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, + 1, 0, 0, 1, 1, 0, + 1, 0, 0, 1, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 210 */ + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 0, 0, 1, 0, + 1, 1, 0, 0, 1, 0, + 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, + 1, 0, 0, 1, 1, 0, + 1, 0, 0, 1, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 211 */ + 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 212 */ + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 213 */ + 0, 0, 1, 0, 0, 1, + 0, 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 214 */ + 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 215 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 216 */ + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 1, 1, 0, 0, + 1, 0, 1, 0, 0, 0, + 1, 0, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 217 */ + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 218 */ + 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 219 */ + 0, 0, 1, 0, 0, 1, + 0, 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 220 */ + 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 221 */ + 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 222 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + +/* Char 223 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 0, 0, 1, 0, + 1, 0, 1, 1, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 224 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 225 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 226 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 227 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 228 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 229 */ + 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 230 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 231 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 1, 1, 0, 0, 0, + +/* Char 232 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 233 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 234 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, + +/* Char 235 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 236 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 237 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 238 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 239 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 1, + 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 0, + 1, 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, 0, + 1, 0, 0, 1, 0, 0, + 1, 0, 0, 1, 0, 0, + 0, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 240 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 1, 1, 1, + 0, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 1, 0, + 1, 0, 0, 1, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 241 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 242 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 243 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 244 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 245 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 246 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 247 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 248 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 249 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 250 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 251 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 252 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + +/* Char 253 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 0, + 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, 0, + 1, 1, 1, 0, 0, 0, + +/* Char 254 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + +/* Char 255 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + + +}; + +ossimGdFont ossimGdFontSmallRep = +{ + 256, + 0, + 6, + 13, + ossimGdFontSmallData +}; + +ossimGdFontPtr ossimGdFontSmall = &ossimGdFontSmallRep; + +/* This file has not been truncated. */ diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/gdfontt.inc b/Utilities/OSSIM/ossim_core/imaging/annotation/gdfontt.inc new file mode 100644 index 0000000000..6db0045fb5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/gdfontt.inc @@ -0,0 +1,2589 @@ + +/* + This is a header file for gd font, generated using + bdftogd version 0.5 by Jan Pazdziora, adelton@fi.muni.cz + from bdf font + -Misc-Fixed-Medium-R-Normal--8-80-75-75-C-50-ISO8859-2 + at Thu Jan 8 13:49:54 1998. + The original bdf was holding following copyright: + "Libor Skarvada, libor@informatics.muni.cz" + */ +#include "ossimGdFont.h" + +char ossimGdFontTinyData[] = +{ +/* Char 0 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 1 */ + 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 1, 1, 0, + 1, 1, 1, 1, 1, + 0, 1, 1, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 2 */ + 0, 1, 0, 1, 0, + 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, + 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, + 1, 0, 1, 0, 0, + 0, 1, 0, 1, 0, + 1, 0, 1, 0, 0, + +/* Char 3 */ + 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, + 0, 1, 1, 1, 0, + 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, + 0, 0, 1, 1, 1, + 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, + +/* Char 4 */ + 1, 1, 1, 0, 0, + 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, + 1, 0, 1, 1, 1, + 1, 0, 1, 0, 0, + 0, 0, 1, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + +/* Char 5 */ + 0, 1, 1, 0, 0, + 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, + 0, 0, 1, 0, 1, + 0, 0, 1, 1, 0, + 0, 0, 1, 0, 1, + +/* Char 6 */ + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, + 0, 0, 1, 0, 0, + 0, 0, 1, 1, 0, + 0, 0, 1, 0, 0, + +/* Char 7 */ + 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, + 1, 0, 1, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 8 */ + 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 9 */ + 1, 0, 0, 1, 0, + 1, 1, 0, 1, 0, + 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 1, 1, + +/* Char 10 */ + 1, 0, 1, 0, 0, + 1, 0, 1, 0, 0, + 1, 0, 1, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 1, 1, 1, + 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, + +/* Char 11 */ + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 12 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + +/* Char 13 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + +/* Char 14 */ + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 1, 1, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 15 */ + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 1, 1, 1, 1, 1, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + +/* Char 16 */ + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 17 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 18 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 19 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 20 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 21 */ + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 1, 1, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + +/* Char 22 */ + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 1, 1, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + +/* Char 23 */ + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 24 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + +/* Char 25 */ + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + +/* Char 26 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 27 */ + 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 28 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, + 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 29 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, + 1, 1, 1, 1, 1, + 0, 0, 1, 0, 0, + 1, 1, 1, 1, 1, + 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 30 */ + 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, + 0, 1, 0, 0, 1, + 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 0, 1, + 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 31 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 32 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 33 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 34 */ + 0, 0, 0, 0, 0, + 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 35 */ + 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, + 1, 1, 1, 1, 1, + 0, 1, 0, 1, 0, + 1, 1, 1, 1, 1, + 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 36 */ + 0, 0, 1, 0, 0, + 0, 1, 1, 1, 0, + 1, 0, 1, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 1, 0, 1, + 0, 1, 1, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 37 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, + 1, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 1, 1, + 1, 0, 0, 1, 1, + 0, 0, 0, 0, 0, + +/* Char 38 */ + 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 1, + 0, 0, 0, 0, 0, + +/* Char 39 */ + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 40 */ + 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 41 */ + 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 42 */ + 0, 0, 0, 0, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 1, 1, 1, 1, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 43 */ + 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 1, 1, 1, 1, 1, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 44 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 45 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 46 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 47 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 48 */ + 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 49 */ + 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 50 */ + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 51 */ + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 52 */ + 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 1, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 53 */ + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, + 1, 1, 1, 0, 0, + 0, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 54 */ + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 0, 0, + 1, 0, 1, 0, 0, + 1, 1, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 55 */ + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 56 */ + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 57 */ + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 1, 1, 0, + 0, 1, 0, 1, 0, + 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 58 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 59 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, + 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, + +/* Char 60 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 61 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 62 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 63 */ + 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 1, 0, + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 64 */ + 0, 0, 1, 1, 0, + 0, 1, 0, 0, 1, + 1, 0, 0, 1, 1, + 1, 0, 1, 0, 1, + 1, 0, 1, 0, 1, + 1, 0, 0, 1, 0, + 0, 1, 0, 0, 0, + 0, 0, 1, 1, 0, + +/* Char 65 */ + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 1, 1, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 66 */ + 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 67 */ + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 68 */ + 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 69 */ + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, + 1, 1, 1, 0, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 70 */ + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, + 1, 1, 1, 0, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 71 */ + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 0, 0, + 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 72 */ + 0, 0, 0, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 1, 1, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 73 */ + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 74 */ + 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, + 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 75 */ + 0, 0, 0, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 1, 0, 0, + 1, 1, 0, 0, 0, + 1, 0, 1, 0, 0, + 1, 0, 1, 0, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 76 */ + 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 77 */ + 0, 0, 0, 0, 0, + 1, 0, 0, 1, 0, + 1, 1, 1, 1, 0, + 1, 1, 1, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 78 */ + 0, 0, 0, 0, 0, + 1, 0, 0, 1, 0, + 1, 1, 0, 1, 0, + 1, 1, 1, 1, 0, + 1, 0, 1, 1, 0, + 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 79 */ + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 80 */ + 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 1, 1, 0, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 81 */ + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 1, 0, 1, 0, + 1, 0, 1, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 1, 0, + +/* Char 82 */ + 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 1, 1, 0, 0, + 1, 0, 1, 0, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 83 */ + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 1, 0, + 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 84 */ + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 85 */ + 0, 0, 0, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 86 */ + 0, 0, 0, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 87 */ + 0, 0, 0, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 1, 1, 1, 0, + 1, 1, 1, 1, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 88 */ + 0, 0, 0, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 89 */ + 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, + 1, 0, 0, 0, 1, + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 90 */ + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 91 */ + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 92 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, + 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, + +/* Char 93 */ + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 94 */ + 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 95 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, + +/* Char 96 */ + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 97 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 1, 1, 0, + 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 98 */ + 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 99 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 100 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 1, 1, 0, + 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 101 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 1, 1, 0, + 1, 1, 0, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 102 */ + 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 1, 0, + 0, 1, 0, 0, 0, + 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 103 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + +/* Char 104 */ + 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 105 */ + 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 106 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + +/* Char 107 */ + 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 1, 0, + 1, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 108 */ + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 109 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 0, 1, 0, + 1, 0, 1, 0, 1, + 1, 0, 1, 0, 1, + 1, 0, 0, 0, 1, + 0, 0, 0, 0, 0, + +/* Char 110 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 0, 1, 0, 0, + 1, 1, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 111 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 112 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 1, 1, 0, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + +/* Char 113 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, + +/* Char 114 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 0, 1, 0, 0, + 1, 1, 0, 1, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 115 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, + 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 116 */ + 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, + 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 117 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 1, 1, 0, + 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 118 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 119 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, + 1, 0, 1, 0, 1, + 1, 0, 1, 0, 1, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 120 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 121 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + +/* Char 122 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 123 */ + 0, 0, 1, 1, 0, + 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, + 1, 1, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 124 */ + 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 125 */ + 0, 1, 1, 0, 0, + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, + 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 126 */ + 0, 0, 0, 0, 0, + 0, 1, 0, 1, 0, + 1, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 127 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 128 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 129 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 130 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 131 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 132 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 133 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 134 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 135 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 136 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 137 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 138 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 139 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 140 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 141 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 142 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 143 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 144 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 145 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 146 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 147 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 148 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 149 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 150 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 151 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 152 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 153 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 154 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 155 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 156 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 157 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 158 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 159 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 160 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 161 */ + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 1, 1, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 1, 1, 0, + 0, 0, 0, 1, 1, + +/* Char 162 */ + 1, 0, 0, 0, 1, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 163 */ + 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 1, 0, 0, 0, + 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, + 0, 0, 0, 0, 0, + +/* Char 164 */ + 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, + 0, 1, 1, 1, 0, + 0, 1, 0, 1, 0, + 0, 1, 1, 1, 0, + 1, 0, 0, 0, 1, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 165 */ + 0, 0, 1, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 1, 0, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 166 */ + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 1, 1, 0, + 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 1, 0, + 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 167 */ + 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, + 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + +/* Char 168 */ + 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 169 */ + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 1, 1, 0, + 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 1, 0, + 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 170 */ + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 1, 0, + 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, + +/* Char 171 */ + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + 1, 1, 1, 1, 1, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 172 */ + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 173 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 174 */ + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 175 */ + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 176 */ + 0, 0, 1, 0, 0, + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 177 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 1, 1, 0, + 0, 1, 0, 1, 0, + 0, 0, 0, 1, 1, + +/* Char 178 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, + +/* Char 179 */ + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 180 */ + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 181 */ + 0, 0, 0, 1, 1, + 1, 1, 0, 0, 1, + 0, 1, 0, 1, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, + 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 182 */ + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, + 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 183 */ + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 184 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + +/* Char 185 */ + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, + 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 186 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, + 0, 0, 1, 1, 0, + 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, + +/* Char 187 */ + 0, 0, 0, 1, 1, + 0, 1, 0, 0, 1, + 0, 1, 0, 1, 0, + 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 188 */ + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 189 */ + 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 190 */ + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 191 */ + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 192 */ + 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, + 1, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 1, 1, 0, 0, + 1, 0, 1, 0, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 193 */ + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 1, 1, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 194 */ + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 1, 1, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 195 */ + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 1, 1, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 196 */ + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 1, 1, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 197 */ + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 198 */ + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 199 */ + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 1, 1, 0, 0, 0, + +/* Char 200 */ + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 201 */ + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, + 1, 1, 1, 0, 0, + 1, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 202 */ + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, + 1, 1, 1, 0, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, + +/* Char 203 */ + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, + 1, 1, 1, 0, 0, + 1, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 204 */ + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, + 1, 1, 1, 0, 0, + 1, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 205 */ + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 206 */ + 0, 0, 1, 0, 0, + 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 207 */ + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + 1, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 208 */ + 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, + 0, 1, 0, 1, 0, + 1, 1, 0, 1, 0, + 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, + 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 209 */ + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 1, 0, 1, 0, + 1, 1, 1, 1, 0, + 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 210 */ + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 1, 0, 1, 0, + 1, 1, 1, 1, 0, + 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 211 */ + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 212 */ + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 213 */ + 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 214 */ + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 215 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 216 */ + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + 1, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 1, 1, 0, 0, + 1, 0, 1, 0, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 217 */ + 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 218 */ + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 219 */ + 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 220 */ + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 221 */ + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 1, 0, 0, 0, 1, + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 222 */ + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, + +/* Char 223 */ + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 1, 0, 1, 0, + 1, 0, 1, 0, 0, + 1, 0, 0, 0, 0, + +/* Char 224 */ + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 1, 0, 1, 0, 0, + 1, 1, 0, 1, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 225 */ + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 1, 1, 0, + 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 226 */ + 0, 0, 1, 0, 0, + 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 1, 1, 0, + 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 227 */ + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 1, 1, 0, + 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 228 */ + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 1, 1, 0, + 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 229 */ + 0, 0, 0, 0, 1, + 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 230 */ + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 231 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 1, 1, 1, 0, 0, + +/* Char 232 */ + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 233 */ + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 1, 1, 0, + 1, 1, 0, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 234 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 1, 1, 0, + 1, 1, 0, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 1, 1, + +/* Char 235 */ + 0, 0, 0, 0, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 1, 1, 0, + 1, 1, 0, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 236 */ + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 1, 1, 0, + 1, 1, 0, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 237 */ + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 238 */ + 0, 0, 1, 0, 0, + 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 239 */ + 0, 0, 0, 1, 1, + 0, 0, 1, 0, 1, + 0, 0, 1, 0, 1, + 0, 1, 1, 0, 0, + 1, 0, 1, 0, 0, + 1, 0, 1, 0, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 240 */ + 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, + 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 1, 1, 0, + 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 241 */ + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 1, 0, 1, 0, 0, + 1, 1, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 242 */ + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 1, 0, 1, 0, 0, + 1, 1, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 243 */ + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 244 */ + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 245 */ + 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 246 */ + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 247 */ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 248 */ + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 1, 0, 1, 0, 0, + 1, 1, 0, 1, 0, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + +/* Char 249 */ + 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 1, 1, 0, + 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 250 */ + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 1, 1, 0, + 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 251 */ + 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 1, 1, 0, + 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 252 */ + 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 1, 1, 0, + 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, + +/* Char 253 */ + 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, + +/* Char 254 */ + 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, + 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, + 0, 1, 1, 0, 0, + +/* Char 255 */ + 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + + +}; + +ossimGdFont ossimGdFontTinyRep = +{ + 256, + 0, + 5, + 8, + ossimGdFontTinyData +}; + +ossimGdFontPtr ossimGdFontTiny = &ossimGdFontTinyRep; + +/* This file has not been truncated. */ diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationEllipseObject.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationEllipseObject.cpp new file mode 100644 index 0000000000..9c276a689b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationEllipseObject.cpp @@ -0,0 +1,180 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See LICENSE.txt file in the top level directory. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimAnnotationEllipseObject.cpp,v 1.9 2005/12/07 19:08:55 dburken Exp $ +#include <imaging/annotation/ossimAnnotationEllipseObject.h> +#include <imaging/ossimRgbImage.h> +#include <base/common/ossimCommon.h> + +RTTI_DEF1(ossimAnnotationEllipseObject, + "ossimAnnotationEllipseObject", + ossimAnnotationObject) + +ossimAnnotationEllipseObject::ossimAnnotationEllipseObject( + const ossimDpt& center, + const ossimDpt& widthHeight, + bool enableFill, + ossim_uint8 r, + ossim_uint8 g, + ossim_uint8 b, + ossim_uint8 thickness) + : ossimAnnotationObject(r, g, b, thickness), + theCenter(center), + theWidthHeight(widthHeight), + theFillEnabled(enableFill), + theBoundingRect(0,0,0,0) +{ + computeBoundingRect(); +} + +ossimAnnotationEllipseObject::ossimAnnotationEllipseObject( + const ossimAnnotationEllipseObject& rhs) + : + theCenter(rhs.theCenter), + theWidthHeight(rhs.theWidthHeight), + theFillEnabled(rhs.theFillEnabled), + theBoundingRect(rhs.theBoundingRect) +{ +} + +ossimObject* ossimAnnotationEllipseObject::dup()const +{ + return new ossimAnnotationEllipseObject(*this); +} + +ossimAnnotationEllipseObject::~ossimAnnotationEllipseObject() +{ +} + +void ossimAnnotationEllipseObject::applyScale(double x, double y) +{ + theCenter.x *= x; + theCenter.y *= y; + theWidthHeight.x *= x; + theWidthHeight.y *= y; + theBoundingRect *= ossimDpt(x,y); +} + + + +void ossimAnnotationEllipseObject::draw(ossimRgbImage& anImage)const +{ + anImage.setDrawColor(theRed, theGreen, theBlue); + anImage.setThickness(theThickness); + + if(theBoundingRect.intersects(anImage.getImageData()->getImageRectangle())) + { + if(theFillEnabled) + { +// anImage.drawFilledArc(irint(theCenter.x), +// irint(theCenter.y), +// irint(theWidthHeight.x), +// irint(theWidthHeight.y), +// 0, +// 360); + anImage.drawFilledArc((int)(theCenter.x), + (int)(theCenter.y), + (int)(theWidthHeight.x), + (int)(theWidthHeight.y), + 0, + 360); + } + else + { +// anImage.drawArc(irint(theCenter.x), +// irint(theCenter.y), +// irint(theWidthHeight.x), +// irint(theWidthHeight.y), +// 0, +// 360); + anImage.drawArc((int)(theCenter.x), + (int)(theCenter.y), + (int)(theWidthHeight.x), + (int)(theWidthHeight.y), + 0, + 360); + } + } +} + +bool ossimAnnotationEllipseObject::intersects(const ossimDrect& rect)const +{ + return rect.intersects(theBoundingRect); +} + +ossimAnnotationObject* ossimAnnotationEllipseObject::getNewClippedObject( + const ossimDrect& rect)const +{ + if(intersects(rect)) + { + return (ossimAnnotationObject*)dup(); + } + + return (ossimAnnotationEllipseObject*)NULL; +} + +std::ostream& ossimAnnotationEllipseObject::print(std::ostream& out)const +{ + ossimAnnotationObject::print(out); + out << endl; + out << "ellipse_center: " << theCenter << endl + << "ellipse_height: " << theWidthHeight.y << endl + << "ellipse_width: " << theWidthHeight.x << endl + << "fill_enabled: " << theFillEnabled << endl + << "ellipse_bounding_rect: " << theBoundingRect; + return out; +} + +void ossimAnnotationEllipseObject::getBoundingRect(ossimDrect& rect)const +{ + rect = theBoundingRect; +} + +void ossimAnnotationEllipseObject::computeBoundingRect() +{ + theBoundingRect = ossimDrect(theCenter.x - theWidthHeight.x, + theCenter.y - theWidthHeight.y, + theCenter.x + theWidthHeight.x, + theCenter.y + theWidthHeight.y); +} + +bool ossimAnnotationEllipseObject::isPointWithin(const ossimDpt& point)const +{ + return theBoundingRect.pointWithin(point); +} + +void ossimAnnotationEllipseObject::setCenterWidthHeight(const ossimDpt& center, + const ossimDpt& widthHeight) +{ + theCenter = center; + theWidthHeight = widthHeight; + + computeBoundingRect(); +} + +void ossimAnnotationEllipseObject::setFill(bool enabled) +{ + theFillEnabled = enabled; +} + +bool ossimAnnotationEllipseObject::getFill() const +{ + return theFillEnabled; +} + +bool ossimAnnotationEllipseObject::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + return ossimAnnotationObject::saveState(kwl, prefix); +} + +bool ossimAnnotationEllipseObject::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + return ossimAnnotationObject::loadState(kwl, prefix); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationEllipseObject.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationEllipseObject.h new file mode 100644 index 0000000000..742418465e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationEllipseObject.h @@ -0,0 +1,75 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See LICENSE.txt file in the top level directory. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimAnnotationEllipseObject.h,v 1.12 2005/12/07 19:08:55 dburken Exp $ +#ifndef ossimAnnotationEllipseObject_HEADER +#define ossimAnnotationEllipseObject_HEADER + +#include <imaging/annotation/ossimAnnotationObject.h> + +class OSSIMDLLEXPORT ossimAnnotationEllipseObject : public ossimAnnotationObject +{ +public: + ossimAnnotationEllipseObject(const ossimDpt& center = ossimDpt(0,0), + const ossimDpt& widthHeight = ossimDpt(1,1), + bool enableFill = false, + ossim_uint8 r = 255, + ossim_uint8 g = 255, + ossim_uint8 b = 255, + ossim_uint8 thickness = 1); + ossimAnnotationEllipseObject(const ossimAnnotationEllipseObject& rhs); + + virtual ossimObject* dup()const; + + virtual ~ossimAnnotationEllipseObject(); + + virtual void applyScale(double x, double y); + + virtual void draw(ossimRgbImage& anImage)const; + + virtual bool intersects(const ossimDrect& rect)const; + + virtual ossimAnnotationObject* getNewClippedObject( + const ossimDrect& rect)const; + + virtual std::ostream& print(std::ostream& out)const; + virtual void getBoundingRect(ossimDrect& rect)const; + virtual void computeBoundingRect(); + /*! + */ + virtual bool isPointWithin(const ossimDpt& imagePoint)const; + virtual void setCenterWidthHeight(const ossimDpt& center, + const ossimDpt& widthHeight); + virtual void setFill(bool enabled); + + /** @return theFillEnabled flag. */ + virtual bool getFill() const; + + /** + * Saves the current state of this object. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +protected: + ossimDpt theCenter; + ossimDpt theWidthHeight; + bool theFillEnabled; + ossimDrect theBoundingRect; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationFontObject.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationFontObject.cpp new file mode 100644 index 0000000000..9fc70658dd --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationFontObject.cpp @@ -0,0 +1,397 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimAnnotationFontObject.cpp,v 1.14 2005/12/09 21:53:22 dburken Exp $ + +#include <imaging/annotation/ossimAnnotationFontObject.h> +#include <fonts/factory/ossimFontFactoryRegistry.h> + +RTTI_DEF1(ossimAnnotationFontObject, "ossimAnnotationFontObject", ossimAnnotationObject); + +ossimAnnotationFontObject::ossimAnnotationFontObject() + :ossimAnnotationObject(), + theFont(ossimFontFactoryRegistry::instance()->getDefaultFont()), + theOwnsFontFlag(false), + theCenterPosition(0,0), + theString(""), + theRotation(0.0), + theHorizontalScale(0.0), + theVerticalScale(0.0), + theHorizontalShear(0.0), + theVerticalShear(0.0) +{ + setFontInfo(); + theBoundingRect.makeNan(); +} + +ossimAnnotationFontObject::ossimAnnotationFontObject(const ossimIpt& upperLeft, + const ossimString& s, + const ossimIpt& pixelSize, + double rotation, + const ossimDpt& scale, + const ossimDpt& shear, + unsigned char r, + unsigned char g, + unsigned char b) + :ossimAnnotationObject(r,g,b), + theFont(ossimFontFactoryRegistry::instance()->getDefaultFont()), + theOwnsFontFlag(false), + theString(s), + thePixelSize(pixelSize), + theRotation(rotation), + theHorizontalScale(scale.x), + theVerticalScale(scale.y), + theHorizontalShear(shear.x), + theVerticalShear(shear.y) +{ + setFontInfo(); + if (theFont) + { + theFont->getBoundingBox(theBoundingRect); + } + theBoundingRect += upperLeft; + theCenterPosition = theBoundingRect.midPoint(); +} + +ossimAnnotationFontObject::ossimAnnotationFontObject(const ossimAnnotationFontObject& rhs) + :ossimAnnotationObject(rhs), + theCenterPosition(rhs.theCenterPosition), + theString(rhs.theString), + thePixelSize(rhs.thePixelSize), + theRotation(rhs.theRotation), + theHorizontalScale(rhs.theHorizontalScale), + theVerticalScale(rhs.theVerticalScale), + theHorizontalShear(rhs.theHorizontalShear), + theVerticalShear(rhs.theVerticalShear), + theBoundingRect(rhs.theBoundingRect) +{ + if(rhs.theOwnsFontFlag&&theFont) + { + theFont = (ossimFont*)rhs.theFont->dup(); + } + else + { + theFont = rhs.theFont; + } + + setFontInfo(); +} + + +ossimAnnotationFontObject::~ossimAnnotationFontObject() +{ + if(theFont&&theOwnsFontFlag) + { + delete theFont; + theFont = NULL; + theOwnsFontFlag = false; + } + else + { + theFont = NULL; + theOwnsFontFlag = false; + } +} + +void ossimAnnotationFontObject::draw(ossimRgbImage& anImage)const +{ + if(theBoundingRect.hasNans()) + { + return; + } + if (!theFont) + { + return; + } + + if(!thePixelSize.x || !thePixelSize.y) + { + return; // (DAH) we have to have some demension to write! + } + + ossimRefPtr<ossimImageData> destination = anImage.getImageData(); + + if(destination.valid()) + { + ossimIrect destRect = anImage.getImageData()->getImageRectangle(); + + ossimIpt shift(-theBoundingRect.ul().x, + -theBoundingRect.ul().y); + + destRect += shift; + ossimIrect boundingRect = theBoundingRect + shift; + + if(boundingRect.intersects(destRect)) + { + setFontInfo(); + + ossimIrect fontBufferRect; + ossimIrect boundingFontBox; + + theFont->setClippingBox(destRect); + theFont->getBoundingBox(boundingFontBox); + + const ossim_uint8* srcBuf = theFont->rasterize(); + if (!srcBuf) + { + return; + } + + theFont->getBufferRect(fontBufferRect); + + ossimIrect clipRect = boundingRect.clipToRect(fontBufferRect); + + long clipHeight = clipRect.height(); + long clipWidth = clipRect.width(); + + long destinationOffset = (long)(((clipRect.ul().y - destRect.ul().y)* destRect.width()) + + (clipRect.ul().x - destRect.ul().x)); + long fontBufferOffset = (long)(((clipRect.ul().y - fontBufferRect.ul().y)*fontBufferRect.width()) + + (clipRect.ul().x - fontBufferRect.ul().x)); + + + long destinationIndex = destinationOffset; + long srcIndex = fontBufferOffset; + long num_bands = destination->getNumberOfBands(); + ossim_int32 s_width = (ossim_int32)fontBufferRect.width(); + ossim_int32 d_width = (ossim_int32)destRect.width(); + + num_bands = num_bands > 3? 3:num_bands; + + unsigned char colorArray[3]; + long band = 0; + colorArray[0] = theRed; + colorArray[1] = theGreen; + colorArray[2] = theBlue; + ossim_uint8** destBuf = new ossim_uint8*[num_bands]; + for(band = 0; band < num_bands;++band) + { + destBuf[band] = static_cast<ossim_uint8*>(destination->getBuf(band)); + if (!destBuf[band]) + { + delete [] destBuf; + return; + } + } + + for(long line = 0; line < clipHeight; ++line) + { + for(long col = 0; col < clipWidth; ++col) + { + if(srcBuf[srcIndex + col]) + { + for (band=0; band<num_bands; ++band) + { + *(destBuf[band] + destinationIndex + col) = colorArray[band]; + } + } + } + srcIndex += s_width; + destinationIndex += d_width; + } + delete [] destBuf; + } + } +} + +std::ostream& ossimAnnotationFontObject::print(std::ostream& out)const +{ + if(theFont) + { + out << "Family: " << theFont->getFamilyName() << endl + << "Style: " << theFont->getStyleName() << endl; + } + out << "String: " << theString << endl + << "Center Position: " << theCenterPosition << endl + << "Rotation: " << theRotation << endl + << "Horizontal shear: " << theHorizontalShear << endl + << "Vertical shear: " << theVerticalShear << endl + << "Vertical scale: " << theVerticalScale << endl + << "Horizontal scale: " << theHorizontalScale << endl + << "Bounding rect: " << theBoundingRect << endl; + return out; +} + +void ossimAnnotationFontObject::getBoundingRect(ossimDrect& rect)const +{ + rect = theBoundingRect; +} + +void ossimAnnotationFontObject::computeBoundingRect() +{ + setFontInfo(); + if(theFont) + { + ossimIrect textRect; + theFont->getBoundingBox(textRect); + ossim_int32 w = textRect.width(); + ossim_int32 h = textRect.height(); + ossim_int32 ulx = theCenterPosition.x - w/2; + ossim_int32 uly = theCenterPosition.y - h/2; + theBoundingRect = ossimIrect(ulx, + uly, + ulx + w - 1, + uly + h - 1); + } +} + +bool ossimAnnotationFontObject::isPointWithin(const ossimDpt& imagePoint)const +{ + return theBoundingRect.pointWithin(imagePoint); +} + +void ossimAnnotationFontObject::setFont(ossimFont* font, + bool ownsFontFlag) +{ + if(theOwnsFontFlag) + { + delete theFont; + theFont = (ossimFont*)NULL; + } + theFont = font; + theOwnsFontFlag = ownsFontFlag; + + if(!theFont) + { + theFont = ossimFontFactoryRegistry::instance()->getDefaultFont(); + theOwnsFontFlag = false; + } +} + +void ossimAnnotationFontObject::setPositionCenter(const ossimIpt& position) +{ + theCenterPosition = position; + computeBoundingRect(); +} + +void ossimAnnotationFontObject::setFontInfo()const +{ + if(theFont) + { + theFont->setString(theString); + theFont->setRotation(theRotation); + theFont->setScale(theHorizontalScale, theVerticalScale); + theFont->setHorizontalVerticalShear(theHorizontalShear, theVerticalShear); + theFont->setPixelSize(thePixelSize.x, + thePixelSize.y); + } +} + +void ossimAnnotationFontObject::setString(const ossimString& s) +{ + theString = s; +} + +ossimString ossimAnnotationFontObject::getString()const +{ + return theString; +} + +ossimAnnotationObject* ossimAnnotationFontObject::getNewClippedObject(const ossimDrect& rect)const +{ + if(intersects(rect)) + { + return (ossimAnnotationObject*)dup(); + } + + return (ossimAnnotationObject*)NULL; +} + +bool ossimAnnotationFontObject::intersects(const ossimDrect& rect)const +{ + return rect.intersects(theBoundingRect); +} + +void ossimAnnotationFontObject::setPointSize(const ossimIpt& size) +{ + thePixelSize = size; + setFontInfo(); + if (theFont) + { + theFont->getBoundingBox(theBoundingRect); + } + theBoundingRect += (theCenterPosition - theBoundingRect.midPoint()); + theCenterPosition = theBoundingRect.midPoint(); +} + +void ossimAnnotationFontObject::setRotation(double rotation) +{ + theRotation = rotation; + setFontInfo(); + if (theFont) + { + theFont->getBoundingBox(theBoundingRect); + } + theBoundingRect += (theCenterPosition - theBoundingRect.midPoint()); + theCenterPosition = theBoundingRect.midPoint(); +} + +void ossimAnnotationFontObject::setScale(const ossimDpt& scale) +{ + theHorizontalScale = scale.x; + theVerticalScale = scale.y; + setFontInfo(); + if (theFont) + { + theFont->getBoundingBox(theBoundingRect); + } + theBoundingRect += (theCenterPosition - theBoundingRect.midPoint()); + theCenterPosition = theBoundingRect.midPoint(); +} + +void ossimAnnotationFontObject::setShear(const ossimDpt& shear) +{ + theHorizontalShear = shear.x; + theVerticalShear = shear.y; + setFontInfo(); + if (theFont) + { + theFont->getBoundingBox(theBoundingRect); + } + theBoundingRect += (theCenterPosition - theBoundingRect.midPoint()); + theCenterPosition = theBoundingRect.midPoint(); +} + +void ossimAnnotationFontObject::setGeometryInformation(const ossimFontInformation& info) +{ + thePixelSize = info.thePointSize; + theRotation = info.theRotation; + theHorizontalScale = info.theScale.x; + theVerticalScale = info.theScale.y; + theHorizontalShear = info.theShear.x; + theVerticalShear = info.theShear.y; + + setFontInfo(); + if (theFont) + { + theFont->getBoundingBox(theBoundingRect); + } + theBoundingRect += (theCenterPosition - theBoundingRect.midPoint()); + theCenterPosition = theBoundingRect.midPoint(); +} + +void ossimAnnotationFontObject::applyScale(double x, double y) +{ + theCenterPosition.x = irint(theCenterPosition.x *x); + theCenterPosition.y = irint(theCenterPosition.x *y); + theHorizontalScale *= x; + theVerticalScale *= y; + + setFontInfo(); + if (theFont) + { + theFont->getBoundingBox(theBoundingRect); + } + theBoundingRect += (theCenterPosition - theBoundingRect.midPoint()); + theCenterPosition = theBoundingRect.midPoint(); +} + +ossimObject* ossimAnnotationFontObject::dup()const +{ + return new ossimAnnotationFontObject(*this); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationFontObject.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationFontObject.h new file mode 100644 index 0000000000..6394dab77c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationFontObject.h @@ -0,0 +1,85 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimAnnotationFontObject.h,v 1.13 2005/12/09 21:51:47 dburken Exp $ +#ifndef ossimAnnotationFontObject_HEADER +#define ossimAnnotationFontObject_HEADER +#include <imaging/annotation/ossimAnnotationObject.h> +#include <base/common/ossimFontInformation.h> +#include <base/data_types/ossimIpt.h> +#include <fonts/ossimFont.h> + +/** + * Class to draw fonts onto an image. + * @note This class requires a font path to be set for the factory: + * "ossimFontFactoryRegistry". You should set at a minimum the keyword + * "font.dir1" in your ossim_prefernces file. + * Example from a RedHat 9.0 system: + * font.dir1: /usr/share/fonts/default/Type1 + * + * @see file ossim/etc/templates/ossim_prefernces_template + */ +class OSSIMDLLEXPORT ossimAnnotationFontObject : public ossimAnnotationObject +{ + +public: + friend class ossimGeoAnnotationFontObject; + ossimAnnotationFontObject(); + ossimAnnotationFontObject(const ossimIpt& upperLeft, + const ossimString& s, + const ossimIpt& pixelSize = ossimIpt(12, 12), + double rotation = 0.0, + const ossimDpt& scale = ossimDpt(1.0, 1.0), + const ossimDpt& shear = ossimDpt(0.0,0.0), + unsigned char r=255, + unsigned char g=255, + unsigned char b=255); + ossimAnnotationFontObject(const ossimAnnotationFontObject& rhs); + + + virtual ~ossimAnnotationFontObject(); + + virtual ossimObject* dup()const; + + virtual void draw(ossimRgbImage& anImage)const; + virtual std::ostream& print(std::ostream& out)const; + virtual void getBoundingRect(ossimDrect& rect)const; + virtual void setString(const ossimString& s); + virtual ossimString getString()const; + virtual void computeBoundingRect(); + virtual ossimAnnotationObject* getNewClippedObject(const ossimDrect& rect)const; + virtual bool intersects(const ossimDrect& rect)const; + virtual bool isPointWithin(const ossimDpt& imagePoint)const; + virtual void setFont(ossimFont* font, + bool ownsFontFlag=true); + virtual void setPositionCenter(const ossimIpt& position); + virtual void setPointSize(const ossimIpt& size); + virtual void setRotation(double rotation); + virtual void setScale(const ossimDpt& scale); + virtual void setShear(const ossimDpt& shear); + virtual void setGeometryInformation(const ossimFontInformation& info); + virtual void applyScale(double x, double y); + +protected: + mutable ossimFont* theFont; + bool theOwnsFontFlag; + ossimIpt theCenterPosition; + ossimString theString; + ossimIpt thePixelSize; + double theRotation; + double theHorizontalScale; + double theVerticalScale; + double theHorizontalShear; + double theVerticalShear; + ossimIrect theBoundingRect; + + void setFontInfo()const; +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationGdBitmapFont.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationGdBitmapFont.cpp new file mode 100644 index 0000000000..6fe84b3dfe --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationGdBitmapFont.cpp @@ -0,0 +1,195 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimAnnotationGdBitmapFont.cpp,v 1.11 2004/05/23 17:49:36 dburken Exp $ +#include "ossimAnnotationGdBitmapFont.h" +#include "imaging/ossimRgbImage.h" +#include "base/common/ossimCommon.h" + +#include "gdfonts.inc" +#include "gdfontl.inc" +#include "gdfontg.inc" +#include "gdfontmb.inc" +#include "gdfontt.inc" + +ossimAnnotationGdBitmapFont::ossimAnnotationGdBitmapFont(const ossimDpt& position, + const ossimString &text, + ossimGdFontPtr font, + unsigned char r, + unsigned char g, + unsigned char b, + long thickness) + :ossimAnnotationObject(r, g, b, thickness), + theFontPtr(font), + theText(text), + thePosition(position) +{ + computeBoundingRect(); +} + +ossimAnnotationGdBitmapFont::ossimAnnotationGdBitmapFont(const ossimAnnotationGdBitmapFont& rhs) + : ossimAnnotationObject(rhs), + theFontPtr(rhs.theFontPtr), + theText(rhs.theText), + theBoundingRect(rhs.theBoundingRect), + thePosition(rhs.thePosition) +{ +} + +ossimAnnotationGdBitmapFont::~ossimAnnotationGdBitmapFont() +{ +} + +void ossimAnnotationGdBitmapFont::getBoundingRect(ossimDrect& rect)const +{ + rect = theBoundingRect; +} + +void ossimAnnotationGdBitmapFont::applyScale(double x, double y) +{ + thePosition.x *= x; + thePosition.y *= y; + + theBoundingRect *= ossimDpt(x, y); +} + +void ossimAnnotationGdBitmapFont::draw(ossimRgbImage& anImage)const +{ + if(!theFontPtr|| + !anImage.getImageData()) + { + return; + } + ossimDpt origin = anImage.getImageData()->getOrigin(); + + ossimDrect rect = anImage.getImageData()->getImageRectangle(); + + if(theBoundingRect.intersects(rect)) + { + anImage.setDrawColor(theRed, theGreen, theBlue); + ossimDpt position(thePosition.x - origin.x, + thePosition.y - origin.y); + for(ossim_uint32 character = 0; character < theText.size(); ++character) + { + long charOffset = theText[(int)character]; + + // we need to shift the offset to a positive value. + // if it goes negative we just add 256 to the value. + if(charOffset < 0) + { + charOffset += 256; + } + // get the starting offset to the bitmap + long offset = charOffset*theFontPtr->w*theFontPtr->h; + for(long row = 0; row < theFontPtr->h; ++row) + { + for(long col = 0; col < theFontPtr->w; ++col) + { + if(theFontPtr->data[(int)offset]) + { + anImage.slowPlotPixel(irint(position.x + col), + irint(position.y + row), + theRed, + theGreen, + theBlue); + } + ++offset; + } + } + position.x += theFontPtr->w; + } + } +} + +ossimAnnotationObject* ossimAnnotationGdBitmapFont::getNewClippedObject(const ossimDrect& rect)const +{ + ossimAnnotationGdBitmapFont* result = (ossimAnnotationGdBitmapFont*)NULL; + + if(intersects(rect)) + { + result = (ossimAnnotationGdBitmapFont*)dup(); + } + + return result; +} + +std::ostream& ossimAnnotationGdBitmapFont::print(std::ostream& out)const +{ + out << "text_value: " << theText << endl + << "text_bouding_rect: " << theBoundingRect << endl + << "text_position: " << thePosition << endl; + return out; +} + +void ossimAnnotationGdBitmapFont::computeBoundingRect() +{ + if(theFontPtr) + { + theBoundingRect = ossimDrect(thePosition.x, + thePosition.y, + thePosition.x + theText.size()*theFontPtr->w, + thePosition.y + theFontPtr->h); + } +} + +void ossimAnnotationGdBitmapFont::setFont(ossimGdFontPtr font) +{ + theFontPtr = font; +} + +void ossimAnnotationGdBitmapFont::setText(const ossimString& text) +{ + theText = text; + computeBoundingRect(); +} + +void ossimAnnotationGdBitmapFont::setUpperLeftText(const ossimDpt& upperLeft, + const ossimString& text) +{ + setText(text); + setUpperLeftTextPosition(upperLeft); +} + +void ossimAnnotationGdBitmapFont::setUpperLeftTextPosition(const ossimDpt& position) +{ + thePosition = position; + computeBoundingRect(); +} + +void ossimAnnotationGdBitmapFont::setCenterText(const ossimDpt& upperLeft, + const ossimString& text) +{ + setText(text); + setCenterTextPosition(upperLeft); +} + +void ossimAnnotationGdBitmapFont::setCenterTextPosition(const ossimDpt& position) +{ + thePosition.x = position.x - theBoundingRect.width()/2.0; + thePosition.y = position.y - theBoundingRect.height()/2.0; + computeBoundingRect(); +} + +bool ossimAnnotationGdBitmapFont::isPointWithin(const ossimDpt& imagePoint)const +{ + return theBoundingRect.pointWithin(imagePoint); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationGdBitmapFont.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationGdBitmapFont.h new file mode 100644 index 0000000000..72a1ae3b3a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationGdBitmapFont.h @@ -0,0 +1,137 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimAnnotationGdBitmapFont.h,v 1.10 2004/05/23 17:49:36 dburken Exp $ +#ifndef ossimAnnotationGdBitmapFont_HEADER +#define ossimAnnotationGdBitmapFont_HEADER +#include "ossimAnnotationObject.h" +#include "ossimGdFont.h" +#include "ossimGdFontExterns.h" +#include "base/data_types/ossimString.h" + +/*! + * This is a class that will have hardcoded + * bitmap fonts. These fonts will be from + * the gd library. + */ +class OSSIMDLLEXPORT ossimAnnotationGdBitmapFont : public ossimAnnotationObject +{ +public: + ossimAnnotationGdBitmapFont(const ossimDpt& position=ossimDpt(0,0), + const ossimString &text=ossimString(""), + ossimGdFontPtr font = ossimGdFontLarge, + unsigned char r = 255, + unsigned char g = 255, + unsigned char b = 255, + long thickness = 1); + ossimAnnotationGdBitmapFont(const ossimAnnotationGdBitmapFont& rhs); + virtual ~ossimAnnotationGdBitmapFont(); + + virtual ossimObject* dup()const + { + return new ossimAnnotationGdBitmapFont(*this); + } + + virtual void applyScale(double x, double y); + + /*! + * Will draw the bitmap to the screen. + */ + virtual void draw(ossimRgbImage& anImage)const; + virtual bool intersects(const ossimDrect& rect)const + { + return rect.intersects(theBoundingRect); + } + virtual ossimAnnotationObject* getNewClippedObject(const ossimDrect& rect)const; + + virtual std::ostream& print(std::ostream& out)const; + + /*! + * Will retrieve the bound rectangle for this + * object. + */ + virtual void getBoundingRect(ossimDrect& rect)const; + + /*! + * will compute the bounding rectangle. + */ + virtual void computeBoundingRect(); + + /*! + * Sets the current bitmap font to use. + */ + virtual void setFont(ossimGdFontPtr font); + + /*! + * Set's the text string to render. + */ + virtual void setText(const ossimString& text); + + /*! + * Set's the text string to render. This + * will assume that the x,y passed in is + * suppose to be the center. We will compute + * the upper left corner from this + */ + virtual void setCenterText(const ossimDpt& center, + const ossimString& text); + + /*! + * Set's the text string to render. This + * will assume that the x,y passed in is + * suppose to be the upper left. + */ + virtual void setUpperLeftText(const ossimDpt& upperLeft, + const ossimString& text); + + /*! + * Sets the center position of the string. + * will use this value to compute the actual + * origin of upper left corner of the first + * character. Make sure you have the text + * set before you call this method + */ + virtual void setCenterTextPosition(const ossimDpt& position); + + /*! + * The actual upper left corner of the character. + */ + virtual void setUpperLeftTextPosition(const ossimDpt& position); + + /*! + * Will determine if the point is within the font + */ + virtual bool isPointWithin(const ossimDpt& imagePoint)const; + +protected: + ossimGdFontPtr theFontPtr; + ossimString theText; + ossimDrect theBoundingRect; + + /*! + * This position is suppose to be the upperleft + * corner of the first character in the string + */ + ossimDpt thePosition; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationLineObject.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationLineObject.cpp new file mode 100644 index 0000000000..604e0f840d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationLineObject.cpp @@ -0,0 +1,183 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimAnnotationLineObject.cpp,v 1.10 2005/02/11 15:07:30 dburken Exp $ + +#include <imaging/annotation/ossimAnnotationLineObject.h> +#include <imaging/ossimRgbImage.h> + +RTTI_DEF1(ossimAnnotationLineObject, + "ossimAnnotationLineObject", + ossimAnnotationObject) + +ossimAnnotationLineObject::ossimAnnotationLineObject() + :ossimAnnotationObject(), + theStart(0,0), + theEnd(0,0), + theBoundingRect(0,0,0,0) +{ +} + +ossimAnnotationLineObject::ossimAnnotationLineObject(const ossimIpt& start, + const ossimIpt& end, + unsigned char r, + unsigned char g, + unsigned char b, + long thickness) + :ossimAnnotationObject(r, g, b, thickness), + theStart(start), + theEnd(end) +{ + computeBoundingRect(); +} + +ossimAnnotationLineObject::ossimAnnotationLineObject(long x1, + long y1, + long x2, + long y2, + unsigned char r, + unsigned char g, + unsigned char b, + long thickness) + :ossimAnnotationObject(r, g, b, thickness), + theStart(x1, y1), + theEnd(x2, y2) +{ + computeBoundingRect(); +} + +ossimAnnotationLineObject::ossimAnnotationLineObject(const ossimAnnotationLineObject& rhs) + :ossimAnnotationObject(rhs), + theStart(rhs.theStart), + theEnd(rhs.theEnd), + theBoundingRect(rhs.theBoundingRect) +{ +} + +ossimObject* ossimAnnotationLineObject::dup()const +{ + return new ossimAnnotationLineObject(*this); +} + +void ossimAnnotationLineObject::applyScale(double x, double y) +{ + theStart.x = irint(theStart.x*x); + theStart.y = irint(theStart.y*y); + theEnd.x = irint(theEnd.x*x); + theEnd.y = irint(theEnd.y*y); +} + +ossimAnnotationObject* ossimAnnotationLineObject::getNewClippedObject(const ossimDrect& rect)const +{ + ossimAnnotationLineObject* result = (ossimAnnotationLineObject*)NULL; + ossimDpt start = theStart; + ossimDpt end = theEnd; + + if(rect.clip(start, end)) + { + result = (ossimAnnotationLineObject*)dup(); + result->setLine(start, end); + } + + return result; +} + +bool ossimAnnotationLineObject::intersects(const ossimDrect& rect)const +{ + ossimDpt start = theStart; + ossimDpt end = theEnd; + + return rect.clip(start, end); +} + +void ossimAnnotationLineObject::draw(ossimRgbImage& anImage)const +{ + if(anImage.getImageData().valid()) + { + anImage.setDrawColor(theRed, theGreen, theBlue); + anImage.setThickness(theThickness); + ossimDrect imageRect = anImage.getImageData()->getImageRectangle(); + ossimDpt start = theStart; + ossimDpt end = theEnd; + + if(anImage.getImageData().valid()) + { + // we need to extend it by a couple of pixels since + // if a pixel lies on the edge and then another pixel is just off + // the edge we will get a stair step and so for several pixels + // the line might be inside the image rectangle but the clip + // algorithm will only draw 1 pixel since it thinks the first + // point is inside and the second point is outside and will + // execute the clip algorithm keeping only the first + // point. + ossimDrect clipRect(imageRect.ul().x - 10, + imageRect.ul().y - 10, + imageRect.lr().x + 10, + imageRect.lr().y + 10); + // now we can draw. + if(clipRect.clip(start, end)) + { + anImage.drawLine(ossimIpt((int)start.x, + (int)start.y), + ossimIpt((int)end.x, + (int)end.y)); + } + } + } +} + +std::ostream& ossimAnnotationLineObject::print(std::ostream& out)const +{ + out << "line_start: " << theStart << endl + << "line_end: " << theEnd << endl + << "bounding_rect: " << theBoundingRect << endl; + return out; +} + +void ossimAnnotationLineObject::getBoundingRect(ossimDrect& rect)const +{ + rect = theBoundingRect; +} + +void ossimAnnotationLineObject::computeBoundingRect() +{ + vector<ossimDpt> pts(2); + + pts[0] = theStart; + pts[1] = theEnd; + + theBoundingRect = ossimDrect(pts); +} + +void ossimAnnotationLineObject::setLine(const ossimDpt& start, + const ossimDpt& end) +{ + theStart = start; + theEnd = end; + computeBoundingRect(); +} +void ossimAnnotationLineObject::getLine(ossimDpt& start, ossimDpt& end) +{ + start = theStart; + end = theEnd; +} + +bool ossimAnnotationLineObject::isPointWithin(const ossimDpt& point)const +{ + if(theBoundingRect.pointWithin(point)) + { + // we will use the implicit form of a line to determine if the point is + // on the line. For now we will just return true if it is within the + // bounding rect. + return true; + } + + return false; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationLineObject.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationLineObject.h new file mode 100644 index 0000000000..d483e90b35 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationLineObject.h @@ -0,0 +1,76 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimAnnotationLineObject.h,v 1.12 2004/05/23 17:49:37 dburken Exp $ +#ifndef ossimAnnotationLineObject_HEADER +#define ossimAnnotationLineObject_HEADER +#include "ossimAnnotationObject.h" +#include "base/data_types/ossimIpt.h" + +class OSSIMDLLEXPORT ossimAnnotationLineObject : public ossimAnnotationObject +{ +public: + ossimAnnotationLineObject(); + ossimAnnotationLineObject(const ossimIpt& start, + const ossimIpt& end, + unsigned char r=255, + unsigned char g=255, + unsigned char b=255, + long thickness=1); + + ossimAnnotationLineObject(long x1, + long y1, + long x2, + long y2, + unsigned char r=255, + unsigned char g=255, + unsigned char b=255, + long thickness=1); + + ossimAnnotationLineObject(const ossimAnnotationLineObject& rhs); + + virtual ossimObject* dup()const; + + virtual void applyScale(double x, double y); + + virtual ossimAnnotationObject* getNewClippedObject(const ossimDrect& rect)const; + + virtual bool intersects(const ossimDrect& rect)const; + + virtual void draw(ossimRgbImage& anImage)const; + virtual std::ostream& print(std::ostream& out)const; + virtual void getBoundingRect(ossimDrect& rect)const; + virtual bool isPointWithin(const ossimDpt& imagePoint)const; + virtual void computeBoundingRect(); + + void setLine(const ossimDpt& start, const ossimDpt& end); + void getLine(ossimDpt& start, ossimDpt& end); + +protected: + ossimIpt theStart; + ossimIpt theEnd; + ossimDrect theBoundingRect; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMapGridSource.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMapGridSource.h new file mode 100644 index 0000000000..75e273f322 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMapGridSource.h @@ -0,0 +1,14 @@ +#ifndef ossimAnnotationMapGridSource_HEADER +#define ossimAnnotationMapGridSource_HEADER +#include "ossimAnnotationSource.h" + +class ossimAnnotationMapGridSource : public ossimAnnotationSource +{ +public: + ossimAnnotationMapGridSource(); + +protected: + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiEllipseObject.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiEllipseObject.cpp new file mode 100644 index 0000000000..c28f200576 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiEllipseObject.cpp @@ -0,0 +1,237 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimAnnotationMultiEllipseObject.cpp,v 1.5 2004/05/23 17:49:37 dburken Exp $ + +#include <imaging/annotation/ossimAnnotationMultiEllipseObject.h> + +ossimAnnotationMultiEllipseObject::ossimAnnotationMultiEllipseObject + (const std::vector<ossimDpt>& pointList, + const ossimDpt& widthHeight, + bool enableFill, + unsigned char r, + unsigned char g, + unsigned char b, + long thickness) + : + ossimAnnotationObject(r, g, b, thickness), + thePointList(pointList), + theWidthHeight(widthHeight), + theFillFlag(enableFill) +{ + computeBoundingRect(); +} + +ossimAnnotationMultiEllipseObject::ossimAnnotationMultiEllipseObject + (const ossimDpt& widthHeight, + bool enableFill, + unsigned char r, + unsigned char g, + unsigned char b, + long thickness) + : + ossimAnnotationObject(r, g, b, thickness), + theWidthHeight(widthHeight), + theFillFlag(enableFill) +{ + theBoundingRect.makeNan(); +} + +ossimAnnotationMultiEllipseObject::ossimAnnotationMultiEllipseObject(const ossimAnnotationMultiEllipseObject& rhs) + :thePointList(rhs.thePointList), + theWidthHeight(rhs.theWidthHeight), + theFillFlag(rhs.theFillFlag), + theBoundingRect(rhs.theBoundingRect) +{ +} + +ossimObject* ossimAnnotationMultiEllipseObject::dup()const +{ + return new ossimAnnotationMultiEllipseObject(*this); +} + +ossimAnnotationMultiEllipseObject::~ossimAnnotationMultiEllipseObject() +{} + +ossimAnnotationObject* ossimAnnotationMultiEllipseObject::getNewClippedObject(const ossimDrect& rect)const +{ + ossimNotify(ossimNotifyLevel_WARN) + << "ossimAnnotationMultiEllipseObject::getNewClippedObject WARNING: Not implemented" + << std::endl; + return NULL; +} + +void ossimAnnotationMultiEllipseObject::applyScale(double x, double y) +{ + int i; + int upper = (int)thePointList.size(); + for(i = 0; i < upper; ++i) + { + thePointList[i].x *= x; + thePointList[i].y *= y; + } + theWidthHeight.x *= x; + theWidthHeight.y *= y; + + computeBoundingRect(); +} + +void ossimAnnotationMultiEllipseObject::draw(ossimRgbImage& anImage)const +{ + anImage.setDrawColor(theRed, theGreen, theBlue); + anImage.setThickness(theThickness); + ossimDrect imageRect = anImage.getImageData()->getImageRectangle(); + + if(theBoundingRect.intersects(imageRect)) + { + int i; + int upper = (int)thePointList.size(); + if(theFillFlag) + { + for(i = 0; i < upper; ++i) + { + ossimDpt tempPoint = thePointList[i]; + + ossimDrect tempRect(ossimDpt(tempPoint.x - theWidthHeight.x, + tempPoint.y - theWidthHeight.y), + ossimDpt(tempPoint.x + theWidthHeight.x, + tempPoint.y + theWidthHeight.y)); + if(tempRect.intersects(imageRect)) + { + anImage.drawFilledArc(irint(tempPoint.x), + irint(tempPoint.y), + irint(theWidthHeight.x), + irint(theWidthHeight.y), + 0, + 360); + } + } + } + else + { + for(i = 0; i < upper; ++i) + { + ossimDpt tempPoint = thePointList[i]; + + ossimDrect tempRect(ossimDpt(tempPoint.x - theWidthHeight.x, + tempPoint.y - theWidthHeight.y), + ossimDpt(tempPoint.x + theWidthHeight.x, + tempPoint.y + theWidthHeight.y)); + if(tempRect.intersects(imageRect)) + { + anImage.drawArc(irint(tempPoint.x), + irint(tempPoint.y), + irint(theWidthHeight.x), + irint(theWidthHeight.y), + 0, + 360); + } + } + } + } +} + +bool ossimAnnotationMultiEllipseObject::intersects(const ossimDrect& rect)const +{ + return rect.intersects(theBoundingRect); +} + +std::ostream& ossimAnnotationMultiEllipseObject::print(std::ostream& out)const +{ + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimAnnotionMultiEllipseObject::print NOT IMPLEMENTED" + << endl; + return out; +} + +void ossimAnnotationMultiEllipseObject::getBoundingRect(ossimDrect& rect)const +{ + rect = theBoundingRect; +} + +void ossimAnnotationMultiEllipseObject::computeBoundingRect() +{ + theBoundingRect.makeNan(); + + int i; + int upper = (int)thePointList.size(); + for(i = 0; i < upper; ++i) + { + ossimDpt tempPoint = thePointList[i]; + if(!tempPoint.hasNans()) + { + ossimDrect tempRect(ossimDpt(tempPoint.x - theWidthHeight.x, + tempPoint.y - theWidthHeight.y), + ossimDpt(tempPoint.x + theWidthHeight.x, + tempPoint.y + theWidthHeight.y)); + if(!theBoundingRect.hasNans()) + { + theBoundingRect.combine(tempRect); + } + else + { + theBoundingRect = tempRect; + } + } + } +} + +bool ossimAnnotationMultiEllipseObject::isPointWithin(const ossimDpt& imagePoint)const +{ + if(!theBoundingRect.hasNans()) + { + return theBoundingRect.pointWithin(imagePoint); + } + return false; +} + +void ossimAnnotationMultiEllipseObject::setFillFlag(bool flag) +{ + theFillFlag = flag; +} + +void ossimAnnotationMultiEllipseObject::resize(ossim_uint32 size) +{ + if(size) + { + thePointList.resize(size); + } + else + { + thePointList.clear(); + } +} + +void ossimAnnotationMultiEllipseObject::setWidthHeight(const ossimDpt& widthHeight) +{ + theWidthHeight = widthHeight; + computeBoundingRect(); +} + +ossimDpt& ossimAnnotationMultiEllipseObject::operator[](int i) +{ + return thePointList[i]; +} + +const ossimDpt& ossimAnnotationMultiEllipseObject::operator[](int i)const +{ + return thePointList[i]; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiEllipseObject.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiEllipseObject.h new file mode 100644 index 0000000000..e8bc5dfabd --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiEllipseObject.h @@ -0,0 +1,80 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimAnnotationMultiEllipseObject.h,v 1.6 2004/05/23 17:49:37 dburken Exp $ +#ifndef ossimAnnotationMultiEllipseObject_HEADER +#define ossimAnnotationMultiEllipseObject_HEADER +#include <imaging/annotation/ossimAnnotationObject.h> +#include <vector> + +class OSSIMDLLEXPORT ossimAnnotationMultiEllipseObject : public ossimAnnotationObject +{ +public: + ossimAnnotationMultiEllipseObject(const std::vector<ossimDpt>& pointList, + const ossimDpt& widthHeight = ossimDpt(1,1), + bool enableFill = false, + unsigned char r = 255, + unsigned char g = 255, + unsigned char b = 255, + long thickness = 1); + + ossimAnnotationMultiEllipseObject(const ossimDpt& widthHeight = ossimDpt(1,1), + bool enableFill = false, + unsigned char r = 255, + unsigned char g = 255, + unsigned char b = 255, + long thickness = 1); + + ossimAnnotationMultiEllipseObject(const ossimAnnotationMultiEllipseObject& rhs); + + ossimObject* dup()const; + + virtual ~ossimAnnotationMultiEllipseObject(); + + virtual ossimAnnotationObject* getNewClippedObject(const ossimDrect& rect)const; + virtual void applyScale(double x, double y); + virtual void draw(ossimRgbImage& anImage)const; + virtual bool intersects(const ossimDrect& rect)const; + virtual std::ostream& print(std::ostream& out)const; + virtual void getBoundingRect(ossimDrect& rect)const; + virtual void computeBoundingRect(); + /*! + */ + virtual bool isPointWithin(const ossimDpt& imagePoint)const; + + void setFillFlag(bool flag); + + void resize(ossim_uint32 size); + + virtual void setWidthHeight(const ossimDpt& widthHeight); + + ossimDpt& operator[](int i); + + const ossimDpt& operator[](int i)const; + +protected: + std::vector<ossimDpt> thePointList; + ossimDpt theWidthHeight; + bool theFillFlag; + ossimDrect theBoundingRect; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiLineObject.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiLineObject.cpp new file mode 100644 index 0000000000..9d25120b93 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiLineObject.cpp @@ -0,0 +1,191 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimAnnotationMultiLineObject.cpp,v 1.8 2005/02/11 15:07:30 dburken Exp $ +#include <imaging/annotation/ossimAnnotationMultiLineObject.h> + +RTTI_DEF1(ossimAnnotationMultiLineObject, + "ossimAnnotationMultiLineObject", + ossimAnnotationObject); + +void ossimAnnotationMultiLineObject::draw(ossimRgbImage& anImage)const +{ + if(anImage.getImageData().valid()) + { + anImage.setDrawColor(theRed, theGreen, theBlue); + anImage.setThickness(theThickness); + ossimDrect imageRect = anImage.getImageData()->getImageRectangle(); + + + + if(theBoundingRect.intersects(imageRect)) + { + // we need to extend it by a couple of pixels since + // if a pixel lies on the edge and then another pixel is just off + // the edge we will get a stair step and so for several pixels + // the line might be inside the image rectangle but the clip + // algorithm will only draw 1 pixel since it thinks the first + // point is inside and the second point is outside and will + // execute the clip algorithm keeping only the first + // point. + ossimDrect clipRect(imageRect.ul().x - 10, + imageRect.ul().y - 10, + imageRect.lr().x + 10, + imageRect.lr().y + 10); + + for(ossim_uint32 i = 0; i < thePolyLineList.size(); ++i) + { + const vector<ossimDpt>& vList = thePolyLineList[i].getVertexList(); + + if(vList.size() == 1) + { + anImage.drawLine(ossimIpt(vList[0]), + ossimIpt(vList[0])); + } + else + { + for(ossim_uint32 i2 = 0; i2 < (vList.size()-1); ++i2) + { + ossimDpt start = vList[i2]; + ossimDpt end = vList[i2+1]; + // now we can draw. + if(clipRect.clip(start, end)) + { + anImage.drawLine(ossimIpt((int)start.x, + (int)start.y), + ossimIpt((int)end.x, + (int)end.y)); + } + } + } + } + } + } +} + +bool ossimAnnotationMultiLineObject::intersects(const ossimDrect& rect)const +{ + + for(ossim_uint32 i = 0; i < thePolyLineList.size(); ++i) + { + if(thePolyLineList[i].isWithin(rect)) + { + return true; + } + } + return false; +} + + +void ossimAnnotationMultiLineObject::applyScale(double x, + double y) +{ + for(ossim_uint32 i=0; i < thePolyLineList.size(); ++i) + { + vector<ossimDpt>& vList = thePolyLineList[i].getVertexList(); + + for(ossim_uint32 i2 = 0; i2 < vList.size(); ++i2) + { + vList[i].x *= x; + vList[i].y *= y; + vList[i].x *= x; + vList[i].y *= y; + } + } + theBoundingRect *= ossimDpt(x, y); +} + +ossimAnnotationObject* ossimAnnotationMultiLineObject::getNewClippedObject(const ossimDrect& rect)const +{ + ossimAnnotationMultiLineObject* result = (ossimAnnotationMultiLineObject*)NULL; + + if(intersects(rect)) + { + vector<ossimPolyLine> lineList; + vector<ossimPolyLine> tempResult; + + ossimDrect clipRect(rect.ul().x - 10, + rect.ul().y - 10, + rect.lr().x + 10, + rect.lr().y + 10); + + for(ossim_uint32 i =0; i< thePolyLineList.size();++i) + { + if(thePolyLineList[i].clipToRect(tempResult, clipRect)) + { + lineList.insert(lineList.end(), + tempResult.begin(), + tempResult.end()); + } + } + + if(lineList.size() > 0) + { + result = new ossimAnnotationMultiLineObject(lineList, + theRed, + theGreen, + theBlue, + theThickness); + } + } + + return result; +} + +bool ossimAnnotationMultiLineObject::isPointWithin(const ossimDpt& imagePoint)const +{ + for(ossim_uint32 i=0; i < thePolyLineList.size(); ++i) + { + if(thePolyLineList[i].isPointWithin(imagePoint)) + { + return true; + } + + } + + return false; +} + +void ossimAnnotationMultiLineObject::computeBoundingRect() +{ + theBoundingRect.makeNan(); + + if(thePolyLineList.size() == 1) + { + theBoundingRect = thePolyLineList[0].getBoundingRect(); + } + else if(thePolyLineList.size() > 1) + { + for(ossim_uint32 i = 0; i < thePolyLineList.size(); ++i) + { + ossimDrect rect = thePolyLineList[i].getBoundingRect(); + if(theBoundingRect.hasNans()) + { + theBoundingRect = rect; + } + else if(!rect.hasNans()) + { + theBoundingRect = theBoundingRect.combine(rect); + } + } + } +} + +std::ostream& ossimAnnotationMultiLineObject::print(std::ostream& out)const +{ + ossimAnnotationObject::print(out); + + for(ossim_uint32 i = 0; i < thePolyLineList.size();++i) + { + out << thePolyLineList[i] << endl + <<"______________________________________"<<endl; + } + return out; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiLineObject.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiLineObject.h new file mode 100644 index 0000000000..7485bfa937 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiLineObject.h @@ -0,0 +1,102 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossimAnnotationMultiLineObject.h,v 1.5 2004/05/23 17:49:37 dburken Exp $ +#ifndef ossimAnnotationMultiLineObject_HEADER +#define ossimAnnotationMultiLineObject_HEADER +#include "ossimAnnotationObject.h" +#include "base/data_types/ossimIpt.h" +#include "base/data_types/ossimPolyLine.h" + +class OSSIMDLLEXPORT ossimAnnotationMultiLineObject : public ossimAnnotationObject +{ +public: + ossimAnnotationMultiLineObject(); + ossimAnnotationMultiLineObject(const std::vector<ossimPolyLine>& lineList, + unsigned char r=255, + unsigned char g=255, + unsigned char b=255, + long thickness=1) + :ossimAnnotationObject(r, g, b, thickness), + thePolyLineList(lineList) + { + computeBoundingRect(); + } + + ossimAnnotationMultiLineObject(const ossimPolyLine& lineList, + unsigned char r=255, + unsigned char g=255, + unsigned char b=255, + long thickness=1) + :ossimAnnotationObject(r, g, b, thickness) + { + thePolyLineList.push_back(lineList); + computeBoundingRect(); + } + + + ossimAnnotationMultiLineObject(const ossimAnnotationMultiLineObject& rhs) + :ossimAnnotationObject(rhs), + thePolyLineList(rhs.thePolyLineList), + theBoundingRect(rhs.theBoundingRect) + { + } + + virtual ossimObject* dup()const + { + return new ossimAnnotationMultiLineObject(*this); + } + + virtual void applyScale(double x, + double y); + virtual ossimAnnotationObject* getNewClippedObject(const ossimDrect& rect)const; + virtual bool intersects(const ossimDrect& rect)const; + virtual void draw(ossimRgbImage& anImage)const; + virtual std::ostream& print(std::ostream& out)const; + virtual void getBoundingRect(ossimDrect& rect)const + { + rect = theBoundingRect; + } + virtual bool isPointWithin(const ossimDpt& imagePoint)const; + virtual void computeBoundingRect(); + + virtual const vector<ossimPolyLine>& getPolyLineList()const + { + return thePolyLineList; + } + + virtual vector<ossimPolyLine>& getPolyLineList() + { + return thePolyLineList; + } + virtual void setPolyLine(const ossimPolyLine& line) + { + thePolyLineList.clear(); + thePolyLineList.push_back(line); + } +protected: + vector<ossimPolyLine> thePolyLineList; + ossimDrect theBoundingRect; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiPolyLineObject.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiPolyLineObject.cpp new file mode 100644 index 0000000000..5b9066fccf --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiPolyLineObject.cpp @@ -0,0 +1,268 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimAnnotationMultiPolyLineObject.cpp,v 1.5 2004/05/23 17:49:37 dburken Exp $ +#include <imaging/annotation/ossimAnnotationMultiPolyLineObject.h> +#include <imaging/annotation/ossimAnnotationMultiLineObject.h> +#include <imaging/ossimRgbImage.h> +#include <base/data_types/ossimIrect.h> +#include <base/data_types/ossimDrect.h> +#include <base/data_types/ossimLine.h> + +RTTI_DEF1(ossimAnnotationMultiPolyLineObject, "ossimAnnotationMultiPolyLineObject", ossimAnnotationObject) + +ossimAnnotationMultiPolyLineObject::ossimAnnotationMultiPolyLineObject() + :ossimAnnotationObject() +{ + computeBoundingRect(); +} + +ossimAnnotationMultiPolyLineObject::ossimAnnotationMultiPolyLineObject(const vector<ossimPolyLine>& multiPoly, + unsigned char r, + unsigned char g, + unsigned char b, + long thickness) + :ossimAnnotationObject(r, g, b, thickness) +{ + theMultiPolyLine = multiPoly; + computeBoundingRect(); +} + +ossimAnnotationMultiPolyLineObject::~ossimAnnotationMultiPolyLineObject() +{ +} + +void ossimAnnotationMultiPolyLineObject::applyScale(double x, + double y) +{ + for(ossim_uint32 i =0; i<theMultiPolyLine.size(); ++i) + { + theMultiPolyLine[i] *= ossimDpt(x, y); + } + + theBoundingRect *= ossimDpt(x,y); +} + +bool ossimAnnotationMultiPolyLineObject::intersects(const ossimDrect& rect)const +{ + // do the quick checks first + // + if(rect.hasNans()) return false; + if(!rect.intersects(theBoundingRect)) return false; + if(theMultiPolyLine.size()<1) return false; + + for(ossim_uint32 i =0; i < theMultiPolyLine.size(); ++i) + { + vector<ossimPolyLine> result; + + if(theMultiPolyLine[i].clipToRect(result, rect)) + { + return true; + } + } + + return false; +} + +ossimAnnotationObject* ossimAnnotationMultiPolyLineObject::getNewClippedObject(const ossimDrect& rect)const +{ + ossimAnnotationObject* result = (ossimAnnotationObject*)NULL; + + ossimNotify(ossimNotifyLevel_WARN) + << "ossimAnnotationMultiPolyLineObject::getNewClippedObject\n" + << "Not implemented for " << getClassName() << endl; + return result; +} + +void ossimAnnotationMultiPolyLineObject::draw(ossimRgbImage& anImage)const +{ + if(theMultiPolyLine.size()<1) return; + if(theBoundingRect.hasNans()) return; + + + anImage.setDrawColor(theRed, theGreen, theBlue); + anImage.setThickness(theThickness); + ossimDrect imageRect = anImage.getImageData()->getImageRectangle(); + + if(theBoundingRect.intersects(imageRect)) + { + // we need to extend it by a couple of pixels since + // if a pixel lies on the edge and then another pixel is just off + // the edge we will get a stair step and so for several pixels + // the line might be inside the image rectangle but the clip + // algorithm will only draw 1 pixel since it thinks the first + // point is inside and the second point is outside and will + // execute the clip algorithm keeping only the first + // point. + ossimDrect clipRect(imageRect.ul().x - 10, + imageRect.ul().y - 10, + imageRect.lr().x + 10, + imageRect.lr().y + 10); + + int j = 0; + for(ossim_uint32 i = 0; i < theMultiPolyLine.size(); ++i) + { + const ossimPolyLine& poly = theMultiPolyLine[i]; + int vertexCount = poly.getNumberOfVertices(); + + if(vertexCount > 1) + { + + ossimDpt start, end; + start = poly[0]; + end = poly[1]; + j = 1; + do + { + if(clipRect.clip(start, end)) + { + anImage.drawLine(ossimIpt(start), + ossimIpt(end)); + } + ++j; + start = poly[j-1]; + end = poly[j]; + }while(j < vertexCount); + } + else if(vertexCount == 1) + { + anImage.drawLine(ossimIpt(poly[0]), + ossimIpt(poly[0])); + } + } + } +} + +std::ostream& ossimAnnotationMultiPolyLineObject::print(std::ostream& out)const +{ + ossimAnnotationObject::print(out); + out << endl; + out << setw(15)<<setiosflags(ios::left)<<"type:"<<getClassName() << endl + << setw(15)<<setiosflags(ios::left)<<"polylines:"<<theMultiPolyLine.size()<<endl; + + for(ossim_uint32 i = 0; i < theMultiPolyLine.size(); ++i) + { + out << "____________________________________________________"<<endl + << theMultiPolyLine[i] << endl; + } + out << "____________________________________________________"<<endl; + return out; +} + +void ossimAnnotationMultiPolyLineObject::getBoundingRect(ossimDrect& rect)const +{ + rect = theBoundingRect; +} + +void ossimAnnotationMultiPolyLineObject::computeBoundingRect() +{ + if(theMultiPolyLine.size()) + { + ossimDrect rect(theMultiPolyLine[0].getVertexList()); + + for(ossim_uint32 i = 1; i < theMultiPolyLine.size(); ++i) + { + ossimDrect rect2(theMultiPolyLine[i].getVertexList()); + + if(rect.hasNans()) + { + rect = rect2; + } + else + { + if(!rect2.hasNans()) + { + rect = rect.combine(rect2); + } + } + } + + theBoundingRect = rect; + } + else + { + theBoundingRect.makeNan(); + } + if(!theBoundingRect.hasNans()) + { + ossimIpt origin = theBoundingRect.ul(); + theBoundingRect = ossimDrect(origin.x - theThickness/2, + origin.y - theThickness/2, + origin.x + (theBoundingRect.width()-1) + theThickness/2, + origin.y + (theBoundingRect.height()-1) + theThickness/2); + } +} + +bool ossimAnnotationMultiPolyLineObject::isPointWithin(const ossimDpt& imagePoint)const +{ +// for(ossim_uint32 i = 0; i < theMultiPolyLine.size(); ++i) +// { +// if(theMultiPolyLine[i].isPointWithin(imagePoint)) +// { +// return true; +// } +// } + + return theBoundingRect.pointWithin(imagePoint); +} + +ossimAnnotationMultiPolyLineObject::ossimAnnotationMultiPolyLineObject(const ossimAnnotationMultiPolyLineObject& rhs) + : ossimAnnotationObject(rhs), + theMultiPolyLine(rhs.theMultiPolyLine), + theBoundingRect(rhs.theBoundingRect) +{ +} + +ossimObject* ossimAnnotationMultiPolyLineObject::dup()const +{ + return new ossimAnnotationMultiPolyLineObject(*this); +} + +void ossimAnnotationMultiPolyLineObject::addPolyLine(const ossimPolyLine& poly) +{ + theMultiPolyLine.push_back(poly); +} + +void ossimAnnotationMultiPolyLineObject::addPoint(ossim_uint32 polygonIndex, + const ossimDpt& pt) +{ + if(polygonIndex < theMultiPolyLine.size()) + { + theMultiPolyLine[polygonIndex].addPoint(pt); + } +} + +void ossimAnnotationMultiPolyLineObject::setMultiPolyLine(const vector<ossimPolyLine>& multiPoly) +{ + theMultiPolyLine = multiPoly; + computeBoundingRect(); +} + +const std::vector<ossimPolyLine>& ossimAnnotationMultiPolyLineObject::getMultiPolyLine()const +{ + return theMultiPolyLine; +} + +std::vector<ossimPolyLine>& ossimAnnotationMultiPolyLineObject::getMultiPolyLine() +{ + return theMultiPolyLine; +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiPolyLineObject.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiPolyLineObject.h new file mode 100644 index 0000000000..e51894b43e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiPolyLineObject.h @@ -0,0 +1,70 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimAnnotationMultiPolyLineObject.h,v 1.2 2004/05/23 17:49:37 dburken Exp $ +#ifndef ossimAnnotationMultiPolyLineObject_HEADER +#define ossimAnnotationMultiPolyLineObject_HEADER + +#include "ossimAnnotationObject.h" +#include "base/data_types/ossimIpt.h" +#include "base/data_types/ossimPolyLine.h" + +class OSSIMDLLEXPORT ossimAnnotationMultiPolyLineObject : public ossimAnnotationObject +{ +public: + ossimAnnotationMultiPolyLineObject(); + ossimAnnotationMultiPolyLineObject(const vector<ossimPolyLine>& multiPoly, + unsigned char r, + unsigned char g, + unsigned char b, + long thickness); + + ossimAnnotationMultiPolyLineObject(const ossimAnnotationMultiPolyLineObject& rhs); + + virtual ossimObject* dup()const; + + virtual ~ossimAnnotationMultiPolyLineObject(); + virtual void applyScale(double x, + double y); + virtual void draw(ossimRgbImage& anImage)const; + virtual bool intersects(const ossimDrect& rect)const; + + virtual ossimAnnotationObject* getNewClippedObject(const ossimDrect& rect)const; + virtual std::ostream& print(std::ostream& out)const; + virtual void getBoundingRect(ossimDrect& rect)const; + virtual void addPolyLine(const ossimPolyLine& poly); + virtual void addPoint(ossim_uint32 polygonIndex, const ossimDpt& pt); + + virtual void setMultiPolyLine(const vector<ossimPolyLine>& multiPoly); + virtual void computeBoundingRect(); + virtual bool isPointWithin(const ossimDpt& imagePoint)const; + + const std::vector<ossimPolyLine>& getMultiPolyLine()const; + std::vector<ossimPolyLine>& getMultiPolyLine(); +protected: + vector<ossimPolyLine> theMultiPolyLine; + ossimDrect theBoundingRect; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiPolyObject.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiPolyObject.cpp new file mode 100644 index 0000000000..64330c07a7 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiPolyObject.cpp @@ -0,0 +1,322 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossimAnnotationMultiPolyObject.cpp,v 1.18 2004/12/21 20:12:40 gpotts Exp $ +#include "ossimAnnotationMultiPolyObject.h" +#include "ossimAnnotationMultiLineObject.h" +#include "imaging/ossimRgbImage.h" +#include "base/data_types/ossimIrect.h" +#include "base/data_types/ossimDrect.h" +#include "base/data_types/ossimLine.h" + +RTTI_DEF1(ossimAnnotationMultiPolyObject, "ossimAnnotationMultiPolyObject", ossimAnnotationObject) + +ossimAnnotationMultiPolyObject::ossimAnnotationMultiPolyObject() + :ossimAnnotationObject(), + theFillEnabled(false) +{ + computeBoundingRect(); +} + +ossimAnnotationMultiPolyObject::ossimAnnotationMultiPolyObject(const vector<ossimPolygon>& multiPoly, + bool enableFill, + unsigned char r, + unsigned char g, + unsigned char b, + long thickness) + :ossimAnnotationObject(r, g, b, thickness), + theFillEnabled(enableFill) +{ + theMultiPolygon = multiPoly; + computeBoundingRect(); +} + +ossimAnnotationMultiPolyObject::~ossimAnnotationMultiPolyObject() +{ +} + +void ossimAnnotationMultiPolyObject::applyScale(double x, + double y) +{ + for(ossim_uint32 i =0; i<theMultiPolygon.size(); ++i) + { + theMultiPolygon[i] *= ossimDpt(x, y); + } + + theBoundingRect *= ossimDpt(x,y); +} + +bool ossimAnnotationMultiPolyObject::intersects(const ossimDrect& rect)const +{ + // do the quick checks first + // + if(rect.hasNans()) return false; + if(!rect.intersects(theBoundingRect)) return false; + if(theMultiPolygon.size()<1) return false; + + for(ossim_uint32 i =0; i < theMultiPolygon.size(); ++i) + { + vector<ossimPolygon> result; + + if(theMultiPolygon[i].clipToRect(result, rect)) + { + return true; + } + } + + return false; +} + +ossimAnnotationObject* ossimAnnotationMultiPolyObject::getNewClippedObject(const ossimDrect& rect)const +{ + ossimAnnotationObject* result = (ossimAnnotationObject*)NULL; + + if(theBoundingRect.intersects(rect)) + { + ossimDrect clipRect(rect.ul().x - 10, + rect.ul().y - 10, + rect.lr().x + 10, + rect.lr().y + 10); + + if(theFillEnabled) + { + vector<ossimPolygon> polyListResult; + + for(ossim_uint32 i = 0; i < theMultiPolygon.size(); ++i) + { + vector<ossimPolygon> tempList; + + if(theMultiPolygon[i].clipToRect(tempList, rect)) + { + polyListResult.insert(polyListResult.end(), + tempList.begin(), + tempList.end()); + } + } + + if(polyListResult.size()) + { + result = new ossimAnnotationMultiPolyObject(polyListResult, + theFillEnabled, + theRed, + theGreen, + theBlue, + theThickness); + } + } + else + { + vector<ossimPolyLine> lineListResult; + vector<ossimPolyLine> tempResult; + + for(ossim_uint32 i = 0; i< theMultiPolygon.size();++i) + { + ossimPolyLine polyLine = theMultiPolygon[i]; + + if(polyLine.clipToRect(tempResult, + clipRect)) + { + lineListResult.insert(lineListResult.end(), + tempResult.begin(), + tempResult.end()); + } + } + + if(lineListResult.size()) + { + result = new ossimAnnotationMultiLineObject(lineListResult, + theRed, + theGreen, + theBlue, + theThickness); + } + } + } + + return result; +} + +void ossimAnnotationMultiPolyObject::draw(ossimRgbImage& anImage)const +{ + if(theMultiPolygon.size()<1) return; + if(theBoundingRect.hasNans()) return; + + + anImage.setDrawColor(theRed, theGreen, theBlue); + anImage.setThickness(theThickness); + ossimDrect imageRect = anImage.getImageData()->getImageRectangle(); + + if(theBoundingRect.intersects(imageRect)) + { + // we need to extend it by a couple of pixels since + // if a pixel lies on the edge and then another pixel is just off + // the edge we will get a stair step and so for several pixels + // the line might be inside the image rectangle but the clip + // algorithm will only draw 1 pixel since it thinks the first + // point is inside and the second point is outside and will + // execute the clip algorithm keeping only the first + // point. + ossimDrect clipRect(imageRect.ul().x - 10, + imageRect.ul().y - 10, + imageRect.lr().x + 10, + imageRect.lr().y + 10); + + int j = 0; + for(ossim_uint32 i = 0; i < theMultiPolygon.size(); ++i) + { + const ossimPolygon& poly = theMultiPolygon[i]; + int vertexCount = poly.getVertexCount(); + if(!theFillEnabled) + { + if(poly.getNumberOfVertices() == 1) + { + ossimDpt start, end; + start = poly[0]; + end = poly[0]; + if(clipRect.clip(start, end)) + { + anImage.drawLine(ossimIpt(start), + ossimIpt(end)); + } + } + else if(poly.getNumberOfVertices() == 2) + { + ossimDpt start, end; + start = poly[0]; + end = poly[1]; + if(clipRect.clip(start, end)) + { + anImage.drawLine(ossimIpt(start), + ossimIpt(end)); + } + } + else if(vertexCount > 2) + { + ossimDpt start, end; + start = poly[vertexCount-1]; + end = poly[0]; + j = 0; + do + { + if(clipRect.clip(start, end)) + { + anImage.drawLine(ossimIpt(start), + ossimIpt(end)); + } + ++j; + start = poly[j-1]; + end = poly[j]; + }while(j < vertexCount); + } + } + else + { + vector<ossimPolygon> result; + if(poly.clipToRect(result, imageRect)) + { + for(j = 0; j < (int)result.size();++j) + { + anImage.drawFilledPolygon(result[j].getVertexList()); + } + } + } + } + } +} + +std::ostream& ossimAnnotationMultiPolyObject::print(std::ostream& out)const +{ + ossimAnnotationObject::print(out); + out << endl; + out << setw(15)<<setiosflags(ios::left)<<"type:"<<getClassName() << endl + << setw(15)<<setiosflags(ios::left)<<"polygons:"<<theMultiPolygon.size()<<endl + << setw(15)<<setiosflags(ios::left)<<"fill enable: " << theFillEnabled << endl; + + for(ossim_uint32 i = 0; i < theMultiPolygon.size(); ++i) + { + out << "____________________________________________________"<<endl + << theMultiPolygon[i] << endl; + } + out << "____________________________________________________"<<endl; + return out; +} + +void ossimAnnotationMultiPolyObject::getBoundingRect(ossimDrect& rect)const +{ + rect = theBoundingRect; +} + +void ossimAnnotationMultiPolyObject::clear() +{ + theMultiPolygon.clear(); +} + +void ossimAnnotationMultiPolyObject::computeBoundingRect() +{ + if(theMultiPolygon.size()) + { + ossimDrect rect(theMultiPolygon[0]); + + for(ossim_uint32 i = 1; i < theMultiPolygon.size(); ++i) + { + ossimDrect rect2(theMultiPolygon[i]); + + if(rect.hasNans()) + { + rect = rect2; + } + else + { + if(!rect2.hasNans()) + { + rect = rect.combine(rect2); + } + } + } + + theBoundingRect = rect; + } + else + { + theBoundingRect.makeNan(); + } + if(!theBoundingRect.hasNans()) + { + ossimIpt origin = theBoundingRect.ul(); + theBoundingRect = ossimDrect(origin.x - theThickness/2, + origin.y - theThickness/2, + origin.x + (theBoundingRect.width()-1) + theThickness/2, + origin.y + (theBoundingRect.height()-1) + theThickness/2); + } +} + +bool ossimAnnotationMultiPolyObject::isPointWithin(const ossimDpt& imagePoint)const +{ + for(ossim_uint32 i = 0; i < theMultiPolygon.size(); ++i) + { + if(theMultiPolygon[i].isPointWithin(imagePoint)) + { + return true; + } + } + + return false; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiPolyObject.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiPolyObject.h new file mode 100644 index 0000000000..95a3b5a9dd --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationMultiPolyObject.h @@ -0,0 +1,97 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimAnnotationMultiPolyObject.h,v 1.7 2004/05/23 17:49:37 dburken Exp $ +#ifndef ossimAnnotationMultiPolyObject_HEADER +#define ossimAnnotationMultiPolyObject_HEADER +#include "ossimAnnotationObject.h" +#include "base/data_types/ossimIpt.h" +#include "base/data_types/ossimPolygon.h" + +class OSSIMDLLEXPORT ossimAnnotationMultiPolyObject : public ossimAnnotationObject +{ +public: + ossimAnnotationMultiPolyObject(); + ossimAnnotationMultiPolyObject(const vector<ossimPolygon>& multiPoly, + bool enableFill, + unsigned char r, + unsigned char g, + unsigned char b, + long thickness); + + ossimAnnotationMultiPolyObject(const ossimAnnotationMultiPolyObject& rhs) + : ossimAnnotationObject(rhs), + theMultiPolygon(rhs.theMultiPolygon), + theBoundingRect(rhs.theBoundingRect), + theFillEnabled(rhs.theFillEnabled) + { + } + virtual ossimObject* dup()const + { + return new ossimAnnotationMultiPolyObject(*this); + } + virtual ~ossimAnnotationMultiPolyObject(); + virtual void applyScale(double x, + double y); + virtual void draw(ossimRgbImage& anImage)const; + virtual bool intersects(const ossimDrect& rect)const; + + virtual ossimAnnotationObject* getNewClippedObject(const ossimDrect& rect)const; + virtual std::ostream& print(std::ostream& out)const; + virtual void getBoundingRect(ossimDrect& rect)const; + virtual void clear(); + virtual void addPolygon(const ossimPolygon& poly) + { + theMultiPolygon.push_back(poly); + } + virtual void addPoint(ossim_uint32 polygonIndex, + const ossimDpt& pt) + { + if(polygonIndex < theMultiPolygon.size()) + { + theMultiPolygon[polygonIndex].addPoint(pt); + } + } + + virtual void setMultiPolygon(const vector<ossimPolygon>& multiPoly) + { + theMultiPolygon = multiPoly; + computeBoundingRect(); + } + virtual void computeBoundingRect(); + virtual bool isPointWithin(const ossimDpt& imagePoint)const; + + const std::vector<ossimPolygon>& getMultiPolygon()const{return theMultiPolygon;} + std::vector<ossimPolygon>& getMultiPolygon(){return theMultiPolygon;} + void setFillFlag(bool flag) + { + theFillEnabled = flag; + } +protected: + vector<ossimPolygon> theMultiPolygon; + ossimDrect theBoundingRect; + bool theFillEnabled; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationObject.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationObject.cpp new file mode 100644 index 0000000000..8e81d39d12 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationObject.cpp @@ -0,0 +1,161 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See LICENSE.txt file in the top level directory. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimAnnotationObject.cpp,v 1.14 2005/12/07 19:03:12 dburken Exp $ +#include "ossimAnnotationObject.h" + +RTTI_DEF1(ossimAnnotationObject, "ossimAnnotationObject", ossimObject) + +ossim_uint32 ossimAnnotationObject::theIdCounter = 0; + +ossimAnnotationObject::~ossimAnnotationObject() +{} + +void ossimAnnotationObject::restIdCounter() +{ + theIdCounter = 0; +} + +ossim_uint32 ossimAnnotationObject::getNextId() +{ + ossim_uint32 id = theIdCounter; + ++theIdCounter; + return id; +} + +ossimAnnotationObject::ossimAnnotationObject(ossim_uint8 r, + ossim_uint8 g, + ossim_uint8 b, + ossim_uint8 thickness) + :theRed(r), + theGreen(g), + theBlue(b), + theThickness(thickness) +{ + theId = getNextId(); +} + +void ossimAnnotationObject::setColor(ossim_uint8 r, + ossim_uint8 g, + ossim_uint8 b) +{ + theRed = r; + theGreen = g; + theBlue = b; +} + +void ossimAnnotationObject::setThickness(ossim_uint8 thickness) +{ + theThickness = thickness; +} + +void ossimAnnotationObject::getColor(ossim_uint8 &r, + ossim_uint8 &g, + ossim_uint8 &b)const +{ + r = theRed; + g = theGreen; + b = theBlue; +} + +ossim_uint8 ossimAnnotationObject::getThickness()const +{ + return theThickness; +} + +ossim_uint32 ossimAnnotationObject::getId()const +{ + return theId; +} + +ossim_uint32 ossimAnnotationObject::setId() +{ + theId = getNextId(); + return getId(); +} + +bool ossimAnnotationObject::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + kwl.add(prefix, "red", theRed); + kwl.add(prefix, "green", theGreen); + kwl.add(prefix, "blue", theBlue); + kwl.add(prefix, "thickness", theThickness); + + return ossimObject::saveState(kwl, prefix); +} + +bool ossimAnnotationObject::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* red = kwl.find(prefix, "red"); + const char* green = kwl.find(prefix, "green"); + const char* blue = kwl.find(prefix, "blue"); + const char* thickness = kwl.find(prefix, "thickness"); + + if(red) + { + theRed = (ossim_uint8)ossimString(red).toLong(); + } + if(green) + { + theGreen = (ossim_uint8)ossimString(green).toLong(); + } + if(blue) + { + theBlue = (ossim_uint8)ossimString(blue).toLong(); + } + if(thickness) + { + theThickness = (ossim_uint8)ossimString(thickness).toLong(); + } + + return ossimObject::loadState(kwl, prefix); +} + +bool ossimAnnotationObject::isPointWithin(const ossimDpt& /* imagePoint */) const +{ + return false; +} + +ossimString ossimAnnotationObject::getName()const +{ + return theName; +} + +void ossimAnnotationObject::setName(const ossimString& name) +{ + theName = name; +} + +ossimDrect ossimAnnotationObject::getBoundingRect()const +{ + ossimDrect rect; + getBoundingRect(rect); + return rect; +} + +void ossimAnnotationObject::applyScale(const ossimDpt& scale) +{ + applyScale(scale.x, + scale.y); +} + +std::ostream& ossimAnnotationObject::print(ostream& out) const +{ + + out << setw(15)<<setiosflags(ios::left)<<"Red:" << (long)theRed << endl + << setw(15)<<setiosflags(ios::left)<<"Green:" << (long)theGreen << endl + << setw(15)<<setiosflags(ios::left)<<"Blue" << (long)theBlue << endl + << setw(15)<<setiosflags(ios::left)<<"Thickness:"<<theThickness + << "color_red: " << (long)theRed << endl + << "color_green: " << (long)theGreen << endl + << "color_blue: " << (long)theBlue << endl + << "thickness: " << theThickness << endl; + return out; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationObject.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationObject.h new file mode 100644 index 0000000000..dbc62a0a78 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationObject.h @@ -0,0 +1,105 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See LICENSE.txt file in the top level directory. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimAnnotationObject.h,v 1.25 2005/12/07 19:03:12 dburken Exp $ +#ifndef ossimAnnotationObject_HEADER +#define ossimAnnotationObject_HEADER +#include <iostream> + +#include <base/common/ossimObject.h> +#include <base/common/ossimCommon.h> +#include <base/data_types/ossimDrect.h> +#include <base/data_types/ossimKeywordlist.h> +#include <imaging/ossimRgbImage.h> +#include <base/data_types/ossimString.h> + +class OSSIMDLLEXPORT ossimAnnotationObject : public ossimObject +{ +public: + ossimAnnotationObject(ossim_uint8 r=255, + ossim_uint8 g=255, + ossim_uint8 b=255, + ossim_uint8 thickness=1); + virtual ~ossimAnnotationObject(); + virtual void applyScale(double x, + double y)=0; + virtual void applyScale(const ossimDpt& scale); + + virtual std::ostream& print(std::ostream& out)const; + + virtual void draw(ossimRgbImage& anImage)const=0; + virtual bool intersects(const ossimDrect& rect)const=0; + + /*! + * Will allocate a new object that is clipped to the passed. + * in rect. Look at derived classes to see if the object is actually + * clipped or not. A new object is returned if it clips to the rect + * else NULL should be returned it doesn't clip. + */ + virtual ossimAnnotationObject* getNewClippedObject(const ossimDrect& rect)const=0; + + virtual void getBoundingRect(ossimDrect& rect)const=0; + virtual ossimDrect getBoundingRect()const; + + virtual void computeBoundingRect()=0; + + virtual void setColor(ossim_uint8 r, + ossim_uint8 g, + ossim_uint8 b); + + void getColor(ossim_uint8 &r, + ossim_uint8 &g, + ossim_uint8 &b)const; + + ossim_uint8 getThickness()const; + virtual void setThickness(ossim_uint8 thickness); + + /*! + * This method allows you to pick an object. It will + * return true or false if the point falls somewhere + * on an object. Look at derived classes for further + * information. + */ + virtual bool isPointWithin(const ossimDpt& imagePoint) const; + + /** + * Saves the current state of this object. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual ossimString getName() const; + virtual void setName(const ossimString& name); + + ossim_uint32 getId()const; + virtual ossim_uint32 setId(); + + static ossim_uint32 getNextId(); + static void restIdCounter(); + +protected: + ossim_uint8 theRed; + ossim_uint8 theGreen; + ossim_uint8 theBlue; + ossim_uint8 theThickness; + + ossimString theName; + ossim_uint32 theId; + + static ossim_uint32 theIdCounter; +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationPolyObject.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationPolyObject.cpp new file mode 100644 index 0000000000..5298f781f0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationPolyObject.cpp @@ -0,0 +1,283 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimAnnotationPolyObject.cpp,v 1.22 2005/12/09 17:16:05 dburken Exp $ +#include <imaging/annotation/ossimAnnotationPolyObject.h> +#include <imaging/annotation/ossimAnnotationMultiPolyObject.h> +#include <imaging/annotation/ossimAnnotationMultiLineObject.h> +#include <imaging/ossimRgbImage.h> +#include <base/data_types/ossimIrect.h> + +RTTI_DEF1(ossimAnnotationPolyObject, + "ossimAnnotationPolyObject", + ossimAnnotationObject) + + ossimAnnotationPolyObject::ossimAnnotationPolyObject(bool enableFill, + ossim_uint8 r, + ossim_uint8 g, + ossim_uint8 b, + ossim_uint8 thickness) + :ossimAnnotationObject(r, g, b, thickness), + thePolygon(), + theBoundingRect(), + theFillEnabled(enableFill) +{ +} + +ossimAnnotationPolyObject::ossimAnnotationPolyObject( + const vector<ossimDpt>& imagePts, + bool enableFill, + ossim_uint8 r, + ossim_uint8 g, + ossim_uint8 b, + ossim_uint8 thickness) + :ossimAnnotationObject(r, g, b, thickness), + theFillEnabled(enableFill) +{ + thePolygon = imagePts; + computeBoundingRect(); +} + +ossimAnnotationPolyObject::ossimAnnotationPolyObject( + const ossimAnnotationPolyObject& rhs) + : ossimAnnotationObject(rhs), + thePolygon(rhs.thePolygon), + theBoundingRect(rhs.theBoundingRect), + theFillEnabled(rhs.theFillEnabled) +{ +} + +ossimObject* ossimAnnotationPolyObject::dup()const +{ + return new ossimAnnotationPolyObject(*this); +} + +ossimAnnotationPolyObject::~ossimAnnotationPolyObject() +{ +} + +void ossimAnnotationPolyObject::applyScale(double x, double y) +{ + thePolygon *= ossimDpt(x, y); + theBoundingRect *= ossimDpt(x,y); +} + +bool ossimAnnotationPolyObject::intersects(const ossimDrect& rect)const +{ + // do the quick checks first + // + if(rect.hasNans()) return false; + if(!rect.intersects(theBoundingRect)) return false; + + if(!theFillEnabled) + { + int vertexCount = thePolygon.getVertexCount(); + ossimDpt start, end; + start = thePolygon[vertexCount-1]; + end = thePolygon[0]; + int i = 0; + do + { + if(rect.clip(start, end)) + { + return true; + } + ++i; + start = thePolygon[i]; + end = thePolygon[i-1]; + }while(i < vertexCount); + } + else + { + vector<ossimPolygon> result; + return thePolygon.clipToRect(result, rect); + } + + return false; +} + +ossimAnnotationObject* ossimAnnotationPolyObject::getNewClippedObject(const ossimDrect& rect)const +{ + ossimAnnotationObject* result = (ossimAnnotationObject*)NULL; + + if(theBoundingRect.intersects(rect)) + { + if(theFillEnabled) + { + vector<ossimPolygon> resultPoly; + + if(thePolygon.clipToRect(resultPoly, rect)) + { + if(resultPoly.size() == 1) + { + result = new ossimAnnotationPolyObject(resultPoly[0].getVertexList(), + theFillEnabled, + theRed, + theGreen, + theBlue, + theThickness); + } + else + { + result = new ossimAnnotationMultiPolyObject(resultPoly, + theFillEnabled, + theRed, + theGreen, + theBlue, + theThickness); + } + } + } + else + { + vector<ossimPolyLine> lineListResult; + ossimPolyLine polyLine = thePolygon; + + if(polyLine.clipToRect(lineListResult, + rect)) + { + result = new ossimAnnotationMultiLineObject(lineListResult, + theRed, + theGreen, + theBlue, + theThickness); + } + } + } + + return result; +} + +void ossimAnnotationPolyObject::draw(ossimRgbImage& anImage)const +{ + if(thePolygon.getVertexCount() < 2) return; + if(theBoundingRect.hasNans()) return; + int vertexCount = thePolygon.getVertexCount(); + + anImage.setDrawColor(theRed, theGreen, theBlue); + anImage.setThickness(theThickness); + ossimDrect imageRect = anImage.getImageData()->getImageRectangle(); + if(theBoundingRect.intersects(imageRect)) + { + // we need to extend it by a couple of pixels since + // if a pixel lies on the edge and then another pixel is just off + // the edge we will get a stair step and so for several pixels + // the line might be inside the image rectangle but the clip + // algorithm will only draw 1 pixel since it thinks the first + // point is inside and the second point is outside and will + // execute the clip algorithm keeping only the first + // point. + ossimDrect clipRect(imageRect.ul().x - 10, + imageRect.ul().y - 10, + imageRect.lr().x + 10, + imageRect.lr().y + 10); + + if(!theFillEnabled) + { + ossimDpt start, end; + start = thePolygon[vertexCount-1]; + end = thePolygon[0]; + int i = 0; + do + { + if(clipRect.clip(start, end)) + { + anImage.drawLine(ossimIpt((int)start.x, (int)start.y), + ossimIpt((int)end.x, (int)end.y)); + } + ++i; + start = thePolygon[i]; + end = thePolygon[i-1]; + }while(i < vertexCount); + + } + else + { + vector<ossimPolygon> result; + if(thePolygon.clipToRect(result, imageRect)) + { + for(int i = 0; i < (int)result.size();++i) + { + anImage.drawFilledPolygon(result[i].getVertexList()); + } + } + } + } +} + +std::ostream& ossimAnnotationPolyObject::print(std::ostream& out)const +{ + out << "number_of_points: " << thePolygon.getVertexCount(); + if(thePolygon.getVertexCount() > 0) + { + for(long index =0; index < (long)(thePolygon.getVertexCount()-1); ++index) + { + out << thePolygon[index] << endl; + + } + out << thePolygon[thePolygon.getVertexCount()-1] << endl; + } + out << "fill_enabled: " << theFillEnabled << endl + << "bounding_rect: " << theBoundingRect << endl; + return out; +} + +void ossimAnnotationPolyObject::getBoundingRect(ossimDrect& rect)const +{ + rect = theBoundingRect; +} + +void ossimAnnotationPolyObject::addPoint(const ossimDpt& pt) +{ + thePolygon.addPoint(pt); +} + +void ossimAnnotationPolyObject::setPolygon(const vector<ossimDpt>& imagePoints) +{ + thePolygon = imagePoints; +} + +void ossimAnnotationPolyObject::setPolygon(const ossimPolygon& polygon) +{ + thePolygon = polygon; +} + +void ossimAnnotationPolyObject::setPolygon(const ossimIrect& rect) +{ + thePolygon = rect; +} + +void ossimAnnotationPolyObject::setPolygon(const ossimDrect& rect) +{ + thePolygon = rect; +} + +void ossimAnnotationPolyObject::computeBoundingRect() +{ + theBoundingRect = ossimDrect(thePolygon); +} + +bool ossimAnnotationPolyObject::isPointWithin(const ossimDpt& imagePoint)const +{ + return theBoundingRect.pointWithin(imagePoint); +} + +const ossimPolygon& ossimAnnotationPolyObject::getPolygon() const +{ + return thePolygon; +} + +ossimPolygon& ossimAnnotationPolyObject::getPolygon() +{ + return thePolygon; +} + +void ossimAnnotationPolyObject::setFillFlag(bool flag) +{ + theFillEnabled = flag; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationPolyObject.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationPolyObject.h new file mode 100644 index 0000000000..aceed27464 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationPolyObject.h @@ -0,0 +1,80 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimAnnotationPolyObject.h,v 1.16 2005/12/09 17:16:05 dburken Exp $ +#ifndef ossimAnnotationPolyObject_HEADER +#define ossimAnnotationPolyObject_HEADER + +#include <imaging/annotation/ossimAnnotationObject.h> +#include <base/data_types/ossimIpt.h> +#include <base/data_types/ossimPolygon.h> + +class OSSIMDLLEXPORT ossimAnnotationPolyObject : public ossimAnnotationObject +{ +public: + ossimAnnotationPolyObject(bool enableFill = false, + ossim_uint8 r=255, + ossim_uint8 g=255, + ossim_uint8 b=255, + ossim_uint8 thickness=1); + + ossimAnnotationPolyObject(const vector<ossimDpt>& imagePts, + bool enableFill = false, + ossim_uint8 r=255, + ossim_uint8 g=255, + ossim_uint8 b=255, + ossim_uint8 thickness=1); + + ossimAnnotationPolyObject(const ossimAnnotationPolyObject& rhs); + + ossimObject* dup()const; + + virtual ~ossimAnnotationPolyObject(); + + virtual void applyScale(double x, double y); + + virtual void draw(ossimRgbImage& anImage)const; + + virtual bool intersects(const ossimDrect& rect)const; + + virtual ossimAnnotationObject* getNewClippedObject( + const ossimDrect& rect)const; + + virtual std::ostream& print(std::ostream& out)const; + + virtual void getBoundingRect(ossimDrect& rect)const; + + virtual void addPoint(const ossimDpt& pt); + + virtual void setPolygon(const vector<ossimDpt>& imagePoints); + + virtual void setPolygon(const ossimPolygon& polygon); + + virtual void setPolygon(const ossimIrect& rect); + + virtual void setPolygon(const ossimDrect& rect); + + virtual void computeBoundingRect(); + + virtual bool isPointWithin(const ossimDpt& imagePoint)const; + + const ossimPolygon& getPolygon()const; + + ossimPolygon& getPolygon(); + + virtual void setFillFlag(bool flag); + +protected: + ossimPolygon thePolygon; + ossimDrect theBoundingRect; + bool theFillEnabled; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationSource.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationSource.cpp new file mode 100644 index 0000000000..2a8676d3c6 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationSource.cpp @@ -0,0 +1,457 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See LICENSE.txt file in the top level directory. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimAnnotationSource.cpp,v 1.61 2005/12/07 20:54:19 dburken Exp $ +#include <imaging/annotation/ossimAnnotationSource.h> +#include <imaging/annotation/ossimAnnotationObject.h> +#include <imaging/factory/ossimAnnotationObjectFactory.h> +#include <imaging/ossimRgbImage.h> +#include <imaging/ossimU8ImageData.h> + +#include <base/common/ossimTrace.h> + +RTTI_DEF1(ossimAnnotationSource, "ossimAnnotationSource", ossimImageSourceFilter) + +static ossimTrace traceDebug("ossimAnnotationSource:debug"); + +ossimAnnotationSource::ossimAnnotationSource(ossimImageSource* inputSource) + : + ossimImageSourceFilter(inputSource), + theRectangle(0, 0, 0, 0), + theNumberOfBands(1), + theImage(NULL), + theTile(NULL), + theAnnotationObjectList() +{ + theRectangle.makeNan(); +} + +ossimAnnotationSource::~ossimAnnotationSource() +{ + deleteAll(); + destroy(); +} + +void ossimAnnotationSource::destroy() +{ + if(theImage) + { + delete theImage; + theImage = NULL; + } +} + +void ossimAnnotationSource::allocate(const ossimIrect& rect) +{ + destroy(); + + ossim_uint32 width = rect.width(); + ossim_uint32 height = rect.height(); + + theImage = new ossimRgbImage(); + + theTile = new ossimU8ImageData(this, + theNumberOfBands, + width, + height); + + theTile->initialize(); +} + +ossimScalarType ossimAnnotationSource::getOutputScalarType() const +{ + if(theInputConnection && !isSourceEnabled()) + { + return theInputConnection->getOutputScalarType(); + } + return OSSIM_UCHAR; +} + +ossim_uint32 ossimAnnotationSource::getNumberOfOutputBands()const +{ + if(theInputConnection && !isSourceEnabled()) + { + return theInputConnection->getNumberOfOutputBands(); + } + // this source is an RGB source + return theNumberOfBands; +} + + +void ossimAnnotationSource::initialize() +{ + //--- + // Call the base class initialize. + // Note: This will reset "theInputConnection" if it changed... + //--- + ossimImageSourceFilter::initialize(); + + if (theInputConnection) + { + computeBoundingRect(); + + ossim_uint32 bands = theInputConnection->getNumberOfOutputBands(); + if (bands == 1 || bands == 3) + { + setNumberOfBands(bands); + } + + if (theTile.valid()) // Check for number of band change. + { + if ( theInputConnection->getNumberOfOutputBands() != + theTile->getNumberOfBands()) + { + //--- + // This will wide things slick and force an allocate() + // call on first getTile(). + //--- + destroy(); + } + } + } + else + { + destroy(); + } +} + +ossimIrect ossimAnnotationSource::getBoundingRect(ossim_uint32 resLevel)const +{ + ossimIrect result; + result.makeNan(); + + if(theInputConnection) + { + ossimIrect temp = theInputConnection->getBoundingRect(resLevel); + result = temp; + } + + if(result.hasNans()) + { + result = theRectangle; + } + else if(!theRectangle.hasNans()) + { + result.combine(theRectangle); + } + + return result; +} + + +void ossimAnnotationSource::setNumberOfBands(ossim_uint32 bands) +{ + theNumberOfBands = bands; + + if(theNumberOfBands == 2) theNumberOfBands = 3; + if(theNumberOfBands > 3) theNumberOfBands = 3; + if(theNumberOfBands < 1) theNumberOfBands = 1; +} + +ossimRefPtr<ossimImageData> ossimAnnotationSource::getTile(const ossimIrect& tile_rect, + ossim_uint32 resLevel) +{ + ossimRefPtr<ossimImageData> inputTile = NULL; + + if(theInputConnection) + { + // Fetch tile from pointer from the input source. + inputTile = theInputConnection->getTile(tile_rect, + resLevel); + } + + // Check for remap bypass: + if ( !theEnableFlag) + { + return inputTile; + } + + // Check for first time through or size or band change. + if ( !theTile || + tile_rect.height() != theTile->getHeight() || + tile_rect.width() != theTile->getWidth()) + { + allocate(tile_rect); + } + if(!theTile) + { + return theTile; + } + + theTile->makeBlank(); + + // Set the origin of the output tile. + theTile->setImageRectangle(tile_rect); + + if(inputTile.valid() && + inputTile->getBuf()&& + (inputTile->getDataObjectStatus()!=OSSIM_EMPTY)) + { + if(theTile->getNumberOfBands() != + inputTile->getNumberOfBands()) + { + int maxBands = ossimMin(theTile->getNumberOfBands(), + inputTile->getNumberOfBands()); + int idx = 0; + for(idx = 0; idx < maxBands; ++idx) + { + theTile->loadBand(inputTile->getBuf(idx), + inputTile->getImageRectangle(), + idx); + } + int saveIdx = idx - 1; + for(;idx<(int)theTile->getNumberOfBands();++idx) + { + theTile->loadBand(inputTile->getBuf(saveIdx), + inputTile->getImageRectangle(), + idx); + } + } + else + { + theTile->loadTile(inputTile.get()); + } + } + + drawAnnotations(theTile); + + theTile->validate(); + + return theTile; +} + +bool ossimAnnotationSource::addObject(ossimAnnotationObject* anObject) +{ + if(anObject) + { + theAnnotationObjectList.push_back(anObject); + return true; + } + + return false; +} + +bool ossimAnnotationSource::deleteObject(ossimAnnotationObject* anObject) +{ + if(anObject) + { + vector<ossimAnnotationObject*>::iterator current = theAnnotationObjectList.begin(); + while(current != theAnnotationObjectList.end()) + { + if(*current == anObject) + { + delete anObject; + theAnnotationObjectList.erase(current); + return true; + } + ++current; + } + } + + return false; +} + +bool ossimAnnotationSource::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + // Save the state of all annotation objects we have. + vector<ossimAnnotationObject*>::const_iterator obj = + theAnnotationObjectList.begin(); + ossim_uint32 objIdx = 0; + while (obj < theAnnotationObjectList.end()) + { + ossimString newPrefix = prefix; + + newPrefix += (ossimString("object") + + ossimString::toString(objIdx) + + ossimString(".")); + (*obj)->saveState(kwl, newPrefix.c_str()); + ++objIdx; + ++obj; + } + + return ossimImageSourceFilter::saveState(kwl, prefix); +} + +bool ossimAnnotationSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossim_uint32 index = 0; + ossimString copyPrefix = prefix; + ossim_uint32 result = kwl.getNumberOfSubstringKeys(copyPrefix + + "object[0-9]+\\."); + + ossim_uint32 numberOfMatches = 0; + const ossim_uint32 MAX_INDEX = result + 100; + + while(numberOfMatches < result) + { + ossimString newPrefix = copyPrefix; + newPrefix += ossimString("object"); + newPrefix += ossimString::toString(index); + newPrefix += ossimString("."); + + const char* lookup = kwl.find(newPrefix.c_str(), "type"); + if (lookup) + { + ++numberOfMatches; + + ossimAnnotationObject* obj = NULL; + obj = ossimAnnotationObjectFactory::instance()-> + create(kwl, newPrefix.c_str()); + if (obj) + { + if(!addObject(obj)) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimGeoAnnotationSource::loadState\n" + << "Object " << obj->getClassName() + << " is not a geographic object" << endl; + delete obj; + } + } + } + + ++index; + + if (index > MAX_INDEX) // Avoid infinite loop... + { + break; + } + } + + return ossimImageSourceFilter::loadState(kwl, prefix); +} + +void ossimAnnotationSource::computeBoundingRect() +{ + theRectangle.makeNan(); + + if(theAnnotationObjectList.size()>0) + { + ossimDrect rect; + theAnnotationObjectList[0]->computeBoundingRect(); + + theAnnotationObjectList[0]->getBoundingRect(theRectangle); + + vector<ossimAnnotationObject*>::iterator object = (theAnnotationObjectList.begin()+1); + while(object != theAnnotationObjectList.end()) + { + (*object)->computeBoundingRect(); + (*object)->getBoundingRect(rect); + if(theRectangle.hasNans()) + { + theRectangle = rect; + } + else if(!rect.hasNans()) + { + theRectangle = theRectangle.combine(rect); + } + ++object; + } + } +} + +vector<ossimAnnotationObject*> ossimAnnotationSource::pickObjects(const ossimDpt& imagePoint) +{ + vector<ossimAnnotationObject*> result; + vector<ossimAnnotationObject*>::iterator currentObject; + + currentObject = theAnnotationObjectList.begin(); + + while(currentObject != theAnnotationObjectList.end()) + { + if((*currentObject)->isPointWithin(imagePoint)) + { + result.push_back(*currentObject); + } + + ++currentObject; + } + return result; +} + +vector<ossimAnnotationObject*> ossimAnnotationSource::pickObjects(const ossimDrect& imageRect) +{ + vector<ossimAnnotationObject*> result; + vector<ossimAnnotationObject*>::iterator currentObject; + + currentObject = theAnnotationObjectList.begin(); + + while(currentObject != theAnnotationObjectList.end()) + { + ossimAnnotationObject* current = (*currentObject); + if(current->isPointWithin(imageRect.ul())) + { + result.push_back(*currentObject); + } + else if(current->isPointWithin(imageRect.ll())) + { + result.push_back(*currentObject); + } + else if(current->isPointWithin(imageRect.lr())) + { + result.push_back(*currentObject); + } + else if(current->isPointWithin(imageRect.ur())) + { + result.push_back(*currentObject); + } + + ++currentObject; + } + return result; +} + +void ossimAnnotationSource::deleteAll() +{ + vector<ossimAnnotationObject*>::iterator obj; + + obj = theAnnotationObjectList.begin(); + + while(obj != theAnnotationObjectList.end()) + { + if(*obj) + { + delete *obj; + *obj = NULL; + } + + ++obj; + } + + theAnnotationObjectList.clear(); +} + +void ossimAnnotationSource::drawAnnotations(ossimRefPtr<ossimImageData> tile) +{ + theImage->setCurrentImageData(tile); + + if(theImage->getImageData().valid()) + { + vector<ossimAnnotationObject*>::iterator object = theAnnotationObjectList.begin(); + while(object != theAnnotationObjectList.end()) + { + if(*object) + { + (*object)->draw(*theImage); + } + ++object; + } + } +} + +const vector<ossimAnnotationObject*>& ossimAnnotationSource::getObjectList()const +{ + return theAnnotationObjectList; +} + +vector<ossimAnnotationObject*>& ossimAnnotationSource::getObjectList() +{ + return theAnnotationObjectList; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationSource.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationSource.h new file mode 100644 index 0000000000..871d14eaa4 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimAnnotationSource.h @@ -0,0 +1,140 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See LICENSE.txt file in the top level directory. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimAnnotationSource.h,v 1.29 2005/12/07 18:58:11 dburken Exp $ +#ifndef ossimAnnotationSource_HEADER +#define ossimAnnotationSource_HEADER +#include <list> +#include <imaging/tile_sources/ossimImageSourceFilter.h> +#include <base/data_types/ossimIrect.h> +#include <base/data_types/ossimKeywordlist.h> + + +class ossimRgbImage; +class ossimAnnotationObject; + +class OSSIMDLLEXPORT ossimAnnotationSource : public ossimImageSourceFilter +{ +public: + ossimAnnotationSource(ossimImageSource* inputSource=NULL); + virtual ~ossimAnnotationSource(); + + virtual ossim_uint32 getNumberOfOutputBands() const; + + virtual ossimScalarType getOutputScalarType() const; + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel = 0); + + /*! + * Will allow this source to initialize its data objects. If it needs to + * it should call its connection to get what it needs. + */ + virtual void initialize(); + + /*! + * Will return the bounding rectangle. + */ + virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0)const; + + /*! + * This can be 1 or 3 bands + */ + virtual void setNumberOfBands(ossim_uint32 bands); + + /*! + * Will add an object to the list. + * it will own the object added. + */ + virtual bool addObject(ossimAnnotationObject* anObject); + + /*! + * Will delete an object from the list. + * Note: the passed in pointer is no long + * valid. + */ + virtual bool deleteObject(ossimAnnotationObject* anObject); + + /*! + * Saves the current state of this object. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual void computeBoundingRect(); + + /*! + * Calls the isPointWithin all Annotation + * Objects. Note: Do not delete these objects. + */ + vector<ossimAnnotationObject*> pickObjects(const ossimDpt& imagePoint); + + /*! + * Note: do not delete the objects returned. + */ + vector<ossimAnnotationObject*> pickObjects(const ossimDrect& imageRect); + + const vector<ossimAnnotationObject*>& getObjectList()const; + + vector<ossimAnnotationObject*>& getObjectList(); + + /*! + Clears theAnnotationObjectList vector. All elements are deleted. + */ + void deleteAll(); + + virtual void drawAnnotations(ossimRefPtr<ossimImageData> tile); + +protected: + + void allocate(const ossimIrect& rect); + void destroy(); + + ossimAnnotationSource(const ossimAnnotationSource& rhs):ossimImageSourceFilter(rhs){} + + /*! + * What is the size of the image. This class + * is an image producer and it needs to know about + * its bounds. We will default the rectangle to an + * empty region. + */ + ossimDrect theRectangle; + + /*! + * The output band can be set to 1 or 3 for + * grey or RGB scale. We will default this to + * a 1 band image. + */ + ossim_uint32 theNumberOfBands; + + /*! + * This has all the routines we need for drawing + * lines, circles and polygons. + */ + ossimRgbImage* theImage; + + ossimRefPtr<ossimImageData> theTile; + + /*! + * These will be all your primitives in + * Example: lines, circles, text ... + */ + std::vector<ossimAnnotationObject*> theAnnotationObjectList; + +TYPE_DATA +}; + +#endif /* #ifndef ossimAnnotationSource_HEADER */ + diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimEsriShapeFileFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimEsriShapeFileFilter.cpp new file mode 100644 index 0000000000..6c34bbb611 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimEsriShapeFileFilter.cpp @@ -0,0 +1,813 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See LICENSE.txt file in the top level directory. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimEsriShapeFileFilter.cpp,v 1.47 2005/12/07 19:07:00 dburken Exp $ + +#include <cstdio> +#include <cstdlib> +#include <sstream> +using namespace std; + +#include <imaging/annotation/ossimEsriShapeFileFilter.h> +#include <vec/shape/ossimShapeFile.h> +#include <imaging/annotation/ossimAnnotationPolyObject.h> +#include <imaging/annotation/ossimGeoAnnotationPolyLineObject.h> +#include <imaging/annotation/ossimAnnotationObject.h> +#include <imaging/annotation/ossimGeoAnnotationPolyObject.h> +#include <imaging/annotation/ossimGeoAnnotationEllipseObject.h> +#include <base/common/ossimTrace.h> +#include <base/common/ossimCommon.h> +#include <base/common/ossimConstants.h> +#include <base/common/ossimKeywordNames.h> +#include <base/common/ossimTrace.h> +#include <base/context/ossimNotifyContext.h> +#include <base/data_types/ossimFilename.h> +#include <base/data_types/ossimGeoPolygon.h> +#include <base/misc/ossimUnitConversionTool.h> +#include <projections/ossimProjection.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <projections/map_projections/ossimMapProjection.h> + + +RTTI_DEF2(ossimEsriShapeFileFilter, + "ossimEsriShapeFileFilter", + ossimAnnotationSource, + ossimViewInterface); + +static const ossimTrace traceDebug("ossimEsriShapeFileFilter:debug"); + +ossimEsriShapeFileFilter::ossimEsriShapeFileFilter(ossimImageSource* inputSource) + :ossimAnnotationSource(inputSource), + ossimViewInterface(), + theViewProjection(NULL), + theShapeFileProjection(NULL), + theOwnsViewProjectionFlag(true), + theCoordinateSystem(OSSIM_GEOGRAPHIC_SPACE), + theUnitType(OSSIM_METERS), + theTree((SHPTree*)NULL), + theMaxQuadTreeLevels(10), + thePenColor(255,255,255), + theBrushColor(255,255,255), + theFillFlag(false), + theThickness(1), + thePointWidthHeight(1, 1), + theBorderSize(0.0), + theBorderSizeUnits(OSSIM_DEGREES) +{ + ossimViewInterface::theObject = this; + ossimAnnotationSource::setNumberOfBands(3); + theBoundingRect.makeNan(); + theMinArray[0] = theMinArray[1] = theMinArray[2] = theMinArray[3] = OSSIM_DBL_NAN; + theMaxArray[0] = theMaxArray[1] = theMaxArray[2] = theMaxArray[3] = OSSIM_DBL_NAN; +} + +ossimEsriShapeFileFilter::~ossimEsriShapeFileFilter() +{ + removeViewProjection(); + + if(theTree) + { + SHPDestroyTree(theTree); + } + + deleteCache(); +} + +bool ossimEsriShapeFileFilter::setView(ossimObject* baseObject, + bool ownsTheView) +{ + ossimProjection* proj = PTR_CAST(ossimProjection, baseObject); + if(proj) + { + setProjection(proj, ownsTheView); + + return true; + } + else if(!baseObject) + { + setProjection((ossimProjection*)NULL, true); + } + + return false; +} + +ossimObject* ossimEsriShapeFileFilter::getView() +{ + return theViewProjection; +} + +const ossimObject* ossimEsriShapeFileFilter::getView()const +{ + return theViewProjection; +} + +bool ossimEsriShapeFileFilter::addObject(ossimAnnotationObject* anObject) +{ + ossimNotify(ossimNotifyLevel_WARN) + << "ossimEsriShapeFileFilter::addObject\n" + << "Can't add objects to layer, must go through Esri loadShapeFile" + <<endl; + + return false; +} + +void ossimEsriShapeFileFilter::computeBoundingRect() +{ +// ossimAnnotationSource::computeBoundingRect(); + + std::multimap<int, ossimAnnotationObject*>::iterator iter = theShapeCache.begin(); + + theBoundingRect.makeNan(); + while(iter != theShapeCache.end()) + { + ossimDrect rect = (*iter).second->getBoundingRect(); + if(theBoundingRect.hasNans()) + { + theBoundingRect = rect; + } + else + { + if(!rect.hasNans()) + { + theBoundingRect = theBoundingRect.combine(rect); + } + } + + ++iter; + } +} + +ossimIrect ossimEsriShapeFileFilter::getBoundingRect(ossim_uint32 resLevel)const +{ + if(!isSourceEnabled()|| + getInput()) + { + if(getInput()) + { + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, + getInput()); + if(input) + { + return input->getBoundingRect(resLevel); + } + } + } + return theBoundingRect; +} + +void ossimEsriShapeFileFilter::drawAnnotations(ossimRefPtr<ossimImageData> tile) +{ + ossimAnnotationSource::drawAnnotations(tile); + + if (!theTree||!theShapeFile.isOpen()) return; + if(theViewProjection) + { + ossimIrect rect = tile->getImageRectangle(); + + rect = ossimIrect(rect.ul().x, + rect.ul().y, + rect.lr().x, + rect.lr().y); + double boundsMin[2]; + double boundsMax[2]; + + ossimGpt gp1; + ossimGpt gp2; + ossimGpt gp3; + ossimGpt gp4; + + theViewProjection->lineSampleToWorld(rect.ul(), + gp1); + theViewProjection->lineSampleToWorld(rect.ur(), + gp2); + theViewProjection->lineSampleToWorld(rect.lr(), + gp3); + theViewProjection->lineSampleToWorld(rect.ll(), + gp4); + + ossimDrect boundsRect( ossimDpt(gp1.lond(), + gp1.latd()), + ossimDpt(gp2.lond(), + gp2.latd()), + ossimDpt(gp3.lond(), + gp3.latd()), + ossimDpt(gp4.lond(), + gp4.latd()), + OSSIM_RIGHT_HANDED); + + boundsMin[0] = boundsRect.ul().x; + boundsMin[1] = boundsRect.lr().y; + + boundsMax[0] = boundsRect.lr().x; + boundsMax[1] = boundsRect.ul().y; + + int n; + int *array=(int*)NULL; + + array = SHPTreeFindLikelyShapes(theTree, + boundsMin, + boundsMax, + &n); + + theImage->setCurrentImageData(tile); + if(n&&array) + { + for(int i = 0; i < n; ++i) + { + std::multimap<int, ossimAnnotationObject*>::iterator iter = theShapeCache.find(array[i]); + while( ((*iter).first == array[i]) && (iter != theShapeCache.end()) ) + { + (*iter).second->draw(*theImage); + ++iter; + } + } + + free(array); + } + } +} + +void ossimEsriShapeFileFilter::transformObjects(ossimProjection* projection) +{ + std::multimap<int, ossimAnnotationObject*>::iterator iter = theShapeCache.begin(); + + + ossimProjection* proj = theViewProjection; + if(projection) + { + proj = projection; + } + + if(!proj) return; + + while(iter != theShapeCache.end()) + { + ossimGeoAnnotationObject* obj = PTR_CAST(ossimGeoAnnotationObject, + (*iter).second); + if(obj) + { + obj->transform(proj); + } + ++iter; + } + + computeBoundingRect(); +} + +void ossimEsriShapeFileFilter::setProjection(ossimProjection* projection, + bool ownsProjectionFlag) +{ + removeViewProjection(); + + theViewProjection = projection; + theOwnsViewProjectionFlag = ownsProjectionFlag; + + transformObjects(); +} + +bool ossimEsriShapeFileFilter::getImageGeometry(ossimKeywordlist& kwl, + const char* prefix) +{ + if(theViewProjection) + { + return theViewProjection->saveState(kwl, prefix); + } + else + { + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, getInput(0)); + if(input) + { + return input->getImageGeometry(kwl, prefix); + } + else + { + kwl.add(prefix, + ossimKeywordNames::TYPE_KW, + "ossimEquDistCylProjection", + true); + kwl.add(prefix, + ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LAT, + .1, + true); + kwl.add(prefix, + ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LON, + .1, + true); + kwl.add(prefix, + ossimKeywordNames::CENTRAL_MERIDIAN_KW, + 0.0, + true); + kwl.add(prefix, + ossimKeywordNames::ORIGIN_LATITUDE_KW, + 0.0, + true); + kwl.add(prefix, + ossimKeywordNames::DATUM_KW, + "WGE", + true); + return true; + } + } + + return false; +} + +void ossimEsriShapeFileFilter::removeViewProjection() +{ + if(theViewProjection&&theOwnsViewProjectionFlag) + { + delete theViewProjection; + } + + theViewProjection = NULL; +} + +void ossimEsriShapeFileFilter::deleteCache() +{ + std::multimap<int, ossimAnnotationObject*>::iterator iter = theShapeCache.begin(); + + + while(iter != theShapeCache.end()) + { + if((*iter).second) + { + delete (*iter).second; + } + ++iter; + } + + theShapeCache.clear(); +} + +void ossimEsriShapeFileFilter::checkAndSetDefaultView() +{ + if(!theViewProjection) + { + ossimKeywordlist tempKwl; + getImageGeometry(tempKwl); + + theViewProjection = ossimProjectionFactoryRegistry::instance()->createProjection(tempKwl); + + if(theViewProjection) + { + transformObjects(); + } + } +} + +bool ossimEsriShapeFileFilter::loadShapeFile(const ossimFilename& shapeFile) +{ + if(theTree) + { + SHPDestroyTree(theTree); + theTree = (SHPTree*)NULL; + } + theShapeFile.open(shapeFile); + deleteCache(); + deleteAll(); + + if(theShapeFile.isOpen()) + { + theShapeFile.getBounds(theMinArray[0],theMinArray[1],theMinArray[2],theMinArray[3], + theMaxArray[0],theMaxArray[1],theMaxArray[2],theMaxArray[3]); + + theTree = SHPCreateTree(theShapeFile.getHandle(), + 2, + theMaxQuadTreeLevels, + theMinArray, + theMaxArray); + + ossimShapeObject obj; + for(int index = 0 ; index < theShapeFile.getNumberOfShapes(); ++index) + { + obj.loadShape(theShapeFile, + index); + + if(obj.isLoaded()) + { + switch(obj.getType()) + { + case SHPT_POLYGON: + case SHPT_POLYGONZ: + { + loadPolygon(obj); + break; + } + case SHPT_POINT: + case SHPT_POINTZ: + { + loadPoint(obj); + break; + } + case SHPT_ARC: + case SHPT_ARCZ: + { + loadArc(obj); + break; + } + case SHPT_NULL: + { + break; + } + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimEsriShapeFileFilter::loadShapeFile\n" + << "SHAPE " << obj.getTypeByName() + << " Not supported" << endl; + break; + } + } + } + } + + theCurrentObject = theShapeCache .begin(); + if(theViewProjection) + { + transformObjects(); + } + else + { + checkAndSetDefaultView(); + } + } + + return true; +} + +void ossimEsriShapeFileFilter::loadPolygon(ossimShapeObject& obj) +{ + int starti = 0; + int endi = 0; + if(obj.getNumberOfParts() > 1) + { + starti = obj.getShapeObject()->panPartStart[0]; + endi = obj.getShapeObject()->panPartStart[1]; + } + else + { + starti = 0; + endi = obj.getShapeObject()->nVertices; + } + + vector<ossimGpt> groundPolygon; + for(ossim_uint32 part = 0; part < obj.getNumberOfParts(); ++part) + { + if(obj.getPartType(part) != SHPP_RING) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimEsriShapeFileFilter::loadPolygon\n" + << "Part = " << obj.getPartByName(part) + << " not supported for shape = " + << obj.getTypeByName() << endl; + break; + } + groundPolygon.clear(); + for(ossim_int32 vertexNumber = starti; vertexNumber < endi; ++vertexNumber) + { + groundPolygon.push_back(ossimGpt(obj.getShapeObject()->padfY[vertexNumber], + obj.getShapeObject()->padfX[vertexNumber])); + + } + starti = endi; + if((part + 2) < obj.getNumberOfParts()) + { + endi = obj.getShapeObject()->panPartStart[part+2]; + } + else + { + endi = obj.getShapeObject()->nVertices; + } + + ossimRgbVector color; + + if(theFillFlag) + { + color = theBrushColor; + } + else + { + color = thePenColor; + } + + if(theBorderSize != 0.0) + { + ossimGeoPolygon tempPoly(groundPolygon); + ossimGeoPolygon tempPoly2; + + tempPoly.stretchOut(tempPoly2, + theBorderSize); + groundPolygon = tempPoly2.getVertexList(); + + } + + ossimGeoAnnotationObject *newGeoObj = new ossimGeoAnnotationPolyObject(groundPolygon, + theFillFlag, + color.getR(), + color.getG(), + color.getB(), + theThickness); + newGeoObj->setName(theFeatureName); + theShapeCache.insert(make_pair(obj.getId(), + newGeoObj)); + } +} + +void ossimEsriShapeFileFilter::loadPoint(ossimShapeObject& obj) +{ + int n = obj.getNumberOfVertices(); + + if(n) + { + ossimGpt gpt(obj.getShapeObject()->padfY[0], + obj.getShapeObject()->padfX[0]); + + ossimRgbVector color; + + if(theFillFlag) + { + color = theBrushColor; + } + else + { + color = thePenColor; + } + ossimGeoAnnotationEllipseObject *newGeoObj = + new ossimGeoAnnotationEllipseObject(gpt, + thePointWidthHeight, + theFillFlag, + color.getR(), + color.getG(), + color.getB(), + theThickness); + newGeoObj->setEllipseWidthHeightUnitType(OSSIM_PIXEL); + newGeoObj->setName(theFeatureName); + theShapeCache.insert(make_pair(obj.getId(), + newGeoObj)); + + } +} + +void ossimEsriShapeFileFilter::loadArc(ossimShapeObject& obj) +{ + int starti = 0; + int endi = 0; + if(obj.getNumberOfParts() > 1) + { + starti = obj.getShapeObject()->panPartStart[0]; + endi = obj.getShapeObject()->panPartStart[1]; + } + else + { + starti = 0; + endi = obj.getShapeObject()->nVertices; + } + + vector<ossimGpt> groundPolygon; + for(ossim_uint32 part = 0; part < obj.getNumberOfParts(); ++part) + { + if(obj.getPartType(part) != SHPP_RING) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimEsriShapeFileFilter::loadArc\n" + << "Part = " << obj.getPartByName(part) + << " not supported for shape = " + << obj.getTypeByName() << endl; + break; + } + groundPolygon.clear(); + for(ossim_int32 vertexNumber = starti; vertexNumber < endi; ++vertexNumber) + { + groundPolygon.push_back(ossimGpt(obj.getShapeObject()->padfY[vertexNumber], + obj.getShapeObject()->padfX[vertexNumber])); + + } + starti = endi; + if((part + 2) < obj.getNumberOfParts()) + { + endi = obj.getShapeObject()->panPartStart[part+2]; + } + else + { + endi = obj.getShapeObject()->nVertices; + } + + ossimRgbVector color; + + if(theFillFlag) + { + color = theBrushColor; + } + else + { + color = thePenColor; + } + + ossimGeoAnnotationObject *newGeoObj = new ossimGeoAnnotationPolyLineObject(groundPolygon, + color.getR(), + color.getG(), + color.getB(), + theThickness); + newGeoObj->setName(theFeatureName); + theShapeCache.insert(make_pair(obj.getId(), + newGeoObj)); + } +} + +bool ossimEsriShapeFileFilter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimString s; + + kwl.add(prefix, + ossimKeywordNames::FILENAME_KW, + theShapeFile.getFilename(), + true); + + kwl.add(prefix, + ossimKeywordNames::MAX_QUADTREE_LEVELS_KW, + theMaxQuadTreeLevels, + true); + + s = ossimString::toString((int)thePenColor.getR()) + " " + + ossimString::toString((int)thePenColor.getG()) + " " + + ossimString::toString((int)thePenColor.getB()); + + kwl.add(prefix, + ossimKeywordNames::PEN_COLOR_KW, + s.c_str(), + true); + + s = ossimString::toString((int)theBrushColor.getR()) + " " + + ossimString::toString((int)theBrushColor.getG()) + " " + + ossimString::toString((int)theBrushColor.getB()); + + kwl.add(prefix, + ossimKeywordNames::BRUSH_COLOR_KW, + s.c_str(), + true); + + kwl.add(prefix, + ossimKeywordNames::FILL_FLAG_KW, + (int)theFillFlag, + true); + + kwl.add(prefix, + ossimKeywordNames::FEATURE_NAME_KW, + theFeatureName.c_str(), + true); + + kwl.add(prefix, + ossimKeywordNames::THICKNESS_KW, + theThickness, + true); + + ossimString border; + border = ossimString::toString(theBorderSize); + border += " degrees"; + kwl.add(prefix, + ossimKeywordNames::BORDER_SIZE_KW, + border, + true); + + s = ossimString::toString((int)thePointWidthHeight.x) + " " + + ossimString::toString((int)thePointWidthHeight.y) + " "; + + kwl.add(prefix, + ossimKeywordNames::POINT_WIDTH_HEIGHT_KW, + s.c_str(), + true); + + if(theViewProjection) + { + ossimString newPrefix = prefix; + newPrefix += "view_proj."; + theViewProjection->saveState(kwl, + newPrefix.c_str()); + } + + return ossimAnnotationSource::saveState(kwl, prefix); +} + +bool ossimEsriShapeFileFilter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + + const char* quadLevels = kwl.find(prefix, ossimKeywordNames::MAX_QUADTREE_LEVELS_KW); + const char* filename = kwl.find(prefix, ossimKeywordNames::FILENAME_KW); + const char* penColor = kwl.find(prefix, ossimKeywordNames::PEN_COLOR_KW); + const char* brushColor = kwl.find(prefix, ossimKeywordNames::BRUSH_COLOR_KW); + const char* featureName = kwl.find(prefix, ossimKeywordNames::FEATURE_NAME_KW); + const char* fillFlag = kwl.find(prefix, ossimKeywordNames::FILL_FLAG_KW); + const char* thickness = kwl.find(prefix, ossimKeywordNames::THICKNESS_KW); + const char* pointWh = kwl.find(prefix, ossimKeywordNames::POINT_WIDTH_HEIGHT_KW); + const char* border_size = kwl.find(prefix, ossimKeywordNames::BORDER_SIZE_KW); + + deleteCache(); + + if(thickness) + { + theThickness = ossimString(thickness).toLong(); + } + if(quadLevels) + { + theMaxQuadTreeLevels = ossimString(quadLevels).toLong(); + } + + if(penColor) + { + int r, g, b; + istringstream s(penColor); + s>>r>>g>>b; + thePenColor = ossimRgbVector((ossim_uint8)r, (ossim_uint8)g, (ossim_uint8)b); + } + + if(brushColor) + { + int r, g, b; + istringstream s(brushColor); + s>>r>>g>>b; + theBrushColor = ossimRgbVector((ossim_uint8)r, (ossim_uint8)g, (ossim_uint8)b); + } + if(pointWh) + { + double w, h; + istringstream s(pointWh); + s>>w>>h; + thePointWidthHeight = ossimDpt(w, h); + } + + if(fillFlag) + { + theFillFlag = ossimString(fillFlag).toBool(); + } + + if(border_size) + { + istringstream input(border_size); + + ossimString s; + input >> s; + + theBorderSize = s.toDouble(); + + ossimString s2; + + input >> s2; + + s2 = s2.upcase(); + + if(s2 == "US") + { + theBorderSizeUnits = OSSIM_US_SURVEY_FEET; + } + else if(s2 == "METERS") + { + theBorderSizeUnits = OSSIM_METERS; + } + else if(s2 == "FEET") + { + theBorderSizeUnits = OSSIM_FEET; + } + else + { + theBorderSizeUnits = OSSIM_DEGREES; + } + ossimUnitConversionTool unitConvert(theBorderSize, + theBorderSizeUnits); + + theBorderSize = unitConvert.getValue(OSSIM_DEGREES); + theBorderSizeUnits = OSSIM_DEGREES; + } + else + { + theBorderSize = 0.0; + theBorderSizeUnits = OSSIM_DEGREES; + } + + theFeatureName = featureName; + + removeViewProjection(); + + ossimString newPrefix = prefix; + newPrefix += "view_proj."; + + theViewProjection = ossimProjectionFactoryRegistry::instance()->createProjection(kwl, + newPrefix.c_str()); + theOwnsViewProjectionFlag = true; + + if(filename) + { + loadShapeFile(ossimFilename(filename)); + } + + checkAndSetDefaultView(); + + + return ossimAnnotationSource::loadState(kwl, prefix); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimEsriShapeFileFilter.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimEsriShapeFileFilter.h new file mode 100644 index 0000000000..13a28e837c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimEsriShapeFileFilter.h @@ -0,0 +1,270 @@ +//******************************************************************* +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimEsriShapeFileFilter.h,v 1.26 2005/05/23 15:40:28 gpotts Exp $ + +#ifndef ossimEsriShapeFileFilter_HEADER +#define ossimEsriShapeFileFilter_HEADER +#include <map> +#include <imaging/annotation/ossimGeoAnnotationSource.h> +#include <base/common/ossimViewInterface.h> +#include <vec/shape/shapefil.h> +#include <vec/shape/ossimShapeFile.h> +#include <base/data_types/color_space/ossimRgbVector.h> + +class ossimGeoAnnotationObject; +class ossimAnnotationObject; + +/*! + * class ossimEsriShapeFileFilter + * + * This class is used to render shape files. Iif this filter has + * an input connection to an ossimImageSourceInterface then it will + * draw any vectors over the input tile. If it is not connected + * it will just render its vector data to a tile and return it. + * <pre> + * supported keywords: + * + * max_quadtree_levels: // number of levels for faster hit testing + * // defaults to 10 + * + * fill_flag: // 1 for true 0 for false. Default is false + * // and specifies how all closed surfaces are + * // to be drawn + * + * feature_name: // currently not used. + * + * pen_color: // specified in Red Green Blue and is the color used + * // if the fill flag is not specified. Future changes + * // might be to include this as an outline color for + * // filled objects. Default is white. Example: 255 255 255 + * + * brush_color: // Color used by objects that have the fill flag enabled + * // format is Red Green Blue. Default is white. + * + * line_thickness: // line drawing thickness in pixels. + * + * border_size: // can be us feet, feet, meters, degrees, + * // will automatically expand all polygons by the + * // specified size. Uses the centroid to estimate + * // non degree units when converting to degrees. + * + * point_width_height: // Specifies the width and height of a point object in + * // pixels. Default is 1 and has the following format + * // w h. Example 1 1 + * + * filename: // The esri shape file to be used + * + * example Keyword list: See ossimAnnotationSource for any additional keywords + * + * + * brush_color: 255 255 255 + * feature_name: + * filename: + * fill_flag: 0 + * max_quadtree_levels: 10 + * pen_color: 255 255 255 + * point_width_height: 1 1 + * thickness: 1 + * border_size: 25 meters + * type: ossimEsriShapeFileFilter + * + * </pre> + */ +class ossimEsriShapeFileFilter : public ossimAnnotationSource, + public ossimViewInterface +{ +public: + ossimEsriShapeFileFilter(ossimImageSource* inputSource=NULL); + ~ossimEsriShapeFileFilter(); + + virtual bool setView(ossimObject* baseObject, + bool ownsTheView = false); + + virtual ossimObject* getView(); + virtual const ossimObject* getView()const; + + virtual bool addObject(ossimAnnotationObject* anObject); + virtual void transformObjects(ossimProjection* projection=0); + virtual void setProjection(ossimProjection* projection, + bool ownsProjectionFlag=false); + virtual bool getImageGeometry(ossimKeywordlist& kwl, + const char* prefix = 0); + virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0)const; + virtual void computeBoundingRect(); + + virtual void drawAnnotations(ossimRefPtr<ossimImageData> tile); + /*! + * Will delete the current objects within the layer and add all + * objects in the passed in file. + */ + virtual bool loadShapeFile(const ossimFilename& shapeFile); + + virtual ossimFilename getFilename()const + { + return theShapeFile.getFilename(); + } + virtual ossim_int32 getMaxQuadTreeLevels()const + { + return theMaxQuadTreeLevels; + } + + virtual void setMaxQuadTreeLevels(ossim_int32 levels) + { + theMaxQuadTreeLevels = (levels>0?levels:10); + } + + virtual void setBrushColor(const ossimRgbVector& brushColor) + { + theBrushColor = brushColor; + } + + virtual void setPenColor(const ossimRgbVector& penColor) + { + thePenColor = penColor; + } + + virtual ossimRgbVector getPenColor()const + { + return thePenColor; + } + + virtual ossimRgbVector getBrushColor()const + { + return theBrushColor; + } + + virtual bool getFillFlag()const + { + return theFillFlag; + } + + virtual void setFillFlag(bool flag) + { + theFillFlag=flag; + } + virtual ossimString getFeatureName()const + { + return theFeatureName; + } + virtual void setFeatureName(const ossimString& name) + { + theFeatureName = name; + } + + virtual void setThickness(ossim_int32 thickness) + { + theThickness = thickness >= 0? thickness:1; + } + virtual ossim_int32 getThickness()const + { + return theThickness; + } + virtual void setPointRadius(double r) + { + thePointWidthHeight = ossimDpt(fabs(r)*2, fabs(r)*2); + } + virtual double getPointRadius()const + { + return thePointWidthHeight.x/2.0; + } + + virtual ossimAnnotationObject* nextObject(bool restart=false) + { + if(restart) + { + theCurrentObject = theShapeCache.begin(); + } + else + { + if(theCurrentObject != theShapeCache.end()) + { + ++theCurrentObject; + } + + } + + if(theCurrentObject == theShapeCache.end()) + { + return (ossimAnnotationObject*)NULL; + } + return (*theCurrentObject).second; + } + + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=NULL)const; + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=NULL); +protected: + + /*! + * This holds the output projection. This is used to transform + * the objects to the projection plane. + */ + ossimProjection* theViewProjection; + + /*! + * If the shape file is projected we must know the projector. + * This will allow us to define the geographic objects correctly. + */ + ossimProjection* theShapeFileProjection; + + /*! + * Flag that indicates if we own the view projection. + */ + bool theOwnsViewProjectionFlag; + + /*! + * Specifies if its image/pixel space, Geographic, projected ...etc. + */ + ossimCoordinateSystemType theCoordinateSystem; + + /*! + * If its projected this spceifies the type of unit. We + * need to know if the projection is in meters, feet, us survey feet + * ... etc. + */ + ossimUnitType theUnitType; + + SHPTree* theTree; + + ossimShapeFile theShapeFile; + + double theMinArray[4]; + double theMaxArray[4]; + + int theMaxQuadTreeLevels; + ossimRgbVector thePenColor; + ossimRgbVector theBrushColor; + bool theFillFlag; + ossim_int32 theThickness; + ossimString theFeatureName; + ossimDpt thePointWidthHeight; + double theBorderSize; + ossimUnitType theBorderSizeUnits; + + mutable std::multimap<int, ossimAnnotationObject*>::iterator theCurrentObject; + + std::multimap<int, ossimAnnotationObject*> theShapeCache; + ossimDrect theBoundingRect; + + void removeViewProjection(); + void deleteCache(); + void checkAndSetDefaultView(); + + virtual void loadPolygon(ossimShapeObject& obj); + virtual void loadPoint(ossimShapeObject& obj); + virtual void loadArc(ossimShapeObject& obj); + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGdFont.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGdFont.h new file mode 100644 index 0000000000..5a6b4cc024 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGdFont.h @@ -0,0 +1,54 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimGdFont.h,v 1.1 2001/06/05 19:11:52 gpotts Exp $ +#ifndef ossimGdFont_HEADER +#define ossimGdFont_HEADER +/* gd.h: declarations file for the graphic-draw module. + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. This software is provided "AS IS." Thomas Boutell and + * Boutell.Com, Inc. disclaim all warranties, either express or implied, + * including but not limited to implied warranties of merchantability and + * fitness for a particular purpose, with respect to this code and accompanying + * documentation. */ + +typedef struct { + /* # of characters in font */ + int nchars; + /* First character is numbered... (usually 32 = space) */ + int offset; + /* Character width and height */ + int w; + int h; + /* Font data; array of characters, one row after another. + Easily included in code, also easily loaded from + data files. */ + char *data; +} ossimGdFont; + +/* Text functions take these. */ +typedef ossimGdFont *ossimGdFontPtr; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGdFontExterns.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGdFontExterns.h new file mode 100644 index 0000000000..a8fb1d75dd --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGdFontExterns.h @@ -0,0 +1,33 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimGdFontExterns.h,v 1.1 2001/06/05 19:11:52 gpotts Exp $ +#ifndef ossimGdFontExterns_HEADER +#define ossimGdFontExterns_HEADER +#include "ossimGdFont.h" +extern ossimGdFontPtr ossimGdFontGiant; +extern ossimGdFontPtr ossimGdFontTiny; +extern ossimGdFontPtr ossimGdFontSmall; +extern ossimGdFontPtr ossimGdFontLarge; +extern ossimGdFontPtr ossimGdFontMediumBold; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationBitmap.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationBitmap.cpp new file mode 100644 index 0000000000..e242232347 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationBitmap.cpp @@ -0,0 +1,168 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimGeoAnnotationBitmap.cpp,v 1.8 2005/02/18 15:27:41 dburken Exp $ + +#include <imaging/annotation/ossimGeoAnnotationBitmap.h> +#include <projections/ossimProjection.h> +#include <base/data_types/ossimIrect.h> + +RTTI_DEF1(ossimGeoAnnotationBitmap, + "ossimGeoAnnotationBitmap", + ossimGeoAnnotationObject) + +ossimGeoAnnotationBitmap::ossimGeoAnnotationBitmap( + const ossimGpt& center, + ossimRefPtr<ossimImageData> imageData, + unsigned char r, + unsigned char g, + unsigned char b) + :ossimGeoAnnotationObject(r, g, b), + theCenterPoint(center), + theProjectedPoint(0,0), + theImageData(NULL) +{ + if(imageData.valid() && + (imageData->getScalarType()==OSSIM_UCHAR)) + { + theImageData = imageData; + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimGeoAnnotationBitmap::ossimGeoAnnotationBitmap\n" + << "Invalid image data passed to ossimGeoAnnotationBitmap " + << "constructor" << endl; + } +} + +ossimGeoAnnotationBitmap::ossimGeoAnnotationBitmap( + const ossimGeoAnnotationBitmap& rhs) + : + ossimGeoAnnotationObject(rhs), + theCenterPoint(theCenterPoint), + theProjectedPoint(theProjectedPoint), + theImageData(rhs.theImageData) +{ +} + +ossimGeoAnnotationBitmap::~ossimGeoAnnotationBitmap() +{ +} + +std::ostream& ossimGeoAnnotationBitmap::print(std::ostream& out)const +{ + out << "center: " << theCenterPoint << endl; + return out; +} + +void ossimGeoAnnotationBitmap::draw(ossimRgbImage& anImage)const +{ + ossimRefPtr<ossimImageData> destination = anImage.getImageData(); + + if(!destination) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimGeoAnnotationBitmap::draw\n" + << "ERROR: can't draw annotation bitmap to NULL buffer" << endl; + + return; + } + ossimIrect destinationRect = destination->getImageRectangle(); + ossimIrect srcRect = theImageData->getImageRectangle(); + if(!srcRect.intersects(destinationRect)) + { + return; + } + ossimIrect clipRect = srcRect.clipToRect(destinationRect); + + long clipHeight = (long)clipRect.height(); + long clipWidth = (long)clipRect.width(); + + + if(clipRect.width() != 1.0 && + clipRect.height() != 1.0) + { + long destinationOffset = (long)(((clipRect.ul().y - destinationRect.ul().y)* destinationRect.width()) + + (clipRect.ul().x - destinationRect.ul().x)); + long srcOffset = (long)(((clipRect.ul().y - srcRect.ul().y)*srcRect.width()) + + (clipRect.ul().x - srcRect.ul().x)); + long destinationIndex = destinationOffset; + long srcIndex = srcOffset; + long num_bands = destination->getNumberOfBands(); + ossim_int32 s_width = (ossim_int32)srcRect.width(); + ossim_int32 d_width = (ossim_int32)destinationRect.width(); + + num_bands = num_bands > 3? 3:num_bands; + + const ossim_uint8* imageDataBuf = static_cast<const ossim_uint8*>(theImageData->getBuf()); + unsigned char colorArray[3]; + colorArray[0] = theRed; + colorArray[1] = theGreen; + colorArray[2] = theBlue; + for (long band=0; band<num_bands; ++band) + { + ossim_uint8* destinationBand = static_cast<ossim_uint8*>(destination->getBuf(band)); + destinationIndex = destinationOffset; + srcIndex = srcOffset; + for(long line = 0; line < clipHeight; ++line) + { + for(long col = 0; col < clipWidth; ++col) + { + if(imageDataBuf[srcIndex + col]) + { + destinationBand[destinationIndex + col] = colorArray[band]; + } + } + srcIndex += s_width; + destinationIndex += d_width; + } + } + } +} + +void ossimGeoAnnotationBitmap::getBoundingRect(ossimDrect& rect)const +{ + rect = ossimDrect(0,0,0,0); + + if(theImageData.valid()) + { + rect = theImageData->getImageRectangle(); + } +} + +void ossimGeoAnnotationBitmap::transform(ossimProjection* projection) +{ + if(projection) + { + projection->worldToLineSample(theCenterPoint, + theProjectedPoint); + theProjectedPoint = ossimIpt(theProjectedPoint); + if(theImageData.valid()) + { + ossimDpt origin(theProjectedPoint.x - theImageData->getWidth()/2.0, + theProjectedPoint.y - theImageData->getHeight()/2.0); + + theImageData->setOrigin(origin); + } + } +} + +void ossimGeoAnnotationBitmap::setImageData( + ossimRefPtr<ossimImageData>& imageData) +{ + theImageData = imageData; +} + +void ossimGeoAnnotationBitmap::computeBoundingRect() +{ + // nothing to be done since we don't support + // rotated bitmaps yet. +} diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationBitmap.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationBitmap.h new file mode 100644 index 0000000000..01efcde127 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationBitmap.h @@ -0,0 +1,71 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimGeoAnnotationBitmap.h,v 1.10 2005/02/18 15:27:41 dburken Exp $ +#ifndef ossimGeoAnnotationBitmap_HEADER +#define ossimGeoAnnotationBitmap_HEADER +#include <imaging/annotation/ossimGeoAnnotationObject.h> + +class OSSIMDLLEXPORT ossimGeoAnnotationBitmap: public ossimGeoAnnotationObject +{ +public: + + ossimGeoAnnotationBitmap(const ossimGpt& center= ossimGpt(0,0,0), + ossimRefPtr<ossimImageData> imageData=NULL, + unsigned char r = 255, + unsigned char g = 255, + unsigned char b = 255); + + ossimGeoAnnotationBitmap(const ossimGeoAnnotationBitmap& rhs); + + virtual ~ossimGeoAnnotationBitmap(); + + virtual ossimObject* dup()const + { + return new ossimGeoAnnotationBitmap(*this); + } + virtual bool intersects(const ossimDrect& rect) const + { + if(theImageData.valid()) + { + return theImageData->getImageRectangle().intersects(rect); + } + + return false; + } + virtual ossimGeoAnnotationBitmap* getNewClippedObject(const ossimDrect& rect)const + { + ossimGeoAnnotationBitmap* result = (ossimGeoAnnotationBitmap*)dup(); + + ossimNotify(ossimNotifyLevel_WARN) << "ossimGeoAnnotationBitmap::getNewClippedObject WRNING: not implemented" << std::endl; + + return result; + } + virtual void applyScale(double x, + double y) + { + + } + virtual std::ostream& print(std::ostream& out)const; + virtual void draw(ossimRgbImage& anImage)const; + virtual void getBoundingRect(ossimDrect& rect)const; + virtual void transform(ossimProjection* projection); + virtual void setImageData(ossimRefPtr<ossimImageData>& imageData); + virtual void computeBoundingRect(); + +protected: + ossimGpt theCenterPoint; + ossimDpt theProjectedPoint; + ossimRefPtr<ossimImageData> theImageData; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationEllipseObject.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationEllipseObject.cpp new file mode 100644 index 0000000000..3203d98057 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationEllipseObject.cpp @@ -0,0 +1,307 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimGeoAnnotationEllipseObject.cpp,v 1.16 2005/12/16 14:28:27 dburken Exp $ + +#include <sstream> + +#include <imaging/annotation/ossimGeoAnnotationEllipseObject.h> +#include <imaging/annotation/ossimAnnotationEllipseObject.h> +#include <projections/ossimProjection.h> +#include <base/misc/lookup_tables/ossimUnitTypeLut.h> +#include <base/misc/ossimUnitConversionTool.h> + +RTTI_DEF1(ossimGeoAnnotationEllipseObject, + "ossimGeoAnnotationEllipseObject", + ossimGeoAnnotationObject); + +ossimGeoAnnotationEllipseObject::ossimGeoAnnotationEllipseObject( + const ossimGpt& center, + const ossimDpt& widthHeight, + bool enableFill, + ossim_uint8 r, + ossim_uint8 g, + ossim_uint8 b, + ossim_uint8 thickness) + :ossimGeoAnnotationObject(r, g, b, thickness), + theProjectedEllipse(NULL), + theCenter(center), + theWidthHeight(widthHeight), + theEllipseWidthHeightUnitType(OSSIM_PIXEL) // default to image space +{ + theProjectedEllipse = new ossimAnnotationEllipseObject(ossimDpt(0,0), + ossimDpt(0,0), + enableFill, + r, + g, + b, + thickness); +} + +ossimGeoAnnotationEllipseObject::ossimGeoAnnotationEllipseObject( + const ossimGeoAnnotationEllipseObject& rhs) + :ossimGeoAnnotationObject(rhs), + theProjectedEllipse(rhs.theProjectedEllipse?(ossimAnnotationEllipseObject*)rhs.theProjectedEllipse->dup():(ossimAnnotationEllipseObject*)NULL), + theCenter(rhs.theCenter), + theWidthHeight(rhs.theWidthHeight), + theEllipseWidthHeightUnitType(rhs.theEllipseWidthHeightUnitType) +{ +} + +ossimGeoAnnotationEllipseObject::~ossimGeoAnnotationEllipseObject() +{ + if(theProjectedEllipse) + { + delete theProjectedEllipse; + theProjectedEllipse = NULL; + } +} + +ossimObject* ossimGeoAnnotationEllipseObject::dup()const +{ + return new ossimGeoAnnotationEllipseObject(*this); +} + +void ossimGeoAnnotationEllipseObject::applyScale(double x, + double y) +{ + if(theProjectedEllipse) theProjectedEllipse->applyScale(x, y); + theCenter.lond(theCenter.lond()*x); + theCenter.latd(theCenter.latd()*y); + theWidthHeight .x *= x; + theWidthHeight .y *= y; +} + +std::ostream& ossimGeoAnnotationEllipseObject::print(std::ostream& out)const +{ + out << "center ground: " << theCenter << endl + << "width height image space flag = " << theEllipseWidthHeightUnitType + << endl + << *theProjectedEllipse; + return out; +} + +void ossimGeoAnnotationEllipseObject::draw(ossimRgbImage& anImage)const +{ + if(theProjectedEllipse) + { + theProjectedEllipse->draw(anImage); + } +} + +bool ossimGeoAnnotationEllipseObject::intersects(const ossimDrect& rect)const +{ + if(theProjectedEllipse) + { + theProjectedEllipse->intersects(rect); + } + + return false; +} + +ossimAnnotationObject* ossimGeoAnnotationEllipseObject::getNewClippedObject(const ossimDrect& rect)const +{ + if(intersects(rect)) + { + if(theProjectedEllipse) + { + return theProjectedEllipse->getNewClippedObject(rect); + } + } + + return (ossimAnnotationObject*)NULL; +} + +void ossimGeoAnnotationEllipseObject::getBoundingRect(ossimDrect& rect)const +{ + if(theProjectedEllipse) + { + theProjectedEllipse->getBoundingRect(rect); + } + else + { + rect.makeNan(); + } +} + +void ossimGeoAnnotationEllipseObject::computeBoundingRect() +{ + if(theProjectedEllipse) + { + theProjectedEllipse->computeBoundingRect(); + } +} + +void ossimGeoAnnotationEllipseObject::transform(ossimProjection* projection) +{ + if(!projection) + { + return; + } + + // Ellipse center, height and width in image space. + ossimDpt projectedCenter; + ossimDpt projectedWidthHeight; + + // first get the center projected + projection->worldToLineSample(theCenter, projectedCenter); + + getWidthHeightInPixels(projectedWidthHeight, projection); + + theProjectedEllipse->setCenterWidthHeight(projectedCenter, + projectedWidthHeight); +} + +bool ossimGeoAnnotationEllipseObject::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + ossimUnitTypeLut ul; + + kwl.add(prefix, "center", theCenter.toString().c_str()); + kwl.add(prefix, "ellipse_width", theWidthHeight.x); + kwl.add(prefix, "ellipse_height", theWidthHeight.y); + kwl.add(prefix, "fill", (ossim_int32)theProjectedEllipse->getFill()); + kwl.add(prefix, "units", + ul.getEntryString(theEllipseWidthHeightUnitType).c_str()); + + return ossimGeoAnnotationObject::saveState(kwl, prefix); +} + +bool ossimGeoAnnotationEllipseObject::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + if (!theProjectedEllipse) + { + return false; + } + + //--- + // Base class state must be called first to pick up colors... + //--- + bool status = ossimGeoAnnotationObject::loadState(kwl, prefix); + if (status == true) + { + theProjectedEllipse->setColor(theRed, theGreen, theBlue); + theProjectedEllipse->setThickness(theThickness); + } + + const char* center = kwl.find(prefix, "center"); + const char* ellipse_width = kwl.find(prefix, "ellipse_width"); + const char* ellipse_height = kwl.find(prefix, "ellipse_height"); + const char* fill = kwl.find(prefix, "fill"); + const char* units = kwl.find(prefix, "units"); + + if(units) + { + ossimUnitTypeLut ul; + theEllipseWidthHeightUnitType = + static_cast<ossimUnitType>(ul.getEntryNumber(units)); + if (theEllipseWidthHeightUnitType == OSSIM_UNIT_UNKNOWN) + { + theEllipseWidthHeightUnitType = OSSIM_PIXEL; + } + } + + if (center) + { + std::istringstream is(center); + is >> theCenter; + } + if(ellipse_width) + { + theWidthHeight.x = ossimString(ellipse_width).toDouble(); + } + if(ellipse_height) + { + theWidthHeight.y = ossimString(ellipse_height).toDouble(); + } + if(fill) + { + if(ossimString(fill).toLong()) + { + theProjectedEllipse->setFill(true); + } + else + { + theProjectedEllipse->setFill(false); + } + } + + return status; +} + +void ossimGeoAnnotationEllipseObject::setEllipseWidthHeightUnitType( + ossimUnitType type) +{ + theEllipseWidthHeightUnitType = type; +} + +void ossimGeoAnnotationEllipseObject::getWidthHeightInPixels( + ossimDpt& widthHeight, const ossimProjection* projection) const +{ + switch (theEllipseWidthHeightUnitType) + { + case OSSIM_PIXEL: + { + widthHeight = theWidthHeight; + + break; + } + + case OSSIM_DEGREES: + case OSSIM_MINUTES: + case OSSIM_SECONDS: + { + ossimGpt origin = projection->origin(); + ossimDpt gsd = projection->getMetersPerPixel(); + + ossimUnitConversionTool uct(origin, + theWidthHeight.x, + theEllipseWidthHeightUnitType); + + double x = uct.getValue(OSSIM_METERS); + + uct.setValue(theWidthHeight.y, theEllipseWidthHeightUnitType); + + double y = uct.getValue(OSSIM_METERS); + + widthHeight.x = ceil(x/gsd.x); + widthHeight.y = ceil(y/gsd.y); + + break; + } + + case OSSIM_METERS: + { + ossimDpt gsd = projection->getMetersPerPixel(); + widthHeight.x = static_cast<ossim_int32>(theWidthHeight.x/gsd.x+0.5); + widthHeight.y = static_cast<ossim_int32>(theWidthHeight.y/gsd.y+0.5); + + break; + } + + default: + { + ossimDpt gsd = projection->getMetersPerPixel(); + + ossimUnitConversionTool uct(theWidthHeight.x, + theEllipseWidthHeightUnitType); + + double x = uct.getValue(OSSIM_METERS); + + uct.setValue(theWidthHeight.y, theEllipseWidthHeightUnitType); + + double y = uct.getValue(OSSIM_METERS); + + widthHeight.x = ceil(x/gsd.x); + widthHeight.y = ceil(y/gsd.y); + + break; + } + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationEllipseObject.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationEllipseObject.h new file mode 100644 index 0000000000..069ede1832 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationEllipseObject.h @@ -0,0 +1,86 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See LICENSE.txt file in the top level directory. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimGeoAnnotationEllipseObject.h,v 1.12 2005/12/09 21:49:02 dburken Exp $ +#ifndef ossimGeoAnnotationEllipseObject_HEADER +#define ossimGeoAnnotationEllipseObject_HEADER +#include <imaging/annotation/ossimGeoAnnotationObject.h> + +class ossimAnnotationEllipseObject; + +class OSSIMDLLEXPORT ossimGeoAnnotationEllipseObject : public ossimGeoAnnotationObject +{ +public: + + /*! + * It is important to note that the width and height + * should be specified in width = deltaLon and + * height = deltaLat. Use the ossimDpt .lat and .lon + * attributes to set it. + */ + ossimGeoAnnotationEllipseObject(const ossimGpt& center = ossimGpt(0,0), + const ossimDpt& widthHeight = ossimDpt(0,0), + bool enableFill = false, + ossim_uint8 r = 255, + ossim_uint8 g = 255, + ossim_uint8 b = 255, + ossim_uint8 thickness = 1); + ossimGeoAnnotationEllipseObject(const ossimGeoAnnotationEllipseObject& rhs); + virtual ~ossimGeoAnnotationEllipseObject(); + + virtual ossimObject* dup()const; + + virtual void applyScale(double x, double y); + virtual std::ostream& print(std::ostream& out)const; + virtual void draw(ossimRgbImage& anImage)const; + virtual bool intersects(const ossimDrect& rect)const; + virtual ossimAnnotationObject* getNewClippedObject(const ossimDrect& rect)const; + virtual void getBoundingRect(ossimDrect& rect)const; + virtual void computeBoundingRect(); + virtual void transform(ossimProjection* projection); + + /** + * Saves the current state of this object. + * + * Keywords: + * + * center: ( 42.403388263727003, -90.708557648541046, 0.0, WGE ) + * + * ellipse_width: 500 + * + * ellipse_height: 500 + * + * units: meters + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual void setEllipseWidthHeightUnitType(ossimUnitType type); + +protected: + + void getWidthHeightInPixels(ossimDpt& widthHeight, + const ossimProjection* projection) const; + + ossimAnnotationEllipseObject* theProjectedEllipse; + ossimGpt theCenter; + ossimDpt theWidthHeight; + + ossimUnitType theEllipseWidthHeightUnitType; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationFontObject.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationFontObject.cpp new file mode 100644 index 0000000000..367e20dae4 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationFontObject.cpp @@ -0,0 +1,290 @@ +//************************************************************************* +// License: See top level LICENSE.txt file. +// +// Author: Garrett Potts +// +//************************************************************************* +//$Id: ossimGeoAnnotationFontObject.cpp,v 1.7 2005/12/16 14:28:27 dburken Exp $ + +#include <sstream> + +#include <imaging/annotation/ossimGeoAnnotationFontObject.h> +#include <imaging/annotation/ossimAnnotationFontObject.h> +#include <projections/ossimProjection.h> +#include <fonts/ossimFont.h> +#include <fonts/factory/ossimFontFactoryRegistry.h> +#include <base/context/ossimNotifyContext.h> + +RTTI_DEF1(ossimGeoAnnotationFontObject, + "ossimGeoAnnotationFontObject", + ossimGeoAnnotationObject); + + +ossimGeoAnnotationFontObject::ossimGeoAnnotationFontObject() + : + ossimGeoAnnotationObject(), + theCenterGround(), + theFont(NULL), + theFontInfo(), + theAnnotationFontObject(NULL) +{ + theFont = (ossimFont*)ossimFontFactoryRegistry::instance()-> + getDefaultFont()->dup(); + if (!theFont) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimGeoAnnotationFontObject::ossimGeoAnnotationFontObject" + << " WARNING: No font support..." + << endl; + } + theAnnotationFontObject = + new ossimAnnotationFontObject(ossimIpt(0,0), + ossimString("")); + + theAnnotationFontObject->setFont(theFont, false); + +} + +ossimGeoAnnotationFontObject::ossimGeoAnnotationFontObject( + const ossimGpt& location, + const ossimString& s, + const ossimIpt& pixelSize, + double rotation, + const ossimDpt& scale, + const ossimDpt& shear, + ossim_uint8 r, + ossim_uint8 g, + ossim_uint8 b) + : + ossimGeoAnnotationObject(r, g, b), + theCenterGround(location), + theFont(NULL), + theFontInfo(), + theAnnotationFontObject(NULL) +{ + ossimDpt pt; + pt.makeNan(); + + theAnnotationFontObject = new ossimAnnotationFontObject(pt, + s, + pixelSize, + rotation, + scale, + shear, + r, + g, + b); +} + +ossimGeoAnnotationFontObject::ossimGeoAnnotationFontObject( + const ossimGeoAnnotationFontObject& rhs) + : + ossimGeoAnnotationObject(rhs), + theCenterGround(rhs.theCenterGround), + theFont(rhs.theFont?(ossimFont*)rhs.theFont->dup():(ossimFont*)NULL), + theFontInfo(), + theAnnotationFontObject( + new ossimAnnotationFontObject( + ossimDpt(OSSIM_DBL_NAN, OSSIM_DBL_NAN), + rhs.theAnnotationFontObject->theString, + rhs.theAnnotationFontObject->thePixelSize, + rhs.theAnnotationFontObject->theRotation, + ossimDpt(rhs.theAnnotationFontObject->theHorizontalScale, + rhs.theAnnotationFontObject->theVerticalScale), + ossimDpt(rhs.theAnnotationFontObject->theHorizontalShear, + rhs.theAnnotationFontObject->theVerticalShear), + rhs.theRed, + rhs.theGreen, + rhs.theBlue)) +{ + theAnnotationFontObject->setFont(theFont, false); +} + +ossimGeoAnnotationFontObject::~ossimGeoAnnotationFontObject() +{ + if(theAnnotationFontObject) + { + delete theAnnotationFontObject; + theAnnotationFontObject = NULL; + } + if(theFont) + { + delete theFont; + theFont = NULL; + } +} + +ossimObject* ossimGeoAnnotationFontObject::dup()const +{ + return new ossimGeoAnnotationFontObject(*this); +} + + +void ossimGeoAnnotationFontObject::setFont(ossimFont* font) +{ + if(theFont) + { + delete theFont; + theFont = NULL; + } + theFont = font; + + theAnnotationFontObject->setFont(theFont, false); +} + +ossimFont* ossimGeoAnnotationFontObject::getFont() +{ + return theFont; +} + +void ossimGeoAnnotationFontObject::setPointSize(const ossimIpt& size) +{ + if(theAnnotationFontObject) + { + theAnnotationFontObject->setPointSize(size); + } +} + +void ossimGeoAnnotationFontObject::setRotation(double rotation) +{ + if(theAnnotationFontObject) + { + theAnnotationFontObject->setRotation(rotation); + } +} + +void ossimGeoAnnotationFontObject::setScale(const ossimDpt& scale) +{ + if(theAnnotationFontObject) + { + theAnnotationFontObject->setScale(scale); + } +} + +void ossimGeoAnnotationFontObject::setShear(const ossimDpt& shear) +{ + if(theAnnotationFontObject) + { + theAnnotationFontObject->setShear(shear); + } +} + +void ossimGeoAnnotationFontObject::setColor(ossim_uint8 r, + ossim_uint8 g, + ossim_uint8 b) +{ + if(theAnnotationFontObject) + { + theAnnotationFontObject->setColor(r, g, b); + } +} + +void ossimGeoAnnotationFontObject::transform(ossimProjection* projection) +{ + if(projection) + { + ossimDpt ipt; + + projection->worldToLineSample(theCenterGround, ipt); + theAnnotationFontObject->setPositionCenter(ipt); + theAnnotationFontObject->computeBoundingRect(); + } +} + +void ossimGeoAnnotationFontObject::setCenterGround(const ossimGpt& gpt) +{ + theCenterGround = gpt; +} + +ossimAnnotationFontObject* ossimGeoAnnotationFontObject::getFontObject() +{ + return theAnnotationFontObject; +} + +void ossimGeoAnnotationFontObject::draw(ossimRgbImage& anImage)const +{ + theAnnotationFontObject->draw(anImage); +} + +void ossimGeoAnnotationFontObject::computeBoundingRect() +{ + theAnnotationFontObject->computeBoundingRect(); +} + +void ossimGeoAnnotationFontObject::getBoundingRect(ossimDrect& rect)const +{ + theAnnotationFontObject->getBoundingRect(rect); +} + +ossimAnnotationObject* ossimGeoAnnotationFontObject::getNewClippedObject( + const ossimDrect& rect)const +{ + return (ossimAnnotationObject*)NULL; +} + +bool ossimGeoAnnotationFontObject::intersects(const ossimDrect& rect)const +{ + return theAnnotationFontObject->intersects(rect); +} + +void ossimGeoAnnotationFontObject::applyScale(double x, double y) +{ + theAnnotationFontObject->applyScale(x,y); +} + +bool ossimGeoAnnotationFontObject::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + kwl.add(prefix, "center", theCenterGround.toString().c_str()); + kwl.add(prefix, "text", theAnnotationFontObject->getString().c_str()); + theFontInfo.saveState(kwl, prefix); + + return ossimGeoAnnotationObject::saveState(kwl, prefix); +} + +bool ossimGeoAnnotationFontObject::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + //--- + // Base class state must be called first to pick up colors... + //--- + bool status = ossimGeoAnnotationObject::loadState(kwl, prefix); + + theAnnotationFontObject->setColor(theRed, theGreen, theBlue); + theAnnotationFontObject->setThickness(theThickness); + + const char* lookup; + + lookup = kwl.find(prefix, "text"); + if (lookup) + { + theAnnotationFontObject->setString(ossimString(lookup)); + } + + lookup = kwl.find(prefix, "center"); + if (lookup) + { + std::istringstream is(lookup); + is >> theCenterGround; + } + + // Get the font information. + theFontInfo.loadState(kwl, prefix); + + // See if we can make a font. + ossimFont* f = ossimFontFactoryRegistry::instance()-> + createFont(theFontInfo); + if (f) + { + if (theFont) + { + delete theFont; + } + theFont = f; + theAnnotationFontObject->setFont(theFont, false); + } + + theAnnotationFontObject->setGeometryInformation(theFontInfo); + + return status; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationFontObject.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationFontObject.h new file mode 100644 index 0000000000..f52a7b8b97 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationFontObject.h @@ -0,0 +1,128 @@ +//************************************************************************* +// License: See top level LICENSE.txt file. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimGeoAnnotationFontObject.h,v 1.6 2005/12/11 17:12:16 dburken Exp $ +#ifndef ossimGeoAnnotationFontObject_HEADER +#define ossimGeoAnnotationFontObject_HEADER +#include <imaging/annotation/ossimGeoAnnotationObject.h> +#include <imaging/annotation/ossimAnnotationFontObject.h> + +class ossimFont; + +class ossimGeoAnnotationFontObject : public ossimGeoAnnotationObject +{ +public: + ossimGeoAnnotationFontObject(); + + + ossimGeoAnnotationFontObject(const ossimGpt& location, + const ossimString& s, + const ossimIpt& pixelSize = ossimIpt(12, 12), + double rotation = 0.0, + const ossimDpt& scale = ossimDpt(1.0, 1.0), + const ossimDpt& shear = ossimDpt(0.0,0.0), + ossim_uint8 r=255, + ossim_uint8 g=255, + ossim_uint8 b=255); + ossimGeoAnnotationFontObject(const ossimGeoAnnotationFontObject& rhs); + + virtual ~ossimGeoAnnotationFontObject(); + + virtual ossimObject* dup()const; + + ossimAnnotationFontObject* getFontObject(); + + void setFont(ossimFont* font); + + ossimFont* getFont(); + + virtual void setPointSize(const ossimIpt& size); + + virtual void setRotation(double rotation); + + virtual void setScale(const ossimDpt& scale); + + virtual void setShear(const ossimDpt& shear); + + virtual void setColor(ossim_uint8 r, + ossim_uint8 g, + ossim_uint8 b); + + virtual void transform(ossimProjection* projection); + + virtual void setCenterGround(const ossimGpt& gpt); + + virtual void draw(ossimRgbImage& anImage)const; + + virtual void computeBoundingRect(); + + virtual void getBoundingRect(ossimDrect& rect)const; + + virtual ossimAnnotationObject* getNewClippedObject( + const ossimDrect& rect)const; + + virtual bool intersects(const ossimDrect& rect)const; + + virtual void applyScale(double x, double y); + + /** + * Saves the current state of this object. + * + * @see loadState for keywords. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + * + * Keywords: + * + * For center format is: ( latitude, longitude, height, datum_code ) + * center: ( 42.01, -90.71, 0.0, WGE ) + * + * For point_size format is: "( x, y )" + * point_size: ( 18, 18 ) + * + * For scale format is: "( x, y )" + * scale: ( 1.0, 1.0 ) + * + * For shear format is: "( x, y )" + * shear: ( 0.0, 0.0 ) + * + * text: Airport + * + * USE ONE OF family_name: + * family_name: URW Palladio L + * family_name: gd sans + * family_name: URW Bookman L + * family_name: Nimbus Roman No9 L + * family_name: Nimbus Sans L + * family_name: URW Palladio L + * family_name: Century Schoolbook L + * family_name: Nimbus Mono L + * family_name: Nimbus Sans L Condensed + * + * USE ONE OF style_name: + * style_name: normal + * style_name: bold + * style_name: italic + * style_name: bold italic + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +protected: + ossimGpt theCenterGround; + ossimFont* theFont; + ossimFontInformation theFontInfo; + ossimAnnotationFontObject* theAnnotationFontObject; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationGdBitmapFont.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationGdBitmapFont.cpp new file mode 100644 index 0000000000..41e4eb7de2 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationGdBitmapFont.cpp @@ -0,0 +1,139 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimGeoAnnotationGdBitmapFont.cpp,v 1.8 2004/05/23 17:49:37 dburken Exp $ +#include "ossimGeoAnnotationGdBitmapFont.h" +#include "ossimAnnotationGdBitmapFont.h" +#include "projections/ossimProjection.h" + +RTTI_DEF1(ossimGeoAnnotationGdBitmapFont, "ossimGeoAnnotationGdBitmapFont", ossimGeoAnnotationObject) + +ossimGeoAnnotationGdBitmapFont::ossimGeoAnnotationGdBitmapFont(const ossimGpt& position, + const ossimString &text, + ossimGdFontPtr font, + unsigned char r, + unsigned char g, + unsigned char b, + long thickness) + : ossimGeoAnnotationObject(r, g, b, thickness), + thePosition(position) +{ + theProjectedFont = new ossimAnnotationGdBitmapFont(ossimDpt(0,0), + text, + font, + r, + g, + b, + thickness); +} + +ossimGeoAnnotationGdBitmapFont::ossimGeoAnnotationGdBitmapFont(const ossimGeoAnnotationGdBitmapFont& rhs) + :ossimGeoAnnotationObject(rhs), + theProjectedFont(rhs.theProjectedFont?(ossimAnnotationGdBitmapFont*)theProjectedFont->dup():(ossimAnnotationGdBitmapFont*)NULL), + thePosition(rhs.thePosition) +{ +} + + +ossimGeoAnnotationGdBitmapFont::~ossimGeoAnnotationGdBitmapFont() +{ + if(theProjectedFont) + { + delete theProjectedFont; + theProjectedFont=NULL; + } +} + +void ossimGeoAnnotationGdBitmapFont::applyScale(double x, double y) +{ + thePosition.lond(thePosition.lond()*x); + thePosition.latd(thePosition.latd()*y); + + if(theProjectedFont) + { + theProjectedFont->applyScale(x, y); + } +} + +std::ostream& ossimGeoAnnotationGdBitmapFont::print(std::ostream& out)const +{ + out << "position: " << thePosition; + theProjectedFont->print(out); + return out; +} + +void ossimGeoAnnotationGdBitmapFont::draw(ossimRgbImage& anImage)const +{ + theProjectedFont->draw(anImage); +} + +void ossimGeoAnnotationGdBitmapFont::getBoundingRect(ossimDrect& rect)const +{ + theProjectedFont->getBoundingRect(rect); +} + +bool ossimGeoAnnotationGdBitmapFont::intersects(const ossimDrect& rect)const +{ + if(theProjectedFont) + { + return theProjectedFont->intersects(rect); + } + + return false; +} + +ossimAnnotationObject* ossimGeoAnnotationGdBitmapFont::getNewClippedObject(const ossimDrect& rect)const +{ + if(intersects(rect)) + { + if(theProjectedFont) + { + return theProjectedFont->getNewClippedObject(rect); + } + } + + return (ossimAnnotationObject*)NULL; +} + +void ossimGeoAnnotationGdBitmapFont::computeBoundingRect() +{ + theProjectedFont->computeBoundingRect(); +} + +void ossimGeoAnnotationGdBitmapFont::transform(ossimProjection* projection) +{ + ossimDpt position; + + projection->worldToLineSample(thePosition, position); + + theProjectedFont->setUpperLeftTextPosition(position); +} + +void ossimGeoAnnotationGdBitmapFont::setText(const ossimString& text) +{ + theProjectedFont->setText(text); +} + +void ossimGeoAnnotationGdBitmapFont::setFont(ossimGdFontPtr font) +{ + theProjectedFont->setFont(font); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationGdBitmapFont.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationGdBitmapFont.h new file mode 100644 index 0000000000..eb933574d9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationGdBitmapFont.h @@ -0,0 +1,74 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimGeoAnnotationGdBitmapFont.h,v 1.8 2004/05/23 17:49:37 dburken Exp $ +#ifndef ossimGeoAnnotationGdBitmapFont_HEADER +#define ossimGeoAnnotationGdBitmapFont_HEADER + +#include "ossimGeoAnnotationObject.h" +#include "ossimGdFont.h" +#include "ossimGdFontExterns.h" +class ossimAnnotationGdBitmapFont; + +class OSSIMDLLEXPORT ossimGeoAnnotationGdBitmapFont : public ossimGeoAnnotationObject +{ +public: + ossimGeoAnnotationGdBitmapFont(const ossimGpt& position=ossimGpt(0,0,0), + const ossimString &text=ossimString(""), + ossimGdFontPtr font = ossimGdFontLarge, + unsigned char r = 255, + unsigned char g = 255, + unsigned char b = 255, + long thickness = 1); + ossimGeoAnnotationGdBitmapFont(const ossimGeoAnnotationGdBitmapFont& rhs); + virtual ~ossimGeoAnnotationGdBitmapFont(); + virtual ossimObject* dup()const + { + return new ossimGeoAnnotationGdBitmapFont(*this); + } + virtual void applyScale(double x, double y); + virtual std::ostream& print(std::ostream& out)const; + virtual void draw(ossimRgbImage& anImage)const; + virtual bool intersects(const ossimDrect& rect)const; + virtual ossimAnnotationObject* getNewClippedObject(const ossimDrect& rect)const; + virtual void getBoundingRect(ossimDrect& rect)const; + virtual void computeBoundingRect(); + /*! + * Add the projection interface to all + * geographically defined objects. + */ + virtual void transform(ossimProjection* projection); + + virtual void setText(const ossimString& text); + virtual void setFont(ossimGdFontPtr font); + +protected: + ossimAnnotationGdBitmapFont* theProjectedFont; + + /*! + * Will be the upper left corner of text; + */ + ossimGpt thePosition; +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationLineObject.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationLineObject.cpp new file mode 100644 index 0000000000..398673b91c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationLineObject.cpp @@ -0,0 +1,141 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimGeoAnnotationLineObject.cpp,v 1.9 2004/05/23 17:49:37 dburken Exp $ +#include "ossimGeoAnnotationLineObject.h" +#include "ossimAnnotationLineObject.h" +#include "projections/ossimProjection.h" + +RTTI_DEF1(ossimGeoAnnotationLineObject, "ossimGeoAnnotationLineObject", ossimGeoAnnotationObject) + +ossimGeoAnnotationLineObject::ossimGeoAnnotationLineObject(const ossimGpt& start, + const ossimGpt& end, + unsigned char r, + unsigned char g, + unsigned char b, + long thickness) + :ossimGeoAnnotationObject(r, g, b, thickness), + theProjectedLineObject(NULL), + theStart(start), + theEnd(end) +{ + theProjectedLineObject = new ossimAnnotationLineObject(ossimDpt(0,0), + ossimDpt(0,0), + r, + g, + b, + thickness); +} + +ossimGeoAnnotationLineObject::ossimGeoAnnotationLineObject(const ossimGeoAnnotationLineObject& rhs) + :ossimGeoAnnotationObject(rhs), + theProjectedLineObject(rhs.theProjectedLineObject?(ossimAnnotationLineObject*)rhs.theProjectedLineObject->dup():(ossimAnnotationLineObject*)NULL), + theStart(rhs.theStart), + theEnd(rhs.theEnd) +{ + +} + + +ossimGeoAnnotationLineObject::~ossimGeoAnnotationLineObject() +{ + if(theProjectedLineObject) + { + delete theProjectedLineObject; + theProjectedLineObject = NULL; + } +} + +void ossimGeoAnnotationLineObject::applyScale(double x, double y) +{ + theStart.lond(theStart.lond()*x); + theStart.latd(theStart.latd()*y); + theEnd.lond(theEnd.lond()*x); + theEnd.latd(theEnd.latd()*y); + + if(theProjectedLineObject) + { + theProjectedLineObject->applyScale(x, y); + } +} + +void ossimGeoAnnotationLineObject::transform(ossimProjection* projection) +{ + if(projection) + { + ossimDpt projectedStart; + ossimDpt projectedEnd; + + projection->worldToLineSample(theStart, + projectedStart); + projection->worldToLineSample(theEnd, + projectedEnd); + + theProjectedLineObject->setLine(projectedStart, + projectedEnd); + } +} + +std::ostream& ossimGeoAnnotationLineObject::print(std::ostream& out)const +{ + out << "start ground: " << theStart << endl; + out << "end ground: " << theEnd << endl; + return out; +} + +void ossimGeoAnnotationLineObject::draw(ossimRgbImage& anImage)const +{ + theProjectedLineObject->draw(anImage); +} + +bool ossimGeoAnnotationLineObject::intersects(const ossimDrect& rect)const +{ + if(theProjectedLineObject) + { + return theProjectedLineObject->intersects(rect); + } + + return false; +} + +ossimAnnotationObject* ossimGeoAnnotationLineObject::getNewClippedObject(const ossimDrect& rect)const +{ + if(intersects(rect)) + { + if(theProjectedLineObject) + { + return theProjectedLineObject->getNewClippedObject(rect); + } + } + + return (ossimAnnotationObject*)NULL; +} + +void ossimGeoAnnotationLineObject::getBoundingRect(ossimDrect& rect)const +{ + theProjectedLineObject->getBoundingRect(rect); +} + +void ossimGeoAnnotationLineObject::computeBoundingRect() +{ + theProjectedLineObject->computeBoundingRect(); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationLineObject.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationLineObject.h new file mode 100644 index 0000000000..453400d7b4 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationLineObject.h @@ -0,0 +1,65 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimGeoAnnotationLineObject.h,v 1.7 2004/05/23 17:49:37 dburken Exp $ +#ifndef ossimGeoAnnotationLineObject_HEADER +#define ossimGeoAnnotationLineObject_HEADER +#include "base/data_types/ossimGpt.h" +#include "ossimGeoAnnotationObject.h" + +class OSSIMDLLEXPORT ossimAnnotationLineObject; + +class ossimGeoAnnotationLineObject : public ossimGeoAnnotationObject +{ +public: + ossimGeoAnnotationLineObject(const ossimGpt& start, + const ossimGpt& end, + unsigned char r=255, + unsigned char g=255, + unsigned char b=255, + long thickness=1); + ossimGeoAnnotationLineObject(const ossimGeoAnnotationLineObject& rhs); + virtual ~ossimGeoAnnotationLineObject(); + + virtual ossimObject* dup()const + { + return new ossimGeoAnnotationLineObject(*this); + } + + virtual void applyScale(double x, double y); + virtual void transform(ossimProjection* projection); + virtual std::ostream& print(std::ostream& out)const; + virtual bool intersects(const ossimDrect& rect)const; + virtual ossimAnnotationObject* getNewClippedObject(const ossimDrect& rect)const; + virtual void draw(ossimRgbImage& anImage)const; + virtual void getBoundingRect(ossimDrect& rect)const; + virtual void computeBoundingRect(); + +protected: + ossimAnnotationLineObject* theProjectedLineObject; + ossimGpt theStart; + ossimGpt theEnd; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationMultiEllipseObject.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationMultiEllipseObject.cpp new file mode 100644 index 0000000000..c868dbbaca --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationMultiEllipseObject.cpp @@ -0,0 +1,186 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimGeoAnnotationMultiEllipseObject.cpp,v 1.7 2004/05/23 17:49:37 dburken Exp $ + +#include <imaging/annotation/ossimGeoAnnotationMultiEllipseObject.h> +#include <imaging/annotation/ossimAnnotationMultiEllipseObject.h> +#include <projections/ossimProjection.h> + +ossimGeoAnnotationMultiEllipseObject::ossimGeoAnnotationMultiEllipseObject() + :ossimGeoAnnotationObject(), + theProjectedObject(new ossimAnnotationMultiEllipseObject()), + theWidthHeight(1,1), + theFillFlag(false) +{ + theProjectedObject->setFillFlag(false); +} + +ossimGeoAnnotationMultiEllipseObject::ossimGeoAnnotationMultiEllipseObject(const std::vector<ossimGpt>& pointList, + const ossimDpt& widthHeight, + bool enableFill, + unsigned char r, + unsigned char g, + unsigned char b, + long thickness) + :ossimGeoAnnotationObject(r, g, b, thickness), + theProjectedObject(new ossimAnnotationMultiEllipseObject(widthHeight,enableFill, r, g, b, thickness )), + thePointList(pointList), + theWidthHeight(widthHeight), + theFillFlag(enableFill) +{ + +} + +ossimGeoAnnotationMultiEllipseObject::ossimGeoAnnotationMultiEllipseObject(const ossimDpt& widthHeight, + bool enableFill, + unsigned char r, + unsigned char g, + unsigned char b, + long thickness) + :ossimGeoAnnotationObject(r, g, b,thickness), + theProjectedObject(new ossimAnnotationMultiEllipseObject(widthHeight,enableFill, r, g, b, thickness )), + theWidthHeight(widthHeight), + theFillFlag(enableFill) +{ +} + +ossimGeoAnnotationMultiEllipseObject::ossimGeoAnnotationMultiEllipseObject(const ossimGeoAnnotationMultiEllipseObject& rhs) + :ossimGeoAnnotationObject(rhs), + theProjectedObject((ossimAnnotationMultiEllipseObject*)rhs.theProjectedObject->dup()), + thePointList(rhs.thePointList), + theWidthHeight(rhs.theWidthHeight), + theFillFlag(rhs.theFillFlag) +{ +} + +void ossimGeoAnnotationMultiEllipseObject::transform(ossimProjection* projection) +{ + theProjectedObject->resize(thePointList.size()); + int i = 0; + int bounds = (int)thePointList.size(); + + for(i = 0; i < bounds; ++i) + { + projection->worldToLineSample(thePointList[i], (*theProjectedObject)[i]); + + } + computeBoundingRect(); +} + +void ossimGeoAnnotationMultiEllipseObject::setFillFlag(bool fillFlag) +{ + theProjectedObject->setFillFlag(fillFlag); + theFillFlag = fillFlag; +} + +void ossimGeoAnnotationMultiEllipseObject::setColor(unsigned char r, + unsigned char g, + unsigned char b) +{ + ossimAnnotationObject::setColor(r,g,b); + if(theProjectedObject) + { + theProjectedObject->setColor(r,g,b); + } +} + +void ossimGeoAnnotationMultiEllipseObject::setThickness(long thickness) +{ + ossimAnnotationObject::setThickness(thickness); + if(theProjectedObject) + { + theProjectedObject->setThickness(thickness); + } +} + + +void ossimGeoAnnotationMultiEllipseObject::applyScale(double x, + double y) +{ + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimGeoAnnotationMultiEllipseObject::applyScale NOT IMPLEMENTED" + << endl; +} + +void ossimGeoAnnotationMultiEllipseObject::draw(ossimRgbImage& anImage)const +{ + theProjectedObject->draw(anImage); +} + +bool ossimGeoAnnotationMultiEllipseObject::intersects(const ossimDrect& rect)const +{ + return theProjectedObject->intersects(rect); +} + +void ossimGeoAnnotationMultiEllipseObject::setWidthHeight(const ossimDpt& widthHeight) +{ + theWidthHeight = widthHeight; + theProjectedObject->setWidthHeight(widthHeight); +} + +std::ostream& ossimGeoAnnotationMultiEllipseObject::print(std::ostream& out)const +{ + theProjectedObject->print(out); + return out; +} + +void ossimGeoAnnotationMultiEllipseObject::getBoundingRect(ossimDrect& rect)const +{ + theProjectedObject->getBoundingRect(rect); +} + +void ossimGeoAnnotationMultiEllipseObject::computeBoundingRect() +{ + theProjectedObject->computeBoundingRect(); +} + +ossimObject* ossimGeoAnnotationMultiEllipseObject::dup()const +{ + return new ossimGeoAnnotationMultiEllipseObject(*this); +} + +ossimAnnotationObject* ossimGeoAnnotationMultiEllipseObject::getNewClippedObject(const ossimDrect& rect)const +{ + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimGeoAnnotationMultiEllipseObject::getNewClippedObject " + << "NOT IMPLEMENTED" << endl; + return (ossimAnnotationObject*)dup(); +} + +void ossimGeoAnnotationMultiEllipseObject::addPoint(const ossimGpt& point) +{ + thePointList.push_back(point); +} + +void ossimGeoAnnotationMultiEllipseObject::setPoint(int i, + const ossimGpt& point) +{ + thePointList[i] = point; +} + +void ossimGeoAnnotationMultiEllipseObject::resize(ossim_uint32 newSize) +{ + if(newSize) + { + thePointList.resize(newSize); + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationMultiEllipseObject.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationMultiEllipseObject.h new file mode 100644 index 0000000000..27b00a0649 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationMultiEllipseObject.h @@ -0,0 +1,83 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimGeoAnnotationMultiEllipseObject.h,v 1.8 2004/05/23 17:49:37 dburken Exp $ +#ifndef ossimGeoAnnotationMultiEllipseObject_HEADER +#define ossimGeoAnnotationMultiEllipseObject_HEADER +#include "ossimGeoAnnotationObject.h" +#include <vector> +class ossimAnnotationMultiEllipseObject; +class OSSIMDLLEXPORT ossimGeoAnnotationMultiEllipseObject : public ossimGeoAnnotationObject +{ +public: + ossimGeoAnnotationMultiEllipseObject(); + ossimGeoAnnotationMultiEllipseObject(const std::vector<ossimGpt>& centerPoints, + const ossimDpt& widthHeight, + bool enableFill = false, + unsigned char r = 255, + unsigned char g = 255, + unsigned char b = 255, + long thickness = 1); + ossimGeoAnnotationMultiEllipseObject(const ossimDpt& widthHeight, + bool enableFill = false, + unsigned char r = 255, + unsigned char g = 255, + unsigned char b = 255, + long thickness = 1); + ossimGeoAnnotationMultiEllipseObject(const ossimGeoAnnotationMultiEllipseObject& rhs); + + virtual ossimObject* dup()const; + + virtual ossimAnnotationObject* getNewClippedObject(const ossimDrect& rect)const; + + virtual void transform(ossimProjection* projection); + + virtual void applyScale(double x, double y); + + virtual void draw(ossimRgbImage& anImage)const; + virtual bool intersects(const ossimDrect& rect)const; + + virtual void addPoint(const ossimGpt& point); + + virtual void setColor(unsigned char r, + unsigned char g, + unsigned char b); + virtual void setThickness(long thickness); + + virtual void setPoint(int i, const ossimGpt& point); + + virtual void setWidthHeight(const ossimDpt& widthHeight); + virtual void resize(ossim_uint32 newSize); + + virtual void setFillFlag(bool fillFlag); + virtual std::ostream& print(std::ostream& out)const; + virtual void getBoundingRect(ossimDrect& rect)const; + virtual void computeBoundingRect(); + +protected: + ossimAnnotationMultiEllipseObject* theProjectedObject; + + std::vector<ossimGpt> thePointList; + ossimDpt theWidthHeight; + bool theFillFlag; +}; + +#endif /* #ifndef ossimGeoAnnotationMultiEllipseObject_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationMultiPolyLineObject.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationMultiPolyLineObject.cpp new file mode 100644 index 0000000000..1f021df206 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationMultiPolyLineObject.cpp @@ -0,0 +1,354 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See LICENSE.txt file in the top level directory. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimGeoAnnotationMultiPolyLineObject.cpp,v 1.7 2005/12/08 13:42:58 dburken Exp $ + +#include <sstream> + +#include <imaging/annotation/ossimGeoAnnotationMultiPolyLineObject.h> +#include <imaging/annotation/ossimAnnotationMultiPolyLineObject.h> +#include <projections/ossimProjection.h> + +RTTI_DEF1(ossimGeoAnnotationMultiPolyLineObject, + "ossimGeoAnnotationMultiPolyLineObject", + ossimGeoAnnotationObject); + +ossimGeoAnnotationMultiPolyLineObject::ossimGeoAnnotationMultiPolyLineObject() + : + ossimGeoAnnotationObject(), + theMultiPolyLine(), + theBoundingRect(), + theDatum(ossimDatumFactory::instance()->wgs84()), + theProjectedPolyLineObject(NULL) +{ + allocateProjectedPolyLine(); + theBoundingRect.makeNan(); +} + +ossimGeoAnnotationMultiPolyLineObject::ossimGeoAnnotationMultiPolyLineObject( + const vector<ossimPolyLine>& multiPoly, + ossim_uint8 r, + ossim_uint8 g, + ossim_uint8 b, + ossim_uint8 thickness) + : + ossimGeoAnnotationObject(r, g, b, thickness), + theMultiPolyLine(multiPoly), + theBoundingRect(), + theDatum(ossimDatumFactory::instance()->wgs84()), + theProjectedPolyLineObject(NULL) +{ + allocateProjectedPolyLine(); + theBoundingRect.makeNan(); +} + +ossimGeoAnnotationMultiPolyLineObject::ossimGeoAnnotationMultiPolyLineObject( + const ossimGeoAnnotationMultiPolyLineObject& rhs) + :ossimGeoAnnotationObject(rhs), + theMultiPolyLine(rhs.theMultiPolyLine), + theBoundingRect(rhs.theBoundingRect), + theDatum(rhs.theDatum), + theProjectedPolyLineObject(rhs.theProjectedPolyLineObject?(ossimAnnotationMultiPolyLineObject*)rhs.theProjectedPolyLineObject->dup():NULL) +{ +} + +ossimObject* ossimGeoAnnotationMultiPolyLineObject::dup()const +{ + return new ossimGeoAnnotationMultiPolyLineObject(*this); +} + +ossimGeoAnnotationMultiPolyLineObject::~ossimGeoAnnotationMultiPolyLineObject() +{ + if(theProjectedPolyLineObject) + { + delete theProjectedPolyLineObject; + theProjectedPolyLineObject = NULL; + } +} + +void ossimGeoAnnotationMultiPolyLineObject::applyScale(double x, double y) +{ + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimGeoAnnotationPolyLineObject::applyScale NOT IMPLEMENTED!!!!" + << endl; +} + +void ossimGeoAnnotationMultiPolyLineObject::transform(ossimProjection* projection) +{ + cout << "ossimGeoAnnotationMultiPolyLineObject::transform entered..." + << endl; + + if(!projection) return; + int polyI = 0; + int pointI = 0; + + allocateProjectedPolyLine(); + if(!theProjectedPolyLineObject) + { + return; + } + std::vector<ossimPolyLine>& multiPolyLine = theProjectedPolyLineObject->getMultiPolyLine(); + ossimGpt tempPoint(0,0, OSSIM_DBL_NAN, theDatum); + for(polyI = 0; polyI < (int)theMultiPolyLine.size(); ++polyI) + { + ossimPolyLine polyLine; + + int numberOfVertices = (int)theMultiPolyLine[polyI].getNumberOfVertices(); + for(pointI = 0; pointI < numberOfVertices; ++pointI) + { + tempPoint.latd(theMultiPolyLine[polyI][pointI].lat); + tempPoint.lond(theMultiPolyLine[polyI][pointI].lon); + ossimDpt temp; + projection->worldToLineSample(tempPoint, temp); + if(!temp.hasNans()) + { + multiPolyLine[polyI].addPoint(temp); + } + } + multiPolyLine[polyI].roundToIntegerBounds(true); + } + +} + +std::ostream& ossimGeoAnnotationMultiPolyLineObject::print(std::ostream& out)const +{ + ossimNotify(ossimNotifyLevel_INFO) + << "ossimGeoAnnotationMultiPolyLineObject::print\n" + << "Poly line size: " << theMultiPolyLine.size() << endl; + return out; +} + +bool ossimGeoAnnotationMultiPolyLineObject::intersects(const ossimDrect& rect)const +{ + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimGeoAnnotationMultiPolyObject::intersects NOT IMPLEMENTED" + << endl; + return false; +} + +ossimAnnotationObject* ossimGeoAnnotationMultiPolyLineObject::getNewClippedObject(const ossimDrect& rect)const +{ + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimGeoAnnotationMultiPolyObject::getNewClippedObject " + << "NOT IMPLEMENTED" << endl; + + return (ossimAnnotationObject*)(dup()); +} + +void ossimGeoAnnotationMultiPolyLineObject::draw(ossimRgbImage& anImage)const +{ + if(theProjectedPolyLineObject) + { + theProjectedPolyLineObject->draw(anImage); + } +} + +void ossimGeoAnnotationMultiPolyLineObject::getBoundingRect(ossimDrect& rect)const +{ + rect = theBoundingRect; +} + +void ossimGeoAnnotationMultiPolyLineObject::addPoint(ossim_uint32 polygonIndex, + const ossimGpt& pt) +{ + if(polygonIndex < theMultiPolyLine.size()) + { + theMultiPolyLine[polygonIndex].addPoint(pt); + + // we will have to reset the projected polygon + if(theProjectedPolyLineObject) + { + delete theProjectedPolyLineObject; + theProjectedPolyLineObject = NULL; + } + } +} + +void ossimGeoAnnotationMultiPolyLineObject::setMultiPolyLine( + const vector<ossimPolyLine>& multiPoly) +{ + theMultiPolyLine = multiPoly; + if(theProjectedPolyLineObject) + { + delete theProjectedPolyLineObject; + theProjectedPolyLineObject = NULL; + } +} + +void ossimGeoAnnotationMultiPolyLineObject::computeBoundingRect() +{ + theBoundingRect.makeNan(); + if(theProjectedPolyLineObject) + { + theProjectedPolyLineObject->computeBoundingRect(); + theProjectedPolyLineObject->getBoundingRect(theBoundingRect); + } + +} + +bool ossimGeoAnnotationMultiPolyLineObject::isPointWithin(const ossimDpt& imagePoint)const +{ + if(theProjectedPolyLineObject) + { + return theProjectedPolyLineObject->isPointWithin(imagePoint); + } + + return false; +} + +void ossimGeoAnnotationMultiPolyLineObject::setColor(ossim_uint8 r, + ossim_uint8 g, + ossim_uint8 b) +{ + ossimAnnotationObject::setColor(r, g, b); + if(theProjectedPolyLineObject) + { + theProjectedPolyLineObject->setColor(r, g, b); + } +} + +void ossimGeoAnnotationMultiPolyLineObject::setThickness(long thickness) +{ + ossimAnnotationObject::setThickness(thickness); + if(theProjectedPolyLineObject) + { + theProjectedPolyLineObject->setThickness(thickness); + } +} + +void ossimGeoAnnotationMultiPolyLineObject::setDatum(const ossimDatum* datum) +{ + theDatum = datum; +} + +const ossimDatum* ossimGeoAnnotationMultiPolyLineObject::getDatum()const +{ + return theDatum; +} + +const std::vector<ossimPolyLine>& +ossimGeoAnnotationMultiPolyLineObject::getMultiPolyLine() const +{ + return theMultiPolyLine; +} + +std::vector<ossimPolyLine>& +ossimGeoAnnotationMultiPolyLineObject::getMultiPolyLine() +{ + return theMultiPolyLine; +} + +bool ossimGeoAnnotationMultiPolyLineObject::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + ossim_uint32 vIdx = 0; + + for(ossim_uint32 i = 0; i < theMultiPolyLine.size(); ++i) + { + ossimPolyLine pl = theMultiPolyLine[i]; + for(ossim_uint32 j = 0; j < pl.getNumberOfVertices(); ++j) + { + ossimDpt dpt = pl[j]; + std::ostringstream os; + os << setprecision(15) << dpt.x << " " << dpt.y << endl; + + ossimString key = "v"; + key += ossimString::toString(vIdx); + kwl.add(prefix, key.c_str(), os.str().c_str()); + ++vIdx; + } + } + + return ossimGeoAnnotationObject::saveState(kwl, prefix); +} + +bool ossimGeoAnnotationMultiPolyLineObject::loadState( + const ossimKeywordlist& kwl, const char* prefix) +{ + cout << "ossimGeoAnnotationMultiPolyLineObject::loadState entered..." + << endl; + + //--- + // Base class state must be called first to pick up colors... + //--- + bool status = ossimGeoAnnotationObject::loadState(kwl, prefix); + + ossim_uint32 index = 0; + ossimString copyPrefix = prefix; + ossim_uint32 count = kwl.getNumberOfSubstringKeys(copyPrefix+ + "v[0-9]"); + + + cout << "count: " << count << endl; + + ossim_uint32 numberOfMatches = 0; + const ossim_uint32 MAX_INDEX = count + 100; + ossimPolyLine pl; + + while(numberOfMatches < count) + { + ossimString key = "v"; + key += ossimString::toString(index); + + cout << "prefix: " << prefix + << "\nkey: " << key + << endl; + + const char* lookup = kwl.find(prefix, key.c_str()); + if (lookup) + { + ++numberOfMatches; + ossimDpt dpt; + + std::istringstream is(lookup); + is >> dpt.x >> dpt.y; + cout << "added point: " << dpt << endl; + pl.addPoint(dpt); + } + + if (pl.size() == 2) + { + cout << "added line: " << pl << endl; + + theMultiPolyLine.push_back(pl); + pl.clear(); + } + + ++index; + + if (index > MAX_INDEX) // Avoid infinite loop... + { + break; + } + } + + return status; +} + +void ossimGeoAnnotationMultiPolyLineObject::allocateProjectedPolyLine() +{ + if(theProjectedPolyLineObject) + { + delete theProjectedPolyLineObject; + theProjectedPolyLineObject = NULL; + } + + vector<ossimPolyLine> polyList; + + if(theMultiPolyLine.size()) + { + polyList.resize(theMultiPolyLine.size()); + + theProjectedPolyLineObject = new ossimAnnotationMultiPolyLineObject( + polyList, + theRed, + theGreen, + theBlue, + theThickness); + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationMultiPolyLineObject.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationMultiPolyLineObject.h new file mode 100644 index 0000000000..aaa629f7a0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationMultiPolyLineObject.h @@ -0,0 +1,90 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See LICENSE.txt file in the top level directory. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimGeoAnnotationMultiPolyLineObject.h,v 1.5 2005/12/08 13:42:58 dburken Exp $ +#ifndef ossimGeoAnnotationMultiPolyLineObject_HEADER +#define ossimGeoAnnotationMultiPolyLineObject_HEADER + +#include <imaging/annotation/ossimGeoAnnotationObject.h> +#include <imaging/annotation/ossimAnnotationMultiPolyObject.h> +#include <imaging/annotation/ossimAnnotationMultiPolyLineObject.h> +#include <base/data_types/ossimIpt.h> +#include <base/data_types/ossimPolyLine.h> + +class ossimDatum; + +class OSSIMDLLEXPORT ossimGeoAnnotationMultiPolyLineObject : public ossimGeoAnnotationObject +{ +public: + ossimGeoAnnotationMultiPolyLineObject(); + ossimGeoAnnotationMultiPolyLineObject(const vector<ossimPolyLine>& multiPolyLine, + ossim_uint8 r=255, + ossim_uint8 g=255, + ossim_uint8 b=255, + ossim_uint8 thickness=1); + + ossimGeoAnnotationMultiPolyLineObject(const ossimGeoAnnotationMultiPolyLineObject& rhs); + virtual ossimObject* dup()const; + + virtual ~ossimGeoAnnotationMultiPolyLineObject(); + virtual void transform(ossimProjection* projection); + virtual void applyScale(double x, double y); + virtual void draw(ossimRgbImage& anImage)const; + virtual bool intersects(const ossimDrect& rect)const; + + virtual ossimAnnotationObject* getNewClippedObject(const ossimDrect& rect)const; + virtual std::ostream& print(std::ostream& out)const; + virtual void getBoundingRect(ossimDrect& rect)const; + virtual void addPoint(ossim_uint32 polygonIndex, + const ossimGpt& pt); + + virtual void setMultiPolyLine(const vector<ossimPolyLine>& multiPoly); + + virtual void computeBoundingRect(); + + virtual bool isPointWithin(const ossimDpt& imagePoint)const; + + virtual void setColor(ossim_uint8 r, + ossim_uint8 g, + ossim_uint8 b); + + virtual void setThickness(long thickness); + + void setDatum(const ossimDatum* datum); + + const ossimDatum* getDatum()const; + + const std::vector<ossimPolyLine>& getMultiPolyLine()const; + + std::vector<ossimPolyLine>& getMultiPolyLine(); + + /** + * Saves the current state of this object. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +protected: + vector<ossimPolyLine> theMultiPolyLine; + ossimDrect theBoundingRect; + const ossimDatum* theDatum; + ossimAnnotationMultiPolyLineObject* theProjectedPolyLineObject; + + void allocateProjectedPolyLine(); + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationMultiPolyObject.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationMultiPolyObject.cpp new file mode 100644 index 0000000000..d135298336 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationMultiPolyObject.cpp @@ -0,0 +1,199 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimGeoAnnotationMultiPolyObject.cpp,v 1.11 2004/12/21 20:12:40 gpotts Exp $ + +#include <imaging/annotation/ossimGeoAnnotationMultiPolyObject.h> +#include <imaging/annotation/ossimAnnotationMultiPolyObject.h> +#include <projections/ossimProjection.h> +#include <base/data_types/ossimPolyArea2d.h> + +RTTI_DEF1(ossimGeoAnnotationMultiPolyObject, "ossimGeoAnnotationMultiPolyObject", ossimGeoAnnotationObject); + +ossimGeoAnnotationMultiPolyObject::ossimGeoAnnotationMultiPolyObject() + : + ossimGeoAnnotationObject(), + theMultiPolygon(), + theBoundingRect(), + theFillEnabled(false), + theProjectedPolyObject(NULL) +{ + allocateProjectedPolygon(); + theBoundingRect.makeNan(); +} + +ossimGeoAnnotationMultiPolyObject::ossimGeoAnnotationMultiPolyObject(const vector<ossimGeoPolygon>& multiPoly, + bool enableFill, + unsigned char r, + unsigned char g, + unsigned char b, + long thickness) + : + ossimGeoAnnotationObject(r, g, b, thickness), + theMultiPolygon(multiPoly), + theBoundingRect(), + theFillEnabled(enableFill), + theProjectedPolyObject(NULL) +{ + allocateProjectedPolygon(); + theBoundingRect.makeNan(); +} + +ossimGeoAnnotationMultiPolyObject::ossimGeoAnnotationMultiPolyObject(const ossimGeoAnnotationMultiPolyObject& rhs) + : + ossimGeoAnnotationObject(rhs), + theMultiPolygon(rhs.theMultiPolygon), + theBoundingRect(rhs.theBoundingRect), + theFillEnabled(rhs.theFillEnabled), + theProjectedPolyObject(rhs.theProjectedPolyObject?(ossimAnnotationMultiPolyObject*)rhs.theProjectedPolyObject->dup():NULL) +{ +} + +ossimGeoAnnotationMultiPolyObject::~ossimGeoAnnotationMultiPolyObject() +{ + if(theProjectedPolyObject) + { + delete theProjectedPolyObject; + theProjectedPolyObject = NULL; + } +} + +void ossimGeoAnnotationMultiPolyObject::applyScale(double x, + double y) +{ + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimGeoAnnotationPolyObject::applyScale NOT IMPLEMENTED!!!!" + << endl; +} + +void ossimGeoAnnotationMultiPolyObject::transform(ossimProjection* projection) +{ + if(!projection) return; + allocateProjectedPolygon(); + int polyI = 0; + int pointI = 0; + + ossimDpt temp; + std::vector<ossimPolygon> visiblePolygons; + ossimPolygon polygon; + for(polyI = 0; polyI < (int)theMultiPolygon.size(); ++polyI) + { + polygon.clear(); + for(pointI = 0; pointI < (int)theMultiPolygon[polyI].size(); ++pointI) + { + projection->worldToLineSample(theMultiPolygon[polyI][pointI], + temp); + if(!temp.hasNans()) + { + polygon.addPoint(temp); + } + } + theProjectedPolyObject->addPolygon(polygon); + } +} + +std::ostream& ossimGeoAnnotationMultiPolyObject::print(std::ostream& out)const +{ + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimGeoAnnotationMultiPolyObject::print NOT IMPLEMENTED" + << endl; + return out; +} + +bool ossimGeoAnnotationMultiPolyObject::intersects(const ossimDrect& rect)const +{ + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimGeoAnnotationMultiPolyObject::intersects NOT IMPLEMENTED" + << endl; + return false; +} + +ossimAnnotationObject* ossimGeoAnnotationMultiPolyObject::getNewClippedObject(const ossimDrect& rect)const +{ + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimGeoAnnotationMultiPolyObject::getNewClippedObject " + << "NOT IMPLEMENTED" << endl; + + return (ossimAnnotationObject*)(dup()); +} + +void ossimGeoAnnotationMultiPolyObject::draw(ossimRgbImage& anImage)const +{ + if(theProjectedPolyObject) + { + theProjectedPolyObject->draw(anImage); + } +} + +void ossimGeoAnnotationMultiPolyObject::getBoundingRect(ossimDrect& rect)const +{ + rect = theBoundingRect; +} + +void ossimGeoAnnotationMultiPolyObject::computeBoundingRect() +{ + theBoundingRect.makeNan(); + if(theProjectedPolyObject) + { + theProjectedPolyObject->computeBoundingRect(); + theProjectedPolyObject->getBoundingRect(theBoundingRect); + } +} + +bool ossimGeoAnnotationMultiPolyObject::isPointWithin(const ossimDpt& imagePoint)const +{ + if(theProjectedPolyObject) + { + return theProjectedPolyObject->isPointWithin(imagePoint); + } + + return false; +} + +void ossimGeoAnnotationMultiPolyObject::setFillFlag(bool flag) +{ + theFillEnabled = flag; + if(theProjectedPolyObject) + { + theProjectedPolyObject->setFillFlag(flag); + } +} + +void ossimGeoAnnotationMultiPolyObject::allocateProjectedPolygon() +{ + if(theProjectedPolyObject) + { + delete theProjectedPolyObject; + theProjectedPolyObject = NULL; + } + + vector<ossimPolygon> polyList; + + if(theMultiPolygon.size()) + { + theProjectedPolyObject = new ossimAnnotationMultiPolyObject(polyList, + theFillEnabled, + theRed, + theGreen, + theBlue, + theThickness); + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationMultiPolyObject.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationMultiPolyObject.h new file mode 100644 index 0000000000..ec88ca5889 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationMultiPolyObject.h @@ -0,0 +1,118 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// Description: +// +//************************************************************************* +// $Id: ossimGeoAnnotationMultiPolyObject.h,v 1.5 2004/05/23 17:49:37 dburken Exp $ +#ifndef ossimGeoAnnotationMultiPolyObject_HEADER +#define ossimGeoAnnotationMultiPolyObject_HEADER +#include "ossimGeoAnnotationObject.h" +#include "base/data_types/ossimIpt.h" +#include "base/data_types/ossimGeoPolygon.h" +#include "ossimAnnotationMultiPolyObject.h" + +class OSSIMDLLEXPORT ossimGeoAnnotationMultiPolyObject : public ossimGeoAnnotationObject +{ +public: + ossimGeoAnnotationMultiPolyObject(); + ossimGeoAnnotationMultiPolyObject(const vector<ossimGeoPolygon>& multiPoly, + bool enableFill=false, + unsigned char r=255, + unsigned char g=255, + unsigned char b=255, + long thickness=1); + + ossimGeoAnnotationMultiPolyObject(const ossimGeoAnnotationMultiPolyObject& rhs); + virtual ossimObject* dup()const + { + return new ossimGeoAnnotationMultiPolyObject(*this); + } + virtual ~ossimGeoAnnotationMultiPolyObject(); + virtual void transform(ossimProjection* projection); + virtual void applyScale(double x, + double y); + virtual void draw(ossimRgbImage& anImage)const; + virtual bool intersects(const ossimDrect& rect)const; + + virtual ossimAnnotationObject* getNewClippedObject(const ossimDrect& rect)const; + virtual std::ostream& print(std::ostream& out)const; + virtual void getBoundingRect(ossimDrect& rect)const; + virtual void addPoint(ossim_uint32 polygonIndex, + const ossimGpt& pt) + { + if(polygonIndex < theMultiPolygon.size()) + { + theMultiPolygon[polygonIndex].addPoint(pt); + + // we will have to reset the projected polygon + if(theProjectedPolyObject) + { + delete theProjectedPolyObject; + theProjectedPolyObject = NULL; + } + } + } + + virtual void setMultiPolygon(const vector<ossimGeoPolygon>& multiPoly) + { + theMultiPolygon = multiPoly; + if(theProjectedPolyObject) + { + delete theProjectedPolyObject; + theProjectedPolyObject = NULL; + } + } + virtual void setColor(unsigned char r, + unsigned char g, + unsigned char b) + { + ossimAnnotationObject::setColor(r, g, b); + if(theProjectedPolyObject) + { + theProjectedPolyObject->setColor(r, g, b); + } + } + + virtual void setThickness(long thickness) + { + ossimAnnotationObject::setThickness(thickness); + if(theProjectedPolyObject) + { + theProjectedPolyObject->setThickness(thickness); + } + } + virtual void computeBoundingRect(); + virtual bool isPointWithin(const ossimDpt& imagePoint)const; + virtual void setFillFlag(bool flag); + + const std::vector<ossimGeoPolygon>& getMultiPolygon()const{return theMultiPolygon;} + std::vector<ossimGeoPolygon>& getMultiPolygon(){return theMultiPolygon;} + +protected: + vector<ossimGeoPolygon> theMultiPolygon; + ossimDrect theBoundingRect; + bool theFillEnabled; + ossimAnnotationMultiPolyObject* theProjectedPolyObject; + + void allocateProjectedPolygon(); +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationObject.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationObject.cpp new file mode 100644 index 0000000000..03f7998348 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationObject.cpp @@ -0,0 +1,46 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See LICENSE.txt file in the top level directory. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimGeoAnnotationObject.cpp,v 1.3 2005/12/07 19:05:11 dburken Exp $ + +#include <imaging/annotation/ossimGeoAnnotationObject.h> + +RTTI_DEF1(ossimGeoAnnotationObject, + "ossimGeoAnnotationObject", + ossimAnnotationObject) + +ossimGeoAnnotationObject::ossimGeoAnnotationObject(unsigned char r, + unsigned char g, + unsigned char b, + long thickness) + :ossimAnnotationObject(r, g, b, thickness) +{ +} + +ossimGeoAnnotationObject::ossimGeoAnnotationObject( + const ossimGeoAnnotationObject& rhs) + : + ossimAnnotationObject(rhs) +{ +} + +ossimGeoAnnotationObject::~ossimGeoAnnotationObject() +{ +} + +bool ossimGeoAnnotationObject::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + return ossimAnnotationObject::saveState(kwl, prefix); +} + +bool ossimGeoAnnotationObject::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + return ossimAnnotationObject::loadState(kwl, prefix); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationObject.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationObject.h new file mode 100644 index 0000000000..97e94f6226 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationObject.h @@ -0,0 +1,51 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See LICENSE.txt file in the top level directory. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimGeoAnnotationObject.h,v 1.4 2005/12/07 19:05:11 dburken Exp $ +#ifndef ossimGeoAnnotationObject_HEADER +#define ossimGeoAnnotationObject_HEADER +#include <imaging/annotation/ossimAnnotationObject.h> +#include <base/data_types/ossimGpt.h> + +class ossimProjection; + +class OSSIM_DLL ossimGeoAnnotationObject : public ossimAnnotationObject +{ +public: + ossimGeoAnnotationObject(unsigned char r=255, + unsigned char g=255, + unsigned char b=255, + long thickness=1); + + ossimGeoAnnotationObject(const ossimGeoAnnotationObject& rhs); + + virtual ~ossimGeoAnnotationObject(); + + /*! + * Add the projection interface to all + * geographically defined objects. + */ + virtual void transform(ossimProjection* projection)=0; + + /** + * Saves the current state of this object. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationPolyLineObject.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationPolyLineObject.cpp new file mode 100644 index 0000000000..20d0def39e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationPolyLineObject.cpp @@ -0,0 +1,178 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimGeoAnnotationPolyLineObject.cpp,v 1.3 2005/05/27 12:17:43 gpotts Exp $ +#include "ossimGeoAnnotationPolyLineObject.h" +#include "ossimAnnotationMultiLineObject.h" +#include "projections/ossimProjection.h" + +RTTI_DEF1(ossimGeoAnnotationPolyLineObject, "ossimGeoAnnotationPolyLineObject", ossimGeoAnnotationObject) + +ossimGeoAnnotationPolyLineObject::ossimGeoAnnotationPolyLineObject(const vector<ossimGpt>& groundPts, + unsigned char r, + unsigned char g, + unsigned char b, + long thickness) + :ossimGeoAnnotationObject(r, g, b, thickness), + theProjectedMultiLineObject(NULL) +{ + + thePolygon = groundPts; + + // we will initialize the projected polygon's size + // so we don't have to reset it every time we do a + // projection + // + vector<ossimDpt> projectedPoints(thePolygon.size()); + + theProjectedMultiLineObject = new ossimAnnotationMultiLineObject(ossimPolyLine(projectedPoints), + r, + g, + b, + thickness); +} + +ossimGeoAnnotationPolyLineObject::ossimGeoAnnotationPolyLineObject(const ossimGeoAnnotationPolyLineObject& rhs) + :ossimGeoAnnotationObject(rhs), + thePolygon(rhs.thePolygon), + theProjectedMultiLineObject(rhs.theProjectedMultiLineObject?(ossimAnnotationMultiLineObject*)rhs.theProjectedMultiLineObject->dup():(ossimAnnotationMultiLineObject*)NULL) +{ +} + +ossimGeoAnnotationPolyLineObject::~ossimGeoAnnotationPolyLineObject() +{ + if(theProjectedMultiLineObject) + { + delete theProjectedMultiLineObject; + theProjectedMultiLineObject = NULL; + } +} + +void ossimGeoAnnotationPolyLineObject::applyScale(double x, + double y) +{ + for(int i = 0; i < (int)thePolygon.size(); ++i) + { + thePolygon[i].lond(thePolygon[i].lond()*x); + thePolygon[i].latd(thePolygon[i].latd()*y); + } + if(theProjectedMultiLineObject) + { + theProjectedMultiLineObject->applyScale(x, y); + } + +} + +void ossimGeoAnnotationPolyLineObject::transform(ossimProjection* projection) +{ + // make sure it's not null + if(!projection) + { + return; + } + vector<ossimPolyLine>& polyList =theProjectedMultiLineObject->getPolyLineList(); + + if(polyList.size()) + { + vector<ossimDpt>& poly = polyList[0].getVertexList(); + + long upperBound = thePolygon.size(); + + for(long index=0; index < upperBound; ++index) + { + projection->worldToLineSample(thePolygon[index], poly[index]); + } + + // update the bounding rect + // + theProjectedMultiLineObject->computeBoundingRect(); + } +} + +std::ostream& ossimGeoAnnotationPolyLineObject::print(std::ostream& out)const +{ + out << "number_of_points: " << thePolygon.size() << endl; + if(thePolygon.size() > 0) + { + for(long index =0; index < (long)(thePolygon.size()-1); ++index) + { + out << thePolygon[index] << endl; + } + out << thePolygon[thePolygon.size()-1] << endl; + } + out << "Projected Polygon" << endl; + theProjectedMultiLineObject->print(out); + return out; +} + +void ossimGeoAnnotationPolyLineObject::draw(ossimRgbImage& anImage)const +{ + theProjectedMultiLineObject->draw(anImage); +} + +bool ossimGeoAnnotationPolyLineObject::intersects(const ossimDrect& rect)const +{ + if(theProjectedMultiLineObject) + { + return theProjectedMultiLineObject->intersects(rect); + } + + return false; +} + +ossimAnnotationObject* ossimGeoAnnotationPolyLineObject::getNewClippedObject(const ossimDrect& rect)const +{ + if(theProjectedMultiLineObject) + { + return theProjectedMultiLineObject->getNewClippedObject(rect); + } + + return (ossimAnnotationObject*)NULL;; +} + +void ossimGeoAnnotationPolyLineObject::getBoundingRect(ossimDrect& rect)const +{ + theProjectedMultiLineObject->getBoundingRect(rect); +} + +void ossimGeoAnnotationPolyLineObject::computeBoundingRect() +{ + theProjectedMultiLineObject->computeBoundingRect(); +} + +void ossimGeoAnnotationPolyLineObject::setColor(unsigned char r, + unsigned char g, + unsigned char b) +{ + if(theProjectedMultiLineObject) + { + theProjectedMultiLineObject->setColor(r, g, b); + } +} + +void ossimGeoAnnotationPolyLineObject::setThickness(long thickness) +{ + if(theProjectedMultiLineObject) + { + theProjectedMultiLineObject->setThickness(thickness); + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationPolyLineObject.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationPolyLineObject.h new file mode 100644 index 0000000000..e0f06f4c35 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationPolyLineObject.h @@ -0,0 +1,69 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimGeoAnnotationPolyLineObject.h,v 1.4 2005/05/27 12:17:43 gpotts Exp $ +#ifndef ossimGeoAnnotationPolyLineObject_HEADER +#define ossimGeoAnnotationPolyLineObject_HEADER +#include "base/data_types/ossimGpt.h" +#include "ossimGeoAnnotationObject.h" + +class ossimAnnotationMultiLineObject; + +class OSSIMDLLEXPORT ossimGeoAnnotationPolyLineObject : public ossimGeoAnnotationObject +{ +public: + ossimGeoAnnotationPolyLineObject(const vector<ossimGpt>& groundPts, + unsigned char r=255, + unsigned char g=255, + unsigned char b=255, + long thickness=1); + ossimGeoAnnotationPolyLineObject(const ossimGeoAnnotationPolyLineObject& rhs); + virtual ~ossimGeoAnnotationPolyLineObject(); + virtual ossimObject* dup()const + { + return new ossimGeoAnnotationPolyLineObject(*this); + } + + virtual void applyScale(double x, + double y); + + virtual void transform(ossimProjection* projection); + virtual std::ostream& print(std::ostream& out)const; + virtual void draw(ossimRgbImage& anImage)const; + virtual ossimAnnotationObject* getNewClippedObject(const ossimDrect& rect)const; + virtual bool intersects(const ossimDrect& rect)const; + + virtual void getBoundingRect(ossimDrect& rect)const; + virtual void computeBoundingRect(); + virtual void setColor(unsigned char r, + unsigned char g, + unsigned char b); + virtual void setThickness(long thickness); + +protected: + vector<ossimGpt> thePolygon; + ossimAnnotationMultiLineObject* theProjectedMultiLineObject; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationPolyObject.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationPolyObject.cpp new file mode 100644 index 0000000000..9c08803471 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationPolyObject.cpp @@ -0,0 +1,302 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimGeoAnnotationPolyObject.cpp,v 1.14 2005/12/16 14:28:27 dburken Exp $ + +#include <sstream> + +#include <imaging/annotation/ossimGeoAnnotationPolyObject.h> +#include <imaging/annotation/ossimAnnotationPolyObject.h> +#include <projections/ossimProjection.h> +#include <base/common/ossimTrace.h> + +static const ossimTrace +traceDebug(ossimString("ossimGeoAnnotationPolyObject:debug")); + +RTTI_DEF1(ossimGeoAnnotationPolyObject, + "ossimGeoAnnotationPolyObject", + ossimGeoAnnotationObject) + +ossimGeoAnnotationPolyObject::ossimGeoAnnotationPolyObject(bool enableFill, + ossim_uint8 r, + ossim_uint8 g, + ossim_uint8 b, + ossim_uint8 thickness) + :ossimGeoAnnotationObject(r, g, b, thickness), + thePolygon(), + theProjectedPolyObject(NULL) +{ + theProjectedPolyObject = new ossimAnnotationPolyObject(enableFill, + r, + g, + b, + thickness); +} + +ossimGeoAnnotationPolyObject::ossimGeoAnnotationPolyObject( + const std::vector<ossimGpt>& groundPts, + bool enableFill, + ossim_uint8 r, + ossim_uint8 g, + ossim_uint8 b, + ossim_uint8 thickness) + :ossimGeoAnnotationObject(r, g, b, thickness), + thePolygon(), + theProjectedPolyObject(NULL) +{ + + thePolygon = groundPts; + + // we will initialize the projected polygon's size + // so we don't have to reset it every time we do a + // projection + // + std::vector<ossimDpt> projectedPoints(thePolygon.size()); + + theProjectedPolyObject = new ossimAnnotationPolyObject(projectedPoints, + enableFill, + r, + g, + b, + thickness); +} + +ossimGeoAnnotationPolyObject::ossimGeoAnnotationPolyObject( + const ossimGeoAnnotationPolyObject& rhs) + :ossimGeoAnnotationObject(rhs), + thePolygon(rhs.thePolygon), + theProjectedPolyObject(rhs.theProjectedPolyObject?(ossimAnnotationPolyObject*)rhs.theProjectedPolyObject->dup():(ossimAnnotationPolyObject*)NULL) +{ +} + +ossimGeoAnnotationPolyObject::~ossimGeoAnnotationPolyObject() +{ + if(theProjectedPolyObject) + { + delete theProjectedPolyObject; + theProjectedPolyObject = NULL; + } +} + +ossimObject* ossimGeoAnnotationPolyObject::dup()const +{ + return new ossimGeoAnnotationPolyObject(*this); +} + +void ossimGeoAnnotationPolyObject::applyScale(double x, + double y) +{ + for(int i = 0; i < (int)thePolygon.size(); ++i) + { + thePolygon[i].lond(thePolygon[i].lond()*x); + thePolygon[i].latd(thePolygon[i].latd()*y); + } + if(theProjectedPolyObject) + { + theProjectedPolyObject->applyScale(x, y); + } + +} + +void ossimGeoAnnotationPolyObject::transform(ossimProjection* projection) +{ + // make sure it's not null + if(!projection) + { + return; + } + ossimPolygon& poly = theProjectedPolyObject->getPolygon(); + long upperBound = thePolygon.size(); + + for(long index=0; index < upperBound; ++index) + { + projection->worldToLineSample(thePolygon[index], poly[index]); + } + + // update the bounding rect + // + theProjectedPolyObject->computeBoundingRect(); +} + +std::ostream& ossimGeoAnnotationPolyObject::print(std::ostream& out)const +{ + out << "number_of_points: " << thePolygon.size() << std::endl; + if(thePolygon.size() > 0) + { + for(long index =0; index < (long)(thePolygon.size()-1); ++index) + { + out << thePolygon[index] << std::endl; + } + out << thePolygon[thePolygon.size()-1] << std::endl; + } + out << "Projected Polygon" << std::endl; + theProjectedPolyObject->print(out); + return out; +} + +void ossimGeoAnnotationPolyObject::draw(ossimRgbImage& anImage)const +{ + if(theProjectedPolyObject) + { + theProjectedPolyObject->draw(anImage); + } +} + +ossimAnnotationObject* ossimGeoAnnotationPolyObject::getNewClippedObject( + const ossimDrect& rect)const +{ + if(theProjectedPolyObject) + { + return theProjectedPolyObject->getNewClippedObject(rect); + } + + return (ossimAnnotationObject*)NULL; +} + +bool ossimGeoAnnotationPolyObject::intersects(const ossimDrect& rect)const +{ + if(theProjectedPolyObject) + { + return theProjectedPolyObject->intersects(rect); + } + + return false; +} + +void ossimGeoAnnotationPolyObject::getBoundingRect(ossimDrect& rect)const +{ + rect.makeNan(); + if(theProjectedPolyObject) + { + theProjectedPolyObject->getBoundingRect(rect); + } +} + +void ossimGeoAnnotationPolyObject::computeBoundingRect() +{ + if(theProjectedPolyObject) + { + theProjectedPolyObject->computeBoundingRect(); + } +} + +const std::vector<ossimGpt>& ossimGeoAnnotationPolyObject::getPolygon()const +{ + return thePolygon; +} + +void ossimGeoAnnotationPolyObject::setFillFlag(bool flag) +{ + if(theProjectedPolyObject) + { + theProjectedPolyObject->setFillFlag(flag); + } +} + +void ossimGeoAnnotationPolyObject::setColor(ossim_uint8 r, + ossim_uint8 g, + ossim_uint8 b) +{ + ossimAnnotationObject::setColor(r, g, b); + if(theProjectedPolyObject) + { + theProjectedPolyObject->setColor(r, g, b); + } +} + +void ossimGeoAnnotationPolyObject::setThickness(long thickness) +{ + ossimAnnotationObject::setThickness(thickness); + if(theProjectedPolyObject) + { + theProjectedPolyObject->setThickness(thickness); + } +} + +bool ossimGeoAnnotationPolyObject::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + ossim_uint32 vIdx = 0; + + for(ossim_uint32 i = 0; i < thePolygon.size(); ++i) + { + ossimString key = "v"; + key += ossimString::toString(vIdx); + + kwl.add(prefix, key.c_str(), thePolygon[i].toString().c_str()); + + ++vIdx; + } + + return ossimGeoAnnotationObject::saveState(kwl, prefix); +} + +bool ossimGeoAnnotationPolyObject::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + if (!theProjectedPolyObject) + { + return false; + } + + //--- + // Base class state must be called first to pick up colors... + //--- + bool status = ossimGeoAnnotationObject::loadState(kwl, prefix); + + ossim_uint32 index = 0; + ossimString copyPrefix = prefix; + ossim_uint32 count = kwl.getNumberOfSubstringKeys(copyPrefix+"v[0-9]*"); + + ossim_uint32 numberOfMatches = 0; + const ossim_uint32 MAX_INDEX = count + 100; + + while(numberOfMatches < count) + { + ossimString key = "v"; + key += ossimString::toString(index); + + const char* lookup = kwl.find(prefix, key.c_str()); + if (lookup) + { + ++numberOfMatches; + ossimGpt gpt; + + std::istringstream is(lookup); + is >> gpt; + thePolygon.push_back(gpt); + } + + ++index; + + if (index > MAX_INDEX) // Avoid infinite loop... + { + break; + } + } + + // Set up the annotator. + theProjectedPolyObject->setColor(theRed, theGreen, theBlue); + theProjectedPolyObject->setThickness(theThickness); + + std::vector<ossimDpt> projectedPoints(thePolygon.size()); + theProjectedPolyObject->setPolygon(projectedPoints); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimGeoAnnotationPolyObject::loadState DEBUG:" << std::endl; + for (ossim_uint32 i=0; i<thePolygon.size(); ++i) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "thePolygon[" << i << "]: " << thePolygon[i] << std::endl; + } + } + + return status; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationPolyObject.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationPolyObject.h new file mode 100644 index 0000000000..e58c560477 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationPolyObject.h @@ -0,0 +1,88 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimGeoAnnotationPolyObject.h,v 1.12 2005/12/09 18:23:47 dburken Exp $ +#ifndef ossimGeoAnnotationPolyObject_HEADER +#define ossimGeoAnnotationPolyObject_HEADER + +#include <vector> + +#include <base/data_types/ossimGpt.h> +#include <imaging/annotation/ossimGeoAnnotationObject.h> +class ossimAnnotationPolyObject; + +class OSSIMDLLEXPORT ossimGeoAnnotationPolyObject : public ossimGeoAnnotationObject +{ +public: + ossimGeoAnnotationPolyObject(bool enableFill = false, + ossim_uint8 r=255, + ossim_uint8 g=255, + ossim_uint8 b=255, + ossim_uint8 thickness=1); + + ossimGeoAnnotationPolyObject(const std::vector<ossimGpt>& groundPts, + bool enableFill = false, + ossim_uint8 r=255, + ossim_uint8 g=255, + ossim_uint8 b=255, + ossim_uint8 thickness=1); + + ossimGeoAnnotationPolyObject(const ossimGeoAnnotationPolyObject& rhs); + + virtual ~ossimGeoAnnotationPolyObject(); + + virtual ossimObject* dup()const; + + virtual void applyScale(double x, double y); + + virtual void transform(ossimProjection* projection); + + virtual std::ostream& print(std::ostream& out)const; + + virtual void draw(ossimRgbImage& anImage)const; + + virtual ossimAnnotationObject* getNewClippedObject( + const ossimDrect& rect)const; + + virtual bool intersects(const ossimDrect& rect)const; + + virtual void getBoundingRect(ossimDrect& rect)const; + + virtual void computeBoundingRect(); + + virtual const std::vector<ossimGpt>& getPolygon()const; + + virtual void setFillFlag(bool flag); + + virtual void setColor(ossim_uint8 r, + ossim_uint8 g, + ossim_uint8 b); + + virtual void setThickness(long thickness); + + /** + * Saves the current state of this object. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +protected: + std::vector<ossimGpt> thePolygon; + ossimAnnotationPolyObject* theProjectedPolyObject; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationSource.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationSource.cpp new file mode 100644 index 0000000000..22475c395e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationSource.cpp @@ -0,0 +1,207 @@ +//************************************************************************ +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See LICENSE.txt file in the top level directory. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimGeoAnnotationSource.cpp,v 1.19 2005/12/07 18:56:13 dburken Exp $ + +#include <imaging/annotation/ossimGeoAnnotationSource.h> +#include <imaging/annotation/ossimGeoAnnotationObject.h> +#include <projections/ossimProjection.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> + +RTTI_DEF2(ossimGeoAnnotationSource, + "ossimGeoAnnotationSource", + ossimAnnotationSource, + ossimViewInterface); + + +ostream& operator <<(ostream& out, const ossimGeoAnnotationSource& rhs) +{ + const vector<ossimAnnotationObject*> &tempList = rhs.getObjectList(); + for(ossim_uint32 index = 0; index < tempList.size(); ++index) + { + out << "output " << index << endl; + tempList[index]->print(out); + } + + return out; +} + +ossimGeoAnnotationSource::ossimGeoAnnotationSource(ossimProjection* projection, + bool ownsProjectionFlag) + :ossimAnnotationSource(), + ossimViewInterface(), + theProjection(projection), + theOwnsProjectionFlag(ownsProjectionFlag) +{ + ossimViewInterface::theObject = this; +} + +ossimGeoAnnotationSource::ossimGeoAnnotationSource(ossimImageSource* inputSource, + ossimProjection* projection, + bool ownsProjectionFlag) + :ossimAnnotationSource(inputSource), + ossimViewInterface(), + theProjection(projection), + theOwnsProjectionFlag(ownsProjectionFlag) +{ + ossimViewInterface::theObject = this; +} + +ossimGeoAnnotationSource::~ossimGeoAnnotationSource() +{ + removeProjection(); +} + +bool ossimGeoAnnotationSource::addObject(ossimAnnotationObject* anObject) +{ + ossimGeoAnnotationObject *objectToAdd = PTR_CAST(ossimGeoAnnotationObject, anObject); + + if(objectToAdd) + { + ossimAnnotationSource::addObject(objectToAdd); + if(theProjection) + { + objectToAdd->transform(theProjection); + computeBoundingRect(); + } + return true; + } + + return false; +} + +void ossimGeoAnnotationSource::setProjection(ossimProjection* projection, + bool ownsProjectionFlag) +{ + // remove our current set projection first + removeProjection(); + + theProjection = projection; + theOwnsProjectionFlag = ownsProjectionFlag; + transformObjects(theProjection); + +} + +bool ossimGeoAnnotationSource::setView(ossimObject* baseObject, + bool ownsTheView) +{ + ossimProjection* proj = PTR_CAST(ossimProjection, baseObject); + if(proj) + { + setProjection(proj, ownsTheView); + + return true; + } + + return false; +} + +ossimObject* ossimGeoAnnotationSource::getView() +{ + return theProjection; +} + +const ossimObject* ossimGeoAnnotationSource::getView()const +{ + return theProjection; +} + +void ossimGeoAnnotationSource::computeBoundingRect() +{ +// static const char *MODULE = "ossimAnnotationSource::computeBoundingRect"; + + theRectangle.makeNan(); + + if(theAnnotationObjectList.size()>0) + { + ossimDrect rect; + theAnnotationObjectList[0]->getBoundingRect(theRectangle); + + vector<ossimAnnotationObject*>::iterator object = (theAnnotationObjectList.begin()+1); + while(object != theAnnotationObjectList.end()) + { + (*object)->getBoundingRect(rect); + theRectangle = theRectangle.combine(rect); + ++object; + } + } +} + +void ossimGeoAnnotationSource::transformObjects(ossimProjection* projection) +{ + if(!theProjection && !projection) + { + return; + } + if(!projection) + { + projection = theProjection; + } + + if(!theProjection) return; + vector<ossimAnnotationObject*>::iterator currentObject; + + currentObject = theAnnotationObjectList.begin(); + + while(currentObject != theAnnotationObjectList.end()) + { + // this is safe since we trapped all adds to make + // sure that each object added to the list is + // geographic. + ossimGeoAnnotationObject* object = static_cast<ossimGeoAnnotationObject*>(*currentObject); + + // transform the object to image space. + object->transform(projection); + + ++currentObject; + } + computeBoundingRect(); +} + +void ossimGeoAnnotationSource::removeProjection() +{ + if(theProjection&&theOwnsProjectionFlag) + { + delete theProjection; + } + + theProjection = NULL; +} + +bool ossimGeoAnnotationSource::getImageGeometry(ossimKeywordlist& kwl, + const char* prefix) +{ + if(theProjection) + { + theProjection->saveState(kwl, prefix); + return true; + } + return ossimImageSource::getImageGeometry(kwl, prefix); +} + +bool ossimGeoAnnotationSource::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + return ossimAnnotationSource::saveState(kwl, prefix); +} + + +bool ossimGeoAnnotationSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimProjection* proj = ossimProjectionFactoryRegistry::instance()->createProjection(kwl,"view_proj."); + + if(proj) + { + removeProjection(); + theOwnsProjectionFlag = true; + theProjection = proj; + } + + return ossimAnnotationSource::loadState(kwl, prefix); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationSource.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationSource.h new file mode 100644 index 0000000000..2fb28210fd --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeoAnnotationSource.h @@ -0,0 +1,75 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See LICENSE.txt file in the top level directory. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimGeoAnnotationSource.h,v 1.8 2005/12/07 18:56:13 dburken Exp $ +#ifndef ossimGeoAnnotationSource_HEADER +#define ossimGeoAnnotationSource_HEADER + +#include <iostream> +#include <imaging/annotation/ossimAnnotationSource.h> +#include <base/common/ossimViewInterface.h> + +class ossimGeoAnnotationObject; +class ossimProjection; + +class OSSIM_DLL ossimGeoAnnotationSource : + public ossimAnnotationSource, + public ossimViewInterface +{ +public: + friend std::ostream& operator <<(std::ostream& out, const ossimGeoAnnotationSource& rhs); + ossimGeoAnnotationSource(ossimProjection* projection=NULL, + bool ownsProjectionFlag=false); + + ossimGeoAnnotationSource(ossimImageSource* inputSource, + ossimProjection* projection=NULL, + bool ownsProjectionFlag=false); + + virtual ~ossimGeoAnnotationSource(); + + /*! + * Will add an object to the list. + * it will own the object added. If the + * object is not geographic + */ + virtual bool addObject(ossimAnnotationObject* anObject); + virtual void computeBoundingRect(); + virtual void transformObjects(ossimProjection* projection=0); + virtual void setProjection(ossimProjection* projection, + bool ownsProjectionFlag=false); + virtual bool setView(ossimObject* baseObject, + bool ownsTheView = false); + virtual bool getImageGeometry(ossimKeywordlist& kwl, + const char* prefix=0); + + virtual ossimObject* getView(); + virtual const ossimObject* getView()const; + + /** + * Saves the current state of this object. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +protected: + ossimProjection* theProjection; + bool theOwnsProjectionFlag; + + void removeProjection(); + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeographicAnnotationGrid.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeographicAnnotationGrid.cpp new file mode 100644 index 0000000000..b61d2d7334 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeographicAnnotationGrid.cpp @@ -0,0 +1,283 @@ +#include "ossimGeographicAnnotationGrid.h" +#include "projections/map_projections/ossimMapProjection.h" +#include "imaging/ossimRgbImage.h" +#include "base/data_types/ossimGrect.h" +#include "ossimAnnotationLineObject.h" +#include "ossimAnnotationGdBitmapFont.h" +#include "base/data_types/ossimDms.h" +#include "base/common/ossimTrace.h" + + +static ossimTrace traceDebug("ossimGeographicAnnotationGrid:debug"); + +ossimGeographicAnnotationGrid::ossimGeographicAnnotationGrid() + : ossimAnnotationObject(), + theViewProjection(NULL), + theGroundRect(0,0,0,0), + theDeltaLatSpacing(1.0/60.0), // every minute + theDeltaLonSpacing(1.0/60.0) +{ +} + +void ossimGeographicAnnotationGrid::draw(ossimRgbImage& anImage)const + +{ + if(!anImage.getImageData()) + { + return; + } + anImage.setDrawColor(theRed, theGreen,theBlue); + + if((fabs(theDeltaLatSpacing) <= DBL_EPSILON)|| + (fabs(theDeltaLonSpacing) <= DBL_EPSILON)) + { + return; + } + +// ossimDrect imageRect = anImage.getImageData()->getImageRectangle(); + // If the view projection exists we will use it to + // compute the bounding ground rect and find all lines + // that overlap that area in the lat and lon direction + // and draw them. + // + // I the projection doesn't exist we will assume that + // the geographic grid to generate will be 0,0 is origin + // -180lon and 90lat. + // + if(theViewProjection) + { + ossimAnnotationLineObject *line=NULL; + ossimAnnotationGdBitmapFont *font=NULL; + + line = new ossimAnnotationLineObject(); + font = new ossimAnnotationGdBitmapFont(); + + ossimDpt start; + ossimDpt end; + ossimGpt groundUpper(0,0,0,theGroundRect.ul().datum()); + ossimGpt groundLower(0,0,0,theGroundRect.ul().datum()); + double height = theGroundRect.height(); + double width = theGroundRect.width(); + double lat = theGroundRect.ul().latd(); +// ossimDrect imageRect = anImage.getImageData()->getImageRectangle(); + double lon; + + // used for the font spacing + ossimDrect boundingRect; + + // we will go across the longitudinal direction first + for(lon = theGroundRect.ul().lond()+theDeltaLonSpacing; + lon <= theGroundRect.ur().lond(); + lon += theDeltaLonSpacing) + { + groundUpper.lond(lon); + groundUpper.latd(lat); + groundLower.lond(lon); + groundLower.latd(lat-height); + + theViewProjection->worldToLineSample(groundUpper, start); + theViewProjection->worldToLineSample(groundLower, end); + + line->setLine(start, end); + line->draw(anImage); + } + lon = theGroundRect.ul().lond(); + + // now go accross longitude and place the + // text in. + for(lon = theGroundRect.ul().lond()+theDeltaLonSpacing; + lon <= theGroundRect.ur().lond(); + lon += theDeltaLonSpacing) + { + groundUpper.lond(lon); + groundUpper.latd(lat); + groundLower.lond(lon); + groundLower.latd(lat-height); + + theViewProjection->worldToLineSample(groundUpper, start); + theViewProjection->worldToLineSample(groundLower, end); + font->setText(ossimDms(groundUpper.lond(), false).toString("ddd@mm'ss.ssss\"C")); + font->getBoundingRect(boundingRect); + start.y -= boundingRect.height(); + font->setCenterTextPosition(start); + font->draw(anImage); + + end.y += boundingRect.height(); + font->setCenterText(end, + ossimDms(groundLower.lond(), false).toString("ddd@mm'ss.ssssC")); + font->draw(anImage); + } + lon = theGroundRect.ul().lond(); + + ossimGpt groundLeft; + ossimGpt groundRight; + + // Now go down lat direction + for(lat = theGroundRect.ul().latd()-theDeltaLatSpacing; + lat >= theGroundRect.lr().latd(); + lat -= theDeltaLatSpacing) + { + groundLeft.lond(lon); + groundLeft.latd(lat); + groundRight.lond(lon+width); + groundRight.latd(lat); + + theViewProjection->worldToLineSample(groundLeft, start); + theViewProjection->worldToLineSample(groundRight, end); + + line->setLine(start, end); + line->draw(anImage); + } + + // now go down lat direction font + for(lat = theGroundRect.ul().latd()-theDeltaLatSpacing; + lat >= theGroundRect.lr().latd(); + lat -= theDeltaLatSpacing) + { + groundLeft.lond(lon); + groundLeft.latd(lat); + groundRight.lond(lon+width); + groundRight.latd(lat); + + theViewProjection->worldToLineSample(groundLeft, start); + theViewProjection->worldToLineSample(groundRight, end); + + + font->setText(ossimDms(groundLeft.latd()).toString("ddd@mm'ss.ssss\"C")); + font->getBoundingRect(boundingRect); + start.x -= boundingRect.width()/2.0-1; + font->setCenterTextPosition(start); + font->draw(anImage); + + end.x += boundingRect.width()/2.0+1; + font->setCenterText(end, + ossimDms(groundRight.latd()).toString("ddd@mm'ss.ssssC")); + font->draw(anImage); + } + + delete line; + line = NULL; + delete font; + font = NULL; + } +} + + +void ossimGeographicAnnotationGrid::setViewProjectionInformation(ossimMapProjection* projection, + const ossimGrect& boundingGroundRect) +{ + static const char* MODULE = "ossimGeographicAnnotationGrid::setViewProjectionInformation"; + theViewProjection = projection; + + // set the ground and then stretch it + // to cover which even degree grid we are currently + // in. + theGroundRect = boundingGroundRect; + + // find the even degree grid. + ossimGrect rect(ossimGpt(90, -180), + ossimGpt(-90, 180)); + + // make sure that it is within the range of the + // geographic grid. + ossimGrect clipRect = rect.clipToRect(boundingGroundRect); + + // for easier math we will shift the points so they + // are between 0..360Lon and 0..180Lat. This way + // we are working with just positive numbers + double upperLeftLonShift = clipRect.ul().lond() + 180; + double upperLeftLatShift = clipRect.ul().latd() + 90; + double lowerRightLonShift = clipRect.lr().lond() + 180; + double lowerRightLatShift = clipRect.lr().latd() + 90; + + // now find the even boundaries + double upperLeftLonCell = floor(upperLeftLonShift/theDeltaLonSpacing)* + theDeltaLonSpacing; + double upperLeftLatCell = floor(upperLeftLatShift/theDeltaLatSpacing)* + theDeltaLatSpacing; + double lowerRightLonCell = floor(lowerRightLonShift/theDeltaLonSpacing)* + theDeltaLonSpacing; + double lowerRightLatCell = floor(lowerRightLatShift/theDeltaLatSpacing)* + theDeltaLatSpacing; + + // now adjust them by 1 boundary distance. + upperLeftLonCell -= theDeltaLonSpacing; + upperLeftLatCell += theDeltaLatSpacing; + lowerRightLonCell += theDeltaLonSpacing; + lowerRightLatCell -= theDeltaLatSpacing; + + // now clamp to the range of the lat and lon + upperLeftLonCell = (upperLeftLonCell<0?0:upperLeftLonCell); + upperLeftLatCell = (upperLeftLatCell>180?180:upperLeftLatCell); + lowerRightLonCell = (lowerRightLonCell>360?360:lowerRightLonCell); + lowerRightLatCell = (lowerRightLatCell<0?0:lowerRightLatCell); + + // now shift them back into range + upperLeftLonCell -= 180; + upperLeftLatCell -= 90; + lowerRightLonCell -= 180; + lowerRightLatCell -= 90; + + const ossimDatum* datum = theGroundRect.ul().datum(); + theGroundRect = ossimGrect(upperLeftLatCell, upperLeftLonCell, + lowerRightLatCell, lowerRightLonCell, + datum); + + if(traceDebug()) + { + CLOG << "Ground Rect: " << theGroundRect << endl; + } + computeBoundingRect(); +} + +void ossimGeographicAnnotationGrid::getBoundingRect(ossimDrect& rect)const +{ + rect = theBoundingRect; +} + +void ossimGeographicAnnotationGrid::computeBoundingRect() +{ + static const char* MODULE = "ossimGeographicAnnotationGrid::computeBoundingRect"; + + if(theViewProjection) + { + vector<ossimDpt> points(4); + + theViewProjection->worldToLineSample(theGroundRect.ul(), points[0]); + theViewProjection->worldToLineSample(theGroundRect.ll(), points[1]); + theViewProjection->worldToLineSample(theGroundRect.lr(), points[2]); + theViewProjection->worldToLineSample(theGroundRect.ur(), points[3]); + + // now solve the bounding rect in view space. + theBoundingRect = ossimDrect(points); + + // for now we will add a border for the labelling + // of lat lon readouts. We need a better border + // computation that checks exactly what we need + // based on font sizes. + // + ossimDpt ul = theBoundingRect.ul(); + ossimDpt lr = theBoundingRect.lr(); + + + ossimAnnotationGdBitmapFont font; + font.setCenterText(ossimDpt(0,0),"ddd@mm'ss.ssssC"); + ossimDrect boundingRect; + font.getBoundingRect(boundingRect); + + theBoundingRect = ossimDrect(ul.x - boundingRect.width(), + ul.y - boundingRect.height(), + lr.x + boundingRect.width(), + lr.y + boundingRect.height()); + + if(traceDebug()) + { + CLOG << " bounding rect: " << theBoundingRect << endl; + } + } +} + +std::ostream& ossimGeographicAnnotationGrid::print(std::ostream& out)const +{ + return out; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeographicAnnotationGrid.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeographicAnnotationGrid.h new file mode 100644 index 0000000000..3b5fc0a882 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimGeographicAnnotationGrid.h @@ -0,0 +1,52 @@ +#ifndef ossimGeographicAnnotationGrid_HEADER +#define ossimGeographicAnnotationGrid_HEADER +#include "ossimAnnotationObject.h" +#include "base/data_types/ossimGpt.h" +#include "base/data_types/ossimGrect.h" +#include "base/data_types/ossimDrect.h" + +class ossimMapProjection; + +class ossimGeographicAnnotationGrid : public ossimAnnotationObject +{ +public: + ossimGeographicAnnotationGrid(); + + virtual void draw(ossimRgbImage& anImage)const; + + /*! + * We need to know what projection the view + * and we need to know the bounding rect for + * the view in geographic space. The bounding + * rect is there for an area of interest. + */ + virtual void setViewProjectionInformation(ossimMapProjection* projection, + const ossimGrect& boundingGroundRect); + + virtual void getBoundingRect(ossimDrect& rect)const; + virtual void computeBoundingRect(); + virtual std::ostream& print(std::ostream& out)const; + +protected: + /*! + * Holds the view projection. + */ + ossimMapProjection* theViewProjection; + + ossimGrect theGroundRect; + + /*! + * This will be computed based on the bounding + * ground and projection. + */ + ossimDrect theBoundingRect; + + /*! + * Will hold the spacing of the grid cells in + * geographic lat lon change. + */ + double theDeltaLatSpacing; + double theDeltaLonSpacing; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimMapCompositionSource.cpp b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimMapCompositionSource.cpp new file mode 100644 index 0000000000..55874d4745 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimMapCompositionSource.cpp @@ -0,0 +1,4032 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimMapCompositionSource.cpp,v 1.41 2005/09/09 19:23:58 gpotts Exp $ + +#include <imaging/annotation/ossimMapCompositionSource.h> +#include <imaging/ossimU8ImageData.h> +#include <imaging/ossimImageDataHelper.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <projections/map_projections/ossimMapProjection.h> +#include <imaging/annotation/ossimAnnotationFontObject.h> +#include <imaging/annotation/ossimAnnotationLineObject.h> +#include <fonts/factory/ossimFontFactoryRegistry.h> +#include <base/data_types/ossimString.h> +#include <base/data_types/ossimDms.h> +#include <base/common/ossimTrace.h> +#include <base/property/ossimColorProperty.h> +#include <base/property/ossimContainerProperty.h> +#include <base/property/ossimFontProperty.h> +#include <base/property/ossimBooleanProperty.h> +#include <base/property/ossimTextProperty.h> +#include <base/property/ossimNumericProperty.h> +#include <base/property/ossimStringProperty.h> + +#include <sstream> +using namespace std; + +static const char* GRID_TYPE_ENUM_NAMES[] = {"none", + "line", + "reseaux"}; + +static const char* VIEW_WIDTH_KW = "view_width"; +static const char* VIEW_HEIGHT_KW = "view_height"; +static const char* METER_GRID_SPACING_X_KW = "meter_grid_spacing_x"; +static const char* METER_GRID_SPACING_Y_KW = "meter_grid_spacing_y"; +static const char* GEO_GRID_SPACING_LON_KW = "geo_grid_spacing_lon"; +static const char* GEO_GRID_SPACING_LAT_KW = "geo_grid_spacing_lat"; +static const char* METER_GRID_TYPE_KW = "meter_grid_type"; +static const char* GEO_GRID_TYPE_KW = "geo_grid_type"; +static const char* TOP_BORDER_LENGTH_KW = "top_border_length"; +static const char* BOTTOM_BORDER_LENGTH_KW = "bottom_border_length"; +static const char* LEFT_BORDER_LENGTH_KW = "top_border_length"; +static const char* RIGHT_BORDER_LENGTH_KW = "right_border_length"; +static const char* BORDER_COLOR_KW = "border_color"; +static const char* GEO_GRID_COLOR_KW = "geo_grid_color"; +static const char* METER_GRID_COLOR_KW = "meter_grid_color"; +static const char* TITLE_STRING_KW = "title_string"; +static const char* TITLE_COLOR_KW = "title_color"; + +static const char* TOP_GEO_LABEL_COLOR_KW = "top_geo_label_color"; +static const char* BOTTOM_GEO_LABEL_COLOR_KW = "bottom_geo_label_color"; +static const char* LEFT_GEO_LABEL_COLOR_KW = "left_geo_label_color"; +static const char* RIGHT_GEO_LABEL_COLOR_KW = "right_geo_label_color"; + +static const char* TOP_METER_LABEL_COLOR_KW = "top_meter_label_color"; +static const char* BOTTOM_METER_LABEL_COLOR_KW = "bottom_meter_label_color"; +static const char* LEFT_METER_LABEL_COLOR_KW = "left_meter_label_color"; +static const char* RIGHT_METER_LABEL_COLOR_KW = "right_meter_label_color"; + + +static const char* TOP_GEO_LABEL_FORMAT_KW = "top_geo_label_format"; +static const char* BOTTOM_GEO_LABEL_FORMAT_KW = "bottom_geo_label_format"; +static const char* LEFT_GEO_LABEL_FORMAT_KW = "left_geo_label_format"; +static const char* RIGHT_GEO_LABEL_FORMAT_KW = "right_geo_label_format"; + +static const char* TOP_GEO_LABEL_FLAG_KW = "top_geo_label_flag"; +static const char* BOTTOM_GEO_LABEL_FLAG_KW = "bottom_geo_label_flag"; +static const char* LEFT_GEO_LABEL_FLAG_KW = "left_geo_label_flag"; +static const char* RIGHT_GEO_LABEL_FLAG_KW = "right_geo_label_flag"; + +static const char* TOP_METER_LABEL_FLAG_KW = "top_meter_label_flag"; +static const char* BOTTOM_METER_LABEL_FLAG_KW = "bottom_meter_label_flag"; +static const char* LEFT_METER_LABEL_FLAG_KW = "left_meter_label_flag"; +static const char* RIGHT_METER_LABEL_FLAG_KW = "right_meter_label_flag"; + +static const char* TOP_GEO_LABEL_FONT_KW = "top_geo_label_font"; +static const char* BOTTOM_GEO_LABEL_FONT_KW = "bottom_geo_label_font"; +static const char* LEFT_GEO_LABEL_FONT_KW = "left_geo_label_font"; +static const char* RIGHT_GEO_LABEL_FONT_KW = "right_geo_label_font"; +static const char* TOP_METER_LABEL_FONT_KW = "top_meter_label_font"; +static const char* BOTTOM_METER_LABEL_FONT_KW = "bottom_meter_label_font"; +static const char* LEFT_METER_LABEL_FONT_KW = "left_meter_label_font"; +static const char* RIGHT_METER_LABEL_FONT_KW = "right_meter_label_font"; +static const char* TITLE_FONT_KW = "title_font"; + +static ossimTrace traceDebug("ossimMapCompositionSource:debug"); + +RTTI_DEF1(ossimMapCompositionSource, "ossimMapCompositionSource", ossimAnnotationSource); +ossimMapCompositionSource::ossimMapCompositionSource() + :ossimAnnotationSource(), + theMeterGridType(OSSIM_GRID_NONE), + theGeographicGridType(OSSIM_GRID_LINE), + theTopBorderLength(200), + theBottomBorderLength(200), + theLeftBorderLength(300), + theRightBorderLength(300), + theBorderColor(255,255,255), + theGeographicGridColor(255,255,255), + theMeterGridColor(255,255,255), + theTitleString(""), + theTitleFont(NULL), + theTitleColor(1, 1, 1), + theTopGeographicLabelColor(1, 1, 1), + theBottomGeographicLabelColor(1, 1, 1), + theLeftGeographicLabelColor(1, 1, 1), + theRightGeographicLabelColor(1, 1, 1), + theTopMeterLabelColor(1, 1, 1), + theBottomMeterLabelColor(1, 1, 1), + theLeftMeterLabelColor(1, 1, 1), + theRightMeterLabelColor(1, 1, 1), + theGeographicTopLabelFont(NULL), + theGeographicBottomLabelFont(NULL), + theGeographicLeftLabelFont(NULL), + theGeographicRightLabelFont(NULL), + theMeterTopLabelFont(NULL), + theMeterBottomLabelFont(NULL), + theMeterLeftLabelFont(NULL), + theMeterRightLabelFont(NULL), + theTopGeographicFormat("dd@mm'ss\".ssssC"), + theBottomGeographicFormat("dd@mm'ss\".ssssC"), + theLeftGeographicFormat("dd@mm'ss\".ssssC"), + theRightGeographicFormat("dd@mm'ss\".ssssC"), + theTopGeographicLabelFlag(true), + theBottomGeographicLabelFlag(true), + theLeftGeographicLabelFlag(true), + theRightGeographicLabelFlag(true), + theTopGeographicTickFlag(true), + theBottomGeographicTickFlag(true), + theLeftGeographicTickFlag(true), + theRightGeographicTickFlag(true), + theTopMeterLabelFlag(false), + theBottomMeterLabelFlag(false), + theLeftMeterLabelFlag(false), + theRightMeterLabelFlag(false), + theTopMeterTickFlag(false), + theBottomMeterTickFlag(false), + theLeftMeterTickFlag(false), + theRightMeterTickFlag(false), + theGeographicSpacing(1.0, 1.0), + theMeterSpacing(3600*30, 3600*30), + theInputProjection(NULL) +{ + theViewWidthHeight = ossimIpt(-1,-1); + vector<ossimFontInformation> info; + ossimFontFactoryRegistry::instance()->getFontInformation(info); + + if(info.size()) + { + theGeographicTopLabelFont = ossimFontFactoryRegistry::instance()->createFont(info[0]); + theGeographicTopLabelFontInfo = info[0]; + theGeographicTopLabelFontInfo.thePointSize = ossimIpt(12,12); + + if(theGeographicTopLabelFont) + { + theGeographicBottomLabelFont = (ossimFont*)theGeographicTopLabelFont->dup(); + theGeographicBottomLabelFontInfo = theGeographicTopLabelFontInfo; + theGeographicLeftLabelFont = (ossimFont*)theGeographicTopLabelFont->dup(); + theGeographicLeftLabelFontInfo = theGeographicTopLabelFontInfo; + theGeographicRightLabelFont = (ossimFont*)theGeographicTopLabelFont->dup(); + theGeographicRightLabelFontInfo = theGeographicTopLabelFontInfo; + + theMeterTopLabelFont = (ossimFont*)theGeographicTopLabelFont->dup(); + theMeterTopLabelFontInfo = theGeographicTopLabelFontInfo; + theMeterBottomLabelFont = (ossimFont*)theGeographicTopLabelFont->dup(); + theMeterBottomLabelFontInfo = theGeographicTopLabelFontInfo; + theMeterLeftLabelFont = (ossimFont*)theGeographicTopLabelFont->dup(); + theMeterLeftLabelFontInfo = theGeographicTopLabelFontInfo; + theMeterRightLabelFont = (ossimFont*)theGeographicTopLabelFont->dup(); + theMeterRightLabelFontInfo = theGeographicTopLabelFontInfo; + + theTitleFont = (ossimFont*)theGeographicTopLabelFont->dup(); + theTitleFontInfo = theGeographicTopLabelFontInfo; + theTitleFontInfo.thePointSize = ossimIpt(48, 48); + } + } +} + +ossimMapCompositionSource::~ossimMapCompositionSource() +{ + if(theInputProjection) + { + delete theInputProjection; + theInputProjection = NULL; + } + + if(theGeographicTopLabelFont) + { + delete theGeographicTopLabelFont; + theGeographicTopLabelFont = NULL; + } + if(theGeographicBottomLabelFont) + { + delete theGeographicBottomLabelFont; + theGeographicBottomLabelFont = NULL; + } + if(theGeographicLeftLabelFont) + { + delete theGeographicLeftLabelFont; + theGeographicLeftLabelFont = NULL; + } + if(theGeographicRightLabelFont) + { + delete theGeographicRightLabelFont; + theGeographicRightLabelFont = NULL; + } + + if(theMeterTopLabelFont) + { + delete theMeterTopLabelFont; + theMeterTopLabelFont = NULL; + } + + if(theMeterBottomLabelFont) + { + delete theMeterBottomLabelFont; + theMeterBottomLabelFont = NULL; + } + + if(theMeterLeftLabelFont) + { + delete theMeterLeftLabelFont; + theMeterLeftLabelFont = NULL; + } + + if(theMeterRightLabelFont) + { + delete theMeterRightLabelFont; + theMeterRightLabelFont = NULL; + } + + if(theTitleFont) + { + delete theTitleFont; + theTitleFont = NULL; + } + deleteFixedAnnotations(); +} + +ossimRefPtr<ossimImageData> ossimMapCompositionSource::getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if(!theTile) + { + allocate(tileRect); + if(!theTile) + { + if(theInputConnection) + { + return theInputConnection->getTile(tileRect, resLevel); + } + } + } + theTile->setImageRectangle(tileRect); + theTile->makeBlank(); + + if(theInputConnection) + { + ossimRefPtr<ossimImageData> tile = theInputConnection->getTile(tileRect, + resLevel); + + if(tile.valid()) + { + if(tile->getScalarType() != OSSIM_UCHAR) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimMapCompositionSource::getTile\n" + << "Error input is not uchar" << endl; + return tile; + } + else + { + if(tile->getBuf()&&(tile->getDataObjectStatus() != OSSIM_EMPTY)) + { + int band = 0; + int outBands = theTile->getNumberOfBands(); + int minBand = std::min((long)theTile->getNumberOfBands(), + (long)tile->getNumberOfBands()); + for(band = 0; band < minBand; ++band) + { + theTile->loadBand(tile->getBuf(band), + tile->getImageRectangle(), + band); + } + // copy last band of input tile to all output + // bands if the input tile did not have enough bands. + // + for(;band < outBands;++band) + { + theTile->loadBand(tile->getBuf(minBand-1), + tile->getImageRectangle(), + band); + } + } + drawBorders(); + drawAnnotations(theTile); + } + } + } + theTile->validate(); + return theTile; +} + +void ossimMapCompositionSource::setGeographicLabelFormat(const ossimString format) +{ + if( (format == theTopGeographicFormat)&& + (format == theBottomGeographicFormat)&& + (format == theLeftGeographicFormat)&& + (format == theRightGeographicFormat)) + { + return; + } + theTopGeographicFormat = format; + theBottomGeographicFormat = format; + theLeftGeographicFormat = format; + theRightGeographicFormat = format; +} + +void ossimMapCompositionSource::setTopGeographicLabelFormat(const ossimString& format) +{ + if(format == theTopGeographicFormat) + { + return; + } + theTopGeographicFormat = format; +} + +void ossimMapCompositionSource::setBottomGeographicLabelFormat(const ossimString& format) +{ + if(format == theBottomGeographicFormat) + { + return; + } + theBottomGeographicFormat = format; + + // need to reset the fonts +// layoutAnnotations(); +} + +void ossimMapCompositionSource::setLeftGeographicLabelFormat(const ossimString& format) +{ + if(format == theLeftGeographicFormat) + { + return; + } + theLeftGeographicFormat = format; + + // need to reset the fonts +// layoutAnnotations(); +} + +void ossimMapCompositionSource::setRightGeographicLabelFormat(const ossimString& format) +{ + if(format == theRightGeographicFormat) + { + return; + } + theRightGeographicFormat = format; + +} + +void ossimMapCompositionSource::setTitleFont(const ossimFontInformation& fontInfo) +{ + if(theTitleFontInfo == fontInfo) + { + return; + } + ossimFont* font = ossimFontFactoryRegistry::instance()->createFont(fontInfo); + if(font) + { + if(theTitleFont) + { + delete theTitleFont; + theTitleFont = NULL; + } + + theTitleFont = font; + theTitleFontInfo = fontInfo; + } +} + +void ossimMapCompositionSource::setGeographicTopLabelFont(const ossimFontInformation& fontInfo) +{ + const char* MODULE = "ossimMapCompositionSource::setGeographicTopLabelFont"; + + if(traceDebug()) + { + CLOG << "Entering...." <<endl; + } + if(theGeographicTopLabelFontInfo == fontInfo) + { + if(traceDebug()) + { + CLOG << "Font info the same exiting...." <<endl + << theGeographicTopLabelFontInfo << endl; + } + + return; + } + ossimFont* font = ossimFontFactoryRegistry::instance()->createFont(fontInfo); + + if(font) + { + if(theGeographicTopLabelFont) + { + delete theGeographicTopLabelFont; + theGeographicTopLabelFont = NULL; + } + + if(traceDebug()) + { + CLOG << "Previous font info " <<endl + << theGeographicTopLabelFont << endl; + } + theGeographicTopLabelFont = font; + theGeographicTopLabelFontInfo = fontInfo; + + if(traceDebug()) + { + CLOG << "New font info " <<endl + << theGeographicTopLabelFont << endl; + } + } +} + +void ossimMapCompositionSource::setGeographicBottomLabelFont(const ossimFontInformation& fontInfo) +{ + if(theGeographicBottomLabelFontInfo == fontInfo) + { + return; + } + ossimFont* font = ossimFontFactoryRegistry::instance()->createFont(fontInfo); + + if(font) + { + if(theGeographicBottomLabelFont) + { + delete theGeographicBottomLabelFont; + theGeographicBottomLabelFont = NULL; + } + + theGeographicBottomLabelFont = font; + theGeographicBottomLabelFontInfo = fontInfo; + + } +} + +void ossimMapCompositionSource::setGeographicLeftLabelFont(const ossimFontInformation& fontInfo) +{ + if(theGeographicRightLabelFontInfo == fontInfo) + { + return; + } + ossimFont* font = ossimFontFactoryRegistry::instance()->createFont(fontInfo); + + if(font) + { + if(theGeographicLeftLabelFont) + { + delete theGeographicLeftLabelFont; + theGeographicLeftLabelFont = NULL; + } + + theGeographicLeftLabelFont = font; + theGeographicLeftLabelFontInfo = fontInfo; + + } +} + +void ossimMapCompositionSource::setGeographicRightLabelFont(const ossimFontInformation& fontInfo) +{ + if(theGeographicRightLabelFontInfo == fontInfo) + { + return; + } + + ossimFont* font = ossimFontFactoryRegistry::instance()->createFont(fontInfo); + + if(font) + { + if(theGeographicRightLabelFont) + { + delete theGeographicRightLabelFont; + theGeographicRightLabelFont = NULL; + } + + theGeographicRightLabelFont = font; + theGeographicRightLabelFontInfo = fontInfo; + } +} + + +void ossimMapCompositionSource::setMeterTopLabelFont(const ossimFontInformation& fontInfo) +{ + if(theMeterTopLabelFontInfo == fontInfo) + { + return; + } + ossimFont* font = ossimFontFactoryRegistry::instance()->createFont(fontInfo); + + if(font) + { + if(theMeterTopLabelFont) + { + delete theMeterTopLabelFont; + theMeterTopLabelFont = NULL; + } + + theMeterTopLabelFont = font; + theMeterTopLabelFontInfo = fontInfo; + } +} + +void ossimMapCompositionSource::setMeterBottomLabelFont(const ossimFontInformation& fontInfo) +{ + if(theMeterBottomLabelFontInfo == fontInfo) + { + return; + } + ossimFont* font = ossimFontFactoryRegistry::instance()->createFont(fontInfo); + + if(font) + { + if(theMeterBottomLabelFont) + { + delete theMeterBottomLabelFont; + theMeterBottomLabelFont = NULL; + } + + theMeterBottomLabelFont = font; + theMeterBottomLabelFontInfo = fontInfo; + } +} + +void ossimMapCompositionSource::setMeterLeftLabelFont(const ossimFontInformation& fontInfo) +{ + if(theMeterLeftLabelFontInfo == fontInfo) + { + return; + } + ossimFont* font = ossimFontFactoryRegistry::instance()->createFont(fontInfo); + + if(font) + { + if(theMeterLeftLabelFont) + { + delete theMeterLeftLabelFont; + theMeterLeftLabelFont = NULL; + } + + theMeterLeftLabelFont = font; + theMeterLeftLabelFontInfo = fontInfo; + } +} + +void ossimMapCompositionSource::setMeterRightLabelFont(const ossimFontInformation& fontInfo) +{ + if(theMeterRightLabelFontInfo == fontInfo) + { + return; + } + ossimFont* font = ossimFontFactoryRegistry::instance()->createFont(fontInfo); + + if(font) + { + if(theMeterRightLabelFont) + { + delete theMeterRightLabelFont; + theMeterRightLabelFont = NULL; + } + + theMeterRightLabelFont = font; + theMeterRightLabelFontInfo = fontInfo; + } +} + +ossimIrect ossimMapCompositionSource::getBoundingRect(ossim_uint32 resLevel)const +{ + ossimIrect result; + + result.makeNan(); + if(theInputConnection) + { + ossimIrect inputRect = getViewingRect(); + + if(!inputRect.hasNans()) + { + ossimDpt decimation; + getDecimationFactor(resLevel, + decimation); + int leftBorderLength = theLeftBorderLength; + int rightBorderLength = theRightBorderLength; + int topBorderLength = theTopBorderLength; + int bottomBorderLength = theBottomBorderLength; + + ossimIpt p1(inputRect.ul().x - leftBorderLength, + inputRect.ul().y - topBorderLength); + + ossimIpt p2(inputRect.ur().x + rightBorderLength, + inputRect.ur().y - topBorderLength); + + ossimIpt p3(inputRect.lr().x + rightBorderLength, + inputRect.lr().y + bottomBorderLength); + + ossimIpt p4(inputRect.ll().x - leftBorderLength, + inputRect.ll().y + bottomBorderLength); + + result = ossimIrect(p1, p2, p3, p4); + + if(!decimation.hasNans()) + { + result*=decimation; + } + } + } + return result; +} + +void ossimMapCompositionSource::layoutAnnotations() +{ + deleteFixedAnnotations(); + + addTitle(); + addGridLabels(); + if(theGeographicGridType == OSSIM_GRID_LINE) + { + addGeographicGridLines(); + } + else if(theGeographicGridType == OSSIM_GRID_RESEAUX) + { + addGeographicGridReseaux(); + } + + if(theMeterGridType == OSSIM_GRID_LINE) + { + addMeterGridLines(); + } + else if(theMeterGridType == OSSIM_GRID_RESEAUX) + { + addMeterGridReseaux(); + } +} + + +void ossimMapCompositionSource::initialize() +{ + ossimAnnotationSource::initialize(); + + if(theInputConnection) + { + if(theInputProjection) + { + delete theInputProjection; + theInputProjection = NULL; + } + + computeBorderRects(); + + ossimKeywordlist kwl; + + theInputConnection->getImageGeometry(kwl); + ossimProjection* proj = ossimProjectionFactoryRegistry::instance()->createProjection(kwl); + + theInputProjection = PTR_CAST(ossimMapProjection, proj); + if(!theInputProjection&&proj) + { + delete proj; + proj = NULL; + } + + layoutAnnotations(); + } + else + { + deleteFixedAnnotations(); + } +} + +void ossimMapCompositionSource::computeBorderRects() +{ + if(theInputConnection) + { + ossimIrect inputRect = getViewingRect();; + + theTopBorder = ossimIrect(inputRect.ul().x - theLeftBorderLength, + inputRect.ul().y - theTopBorderLength, + inputRect.ur().x + theRightBorderLength, + inputRect.ur().y); + + theBottomBorder = ossimIrect(inputRect.ll().x - theLeftBorderLength, + inputRect.ll().y, + inputRect.lr().x + theRightBorderLength, + inputRect.lr().y + theBottomBorderLength); + + theLeftBorder = ossimIrect(theTopBorder.ul().x, + theTopBorder.ll().y, + inputRect.ll().x, + inputRect.ll().y); + + theRightBorder = ossimIrect(inputRect.ur().x, + inputRect.ur().y, + theBottomBorder.lr().x, + inputRect.lr().y); + } + else + { + theTopBorder.makeNan(); + theBottomBorder.makeNan(); + theLeftBorder.makeNan(); + theRightBorder.makeNan(); + } + +} + +void ossimMapCompositionSource::drawBorders() +{ + if(theTile.valid()) + { + ossimIrect top = theTopBorder; + ossimIrect bottom = theBottomBorder; + ossimIrect left = theLeftBorder; + ossimIrect right = theRightBorder; + +// if(resLevel) +// { +// ossimDpt decimation; +// getDecimationFactor(resLevel, +// decimation); + +// if(!decimation.hasNans()) +// { +// top*=decimation; +// bottom*=decimation; +// left*=decimation; +// right*=decimation; +// } +// } + ossimIrect tileRect = theTile->getImageRectangle(); + + ossimImageDataHelper helper(theTile.get()); + + if(top.intersects(tileRect)) + { + helper.fill(theBorderColor, + top.clipToRect(tileRect),false); + } + if(bottom.intersects(tileRect)) + { + helper.fill(theBorderColor, + bottom.clipToRect(tileRect),false); + } + if(left.intersects(tileRect)) + { + helper.fill(theBorderColor, + left.clipToRect(tileRect),false); + } + if(right.intersects(tileRect)) + { + helper.fill(theBorderColor, + right.clipToRect(tileRect),false); + } + } +} + +void ossimMapCompositionSource::addGridLabels() +{ + addGeographicTopGridLabels(); + addGeographicBottomGridLabels(); + addGeographicLeftGridLabels(); + addGeographicRightGridLabels(); + + addMeterGridLabels(); +} + +void ossimMapCompositionSource::addGeographicTopGridLabels() +{ + const char* MODULE = "ossimMapCompositionSource::addGeographicTopGridLabels"; + if(traceDebug()) + { + CLOG << "Entering...." << endl; + } + if((!theTopGeographicLabelFlag)&&(!theTopGeographicTickFlag)) + { + if(traceDebug()) + { + CLOG << "Exiting, flags are false...." << endl; + } + return; + } + if(theInputConnection&&theInputProjection) + { + ossimGpt gpt[4]; + ossimDrect rect = getViewingRect(); + + if(rect.hasNans()) return; + theInputProjection->lineSampleToWorld(rect.ul(), + gpt[0]); + theInputProjection->lineSampleToWorld(rect.ur(), + gpt[1]); + theInputProjection->lineSampleToWorld(rect.lr(), + gpt[2]); + theInputProjection->lineSampleToWorld(rect.ll(), + gpt[3]); + + ossimDrect grect(gpt[0], + gpt[1], + gpt[2], + gpt[3], + OSSIM_RIGHT_HANDED); + + if(grect.hasNans()) return; + ossimDpt ulLatLon(((int)((grect.ul().x-theGeographicSpacing.x)/theGeographicSpacing.x))*theGeographicSpacing.x, + ((int)((grect.ul().y+theGeographicSpacing.y)/theGeographicSpacing.y))*theGeographicSpacing.y); + + ossimDpt lrLatLon(((int)((grect.lr().x+theGeographicSpacing.x)/theGeographicSpacing.x))*theGeographicSpacing.x, + ((int)((grect.lr().y-theGeographicSpacing.y)/theGeographicSpacing.y))*theGeographicSpacing.y); + + while(ulLatLon.lat > 90) + { + ulLatLon.lat -= theGeographicSpacing.lat; + } + while(ulLatLon.lon < -180) + { + ulLatLon.lon += theGeographicSpacing.lon; + } + while(lrLatLon.lat < -90) + { + ulLatLon.lat += theGeographicSpacing.lat; + } + while(lrLatLon.lon > 180) + { + ulLatLon.lon -= theGeographicSpacing.lon; + } + + ossimDrect latLonSpacing(ulLatLon, + lrLatLon, + OSSIM_RIGHT_HANDED); + + if(traceDebug()) + { + CLOG << "labeling bounding geo rect = " << latLonSpacing << endl; + } + // do the top side labels. + for(double lon = latLonSpacing.ul().x; lon <= latLonSpacing.lr().x; lon+=theGeographicSpacing.x) + { + ossimDpt tipt; // top + ossimDpt bipt; // bottom + + ossimGpt tgpt(latLonSpacing.ul().y, + lon, + 0.0, + gpt[0].datum()); + + ossimGpt bgpt(latLonSpacing.lr().y, + lon, + 0.0, + gpt[0].datum()); + + theInputProjection->worldToLineSample(tgpt, + tipt); + + theInputProjection->worldToLineSample(bgpt, + bipt); + + + if((!tipt.hasNans()&& + !bipt.hasNans()) && + rect.clip(tipt, bipt)) + { + ossimIpt rounded(tipt); + if( (rounded.x >= rect.ul().x)&& + (rounded.x <= rect.lr().x)) + { + if(theTopGeographicLabelFlag) + { + ossimDms dms(tgpt.lond(), false); + + ossimString dmsString = dms.toString(theTopGeographicFormat.c_str()); + ossimAnnotationFontObject* lonLabel = new ossimAnnotationFontObject(ossimIpt(0,0), + dmsString); + lonLabel->setFont(theGeographicTopLabelFont, false); + + lonLabel->setGeometryInformation(theGeographicTopLabelFontInfo); + lonLabel->computeBoundingRect(); + ossimDrect boundsD; + lonLabel->getBoundingRect(boundsD); + + ossimIpt center( rounded.x, + irint(rect.ul().y-(boundsD.height()/2))); + + lonLabel->setColor(theTopGeographicLabelColor.getR(), theTopGeographicLabelColor.getG(), theTopGeographicLabelColor.getB()); + lonLabel->setPositionCenter(center); + lonLabel->computeBoundingRect(); + + ossimDrect labelRect; + lonLabel->getBoundingRect(labelRect); + + if(rect.intersects(labelRect)) + { + ossimIrect intersection = rect.clipToRect(labelRect); + center.y -= irint(rect.ul().y - intersection.lr().y); + } + + center.y -= 24; // this will need to be the tick height later; + lonLabel->setPositionCenter(center); + lonLabel->computeBoundingRect(); + + addFixedAnnotation(lonLabel); + } + if(theTopGeographicTickFlag) + { + ossimAnnotationLineObject* lineLabel = new ossimAnnotationLineObject(ossimIpt(rounded.x, + irint(rect.ul().y-24)), + ossimIpt(rounded.x, + irint(rect.ul().y))); + lineLabel->setColor(theTopGeographicLabelColor.getR(), theTopGeographicLabelColor.getG(), theTopGeographicLabelColor.getB()); + addFixedAnnotation(lineLabel); + } + } + } + } + } + if(traceDebug()) + { + CLOG << "Exiting...." << endl; + } +} + +void ossimMapCompositionSource::addGeographicBottomGridLabels() +{ + if((!theBottomGeographicLabelFlag)&&(!theBottomGeographicTickFlag)) + { + return; + } + if(theInputConnection&&theInputProjection) + { + ossimGpt gpt[4]; + ossimDrect rect = getViewingRect(); + + if(rect.hasNans()) return; + theInputProjection->lineSampleToWorld(rect.ul(), + gpt[0]); + theInputProjection->lineSampleToWorld(rect.ur(), + gpt[1]); + theInputProjection->lineSampleToWorld(rect.lr(), + gpt[2]); + theInputProjection->lineSampleToWorld(rect.ll(), + gpt[3]); + + ossimDrect grect(gpt[0], + gpt[1], + gpt[2], + gpt[3], + OSSIM_RIGHT_HANDED); + + if(grect.hasNans()) return; + ossimDpt ulLatLon(((int)((grect.ul().x-theGeographicSpacing.x)/theGeographicSpacing.x))*theGeographicSpacing.x, + ((int)((grect.ul().y+theGeographicSpacing.y)/theGeographicSpacing.y))*theGeographicSpacing.y); + + ossimDpt lrLatLon(((int)((grect.lr().x+theGeographicSpacing.x)/theGeographicSpacing.x))*theGeographicSpacing.x, + ((int)((grect.lr().y-theGeographicSpacing.y)/theGeographicSpacing.y))*theGeographicSpacing.y); + + while(ulLatLon.lat > 90) + { + ulLatLon.lat -= theGeographicSpacing.lat; + } + while(ulLatLon.lon < -180) + { + ulLatLon.lon += theGeographicSpacing.lon; + } + while(lrLatLon.lat < -90) + { + ulLatLon.lat += theGeographicSpacing.lat; + } + while(lrLatLon.lon > 180) + { + ulLatLon.lon -= theGeographicSpacing.lon; + } + + ossimDrect latLonSpacing(ulLatLon, + lrLatLon, + OSSIM_RIGHT_HANDED); + + // do the top side labels. + for(double lon = latLonSpacing.ul().x; lon <= latLonSpacing.lr().x; lon+=theGeographicSpacing.x) + { + ossimDpt tipt; // top + ossimDpt bipt; // bottom + + ossimGpt tgpt(latLonSpacing.ul().y, + lon, + 0.0, + gpt[0].datum()); + + ossimGpt bgpt(latLonSpacing.lr().y, + lon, + 0.0, + gpt[0].datum()); + + theInputProjection->worldToLineSample(tgpt, + tipt); + + theInputProjection->worldToLineSample(bgpt, + bipt); + + if(rect.clip(tipt, bipt)) + { + ossimIpt rounded(bipt); + if( (rounded.x >= rect.ul().x)&& + (rounded.x <= rect.lr().x)) + { + if(theBottomGeographicLabelFlag) + { + ossimDms dms(bgpt.lond(), false); + + ossimString dmsString = dms.toString(theBottomGeographicFormat.c_str()); + ossimAnnotationFontObject* lonLabel = new ossimAnnotationFontObject(ossimIpt(0,0), + dmsString); + lonLabel->setGeometryInformation(theGeographicBottomLabelFontInfo); + lonLabel->setFont(theGeographicBottomLabelFont, false); +// lonLabel->setFont(theGeographicBottomLabelFont->dup()); + + lonLabel->computeBoundingRect(); + ossimDrect boundsD; + lonLabel->getBoundingRect(boundsD); + ossimIrect bounds = boundsD; + + ossimIpt center( rounded.x, + irint(rect.lr().y+(bounds.height()/2))); + + lonLabel->setColor(theBottomGeographicLabelColor.getR(), theBottomGeographicLabelColor.getG(), theBottomGeographicLabelColor.getB()); + lonLabel->setPositionCenter(center); + lonLabel->computeBoundingRect(); + lonLabel->getBoundingRect(boundsD); + bounds = boundsD; + + ossimDrect labelRect; + lonLabel->getBoundingRect(labelRect); + + if(rect.intersects(labelRect)) + { + ossimIrect intersection = rect.clipToRect(labelRect); + center.y += irint(rect.lr().y - intersection.ul().y); + } + + center.y += 24; // this will need to be the tick height later; + lonLabel->setPositionCenter(center); + lonLabel->computeBoundingRect(); + + + addFixedAnnotation(lonLabel); + } + if(theBottomGeographicTickFlag) + { + ossimAnnotationLineObject* lineLabel = new ossimAnnotationLineObject(ossimIpt(rounded.x, + irint(rect.lr().y+24)), + ossimIpt(rounded.x, + irint(rect.lr().y))); + lineLabel->setColor(theBottomGeographicLabelColor.getR(), theBottomGeographicLabelColor.getG(), theBottomGeographicLabelColor.getB()); + addFixedAnnotation(lineLabel); + } + } + } + } + } +} + +void ossimMapCompositionSource::addGeographicLeftGridLabels() +{ + if((!theLeftGeographicLabelFlag)&&(!theLeftGeographicTickFlag)) + { + return; + } + if(theInputConnection&&theInputProjection) + { + ossimGpt gpt[4]; + ossimDrect rect = getViewingRect(); + + if(rect.hasNans()) return; + theInputProjection->lineSampleToWorld(rect.ul(), + gpt[0]); + theInputProjection->lineSampleToWorld(rect.ur(), + gpt[1]); + theInputProjection->lineSampleToWorld(rect.lr(), + gpt[2]); + theInputProjection->lineSampleToWorld(rect.ll(), + gpt[3]); + + ossimDrect grect(gpt[0], + gpt[1], + gpt[2], + gpt[3], + OSSIM_RIGHT_HANDED); + + if(grect.hasNans()) return; + ossimDpt ulLatLon(((int)((grect.ul().x-theGeographicSpacing.x)/theGeographicSpacing.x))*theGeographicSpacing.x, + ((int)((grect.ul().y+theGeographicSpacing.y)/theGeographicSpacing.y))*theGeographicSpacing.y); + + ossimDpt lrLatLon(((int)((grect.lr().x+theGeographicSpacing.x)/theGeographicSpacing.x))*theGeographicSpacing.x, + ((int)((grect.lr().y-theGeographicSpacing.y)/theGeographicSpacing.y))*theGeographicSpacing.y); + + while(ulLatLon.lat > 90) + { + ulLatLon.lat -= theGeographicSpacing.lat; + } + while(ulLatLon.lon < -180) + { + ulLatLon.lon += theGeographicSpacing.lon; + } + while(lrLatLon.lat < -90) + { + ulLatLon.lat += theGeographicSpacing.lat; + } + while(lrLatLon.lon > 180) + { + ulLatLon.lon -= theGeographicSpacing.lon; + } + + ossimDrect latLonSpacing(ulLatLon, + lrLatLon, + OSSIM_RIGHT_HANDED); + // do the left side labels + for(double lat = latLonSpacing.ul().y; lat >= latLonSpacing.lr().y; lat-=theGeographicSpacing.y) + { + ossimDpt lipt; + ossimDpt ript; + ossimGpt lgpt(lat, + latLonSpacing.ul().x, + 0.0, + gpt[0].datum()); + ossimGpt rgpt(lat, + latLonSpacing.ur().x, + 0.0, + gpt[0].datum()); + + + theInputProjection->worldToLineSample(lgpt, + lipt); + + theInputProjection->worldToLineSample(rgpt, + ript); + if(rect.clip(lipt, ript)) + { + ossimIpt rounded(lipt); + if( (rounded.y >= rect.ul().y)&& + (rounded.y <= rect.lr().y)) + { + if(theLeftGeographicLabelFlag) + { + ossimDms dms(lgpt.latd()); + + ossimString dmsString = dms.toString(theLeftGeographicFormat.c_str()); + ossimAnnotationFontObject* latLabel = new ossimAnnotationFontObject(ossimIpt(0,0), + dmsString); + latLabel->setGeometryInformation(theGeographicLeftLabelFontInfo); + latLabel->setFont(theGeographicLeftLabelFont, false); +// latLabel->setFont(theGeographicLeftLabelFont->dup()); + + latLabel->computeBoundingRect(); + ossimDrect boundsD; + latLabel->getBoundingRect(boundsD); + ossimIrect bounds = boundsD; + + ossimIpt center( irint((rect.ul().x - (bounds.width()/2))), + rounded.y); + + latLabel->setColor(theLeftGeographicLabelColor.getR(), theLeftGeographicLabelColor.getG(), theLeftGeographicLabelColor.getB()); + latLabel->setPositionCenter(center); + latLabel->computeBoundingRect(); + latLabel->getBoundingRect(boundsD); + bounds = boundsD; + + ossimDrect labelRect; + latLabel->getBoundingRect(labelRect); + + if(rect.intersects(labelRect)) + { + ossimIrect intersection = rect.clipToRect(labelRect); + center.x -= irint(rect.ul().x - intersection.ur().x); + } + + center.x -= 24; // this will need to be the tick height later; + latLabel->setPositionCenter(center); + latLabel->computeBoundingRect(); + + + + addFixedAnnotation(latLabel); + } + + if(theLeftGeographicTickFlag) + { + ossimAnnotationLineObject* lineLabel = new ossimAnnotationLineObject(ossimIpt(irint(rect.ul().x), + rounded.y), + ossimIpt(irint(rect.ul().x-23), + rounded.y)); + lineLabel->setColor(theLeftGeographicLabelColor.getR(), theLeftGeographicLabelColor.getG(), theLeftGeographicLabelColor.getB()); + addFixedAnnotation(lineLabel); + } + } + } + } + } +} + +void ossimMapCompositionSource::addGeographicRightGridLabels() +{ + if((!theRightGeographicLabelFlag)&&(!theRightGeographicTickFlag)) + { + return; + } + if(theInputConnection&&theInputProjection) + { + ossimGpt gpt[4]; + ossimDrect rect = getViewingRect(); + + if(rect.hasNans()) return; + theInputProjection->lineSampleToWorld(rect.ul(), + gpt[0]); + theInputProjection->lineSampleToWorld(rect.ur(), + gpt[1]); + theInputProjection->lineSampleToWorld(rect.lr(), + gpt[2]); + theInputProjection->lineSampleToWorld(rect.ll(), + gpt[3]); + + ossimDrect grect(gpt[0], + gpt[1], + gpt[2], + gpt[3], + OSSIM_RIGHT_HANDED); + + if(grect.hasNans()) return; + ossimDpt ulLatLon(((int)((grect.ul().x-theGeographicSpacing.x)/theGeographicSpacing.x))*theGeographicSpacing.x, + ((int)((grect.ul().y+theGeographicSpacing.y)/theGeographicSpacing.y))*theGeographicSpacing.y); + + ossimDpt lrLatLon(((int)((grect.lr().x+theGeographicSpacing.x)/theGeographicSpacing.x))*theGeographicSpacing.x, + ((int)((grect.lr().y-theGeographicSpacing.y)/theGeographicSpacing.y))*theGeographicSpacing.y); + + while(ulLatLon.lat > 90) + { + ulLatLon.lat -= theGeographicSpacing.lat; + } + while(ulLatLon.lon < -180) + { + ulLatLon.lon += theGeographicSpacing.lon; + } + while(lrLatLon.lat < -90) + { + ulLatLon.lat += theGeographicSpacing.lat; + } + while(lrLatLon.lon > 180) + { + ulLatLon.lon -= theGeographicSpacing.lon; + } + + ossimDrect latLonSpacing(ulLatLon, + lrLatLon, + OSSIM_RIGHT_HANDED); + // do the left side labels + for(double lat = latLonSpacing.ul().y; lat >= latLonSpacing.lr().y; lat-=theGeographicSpacing.y) + { + ossimDpt lipt; + ossimDpt ript; + ossimGpt lgpt(lat, + latLonSpacing.ul().x, + 0.0, + gpt[0].datum()); + ossimGpt rgpt(lat, + latLonSpacing.ur().x, + 0.0, + gpt[0].datum()); + + + theInputProjection->worldToLineSample(lgpt, + lipt); + + theInputProjection->worldToLineSample(rgpt, + ript); + + if(rect.clip(lipt, ript)) + { + ossimIpt rounded(ript); + if( (rounded.y >= rect.ul().y)&& + (rounded.y <= rect.lr().y)) + { + if(theRightGeographicLabelFlag) + { + ossimDms dms(rgpt.latd()); + + ossimString dmsString = dms.toString(theRightGeographicFormat.c_str()); + ossimAnnotationFontObject* latLabel = new ossimAnnotationFontObject(ossimIpt(0,0), + dmsString); + latLabel->setGeometryInformation(theGeographicRightLabelFontInfo); + latLabel->setFont(theGeographicRightLabelFont, false); +// latLabel->setFont(theGeographicRightLabelFont->dup()); + latLabel->computeBoundingRect(); + ossimDrect boundsD; + latLabel->getBoundingRect(boundsD); + ossimIrect bounds = boundsD; + + ossimIpt center( irint((rect.ur().x + (bounds.width()/2))), + rounded.y); + + latLabel->setColor(theRightGeographicLabelColor.getR(), theRightGeographicLabelColor.getG(), theRightGeographicLabelColor.getB()); + latLabel->setPositionCenter(center); + latLabel->computeBoundingRect(); + latLabel->getBoundingRect(boundsD); + bounds = boundsD; + + ossimDrect labelRect; + latLabel->getBoundingRect(labelRect); + + if(rect.intersects(labelRect)) + { + ossimIrect intersection = rect.clipToRect(labelRect); + center.x -= irint(rect.ur().x - intersection.ul().x); + } + + center.x += 24; // this will need to be the tick height later; + latLabel->setPositionCenter(center); + latLabel->computeBoundingRect(); + + + addFixedAnnotation(latLabel); + } + + if(theRightGeographicTickFlag) + { + ossimAnnotationLineObject* lineLabel = new ossimAnnotationLineObject(ossimIpt(irint(rect.lr().x), + rounded.y), + ossimIpt(irint(rect.lr().x+23), + rounded.y)); + + lineLabel->setColor(theRightGeographicLabelColor.getR(), theRightGeographicLabelColor.getG(), theRightGeographicLabelColor.getB()); + addFixedAnnotation(lineLabel); + } + } + } + } + } +} + +void ossimMapCompositionSource::addGeographicGridLines() +{ + if(theInputConnection&&theInputProjection) + { + ossimGpt gpt[4]; + ossimDrect rect = getViewingRect(); + + if(rect.hasNans()) return; + theInputProjection->lineSampleToWorld(rect.ul(), + gpt[0]); + theInputProjection->lineSampleToWorld(rect.ur(), + gpt[1]); + theInputProjection->lineSampleToWorld(rect.lr(), + gpt[2]); + theInputProjection->lineSampleToWorld(rect.ll(), + gpt[3]); + + ossimDrect grect(gpt[0], + gpt[1], + gpt[2], + gpt[3], + OSSIM_RIGHT_HANDED); + + if(grect.hasNans()) return; + ossimDpt ulLatLon(((int)((grect.ul().x-theGeographicSpacing.x)/theGeographicSpacing.x))*theGeographicSpacing.x, + ((int)((grect.ul().y+theGeographicSpacing.y)/theGeographicSpacing.y))*theGeographicSpacing.y); + + ossimDpt lrLatLon(((int)((grect.lr().x+theGeographicSpacing.x)/theGeographicSpacing.x))*theGeographicSpacing.x, + ((int)((grect.lr().y-theGeographicSpacing.y)/theGeographicSpacing.y))*theGeographicSpacing.y); + + while(ulLatLon.lat > 90) + { + ulLatLon.lat -= theGeographicSpacing.lat; + } + while(ulLatLon.lon < -180) + { + ulLatLon.lon += theGeographicSpacing.lon; + } + while(lrLatLon.lat < -90) + { + ulLatLon.lat += theGeographicSpacing.lat; + } + while(lrLatLon.lon > 180) + { + ulLatLon.lon -= theGeographicSpacing.lon; + } + + ossimDrect latLonSpacing(ulLatLon, + lrLatLon, + OSSIM_RIGHT_HANDED); + + + for(double lon = latLonSpacing.ul().x; lon <= latLonSpacing.lr().x; lon+=theGeographicSpacing.x) + { + ossimDpt tipt; // top + ossimDpt bipt; // bottom + + ossimGpt tgpt(latLonSpacing.ul().y, + lon, + 0.0, + gpt[0].datum()); + + ossimGpt bgpt(latLonSpacing.lr().y, + lon, + 0.0, + gpt[0].datum()); + + theInputProjection->worldToLineSample(tgpt, + tipt); + + theInputProjection->worldToLineSample(bgpt, + bipt); + + if(rect.clip(tipt, bipt)) + { + ossimAnnotationLineObject* line = new ossimAnnotationLineObject(tipt, bipt); + line->setColor(theGeographicGridColor.getR(), + theGeographicGridColor.getG(), + theGeographicGridColor.getB()); + addFixedAnnotation(line); + } + } + // do the left side labels + for(double lat = latLonSpacing.ul().y; lat >= latLonSpacing.lr().y; lat-=theGeographicSpacing.y) + { + ossimDpt lipt; + ossimDpt ript; + ossimGpt lgpt(lat, + latLonSpacing.ul().x, + 0.0, + gpt[0].datum()); + ossimGpt rgpt(lat, + latLonSpacing.ur().x, + 0.0, + gpt[0].datum()); + + theInputProjection->worldToLineSample(lgpt, + lipt); + theInputProjection->worldToLineSample(rgpt, + ript); + + if(rect.clip(lipt, ript)) + { + ossimAnnotationLineObject* line = new ossimAnnotationLineObject(lipt, + ript); + + line->setColor(theGeographicGridColor.getR(), + theGeographicGridColor.getG(), + theGeographicGridColor.getB()); + + addFixedAnnotation(line); + } + } + } +} + +void ossimMapCompositionSource::addGeographicGridReseaux() +{ + if(theInputConnection&&theInputProjection) + { + ossimGpt gptArray[4]; + ossimDrect rect = getViewingRect(); + + theInputProjection->lineSampleToWorld(rect.ul(), + gptArray[0]); + theInputProjection->lineSampleToWorld(rect.ur(), + gptArray[1]); + theInputProjection->lineSampleToWorld(rect.lr(), + gptArray[2]); + theInputProjection->lineSampleToWorld(rect.ll(), + gptArray[3]); + + ossimDrect grect(gptArray[0], + gptArray[1], + gptArray[2], + gptArray[3], + OSSIM_RIGHT_HANDED); + + ossimDpt ulLatLon(((int)((grect.ul().x-theGeographicSpacing.x)/theGeographicSpacing.x))*theGeographicSpacing.x, + ((int)((grect.ul().y+theGeographicSpacing.y)/theGeographicSpacing.y))*theGeographicSpacing.y); + + ossimDpt lrLatLon(((int)((grect.lr().x+theGeographicSpacing.x)/theGeographicSpacing.x))*theGeographicSpacing.x, + ((int)((grect.lr().y-theGeographicSpacing.y)/theGeographicSpacing.y))*theGeographicSpacing.y); + + ossimDrect latLonSpacing(ulLatLon, + lrLatLon, + OSSIM_RIGHT_HANDED); + + ossimDpt ipt; // top + for(double lat = latLonSpacing.ul().y; lat >= latLonSpacing.lr().y; lat-=theGeographicSpacing.y) + { + for(double lon = latLonSpacing.ul().x; lon <= latLonSpacing.lr().x; lon+=theGeographicSpacing.x) + { + + ossimGpt gpt(lat, + lon, + 0.0, + gptArray[0].datum()); + + + theInputProjection->worldToLineSample(gpt, + ipt); + + ossimIpt rounded(ipt); + if(rect.pointWithin(ossimDpt(rounded))) + { + ossimIpt horizontalStart(rounded.x-10, rounded.y); + ossimIpt horizontalEnd(rounded.x+10, rounded.y); + + ossimIpt verticalStart(rounded.x, rounded.y-10); + ossimIpt verticalEnd(rounded.x, rounded.y+10); + + ossimAnnotationLineObject* line1 = new ossimAnnotationLineObject(horizontalStart, horizontalEnd); + ossimAnnotationLineObject* line2 = new ossimAnnotationLineObject(verticalStart,verticalEnd); + + line1->setColor(theGeographicGridColor.getR(), + theGeographicGridColor.getG(), + theGeographicGridColor.getB()); + line2->setColor(theGeographicGridColor.getR(), + theGeographicGridColor.getG(), + theGeographicGridColor.getB()); + addFixedAnnotation(line1); + addFixedAnnotation(line2); + } + } + } + } +} + +void ossimMapCompositionSource::addMeterGridLines() +{ + if(theInputConnection&&theInputProjection) + { + ossimDpt dptArray[4]; + ossimDrect rect = getViewingRect(); + + theInputProjection->lineSampleToEastingNorthing(rect.ul(), + dptArray[0]); + theInputProjection->lineSampleToEastingNorthing(rect.ur(), + dptArray[1]); + theInputProjection->lineSampleToEastingNorthing(rect.lr(), + dptArray[2]); + theInputProjection->lineSampleToEastingNorthing(rect.ll(), + dptArray[3]); + + + ossimDrect drect(dptArray[0], + dptArray[1], + dptArray[2], + dptArray[3], + OSSIM_RIGHT_HANDED); + + ossimDpt ulMeter(((int)((drect.ul().x-theMeterSpacing.x)/theMeterSpacing.x))*theMeterSpacing.x, + ((int)((drect.ul().y+theMeterSpacing.y)/theMeterSpacing.y))*theMeterSpacing.y); + + ossimDpt lrMeter(((int)((drect.lr().x+theMeterSpacing.x)/theMeterSpacing.x))*theMeterSpacing.x, + ((int)((drect.lr().y-theMeterSpacing.y)/theMeterSpacing.y))*theMeterSpacing.y); + + ossimDrect meterSpacing(ulMeter, + lrMeter, + OSSIM_RIGHT_HANDED); + + for(double horizontal = meterSpacing.ul().x; + horizontal <= meterSpacing.lr().x; + horizontal+=theMeterSpacing.x) + { + ossimDpt tipt; // top + ossimDpt bipt; // bottom + + ossimDpt tdpt(horizontal, + meterSpacing.ul().y); + + ossimDpt bdpt(horizontal, + meterSpacing.lr().y); + + theInputProjection->eastingNorthingToLineSample(tdpt, + tipt); + + theInputProjection->eastingNorthingToLineSample(bdpt, + bipt); + + if(rect.clip(tipt, bipt)) + { + ossimAnnotationLineObject* line = new ossimAnnotationLineObject(tipt, bipt); + line->setColor(theMeterGridColor.getR(), + theMeterGridColor.getG(), + theMeterGridColor.getB()); + addFixedAnnotation(line); + } + } + // do the left side labels + for(double vertical = meterSpacing.ul().y; + vertical >= meterSpacing.lr().y; + vertical-=theMeterSpacing.y) + { + ossimDpt lipt; + ossimDpt ript; + ossimDpt ldpt(meterSpacing.ul().x, + vertical); + ossimDpt rdpt(meterSpacing.ur().x, + vertical); + + theInputProjection->eastingNorthingToLineSample(ldpt, + lipt); + theInputProjection->eastingNorthingToLineSample(rdpt, + ript); + + if(rect.clip(lipt, ript)) + { + ossimAnnotationLineObject* line = new ossimAnnotationLineObject(lipt, + ript); + + line->setColor(theMeterGridColor.getR(), + theMeterGridColor.getG(), + theMeterGridColor.getB()); + + addFixedAnnotation(line); + } + } + } +} + +void ossimMapCompositionSource::addMeterGridLabels() +{ + if(theInputConnection&&theInputProjection) + { + ossimDpt dptArray[4]; + ossimDrect rect = getViewingRect(); + + theInputProjection->lineSampleToEastingNorthing(rect.ul(), + dptArray[0]); + theInputProjection->lineSampleToEastingNorthing(rect.ur(), + dptArray[1]); + theInputProjection->lineSampleToEastingNorthing(rect.lr(), + dptArray[2]); + theInputProjection->lineSampleToEastingNorthing(rect.ll(), + dptArray[3]); + + ossimDrect drect(dptArray[0], + dptArray[1], + dptArray[2], + dptArray[3], + OSSIM_RIGHT_HANDED); + + ossimDpt ulMeter(((int)((drect.ul().x-theMeterSpacing.x)/theMeterSpacing.x))*theMeterSpacing.x, + ((int)((drect.ul().y+theMeterSpacing.y)/theMeterSpacing.y))*theMeterSpacing.y); + + ossimDpt lrMeter(((int)((drect.lr().x+theMeterSpacing.x)/theMeterSpacing.x))*theMeterSpacing.x, + ((int)((drect.lr().y-theMeterSpacing.y)/theMeterSpacing.y))*theMeterSpacing.y); + + ossimDrect meterSpacing(ulMeter, + lrMeter, + OSSIM_RIGHT_HANDED); + + ossimDrect labelRect; + + // Since we support overlapping grid lables. We will shift + // the meter label if there exists a gegraphic label. To + // do this we need to compute an extra shift length based + // on the font type on each of the sides. We could actually make this + // shift adjustable later???? + // + long extraTopDelta = 0; + long extraBottomDelta = 0; + long extraLeftDelta = 0; + long extraRightDelta = 0; + + if(theTopGeographicLabelFlag&&theGeographicTopLabelFont) + { + ossimDms dms(180, false); + ossimString dmsString = dms.toString(theTopGeographicFormat.c_str()); + + theGeographicTopLabelFont->setString(dmsString); + ossimIrect box; + + theGeographicTopLabelFont->getBoundingBox(box); + extraTopDelta = box.height(); + } + if(theBottomGeographicLabelFlag&&theGeographicBottomLabelFont) + { + ossimDms dms(180, false); + ossimString dmsString = dms.toString(theBottomGeographicFormat.c_str()); + theGeographicBottomLabelFont->setString(dmsString); + ossimIrect box; + + theGeographicBottomLabelFont->getBoundingBox(box); + extraBottomDelta = box.height(); + } + if(theLeftGeographicLabelFlag&&theGeographicLeftLabelFont) + { + ossimDms dms(90.0, true); + ossimString dmsString = dms.toString(theLeftGeographicFormat.c_str()); + theGeographicLeftLabelFont->setString(dmsString); + ossimIrect box; + + theGeographicLeftLabelFont->getBoundingBox(box); + extraLeftDelta = box.width(); + } + if(theRightGeographicLabelFlag&&theGeographicRightLabelFont) + { + ossimDms dms(90.0, true); + ossimString dmsString = dms.toString(theRightGeographicFormat.c_str()); + + theGeographicRightLabelFont->setString(dmsString); + ossimIrect box; + + theGeographicRightLabelFont->getBoundingBox(box); + extraRightDelta = box.width(); + } + + if(theTopMeterLabelFlag || theBottomMeterLabelFlag) + { + for(double horizontal = meterSpacing.ul().x; + horizontal <= meterSpacing.lr().x; + horizontal+=theMeterSpacing.x) + { + ossimDpt tipt; // top + ossimDpt bipt; // bottom + + ossimDpt tdpt(horizontal, + meterSpacing.ul().y); + + ossimDpt bdpt(horizontal, + meterSpacing.lr().y); + + theInputProjection->eastingNorthingToLineSample(tdpt, + tipt); + + theInputProjection->eastingNorthingToLineSample(bdpt, + bipt); + + rect.clip(tipt, bipt); + + tipt = ossimIpt(tipt); + bipt = ossimIpt(bipt); + + if(theTopMeterLabelFlag&&rect.clip(tipt, bipt)) + { + ossimAnnotationFontObject* topLabel = new ossimAnnotationFontObject(ossimIpt(0,0), + ossimString::toString(horizontal).c_str()); + + + topLabel->setFont(theMeterTopLabelFont, false); + + topLabel->setGeometryInformation(theMeterTopLabelFontInfo); + topLabel->computeBoundingRect(); + ossimDrect boundsTop; + topLabel->getBoundingRect(boundsTop); + + ossimIpt centerTop(irint(tipt.x), + irint(rect.ul().y-(boundsTop.height()/2))); + + topLabel->setColor(theTopMeterLabelColor.getR(), + theTopMeterLabelColor.getG(), + theTopMeterLabelColor.getB()); + + + topLabel->setPositionCenter(centerTop); + topLabel->computeBoundingRect(); + + topLabel->getBoundingRect(labelRect); + + if(rect.intersects(labelRect)) + { + ossimIrect intersection = rect.clipToRect(labelRect); + centerTop.y -= irint(rect.ul().y - intersection.lr().y); + } + + centerTop.y -= (24+extraTopDelta); // this will need to be the tick height later; + topLabel->setPositionCenter(centerTop); + topLabel->computeBoundingRect(); + addFixedAnnotation(topLabel); + + if(theTopMeterTickFlag) + { + ossimAnnotationLineObject* lineLabel = new ossimAnnotationLineObject(ossimIpt(irint(tipt.x), + irint(tipt.y-24)), + ossimIpt(irint(tipt.x), + irint(tipt.y))); + + lineLabel->setColor(theTopMeterLabelColor.getR(), theTopMeterLabelColor.getG(), theTopMeterLabelColor.getB()); + addFixedAnnotation(lineLabel); + } + } + // ------------------------- BOTTOM ---------------------------- + + if(theBottomMeterLabelFlag&&rect.pointWithin(bipt)) + { + ossimAnnotationFontObject* bottomLabel = new ossimAnnotationFontObject(ossimIpt(0,0), + ossimString::toString(horizontal).c_str()); + + + bottomLabel->setFont(theMeterBottomLabelFont, false); + + bottomLabel->setGeometryInformation(theMeterBottomLabelFontInfo); + bottomLabel->computeBoundingRect(); + ossimDrect boundsBottom; + bottomLabel->getBoundingRect(boundsBottom); + + ossimIpt centerBottom(irint(bipt.x), + irint(rect.lr().y+(boundsBottom.height()/2))); + + bottomLabel->setColor(theBottomMeterLabelColor.getR(), + theBottomMeterLabelColor.getG(), + theBottomMeterLabelColor.getB()); + + + bottomLabel->setPositionCenter(centerBottom); + bottomLabel->computeBoundingRect(); + + bottomLabel->getBoundingRect(labelRect); + + if(rect.intersects(labelRect)) + { + ossimIrect intersection = rect.clipToRect(labelRect); + centerBottom.y += irint(rect.lr().y - intersection.ul().y); + } + + centerBottom.y += (24+extraBottomDelta); // this will need to be the tick height later; + bottomLabel->setPositionCenter(centerBottom); + bottomLabel->computeBoundingRect(); + addFixedAnnotation(bottomLabel); + if(theBottomMeterTickFlag) + { + ossimAnnotationLineObject* lineLabel = new ossimAnnotationLineObject(ossimIpt(irint(bipt.x), + irint(bipt.y+24)), + ossimIpt(irint(bipt.x), + irint(bipt.y))); + + lineLabel->setColor(theBottomMeterLabelColor.getR(), theBottomMeterLabelColor.getG(), theBottomMeterLabelColor.getB()); + addFixedAnnotation(lineLabel); + } + } + } + } + if(theLeftMeterLabelFlag || theRightMeterLabelFlag) + { + for(double vertical = meterSpacing.ul().y; + vertical >= meterSpacing.lr().y; + vertical-=theMeterSpacing.y) + { + ossimDpt lipt; + ossimDpt ript; + ossimDpt ldpt(meterSpacing.ul().x, + vertical); + ossimDpt rdpt(meterSpacing.ur().x, + vertical); + + theInputProjection->eastingNorthingToLineSample(ldpt, + lipt); + theInputProjection->eastingNorthingToLineSample(rdpt, + ript); + + if(rect.clip(lipt, ript)) + { + //------------------------------------------------ Left label ---------------------------------------------- + ossimAnnotationFontObject* leftLabel = new ossimAnnotationFontObject(ossimIpt(0,0), + ossimString::toString(vertical).c_str()); + + + leftLabel->setFont(theMeterLeftLabelFont, false); + + leftLabel->setGeometryInformation(theMeterLeftLabelFontInfo); + leftLabel->computeBoundingRect(); + ossimDrect boundsLeft; + leftLabel->getBoundingRect(boundsLeft); + + ossimIpt centerLeft(irint(rect.ul().x-(boundsLeft.width()/2)), + irint(lipt.y)); + + + leftLabel->setColor(theLeftMeterLabelColor.getR(), + theLeftMeterLabelColor.getG(), + theLeftMeterLabelColor.getB()); + + + leftLabel->setPositionCenter(centerLeft); + leftLabel->computeBoundingRect(); + + leftLabel->getBoundingRect(labelRect); + + if(rect.intersects(labelRect)) + { + ossimIrect intersection = rect.clipToRect(labelRect); + centerLeft.x -= irint(intersection.lr().x - rect.ul().x); + } + + centerLeft.x -= (24+extraLeftDelta); // this will need to be the tick height later; + leftLabel->setPositionCenter(centerLeft); + leftLabel->computeBoundingRect(); + addFixedAnnotation(leftLabel); + if(theLeftMeterTickFlag) + { + ossimAnnotationLineObject* lineLabel = new ossimAnnotationLineObject(ossimIpt(irint(lipt.x-24), + irint(lipt.y)), + ossimIpt(irint(lipt.x), + irint(lipt.y))); + + lineLabel->setColor(theLeftMeterLabelColor.getR(), theLeftMeterLabelColor.getG(), theLeftMeterLabelColor.getB()); + addFixedAnnotation(lineLabel); + } + + + //--------------------------------RIGHT----------------------------------------------------------- + ossimAnnotationFontObject* rightLabel = new ossimAnnotationFontObject(ossimIpt(0,0), + ossimString::toString(vertical).c_str()); + + + rightLabel->setFont(theMeterRightLabelFont, false); + + rightLabel->setGeometryInformation(theMeterRightLabelFontInfo); + rightLabel->computeBoundingRect(); + ossimDrect boundsRight; + rightLabel->getBoundingRect(boundsRight); + + ossimIpt centerRight(irint(rect.ur().x+(boundsRight.width()/2)), + irint(ript.y)); + + + rightLabel->setColor(theRightMeterLabelColor.getR(), + theRightMeterLabelColor.getG(), + theRightMeterLabelColor.getB()); + + + rightLabel->setPositionCenter(centerRight); + rightLabel->computeBoundingRect(); + + rightLabel->getBoundingRect(labelRect); + + if(rect.intersects(labelRect)) + { + ossimIrect intersection = rect.clipToRect(labelRect); + centerRight.x += irint(intersection.ul().x - rect.ur().x); + } + + centerRight.x += (24+extraRightDelta); // this will need to be the tick height later; + rightLabel->setPositionCenter(centerRight); + rightLabel->computeBoundingRect(); + addFixedAnnotation(rightLabel); + if(theRightMeterTickFlag) + { + ossimAnnotationLineObject* lineLabel = new ossimAnnotationLineObject(ossimIpt(irint(ript.x+24), + irint(ript.y)), + ossimIpt(irint(ript.x), + irint(ript.y))); + + lineLabel->setColor(theRightMeterLabelColor.getR(), theRightMeterLabelColor.getG(), theRightMeterLabelColor.getB()); + addFixedAnnotation(lineLabel); + } + } + } + } + } +} + + +void ossimMapCompositionSource::addMeterGridReseaux() +{ + if(theInputConnection&&theInputProjection) + { + ossimDpt dpt[4]; + ossimDrect rect = getViewingRect(); + + theInputProjection->lineSampleToEastingNorthing(rect.ul(), + dpt[0]); + theInputProjection->lineSampleToEastingNorthing(rect.ur(), + dpt[1]); + theInputProjection->lineSampleToEastingNorthing(rect.lr(), + dpt[2]); + theInputProjection->lineSampleToEastingNorthing(rect.ll(), + dpt[3]); + + ossimDrect drect(dpt[0], + dpt[1], + dpt[2], + dpt[3], + OSSIM_RIGHT_HANDED); + + ossimDpt ulMeter(((int)((drect.ul().x-theMeterSpacing.x)/theMeterSpacing.x))*theMeterSpacing.x, + ((int)((drect.ul().y+theMeterSpacing.y)/theMeterSpacing.y))*theMeterSpacing.y); + + ossimDpt lrMeter(((int)((drect.lr().x+theMeterSpacing.x)/theMeterSpacing.x))*theMeterSpacing.x, + ((int)((drect.lr().y-theMeterSpacing.y)/theMeterSpacing.y))*theMeterSpacing.y); + + ossimDrect meterSpacing(ulMeter, + lrMeter, + OSSIM_RIGHT_HANDED); + + ossimDpt ipt; // top + + for(double vertical = meterSpacing.ul().y; vertical >= meterSpacing.lr().y; vertical-=theMeterSpacing.y) + { + for(double horizontal = meterSpacing.ul().x; horizontal <= meterSpacing.lr().x; horizontal+=theMeterSpacing.x) + { + ossimDpt dpt(horizontal, + vertical); + + theInputProjection->eastingNorthingToLineSample(dpt, + ipt); + + ossimIpt rounded(ipt); + if(rect.pointWithin(ossimDpt(rounded))) + { + ossimIpt horizontalStart(rounded.x-10, rounded.y); + ossimIpt horizontalEnd(rounded.x+10, rounded.y); + + ossimIpt verticalStart(rounded.x, rounded.y-10); + ossimIpt verticalEnd(rounded.x, rounded.y+10); + + ossimAnnotationLineObject* line1 = new ossimAnnotationLineObject(horizontalStart, horizontalEnd); + ossimAnnotationLineObject* line2 = new ossimAnnotationLineObject(verticalStart,verticalEnd); + + line1->setColor(theMeterGridColor.getR(), + theMeterGridColor.getG(), + theMeterGridColor.getB()); + + line2->setColor(theMeterGridColor.getR(), + theMeterGridColor.getG(), + theMeterGridColor.getB()); + addFixedAnnotation(line1); + addFixedAnnotation(line2); + } + } + } + } +} + +void ossimMapCompositionSource::addTitle() +{ + ossimAnnotationFontObject* title = new ossimAnnotationFontObject(ossimIpt(0,0), + theTitleString); + title->setGeometryInformation(theTitleFontInfo); + title->setFont(theTitleFont, false); + title->setColor(theTitleColor.getR(), + theTitleColor.getG(), + theTitleColor.getB()); + title->setPositionCenter(theTopBorder.midPoint()); + title->computeBoundingRect(); + + addFixedAnnotation(title); +} + +ossimIrect ossimMapCompositionSource::getViewingRect()const +{ + ossimIrect result; + result.makeNan(); + + if(theInputConnection) + { + result = theInputConnection->getBoundingRect(); + + if(!result.hasNans()) + { + ossimIpt mid = result.midPoint(); + ossim_int32 w = result.width(); + ossim_int32 h = result.width(); + + if(theViewWidthHeight.x >-1) + { + w = theViewWidthHeight.x; + } + if(theViewWidthHeight.y >-1) + { + h = theViewWidthHeight.y; + } + ossimIpt ul(mid.x - w/2, + mid.y - h/2); + + result = ossimIrect(ul.x, + ul.y, + ul.x + w-1, + ul.y + h -1); + } + } + + return result; +} + +void ossimMapCompositionSource::drawAnnotations( + ossimRefPtr<ossimImageData> tile) +{ + if (!theImage) + { + return; + } + + theImage->setCurrentImageData(theTile); + + if(theImage->getImageData().valid()) + { + vector<ossimAnnotationObject*>::iterator object = theFixedAnnotationList.begin(); + while(object != theFixedAnnotationList.end()) + { + if(*object) + { + (*object)->draw(*theImage); + } + ++object; + } + } + + ossimAnnotationSource::drawAnnotations(tile); +} + +void ossimMapCompositionSource::deleteFixedAnnotations() +{ + for(int i = 0; i < (int)theFixedAnnotationList.size();++i) + { + if(theFixedAnnotationList[i]) + { + delete theFixedAnnotationList[i]; + } + } + + theFixedAnnotationList.clear(); +} + + +void ossimMapCompositionSource::setProperty(ossimRefPtr<ossimProperty> property) +{ + if(!property.valid()) return; + + ossimRefPtr<ossimProperty> tempProp = 0; + ossimFontProperty* fontProp = 0; + ossimColorProperty* colorProp = 0; + ossimBooleanProperty* booleanProp = 0; + + if(property->getName() == "Geographic label properties") + { + ossimContainerProperty* containerProp = PTR_CAST(ossimContainerProperty, + property.get()); + if(containerProp) + { + // first set the font format + // + tempProp = containerProp->getProperty("Top font"); + fontProp = PTR_CAST(ossimFontProperty, tempProp.get()); + if(fontProp) + { + setGeographicTopLabelFont(fontProp->getFontInformation()); + } + tempProp = containerProp->getProperty("Bottom font"); + fontProp = PTR_CAST(ossimFontProperty, tempProp.get()); + if(fontProp) + { + setGeographicBottomLabelFont(fontProp->getFontInformation()); + } + tempProp = containerProp->getProperty("Left font"); + fontProp = PTR_CAST(ossimFontProperty, tempProp.get()); + if(fontProp) + { + setGeographicLeftLabelFont(fontProp->getFontInformation()); + } + tempProp = containerProp->getProperty("Right font"); + fontProp = PTR_CAST(ossimFontProperty, tempProp.get()); + if(fontProp) + { + setGeographicRightLabelFont(fontProp->getFontInformation()); + } + + // set color property + tempProp = containerProp->getProperty("Top color"); + colorProp = PTR_CAST(ossimColorProperty, tempProp.get()); + if(colorProp) + { + setTopGeographicLabelColor(colorProp->getColor()); + } + tempProp = containerProp->getProperty("Bottom color"); + colorProp = PTR_CAST(ossimColorProperty, tempProp.get()); + if(colorProp) + { + setBottomGeographicLabelColor(colorProp->getColor()); + } + tempProp = containerProp->getProperty("Left color"); + colorProp = PTR_CAST(ossimColorProperty, tempProp.get()); + if(colorProp) + { + setLeftGeographicLabelColor(colorProp->getColor()); + } + tempProp = containerProp->getProperty("Right color"); + colorProp = PTR_CAST(ossimColorProperty, tempProp.get()); + if(colorProp) + { + setRightGeographicLabelColor(colorProp->getColor()); + } + + // set enable flags + tempProp = containerProp->getProperty("Top enabled"); + booleanProp = PTR_CAST(ossimBooleanProperty, + tempProp.get()); + if(booleanProp) + { + setTopGeographicLabelFlag(booleanProp->getBoolean()); + } + + tempProp = containerProp->getProperty("Bottom enabled"); + booleanProp = PTR_CAST(ossimBooleanProperty, + tempProp.get()); + if(booleanProp) + { + setBottomGeographicLabelFlag(booleanProp->getBoolean()); + } + + tempProp = containerProp->getProperty("Left enabled"); + booleanProp = PTR_CAST(ossimBooleanProperty, + tempProp.get()); + if(booleanProp) + { + setLeftGeographicLabelFlag(booleanProp->getBoolean()); + } + + tempProp = containerProp->getProperty("Right enabled"); + booleanProp = PTR_CAST(ossimBooleanProperty, + tempProp.get()); + if(booleanProp) + { + setRightGeographicLabelFlag(booleanProp->getBoolean()); + } + + tempProp = containerProp->getProperty("Top tick enabled"); + booleanProp = PTR_CAST(ossimBooleanProperty, + tempProp.get()); + if(booleanProp) + { + setTopGeographicTickMarkFlag(booleanProp->getBoolean()); + } + tempProp = containerProp->getProperty("Bottom tick enabled"); + booleanProp = PTR_CAST(ossimBooleanProperty, + tempProp.get()); + if(booleanProp) + { + setBottomGeographicTickMarkFlag(booleanProp->getBoolean()); + } + tempProp = containerProp->getProperty("Left tick enabled"); + booleanProp = PTR_CAST(ossimBooleanProperty, + tempProp.get()); + if(booleanProp) + { + setLeftGeographicTickMarkFlag(booleanProp->getBoolean()); + } + tempProp = containerProp->getProperty("Right tick enabled"); + booleanProp = PTR_CAST(ossimBooleanProperty, + tempProp.get()); + if(booleanProp) + { + setRightGeographicTickMarkFlag(booleanProp->getBoolean()); + } + } + } + else if(property->getName() == "Geographic grid properties") + { + ossimContainerProperty* containerProp = PTR_CAST(ossimContainerProperty, + property.get()); + if(containerProp) + { + tempProp = containerProp->getProperty("Grid type"); + if(tempProp.valid()) + { + ossimString value = tempProp->valueToString(); + + if(value == "none") + { + setGeographicGridType(OSSIM_GRID_NONE); + } + else if(value == "line") + { + setGeographicGridType(OSSIM_GRID_LINE); + } + else if(value == "reseaux") + { + setGeographicGridType(OSSIM_GRID_RESEAUX); + } + } + tempProp = containerProp->getProperty("Horizontal spacing"); + if(tempProp.valid()) + { + setGeographicSpacingLon(tempProp->valueToString().toDouble()); + } + + tempProp = containerProp->getProperty("Vertical spacing"); + if(tempProp.valid()) + { + setGeographicSpacingLat(tempProp->valueToString().toDouble()); + } + + tempProp = containerProp->getProperty("Color"); + colorProp = PTR_CAST(ossimColorProperty, tempProp.get()); + if(tempProp.valid()) + { + setGeographicGridColor(colorProp->getColor()); + } + } + } + else if(property->getName() == "Meter label properties") + { + ossimContainerProperty* containerProp = PTR_CAST(ossimContainerProperty, + property.get()); + if(containerProp) + { + // first set the font format + // + tempProp = containerProp->getProperty("Top font"); + fontProp = PTR_CAST(ossimFontProperty, tempProp.get()); + if(fontProp) + { + setMeterTopLabelFont(fontProp->getFontInformation()); + } + tempProp = containerProp->getProperty("Bottom font"); + fontProp = PTR_CAST(ossimFontProperty, tempProp.get()); + if(fontProp) + { + setMeterBottomLabelFont(fontProp->getFontInformation()); + } + tempProp = containerProp->getProperty("Left font"); + fontProp = PTR_CAST(ossimFontProperty, tempProp.get()); + if(fontProp) + { + setMeterLeftLabelFont(fontProp->getFontInformation()); + } + tempProp = containerProp->getProperty("Right font"); + fontProp = PTR_CAST(ossimFontProperty, tempProp.get()); + if(fontProp) + { + setMeterRightLabelFont(fontProp->getFontInformation()); + } + + // set color property + tempProp = containerProp->getProperty("Top color"); + colorProp = PTR_CAST(ossimColorProperty, tempProp.get()); + if(colorProp) + { + setTopMeterLabelColor(colorProp->getColor()); + } + tempProp = containerProp->getProperty("Bottom color"); + colorProp = PTR_CAST(ossimColorProperty, tempProp.get()); + if(colorProp) + { + setBottomMeterLabelColor(colorProp->getColor()); + } + tempProp = containerProp->getProperty("Left color"); + colorProp = PTR_CAST(ossimColorProperty, tempProp.get()); + if(colorProp) + { + setLeftMeterLabelColor(colorProp->getColor()); + } + tempProp = containerProp->getProperty("Right color"); + colorProp = PTR_CAST(ossimColorProperty, tempProp.get()); + if(colorProp) + { + setRightMeterLabelColor(colorProp->getColor()); + } + + // set enable flags + tempProp = containerProp->getProperty("Top enabled"); + booleanProp = PTR_CAST(ossimBooleanProperty, + tempProp.get()); + if(booleanProp) + { + setTopMeterLabelFlag(booleanProp->getBoolean()); + } + + tempProp = containerProp->getProperty("Bottom enabled"); + booleanProp = PTR_CAST(ossimBooleanProperty, + tempProp.get()); + if(booleanProp) + { + setBottomMeterLabelFlag(booleanProp->getBoolean()); + } + + tempProp = containerProp->getProperty("Left enabled"); + booleanProp = PTR_CAST(ossimBooleanProperty, + tempProp.get()); + if(booleanProp) + { + setLeftMeterLabelFlag(booleanProp->getBoolean()); + } + + tempProp = containerProp->getProperty("Right enabled"); + booleanProp = PTR_CAST(ossimBooleanProperty, + tempProp.get()); + if(booleanProp) + { + setRightMeterLabelFlag(booleanProp->getBoolean()); + } + + tempProp = containerProp->getProperty("Top tick enabled"); + booleanProp = PTR_CAST(ossimBooleanProperty, + tempProp.get()); + if(booleanProp) + { + setTopMeterTickMarkFlag(booleanProp->getBoolean()); + } + tempProp = containerProp->getProperty("Bottom tick enabled"); + booleanProp = PTR_CAST(ossimBooleanProperty, + tempProp.get()); + if(booleanProp) + { + setBottomMeterTickMarkFlag(booleanProp->getBoolean()); + } + tempProp = containerProp->getProperty("Left tick enabled"); + booleanProp = PTR_CAST(ossimBooleanProperty, + tempProp.get()); + if(booleanProp) + { + setLeftMeterTickMarkFlag(booleanProp->getBoolean()); + } + tempProp = containerProp->getProperty("Right tick enabled"); + booleanProp = PTR_CAST(ossimBooleanProperty, + tempProp.get()); + if(booleanProp) + { + setRightMeterTickMarkFlag(booleanProp->getBoolean()); + } + } + } + else if(property->getName() == "Meter grid properties") + { + ossimContainerProperty* containerProp = PTR_CAST(ossimContainerProperty, + property.get()); + if(containerProp) + { + tempProp = containerProp->getProperty("Grid type"); + if(tempProp.valid()) + { + ossimString value = tempProp->valueToString(); + + if(value == "none") + { + setMeterGridType(OSSIM_GRID_NONE); + } + else if(value == "line") + { + setMeterGridType(OSSIM_GRID_LINE); + } + else if(value == "reseaux") + { + setMeterGridType(OSSIM_GRID_RESEAUX); + } + } + tempProp = containerProp->getProperty("Horizontal spacing"); + if(tempProp.valid()) + { + setMeterSpacingX(tempProp->valueToString().toDouble()); + } + + tempProp = containerProp->getProperty("Vertical spacing"); + if(tempProp.valid()) + { + setMeterSpacingY(tempProp->valueToString().toDouble()); + } + + tempProp = containerProp->getProperty("Color"); + colorProp = PTR_CAST(ossimColorProperty, tempProp.get()); + if(tempProp.valid()) + { + setMeterGridColor(colorProp->getColor()); + } + } + } + else if(property->getName() == "Title properties") + { + ossimContainerProperty* container = PTR_CAST(ossimContainerProperty, + property.get()); + if(container) + { + ossimProperty* titleProp = container->getProperty("Title").get(); + if(titleProp) + { + setTitle(titleProp->valueToString()); + } + ossimFontProperty* fontProp = PTR_CAST(ossimFontProperty, + container->getProperty("Font").get()); + ossimColorProperty* colorProp = PTR_CAST(ossimColorProperty, + container->getProperty("Color").get()); + + if(fontProp) + { + setTitleFont(fontProp->getFontInformation()); + } + if(colorProp) + { + setTitleColor(colorProp->getColor()); + } + } + } + else if(property->getName() == "Viewport properties") + { + ossimContainerProperty* container = PTR_CAST(ossimContainerProperty, + property.get()); + if(container) + { + int w = -1; + int h = -1; + tempProp = container->getProperty("Width"); + if(tempProp.valid()) + { + w = tempProp->valueToString().toInt32(); + } + tempProp = container->getProperty("Height"); + if(tempProp.valid()) + { + h = tempProp->valueToString().toInt32(); + } + setViewWidthHeight(ossimIpt(w, h)); + } + } + else if(property->getName() == "Border color") + { + colorProp = PTR_CAST(ossimColorProperty, + property.get()); + if(colorProp) + { + setBorderColor(colorProp->getColor()); + } + } + else if(property->getName() == "Border size") + { + ossimContainerProperty* container = PTR_CAST(ossimContainerProperty, + property.get()); + if(container) + { + tempProp = container->getProperty("Top"); + if(tempProp.valid()) + { + setTopBorderLength(tempProp->valueToString().toInt32()); + + } + tempProp = container->getProperty("Bottom"); + if(tempProp.valid()) + { + setBottomBorderLength(tempProp->valueToString().toInt32()); + + } + tempProp = container->getProperty("Left"); + if(tempProp.valid()) + { + setLeftBorderLength(tempProp->valueToString().toInt32()); + + } + tempProp = container->getProperty("Right"); + if(tempProp.valid()) + { + setRightBorderLength(tempProp->valueToString().toInt32()); + } + } + } + else + { + ossimAnnotationSource::setProperty(property); + } +} + +ossimRefPtr<ossimProperty> ossimMapCompositionSource::getProperty(const ossimString& name)const +{ + if(name == "Viewport properties") + { + ossimContainerProperty* container = new ossimContainerProperty(name); + + container->addChild(new ossimNumericProperty("Width", + ossimString::toString(theViewWidthHeight.x), + -1,1.0/DBL_EPSILON)); + container->addChild(new ossimNumericProperty("Height", + ossimString::toString(theViewWidthHeight.y), + -1,1.0/DBL_EPSILON)); + container->setCacheRefreshBit(); + return container; + } + else if(name == "Geographic label properties") + { + + ossimContainerProperty* container = new ossimContainerProperty(name); + + container->addChild(new ossimFontProperty("Top font", + theGeographicTopLabelFontInfo)); + container->addChild(new ossimColorProperty("Top color", + theTopGeographicLabelColor)); + container->addChild(new ossimBooleanProperty("Top enabled", + theTopGeographicLabelFlag)); + container->addChild(new ossimBooleanProperty("Top tick enabled", + theTopGeographicTickFlag)); + + container->addChild(new ossimFontProperty("Bottom font", + theGeographicBottomLabelFontInfo)); + container->addChild(new ossimColorProperty("Bottom color", + theBottomGeographicLabelColor)); + container->addChild(new ossimBooleanProperty("Bottom enabled", + theBottomGeographicLabelFlag)); + container->addChild(new ossimBooleanProperty("Bottom tick enabled", + theBottomGeographicTickFlag)); + + container->addChild(new ossimFontProperty("Left font", + theGeographicLeftLabelFontInfo)); + container->addChild(new ossimColorProperty("Left color", + theLeftGeographicLabelColor)); + container->addChild(new ossimBooleanProperty("Left enabled", + theLeftGeographicLabelFlag)); + container->addChild(new ossimBooleanProperty("Left tick enabled", + theLeftGeographicTickFlag)); + + container->addChild(new ossimFontProperty("Right font", + theGeographicRightLabelFontInfo)); + container->addChild(new ossimColorProperty("Right color", + theRightGeographicLabelColor)); + container->addChild(new ossimBooleanProperty("Right enabled", + theRightGeographicLabelFlag)); + container->addChild(new ossimBooleanProperty("Right tick enabled", + theRightGeographicTickFlag)); + container->setCacheRefreshBit(); + return container; + } + else if(name == "Geographic grid properties") + { + ossimContainerProperty* container = new ossimContainerProperty(name); + std::vector<ossimString> gridTypeConstraints; + ossimString value = GRID_TYPE_ENUM_NAMES[(int)theGeographicGridType]; + + gridTypeConstraints.push_back("none"); + gridTypeConstraints.push_back("line"); + gridTypeConstraints.push_back("reseaux"); + + container->addChild(new ossimStringProperty("Grid type", + value, + false, + gridTypeConstraints)); + container->addChild(new ossimColorProperty("Color", + theGeographicGridColor)); + + container->addChild(new ossimNumericProperty("Horizontal spacing", + ossimString::toString(theGeographicSpacing.x), + 0.0, 180.0)); + + container->addChild(new ossimNumericProperty("Vertical spacing", + ossimString::toString(theGeographicSpacing.y), + 0.0, 180.0)); + + container->setCacheRefreshBit(); + return container; + } + else if(name == "Meter label properties") + { + ossimContainerProperty* container = new ossimContainerProperty(name); + + container->addChild(new ossimFontProperty("Top font", + theMeterTopLabelFontInfo)); + container->addChild(new ossimColorProperty("Top color", + theTopMeterLabelColor)); + container->addChild(new ossimBooleanProperty("Top enabled", + theTopMeterLabelFlag)); + container->addChild(new ossimBooleanProperty("Top tick enabled", + theTopMeterTickFlag)); + + container->addChild(new ossimFontProperty("Bottom font", + theMeterBottomLabelFontInfo)); + container->addChild(new ossimColorProperty("Bottom color", + theBottomMeterLabelColor)); + container->addChild(new ossimBooleanProperty("Bottom enabled", + theBottomMeterLabelFlag)); + container->addChild(new ossimBooleanProperty("Bottom tick enabled", + theBottomMeterTickFlag)); + + container->addChild(new ossimFontProperty("Left font", + theMeterLeftLabelFontInfo)); + container->addChild(new ossimColorProperty("Left color", + theLeftMeterLabelColor)); + container->addChild(new ossimBooleanProperty("Left enabled", + theLeftMeterLabelFlag)); + container->addChild(new ossimBooleanProperty("Left tick enabled", + theLeftMeterTickFlag)); + + container->addChild(new ossimFontProperty("Right font", + theMeterRightLabelFontInfo)); + container->addChild(new ossimColorProperty("Right color", + theRightMeterLabelColor)); + container->addChild(new ossimBooleanProperty("Right enabled", + theRightMeterLabelFlag)); + container->addChild(new ossimBooleanProperty("Right tick enabled", + theRightMeterTickFlag)); + + container->setCacheRefreshBit(); + return container; + } + else if(name == "Meter grid properties") + { + ossimContainerProperty* container = new ossimContainerProperty(name); + std::vector<ossimString> gridTypeConstraints; + ossimString value = GRID_TYPE_ENUM_NAMES[(int)theMeterGridType]; + + gridTypeConstraints.push_back("none"); + gridTypeConstraints.push_back("line"); + gridTypeConstraints.push_back("reseaux"); + + container->addChild(new ossimStringProperty("Grid type", + value, + false, + gridTypeConstraints)); + container->addChild(new ossimColorProperty("Color", + theMeterGridColor)); + + container->addChild(new ossimNumericProperty("Horizontal spacing", + ossimString::toString(theMeterSpacing.x), + 0.0, 1.0/DBL_EPSILON)); + + container->addChild(new ossimNumericProperty("Vertical spacing", + ossimString::toString(theMeterSpacing.y), + 0.0, 1.0/DBL_EPSILON)); + container->setCacheRefreshBit(); + return container; + } + else if(name == "Title properties") + { + ossimContainerProperty* container = new ossimContainerProperty(name); + container->addChild(new ossimTextProperty("Title", + theTitleString)); + container->addChild(new ossimFontProperty("Font", + theTitleFontInfo)); + container->addChild(new ossimColorProperty("Color", + theTitleColor)); + + container->setCacheRefreshBit(); + return container; + } + else if(name == "Border size") + { + ossimContainerProperty* container = new ossimContainerProperty(name); + + container->addChild(new ossimNumericProperty("Top", + ossimString::toString(theTopBorderLength), + 0,10000)); + container->addChild(new ossimNumericProperty("Bottom", + ossimString::toString(theBottomBorderLength), + 0,10000)); + container->addChild(new ossimNumericProperty("Left", + ossimString::toString(theLeftBorderLength), + 0,10000)); + container->addChild(new ossimNumericProperty("Right", + ossimString::toString(theRightBorderLength), + 0,10000)); + container->setCacheRefreshBit(); + return container; + } + else if(name == "Border color") + { + ossimColorProperty* colorProp = new ossimColorProperty(name, + theBorderColor); + colorProp->setCacheRefreshBit(); + + return colorProp; + } + else if(name == "Viewport properties") + { + + } + return ossimAnnotationSource::getProperty(name); +} + +void ossimMapCompositionSource::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + ossimAnnotationSource::getPropertyNames(propertyNames); + + + propertyNames.push_back("Title properties"); + propertyNames.push_back("Border size"); + propertyNames.push_back("Border color"); + propertyNames.push_back("Viewport properties"); + propertyNames.push_back("Geographic label properties"); + propertyNames.push_back("Geographic grid properties"); + propertyNames.push_back("Meter label properties"); + propertyNames.push_back("Meter grid properties"); +} + +bool ossimMapCompositionSource::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + VIEW_WIDTH_KW, + theViewWidthHeight.x, + true); + + kwl.add(prefix, + VIEW_HEIGHT_KW, + theViewWidthHeight.x, + true); + + kwl.add(prefix, + METER_GRID_SPACING_X_KW, + theMeterSpacing.x, + true); + + kwl.add(prefix, + METER_GRID_SPACING_Y_KW, + theMeterSpacing.y, + true); + + kwl.add(prefix, + GEO_GRID_SPACING_LON_KW, + theGeographicSpacing.lon, + true); + + kwl.add(prefix, + GEO_GRID_SPACING_LAT_KW, + theGeographicSpacing.lat, + true); + + ossimString meterGridType = "line"; + if(theMeterGridType == OSSIM_GRID_NONE) + { + meterGridType = "none"; + } + else if(theMeterGridType == OSSIM_GRID_RESEAUX) + { + meterGridType = "reseaux"; + } + + kwl.add(prefix, + METER_GRID_TYPE_KW, + meterGridType.c_str(), + true); + + ossimString geoGridType = "line"; + if(theGeographicGridType == OSSIM_GRID_NONE) + { + geoGridType = "none"; + } + else if(theGeographicGridType == OSSIM_GRID_RESEAUX) + { + geoGridType = "reseaux"; + } + + kwl.add(prefix, + GEO_GRID_TYPE_KW, + geoGridType.c_str(), + true); + + kwl.add(prefix, + TOP_BORDER_LENGTH_KW, + theTopBorderLength, + true); + + kwl.add(prefix, + BOTTOM_BORDER_LENGTH_KW, + theBottomBorderLength, + true); + + kwl.add(prefix, + LEFT_BORDER_LENGTH_KW, + theLeftBorderLength, + true); + + kwl.add(prefix, + RIGHT_BORDER_LENGTH_KW, + theRightBorderLength, + true); + + kwl.add(prefix, + BORDER_COLOR_KW, + (ossimString::toString(theBorderColor.getR()) +" "+ + ossimString::toString(theBorderColor.getG()) +" "+ + ossimString::toString(theBorderColor.getB())).c_str(), + true); + + kwl.add(prefix, + GEO_GRID_COLOR_KW, + (ossimString::toString(theGeographicGridColor.getR()) +" "+ + ossimString::toString(theGeographicGridColor.getG()) +" "+ + ossimString::toString(theGeographicGridColor.getB())).c_str(), + true); + + kwl.add(prefix, + METER_GRID_COLOR_KW, + (ossimString::toString(theMeterGridColor.getR()) +" "+ + ossimString::toString(theMeterGridColor.getG()) +" "+ + ossimString::toString(theMeterGridColor.getB())).c_str(), + true); + + kwl.add(prefix, + TITLE_STRING_KW, + theTitleString.c_str(), + true); + + kwl.add(prefix, + TITLE_COLOR_KW, + (ossimString::toString(theTitleColor.getR()) +" "+ + ossimString::toString(theTitleColor.getG()) +" "+ + ossimString::toString(theTitleColor.getB())).c_str(), + true); + + kwl.add(prefix, + TOP_GEO_LABEL_COLOR_KW, + (ossimString::toString(theTopGeographicLabelColor.getR()) +" "+ + ossimString::toString(theTopGeographicLabelColor.getG()) +" "+ + ossimString::toString(theTopGeographicLabelColor.getB())).c_str(), + true); + + kwl.add(prefix, + BOTTOM_GEO_LABEL_COLOR_KW, + (ossimString::toString(theBottomGeographicLabelColor.getR()) +" "+ + ossimString::toString(theBottomGeographicLabelColor.getG()) +" "+ + ossimString::toString(theBottomGeographicLabelColor.getB())).c_str(), + true); + kwl.add(prefix, + LEFT_GEO_LABEL_COLOR_KW, + (ossimString::toString(theLeftGeographicLabelColor.getR()) +" "+ + ossimString::toString(theLeftGeographicLabelColor.getG()) +" "+ + ossimString::toString(theLeftGeographicLabelColor.getB())).c_str(), + true); + kwl.add(prefix, + RIGHT_GEO_LABEL_COLOR_KW, + (ossimString::toString(theRightGeographicLabelColor.getR()) +" "+ + ossimString::toString(theRightGeographicLabelColor.getG()) +" "+ + ossimString::toString(theRightGeographicLabelColor.getB())).c_str(), + true); + + kwl.add(prefix, + TOP_GEO_LABEL_FORMAT_KW, + theTopGeographicFormat, + true); + + kwl.add(prefix, + BOTTOM_GEO_LABEL_FORMAT_KW, + theBottomGeographicFormat, + true); + kwl.add(prefix, + LEFT_GEO_LABEL_FORMAT_KW, + theLeftGeographicFormat, + true); + kwl.add(prefix, + RIGHT_GEO_LABEL_FORMAT_KW, + theRightGeographicFormat, + true); + + kwl.add(prefix, + TOP_GEO_LABEL_FLAG_KW, + (int)theTopGeographicLabelFlag, + true); + + kwl.add(prefix, + BOTTOM_GEO_LABEL_FLAG_KW, + (int)theBottomGeographicLabelFlag, + true); + + kwl.add(prefix, + LEFT_GEO_LABEL_FLAG_KW, + (int)theLeftGeographicLabelFlag, + true); + + kwl.add(prefix, + RIGHT_GEO_LABEL_FLAG_KW, + (int)theRightGeographicLabelFlag, + true); + + kwl.add(prefix, + TOP_METER_LABEL_COLOR_KW, + (ossimString::toString(theTopMeterLabelColor.getR()) +" "+ + ossimString::toString(theTopMeterLabelColor.getG()) +" "+ + ossimString::toString(theTopMeterLabelColor.getB())).c_str(), + true); + + kwl.add(prefix, + BOTTOM_METER_LABEL_COLOR_KW, + (ossimString::toString(theBottomMeterLabelColor.getR()) +" "+ + ossimString::toString(theBottomMeterLabelColor.getG()) +" "+ + ossimString::toString(theBottomMeterLabelColor.getB())).c_str(), + true); + kwl.add(prefix, + LEFT_METER_LABEL_COLOR_KW, + (ossimString::toString(theLeftMeterLabelColor.getR()) +" "+ + ossimString::toString(theLeftMeterLabelColor.getG()) +" "+ + ossimString::toString(theLeftMeterLabelColor.getB())).c_str(), + true); + kwl.add(prefix, + RIGHT_METER_LABEL_COLOR_KW, + (ossimString::toString(theRightMeterLabelColor.getR()) +" "+ + ossimString::toString(theRightMeterLabelColor.getG()) +" "+ + ossimString::toString(theRightMeterLabelColor.getB())).c_str(), + true); + + + kwl.add(prefix, + TOP_METER_LABEL_FLAG_KW, + (int)theTopMeterLabelFlag, + true); + + kwl.add(prefix, + BOTTOM_METER_LABEL_FLAG_KW, + (int)theBottomMeterLabelFlag, + true); + + kwl.add(prefix, + LEFT_METER_LABEL_FLAG_KW, + (int)theLeftMeterLabelFlag, + true); + + kwl.add(prefix, + RIGHT_METER_LABEL_FLAG_KW, + (int)theRightMeterLabelFlag, + true); + + theGeographicTopLabelFontInfo.saveState(kwl, (ossimString(prefix) + ossimString(TOP_GEO_LABEL_FONT_KW) + ".").c_str()); + theGeographicBottomLabelFontInfo.saveState(kwl, (ossimString(prefix) + ossimString(BOTTOM_GEO_LABEL_FONT_KW) + ".").c_str()); + theGeographicLeftLabelFontInfo.saveState(kwl, (ossimString(prefix) + ossimString(LEFT_GEO_LABEL_FONT_KW) + ".").c_str()); + theGeographicRightLabelFontInfo.saveState(kwl, (ossimString(prefix) + ossimString(RIGHT_GEO_LABEL_FONT_KW) + ".").c_str()); + + theMeterTopLabelFontInfo.saveState(kwl, (ossimString(prefix) + ossimString(TOP_METER_LABEL_FONT_KW) + ".").c_str()); + theMeterBottomLabelFontInfo.saveState(kwl, (ossimString(prefix) + ossimString(BOTTOM_METER_LABEL_FONT_KW) + ".").c_str()); + theMeterLeftLabelFontInfo.saveState(kwl, (ossimString(prefix) + ossimString(LEFT_METER_LABEL_FONT_KW) + ".").c_str()); + theMeterRightLabelFontInfo.saveState(kwl, (ossimString(prefix) + ossimString(RIGHT_METER_LABEL_FONT_KW) + ".").c_str()); + + theTitleFontInfo.saveState(kwl, (ossimString(prefix) + ossimString(TITLE_FONT_KW) + ".").c_str()); + + + return ossimImageSource::saveState(kwl, prefix); + +} + +bool ossimMapCompositionSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* viewWidth = kwl.find(prefix, VIEW_WIDTH_KW); + const char* viewHeight = kwl.find(prefix, VIEW_HEIGHT_KW); + const char* meterGridSpacingX = kwl.find(prefix, METER_GRID_SPACING_X_KW); + const char* meterGridSpacingY = kwl.find(prefix, METER_GRID_SPACING_Y_KW); + const char* geoGridSpacingLon = kwl.find(prefix, GEO_GRID_SPACING_LON_KW); + const char* geoGridSpacingLat = kwl.find(prefix, GEO_GRID_SPACING_LAT_KW); + const char* meterGridType = kwl.find(prefix, METER_GRID_TYPE_KW); + const char* geoGridType = kwl.find(prefix, GEO_GRID_TYPE_KW); + const char* topBorderLength = kwl.find(prefix, TOP_BORDER_LENGTH_KW); + const char* bottomBorderLength = kwl.find(prefix, BOTTOM_BORDER_LENGTH_KW); + const char* leftBorderLength = kwl.find(prefix, LEFT_BORDER_LENGTH_KW); + const char* rightBorderLength = kwl.find(prefix, RIGHT_BORDER_LENGTH_KW); + + const char* borderColor = kwl.find(prefix, BORDER_COLOR_KW); + const char* geoGridColor = kwl.find(prefix, GEO_GRID_COLOR_KW); + const char* meterGridColor = kwl.find(prefix, METER_GRID_COLOR_KW); + const char* titleString = kwl.find(prefix, TITLE_STRING_KW); + const char* titleColor = kwl.find(prefix, TITLE_COLOR_KW); + + const char* topGeoLabelColor = kwl.find(prefix, TOP_GEO_LABEL_COLOR_KW); + const char* bottomGeoLabelColor = kwl.find(prefix, BOTTOM_GEO_LABEL_COLOR_KW); + const char* leftGeoLabelColor = kwl.find(prefix, LEFT_GEO_LABEL_COLOR_KW); + const char* rightGeoLabelColor = kwl.find(prefix, RIGHT_GEO_LABEL_COLOR_KW); + + const char* topMeterLabelColor = kwl.find(prefix, TOP_METER_LABEL_COLOR_KW); + const char* bottomMeterLabelColor = kwl.find(prefix, BOTTOM_METER_LABEL_COLOR_KW); + const char* leftMeterLabelColor = kwl.find(prefix, LEFT_METER_LABEL_COLOR_KW); + const char* rightMeterLabelColor = kwl.find(prefix, RIGHT_METER_LABEL_COLOR_KW); + + const char* topGeoLabelFormat = kwl.find(prefix, TOP_GEO_LABEL_FORMAT_KW); + const char* bottomGeoLabelFormat = kwl.find(prefix, BOTTOM_GEO_LABEL_FORMAT_KW); + const char* leftGeoLabelFormat = kwl.find(prefix, LEFT_GEO_LABEL_FORMAT_KW); + const char* rightGeoLabelFormat = kwl.find(prefix, RIGHT_GEO_LABEL_FORMAT_KW); + + const char* topGeoLabelFlag = kwl.find(prefix, TOP_GEO_LABEL_FLAG_KW); + const char* bottomGeoLabelFlag = kwl.find(prefix, BOTTOM_GEO_LABEL_FLAG_KW); + const char* leftGeoLabelFlag = kwl.find(prefix, LEFT_GEO_LABEL_FLAG_KW); + const char* rightGeoLabelFlag = kwl.find(prefix, RIGHT_GEO_LABEL_FLAG_KW); + + const char* topMeterLabelFlag = kwl.find(prefix, TOP_METER_LABEL_FLAG_KW); + const char* bottomMeterLabelFlag = kwl.find(prefix, BOTTOM_METER_LABEL_FLAG_KW); + const char* leftMeterLabelFlag = kwl.find(prefix, LEFT_METER_LABEL_FLAG_KW); + const char* rightMeterLabelFlag = kwl.find(prefix, RIGHT_METER_LABEL_FLAG_KW); + + deleteFixedAnnotations(); + theViewWidthHeight.makeNan(); + + if(viewWidth) + { + theViewWidthHeight.x = ossimString(viewWidth).toLong(); + } + if(viewHeight) + { + theViewWidthHeight.y = ossimString(viewHeight).toLong(); + } + + if(meterGridSpacingX) + { + theMeterSpacing.x = ossimString(meterGridSpacingX).toDouble(); + } + + if(meterGridSpacingY) + { + theMeterSpacing.y = ossimString(meterGridSpacingY).toDouble(); + } + if(geoGridSpacingLon) + { + theGeographicSpacing.lon = ossimString(geoGridSpacingLon).toDouble(); + } + if(geoGridSpacingLat) + { + theGeographicSpacing.lat = ossimString(geoGridSpacingLat).toDouble(); + } + if(meterGridType) + { + ossimString type = ossimString(meterGridType).trim().downcase(); + if(type == "reseaux") + { + theMeterGridType = OSSIM_GRID_RESEAUX; + } + else if(type == "line") + { + theMeterGridType = OSSIM_GRID_LINE; + } + else + { + theMeterGridType = OSSIM_GRID_NONE; + } + } + + if(geoGridType) + { + ossimString type = ossimString(geoGridType).trim().downcase(); + if(type == "reseaux") + { + theGeographicGridType = OSSIM_GRID_RESEAUX; + } + else if(type == "line") + { + theGeographicGridType = OSSIM_GRID_LINE; + } + else + { + theGeographicGridType = OSSIM_GRID_NONE; + } + } + + if(topBorderLength) + { + theTopBorderLength = ossimString(topBorderLength).toULong(); + } + + if(bottomBorderLength) + { + theBottomBorderLength = ossimString(bottomBorderLength).toULong(); + } + if(leftBorderLength) + { + theLeftBorderLength = ossimString(leftBorderLength).toULong(); + } + if(rightBorderLength) + { + theRightBorderLength = ossimString(rightBorderLength).toULong(); + } + + if(borderColor) + { + istringstream in(borderColor); + + int r; + int g; + int b; + in >> r >> g >> b; + + theBorderColor = ossimRgbVector((ossim_uint8)r, (ossim_uint8)g, (ossim_uint8)b); + } + + if(geoGridColor) + { + istringstream in(geoGridColor); + + int r; + int g; + int b; + in >> r >> g >> b; + + theGeographicGridColor = ossimRgbVector((ossim_uint8)r, (ossim_uint8)g, (ossim_uint8)b); + } + + if(meterGridColor) + { + istringstream in(meterGridColor); + + int r; + int g; + int b; + in >> r >> g >> b; + + theMeterGridColor = ossimRgbVector((ossim_uint8)r, (ossim_uint8)g, (ossim_uint8)b); + } + + if(titleString) + { + theTitleString = titleString; + } + + if(titleColor) + { + istringstream in(titleColor); + + int r; + int g; + int b; + in >> r >> g >> b; + + theTitleColor = ossimRgbVector((ossim_uint8)r, (ossim_uint8)g, (ossim_uint8)b); + } + + if(topGeoLabelColor) + { + istringstream in(topGeoLabelColor); + + int r; + int g; + int b; + in >> r >> g >> b; + + theTopGeographicLabelColor = ossimRgbVector((ossim_uint8)r, (ossim_uint8)g, (ossim_uint8)b); + } + + if(bottomGeoLabelColor) + { + istringstream in(bottomGeoLabelColor); + + int r; + int g; + int b; + in >> r >> g >> b; + + theBottomGeographicLabelColor = ossimRgbVector((ossim_uint8)r, (ossim_uint8)g, (ossim_uint8)b); + } + + if(leftGeoLabelColor) + { + istringstream in(leftGeoLabelColor); + + int r; + int g; + int b; + in >> r >> g >> b; + + theLeftGeographicLabelColor = ossimRgbVector((ossim_uint8)r, (ossim_uint8)g, (ossim_uint8)b); + } + + if(rightGeoLabelColor) + { + istringstream in(rightGeoLabelColor); + + int r; + int g; + int b; + in >> r >> g >> b; + + theRightGeographicLabelColor = ossimRgbVector((ossim_uint8)r, (ossim_uint8)g, (ossim_uint8)b); + } + + +///// + if(topMeterLabelColor) + { + istringstream in(topMeterLabelColor); + + int r; + int g; + int b; + in >> r >> g >> b; + + theTopMeterLabelColor = ossimRgbVector((ossim_uint8)r, (ossim_uint8)g, (ossim_uint8)b); + } + + if(bottomMeterLabelColor) + { + istringstream in(bottomMeterLabelColor); + + int r; + int g; + int b; + in >> r >> g >> b; + + theBottomMeterLabelColor = ossimRgbVector((ossim_uint8)r, (ossim_uint8)g, (ossim_uint8)b); + } + + if(leftMeterLabelColor) + { + istringstream in(leftMeterLabelColor); + + int r; + int g; + int b; + in >> r >> g >> b; + + theLeftMeterLabelColor = ossimRgbVector((ossim_uint8)r, (ossim_uint8)g, (ossim_uint8)b); + } + + if(rightMeterLabelColor) + { + istringstream in(rightMeterLabelColor); + + int r; + int g; + int b; + in >> r >> g >> b; + + theRightMeterLabelColor = ossimRgbVector((ossim_uint8)r, (ossim_uint8)g, (ossim_uint8)b); + } + + if(topGeoLabelFormat) + { + theTopGeographicFormat = topGeoLabelFormat; + } + + if(bottomGeoLabelFormat) + { + theBottomGeographicFormat = bottomGeoLabelFormat; + } + + if(leftGeoLabelFormat) + { + theLeftGeographicFormat = leftGeoLabelFormat; + } + + if(rightGeoLabelFormat) + { + theRightGeographicFormat = rightGeoLabelFormat; + } + + if(topGeoLabelFlag) + { + theTopGeographicLabelFlag = ossimString(topGeoLabelFlag).toBool(); + } + if(bottomGeoLabelFlag) + { + theBottomGeographicLabelFlag = ossimString(bottomGeoLabelFlag).toBool(); + } + if(leftGeoLabelFlag) + { + theLeftGeographicLabelFlag = ossimString(leftGeoLabelFlag).toBool(); + } + if(rightGeoLabelFlag) + { + theRightGeographicLabelFlag = ossimString(rightGeoLabelFlag).toBool(); + } + + if(topMeterLabelFlag) + { + theTopMeterLabelFlag = ossimString(topMeterLabelFlag).toBool(); + } + if(bottomMeterLabelFlag) + { + theBottomMeterLabelFlag = ossimString(bottomMeterLabelFlag).toBool(); + } + if(leftMeterLabelFlag) + { + theLeftMeterLabelFlag = ossimString(leftMeterLabelFlag).toBool(); + } + if(rightMeterLabelFlag) + { + theRightMeterLabelFlag = ossimString(rightMeterLabelFlag).toBool(); + } + + theGeographicTopLabelFontInfo.loadState(kwl, (ossimString(prefix) + ossimString(TOP_GEO_LABEL_FONT_KW) + ".").c_str()); + theGeographicBottomLabelFontInfo.loadState(kwl, (ossimString(prefix) + ossimString(BOTTOM_GEO_LABEL_FONT_KW) + ".").c_str()); + theGeographicLeftLabelFontInfo.loadState(kwl, (ossimString(prefix) + ossimString(LEFT_GEO_LABEL_FONT_KW) + ".").c_str()); + theGeographicRightLabelFontInfo.loadState(kwl, (ossimString(prefix) + ossimString(RIGHT_GEO_LABEL_FONT_KW) + ".").c_str()); + + theMeterTopLabelFontInfo.loadState(kwl, (ossimString(prefix) + ossimString(TOP_METER_LABEL_FONT_KW) + ".").c_str()); + theMeterBottomLabelFontInfo.loadState(kwl, (ossimString(prefix) + ossimString(BOTTOM_METER_LABEL_FONT_KW) + ".").c_str()); + theMeterLeftLabelFontInfo.loadState(kwl, (ossimString(prefix) + ossimString(LEFT_METER_LABEL_FONT_KW) + ".").c_str()); + theMeterRightLabelFontInfo.loadState(kwl, (ossimString(prefix) + ossimString(RIGHT_METER_LABEL_FONT_KW) + ".").c_str()); + + theTitleFontInfo.loadState(kwl, (ossimString(prefix) + ossimString(TITLE_FONT_KW) + ".").c_str()); + if(theTitleFont) + { + delete theTitleFont; + theTitleFont = NULL; + } + if(theGeographicTopLabelFont) + { + delete theGeographicTopLabelFont; + theGeographicTopLabelFont = NULL; + } + if(theGeographicBottomLabelFont) + { + delete theGeographicBottomLabelFont; + theGeographicBottomLabelFont = NULL; + } + if(theGeographicLeftLabelFont) + { + delete theGeographicLeftLabelFont; + theGeographicLeftLabelFont = NULL; + } + if(theGeographicRightLabelFont) + { + delete theGeographicRightLabelFont; + theGeographicRightLabelFont = NULL; + } + + if(theMeterTopLabelFont) + { + delete theMeterTopLabelFont; + theMeterTopLabelFont = NULL; + } + if(theMeterBottomLabelFont) + { + delete theMeterBottomLabelFont; + theMeterBottomLabelFont = NULL; + } + if(theMeterLeftLabelFont) + { + delete theMeterLeftLabelFont; + theMeterLeftLabelFont = NULL; + } + if(theMeterRightLabelFont) + { + delete theMeterRightLabelFont; + theMeterRightLabelFont = NULL; + } + + theTitleFont = ossimFontFactoryRegistry::instance()->createFont(theTitleFontInfo); + theGeographicTopLabelFont = ossimFontFactoryRegistry::instance()->createFont(theGeographicTopLabelFontInfo); + theGeographicBottomLabelFont = ossimFontFactoryRegistry::instance()->createFont(theGeographicBottomLabelFontInfo); + theGeographicLeftLabelFont = ossimFontFactoryRegistry::instance()->createFont(theGeographicLeftLabelFontInfo); + theGeographicRightLabelFont = ossimFontFactoryRegistry::instance()->createFont(theGeographicRightLabelFontInfo); + + theMeterTopLabelFont = ossimFontFactoryRegistry::instance()->createFont(theMeterTopLabelFontInfo); + theMeterBottomLabelFont = ossimFontFactoryRegistry::instance()->createFont(theMeterBottomLabelFontInfo); + theMeterLeftLabelFont = ossimFontFactoryRegistry::instance()->createFont(theMeterLeftLabelFontInfo); + theMeterRightLabelFont = ossimFontFactoryRegistry::instance()->createFont(theMeterRightLabelFontInfo); + + vector<ossimFontInformation> info; + + + if(!theTitleFont) + { + theTitleFont = (ossimFont*)ossimFontFactoryRegistry::instance()->getDefaultFont()->dup(); + theTitleFont->getFontInformation(info); + theTitleFontInfo = info[0]; + } + if(!theGeographicTopLabelFont) + { + info.clear(); + theGeographicTopLabelFont = (ossimFont*)ossimFontFactoryRegistry::instance()->getDefaultFont()->dup(); + theGeographicTopLabelFont->getFontInformation(info); + theGeographicTopLabelFontInfo = info[0]; + } + if(!theGeographicBottomLabelFont) + { + info.clear(); + theGeographicBottomLabelFont = (ossimFont*)ossimFontFactoryRegistry::instance()->getDefaultFont()->dup(); + theGeographicBottomLabelFont->getFontInformation(info); + theGeographicBottomLabelFontInfo = info[0]; + } + if(!theGeographicLeftLabelFont) + { + info.clear(); + theGeographicLeftLabelFont = (ossimFont*)ossimFontFactoryRegistry::instance()->getDefaultFont()->dup(); + theGeographicLeftLabelFont->getFontInformation(info); + theGeographicLeftLabelFontInfo = info[0]; + } + if(!theGeographicRightLabelFont) + { + info.clear(); + theGeographicRightLabelFont = (ossimFont*)ossimFontFactoryRegistry::instance()->getDefaultFont()->dup(); + theGeographicRightLabelFont->getFontInformation(info); + theGeographicRightLabelFontInfo = info[0]; + } + + if(!theMeterTopLabelFont) + { + info.clear(); + theMeterTopLabelFont = (ossimFont*)ossimFontFactoryRegistry::instance()->getDefaultFont()->dup(); + theMeterTopLabelFont->getFontInformation(info); + theMeterTopLabelFontInfo = info[0]; + } + if(!theMeterBottomLabelFont) + { + info.clear(); + theMeterBottomLabelFont = (ossimFont*)ossimFontFactoryRegistry::instance()->getDefaultFont()->dup(); + theMeterBottomLabelFont->getFontInformation(info); + theMeterBottomLabelFontInfo = info[0]; + } + if(!theMeterLeftLabelFont) + { + info.clear(); + theMeterLeftLabelFont = (ossimFont*)ossimFontFactoryRegistry::instance()->getDefaultFont()->dup(); + theMeterLeftLabelFont->getFontInformation(info); + theMeterLeftLabelFontInfo = info[0]; + } + if(!theMeterRightLabelFont) + { + info.clear(); + theMeterRightLabelFont = (ossimFont*)ossimFontFactoryRegistry::instance()->getDefaultFont()->dup(); + theMeterRightLabelFont->getFontInformation(info); + theMeterRightLabelFontInfo = info[0]; + } + + bool result = ossimAnnotationSource::loadState(kwl, + prefix); + layoutAnnotations(); + + return result; +} + +ossimScalarType ossimMapCompositionSource::getOutputScalarType() const +{ + return OSSIM_UCHAR; +} + +ossim_uint32 ossimMapCompositionSource::getNumberOfOutputBands() const +{ + return 3; +} + +ossimIpt ossimMapCompositionSource::getViewWidthHeight()const +{ + return theViewWidthHeight; +} + +void ossimMapCompositionSource::getViewWidthHeight(ossimIpt& widthHeight)const +{ + widthHeight = theViewWidthHeight; +} + +void ossimMapCompositionSource::setViewWidthHeight(const ossimIpt& widthHeight) +{ + theViewWidthHeight = widthHeight; +} + +ossim_int32 ossimMapCompositionSource::getTopBorderLength()const +{ + return theTopBorderLength; +} + +ossim_int32 ossimMapCompositionSource::getBottomBorderLength()const +{ + return theBottomBorderLength; +} + +ossim_int32 ossimMapCompositionSource::getLeftBorderLength()const +{ + return theLeftBorderLength; +} + +ossim_int32 ossimMapCompositionSource::getRightBorderLength()const +{ + return theRightBorderLength; +} + +void ossimMapCompositionSource::setTopBorderLength(ossim_int32 length) +{ + theTopBorderLength = length; +} + +void ossimMapCompositionSource::setBottomBorderLength(ossim_int32 length) +{ + theBottomBorderLength = length; +} + +void ossimMapCompositionSource::setLeftBorderLength(ossim_int32 length) +{ + theLeftBorderLength = length; +} + +void ossimMapCompositionSource::setRightBorderLength(ossim_int32 length) +{ + theRightBorderLength = length; +} + +void ossimMapCompositionSource::setGeographicSpacingLat(double value) +{ + theGeographicSpacing.lat = value; +} + +void ossimMapCompositionSource::setGeographicSpacingLon(double value) +{ + theGeographicSpacing.lon = value; +} + +void ossimMapCompositionSource::setMeterSpacingX(double value) +{ + theMeterSpacing.x = value; +} + +void ossimMapCompositionSource::setMeterSpacingY(double value) +{ + theMeterSpacing.y = value; +} + +void ossimMapCompositionSource::setMeterSpacing(double x, double y) +{ + theMeterSpacing.x = x; + theMeterSpacing.y = y; +} + +void ossimMapCompositionSource::setGeographicSpacing(double lat, double lon) +{ + theGeographicSpacing.lat = lat; + theGeographicSpacing.lon = lon; +} + +ossimDpt ossimMapCompositionSource::getGeographicSpacing()const +{ + return theGeographicSpacing; +} + +ossimDpt ossimMapCompositionSource::getMeterSpacing()const +{ + return theMeterSpacing; +} + +ossimString ossimMapCompositionSource::getTopGeographicLabelFormat()const +{ + return theTopGeographicFormat; +} + +ossimString ossimMapCompositionSource::getBottomGeographicLabelFormat()const +{ + return theBottomGeographicFormat; +} + +ossimString ossimMapCompositionSource::getLeftGeographicLabelFormat()const +{ + return theLeftGeographicFormat; +} + +ossimString ossimMapCompositionSource::getRightGeographicLabelFormat()const +{ + return theRightGeographicFormat; +} + +ossimString ossimMapCompositionSource::getTitle()const +{ + return theTitleString; +} + +ossimRgbVector ossimMapCompositionSource::getTitleColor()const +{ + return theTitleColor; +} + +void ossimMapCompositionSource::setTitleColor(const ossimRgbVector& color) +{ + if(theTitleColor != color) + { + theTitleColor = color; + } +} + +void ossimMapCompositionSource::setTitle(const ossimString& s) +{ + if(theTitleString != s) + { + theTitleString = s; + } + +} + +ossimFontInformation ossimMapCompositionSource::getTitleFont()const +{ + return theTitleFontInfo; +} + +ossimFontInformation ossimMapCompositionSource::getGeographicTopLabelFontInfo()const +{ + return theGeographicTopLabelFontInfo; +} + +ossimFontInformation ossimMapCompositionSource::getGeographicBottomLabelFontInfo()const +{ + return theGeographicBottomLabelFontInfo; +} + +ossimFontInformation ossimMapCompositionSource::getGeographicLeftLabelFontInfo()const +{ + return theGeographicLeftLabelFontInfo; +} + +ossimFontInformation ossimMapCompositionSource::getGeographicRightLabelFontInfo()const +{ + return theGeographicRightLabelFontInfo; +} + +ossimFontInformation ossimMapCompositionSource::getMeterTopLabelFontInfo()const +{ + return theMeterTopLabelFontInfo; +} + +ossimFontInformation ossimMapCompositionSource::getMeterBottomLabelFontInfo()const +{ + return theMeterBottomLabelFontInfo; +} + +ossimFontInformation ossimMapCompositionSource::getMeterLeftLabelFontInfo()const +{ + return theMeterLeftLabelFontInfo; +} + +ossimFontInformation ossimMapCompositionSource::getMeterRightLabelFontInfo()const +{ + return theMeterRightLabelFontInfo; +} + +ossimRgbVector ossimMapCompositionSource::getBorderColor()const +{ + return theBorderColor; +} + +void ossimMapCompositionSource::setBorderColor(const ossimRgbVector& color) +{ + theBorderColor=color; +} + +ossimRgbVector ossimMapCompositionSource::getGeographicGridColor()const +{ + return theGeographicGridColor; +} + +ossimRgbVector ossimMapCompositionSource::getMeterGridColor()const +{ + return theMeterGridColor; +} + +ossimRgbVector ossimMapCompositionSource::getTopGeographicLabelColor()const +{ + return theTopGeographicLabelColor; +} + +ossimRgbVector ossimMapCompositionSource::getBottomGeographicLabelColor()const +{ + return theBottomGeographicLabelColor; +} + +ossimRgbVector ossimMapCompositionSource::getLeftGeographicLabelColor()const +{ + return theLeftGeographicLabelColor; +} + +ossimRgbVector ossimMapCompositionSource::getRightGeographicLabelColor()const +{ + return theRightGeographicLabelColor; +} + +void ossimMapCompositionSource::setGeographicGridColor(const ossimRgbVector& color) +{ + theGeographicGridColor = color; +} + +void ossimMapCompositionSource::setTopGeographicLabelColor(const ossimRgbVector& color) +{ + theTopGeographicLabelColor = color; +} + +void ossimMapCompositionSource::setBottomGeographicLabelColor(const ossimRgbVector& color) +{ + theBottomGeographicLabelColor = color; +} + +void ossimMapCompositionSource::setLeftGeographicLabelColor(const ossimRgbVector& color) +{ + theLeftGeographicLabelColor = color; +} + +void ossimMapCompositionSource::setRightGeographicLabelColor(const ossimRgbVector& color) +{ + theRightGeographicLabelColor = color; +} + +void ossimMapCompositionSource::setGeographicLabelColor(const ossimRgbVector& color) +{ + setTopGeographicLabelColor(color); + setBottomGeographicLabelColor(color); + setLeftGeographicLabelColor(color); + setRightGeographicLabelColor(color); +} + +ossimRgbVector ossimMapCompositionSource::getTopMeterLabelColor()const +{ + return theTopMeterLabelColor; +} + +ossimRgbVector ossimMapCompositionSource::getBottomMeterLabelColor()const +{ + return theBottomMeterLabelColor; +} + +ossimRgbVector ossimMapCompositionSource::getLeftMeterLabelColor()const +{ + return theLeftMeterLabelColor; +} + +ossimRgbVector ossimMapCompositionSource::getRightMeterLabelColor()const +{ + return theRightMeterLabelColor; +} + +void ossimMapCompositionSource::setTopMeterLabelColor(const ossimRgbVector& color) +{ + theTopMeterLabelColor = color; +} + +void ossimMapCompositionSource::setBottomMeterLabelColor(const ossimRgbVector& color) +{ + theBottomMeterLabelColor = color; +} + +void ossimMapCompositionSource::setLeftMeterLabelColor(const ossimRgbVector& color) +{ + theLeftMeterLabelColor = color; +} + +void ossimMapCompositionSource::setRightMeterLabelColor(const ossimRgbVector& color) +{ + theRightMeterLabelColor = color; +} + +void ossimMapCompositionSource::setMeterLabelColor(const ossimRgbVector& color) +{ + setTopMeterLabelColor(color); + setBottomMeterLabelColor(color); + setLeftMeterLabelColor(color); + setRightMeterLabelColor(color); +} + +void ossimMapCompositionSource::setMeterGridColor(const ossimRgbVector& color) +{ + theMeterGridColor = color; +} + +void ossimMapCompositionSource::setMeterGridType(ossimGridLineType gridType) +{ + theMeterGridType = gridType; +} + +void ossimMapCompositionSource::setGeographicGridType(ossimGridLineType gridType) +{ + theGeographicGridType = gridType; +} + +void ossimMapCompositionSource::setBorderColor(ossimRgbVector& color) +{ + theBorderColor = color; +} + +ossimMapCompositionSource::ossimGridLineType ossimMapCompositionSource::getGeographicGridType()const +{ + return theGeographicGridType; +} + +ossimMapCompositionSource::ossimGridLineType ossimMapCompositionSource::getMeterGridType()const +{ + return theMeterGridType; +} + +void ossimMapCompositionSource::setGeographicTickMarkFlag(bool flag) +{ + setTopGeographicTickMarkFlag(flag); + setBottomGeographicTickMarkFlag(flag); + setLeftGeographicTickMarkFlag(flag); + setRightGeographicTickMarkFlag(flag); +} + +void ossimMapCompositionSource::setTopGeographicTickMarkFlag(bool flag) +{ + theTopGeographicTickFlag = flag; +} + +void ossimMapCompositionSource::setBottomGeographicTickMarkFlag(bool flag) +{ + theBottomGeographicTickFlag = flag; +} + +void ossimMapCompositionSource::setLeftGeographicTickMarkFlag(bool flag) +{ + theLeftGeographicTickFlag = flag; +} + +void ossimMapCompositionSource::setRightGeographicTickMarkFlag(bool flag) +{ + theRightGeographicTickFlag = flag; +} + +void ossimMapCompositionSource::setTopGeographicLabelFlag(bool flag) +{ + theTopGeographicLabelFlag = flag; +} + +void ossimMapCompositionSource::setBottomGeographicLabelFlag(bool flag) +{ + theBottomGeographicLabelFlag = flag; +} + +void ossimMapCompositionSource::setLeftGeographicLabelFlag(bool flag) +{ + theLeftGeographicLabelFlag = flag; +} + +void ossimMapCompositionSource::setRightGeographicLabelFlag(bool flag) +{ + theRightGeographicLabelFlag = flag; +} + +bool ossimMapCompositionSource::getTopGeographicTickMarkFlag()const +{ + return theTopGeographicTickFlag; +} + +bool ossimMapCompositionSource::getBottomGeographicTickMarkFlag()const +{ + return theBottomGeographicTickFlag; +} + +bool ossimMapCompositionSource::getLeftGeographicTickMarkFlag()const +{ + return theLeftGeographicTickFlag; +} + +bool ossimMapCompositionSource::getRightGeographicTickMarkFlag()const +{ + return theRightGeographicTickFlag; +} + +bool ossimMapCompositionSource::getTopGeographicLabelFlag()const +{ + return theTopGeographicLabelFlag; +} + +bool ossimMapCompositionSource::getBottomGeographicLabelFlag()const +{ + return theBottomGeographicLabelFlag; +} + +bool ossimMapCompositionSource::getLeftGeographicLabelFlag()const +{ + return theLeftGeographicLabelFlag; +} + +bool ossimMapCompositionSource::getRightGeographicLabelFlag()const +{ + return theRightGeographicLabelFlag; +} + +void ossimMapCompositionSource::setMeterTickMarkFlag(bool flag) +{ + setTopMeterTickMarkFlag(flag); + setBottomMeterTickMarkFlag(flag); + setLeftMeterTickMarkFlag(flag); + setRightMeterTickMarkFlag(flag); +} + +void ossimMapCompositionSource::setTopMeterTickMarkFlag(bool flag) +{ + theTopMeterTickFlag = flag; +} + +void ossimMapCompositionSource::setBottomMeterTickMarkFlag(bool flag) +{ + theBottomMeterTickFlag = flag; +} + +void ossimMapCompositionSource::setLeftMeterTickMarkFlag(bool flag) +{ + theLeftMeterTickFlag = flag; +} + +void ossimMapCompositionSource::setRightMeterTickMarkFlag(bool flag) +{ + theRightMeterTickFlag = flag; +} + +void ossimMapCompositionSource::setTopMeterLabelFlag(bool flag) +{ + theTopMeterLabelFlag = flag; +} + +void ossimMapCompositionSource::setBottomMeterLabelFlag(bool flag) +{ + theBottomMeterLabelFlag = flag; +} + +void ossimMapCompositionSource::setLeftMeterLabelFlag(bool flag) +{ + theLeftMeterLabelFlag = flag; +} + +void ossimMapCompositionSource::setRightMeterLabelFlag(bool flag) +{ + theRightMeterLabelFlag = flag; +} + +bool ossimMapCompositionSource::getTopMeterTickMarkFlag()const +{ + return theTopMeterTickFlag; +} + +bool ossimMapCompositionSource::getBottomMeterTickMarkFlag()const +{ + return theBottomMeterTickFlag; +} + +bool ossimMapCompositionSource::getLeftMeterTickMarkFlag()const +{ + return theLeftMeterTickFlag; +} + +bool ossimMapCompositionSource::getRightMeterTickMarkFlag()const +{ + return theRightMeterTickFlag; +} + +bool ossimMapCompositionSource::getTopMeterLabelFlag()const +{ + return theTopMeterLabelFlag; +} + +bool ossimMapCompositionSource::getBottomMeterLabelFlag()const +{ + return theBottomMeterLabelFlag; +} + +bool ossimMapCompositionSource::getLeftMeterLabelFlag()const +{ + return theLeftMeterLabelFlag; +} + +bool ossimMapCompositionSource::getRightMeterLabelFlag()const +{ + return theRightMeterLabelFlag; +} + +void ossimMapCompositionSource::addFixedAnnotation(ossimAnnotationObject* obj) +{ + if(obj) + { + theFixedAnnotationList.push_back(obj); + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/annotation/ossimMapCompositionSource.h b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimMapCompositionSource.h new file mode 100644 index 0000000000..9d4bf456f2 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/annotation/ossimMapCompositionSource.h @@ -0,0 +1,339 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimMapCompositionSource.h,v 1.27 2005/05/23 15:40:28 gpotts Exp $ +#ifndef ossimMapCompositionSource_HEADER +#define ossimMapCompositionSource_HEADER +#include <imaging/annotation/ossimAnnotationSource.h> +#include <base/data_types/color_space/ossimRgbVector.h> +#include <base/data_types/ossimPolyArea2d.h> +#include <fonts/ossimFont.h> +#include <base/common/ossimFontInformation.h> + +class ossimFont; +class ossimMapProjection; +class ossimU8ImageData; + +class ossimMapCompositionSource : public ossimAnnotationSource +{ +public: + enum ossimGridLineType + { + OSSIM_GRID_NONE = 0, + OSSIM_GRID_LINE = 1, + OSSIM_GRID_RESEAUX = 2 + }; + + ossimMapCompositionSource(); + virtual ~ossimMapCompositionSource(); + + virtual ossimScalarType getOutputScalarType() const; + virtual ossim_uint32 getNumberOfOutputBands() const; + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + + + ossimIpt getViewWidthHeight()const; + + void getViewWidthHeight(ossimIpt& widthHeight)const; + + void setViewWidthHeight(const ossimIpt& widthHeight); + + // all borders here + virtual ossim_int32 getTopBorderLength()const; + virtual ossim_int32 getBottomBorderLength()const; + virtual ossim_int32 getLeftBorderLength()const; + virtual ossim_int32 getRightBorderLength()const; + + virtual void setTopBorderLength(ossim_int32 length); + virtual void setBottomBorderLength(ossim_int32 length); + virtual void setLeftBorderLength(ossim_int32 length); + virtual void setRightBorderLength(ossim_int32 length); + + //all spacing here + void setGeographicSpacingLat(double value); + void setGeographicSpacingLon(double value); + void setMeterSpacingX(double value); + void setMeterSpacingY(double value); + void setMeterSpacing(double x, double y); + void setGeographicSpacing(double lat, double lon); + + ossimDpt getGeographicSpacing()const; + ossimDpt getMeterSpacing()const; + + // All geographic formatting here + virtual ossimString getTopGeographicLabelFormat()const; + virtual ossimString getBottomGeographicLabelFormat()const; + virtual ossimString getLeftGeographicLabelFormat()const; + virtual ossimString getRightGeographicLabelFormat()const; + + virtual void setGeographicLabelFormat(const ossimString format); + virtual void setTopGeographicLabelFormat(const ossimString& format); + virtual void setBottomGeographicLabelFormat(const ossimString& format); + virtual void setLeftGeographicLabelFormat(const ossimString& format); + virtual void setRightGeographicLabelFormat(const ossimString& format); + + // All font funtions here. + virtual ossimString getTitle()const; + virtual ossimRgbVector getTitleColor()const; + + virtual void setTitleFont(const ossimFontInformation& fontInfo); + virtual void setTitleColor(const ossimRgbVector& color); + virtual void setTitle(const ossimString& s); + virtual void setGeographicTopLabelFont(const ossimFontInformation& fontInfo); + virtual void setGeographicBottomLabelFont(const ossimFontInformation& fontInfo); + virtual void setGeographicLeftLabelFont(const ossimFontInformation& fontInfo); + virtual void setGeographicRightLabelFont(const ossimFontInformation& fontInfo); + + virtual void setMeterTopLabelFont(const ossimFontInformation& fontInfo); + virtual void setMeterBottomLabelFont(const ossimFontInformation& fontInfo); + virtual void setMeterLeftLabelFont(const ossimFontInformation& fontInfo); + virtual void setMeterRightLabelFont(const ossimFontInformation& fontInfo); + + virtual ossimFontInformation getTitleFont()const; + virtual ossimFontInformation getGeographicTopLabelFontInfo()const; + virtual ossimFontInformation getGeographicBottomLabelFontInfo()const; + virtual ossimFontInformation getGeographicLeftLabelFontInfo()const; + virtual ossimFontInformation getGeographicRightLabelFontInfo()const; + virtual ossimFontInformation getMeterTopLabelFontInfo()const; + virtual ossimFontInformation getMeterBottomLabelFontInfo()const; + virtual ossimFontInformation getMeterLeftLabelFontInfo()const; + virtual ossimFontInformation getMeterRightLabelFontInfo()const; + + // All color funtions here + virtual ossimRgbVector getBorderColor()const; + virtual void setBorderColor(const ossimRgbVector& color); + + virtual ossimRgbVector getGeographicGridColor()const; + virtual ossimRgbVector getMeterGridColor()const; + virtual ossimRgbVector getTopGeographicLabelColor()const; + virtual ossimRgbVector getBottomGeographicLabelColor()const; + virtual ossimRgbVector getLeftGeographicLabelColor()const; + virtual ossimRgbVector getRightGeographicLabelColor()const; + + virtual void setGeographicGridColor(const ossimRgbVector& color); + virtual void setTopGeographicLabelColor(const ossimRgbVector& color); + virtual void setBottomGeographicLabelColor(const ossimRgbVector& color); + virtual void setLeftGeographicLabelColor(const ossimRgbVector& color); + virtual void setRightGeographicLabelColor(const ossimRgbVector& color); + virtual void setGeographicLabelColor(const ossimRgbVector& color); + + virtual ossimRgbVector getTopMeterLabelColor()const; + virtual ossimRgbVector getBottomMeterLabelColor()const; + virtual ossimRgbVector getLeftMeterLabelColor()const; + virtual ossimRgbVector getRightMeterLabelColor()const; + + virtual void setTopMeterLabelColor(const ossimRgbVector& color); + virtual void setBottomMeterLabelColor(const ossimRgbVector& color); + virtual void setLeftMeterLabelColor(const ossimRgbVector& color); + virtual void setRightMeterLabelColor(const ossimRgbVector& color); + virtual void setMeterLabelColor(const ossimRgbVector& color); + virtual void setMeterGridColor(const ossimRgbVector& color); + + // All grid types here + virtual void setMeterGridType(ossimGridLineType gridType); + virtual void setGeographicGridType(ossimGridLineType gridType); + virtual void setBorderColor(ossimRgbVector& color); + + virtual ossimGridLineType getGeographicGridType()const; + virtual ossimGridLineType getMeterGridType()const; + + // all grid flags here + void setGeographicTickMarkFlag(bool flag); + void setTopGeographicTickMarkFlag(bool flag); + void setBottomGeographicTickMarkFlag(bool flag); + void setLeftGeographicTickMarkFlag(bool flag); + void setRightGeographicTickMarkFlag(bool flag); + void setTopGeographicLabelFlag(bool flag); + void setBottomGeographicLabelFlag(bool flag); + void setLeftGeographicLabelFlag(bool flag); + void setRightGeographicLabelFlag(bool flag); + + virtual bool getTopGeographicTickMarkFlag()const; + virtual bool getBottomGeographicTickMarkFlag()const; + virtual bool getLeftGeographicTickMarkFlag()const; + virtual bool getRightGeographicTickMarkFlag()const; + virtual bool getTopGeographicLabelFlag()const; + virtual bool getBottomGeographicLabelFlag()const; + virtual bool getLeftGeographicLabelFlag()const; + virtual bool getRightGeographicLabelFlag()const; + + void setMeterTickMarkFlag(bool flag); + virtual void setTopMeterTickMarkFlag(bool flag); + virtual void setBottomMeterTickMarkFlag(bool flag); + virtual void setLeftMeterTickMarkFlag(bool flag); + virtual void setRightMeterTickMarkFlag(bool flag); + virtual void setTopMeterLabelFlag(bool flag); + virtual void setBottomMeterLabelFlag(bool flag); + virtual void setLeftMeterLabelFlag(bool flag); + virtual void setRightMeterLabelFlag(bool flag); + + virtual bool getTopMeterTickMarkFlag()const; + virtual bool getBottomMeterTickMarkFlag()const; + virtual bool getLeftMeterTickMarkFlag()const; + virtual bool getRightMeterTickMarkFlag()const; + virtual bool getTopMeterLabelFlag()const; + virtual bool getBottomMeterLabelFlag()const; + virtual bool getLeftMeterLabelFlag()const; + virtual bool getRightMeterLabelFlag()const; + virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0)const; + + virtual void initialize(); + + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + + +protected: + ossimIpt theViewWidthHeight; + ossimGridLineType theMeterGridType; + ossimGridLineType theGeographicGridType; + + ossim_uint32 theTopBorderLength; + ossim_uint32 theBottomBorderLength; + ossim_uint32 theLeftBorderLength; + ossim_uint32 theRightBorderLength; + + ossimRgbVector theBorderColor; + + ossimRgbVector theGeographicGridColor; + ossimRgbVector theMeterGridColor; + + // title info + // + ossimString theTitleString; + ossimFont* theTitleFont; + ossimFontInformation theTitleFontInfo; + ossimRgbVector theTitleColor; + + // grid label colors + // + ossimRgbVector theTopGeographicLabelColor; + ossimRgbVector theBottomGeographicLabelColor; + ossimRgbVector theLeftGeographicLabelColor; + ossimRgbVector theRightGeographicLabelColor; + ossimRgbVector theTopMeterLabelColor; + ossimRgbVector theBottomMeterLabelColor; + ossimRgbVector theLeftMeterLabelColor; + ossimRgbVector theRightMeterLabelColor; + + // grid label font + // + ossimFontInformation theGeographicTopLabelFontInfo; + ossimFont* theGeographicTopLabelFont; + ossimFontInformation theGeographicBottomLabelFontInfo; + ossimFont* theGeographicBottomLabelFont; + ossimFontInformation theGeographicLeftLabelFontInfo; + ossimFont* theGeographicLeftLabelFont; + ossimFontInformation theGeographicRightLabelFontInfo; + ossimFont* theGeographicRightLabelFont; + + ossimFontInformation theMeterTopLabelFontInfo; + ossimFont* theMeterTopLabelFont; + ossimFontInformation theMeterBottomLabelFontInfo; + ossimFont* theMeterBottomLabelFont; + ossimFontInformation theMeterLeftLabelFontInfo; + ossimFont* theMeterLeftLabelFont; + ossimFontInformation theMeterRightLabelFontInfo; + ossimFont* theMeterRightLabelFont; + + // grid label dms format strings + // + ossimString theTopGeographicFormat; + ossimString theBottomGeographicFormat; + ossimString theLeftGeographicFormat; + ossimString theRightGeographicFormat; + + // grid label flag + // + bool theTopGeographicLabelFlag; + bool theBottomGeographicLabelFlag; + bool theLeftGeographicLabelFlag; + bool theRightGeographicLabelFlag; + + bool theTopGeographicTickFlag; + bool theBottomGeographicTickFlag; + bool theLeftGeographicTickFlag; + bool theRightGeographicTickFlag; + + bool theTopMeterLabelFlag; + bool theBottomMeterLabelFlag; + bool theLeftMeterLabelFlag; + bool theRightMeterLabelFlag; + + bool theTopMeterTickFlag; + bool theBottomMeterTickFlag; + bool theLeftMeterTickFlag; + bool theRightMeterTickFlag; + + + ossimIrect theTopBorder; + ossimIrect theBottomBorder; + ossimIrect theLeftBorder; + ossimIrect theRightBorder; + + // geo-tick spacing in lat lon + ossimDpt theGeographicSpacing; + + // tick spacing in meter units + ossimDpt theMeterSpacing; + + ossimMapProjection* theInputProjection; + + vector<ossimAnnotationObject*> theFixedAnnotationList; + + /*! + * Override base classes drawAnnotations so we can layout + * any fixed annotations first. + */ + virtual void drawAnnotations(ossimRefPtr<ossimImageData> tile); + + virtual void computeBorderRects(); + virtual void drawBorders(); + virtual void addGridLabels(); + + virtual void addGeographicTopGridLabels(); + virtual void addGeographicBottomGridLabels(); + virtual void addGeographicLeftGridLabels(); + virtual void addGeographicRightGridLabels(); + + virtual void addGeographicGridLines(); + virtual void addGeographicGridReseaux(); + + virtual void addMeterGridLabels(); + + virtual void addMeterGridLines(); + virtual void addMeterGridReseaux(); + + + virtual void addTitle(); + + virtual void layoutAnnotations(); + + virtual void addFixedAnnotation(ossimAnnotationObject* obj); + + virtual void deleteFixedAnnotations(); + + ossimIrect getViewingRect()const; + +// For RTTI +TYPE_DATA +}; +#endif /* #ifndef ossimMapCompositionSource_HEADER */ + diff --git a/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/.cvsignore new file mode 100644 index 0000000000..93652de916 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/.cvsignore @@ -0,0 +1,5 @@ +Makefile +ossimAOD.d +ossimAtCorrGridRemapper.d +ossimAtCorrRemapper.d +ossimGammaRemapper.d diff --git a/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAOD.cpp b/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAOD.cpp new file mode 100644 index 0000000000..ff32461359 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAOD.cpp @@ -0,0 +1,238 @@ +//******************************************************************* +// Copyright (C) 2002 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Kathy Minear +// +// Description: +// +// Class to compute Aerosol Optical Depth (AOD) for with atmospheric +// correction. +// +// +//************************************************************************* +// $Id: ossimAOD.cpp,v 1.5 2005/02/11 15:07:30 dburken Exp $ + +#include <math.h> +#include <imaging/atmospheric_correction/ossimAOD.h> +#include <base/common/ossimTrace.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <imaging/ossimU8ImageData.h> + + +RTTI_DEF1(ossimAOD, "ossimAOD", ossimImageSourceFilter) + +static ossimTrace traceDebug("ossimAOD:debug"); + +ossimAOD::ossimAOD(ossimObject* owner) + : + ossimImageSourceFilter (owner), // base class + theTile (NULL) +{ + //*** + // Set the base class "theEnableFlag" to off since no adjustments have been + // made yet. + //*** + disableSource(); + + // Construction not complete. +} + +ossimAOD::ossimAOD(ossimImageSource* inputSource) + : + ossimImageSourceFilter (NULL, inputSource), // base class + theTile (NULL) +{ + //*** + // Set the base class "theEnableFlag" to off since no adjustments have been + // made yet. + //*** + disableSource(); + + if (inputSource == NULL) + { + setErrorStatus(); + cerr << "ossimAOD::ossimAOD ERROR:" + << "\nNull input source passed to constructor!" << endl; + return; + } + + initialize(); +} + + +ossimAOD::ossimAOD(ossimObject* owner, + ossimImageSource* inputSource) + : + ossimImageSourceFilter (owner, inputSource), // base class + theTile (NULL) +{ + //*** + // Set the base class "theEnableFlag" to off since no adjustments have been + // made yet. + //*** + disableSource(); + + if (inputSource == NULL) + { + setErrorStatus(); + cerr << "ossimAOD::ossimAOD ERROR:" + << "\nNull input source passed to constructor!" << endl; + return; + } + + initialize(); +} + +ossimAOD::~ossimAOD() +{ +} + +ossimRefPtr<ossimImageData> ossimAOD::getTile(const ossimIrect& tile_rect, + ossim_uint32 resLevel) +{ + if (!theInputConnection) + { + return ossimRefPtr<ossimImageData>(); + } + + // Fetch tile from pointer from the input source. + ossimRefPtr<ossimImageData> inputTile = theInputConnection->getTile(tile_rect, + resLevel); + + + if (!inputTile.valid()) // Just in case... + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimAOD::getTile ERROR:" + << "\nReceived null pointer to tile from input source!" + << "\nReturning blank tile." + << endl; + return inputTile; + } + + ossimDataObjectStatus tile_status = inputTile->getDataObjectStatus(); + + if ( !theEnableFlag || + (tile_status == OSSIM_NULL) || + (tile_status == OSSIM_EMPTY) ) + { + return inputTile; + } + + if (!theTile.valid()) + { + allocate(); + if (!theTile.valid()) + { + return inputTile; + } + } + + ossim_uint32 w = tile_rect.width(); + ossim_uint32 h = tile_rect.height(); + ossim_uint32 tw = theTile->getWidth(); + ossim_uint32 th = theTile->getHeight(); + // ossim_uint32 bands = theTile->getNumberOfBands(); + + // Set the origin of the output tile. + theTile->setOrigin(tile_rect.ul()); + + if(w*h != tw*th) + { + theTile->setWidthHeight(w, h); + theTile->initialize(); + } + return theTile; +} + +void ossimAOD::initialize() +{ + ossimImageSourceFilter::initialize(); +} + +void ossimAOD::allocate() +{ + if(theInputConnection) + { + theTile = ossimImageDataFactory::instance()->create(this, + theInputConnection); + theTile->initialize(); + setInitializedFlag(true); + clearErrorStatus(); + } + else + { + setInitializedFlag(false); + setErrorStatus(); + cerr << "ossimAOD::initialize ERROR:" + << "\nCannot call method when input connection is NULL!" + << endl; + }; + + verifyEnabled(); +} + +bool ossimAOD::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + static const char MODULE[] = "ossimAOD::loadState()"; + + if (traceDebug()) CLOG << "entering..." << endl; + + if (!theTile) + { + cerr << MODULE << " ERROR:" + << "Not initialized..." << endl; + return false; + } + + if (traceDebug()) + { + CLOG << "DEBUG:" + << *this + << "\nreturning..." + << endl; + } + + return true; +} + + +void ossimAOD::verifyEnabled() +{ + // Check all the pointers... + if ( !theInputConnection || !theTile ) + { + disableSource(); + return; + } + + enableSource(); +} + +ostream& ossimAOD::print(ostream& os) const +{ + os << "ossimAOD:" + << "\ntheEnableFlag: " << (theEnableFlag?"enabled":"disabled") + << endl; + + return os; +} + +ostream& operator<<(ostream& os, const ossimAOD& hr) +{ + return hr.print(os); +} + +void ossimAOD::writeTemplate(ostream& os) +{ +} + +ossimString ossimAOD::getShortName() const +{ + return ossimString("Aerosol Optical Depth"); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAOD.h b/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAOD.h new file mode 100644 index 0000000000..496ca17220 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAOD.h @@ -0,0 +1,66 @@ +//******************************************************************* +// Copyright (C) 2002 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Kathy Minear +// +// Description: +// +// Class to compute Aerosol Optical Depth (AOD) for with atmospheric +// correction. +// +//************************************************************************* +// $Id: ossimAOD.h,v 1.4 2005/02/11 15:07:30 dburken Exp $ +#ifndef ossimAOD_HEADER +#define ossimAOD_HEADER + +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +class ossimAOD : public ossimImageSourceFilter +{ +public: + + ossimAOD(ossimObject* owner=NULL); + ossimAOD(ossimImageSource* inputSource); + ossimAOD(ossimObject* owner, ossimImageSource* inputSource); + + virtual ~ossimAOD(); + + virtual ossimString getShortName() const; + + virtual void initialize(); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tile_rect, + ossim_uint32 resLevel=0); + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual ostream& print(ostream& os) const; + friend ostream& operator << (ostream& os, const ossimAOD& hr); + + static void writeTemplate(ostream& os); + +protected: + + void allocate(); + + /*! + * Method to set unset the enable flag. + */ + void verifyEnabled(); + + ossimRefPtr<ossimImageData> theTile; + + TYPE_DATA +}; + +#endif /* #ifndef ossimAOD_HEADER */ + diff --git a/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAtCorrGridRemapper.cpp b/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAtCorrGridRemapper.cpp new file mode 100644 index 0000000000..f137505e37 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAtCorrGridRemapper.cpp @@ -0,0 +1,351 @@ +//******************************************************************* +// Copyright (C) 2003 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts <gpotts@imagelinks.com> +// +// Description: +//******************************************************************* +// $Id: ossimAtCorrGridRemapper.cpp,v 1.5 2003/10/07 17:09:55 gpotts Exp $ +#include "ossimAtCorrGridRemapper.h" + +RTTI_DEF1(ossimAtCorrGridRemapper, "ossimAtCorrGridRemapper", ossimAtCorrRemapper); + +ossimAtCorrGridRemapper::ossimAtCorrGridRemapper(ossimObject* owner, + ossimImageSource* inputSource, + const ossimString& sensorType) + :ossimAtCorrRemapper(owner, inputSource, sensorType) +{ + theUseInterpolationFlag = true; +} + +ossimAtCorrGridRemapper::~ossimAtCorrGridRemapper() +{ +} + +void ossimAtCorrGridRemapper::interpolate(const ossimDpt& pt, + int band, + double& a, + double& b, + double& c)const +{ + if(theGridBounds.pointWithin(pt)) + { + double x = (((double)(pt.x - theUlGridBound.x))/theGridBounds.width())*(theGridSize.x-1); + double y = (((double)(pt.y - theUlGridBound.y))/theGridBounds.height())*(theGridSize.y-1); + + int xidx = (int)x; + int yidx = (int)y; + + double xt = x - xidx; + double yt = y - yidx; + + double va00 = theAGrid[band][yidx][xidx]; + double va01 = theAGrid[band][yidx][xidx+1]; + double va11 = theAGrid[band][yidx+1][xidx+1]; + double va10 = theAGrid[band][yidx+1][xidx]; + double vb00 = theBGrid[band][yidx][xidx]; + double vb01 = theBGrid[band][yidx][xidx+1]; + double vb11 = theBGrid[band][yidx+1][xidx+1]; + double vb10 = theBGrid[band][yidx+1][xidx]; + double vc00 = theCGrid[band][yidx][xidx]; + double vc01 = theCGrid[band][yidx][xidx+1]; + double vc11 = theCGrid[band][yidx+1][xidx+1]; + double vc10 = theCGrid[band][yidx+1][xidx]; + + double vaInterpH1 = va00 + (va01-va00)*xt; + double vaInterpH2 = va10 + (va11-va10)*xt; + double vbInterpH1 = vb00 + (vb01-vb00)*xt; + double vbInterpH2 = vb10 + (vb11-vb10)*xt; + double vcInterpH1 = vc00 + (vc01-vc00)*xt; + double vcInterpH2 = vc10 + (vc11-vc10)*xt; + + a = vaInterpH1 + (vaInterpH2-vaInterpH1)*yt; + b = vbInterpH1 + (vbInterpH2-vbInterpH1)*yt; + c = vcInterpH1 + (vcInterpH2-vcInterpH1)*yt; + } + else + { + ossimAtCorrRemapper::interpolate(pt, + band, + a, + b, + c); + } +} + +void ossimAtCorrGridRemapper::initialize() +{ + ossimAtCorrRemapper::initialize(); + + if(theInputConnection) + { + theGridBounds = theInputConnection->getBoundingRect(); + theUlGridBound = theGridBounds.ul(); + } + else + { + theGridBounds.makeNan(); + } + + if(!theAGrid.size()|| + !theBGrid.size()|| + !theCGrid.size()) + { + theUseInterpolationFlag=false; + } + setBaseToAverage(); +} + +void ossimAtCorrGridRemapper::setGridSize(ossim_uint32 numberOfBands, const ossimIpt& gridSize) +{ + + if((theGridSize!=gridSize)||(numberOfBands != theAGrid.size())) + { + theAGrid.resize(numberOfBands); + theBGrid.resize(numberOfBands); + theCGrid.resize(numberOfBands); + + for(ossim_uint32 b = 0; b < numberOfBands;++b) + { + theAGrid[b].resize(gridSize.y); + theBGrid[b].resize(gridSize.y); + theCGrid[b].resize(gridSize.y); + for(int r = 0; r < gridSize.y; ++r) + { + theAGrid[b][r].resize(gridSize.x); + theBGrid[b][r].resize(gridSize.x); + theCGrid[b][r].resize(gridSize.x); + } + + } + theGridSize = gridSize; + } + +} + + +void ossimAtCorrGridRemapper::setBaseToAverage() +{ + ossim_uint32 idxBand; + vector<double> xaAverage(theAGrid.size()); + vector<double> xcAverage(theBGrid.size()); + vector<double> xbAverage(theCGrid.size()); + // double aAverage=0.0, bAverage=0.0, cAverag=0.0; + + + if((theAGrid.size() != theBGrid.size())|| + (theAGrid.size() != theCGrid.size())|| + (theAGrid.size() == 0)) + { + return; + } + + for(idxBand = 0; idxBand < theAGrid.size(); ++idxBand) + { + ossim_uint32 idxRow = 0; + xaAverage[idxBand] = 0.0; + xbAverage[idxBand] = 0.0; + xcAverage[idxBand] = 0.0; + for(idxRow = 0; idxRow < theAGrid[idxBand].size();++idxRow) + { + ossim_uint32 idxCol = 0; + for(idxCol = 0; idxCol < theAGrid[idxBand][idxRow].size();++idxCol) + { + xaAverage[idxBand] += theAGrid[idxBand][idxRow][idxCol]; + + } + } + for(idxRow = 0; idxRow < theBGrid[idxBand].size();++idxRow) + { + ossim_uint32 idxCol = 0; + for(idxCol = 0; idxCol < theBGrid[idxBand][idxRow].size();++idxCol) + { + xbAverage[idxBand] += theBGrid[idxBand][idxRow][idxCol]; + } + } + for(idxRow = 0; idxRow < theCGrid[idxBand].size();++idxRow) + { + ossim_uint32 idxCol = 0; + for(idxCol = 0; idxCol < theCGrid[idxBand][idxRow].size();++idxCol) + { + xaAverage[idxBand] += theCGrid[idxBand][idxRow][idxCol]; + xbAverage[idxBand] += theCGrid[idxBand][idxRow][idxCol]; + xcAverage[idxBand] += theCGrid[idxBand][idxRow][idxCol]; + + } + } + } + + for(idxBand = 0; idxBand < theAGrid.size(); ++idxBand) + { + xaAverage[idxBand] /=(double)(theGridSize.x*theGridSize.y); + xbAverage[idxBand] /=(double)(theGridSize.x*theGridSize.y); + xcAverage[idxBand] /=(double)(theGridSize.x*theGridSize.y); + } + + theXaArray = xaAverage; + theXbArray = xbAverage; + theXcArray = xcAverage; +} + +/*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ +bool ossimAtCorrGridRemapper::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* MODULE = "ossimAtCorrGridRemapper::loadState"; + theAGrid.clear(); + theBGrid.clear(); + theCGrid.clear(); + + if (!theTile || !theSurfaceReflectance) + { + cerr << MODULE << " ERROR:" + << "Not initialized..." << endl; + return false; + } + theUseInterpolationFlag=true; + ossim_uint32 bands = theTile->getNumberOfBands(); + + theAGrid.resize(bands); + theBGrid.resize(bands); + theCGrid.resize(bands); + + + const char* rowsLookup = NULL; + const char* colsLookup = NULL; + for(ossim_uint32 band = 0; band < bands; ++band) + { + ossim_uint32 r = 0; + ossim_uint32 c = 0; + ossimString gridString = "band"; + gridString += ossimString::toString(band+1); + gridString += ".grid"; + + rowsLookup = kwl.find(prefix, + gridString + ".rows"); + + colsLookup = kwl.find(prefix, + gridString + ".cols"); + if(rowsLookup&&colsLookup) + { + cout << "both keywords needed: " << (gridString+".rows") << endl + << (gridString+".cols") << endl; + + theUseInterpolationFlag=false; + return false; + } + + ossim_uint32 rows = ossimString(rowsLookup).toULong(); + ossim_uint32 cols = ossimString(colsLookup).toULong(); + + if(cols&&rows) + { + cout << "value for cols and rows keyword have 0" << endl; + theUseInterpolationFlag=false; + return false; + } + + theAGrid[band].resize(rows); + theBGrid[band].resize(rows); + theCGrid[band].resize(rows); + for(r = 0; r < rows; ++r) + { + theAGrid[band][r].resize(cols); + theBGrid[band][r].resize(cols); + theCGrid[band][r].resize(cols); + } + + ossim_uint32 idx = 1; + const char* aLookup; + const char* bLookup; + const char* cLookup; + for(r = 0; r < rows; ++r) + { + for(c = 0; c < cols; ++c) + { + aLookup = kwl.find(prefix, gridString+".a"+ossimString::toString(idx)); + bLookup = kwl.find(prefix, gridString+".b"+ossimString::toString(idx)); + cLookup = kwl.find(prefix, gridString+".c"+ossimString::toString(idx)); + theAGrid[band][r][c] = ossimString(aLookup).toDouble(); + theBGrid[band][r][c] = ossimString(bLookup).toDouble(); + theCGrid[band][r][c] = ossimString(cLookup).toDouble(); + + ++idx; + } + } + + theGridSize.x = cols; + theGridSize.y = rows; + setBaseToAverage(); + } + + return true; +} + +bool ossimAtCorrGridRemapper::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + + ossim_uint32 bands = theAGrid.size(); + + for(ossim_uint32 band = 0; band < bands; ++band) + { + int idx = 1; + int r = 0; + int c = 0; + ossimString gridString = "band"; + gridString += ossimString::toString(band+1); + gridString += ".grid"; + + ossim_uint32 rows = theAGrid[band].size(); + kwl.add(prefix, + gridString+".rows", + rows, + true); + ossim_uint32 cols = theAGrid[band][0].size(); + kwl.add(prefix, + gridString+".cols", + cols, + true); + for(r = 0; r < theGridSize.y; ++r) + { + for(c = 0; c < theGridSize.x; ++c) + { + kwl.add(prefix, + gridString+".a"+ossimString::toString(idx), + theAGrid[band][r][c], + true); + kwl.add(prefix, + gridString+".b"+ossimString::toString(idx), + theAGrid[band][r][c], + true); + kwl.add(prefix, + gridString+".c"+ossimString::toString(idx), + theAGrid[band][r][c], + true); + + ++idx; + } + } + } + + return ossimAtCorrRemapper::saveState(kwl, prefix); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAtCorrGridRemapper.h b/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAtCorrGridRemapper.h new file mode 100644 index 0000000000..14414d2a1e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAtCorrGridRemapper.h @@ -0,0 +1,154 @@ +//******************************************************************* +// Copyright (C) 2003 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts <gpotts@imagelinks.com> +// +//******************************************************************* +// $Id: ossimAtCorrGridRemapper.h,v 1.3 2003/10/07 17:10:02 gpotts Exp $ +#ifndef ossimAtCorrGridRemapper_HEADER +#define ossimAtCorrGridRemapper_HEADER +#include "ossimAtCorrRemapper.h" + +/*! + * The grid is encoded into band separate grid and allows bilinear interpolation + * of atmospheric correction coefficients. It uses the implementation found in + * ossimAtCorrRemapper. The base class will call interpolate to calculate the + * a, b, c coefficients used. This class just overrides the base interpolation method. For + * gridded remappers + * + * + * + * Sample keywordlist includes: + * + * band1.grid.rows: 4 + * band1.grid.cols: 4 + * band1.grid.a1: + * band1.grid.b1: + * band1.grid.c1: + * band1.grid.a2: + * band1.grid.b2: + * band1.grid.c2: + * band1.grid.a3: + * band1.grid.b3: + * band1.grid.c3: + * band1.grid.a4: + * band1.grid.b4: + * band1.grid.c4: + * band2.grid.rows: 4 + * band2.grid.cols: 4 + * band2.grid.a1: + * band2.grid.b1: + * band2.grid.c1: + * band2.grid.a2: + * band2.grid.b2: + * band2.grid.c2: + * band2.grid.a3: + * band2.grid.b3: + * band2.grid.c3: + * band2.grid.a4: + * band2.grid.b4: + * band2.grid.c4: + * + * : + * : + * : + */ +class ossimAtCorrGridRemapper: public ossimAtCorrRemapper +{ +public: + ossimAtCorrGridRemapper(ossimObject* owner = NULL, + ossimImageSource* inputSource = NULL, + const ossimString& sensorType = ""); + + virtual ~ossimAtCorrGridRemapper(); + + + void setGridRect(const ossimIrect& rect) + { + theGridBounds = rect; + theUlGridBound = rect.ul(); + } + void setGridSize(ossim_uint32 numberOfBands, const ossimIpt& gridSize); + ossimIpt getGridSize()const + { + return theGridSize; + } + + void getValues(ossim_uint32 band, + ossim_uint32 row, + ossim_uint32 col, + double& a, + double& b, + double& c) + { + a = theAGrid[band][row][col]; + b = theAGrid[band][row][col]; + c = theAGrid[band][row][col]; + } + + void getValues(const ossimDpt& pt, + ossim_uint32 band, + double& a, + double& b, + double& c) + { + interpolate(pt, band, a, b, c); + } + + void setValues(ossim_uint32 band, + ossim_uint32 row, + ossim_uint32 col, + const double& a, + const double& b, + const double& c) + { + theAGrid[band][row][col] = a; + theBGrid[band][row][col] = b; + theCGrid[band][row][col] = c; + } + + virtual void initialize(); + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + +protected: + ossimIrect theGridBounds; + ossimIpt theUlGridBound; + ossimIpt theGridSize; + std::vector< std::vector< std::vector<double> > >theAGrid; + std::vector< std::vector< std::vector<double> > >theBGrid; + std::vector< std::vector< std::vector<double> > >theCGrid; + + virtual void interpolate(const ossimDpt& pt, + int band, + double& a, + double& b, + double& c)const; + virtual void setBaseToAverage(); + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAtCorrKeywords.h b/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAtCorrKeywords.h new file mode 100644 index 0000000000..9505ce475a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAtCorrKeywords.h @@ -0,0 +1,35 @@ +//******************************************************************* +// Copyright (C) 2002 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken <dburken@imagelinks.com> +// +// Description: +// Keywords utilized by atmospheric correction code. +// +//************************************************************************* +// $Id: ossimAtCorrKeywords.h,v 1.3 2003/05/13 18:08:37 kminear Exp $ + +static const char AT_CORR_XA_KW[] = "atmospheric_correction.xa"; +static const char AT_CORR_XB_KW[] = "atmospheric_correction.xb"; +static const char AT_CORR_XC_KW[] = "atmospheric_correction.xc"; +static const char AT_CORR_BIAS_KW[] = "atmospheric_correction.bias"; +static const char AT_CORR_GAIN_KW[] = "atmospheric_correction.gain"; +static const char AT_CORR_CALCOEF_KW[] = "atmospheric_correction.calcoef"; +static const char AT_CORR_BANDWIDTH_KW[] = "atmospheric_correction.bandwidth"; + +static const char GAMMA_REMAPPER_GAMMA_KW[] = "gamma_remapper.gamma"; diff --git a/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAtCorrRemapper.cpp b/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAtCorrRemapper.cpp new file mode 100644 index 0000000000..ea72ba067e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAtCorrRemapper.cpp @@ -0,0 +1,729 @@ +//******************************************************************* +// Copyright (C) 2002 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Kathy Minear +// +// Description: +// Takes in DNs for any number of bands +// Converts DNs to Radiance at the satellite values Lsat +// Converts Lsat to Surface Reflectance values +// +//************************************************************************* +// $Id: ossimAtCorrRemapper.cpp,v 1.21 2005/02/11 15:07:30 dburken Exp $ + +#include <math.h> + +#include <imaging/atmospheric_correction/ossimAtCorrRemapper.h> +#include <imaging/atmospheric_correction/ossimAtCorrKeywords.h> +#include <base/common/ossimTrace.h> +#include <imaging/factory/ossimImageDataFactory.h> + + +RTTI_DEF1(ossimAtCorrRemapper, "ossimAtCorrRemapper", ossimImageSourceFilter); + +static ossimTrace traceDebug("ossimAtCorrRemapper:debug"); + +ossimAtCorrRemapper::ossimAtCorrRemapper(ossimObject* owner, + ossimImageSource* inputSource, + const ossimString& sensorType) + : + ossimImageSourceFilter (owner, inputSource), // base class + theTile (NULL), + theSurfaceReflectance (NULL), + theUseInterpolationFlag(false), + theMinPixelValue (0), + theMaxPixelValue (0), + theXaArray (0), + theXbArray (0), + theXcArray (0), + theBiasArray (0), + theGainArray (0), + theCalCoefArray (0), + theBandWidthArray (0), + theSensorType(sensorType) +{ + //*** + // Set the base class "theEnableFlag" to off since no adjustments have been + // made yet. + //*** + disableSource(); + + initialize(); +} + +ossimAtCorrRemapper::~ossimAtCorrRemapper() +{ + if (theSurfaceReflectance) + { + delete [] theSurfaceReflectance; + theSurfaceReflectance = NULL; + } +} + +ossimRefPtr<ossimImageData> ossimAtCorrRemapper::getTile( + const ossimIrect& tile_rect, + ossim_uint32 resLevel) +{ +#if 0 + if (traceDebug()) + { + cout << "ossimAtCorrRemapper::getTile DEBUG:" + << "\ntile_rect: " << tile_rect << endl; + } +#endif + + if (!isInitialized()||!theInputConnection) + { + cerr << "ossimAtCorrRemapper::getTile ERROR:" + << "\nNot initialized!" + << endl; + return ossimRefPtr<ossimImageData>(); + } + + if(!theTile.valid()) + { + initialize(); + if(!theTile) + { + return ossimRefPtr<ossimImageData>(); + } + } + + // Fetch tile from pointer from the input source. + ossimRefPtr<ossimImageData> inputTile = theInputConnection->getTile(tile_rect, + resLevel); + + if (!inputTile.valid()) // Just in case... + { + return ossimRefPtr<ossimImageData>(); + } + + // Check for remap bypass or empty / null input tile. + ossimDataObjectStatus tile_status = inputTile->getDataObjectStatus(); + if (!theEnableFlag || tile_status == OSSIM_NULL || + tile_status == OSSIM_EMPTY) + { + return inputTile; + } + + ossim_uint32 w = tile_rect.width(); + ossim_uint32 h = tile_rect.height(); + ossim_uint32 tw = theTile->getWidth(); + ossim_uint32 th = theTile->getHeight(); + ossim_uint32 bands = theTile->getNumberOfBands(); + + // Set the origin of the output tile. + theTile->setOrigin(tile_rect.ul()); + + if(w*h != tw*th) + { + theTile->setWidthHeight(w, h); + theTile->initialize(); + if(theSurfaceReflectance) + { + delete [] theSurfaceReflectance; + theSurfaceReflectance = NULL; + } + } + + if(!theSurfaceReflectance) + { + ossim_uint32 size = tw*th*bands; +#if 0 + if (traceDebug()) + { + cout << "ossimAtCorrRemapper::getTile DEBUG:" + << "\ntile_rect: " << tile_rect + << "\ntile width: " << tw + << "\ntile height: " << th + << "\nbands: " << bands + << "\nBuffer size: " << size << endl; + } +#endif + + theSurfaceReflectance = new double[size]; + } + + ossim_uint32 buffer_index = 0; + ossimIpt ul = tile_rect.ul(); + ossimIpt lr = tile_rect.lr(); + const double MP = theTile->getMinNormalizedPix(); // Minimum normalized pix. + double a, b, c; + buffer_index = 0; + + cout << setprecision(6); + for (ossim_uint32 band=0; band < bands; ++band) + { + for(ossim_sint32 idxy = ul.y; idxy <= lr.y; ++idxy) + { + for(ossim_sint32 idxx = ul.x; idxx <= lr.x; ++idxx) + { + double p = inputTile->getPix(buffer_index); + + if (p>0.0) + { + if(!theUseInterpolationFlag) + { + a = theXaArray[band]; + b = theXbArray[band]; + c = theXcArray[band]; + } + else + { + interpolate(ossimDpt(idxx, idxy), + band, + a, + b, + c); + } + if(theSensorType == "ls7ms") + { + double radiance_at_satellite + = (theGainArray[band] * p) + theBiasArray[band]; + + double y = (radiance_at_satellite * a) - b; + + p = (y / (1.0 + (c * y)) ); + } + else if(theSensorType == "qbms") + { + double radiance_at_satellite + = theCalCoefArray[band] * p / theBandWidthArray[band]; + + double y = (radiance_at_satellite * a) - b; + + p = (y / (1.0 + (c * y)) ); + } + else if(theSensorType == "ikms") + { + + + double radiance_at_satellite + = p /((theCalCoefArray[band]/1.0)/ theBandWidthArray[band]); + double y = (radiance_at_satellite * a) - b; + + p = (y / (1.0 + (c * y)) ); + + } + + // Note that "p" should now be normalized between 0.0 and 1.0; + + // *** + // Since it wasn't null to start with clip / clamp between minimum + // normalized pixel and one(max). + // *** + p = ( p > MP ? ( p < 1.0 ? p : 1.0) : MP ); + + // Scan the new tile and set the min / max. + if (p < theMinPixelValue[band]) + { + theMinPixelValue[band] = p; + } + else if (p > theMaxPixelValue[band]) + { + theMaxPixelValue[band] = p; + } + + theSurfaceReflectance[buffer_index] = p; + } + else + { + theSurfaceReflectance[buffer_index] = 0.0; // pixel was null... + } + + ++buffer_index; + + } // End of sample loop... + + } // End of line loop... + + } // End of band loop... + + // Copy the buffer to the output tile at the same time unnormalizing it. + theTile->copyNormalizedBufferToTile(theSurfaceReflectance); + + // Validate the output to set the tile status. + theTile->validate(); + + return theTile; +} + +void ossimAtCorrRemapper::initialize() +{ + if(theInputConnection) + { + theTile = ossimImageDataFactory::instance()->create(this, + theInputConnection); + theTile->initialize(); + + if(theSurfaceReflectance) + { + delete []theSurfaceReflectance; + theSurfaceReflectance = NULL; + } + + ossim_uint32 tw = theTile->getWidth(); + ossim_uint32 th = theTile->getHeight(); + ossim_uint32 bands = theTile->getNumberOfBands(); + ossim_uint32 size = tw*th*bands; + if (traceDebug()) + { + cout << "ossimAtCorrRemapper::initialize DEBUG:" + << "\ntile width: " << tw + << "\ntile height: " << th + << "\nbands: " << bands + << "\nBuffer size: " << size << endl; + } + + theSurfaceReflectance = new double[size]; + + setInitializedFlag(true); + clearErrorStatus(); + } + else + { + setInitializedFlag(false); + setErrorStatus(); + }; + + verifyEnabled(); + + if (traceDebug()) + { + cout << "ossimAtCorrRemapper::initialize DEBUG:" + << *this + << endl; + } + +} + +bool ossimAtCorrRemapper::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + static const char MODULE[] = "ossimAtCorrRemapper::loadState()"; + + if (traceDebug()) CLOG << "entering..." << endl; + + if (!theTile || !theSurfaceReflectance) + { + cerr << MODULE << " ERROR:" + << "Not initialized..." << endl; + return false; + } + + ossim_uint32 bands = theTile->getNumberOfBands(); + + // Clear out the old values. + theMinPixelValue.clear(); + theMaxPixelValue.clear(); + theXaArray.clear(); + theXbArray.clear(); + theXcArray.clear(); + theBiasArray.clear(); + theGainArray.clear(); + theCalCoefArray.clear(); + theBandWidthArray.clear(); + + + // Now resize them. + + // Start with arbitrary big number. + theMinPixelValue.resize(bands, 1.0); + + // Start with arbitrary small number. + theMaxPixelValue.resize(bands, 0.0); + + + theXaArray.resize(bands, 1.0); + theXbArray.resize(bands, 1.0); + theXcArray.resize(bands, 1.0); + + theBiasArray.resize(bands, 0.0); + theGainArray.resize(bands, 1.0); + theCalCoefArray.resize(bands); + theBandWidthArray.resize(bands); + + for(ossim_uint32 band = 0; band < bands; ++band) + { + const char* lookup = NULL; + ossimString band_string = ".band"; + band_string += ossimString::toString(band+1); + + ossimString kw = AT_CORR_XA_KW; + kw += band_string; + lookup = kwl.find(prefix, kw.c_str()); + if (lookup) + { + theXaArray[band] = atof(lookup); + } + else + { + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nlookup failed for keyword: " << kw.c_str() << endl; + } + } + + kw = AT_CORR_XB_KW; + kw += band_string; + lookup = kwl.find(prefix, kw.c_str()); + if (lookup) + { + theXbArray[band] = atof(lookup); + } + else + { + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nlookup failed for keyword: " << kw.c_str() + << endl; + } + } + + kw = AT_CORR_XC_KW; + kw += band_string; + lookup = kwl.find(prefix, kw.c_str()); + if (lookup) + { + theXcArray[band] = atof(lookup); + } + else + { + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nlookup failed for keyword: " << kw.c_str() + << endl; + } + } + + if(theSensorType == "ls7ms") + { + kw = AT_CORR_BIAS_KW; + kw += band_string; + lookup = kwl.find(prefix, kw.c_str()); + if (lookup) + { + theBiasArray[band] = atof(lookup); + } + else + { + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nlookup failed for keyword: " << kw.c_str() + << endl; + } + } + + kw = AT_CORR_GAIN_KW; + kw += band_string; + lookup = kwl.find(prefix, kw.c_str()); + if (lookup) + { + theGainArray[band] = atof(lookup); + } + else + { + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nlookup failed for keyword: " << kw.c_str() + << endl; + } + } + } + + if(theSensorType == "qbms") + { + kw = AT_CORR_CALCOEF_KW; + kw += band_string; + lookup = kwl.find(prefix, kw.c_str()); + if (lookup) + { + theCalCoefArray[band] = atof(lookup); + } + else + { + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nlookup failed for keyword: " << kw.c_str() + << endl; + } + } + + kw = AT_CORR_BANDWIDTH_KW; + kw += band_string; + lookup = kwl.find(prefix, kw.c_str()); + if (lookup) + { + theBandWidthArray[band] = atof(lookup); + } + else + { + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nlookup failed for keyword: " << kw.c_str() + << endl; + } + } + } + if(theSensorType == "ikms") + { + kw = AT_CORR_CALCOEF_KW; + kw += band_string; + lookup = kwl.find(prefix, kw.c_str()); + if (lookup) + { + theCalCoefArray[band] = atof(lookup); + } + else + { + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nlookup failed for keyword: " << kw.c_str() + << endl; + } + } + + kw = AT_CORR_BANDWIDTH_KW; + kw += band_string; + lookup = kwl.find(prefix, kw.c_str()); + if (lookup) + { + theBandWidthArray[band] = atof(lookup); + } + else + { + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nlookup failed for keyword: " << kw.c_str() + << endl; + } + } + } + } + + verifyEnabled(); + + if (theEnableFlag) + { + //*** + // Call the base class to pick up the enable flag. Note that this + // can override the state set from verifyEnabled() method. + //*** + ossimString pref; + if (prefix) pref += prefix; + pref += "atmospheric_correction."; + + } + + if (traceDebug()) + { + CLOG << "DEBUG:" + << *this + << "returning..." + << endl; + } + + return true; +} + +void ossimAtCorrRemapper::verifyEnabled() +{ + // Check all the pointers... + if ( !theInputConnection || !theTile || + !theSurfaceReflectance ) + { + disableSource(); + return; + } + + ossim_uint32 bands = theTile->getNumberOfBands(); + if ( (theMinPixelValue.size() != bands) || + (theMaxPixelValue.size() != bands) || + (theXaArray.size() != bands) || + (theXbArray.size() != bands) || + (theXcArray.size() != bands) || + (theBiasArray.size() != bands) || + (theGainArray.size() != bands) || + (theCalCoefArray.size() != bands) || + (theBandWidthArray.size()!= bands)) + { + disableSource(); + return; + } + + enableSource(); +} + +ossimString ossimAtCorrRemapper::getShortName() const +{ + return ossimString("Atmospheric Correction Remapper"); +} + +vector<double> ossimAtCorrRemapper::getNormMinPixelValues() const +{ + return theMinPixelValue; +} + +vector<double> ossimAtCorrRemapper::getNormMaxPixelValues() const +{ + return theMaxPixelValue; +} + +void ossimAtCorrRemapper::getNormMinPixelValues(vector<double>& v) const +{ + v = theMinPixelValue; +} + +void ossimAtCorrRemapper::getNormMaxPixelValues(vector<double>& v) const +{ + v = theMaxPixelValue; +} + +const ossimString& ossimAtCorrRemapper::getSensorType() const +{ + return theSensorType; +} + +void ossimAtCorrRemapper::setSensorType(const ossimString& sensorType) +{ + theSensorType = sensorType; +} + +void ossimAtCorrRemapper::interpolate(const ossimDpt& pt, + int band, + double& a, + double& b, + double& c)const +{ + a = theXaArray[band]; + b = theXbArray[band]; + c = theXcArray[band]; +} + +ostream& ossimAtCorrRemapper::print(ostream& os) const +{ + os << "ossimAtCorrRemapper:" + << "\ntheEnableFlag: " << (theEnableFlag?"enabled":"disabled") + << endl; + + os << setprecision(15) << setiosflags(ios::fixed); + + ossim_uint32 band = 1; + vector<double>::const_iterator i = theMinPixelValue.begin(); + while (i != theMinPixelValue.end()) + { + os << "band[" << band << "] min: " << (*i) << endl; + ++i; + ++band; + } + + band = 1; + i = theMaxPixelValue.begin(); + while (i != theMaxPixelValue.end()) + { + os << "band[" << band << "] max: " << (*i) << endl; + ++i; + ++band; + } + + band = 1; + i = theXaArray.begin(); + while (i != theXaArray.end()) + { + os << "band[" << band << "] xa: " << (*i) << endl; + ++i; + ++band; + } + + band = 1; + i = theXbArray.begin(); + while (i != theXbArray.end()) + { + os << "band[" << band << "] xb: " << (*i) << endl; + ++i; + ++band; + } + + band = 1; + i = theXcArray.begin(); + while (i != theXcArray.end()) + { + os << "band[" << band << "] xc: " << (*i) << endl; + ++i; + ++band; + } + + if(theSensorType == "ls7ms") + { + band = 1; + i = theBiasArray.begin(); + while (i != theBiasArray.end()) + { + os << "band[" << band << "] bias: " << (*i) << endl; + ++i; + ++band; + } + + band = 1; + i = theGainArray.begin(); + while (i != theGainArray.end()) + { + os << "band[" << band << "] gain: " << (*i) << endl; + ++i; + ++band; + } + } + if(theSensorType == "qbms") + { + band = 1; + i = theCalCoefArray.begin(); + while (i != theCalCoefArray.end()) + { + os << "band[" << band << "] calcoef: " << (*i) << endl; + ++i; + ++band; + } + + band = 1; + i = theBandWidthArray.begin(); + while (i != theBandWidthArray.end()) + { + os << "band[" << band << "] bandwidth: " << (*i) << endl; + ++i; + ++band; + } + } + if(theSensorType == "ikms") + { + band = 1; + i = theCalCoefArray.begin(); + while (i != theCalCoefArray.end()) + { + os << "band[" << band << "] calcoef: " << (*i) << endl; + ++i; + ++band; + } + + } + return os; +} + +ostream& operator<<(ostream& os, const ossimAtCorrRemapper& hr) +{ + return hr.print(os); +} + + diff --git a/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAtCorrRemapper.h b/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAtCorrRemapper.h new file mode 100644 index 0000000000..91b70146d3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimAtCorrRemapper.h @@ -0,0 +1,88 @@ +//******************************************************************* +// Copyright (C) 2002 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Kathy Minear +// +// Description: +// Takes in DNs for any number of bands +// Converts DNs to Radiance at the satellite values Lsat +// Converts Lsat to Surface Reflectance values +// +//************************************************************************* +// $Id: ossimAtCorrRemapper.h,v 1.12 2005/02/11 15:07:30 dburken Exp $ +#ifndef ossimAtCorrRemapper_HEADER +#define ossimAtCorrRemapper_HEADER + +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +class ossimAtCorrRemapper : public ossimImageSourceFilter +{ +public: + + ossimAtCorrRemapper(ossimObject* owner = NULL, + ossimImageSource* inputSource = NULL, + const ossimString& sensorType = ""); + + virtual ~ossimAtCorrRemapper(); + + virtual ossimString getShortName() const; + + virtual void initialize(); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tile_rect, + ossim_uint32 resLevel=0); + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual ostream& print(ostream& os) const; + friend ostream& operator << (ostream& os, const ossimAtCorrRemapper& hr); + + vector<double> getNormMinPixelValues() const; + vector<double> getNormMaxPixelValues() const; + + void getNormMinPixelValues(vector<double>& v) const; + void getNormMaxPixelValues(vector<double>& v) const; + + const ossimString& getSensorType() const; + + void setSensorType(const ossimString& sensorType); + +protected: + + /*! + * Method to set unset the enable flag. + */ + void verifyEnabled(); + virtual void interpolate(const ossimDpt& pt, + int band, + double& a, + double& b, + double& c)const; + + ossimRefPtr<ossimImageData> theTile; + double* theSurfaceReflectance; + bool theUseInterpolationFlag; + vector<double> theMinPixelValue; + vector<double> theMaxPixelValue; + vector<double> theXaArray; + vector<double> theXbArray; + vector<double> theXcArray; + vector<double> theBiasArray; + vector<double> theGainArray; + vector<double> theCalCoefArray; + vector<double> theBandWidthArray; + ossimString theSensorType; + +TYPE_DATA +}; + +#endif /* #ifndef ossimAtCorrRemapper_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimGammaRemapper.cpp b/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimGammaRemapper.cpp new file mode 100644 index 0000000000..481f3cb61a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimGammaRemapper.cpp @@ -0,0 +1,433 @@ +//******************************************************************* +// Copyright (C) 2002 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Kathy Minear +// +// Description: Takes in DNs for any number of bands +// Converts DNs to Radiance at the satellite values Lsat +// Converts Lsat to Surface Reflectance values +// +//************************************************************************* +// $Id: ossimGammaRemapper.cpp,v 1.11 2005/05/09 12:39:38 dburken Exp $ + +#include <math.h> + +#include <imaging/atmospheric_correction/ossimGammaRemapper.h> +#include <imaging/atmospheric_correction/ossimAtCorrKeywords.h> +#include <base/common/ossimTrace.h> +#include <base/common/ossimKeywordNames.h> +#include <base/data_types/ossimMultiBandHistogram.h> +#include <base/data_types/ossimHistogram.h> +#include <imaging/factory/ossimImageDataFactory.h> + + +RTTI_DEF1(ossimGammaRemapper, "ossimGammaRemapper", ossimImageSourceFilter) + +static const double DEFAULT_GAMMA = 1.0; + + +static ossimTrace traceDebug("ossimGammaRemapper:debug"); + +ossimGammaRemapper::ossimGammaRemapper(ossimObject* owner) + : + ossimImageSourceFilter (owner), // base class + theTile (NULL), + theBuffer (NULL), + theMinPixelValue (0), + theMaxPixelValue (0), + theGamma (0), + theUserDisabledFlag (false) +{ + //*** + // Set the base class "theEnableFlag" to off since no adjustments have been + // made yet. + //*** + disableSource(); + + // Construction not complete. +} + + +ossimGammaRemapper::ossimGammaRemapper(ossimImageSource* inputSource) + : + ossimImageSourceFilter (NULL, inputSource), // base class + theTile (NULL), + theBuffer (NULL), + theMinPixelValue (0), + theMaxPixelValue (0), + theGamma (0), + theUserDisabledFlag (false) +{ + //*** + // Set the base class "theEnableFlag" to off since no adjustments have been + // made yet. + //*** + disableSource(); + + if (inputSource == NULL) + { + setErrorStatus(); + cerr << "ossimGammaRemapper::ossimGammaRemapper ERROR:" + << "\nNull input source passed to constructor!" << endl; + return; + } + + initialize(); +} + + +ossimGammaRemapper::ossimGammaRemapper(ossimObject* owner, + ossimImageSource* inputSource) + : + ossimImageSourceFilter (owner, inputSource), // base class + theTile (NULL), + theBuffer (NULL), + theMinPixelValue (0), + theMaxPixelValue (0), + theGamma (0) +{ + //*** + // Set the base class "theEnableFlag" to off since no adjustments have been + // made yet. + //*** + disableSource(); + + if (inputSource == NULL) + { + setErrorStatus(); + cerr << "ossimGammaRemapper::ossimGammaRemapper ERROR:" + << "\nNull input source passed to constructor!" << endl; + return; + } + + initialize(); +} + +ossimGammaRemapper::~ossimGammaRemapper() +{ + if (theBuffer) + { + delete [] theBuffer; + theBuffer = NULL; + } +} + +ossimRefPtr<ossimImageData> ossimGammaRemapper::getTile(const ossimIrect& tile_rect, + ossim_uint32 resLevel) +{ + if (!isInitialized()) + { + cerr << "ossimGammaRemapper::getTile ERROR:" + << "\nNot initialized!" + << endl; + return ossimRefPtr<ossimImageData>(); + } + + // Fetch tile from pointer from the input source. + ossimRefPtr<ossimImageData> inputTile = theInputConnection->getTile( + tile_rect, resLevel); + + if (!inputTile.valid()) // Just in case... + { + cerr << "ossimGammaRemapper::getTile ERROR:" + << "\nReceived null pointer to tile from input source!" + << "\nReturning blank tile." + << endl; + theTile->makeBlank(); + return theTile; + } + + // Get its status. + ossimDataObjectStatus tile_status = inputTile->getDataObjectStatus(); + + //--- + // Check for remap bypass: + //--- + if (!theEnableFlag || tile_status == OSSIM_NULL ||!theTile.valid() || + tile_status == OSSIM_EMPTY) + { + return inputTile; + } + + ossim_uint32 w = tile_rect.width(); + ossim_uint32 h = tile_rect.height(); + ossim_uint32 tw = theTile->getWidth(); + ossim_uint32 th = theTile->getHeight(); + ossim_uint32 bands = theTile->getNumberOfBands(); + + // Set the origin of the output tile. + theTile->setOrigin(tile_rect.ul()); + + if(w*h != tw*th) + { + theTile->setWidthHeight(w, h); + theTile->initialize(); + if(theBuffer) + { + delete [] theBuffer; + theBuffer = NULL; + } + } + + if(!theBuffer) + { + theBuffer = new double[w*h*bands]; + } + + // Copy the source tile into the buffer at the same time normalizing it. + inputTile->copyTileToNormalizedBuffer(theBuffer); + + // for each band, get the radiance value + + ossim_uint32 buffer_index = 0; + const double MP = theTile->getMinNormalizedPix(); // Minimum normalized pix. + const ossim_uint32 PPTB = theTile->getSizePerBand(); // Pixels Per Tile Band + + for (ossim_uint32 band=0; band<bands; ++band) + { + for (ossim_uint32 i=0; i<PPTB; ++i) + { + double p = theBuffer[buffer_index]; // input pixel + // double p = getPix(buffer_index); + + if (p) + { + // cout<<"p before: "<<p<<endl; + // Stretch it... + p = (p - theMinPixelValue[band]) / + (theMaxPixelValue[band] - + theMinPixelValue[band]); + + p = pow(p, theGamma[band]); + + + //*** + // Since it wasn't null to start with clip / clamp between minimum + // normalized pixel and one(max). + //*** + p = ( p > MP ? ( p < 1.0 ? p : 1.0) : MP ); + + theBuffer[buffer_index] = p; + } + else + { + theBuffer[buffer_index] = 0.0; + } + + ++buffer_index; + } + } + + // Copy the buffer to the output tile at the same time unnormalizing it. + theTile->copyNormalizedBufferToTile(theBuffer); + + // Set the status to that of the input tile. + theTile->setDataObjectStatus(tile_status); + + return theTile; +} + +void ossimGammaRemapper::initialize() +{ + if(theInputConnection) + { + theTile = ossimImageDataFactory::instance()->create(this, + theInputConnection); + theTile->initialize(); + + if(theBuffer) + { + delete []theBuffer; + theBuffer = NULL; + } + + ossim_uint32 tw = theTile->getWidth(); + ossim_uint32 th = theTile->getHeight(); + ossim_uint32 bands = theTile->getNumberOfBands(); + + theBuffer = new double[tw*th*bands]; + memset(theBuffer, '\0', tw*th*bands); + + setInitializedFlag(true); + clearErrorStatus(); + } + else + { + setInitializedFlag(false); + setErrorStatus(); + cerr << "ossimGammaRemapper::initialize ERROR:" + << "\nCannot call method when input connection is NULL!" + << endl; + }; + + verifyEnabled(); +} + +void ossimGammaRemapper::setMinMaxPixelValues(const vector<double>& v_min, + const vector<double>& v_max) +{ + theMinPixelValue = v_min; + theMaxPixelValue = v_max; + verifyEnabled(); +} + +void ossimGammaRemapper::verifyEnabled() +{ + // Check all the pointers... + if ( !theInputConnection || !theTile || !theBuffer ) + { + disableSource(); + return; + } + + ossim_uint32 bands = theTile->getNumberOfBands(); + if ( (theMinPixelValue.size() != bands) || + (theMaxPixelValue.size() != bands) ) + { + disableSource(); + return; + } + + if (theUserDisabledFlag == false) + { + enableSource(); + } + + if (traceDebug()) + { + cout << *this << endl; + } +} + +bool ossimGammaRemapper::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + //*** + // Call the base class to pick up the enable flag. Note that the + // verifyEnabled flag can override this. + //*** + ossimString pref; + if (prefix) pref += prefix; + pref += "gamma_remapper."; + + if (!theTile) + { + cerr << "ossimGammaRemapper::loadState: ERROR" + << "Not initialized yet!" << endl; + return false; + } + + //--- + // NOTE: + // base class seems to call initialize which in turn errors if you don't + // have a connection yet, so check for the enable keyword here... + // ossimSource::loadState(kwl, pref.c_str()); + //--- + cout << "pref: " << pref + << "kw: " << ossimKeywordNames::ENABLED_KW << endl; + + const char* lookup = kwl.find(pref, ossimKeywordNames::ENABLED_KW); + if(lookup) + { + theEnableFlag = ossimString(lookup).toBool(); + if (theEnableFlag == false) + { + // User want filter disabled... + theUserDisabledFlag = true; + } + } + + ossim_uint32 bands = theTile->getNumberOfBands(); + + theGamma.clear(); + theGamma.resize(bands, 1.0); + + for(ossim_uint32 band = 0; band < bands; ++band) + { + ossimString band_string = ".band"; + band_string += ossimString::toString(band+1); // Start at one. + + ossimString kw = GAMMA_REMAPPER_GAMMA_KW; + kw += band_string; + lookup = kwl.find(prefix, kw.c_str()); + if (lookup) + { + theGamma[band] = atof(lookup); + } + else + { + cout << "MODULE NOTICE:" + << "\nlookup failed for keyword: " << kw.c_str() + << "\nGamma set to " << DEFAULT_GAMMA << " for band: " + << (band+1) << endl; + theGamma[band] = DEFAULT_GAMMA; + } + } + + if (traceDebug()) + { + cout << "ossimGammaRemapper DEBUG:" + << *this + << endl; + } + + return true; +} + +ostream& ossimGammaRemapper::print(ostream& os) const +{ + os << setprecision(15) << setiosflags(ios::fixed) + << "ossimGammaRemapper:" + << "\ntheEnableFlag: " << (theEnableFlag?"enabled":"disabled") + << endl; + + ossim_uint32 band = 1; + vector<double>::const_iterator i = theMinPixelValue.begin(); + while (i != theMinPixelValue.end()) + { + os << "band[" << band << "] min: " << (*i) << endl; + ++i; + ++band; + } + + band = 1; + i = theMaxPixelValue.begin(); + while (i != theMaxPixelValue.end()) + { + os << "band[" << band << "] max: " << (*i) << endl; + ++i; + ++band; + } + + band = 1; + i = theGamma.begin(); + while (i != theGamma.end()) + { + os << "band[" << band << "] gamma: " << (*i) << endl; + ++i; + ++band; + } + + return os; +} + +void ossimGammaRemapper::enableSource() +{ + // Clear the flag... + theUserDisabledFlag = false; + ossimSource::enableSource(); +} + +ossimString ossimGammaRemapper::getShortName() const +{ + return ossimString("Gamma Remapper"); +} + +ostream& operator<<(ostream& os, const ossimGammaRemapper& hr) +{ + return hr.print(os); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimGammaRemapper.h b/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimGammaRemapper.h new file mode 100644 index 0000000000..d540518112 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/atmospheric_correction/ossimGammaRemapper.h @@ -0,0 +1,71 @@ +//******************************************************************* +// Copyright (C) 2002 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Kathy Minear +// +// Description: +// +// Gamma remapper. +// +//************************************************************************* +// $Id: ossimGammaRemapper.h,v 1.8 2005/02/11 15:07:30 dburken Exp $ +#ifndef ossimGammaRemapper_HEADER +#define ossimGammaRemapper_HEADER + +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +class ossimGammaRemapper : public ossimImageSourceFilter +{ +public: + + ossimGammaRemapper(ossimObject* owner=NULL); + ossimGammaRemapper(ossimImageSource* inputSource); + ossimGammaRemapper(ossimObject* owner, ossimImageSource* inputSource); + + virtual ~ossimGammaRemapper(); + + virtual ossimString getShortName()const; + + virtual void initialize(); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tile_rect, + ossim_uint32 resLevel=0); + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual ostream& print(ostream& os) const; + friend ostream& operator<< (ostream& os, const ossimGammaRemapper& hr); + + void setMinMaxPixelValues(const vector<double>& v_min, + const vector<double>& v_max); + + virtual void enableSource(); + +protected: + + /*! + * Method to set unset the enable flag. + */ + + void verifyEnabled(); + + ossimRefPtr<ossimImageData> theTile; + double* theBuffer; + vector<double> theMinPixelValue; + vector<double> theMaxPixelValue; + vector<double> theGamma; + bool theUserDisabledFlag; + + TYPE_DATA +}; + +#endif /* #ifndef ossimGammaRemapper_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/cache/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/cache/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/cache/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/imaging/cache/ossimAppFixedTileCache.cpp b/Utilities/OSSIM/ossim_core/imaging/cache/ossimAppFixedTileCache.cpp new file mode 100644 index 0000000000..da3db0ceca --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/cache/ossimAppFixedTileCache.cpp @@ -0,0 +1,383 @@ +//****************************************************************** +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: This file contains the Application cache algorithm +// +//*********************************** +// $Id: ossimAppFixedTileCache.cpp,v 1.9 2005/08/17 19:18:12 gpotts Exp $ +#include <algorithm> +#include <sstream> +#include <imaging/cache/ossimAppFixedTileCache.h> +#include <imaging/cache/ossimFixedTileCache.h> +#include <base/common/ossimPreferences.h> +#include <base/common/ossimCommon.h> +#include <base/common/ossimTrace.h> + +ossimAppFixedTileCache* ossimAppFixedTileCache::theInstance = NULL; +ossimAppFixedTileCache::ossimAppFixedCacheId ossimAppFixedTileCache::theUniqueAppIdCounter = 0; +const ossim_uint32 ossimAppFixedTileCache::DEFAULT_SIZE = 1024*1024*80; + +static const ossimTrace traceDebug("ossimAppFixedTileCache:debug"); +std::ostream& operator <<(std::ostream& out, const ossimAppFixedTileCache& rhs) +{ + std::map<ossimAppFixedTileCache::ossimAppFixedCacheId, ossimFixedTileCache*>::const_iterator iter = rhs.theAppCacheMap.begin(); + + if(iter == rhs.theAppCacheMap.end()) + { + cout << "***** APP CACHE EMPTY *****" << endl; + } + else + { + while(iter != rhs.theAppCacheMap.end()) + { + out << "Cache id = "<< (*iter).first << " size = " << (*iter).second->getCacheSize() << endl; + ++iter; + } + } + + return out; +} + + +ossimAppFixedTileCache::ossimAppFixedTileCache() +{ + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimAppFixedTileCache::ossimAppFixedTileCache() DEBUG: entered ..." << std::endl; + } + theInstance = this; + theTileSize = ossimIpt(64, 64); + theCurrentCacheSize = 0; + + ossimGetDefaultTileSize(theTileSize); + + ossim_uint32 cacheSize = ossimString(ossimPreferences::instance()->findPreference("cache_size")).toUInt32()*(1024*1024); + const char* tileSize = ossimPreferences::instance()->findPreference("tile_size"); + if(tileSize) + { + std::stringstream in(tileSize); + in >> theTileSize.x >> theTileSize.y; + if(theTileSize.x < 1) theTileSize.x = 64; + if(theTileSize.y < 1) theTileSize.y = 64; + } + if(cacheSize) + { + setMaxCacheSize(cacheSize); + } + else + { + setMaxCacheSize(DEFAULT_SIZE); + } + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG: cache tile size = " << theTileSize << std::endl + << "Cache size = " << cacheSize << " bytes" << std::endl; + } + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimAppFixedTileCache::ossimAppFixedTileCache() DEBUG: leaving ..." << std::endl; + } +} + +ossimAppFixedTileCache::~ossimAppFixedTileCache() +{ + deleteAll(); +} + +ossimAppFixedTileCache *ossimAppFixedTileCache::instance(ossim_uint32 maxSize) +{ + if(!theInstance) + { + theInstance = new ossimAppFixedTileCache; + if(maxSize) + { + theInstance->setMaxCacheSize(maxSize); + } + } + return theInstance; +} + +void ossimAppFixedTileCache::setMaxCacheSize(ossim_uint32 cacheSize) +{ + theMaxGlobalCacheSize = cacheSize; + theMaxCacheSize = cacheSize; + // theMaxCacheSize = (ossim_uint32)(theMaxGlobalCacheSize*.2); +} + +void ossimAppFixedTileCache::flush() +{ + std::map<ossimAppFixedCacheId, ossimFixedTileCache*>::iterator currentIter = theAppCacheMap.begin(); + + while(currentIter != theAppCacheMap.end()) + { + (*currentIter).second->flush(); + ++currentIter; + } + theCurrentCacheSize = 0; +} + +void ossimAppFixedTileCache::flush(ossimAppFixedCacheId cacheId) +{ + ossimFixedTileCache* cache = getCache(cacheId); + + if(cache) + { + theCurrentCacheSize -= cache->getCacheSize(); + cache->flush(); + } +} + +void ossimAppFixedTileCache::deleteCache(ossimAppFixedCacheId cacheId) +{ + ossimFixedTileCache* cache = getCache(cacheId); + std::map<ossimAppFixedCacheId, ossimFixedTileCache*>::iterator iter = theAppCacheMap.find(cacheId); + + if(cache) + { + theAppCacheMap.erase(iter); + theCurrentCacheSize -= cache->getCacheSize(); + delete cache; + } +} + +ossimAppFixedTileCache::ossimAppFixedCacheId ossimAppFixedTileCache::newTileCache(const ossimIrect& tileBoundaryRect, + const ossimIpt& tileSize) +{ + ossimAppFixedCacheId result = theUniqueAppIdCounter; + ossimFixedTileCache* newCache = new ossimFixedTileCache; + if(tileSize.x == 0 || + tileSize.y == 0) + { + newCache->setRect(tileBoundaryRect, theTileSize); + } + else + { + newCache->setRect(tileBoundaryRect, tileSize); + } + + theAppCacheMap.insert(std::make_pair(result, newCache)); + ++theUniqueAppIdCounter; + + return result; +} + +ossimAppFixedTileCache::ossimAppFixedCacheId ossimAppFixedTileCache::newTileCache() +{ + ossimAppFixedCacheId result = theUniqueAppIdCounter; + ossimFixedTileCache* newCache = new ossimFixedTileCache; + + theAppCacheMap.insert(std::make_pair(result, newCache)); + ++theUniqueAppIdCounter; + + return result; + +} + +void ossimAppFixedTileCache::setRect(ossimAppFixedCacheId cacheId, + const ossimIrect& boundaryTileRect) +{ + ossimFixedTileCache* cache = getCache(cacheId); + if(cache) + { + ossim_uint32 cacheSize = cache->getCacheSize(); + cache->setRect(boundaryTileRect, theTileSize); + theCurrentCacheSize += (cache->getCacheSize() - cacheSize); + } +} + +ossimRefPtr<ossimImageData> ossimAppFixedTileCache::getTile( + ossimAppFixedCacheId cacheId, + const ossimIpt& origin) +{ + ossimRefPtr<ossimImageData> result = NULL; + ossimFixedTileCache* cache = getCache(cacheId); + if(cache) + { + result = cache->getTile(origin); + } + + return result; +} + + +ossimRefPtr<ossimImageData> ossimAppFixedTileCache::addTile( + ossimAppFixedCacheId cacheId, + ossimRefPtr<ossimImageData> data) +{ + ossimRefPtr<ossimImageData> result = NULL; + ossimFixedTileCache *aCache = this->getCache(cacheId); + if(!aCache) + { + return result; + } + long dataSize = data->getDataSizeInBytes(); + + if( (theCurrentCacheSize+dataSize) > theMaxGlobalCacheSize) + { + shrinkGlobalCacheSize((ossim_int32)(theMaxGlobalCacheSize*0.1)); + } + + ossim_uint32 cacheSize = aCache->getCacheSize(); + if(cacheSize > theMaxCacheSize) + { +// shrinkCacheSize(aCache, +// (ossim_int32)(aCache->getCacheSize()*.1)); + shrinkCacheSize(aCache, + (ossim_int32)(1024*1024)); + } + cacheSize = aCache->getCacheSize(); + aCache->addTile(data); + theCurrentCacheSize += (aCache->getCacheSize() - cacheSize); + + return result; +} + +void ossimAppFixedTileCache::deleteAll() +{ + std::map<ossimAppFixedCacheId, ossimFixedTileCache*>::iterator iter = theAppCacheMap.begin(); + theCurrentCacheSize = 0; + + while(iter != theAppCacheMap.end()) + { + if((*iter).second) + { + delete (*iter).second; + } + + ++iter; + } + theAppCacheMap.clear(); +} + +ossimRefPtr<ossimImageData> ossimAppFixedTileCache::removeTile( + ossimAppFixedCacheId cacheId, + const ossimIpt& origin) +{ + ossimRefPtr<ossimImageData> result = NULL; + + ossimFixedTileCache* cache = getCache(cacheId); + if(cache) + { + ossim_uint32 cacheSize = cache->getCacheSize(); + result = cache->removeTile(origin); + theCurrentCacheSize += (cache->getCacheSize() - cacheSize); + } + + return result; +} + +void ossimAppFixedTileCache::deleteTile(ossimAppFixedCacheId cacheId, + const ossimIpt& origin) +{ + ossimFixedTileCache* cache = getCache(cacheId); + if(cache) + { + ossim_uint32 cacheSize = cache->getCacheSize(); + cache->deleteTile(origin); + theCurrentCacheSize += (cache->getCacheSize() - cacheSize); + } +} + +ossimFixedTileCache* ossimAppFixedTileCache::getCache(ossimAppFixedCacheId cacheId) +{ + std::map<ossimAppFixedCacheId, ossimFixedTileCache*>::iterator currentIter = theAppCacheMap.find(cacheId); + ossimFixedTileCache* result = (ossimFixedTileCache*)NULL; + + if(currentIter != theAppCacheMap.end()) + { + result = (*currentIter).second; + } + + return result; +} + +void ossimAppFixedTileCache::shrinkGlobalCacheSize(ossim_int32 byteCount) +{ + if(static_cast<ossim_uint32>(byteCount) >= theCurrentCacheSize) + { + flush(); + } + else + { + while(byteCount > 0) + { + std::map<ossimAppFixedCacheId, ossimFixedTileCache*>::iterator iter = theAppCacheMap.begin(); + while( (iter != theAppCacheMap.end())&&(byteCount>0)) + { + ossimFixedTileCache* cache = getCache((*iter).first); + if(cache) + { + ossim_uint32 before = cache->getCacheSize(); + cache->deleteTile(); + ossim_uint32 after = cache->getCacheSize(); + ossim_uint32 delta = (before - after); + byteCount -= delta; + theCurrentCacheSize -= (delta); + ++iter; + } + } + } + } +} + +void ossimAppFixedTileCache::shrinkCacheSize(ossimAppFixedCacheId id, + ossim_int32 byteCount) +{ + ossimFixedTileCache* cache = getCache(id); + + if(cache) + { + shrinkCacheSize(cache, byteCount); + } +} + +void ossimAppFixedTileCache::shrinkCacheSize(ossimFixedTileCache* cache, + ossim_int32 byteCount) +{ + if(cache) + { + ossim_int32 cacheSize = cache->getCacheSize(); + if(cacheSize <= byteCount) + { + cache->flush(); + } + else + { + while(byteCount > 0) + { + ossim_uint32 before = cache->getCacheSize(); + cache->deleteTile(); + ossim_uint32 after = cache->getCacheSize(); + ossim_uint32 delta = ossimAbs((int)(before - after)); + if(delta) + { + byteCount -= delta; + theCurrentCacheSize -= (delta); + } + else + { + byteCount = 0; + } + } + } + } +} + +const ossimIpt& ossimAppFixedTileCache::getTileSize(ossimAppFixedCacheId cacheId) +{ + ossimFixedTileCache* cache = getCache(cacheId); + + if(cache) + { + return cache->getTileSize(); + } + + return theTileSize; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/cache/ossimAppFixedTileCache.h b/Utilities/OSSIM/ossim_core/imaging/cache/ossimAppFixedTileCache.h new file mode 100644 index 0000000000..f4a83190b8 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/cache/ossimAppFixedTileCache.h @@ -0,0 +1,118 @@ +//****************************************************************** +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: This file contains the Application cache algorithm +// +//*********************************** +// $Id: ossimAppFixedTileCache.h,v 1.6 2005/08/17 19:18:12 gpotts Exp $ +#ifndef ossimAppFixedTileCache_HEADER +#define ossimAppFixedTileCache_HEADER +#include <map> +#include <list> +#include <iostream> +#include <base/common/ossimConstants.h> +#include <base/common/ossimRefPtr.h> +#include <base/data_types/ossimIrect.h> + + +class ossimFixedTileCache; +class ossimImageData; + +class ossimAppFixedTileCache +{ +public: + friend std::ostream& operator <<(std::ostream& out, + const ossimAppFixedTileCache& rhs); + static const ossim_uint32 DEFAULT_SIZE; + typedef ossim_int32 ossimAppFixedCacheId; + static ossimAppFixedTileCache *instance(ossim_uint32 maxSize = 0); + virtual ~ossimAppFixedTileCache(); + + /*! + * Will flush all cache registered + */ + virtual void flush(); + virtual void flush(ossimAppFixedCacheId cacheId); + virtual void deleteCache(ossimAppFixedCacheId cacheId); + /*! + * Will create a new Tile cache for this application if the tile size is 0,0 it will + * use the default tile size. Will + * return 0 if not successful. + */ + ossimAppFixedCacheId newTileCache(const ossimIrect& tileBoundaryRect, + const ossimIpt& tileSize=ossimIpt(0,0)); + ossimAppFixedCacheId newTileCache(); + + virtual void setRect(ossimAppFixedCacheId cacheId, + const ossimIrect& boundaryTileRect); + + ossimRefPtr<ossimImageData> getTile(ossimAppFixedCacheId cacheId, + const ossimIpt& origin); + ossimRefPtr<ossimImageData> addTile(ossimAppFixedCacheId cacheId, + ossimRefPtr<ossimImageData> data); + + ossimRefPtr<ossimImageData> removeTile(ossimAppFixedCacheId cacheId, + const ossimIpt& origin); + void deleteTile(ossimAppFixedCacheId cacheId, + const ossimIpt& origin); + + const ossimIpt& getTileSize(ossimAppFixedCacheId cacheId); + + virtual void setMaxCacheSize(ossim_uint32 cacheSize); + +protected: +// struct ossimAppFixedCacheTileInfo +// { +// public: +// ossimAppFixedCacheTileInfo(ossimAppFixedCacheId appId, +// const ossimIpt& origin) +// :theAppCacheId(appId), +// theOrigin(origin) +// {} +// ossimAppFixedCacheId theAppCacheId; +// ossimIpt theOrigin; + +// bool operator ==(const ossimAppFixedCacheTileInfo &rhs)const +// { +// return (theAppCacheId == rhs.theAppCacheId && +// theOrigin == rhs.theOrigin); +// } +// }; + + ossimAppFixedTileCache(); + + ossimFixedTileCache* getCache(ossimAppFixedCacheId cacheId); + + void shrinkGlobalCacheSize(ossim_int32 byteCount); + void shrinkCacheSize(ossimAppFixedCacheId id, + ossim_int32 byteCount); + void shrinkCacheSize(ossimFixedTileCache* cache, + ossim_int32 byteCount); + void deleteAll(); + + static ossimAppFixedTileCache *theInstance; + + /*! + * Will hold the current unique Application id. + */ + static ossimAppFixedCacheId theUniqueAppIdCounter; + ossimIpt theTileSize; + ossim_uint32 theMaxCacheSize; + ossim_uint32 theMaxGlobalCacheSize; + ossim_uint32 theCurrentCacheSize; + + std::map<ossimAppFixedCacheId, ossimFixedTileCache*> theAppCacheMap; + + /*! + * Is used in an Least recently used algorithm + */ +// std::list<ossimAppFixedCacheTileInfo> theUsedQueue; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/cache/ossimAppTileCache.cpp b/Utilities/OSSIM/ossim_core/imaging/cache/ossimAppTileCache.cpp new file mode 100644 index 0000000000..295e0f99d9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/cache/ossimAppTileCache.cpp @@ -0,0 +1,307 @@ +//****************************************************************** +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: This file contains the Application cache algorithm +// +//*********************************** +// $Id: ossimAppTileCache.cpp,v 1.11 2005/03/03 21:59:16 dburken Exp $ + +#include <imaging/cache/ossimAppTileCache.h> +#include <imaging/cache/ossimTileCache.h> +#include <base/common/ossimDataObject.h> +#include <base/common/ossimPreferences.h> + +ossimAppTileCache* ossimAppTileCache::theInstance = NULL; + +// we will need to grab this from the preferences +const ossim_uint32 ossimAppTileCache::DEFAULT_SIZE = 80*1024*1024; +const ossim_uint32 ossimAppTileCache::DEFAULT_BUCKET_SIZE = 293; +ossimAppTileCache::ossimAppCacheId ossimAppTileCache::theUniqueAppIdCounter = 1; + +ossimAppTileCache *ossimAppTileCache::instance(ossim_uint32 maxSize) +{ + cout << "HERE---------------------MAXSIZE = " << maxSize << std::endl; + if(!theInstance) + { + if(maxSize < 1) + { + ossimString cacheSize = ossimPreferences::instance()->findPreference("cache_size"); + if(cacheSize!="") + { + maxSize = cacheSize.toUInt32()*1024*1024; + } + else + { + maxSize = DEFAULT_SIZE; + } + cout << "Setting SIZE----------------------- " << maxSize << std::endl; + } + theInstance = new ossimAppTileCache(maxSize); + } + + return theInstance; +} + +ossimAppTileCache::~ossimAppTileCache() +{ + deleteAll(); +} + +ossimAppTileCache::ossimAppCacheId ossimAppTileCache::newTileCache(ossim_uint32 bucketSize) +{ + ossimTileCache *aCache = NULL; + ossimAppCacheId result = 0; + + aCache = new ossimTileCache(bucketSize); + + if(aCache) + { + theAppCache.insert(make_pair(theUniqueAppIdCounter, aCache)); + result = theUniqueAppIdCounter; + ++theUniqueAppIdCounter; + } + + return result; +} + +/*! + * Will retrieve a tile from the cache. + */ +ossimDataObject *ossimAppTileCache::get(ossimAppCacheId id, + const ossimDpt3d &origin, + ossim_uint32 resLevel) +{ + ossimDataObject* result = NULL; + if(id>0) + { + ossimTileCache *aCache = this->get(id); + if(aCache) + { + result = aCache->get(origin, + resLevel); + if(result) + { + adjustQueue(id, origin, resLevel); + } + } + } + + return result; +} + +ossimDataObject* ossimAppTileCache::removeTile(ossimAppCacheId id, + const ossimDpt3d &origin, + unsigned long resLevel) +{ + ossimDataObject *result = NULL; + if(id>0) + { + ossimTileCache *aCache = this->get(id); + if(aCache) + { + // remove from cache + result = aCache->remove(origin, + resLevel); + // adjust the byte count + if(result) + { + theCurrentCacheSize -= result->getDataSizeInBytes(); + } + removeTileFromQueue(id, origin, resLevel); + } + } + + return result; +} + +ossimDataObject* ossimAppTileCache::insert(ossimAppCacheId appId, + const ossimDpt3d &origin, + const ossimDataObject* data, + ossim_uint32 resLevel) +{ + static char *MODULE = "ossimAppTileCache::insert"; + ossimDataObject *result = NULL; + + // find the cache and if it's not there then return NULL + ossimTileCache *aCache = this->get(appId); + if(!aCache) + { + return result; + } + + ossimDataObject *tileToInsert = NULL; + long dataSize = data->getDataSizeInBytes(); + + if( (theCurrentCacheSize+dataSize) > theMaxCacheSize) + { + ossimDataObject *tempTile = NULL; + do + { + tempTile = removeTile(); + + if(tempTile) + { + delete tempTile; + tempTile = NULL; + } + }while((theCurrentCacheSize+dataSize) > theMaxCacheSize); + } + + if(data) + { + tileToInsert = (ossimDataObject*)data->dup(); + + result = aCache->insert(origin, + tileToInsert, + resLevel); + if(!result) + { + cout << MODULE << " ERROR: can't insert and should not happen" + << endl; + + delete tileToInsert; + } + else + { + theCurrentCacheSize += dataSize; + theUsedQueue.push_back(ossimAppCacheTileInfo(appId, + origin, + resLevel)); + } + } + + return result; +} + + +ossimTileCache* ossimAppTileCache::get(ossimAppCacheId id) +{ + ossimTileCache *result=NULL; + + AppIdIterator anIterator = theAppCache.find(id); + + if(anIterator != theAppCache.end()) + { + result = (*anIterator).second; + } + + return result; +} + +void ossimAppTileCache::deleteCache(ossimAppCacheId appId) +{ + // first delete the cache + AppIdIterator anIterator = theAppCache.find(appId); + if(anIterator != theAppCache.end()) + { + ossimTileCache *aCache = (*anIterator).second; + theCurrentCacheSize -= aCache->sizeInBytes(); + + delete aCache; + + theAppCache.erase(anIterator); + } + // now delete all occurences of the appCacheId in the queue + // used for LRU algorithm. + deleteAppCacheFromQueue(appId); +} + +void ossimAppTileCache::deleteAll() +{ + AppIdIterator iter = theAppCache.begin(); + + while(iter != theAppCache.end()) + { + delete (*iter).second; + ++iter; + } + + theAppCache.clear(); +} + +void ossimAppTileCache::removeTileFromQueue(ossimAppCacheId appId, + const ossimDpt3d &origin, + ossim_uint32 resLevel) +{ + list<ossimAppCacheTileInfo>::iterator anIterator; + + anIterator = theUsedQueue.begin(); + while(anIterator != theUsedQueue.end()) + { + if( ((*anIterator).theAppCacheId == appId) && + ((*anIterator).theOrigin == origin)&& + ((*anIterator).theResLevel == resLevel)) + { + theUsedQueue.erase(anIterator); + return; + } + else + { + ++anIterator; + } + } +} + +void ossimAppTileCache::deleteAppCacheFromQueue(ossimAppCacheId appId) +{ + list<ossimAppCacheTileInfo>::iterator anIterator; + + anIterator = theUsedQueue.begin(); + while(anIterator != theUsedQueue.end()) + { + if( (*anIterator).theAppCacheId == appId) + { + anIterator = theUsedQueue.erase(anIterator); + } + else + { + ++anIterator; + } + } +} + +ossimDataObject* ossimAppTileCache::removeTile() +{ + ossimDataObject *result = NULL; + if(!theUsedQueue.empty()) + { + ossimAppCacheTileInfo &info = *(theUsedQueue.begin()); + + ossimTileCache *aCache = get(info.theAppCacheId); + if(aCache) + { + result = aCache->remove(info.theOrigin, + info.theResLevel); + theCurrentCacheSize -= result->getDataSizeInBytes(); + } + theUsedQueue.erase(theUsedQueue.begin()); + } + + return result; +} + +void ossimAppTileCache::adjustQueue(ossimAppCacheId id, + const ossimDpt3d &origin, + ossim_uint32 resLevel) +{ + list<ossimAppCacheTileInfo>::iterator anIterator = theUsedQueue.begin(); + ossimAppCacheTileInfo info(id, origin, resLevel); + + while(anIterator != theUsedQueue.end()) + { + + if((*anIterator) == info) + { + theUsedQueue.erase(anIterator); + theUsedQueue.push_back(info); + return; + } + ++anIterator; + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/cache/ossimAppTileCache.h b/Utilities/OSSIM/ossim_core/imaging/cache/ossimAppTileCache.h new file mode 100644 index 0000000000..fa88b5c883 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/cache/ossimAppTileCache.h @@ -0,0 +1,169 @@ +//****************************************************************** +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: This file contains the Application cache algorithm +// +//*********************************** +// $Id: ossimAppTileCache.h,v 1.7 2005/03/03 21:59:16 dburken Exp $ +#ifndef ossimAppTileCache_HEADER +#define ossimAppTileCache_HEADER +#include <map> +#include <list> +using namespace std; + +#include <base/common/ossimConstants.h> +#include <base/data_types/ossimDpt3d.h> +// class ossimTile; +class ossimTileCache; +class ossimDataObject; + +class ossimAppTileCache +{ +public: + static const ossim_uint32 DEFAULT_SIZE; + + static const ossim_uint32 DEFAULT_BUCKET_SIZE; + + typedef ossim_int32 ossimAppCacheId; + typedef ossim_int32 ossimTileId; + typedef map<ossimAppCacheId, ossimTileCache*>::iterator AppIdIterator; + + ~ossimAppTileCache(); + + /*! + * We will force a singleton on this class. + */ + static ossimAppTileCache *instance(ossim_uint32 maxSize = 0); + + /*! + * Will create a new Tile cache for this application. Will + * return 0 if not successful. + */ + ossimAppCacheId newTileCache(ossim_uint32 bucketSize=DEFAULT_BUCKET_SIZE); + + /*! + * Will retrieve a tile from the cache. Will return NULL + * if not found. + */ + ossimDataObject *get(ossimAppCacheId id, + const ossimDpt3d &origin, + ossim_uint32 resLevel=0); + + /*! + * Will remove a tile completly from the cache. The + * returned tile is no longer owned by the cache. + */ + ossimDataObject* removeTile(ossimAppCacheId id, + const ossimDpt3d &origin, + unsigned long resLevel); + /*! + * Will insert a tile into the cache. + */ + ossimDataObject* insert(ossimAppCacheId id, + const ossimDpt3d &origin, + const ossimDataObject* data, + ossim_uint32 resLevel=0); + + /*! + * This will delete the specified cache. The LRU queue will + * be updated accordingly + */ + void deleteCache(ossimAppCacheId appId); +protected: + + struct ossimAppCacheTileInfo + { + public: + ossimAppCacheTileInfo(ossimAppCacheId appId, + const ossimDpt3d& origin, + ossim_uint32 resLevel) + :theAppCacheId(appId), + theOrigin(origin), + theResLevel(resLevel) + {} + ossimAppCacheId theAppCacheId; + ossimDpt3d theOrigin; + ossim_uint32 theResLevel; + + bool operator ==(const ossimAppCacheTileInfo &rhs) + { + return (theAppCacheId == rhs.theAppCacheId && + theOrigin == rhs.theOrigin && + theResLevel == rhs.theResLevel); + } + + }; + + ossimAppTileCache(ossim_uint32 maxSize = DEFAULT_SIZE) + : + theMaxCacheSize(maxSize), + theCurrentCacheSize(0) + {} + + void deleteAll(); + /*! + * Used to get access to the App cache. + */ + ossimTileCache* get(ossimAppCacheId id); + + /*! + * will remove all occurances of the appId from the + * queue + */ + void deleteAppCacheFromQueue(ossimAppCacheId appId); + + /*! + * Will remove a single instance of a tile from the queue. + */ + void removeTileFromQueue(ossimAppCacheId appId, + const ossimDpt3d &origin, + ossim_uint32 resLevel); + + void adjustQueue(ossimAppCacheId id, + const ossimDpt3d &origin, + ossim_uint32 resLevel); + /*! + * will pop the queue and remove that tile from its cache + * and return it to the caller. This is used by the insert + * when the max cache size is exceeded. + */ + ossimDataObject* removeTile(); + + + static ossimAppTileCache *theInstance; + /*! + * Will hold the current unique Application id. + */ + static ossimAppCacheId theUniqueAppIdCounter; + /*! + * Will hold the list of application caches + */ + map<ossimAppCacheId, ossimTileCache*> theAppCache; + + /*! + * Is the maximum size of the cache. + */ + ossim_uint32 theMaxGlobalCacheSize; + ossim_uint32 theMaxCacheSize; + + + /*! + * This holds the current cache size. + */ + ossim_uint32 theCurrentCacheSize; + + + /*! + * Is used in an Least recently used algorithm + */ + list<ossimAppCacheTileInfo> theUsedQueue; + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/cache/ossimFixedTileCache.cpp b/Utilities/OSSIM/ossim_core/imaging/cache/ossimFixedTileCache.cpp new file mode 100644 index 0000000000..3c3a94a5b5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/cache/ossimFixedTileCache.cpp @@ -0,0 +1,282 @@ +//****************************************************************** +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: This file contains the Application cache algorithm +// +//*********************************** +// $Id: ossimFixedTileCache.cpp,v 1.18 2005/08/17 19:18:12 gpotts Exp $ +#include <imaging/cache/ossimFixedTileCache.h> +#include <algorithm> + +ossimFixedTileCache::ossimFixedTileCache() +{ + ossimIrect tempRect; + tempRect.makeNan(); + + setRect(tempRect); + theCacheSize = 0; + theMaxCacheSize = 0; + theUseLruFlag = true; +} + +ossimFixedTileCache::~ossimFixedTileCache() +{ + flush(); +} + +void ossimFixedTileCache::setRect(const ossimIrect& rect) +{ + ossimGetDefaultTileSize(theTileSize); + theTileBoundaryRect = rect; + theTileBoundaryRect.stretchToTileBoundary(theTileSize); + theBoundaryWidthHeight.x = theTileBoundaryRect.width(); + theBoundaryWidthHeight.y = theTileBoundaryRect.height(); + theTilesHorizontal = theBoundaryWidthHeight.x/theTileSize.x; + theTilesVertical = theBoundaryWidthHeight.y/theTileSize.y; + flush(); +} + +void ossimFixedTileCache::setRect(const ossimIrect& rect, + const ossimIpt& tileSize) +{ + theTileBoundaryRect = rect; + theTileSize = tileSize; + theTileBoundaryRect.stretchToTileBoundary(theTileSize); + theBoundaryWidthHeight.x = theTileBoundaryRect.width(); + theBoundaryWidthHeight.y = theTileBoundaryRect.height(); + theTilesHorizontal = theBoundaryWidthHeight.x/theTileSize.x; + theTilesVertical = theBoundaryWidthHeight.y/theTileSize.y; + flush(); +} + + +void ossimFixedTileCache::keepTilesWithinRect(const ossimIrect& rect) +{ + std::map<ossim_int32, ossimFixedTileCacheInfo>::iterator tileIter = theTileMap.begin(); + + while(tileIter != theTileMap.end()) + { + ossimIrect tileRect = (*tileIter).second.theTile->getImageRectangle(); + if(!tileRect.intersects(rect)) + { + eraseFromLru(computeId((*tileIter).second.theTile->getOrigin())); + theCacheSize -= (*tileIter).second.theTile->getDataSizeInBytes(); + (*tileIter).second.theTile = NULL; + theTileMap.erase(tileIter); + } + ++tileIter; + } +} + +ossimRefPtr<ossimImageData> ossimFixedTileCache::addTile( + ossimRefPtr<ossimImageData> imageData) +{ + ossimRefPtr<ossimImageData> result = NULL; + if(!imageData.valid()) + { + return result; + } + if(!imageData->getBuf()) + { + return result; + } + + ossim_int32 id = computeId(imageData->getOrigin()); + if(id < 0) + { + return result; + } + + std::map<ossim_int32, ossimFixedTileCacheInfo>::iterator tileIter = + theTileMap.find(id); + + if(tileIter==theTileMap.end()) + { + result = (ossimImageData*)imageData->dup(); + ossimFixedTileCacheInfo cacheInfo(result, id); + + theCacheSize += imageData->getDataSizeInBytes(); + theTileMap.insert(make_pair(id, cacheInfo)); + if(theUseLruFlag) + { + theLruQueue.push_back(id); + } + } + + return result; +} + +ossimRefPtr<ossimImageData> ossimFixedTileCache::getTile(ossim_int32 id) +{ + ossimRefPtr<ossimImageData> result = NULL; + + std::map<ossim_int32, ossimFixedTileCacheInfo>::iterator tileIter = + theTileMap.find(id); + if(tileIter!=theTileMap.end()) + { + result = (*tileIter).second.theTile; + adjustLru(id); + } + + return result; +} + +ossimIpt ossimFixedTileCache::getTileOrigin(ossim_int32 tileId) +{ + ossimIpt result; + result.makeNan(); + + if(tileId < 0) + { + return result; + } + ossim_int32 ty = (tileId/theTilesHorizontal); + ossim_int32 tx = (tileId%theTilesVertical); + + ossimIpt ul = theTileBoundaryRect.ul(); + + result = ossimIpt(ul.x + tx*theTileSize.x, ul.y + ty*theTileSize.y); + + return result; +} + +ossim_int32 ossimFixedTileCache::computeId(const ossimIpt& tileOrigin)const +{ + ossimIpt idDiff = tileOrigin - theTileBoundaryRect.ul(); + + if((idDiff.x < 0)|| + (idDiff.y < 0)|| + (idDiff.x >= theBoundaryWidthHeight.x)|| + (idDiff.y >= theBoundaryWidthHeight.y)) + { + return -1; + } + ossim_uint32 y = idDiff.y/theTileSize.y; + y*=theTilesHorizontal; + + ossim_uint32 x = idDiff.x/theTileSize.x; + + + return (y + x); +} + +void ossimFixedTileCache::deleteTile(ossim_int32 tileId) +{ + std::map<ossim_int32, ossimFixedTileCacheInfo>::iterator tileIter = + theTileMap.find(tileId); + + if(tileIter != theTileMap.end()) + { + if((*tileIter).second.theTile.valid()) + { + theCacheSize -= (*tileIter).second.theTile->getDataSizeInBytes(); + (*tileIter).second.theTile = NULL; + } + theTileMap.erase(tileIter); + eraseFromLru(tileId); + } +} + +ossimRefPtr<ossimImageData> ossimFixedTileCache::removeTile(ossim_int32 tileId) +{ + ossimRefPtr<ossimImageData> result = NULL; + + std::map<ossim_int32, ossimFixedTileCacheInfo>::iterator tileIter = + theTileMap.find(tileId); + + if(tileIter != theTileMap.end()) + { + theCacheSize -= (*tileIter).second.theTile->getDataSizeInBytes(); + if((*tileIter).second.theTile.valid()) + { + result = (*tileIter).second.theTile; + } + theTileMap.erase(tileIter); + eraseFromLru(tileId); + } + + return result; +} + +void ossimFixedTileCache::flush() +{ + std::map<ossim_int32, ossimFixedTileCacheInfo>::iterator tileIter = + theTileMap.begin(); + + while(tileIter != theTileMap.end()) + { + if( (*tileIter).second.theTile.valid()) + { + (*tileIter).second.theTile = NULL; + } + ++tileIter; + } + theLruQueue.clear(); + theTileMap.clear(); + theCacheSize = 0; +} + +void ossimFixedTileCache::deleteTile() +{ + if(theUseLruFlag) + { + if(theLruQueue.begin() != theLruQueue.end()) + { + deleteTile(*(theLruQueue.begin())); + } + } +} + +ossimRefPtr<ossimImageData> ossimFixedTileCache::removeTile() +{ + if(theUseLruFlag) + { + if(theLruQueue.begin() != theLruQueue.end()) + { + return removeTile(*(theLruQueue.begin())); + } + } + + return NULL; +} + +void ossimFixedTileCache::adjustLru(ossim_int32 id) +{ + if(theUseLruFlag) + { + std::list<ossim_int32>::iterator iter = std::find(theLruQueue.begin(), theLruQueue.end(), id); + + if(iter != theLruQueue.end()) + { + ossim_int32 value = *iter; + theLruQueue.erase(iter); + theLruQueue.push_back(value); + } + } +} + +void ossimFixedTileCache::eraseFromLru(ossim_int32 id) +{ + if(theUseLruFlag) + { + + std::list<ossim_int32>::iterator iter = std::find(theLruQueue.begin(), theLruQueue.end(), id); + + if(iter != theLruQueue.end()) + { + theLruQueue.erase(iter); + } + } +} + + +void ossimFixedTileCache::setTileSize(const ossimIpt& tileSize) +{ + setRect(theTileBoundaryRect, tileSize); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/cache/ossimFixedTileCache.h b/Utilities/OSSIM/ossim_core/imaging/cache/ossimFixedTileCache.h new file mode 100644 index 0000000000..dd6bf59dfe --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/cache/ossimFixedTileCache.h @@ -0,0 +1,143 @@ +//****************************************************************** +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: This file contains the Application cache algorithm +// +//*********************************** +// $Id: ossimFixedTileCache.h,v 1.11 2005/08/17 19:18:12 gpotts Exp $ +#ifndef ossimFixedTileCache_HEADER +#define ossimFixedTileCache_HEADER +#include <map> +#include <list> +#include <base/data_types/ossimIpt.h> +#include <base/common/ossimReferenced.h> +#include <base/common/ossimRefPtr.h> +#include <imaging/ossimImageData.h> + +class ossimFixedTileCacheInfo +{ +public: + ossimFixedTileCacheInfo(ossimRefPtr<ossimImageData>& tile, + ossim_int32 tileId=-1) + :theTile(tile), + theTileId(tileId) + { + } + + bool operator <(const ossimFixedTileCacheInfo& rhs)const + { + return (theTileId < rhs.theTileId); + } + bool operator <(ossim_int32 tileId)const + { + return (theTileId < tileId); + } + bool operator >(const ossimFixedTileCacheInfo& rhs)const + { + return (theTileId > rhs.theTileId); + } + bool operator >(ossim_int32 tileId)const + { + return (theTileId > tileId); + } + bool operator ==(const ossimFixedTileCacheInfo& rhs)const + { + return (theTileId == rhs.theTileId); + } + bool operator ==(ossim_int32 tileId)const + { + return (theTileId == tileId); + } + + ossimRefPtr<ossimImageData> theTile; + ossim_int32 theTileId; +}; + +class ossimFixedTileCache : public ossimReferenced +{ +public: + ossimFixedTileCache(); + virtual ~ossimFixedTileCache(); + virtual void setRect(const ossimIrect& rect); + virtual void setRect(const ossimIrect& rect, + const ossimIpt& tileSize); + void ossimFixedTileCache::keepTilesWithinRect(const ossimIrect& rect); + virtual ossimRefPtr<ossimImageData> addTile(ossimRefPtr<ossimImageData> imageData); + virtual ossimRefPtr<ossimImageData> getTile(ossim_int32 id); + virtual ossimRefPtr<ossimImageData> getTile(const ossimIpt& origin) + { + return getTile(computeId(origin)); + } + virtual void setUseLruFlag(bool flag) + { + theUseLruFlag = flag; + } + virtual bool getUseLruFlag()const + { + return theUseLruFlag; + } + virtual void flush(); + virtual void deleteTile(const ossimIpt& origin) + { + deleteTile(computeId(origin)); + } + virtual void deleteTile(ossim_int32 tileId); + virtual ossimRefPtr<ossimImageData> removeTile(const ossimIpt& origin) + { + return removeTile(computeId(origin)); + } + virtual ossimRefPtr<ossimImageData> removeTile(ossim_int32 tileId); + virtual const ossimIrect& getTileBoundaryRect()const + { + return theTileBoundaryRect; + } + virtual ossim_uint32 getNumberOfTiles()const + { + return (ossim_uint32)theTileMap.size(); + } + virtual const ossimIpt& getTileSize()const + { + return theTileSize; + } + virtual ossim_uint32 getCacheSize()const + { + return theCacheSize; + } + virtual void deleteTile(); + virtual ossimRefPtr<ossimImageData> removeTile(); + + virtual void setMaxCacheSie(ossim_uint32 cacheSize) + { + theMaxCacheSize = cacheSize; + } + + ossim_uint32 getMaxCacheSize()const + { + return theMaxCacheSize; + } + + virtual ossimIpt getTileOrigin(ossim_int32 tileId); + virtual ossim_int32 computeId(const ossimIpt& tileOrigin)const; + virtual void setTileSize(const ossimIpt& tileSize); +protected: + ossimIrect theTileBoundaryRect; + ossimIpt theTileSize; + ossimIpt theBoundaryWidthHeight; + ossim_uint32 theTilesHorizontal; + ossim_uint32 theTilesVertical; + ossim_uint32 theCacheSize; + ossim_uint32 theMaxCacheSize; + std::map<ossim_int32, ossimFixedTileCacheInfo> theTileMap; + std::list<ossim_int32> theLruQueue; + bool theUseLruFlag; + virtual void eraseFromLru(ossim_int32 id); + void adjustLru(ossim_int32 id); +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/cache/ossimTileCache.cpp b/Utilities/OSSIM/ossim_core/imaging/cache/ossimTileCache.cpp new file mode 100644 index 0000000000..18ee8e783c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/cache/ossimTileCache.cpp @@ -0,0 +1,189 @@ +//****************************************************************** +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// Description: This file contains the cache algorithm +// +//*********************************** +// $Id: ossimTileCache.cpp,v 1.7 2003/06/15 19:00:41 dburken Exp $ + +#include "ossimTileCache.h" +#include "base/common/ossimDataObject.h" + +void ossimTileCache::display()const +{ + ossimTileCache::Iterator tiles; + + for(long buckets = 0; buckets < theNumberOfBuckets; buckets++) + { + tiles = theCache[buckets].begin(); + while(tiles != theCache[buckets].end()) + { + cout << ((*tiles).second) << endl; + ++tiles; + } + } +} + +ossimTileCache::ossimTileCache(long numberOfBuckets) + : theCache(NULL), + theNumberOfBuckets(numberOfBuckets>0?numberOfBuckets:255), + theSizeInBytes(0) +{ + theCache = new multimap<ossim_uint32, ossimTileInformation*>[theNumberOfBuckets]; +} + +ossimTileCache::~ossimTileCache() +{ + deleteAll(); +} + +ossimDataObject* ossimTileCache::get(const ossimDpt3d &origin, + unsigned long resLevel) +{ + ossimDataObject* result = NULL; + Iterator anIterator; + + ossim_uint32 bucket = bucketHash(origin); + + anIterator = theCache[bucket].find(tileId(origin)); + while(anIterator != theCache[bucket].end()) + { + CacheDataPtr info = (*anIterator).second; + if(info) + { + if(info->theOrigin == origin && + info->theResLevel == resLevel) + { + return info->theCachedTile; + } + } + + ++anIterator; + } + return result; +} + +ossimDataObject* ossimTileCache::remove(const ossimDpt3d &origin, + unsigned long resLevel) +{ + Iterator anIterator; + ossimDataObject *result; + ossim_uint32 bucket = bucketHash(origin); + + anIterator = theCache[bucket].find(tileId(origin)); + while(anIterator != theCache[bucket].end()) + { + CacheDataPtr info = (*anIterator).second; + if(info) + { + if(info->theOrigin == origin && + info->theResLevel == resLevel) + { + theCache[bucket].erase(anIterator); + theSizeInBytes -= info->theCachedTile->getDataSizeInBytes(); + + result = info->theCachedTile; + + delete info; + return result; + } + } + + ++anIterator; + } + + return NULL; +} + +ossimDataObject* ossimTileCache::insert(const ossimDpt3d &origin, + ossimDataObject* data, + unsigned long resLevel) +{ + ossim_uint32 bucket = bucketHash(origin); + + // make sure we keep up with the current size of the + // cache in bytes. This is only the count of the data + // and not any overhead required by the cache. + theSizeInBytes += data->getDataSizeInBytes(); + theCache[bucket].insert(make_pair(tileId(origin), + new CacheData(data, + origin, + resLevel))); + + return data; +} + +void ossimTileCache::invalidate() +{ + +} + +void ossimTileCache::invalidate(const ossimDpt3d &origin, + ossim_uint32 resLevel) +{ +} + + + +ossim_uint32 ossimTileCache::tileId(const ossimDpt3d &aPt) +{ + const unsigned char *bufx = (unsigned char*)(&aPt.x); + const unsigned char *bufy = (unsigned char*)(&aPt.y); + const unsigned char *bufz = (unsigned char*)(&aPt.z); + + // this just multiplies each byte by some prime number + // and add together. + return (ossim_uint32)(bufx[0]*101 + bufx[1]*103 + + bufx[2]*107 + bufx[3]*109 + + bufx[4]*113 + bufx[5]*127 + + bufx[6]*131 + bufx[7]*137 + + bufy[0]*139 + bufy[1]*149 + + bufy[2]*151 + bufy[3]*157 + + bufy[4]*163 + bufy[5]*167 + + bufy[6]*173 + bufy[7]*179 + + bufz[0]*181 + bufz[1]*191 + + bufz[2]*193 + bufz[3]*197 + + bufz[4]*199 + bufz[5]*211 + + bufz[6]*223 + bufz[6]*227); +} + +ossim_uint32 ossimTileCache::bucketHash(const ossimDpt3d &aPt) +{ + return tileId(aPt)%theNumberOfBuckets; +} + +void ossimTileCache::deleteAll() +{ + Iterator anIterator; + + for(long bucket = 0; bucket < theNumberOfBuckets; bucket++) + { + anIterator = theCache[bucket].begin(); + while(anIterator != theCache[bucket].end()) + { + CacheDataPtr info = (*anIterator).second; + delete info->theCachedTile; + delete info; + + ++anIterator; + } + theCache[bucket].clear(); + } + delete [] theCache; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/cache/ossimTileCache.h b/Utilities/OSSIM/ossim_core/imaging/cache/ossimTileCache.h new file mode 100644 index 0000000000..fc4b73f5bd --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/cache/ossimTileCache.h @@ -0,0 +1,114 @@ +//****************************************************************** +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// Description: This file contains the cache algorithm +// +//*********************************** +// $Id: ossimTileCache.h,v 1.5 2003/05/15 14:34:16 dburken Exp $ + +#ifndef DataCache_HEADER +#define DataCache_HEADER +#include <map> +#include <stack> +using namespace std; + +#include "base/common/ossimConstants.h" +#include "base/data_types/ossimDpt3d.h" +class ossimDataObject; +class ossimTileCache +{ +public: + + ossimTileCache(long numberOfBuckets = 10); + virtual ~ossimTileCache(); + + /*! + * This will return a tile if found. Note this tile is still + * owned by the cache. + */ + virtual ossimDataObject* get(const ossimDpt3d &origin, + unsigned long resLevel=0); + + /*! + * Will remove the tile from the cache and will not delete. Note: + * the cache no longer owns the tile. + */ + virtual ossimDataObject* remove(const ossimDpt3d &origin, + unsigned long resLevel=0); + /*! + * This will not duplicate the tile. Note the tile is owned + * by the cache. + */ + virtual ossimDataObject* insert(const ossimDpt3d &origin, + ossimDataObject* data, + unsigned long resLevel=0); + /*! + * Not implemented + */ + void invalidate(); + /*! + * Not implemented + */ + virtual void invalidate(const ossimDpt3d &origin, + ossim_uint32 resLevel); + + + + virtual long numberOfItems()const{return theCache?theCache->size():0;} + virtual void display()const; + + virtual ossim_uint32 sizeInBytes(){return theSizeInBytes;} + +protected: + + struct ossimTileInformation + { + public: + friend ostream& operator <<(ostream &out, + const ossimTileInformation &info) + { + + return out; + } + ossimTileInformation(ossimDataObject* aTile, + const ossimDpt3d &origin = ossimDpt(0,0), + unsigned long resLevel = 0) + : theCachedTile(aTile), + theOrigin(origin), + theResLevel(resLevel) + {} + ossimDataObject* theCachedTile; + ossimDpt3d theOrigin; + unsigned long theResLevel; + }; + + typedef multimap<ossim_uint32, ossimTileInformation*>::iterator Iterator; + typedef ossimTileInformation* CacheDataPtr; + typedef ossimTileInformation CacheData; + + void deleteAll(); + virtual ossim_uint32 bucketHash(const ossimDpt3d &aPt); + virtual ossim_uint32 tileId(const ossimDpt3d &aPt); + + multimap<ossim_uint32, ossimTileInformation*> *theCache; + long theNumberOfBuckets; + ossim_uint32 theSizeInBytes; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/elevation/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/elevation/.cvsignore new file mode 100644 index 0000000000..42d2532435 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/elevation/.cvsignore @@ -0,0 +1,2 @@ +*.d + diff --git a/Utilities/OSSIM/ossim_core/imaging/elevation/ossimElevImageSource.cpp b/Utilities/OSSIM/ossim_core/imaging/elevation/ossimElevImageSource.cpp new file mode 100644 index 0000000000..6db439edab --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/elevation/ossimElevImageSource.cpp @@ -0,0 +1,821 @@ +//******************************************************************* +// Copyright (C) 2002 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: Class provides an elevation image source from the elevation +// manager. +// +//******************************************************************* +// $Id: ossimElevImageSource.cpp,v 1.13 2005/02/11 15:07:30 dburken Exp $ + +#include <time.h> + +#include "ossimElevImageSource.h" +#include "elevation/ossimElevManager.h" +#include "projections/map_projections/ossimLlxyProjection.h" +#include "base/common/ossimKeywordNames.h" +#include "base/common/ossimTrace.h" +#include "base/data_types/ossimKeywordlist.h" + +RTTI_DEF1(ossimElevImageSource, "ossimElevImageSource", ossimImageSource) + +// Static trace for debugging +static ossimTrace traceDebug("ossimElevImage:debug"); + +ossimElevImageSource::ossimElevImageSource() + : + ossimImageSource(NULL, + 0, + 0, + true, + false),// output list is not fixed + theElevManager(NULL), + theTile(NULL), + theTiePoint(), + theLatSpacing(0.0), + theLonSpacing(0.0), + theNumberOfLines(0), + theNumberOfSamps(0) +{} + +ossimElevImageSource::ossimElevImageSource(ossimObject* owner) + : + ossimImageSource(owner, + 0, + 0, + true, + false),// output list is not fixed + theElevManager(NULL), + theTile(NULL), + theTiePoint(), + theLatSpacing(0.0), + theLonSpacing(0.0), + theNumberOfLines(0), + theNumberOfSamps(0) +{} + +ossimElevImageSource::ossimElevImageSource(ossimObject* owner, + const ossimGpt& tie, + double latSpacing, + double lonSpacing, + ossim_uint32 numberLines, + ossim_uint32 numberSamples) + : + ossimImageSource(owner, + 0, + 0, + true, + false),// output list is not fixed + theElevManager(NULL), + theTile(NULL), + theTiePoint(tie), + theLatSpacing(latSpacing), + theLonSpacing(lonSpacing), + theNumberOfLines(numberLines), + theNumberOfSamps(numberSamples) +{ + initialize(); +} + +ossimElevImageSource::ossimElevImageSource(ossimObject* owner, + const ossimKeywordlist& kwl, + const char* prefix) + : + ossimImageSource(owner, + 0, + 0, + true, + false), + theElevManager(NULL), + theTile(NULL), + theTiePoint(), + theLatSpacing(0), + theLonSpacing(0), + theNumberOfLines(0), + theNumberOfSamps(0) +{ + if (loadState(kwl, prefix) == false) + { + setErrorStatus(); + } +} + +ossimElevImageSource::~ossimElevImageSource() +{ +} + +ossimRefPtr<ossimImageData> ossimElevImageSource::getTile( + const ossimIrect& tile_rect, + ossim_uint32 resLevel) +{ + if (!theTile.get()) + { + return theTile; + } + + // First make sure our tile is the right size. + ossim_int32 w = tile_rect.width(); + ossim_int32 h = tile_rect.height(); + ossim_int32 tileW = theTile->getWidth(); + ossim_int32 tileH = theTile->getHeight(); + if( (w != tileW) || (h != tileH) ) + { + theTile->setWidth(w); + theTile->setHeight(h); + if((w*h)!=(tileW*tileH)) + { + theTile->initialize(); + + //*** + // Initialize can reset the min max to defaults if the min happens + // to be "0" so reset it just in case. + // NOTE: We need to fix initialize! + //*** + theTile->setMinPix(theElevManager->getMinHeightAboveMSL(), 0); + theTile->setMaxPix(theElevManager->getMaxHeightAboveMSL(), 0); + } + } + + // Set the origin. + theTile->setOrigin(tile_rect.ul()); + + + if(!isSourceEnabled()) + { + // This tile source bypassed. + theTile->makeBlank(); + return theTile; + } + + //*** + // No overview support yet... + //*** + if (resLevel) + { + // NOTE: Need to add overview support. + cerr << "ossimElevImageSource::getTile ERROR:\nOverviews not supported!" + << endl; + theTile->makeBlank(); + return theTile; + } + + ossimIrect image_rect = getImageRectangle(0); + + if ( !tile_rect.intersects(image_rect) ) + { + // No point in the tile falls within the set boundaries of this source. + theTile->makeBlank(); + return theTile; + } + + // Ok fill the tile with the data from the post... + ossimIrect clip_rect = tile_rect.clipToRect(image_rect); + + if ( !tile_rect.completely_within(clip_rect) ) + { + // Start with a blank tile since it won't be filled all the way. + theTile->makeBlank(); + } + + + // Move the buffer pointer to the first valid pixel. + ossim_uint32 tile_width = theTile->getWidth(); + + ossim_int32 start_offset = (clip_rect.lr().y - tile_rect.ul().y) * tile_width + + clip_rect.ul().x - tile_rect.ul().x; + + //*** + // Since most elevation formats have posts organized positive line up, + // start at the lower left side of the cell so all reads are going + // forward in the file. + //*** + double start_lat = theTiePoint.latd() - theLatSpacing * + (clip_rect.lr().y - image_rect.ul().y); + if (start_lat < -90.0) + { + start_lat = -(start_lat + 180.0); // Wrapped around the south poll. + } + + double lon = theTiePoint.lond() + theLonSpacing * + (clip_rect.ul().x - image_rect.ul().x); + if (lon > 180.0) + { + lon -= 360.0; // Went across the central meridian. + } + + // Copy the data. + ossim_uint32 clipHeight = clip_rect.height(); + ossim_uint32 clipWidth = clip_rect.width(); + + // Get a pointer to the tile buffer. + ossim_float32* buf = static_cast<ossim_float32*>(theTile->getBuf()); + + for (ossim_uint32 sample = 0; sample < clipWidth; ++sample) + { + double lat = start_lat; + ossim_int32 offset = start_offset; + for (ossim_uint32 line = 0; line < clipHeight; ++line) + { + ossimGpt gpt(lat, lon); + buf[offset+sample] = theElevManager->getHeightAboveMSL(gpt); + + lat += theLatSpacing; + if (lat > 90) lat = 180.0 - lat; + + offset -= tile_width; + } + + lon += theLonSpacing; + if (lon > 180.0) lon = lon - 360.0; // Went across the central meridian. + } + +#if 0 + for (ossim_uint32 line = 0; line < clipHeight; ++line) + { + double lon = start_lon; + for (ossim_uint32 sample = 0; sample < clipWidth; ++sample) + { + ossimGpt gpt(lat, lon); + buf[sample] = theElevManager->getHeightAboveMSL(gpt); + lon += theLonSpacing; + if (start_lon > 180.0) + { + start_lon -= 360.0; // Went across the central meridian. + } + } + + buf += tile_width; + lat -= theLatSpacing; + if (lat < -90.0) lat = -(lat + 180.0);// Wrapped around the south poll. + } +#endif + + theTile->validate(); + return theTile; +} + +bool ossimElevImageSource::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + static const char MODULE[] = "ossimElevImageSource::saveState"; + + if (kwl.getErrorStatus() == ossimErrorCodes::OSSIM_ERROR) + { + cerr << MODULE + << " ERROR detected in keyword list! State not saved." + << endl; + return false; + } + + // Save the state of the base class. + ossimImageSource::saveState(kwl, prefix); + + // Save the tie point. + kwl.add(prefix, + ossimKeywordNames::TIE_POINT_LAT_KW, + theTiePoint.latd(), + true); + kwl.add(prefix, + ossimKeywordNames::TIE_POINT_LON_KW, + theTiePoint.lond(), + true); + + // Save the post spacing. + kwl.add(prefix, + ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LAT, + theLatSpacing, + true); + kwl.add(prefix, + ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LON, + theLonSpacing, + true); + + // Save the image size + kwl.add(prefix, + ossimKeywordNames::NUMBER_LINES_KW, + theNumberOfLines, + true); + kwl.add(prefix, + ossimKeywordNames::NUMBER_SAMPLES_KW, + theNumberOfSamps, + true); + + // Save the min / max pixel values. + kwl.add(prefix, + ossimKeywordNames::MIN_VALUE_KW, + getMinPixelValue(0), + true); + kwl.add(prefix, + ossimKeywordNames::MAX_VALUE_KW, + getMaxPixelValue(0), + true); + + return true; +} + +//******************************************************************* +// Public method: +//******************************************************************* +bool ossimElevImageSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + static const char MODULE[] = "ossimElevImageSource::loadState"; + + if (kwl.getErrorStatus() == ossimErrorCodes::OSSIM_ERROR) + { + cerr << MODULE + << " ERROR detected in keyword list! State not load." + << endl; + return false; + } + + // Base class... + ossimImageSource::loadState(kwl, prefix); + + const char* lookup; + + // Get the tie point. + lookup = kwl.find(prefix, ossimKeywordNames::TIE_POINT_LAT_KW); + if (lookup) + { + theTiePoint.latd(ossimString(lookup).toDouble()); + } + else + { + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nRequired keyword not found: " + << ossimKeywordNames::TIE_POINT_LAT_KW + << "\nReturning false" + << endl; + } + + return false; + } + + lookup = kwl.find(prefix, ossimKeywordNames::TIE_POINT_LON_KW); + if (lookup) + { + theTiePoint.lond(ossimString(lookup).toDouble()); + } + else + { + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nRequired keyword not found: " + << ossimKeywordNames::TIE_POINT_LON_KW + << "\nReturning false" + << endl; + } + + return false; + } + + // Get the post spacing. + lookup = kwl.find(prefix, ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LAT); + if (lookup) + { + theLatSpacing = ossimString(lookup).toDouble(); + } + else + { + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nRequired keyword not found: " + << ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LAT + << "\nReturning false" + << endl; + } + + return false; + } + + lookup = kwl.find(prefix, ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LON); + if (lookup) + { + theLonSpacing = ossimString(lookup).toDouble(); + } + else + { + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nRequired keyword not found: " + << ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LON + << "\nReturning false" + << endl; + } + + return false; + } + + // Get the image size. + lookup = kwl.find(prefix, ossimKeywordNames::NUMBER_LINES_KW); + if (lookup) + { + theNumberOfLines = ossimString(lookup).toULong(); + } + else + { + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nRequired keyword not found: " + << ossimKeywordNames::NUMBER_LINES_KW + << "\nReturning false" + << endl; + } + + return false; + } + + lookup = kwl.find(prefix, ossimKeywordNames::NUMBER_SAMPLES_KW); + if (lookup) + { + theNumberOfSamps = ossimString(lookup).toULong(); + } + else + { + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nRequired keyword not found: " + << ossimKeywordNames::NUMBER_SAMPLES_KW + << "\nReturning false" + << endl; + } + + return false; + } + + initialize(); + + //*** + // See if the min / max keyword was set and reset it. + // Note this must be done after initialize since it sets the min / max from + // the elevation manager. + //*** + lookup = kwl.find(prefix, ossimKeywordNames::MIN_VALUE_KW); + if (lookup) + { + setMinPixelValue(ossimString(lookup).toDouble()); + } + lookup = kwl.find(prefix, ossimKeywordNames::MAX_VALUE_KW); + if (lookup) + { + setMaxPixelValue(ossimString(lookup).toDouble()); + } + + if (getErrorStatus() != ossimErrorCodes::OSSIM_OK) + { + return false; + } + + //*** + // Reset the base class to have a fixed input list of "0" size. + // Note: To not do this will result in a core dump destroying objects + // connected to this output. + //*** + theInputObjectList.clear(); + theInputListIsFixedFlag = true; + theOutputListIsFixedFlag = false; + + return true; +} + +void ossimElevImageSource::initialize() +{ + static const char MODULE[] = "ossimElevImageSource::initialize"; + + if (traceDebug()) CLOG << " Entered..." << endl; + + //*** + // First see if the manager pointer has been captured. + //*** + if (!theElevManager) theElevManager = ossimElevManager::instance(); + + if (!theElevManager) + { + setErrorStatus(); + cerr << MODULE << "ERROR:\nNULL elevation manager pointer!" + << "\nObject not initialized!" << endl; + return; + } + + // Basic sanity checks. + if (!theLatSpacing || !theLonSpacing || + !theNumberOfLines || !theNumberOfSamps) + { + setErrorStatus(); + cerr << MODULE << "ERROR:" + << "\nMust set latitude/longitude spacing and number of line and" + << " samples." + << "Object not initialized!" << endl; + return; + + } + + // Check the ground point. + if ( theTiePoint.latd() > 90.0 || theTiePoint.latd() < -90.0 || + theTiePoint.lond() > 180.0 || theTiePoint.lond() < -180.0 ) + { + setErrorStatus(); + cerr << MODULE << "ERROR:\nBogus tie point." + << "\nObject not initialized!" << endl; + return; + } + + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nTie point: " << theTiePoint + << "\nLatitude spacing: " << theLatSpacing + << "\nLongitude spacing: " << theLonSpacing + << "\nLines: " << theNumberOfLines + << "\nSamples: " << theNumberOfSamps + << endl; + } + + //*** + // Since this will return float data we need to set the min / max values + // of the data so that anybody who remaps it to eight bit will do it + // properly. So scan the entire image rectangle using the manager. + // This will do two things, force the elevation manager to load all the + // cells, and at the same time the min / max elevation value will be set. + // NOTE: + // ??? Should the elevation manager clear the list of sources prior to + // the code segment so that the min / max is only from the cells we + // need! + //*** + + cout << "Initializing elevation manager..." << endl; + +#if 0 + // Loop in the longitude or sample direction. + time_t start_t = time(NULL); + double lon = theTiePoint.lond(); + for (ossim_uint32 samp = 0; samp < theNumberOfSamps; ++samp) + { + double lat = theTiePoint.latd() - theLatSpacing * (theNumberOfLines - 1); + if (lat < -90.0) lat = -(lat + 180.0); // Wrapped around the south poll. + + for (ossim_uint32 line = 0; line < theNumberOfLines; ++line) + { + ossimGpt gpt(lat, lon); + theElevManager->getHeightAboveMSL(gpt); + + lat += theLatSpacing; + if (lat > 90) lat = 180 - lat; // Went across poll. + } + + lon += theLonSpacing; + if (lon > 180.0) lon -= 360.0; // Went across the central meridian. + } + time_t stop_t = time(NULL); + cout << "Finished loop two..." << endl; + cout << "Elapsed time for loop two: " << (stop_t - start_t) << endl; +#endif + + theTile = new ossimImageData(this, + OSSIM_FLOAT); + theTile->initialize(); + + // Set the min / max for any normalization down the chain... + theTile->setMinPix(theElevManager->getMinHeightAboveMSL(), 0); + theTile->setMaxPix(theElevManager->getMaxHeightAboveMSL(), 0); + + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nMin pix: " << theTile->getMinPix(0) + << "\nMax pix: " << theTile->getMaxPix(0) + << endl; + } +} + +ossimIrect ossimElevImageSource::getImageRectangle(ossim_uint32 reduced_res_level) const +{ + ossimIrect result(0, 0, theNumberOfSamps-1, theNumberOfLines-1); + + if (reduced_res_level != 0) + { + cerr << "ossimElevImageSource::getImageRectangle ERROR:" + << "\nOnly R0 is supported." << endl; + } + + return result; +} + +bool ossimElevImageSource::getImageGeometry(ossimKeywordlist& kwl, + const char* prefix) +{ + // Save off the image dimensions. + kwl.add(prefix, + ossimKeywordNames::NUMBER_LINES_KW, + theNumberOfLines, + true); + kwl.add(prefix, + ossimKeywordNames::NUMBER_SAMPLES_KW, + theNumberOfLines, + true); + + // Save off the projection info (tie and post spacing). + ossimLlxyProjection proj(theTiePoint, theLatSpacing, theLonSpacing); + return proj.saveState(kwl, prefix); +} + +void ossimElevImageSource::getDecimationFactor(ossim_uint32 resLevel, ossimDpt& result) const +{ + if (resLevel) + { + cerr << "ossimElevImageSource::getDecimationFactor ERROR:" + << "\nReduced res sets currently not supported!" + << endl; + } + + result.line = 1.0; + result.samp = 1.0; +} + +void ossimElevImageSource::getDecimationFactors(vector<ossimDpt>& decimations) const +{ + ossimDpt pt(1.0, 1.0); + decimations.clear(); + decimations.push_back(pt); +} + +ossim_uint32 ossimElevImageSource::getNumberOfDecimationLevels()const +{ + return 1; +} + +ossim_uint32 ossimElevImageSource::getNumberOfInputBands() const +{ + return 1; +} + +ossimScalarType ossimElevImageSource::getOutputScalarType() const +{ + return OSSIM_FLOAT; +} + +ossim_uint32 ossimElevImageSource::getTileWidth() const +{ + if (theTile.get()) return theTile->getWidth(); + + return 0; +} + +ossim_uint32 ossimElevImageSource::getTileHeight() const +{ + if (theTile.get()) return theTile->getHeight(); + + return 0; +} + +void ossimElevImageSource::changeTileSize(const ossimIpt& size) +{ + if (traceDebug()) + { + cout << "ossimElevImageSource::changeTileSize DEBUG:" + << "\nx size: " << size.x + << "\ny size: " << size.y + << endl; + } + + if (!theTile) + { + cerr << "ossimElevImageSource::changeTileSize ERROR:" + << "\nObject not initialized! Returning..." << endl; + return; + } + + theTile = new ossimImageData(this, + OSSIM_FLOAT, + 1, + size.x, + size.y); + theTile->initialize(); + + // Set the min / max for any normalization down the chain... + theTile->setMinPix(theElevManager->getMinHeightAboveMSL(), 0); + theTile->setMaxPix(theElevManager->getMaxHeightAboveMSL(), 0); +} + +ossim_uint32 ossimElevImageSource::getNumberOfLines(ossim_uint32 reduced_res_level) const +{ + if (reduced_res_level) + { + cerr << "ossimElevImageSource::getNumberOfLines ERROR:" + << "\nReduced res sets currently not supported!" + << endl; + return 0; + } + + return theNumberOfLines; +} + +ossim_uint32 ossimElevImageSource::getNumberOfSamples(ossim_uint32 reduced_res_level) const +{ + if (reduced_res_level) + { + cerr << "ossimElevImageSource::getNumberOfSamples ERROR:" + << "\nReduced res sets currently not supported!" + << endl; + return 0; + } + + return theNumberOfSamps; +} + +double ossimElevImageSource::getMinPixelValue(ossim_uint32 band) const +{ + if (band) + { + cerr << "ossimElevImageSource::getMinPixelValue ERROR:" + << "\nReduced res sets currently not supported!" + << endl; + return 0.0; + } + + if (theTile.get()) + { + return theTile->getMinPix(0); + } + else if (theElevManager) + { + return theElevManager->getMinHeightAboveMSL(); + } + + return 0.0; +} + +double ossimElevImageSource::getMaxPixelValue(ossim_uint32 band) const +{ + if (band) + { + cerr << "ossimElevImageSource::getMaxPixelValue ERROR:" + << "\nReduced res sets currently not supported!" + << endl; + return 0.0; + } + + if (theTile.get()) + { + return theTile->getMaxPix(0); + } + else if (theElevManager) + { + return theElevManager->getMaxHeightAboveMSL(); + } + + return 0.0; +} + +void ossimElevImageSource::setMinPixelValue(ossim_float64 min_pix) +{ + if (theTile.get()) + { + theTile->setMinPix(min_pix, 0); + if (traceDebug()) + { + cout << "ossimElevImageSource::setMinPixelValue DEBUG:" + << "\nMin pixel value: " << min_pix + << endl; + } + } + else + { + cerr << "ossimElevImageSource::setMinPixelValue ERROR:" + << "\nObject not initialized!" + << endl; + } +} + +void ossimElevImageSource::setMaxPixelValue(ossim_float64 max_pix) +{ + if (theTile.get()) + { + theTile->setMaxPix(max_pix, 0); + if (traceDebug()) + { + cout << "ossimElevImageSource::setMaxPixelValue DEBUG:" + << "\nMax pixel value: " << max_pix + << endl; + } + } + else + { + cerr << "ossimElevImageSource::setMinPixelValue ERROR:" + << "\nObject not initialized!" + << endl; + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/elevation/ossimElevImageSource.h b/Utilities/OSSIM/ossim_core/imaging/elevation/ossimElevImageSource.h new file mode 100644 index 0000000000..70ca60a94f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/elevation/ossimElevImageSource.h @@ -0,0 +1,146 @@ +//******************************************************************* +// Copyright (C) 2002 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: Class provides an elevation image source from the elevation +// manager. +// +//******************************************************************** +// $Id: ossimElevImageSource.h,v 1.9 2005/02/11 15:07:30 dburken Exp $ + +#ifndef ossimElevImageSource_HEADER +#define ossimElevImageSource_HEADER + +#include "imaging/ossimImageSource.h" +#include "base/common/ossimConstants.h" +#include "base/data_types/ossimGrect.h" + +class ossimElevSource; + +class ossimElevImageSource : public ossimImageSource +{ +public: + + ossimElevImageSource(); + ossimElevImageSource(ossimObject* owner); + ossimElevImageSource(ossimObject* owner, + const ossimGpt& tie, + double latSpacing, // decimal degrees + double lonSpacing , + ossim_uint32 numberLines, + ossim_uint32 numberSamples); + ossimElevImageSource(ossimObject* owner, + const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual ~ossimElevImageSource(); + + /*! + * Returns a pointer to a tile given an origin representing the upper left + * corner of the tile to grab from the image. + * Satisfies pure virtual from TileSource class. + */ + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect, + ossim_uint32 resLevel=0); + + /*! + * Populates the keyword list with image geometry information. This + * method is used to relay projection/model information to users. + * Returns true if geometry info is present, false if not. + */ + virtual bool getImageGeometry(ossimKeywordlist& kwl, + const char* prefix=0); + + /*! + * Returns the number of bands in the image. Alway one for this source. + */ + virtual ossim_uint32 getNumberOfOutputBands()const { return 1; } + + + /*! + * Returns the zero-based (relative) image rectangle for the reduced + * resolution data set (rrds) passed in. Note that rrds 0 is the highest + * resolution rrds. + */ + virtual ossimIrect getImageRectangle(ossim_uint32 reduced_res_level = 0) const; + + /*! + * Returns the absolute bounding rectangle of the image. The upper left + * corner may be non-zero if this is a subimage. + */ + virtual ossimIrect getBoundingRect(ossim_uint32 resLevel = 0) const + { + return getImageRectangle(resLevel); + } + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + bool canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const + { + return false; + } + + virtual void initialize(); + + /*! + * Satisfy pure virtuals from base classes... + */ + virtual void getDecimationFactor(ossim_uint32 resLevel, ossimDpt& result) const; + virtual void getDecimationFactors(vector<ossimDpt>& decimations) const; + virtual ossim_uint32 getNumberOfDecimationLevels()const; + virtual ossim_uint32 getNumberOfInputBands() const; + virtual ossimScalarType getOutputScalarType() const; + virtual ossim_uint32 getTileWidth() const; + virtual ossim_uint32 getTileHeight() const; + virtual void changeTileSize(const ossimIpt& size); + + // access methods + virtual ossimGpt getTiePoint() const { return theTiePoint; } + virtual ossim_float64 getLatitudeSpacing() const { return theLatSpacing; } + virtual ossim_float64 getLongitudeSpacing() const { return theLonSpacing; } + virtual ossim_uint32 getNumberOfLines(ossim_uint32 reduced_res_level = 0) const; + virtual ossim_uint32 getNumberOfSamples(ossim_uint32 reduced_res_level = 0) const; + virtual double getMinPixelValue(ossim_uint32 band=0)const; + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + + // set methods + virtual void setTiePoint(const ossimGpt& gpt) { theTiePoint = gpt; } + virtual void setLatitudeSpacing(ossim_float64 sp) { theLatSpacing = sp; } + virtual void setLongitudeSpacing(ossim_float64 sp) { theLonSpacing = sp; } + virtual void setNumberOfLines(ossim_uint32 lines) { theNumberOfLines = lines; } + virtual void setNumberOfSamples(ossim_uint32 samps) { theNumberOfSamps = samps;} + virtual void setMinPixelValue(ossim_float64 min_pix); + virtual void setMaxPixelValue(ossim_float64 max_pix); + +protected: + + ossimElevSource* theElevManager; + ossimRefPtr<ossimImageData> theTile; + ossimGpt theTiePoint; // upper left tie point + ossim_float64 theLatSpacing; // in decimal degrees + ossim_float64 theLonSpacing; // in decimal degrees + ossim_uint32 theNumberOfLines; + ossim_uint32 theNumberOfSamps; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/factory/.cvsignore new file mode 100644 index 0000000000..42d2532435 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/.cvsignore @@ -0,0 +1,2 @@ +*.d + diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimAnnotationObjectFactory.cpp b/Utilities/OSSIM/ossim_core/imaging/factory/ossimAnnotationObjectFactory.cpp new file mode 100644 index 0000000000..f1c99a23eb --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimAnnotationObjectFactory.cpp @@ -0,0 +1,102 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See LICENSE.txt file in the top level directory. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimAnnotationObjectFactory.cpp,v 1.4 2005/12/09 17:09:23 dburken Exp $ +#include <imaging/factory/ossimAnnotationObjectFactory.h> + +#include <imaging/annotation/ossimGeoAnnotationEllipseObject.h> +#include <imaging/annotation/ossimGeoAnnotationFontObject.h> +#include <imaging/annotation/ossimGeoAnnotationMultiPolyLineObject.h> +#include <imaging/annotation/ossimGeoAnnotationPolyObject.h> + +ossimAnnotationObjectFactory* ossimAnnotationObjectFactory::theInstance=NULL; + +ossimAnnotationObjectFactory::ossimAnnotationObjectFactory() + :ossimFactoryBase<ossimAnnotationObject>() +{ +} + +ossimAnnotationObject* ossimAnnotationObjectFactory::create( + const ossimString& spec) const +{ + if(spec == STATIC_TYPE_NAME(ossimGeoAnnotationEllipseObject)) + { + return new ossimGeoAnnotationEllipseObject; + } + if(spec == STATIC_TYPE_NAME(ossimGeoAnnotationFontObject)) + { + return new ossimGeoAnnotationFontObject; + } + if(spec == STATIC_TYPE_NAME(ossimGeoAnnotationMultiPolyLineObject)) + { + return new ossimGeoAnnotationMultiPolyLineObject; + } + if(spec == STATIC_TYPE_NAME(ossimGeoAnnotationPolyObject)) + { + return new ossimGeoAnnotationPolyObject; + } + + return NULL; +} + +ossimAnnotationObject* ossimAnnotationObjectFactory::create( + const ossimKeywordlist& kwl, + const char* prefix) const +{ + ossimAnnotationObject* result = NULL; + + const char* type = kwl.find(prefix, "type"); + if(type) + { + result = create(ossimString(type)); + if(result) + { + result->loadState(kwl, prefix); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimAnnotationObjectFactory::create WARNING" + << "Unable to create object of type: " + << type << std::endl; + } + } + + return result; +} + +ossimAnnotationObjectFactory* ossimAnnotationObjectFactory::instance() +{ + if(!theInstance) + { + theInstance = new ossimAnnotationObjectFactory(); + } + + return theInstance; +} + +//***************************************************************************** +// METHOD: ossimProjectionFactory::getList() +// +//***************************************************************************** +list<ossimString> ossimAnnotationObjectFactory::getList() const +{ + list<ossimString> rtn_list; + list<ossimString> sub_list; + list<ossimFactoryBase<ossimAnnotationObject>*>::const_iterator factory; + + factory = theRegistry.begin(); + while(factory != theRegistry.end()) + { + sub_list = (*factory)->getList(); + rtn_list.merge(sub_list); + ++factory; + } + + return rtn_list; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimAnnotationObjectFactory.h b/Utilities/OSSIM/ossim_core/imaging/factory/ossimAnnotationObjectFactory.h new file mode 100644 index 0000000000..c4c033db8a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimAnnotationObjectFactory.h @@ -0,0 +1,57 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimAnnotationObjectFactory.h,v 1.1 2001/09/21 19:45:08 gpotts Exp $ +#ifndef ossimAnnotationObjectFactory_HEADER +#define ossimAnnotationObjectFactory_HEADER +#include "base/common/ossimFactoryBaseTemplate.h" +#include "imaging/annotation/ossimAnnotationObject.h" +class ossimAnnotationObjectFactory : public ossimFactoryBase<ossimAnnotationObject> +{ +public: + /*! + * METHOD: instance() + * For accessing static instance of concrete factory. + */ + static ossimAnnotationObjectFactory* instance(); + + /*! + * METHOD: create() + * Attempts to create an instance of the Product given a Specifier or + * keywordlist. Returns successfully constructed product or NULL. + */ + virtual ossimAnnotationObject* create(const ossimString& spec) const; + virtual ossimAnnotationObject* create(const ossimKeywordlist& kwl, + const char* prefix=0) const; + + /*! + * METHOD: getList() + * Returns name list of all products represented by this factory: + */ + virtual list<ossimString> getList() const; + +protected: + ossimAnnotationObjectFactory(); + static ossimAnnotationObjectFactory* theInstance; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageDataFactory.cpp b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageDataFactory.cpp new file mode 100644 index 0000000000..cbeadf9529 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageDataFactory.cpp @@ -0,0 +1,254 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +//************************************************************************* +// $Id: ossimImageDataFactory.cpp,v 1.25 2005/05/11 17:08:19 dburken Exp $ +#include "ossimImageDataFactory.h" +#include "imaging/ossimU8ImageData.h" +#include "imaging/ossimU11ImageData.h" +#include "imaging/ossimU16ImageData.h" +#include "imaging/ossimS16ImageData.h" +#include "imaging/ossimImageData.h" +#include "imaging/ossimImageSource.h" +#include "base/common/ossimTrace.h" +#include "base/misc/lookup_tables/ossimScalarTypeLut.h" + +// Static trace for debugging +static ossimTrace traceDebug("ossimImageDataFactory:debug"); + +ossimImageDataFactory* ossimImageDataFactory::theInstance = NULL; +ossimImageDataFactory::ossimImageDataFactory() +{ + theInstance = NULL; +} + +ossimImageDataFactory::~ossimImageDataFactory() +{ + if(theInstance) + { + delete theInstance; + theInstance = NULL; + } +} + +ossimImageDataFactory* ossimImageDataFactory::instance() +{ + if(!theInstance) + { + theInstance = new ossimImageDataFactory; + } + + return theInstance; +} + +ossimRefPtr<ossimImageData> ossimImageDataFactory::create( + ossimSource* owner, + ossimScalarType scalar, + ossim_uint32 bands)const +{ + ossimIpt defaultTileSize; + ossimGetDefaultTileSize(defaultTileSize); + ossim_uint32 width = defaultTileSize.x; + ossim_uint32 height = defaultTileSize.y; + + // do some bounds checking and initialize to a default + bands = (bands>0)?bands:1; + scalar = scalar != OSSIM_SCALAR_UNKNOWN?scalar:OSSIM_UINT8; + + if (traceDebug()) + { + cout << "ossimImageDataFactory::create DEBUG:" + << "\nCaller: " + << (owner ? owner->getClassName().c_str() : "unknown") + << "\nbands: " << bands + << "\nwidth: " << width + << "\nheight: " << height + << "\nScalar type: " + << (ossimScalarTypeLut::instance()->getEntryString(scalar)) + << endl; + } + + ossimRefPtr<ossimImageData> result = NULL; + switch(scalar) + { + case OSSIM_UINT8: + { + result = new ossimU8ImageData(owner, bands, width, height); + break; + } + + case OSSIM_USHORT11: + { + result = new ossimU11ImageData(owner, bands, width, height); + break; + } + + // ther are bugs in the 16 bit that I don't have time to find. + // The default image data object works good though. + // + // So for now I will comment these out. I think it has something to + // do with the normalization it makes everything black + // + // +// case OSSIM_USHORT16: +// { +// result = new ossimU16ImageData(owner, bands, width, height); +// break; +// } +// case OSSIM_SSHORT16: +// { +// result = new ossimS16ImageData(owner, bands, width, height); +// break; +// } + default: + { + // create a generic image data implementation. + result = new ossimImageData(owner, scalar, bands, width, height); + break; + } + } + + return result; +} + +ossimRefPtr<ossimImageData> ossimImageDataFactory::create( + ossimSource* owner, + ossimScalarType scalar, + ossim_uint32 bands, + ossim_uint32 width, + ossim_uint32 height)const +{ + ossimIpt defaultTileSize; + ossimGetDefaultTileSize(defaultTileSize); + // do some bounds checking and initialize to a default + bands = bands > 0?bands:1; + width = width > 0?width:defaultTileSize.x; + height = height > 0?height:defaultTileSize.y; + scalar = scalar != OSSIM_SCALAR_UNKNOWN?scalar:OSSIM_UINT8; + + if (traceDebug()) + { + cout << "ossimImageDataFactory::create DEBUG:" + << "\nCaller: " + << (owner ? owner->getClassName().c_str() : "unknown") + << "\nbands: " << bands + << "\nwidth: " << width + << "\nheight: " << height + << "\nScalar type: " + << (ossimScalarTypeLut::instance()->getEntryString(scalar)) + << endl; + } + + ossimRefPtr<ossimImageData> result = NULL; + switch(scalar) + { + case OSSIM_UINT8: + { + result = new ossimU8ImageData(owner, bands, width, height); + break; + } + + case OSSIM_USHORT11: + { + result = new ossimU11ImageData(owner, bands, width, height); + break; + } + + // ther are bugs in the 16 bit that I don't have time to find. + // The default image data object works good though. + // + // So for now I will comment these out. I think it has something to + // do with the normalization it makes everything black + // + // +// case OSSIM_USHORT16: +// { +// result = new ossimU16ImageData(owner, bands, width, height); +// break; +// } +// case OSSIM_SSHORT16: +// { +// result = new ossimS16ImageData(owner, bands, width, height); +// break; +// } + default: + { + // create a generic image data implementation. + result = new ossimImageData(owner, scalar, bands, width, height); + break; + } + } + + return result; +} + +ossimRefPtr<ossimImageData> ossimImageDataFactory::create( + ossimSource* owner, + ossim_uint32 bands, + ossimImageSourceInterface* inputSource)const +{ + ossimRefPtr<ossimImageData> result = NULL; + + if(inputSource) + { + ossimScalarType scalar = inputSource->getOutputScalarType(); + ossim_uint32 width = inputSource->getTileWidth(); + ossim_uint32 height = inputSource->getTileHeight(); + + result = create(owner, scalar, bands, width, height); + + for(ossim_uint32 band = 0; band < bands; ++band) + { + result->setMinPix(inputSource->getMinPixelValue(band)); + result->setMaxPix(inputSource->getMaxPixelValue(band)); + result->setNullPix(inputSource->getNullPixelValue(band)); + } + } + else + { + cerr << "ossimImageDataFactory::create ERROR:" + << "\nNULL input source!" << endl; + } + + return result; +} + + +ossimRefPtr<ossimImageData> ossimImageDataFactory::create( + ossimSource* owner, + ossimImageSourceInterface* inputSource)const +{ + ossimRefPtr<ossimImageData> result = NULL; + + if(inputSource) + { + ossimScalarType scalar = inputSource->getOutputScalarType(); + ossim_uint32 bands = inputSource->getNumberOfOutputBands(); + ossim_uint32 width = inputSource->getTileWidth(); + ossim_uint32 height = inputSource->getTileHeight(); + + result = create(owner, scalar, bands, width, height); + + for(ossim_uint32 band = 0; band < bands; ++band) + { + result->setMinPix(inputSource->getMinPixelValue(band)); + result->setMaxPix(inputSource->getMaxPixelValue(band)); + } + result->setNullPix(inputSource->getNullPixelValue()); + } + else + { + cerr << "ossimImageDataFactory::create ERROR:" + << "\nNULL input source!" << endl; + } + + return result; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageDataFactory.h b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageDataFactory.h new file mode 100644 index 0000000000..269ad7ebb0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageDataFactory.h @@ -0,0 +1,62 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +//************************************************************************* +// $Id: ossimImageDataFactory.h,v 1.9 2005/05/20 20:25:19 dburken Exp $ +#ifndef ossimImageDataFactory_HEADER +#define ossimImageDataFactory_HEADER + +#include <imaging/ossimImageData.h> +#include <base/common/ossimRefPtr.h> + +class ossimSource; +class ossimImageSourceInterface; + + +/*! + * This factory should be called by all image source producers to allocate + * an image tile. + */ +class OSSIM_DLL ossimImageDataFactory +{ +public: + virtual ~ossimImageDataFactory(); + static ossimImageDataFactory* instance(); + + virtual ossimRefPtr<ossimImageData> create(ossimSource* owner, + ossimScalarType scalar, + ossim_uint32 bands = 1)const; + + virtual ossimRefPtr<ossimImageData> create(ossimSource* owner, + ossimScalarType scalar, + ossim_uint32 bands, + ossim_uint32 width, + ossim_uint32 height)const; + + virtual ossimRefPtr<ossimImageData> create( + ossimSource* owner, + ossim_uint32 bands, + ossimImageSourceInterface* inputSource)const; + + + virtual ossimRefPtr<ossimImageData> create( + ossimSource* owner, + ossimImageSourceInterface* inputSource)const; + +protected: + ossimImageDataFactory(); // hide + ossimImageDataFactory(const ossimImageDataFactory&){}//hide + void operator = (ossimImageDataFactory&){}// hide + + static ossimImageDataFactory* theInstance; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageHandlerFactory.cpp b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageHandlerFactory.cpp new file mode 100644 index 0000000000..7ae79e8297 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageHandlerFactory.cpp @@ -0,0 +1,633 @@ +//---------------------------------------------------------------------------- +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +//---------------------------------------------------------------------------- +// $Id: ossimImageHandlerFactory.cpp,v 1.38 2005/11/17 15:26:20 gpotts Exp $ +#include <imaging/factory/ossimImageHandlerFactory.h> +#include <imaging/formats/adrg/ossimAdrgTileSource.h> +#include <imaging/formats/ccf/ossimCcfTileSource.h> +#include <imaging/formats/cibcadrg/ossimCibCadrgTileSource.h> +#include <imaging/formats/doqq/ossimDoqqTileSource.h> +#include <imaging/formats/dted/ossimDtedTileSource.h> +#include <imaging/formats/nitf/ossimNitfTileSource.h> +#include <imaging/formats/nitf/ossimQuickbirdNitfTileSource.h> +#include <imaging/formats/srtm/ossimSrtmTileSource.h> +#include <imaging/formats/tiff/ossimQuickbirdTiffTileSource.h> +#include <imaging/formats/tiff/ossimTiffTileSource.h> +#include <imaging/formats/usgs_dem/ossimUsgsDemTileSource.h> +#include <imaging/formats/landsat/ossimLandsatTileSource.h> +#include <imaging/formats/general_raster/ossimGeneralRasterTileSource.h> +#include <imaging/formats/ers/ossimERSTileSource.h> +#include <imaging/formats/vpf/ossimVpfTileSource.h> +#include <base/common/ossimTrace.h> +#include <base/common/ossimKeywordNames.h> +#include <imaging/formats/jpeg/ossimJpegTileSource.h> + +static const ossimTrace traceDebug("ossimImageHandlerFactory:debug"); + +RTTI_DEF1(ossimImageHandlerFactory, "ossimImageHandlerFactory", ossimImageHandlerFactoryBase); + +ossimImageHandlerFactory* ossimImageHandlerFactory::theInstance = 0; +ossimImageHandlerFactory::~ossimImageHandlerFactory() +{ + theInstance = (ossimImageHandlerFactory*)NULL; +} + +ossimImageHandlerFactory* ossimImageHandlerFactory::instance() +{ + if(!theInstance) + { + theInstance = new ossimImageHandlerFactory; + + // let's turn off tiff error reporting + TIFFSetErrorHandler(NULL); + TIFFSetWarningHandler(NULL); + } + + return theInstance; +} + +ossimImageHandler* ossimImageHandlerFactory::open(const ossimFilename& fileName)const +{ + ossimFilename copyFilename = fileName; + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimImageHandlerFactory::open(filename) DEBUG: entered..." + << std::endl + << "Attempting to open file " << copyFilename << std::endl; + } + ossimImageHandler* result = NULL; + + + if(copyFilename.ext() == "gz") + { + copyFilename = copyFilename.setExtension(""); + } + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying JPEG" << std::endl; + } + result = new ossimJpegTileSource; + if(result->open(copyFilename)) + { + return result; + } + delete result; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying adrg" << std::endl; + } + + // test if ADRG + result = new ossimAdrgTileSource(); + + if(result->open(copyFilename)) + { + return result; + } + delete result; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying ccf" << std::endl; + } + // test if ccf + result = new ossimCcfTileSource(); + if(result->open(copyFilename)) + { + return result; + } + + delete result; + + // this must be checked first before the TIFF handler + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying Quickbird TIFF" + << std::endl; + } + result = new ossimQuickbirdTiffTileSource; + if(result->open(copyFilename)) + { + return result; + } + delete result; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying tif" << std::endl; + } + // test for tiff + result = new ossimTiffTileSource; + if(result->open(copyFilename)) + { + return result; + } + delete result; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying CIB/CADRG" + << std::endl; + } + result = new ossimCibCadrgTileSource; + if(result->open(copyFilename)) + { + return result; + } + delete result; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying DOQQ" << std::endl; + } + result = new ossimDoqqTileSource; + if(result->open(copyFilename)) + { + return result; + } + delete result; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying DTED" << std::endl; + } + result = new ossimDtedTileSource; + if(result->open(copyFilename)) + { + return result; + } + + delete result; + + // this must be checked first before the NITF raw handler + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying Quickbird Nitf" + << std::endl; + } + result = new ossimQuickbirdNitfTileSource; + if(result->open(copyFilename)) + { + return result; + } + delete result; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying Nitf" << std::endl; + } + result = new ossimNitfTileSource; + if(result->open(copyFilename)) + { + return result; + } + delete result; + + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying USGS Dem" + << std::endl; + } + result = new ossimUsgsDemTileSource; + if(result->open(copyFilename)) + { + return result; + } + delete result; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying Landsat" + << std::endl; + } + result = new ossimLandsatTileSource; + if(result->open(copyFilename)) + { + return result; + } + delete result; + + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying Vpf" << std::endl; + } + result = new ossimVpfTileSource; + if(result->open(copyFilename)) + { + return result; + } + delete result; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying ERS" << std::endl; + } + result = new ossimERSTileSource; + if(result->open(copyFilename)) + { + return result; + } + delete result; + + // Note: SRTM should be in front of general raster... + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying SRTM" + << std::endl; + } + result = new ossimSrtmTileSource; + if(result->open(copyFilename)) + { + return result; + } + delete result; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying General Raster" + << std::endl; + } + result = new ossimGeneralRasterTileSource; + if(result->open(copyFilename)) + { + return result; + } + delete result; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimImageHandlerFactory::open(filename) DEBUG: returning..." << std::endl; + } + return (ossimImageHandler*)NULL; +} + +ossimImageHandler* ossimImageHandlerFactory::open(const ossimKeywordlist& kwl, + const char* prefix)const +{ + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimImageHandlerFactory::open(kwl, prefix) DEBUG: entered..." + << std::endl; + } + ossimImageHandler* result = NULL; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying adrg" << std::endl; + } + result = new ossimAdrgTileSource(); + + if(result->loadState(kwl, prefix)) + { + return result; + } + delete result; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying ccf" << std::endl; + } + result = new ossimCcfTileSource(); + if(result->loadState(kwl, prefix)) + { + return result; + } + delete result; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying CIB/CADRG" + << std::endl; + } + result = new ossimCibCadrgTileSource(); + if(result->loadState(kwl, prefix)) + { + return result; + } + delete result; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying DOQQ" << std::endl; + } + result = new ossimDoqqTileSource(); + if(result->loadState(kwl, prefix)) + { + return result; + } + delete result; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying DTED" << std::endl; + } + result = new ossimDtedTileSource(); + if(result->loadState(kwl, prefix)) + { + return result; + } + delete result; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying jpeg" << std::endl; + } + result = new ossimJpegTileSource(); + if(result->loadState(kwl, prefix)) + { + return result; + } + delete result; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying Quickbird NITF" + << std::endl; + } + result = new ossimQuickbirdNitfTileSource; + if(result->loadState(kwl, prefix)) + { + return result; + } + + delete result; + + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying Nitf" << std::endl; + } + result = new ossimNitfTileSource(); + if(result->loadState(kwl, prefix)) + { + return result; + } + delete result; + + // Must be before tiff... + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying Quickbird TIFF" + << std::endl; + } + result = new ossimQuickbirdTiffTileSource; + if(result->loadState(kwl, prefix)) + { + return result; + } + + delete result; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying tiff" << std::endl; + } + result = new ossimTiffTileSource(); + if(result->loadState(kwl, prefix)) + { + return result; + } + delete result; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying USGS Dem" + << std::endl; + } + result = new ossimUsgsDemTileSource(); + if(result->loadState(kwl, prefix)) + { + return result; + } + delete result; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying Landsat" << std::endl; + } + result = new ossimLandsatTileSource(); + if(result->loadState(kwl, prefix)) + { + return result; + } + delete result; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying VPF" << std::endl; + } + result = new ossimVpfTileSource; + if(result->loadState(kwl, prefix)) + { + return result; + } + delete result; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying ERS" << std::endl; + } + result = new ossimERSTileSource; + if(result->loadState(kwl, prefix)) + { + return result; + } + + // Note: SRTM should be in front of general raster... + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying SRTM" + << std::endl; + } + result = new ossimSrtmTileSource(); + if(result->loadState(kwl, prefix)) + { + return result; + } + delete result; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "trying General Raster" + << std::endl; + } + result = new ossimGeneralRasterTileSource(); + if(result->loadState(kwl, prefix)) + { + return result; + } + delete result; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimImageHandlerFactory::open(kwl, prefix) DEBUG: returning..." + << std::endl; + } + return (ossimImageHandler*)NULL; +} + +ossimObject* ossimImageHandlerFactory::createObject(const ossimString& typeName)const +{ + if(STATIC_TYPE_NAME(ossimAdrgTileSource) == typeName) + { + return new ossimAdrgTileSource(); + } + if(STATIC_TYPE_NAME(ossimCcfTileSource) == typeName) + { + return new ossimCcfTileSource(); + } + if(STATIC_TYPE_NAME(ossimCibCadrgTileSource) == typeName) + { + return new ossimCibCadrgTileSource(); + } + if(STATIC_TYPE_NAME(ossimDoqqTileSource) == typeName) + { + return new ossimDoqqTileSource(); + } + if(STATIC_TYPE_NAME(ossimDtedTileSource) == typeName) + { + return new ossimDtedTileSource(); + } + if(STATIC_TYPE_NAME(ossimJpegTileSource) == typeName) + { + return new ossimJpegTileSource(); + } + if(STATIC_TYPE_NAME(ossimNitfTileSource) == typeName) + { + return new ossimNitfTileSource(); + } + if(STATIC_TYPE_NAME(ossimTiffTileSource) == typeName) + { + return new ossimTiffTileSource(); + } + if(STATIC_TYPE_NAME(ossimUsgsDemTileSource) == typeName) + { + return new ossimUsgsDemTileSource(); + } + if(STATIC_TYPE_NAME(ossimLandsatTileSource) == typeName) + { + return new ossimLandsatTileSource(); + } + if(STATIC_TYPE_NAME(ossimERSTileSource) == typeName) + { + return new ossimERSTileSource(); + } + if(STATIC_TYPE_NAME(ossimSrtmTileSource) == typeName) + { + return new ossimSrtmTileSource(); + } + if(STATIC_TYPE_NAME(ossimGeneralRasterTileSource) == typeName) + { + return new ossimGeneralRasterTileSource(); + } + + return (ossimObject*)NULL; +} + +ossimObject* ossimImageHandlerFactory::createObject(const ossimKeywordlist& kwl, + const char* prefix)const +{ + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimImageHandlerFactory::createObject(kwl, prefix) DEBUG:" + << " entering ..." << std::endl; + } + ossimObject* result = (ossimObject*)NULL; + const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + + if(type) + { + if (ossimString(type).trim() == STATIC_TYPE_NAME(ossimImageHandler)) + { + const char* lookup = kwl.find(prefix, ossimKeywordNames::FILENAME_KW); + + if (lookup) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "BEBUG: filename " << lookup << std::endl; + } + // Call the open that takes a filename... + result = this->open(kwl, prefix);//ossimFilename(lookup)); + } + } + else + { + result = createObject(ossimString(type)); + if(result) + { + result->loadState(kwl, prefix); + } + } + } + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimImageHandlerFactory::createObject(kwl, prefix) DEBUG: returning result ..." << std::endl; + } + return result; +} + +void ossimImageHandlerFactory::getTypeNameList(std::vector<ossimString>& typeList)const +{ + typeList.push_back(STATIC_TYPE_NAME(ossimAdrgTileSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimCcfTileSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimCibCadrgTileSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimDoqqTileSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimDtedTileSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimJpegTileSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimNitfTileSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimTiffTileSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimUsgsDemTileSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimLandsatTileSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimERSTileSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimSrtmTileSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimGeneralRasterTileSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimQuickbirdNitfTileSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimQuickbirdTiffTileSource)); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageHandlerFactory.h b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageHandlerFactory.h new file mode 100644 index 0000000000..cdcdce312f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageHandlerFactory.h @@ -0,0 +1,76 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// +// Description: +// +// Contains class declaration for ossimImageHandlerFactoryMaker. +//******************************************************************* +// $Id: ossimImageHandlerFactory.h,v 1.4 2004/05/26 21:43:14 dburken Exp $ + +#ifndef ossimImageHandlerFactory_HEADER +#define ossimImageHandlerFactory_HEADER +#include "ossimImageHandlerFactoryBase.h" + +#include "base/data_types/ossimString.h" + +class ossimImageHandler; +class ossimFilename; +class ossimKeywordlist; + +//******************************************************************* +// CLASS: ossimImageHandlerFactory +//******************************************************************* +class OSSIMDLLEXPORT ossimImageHandlerFactory : public ossimImageHandlerFactoryBase +{ +public: + virtual ~ossimImageHandlerFactory(); + static ossimImageHandlerFactory* instance(); + + virtual ossimImageHandler* open(const ossimFilename& fileName)const; + virtual ossimImageHandler* open(const ossimKeywordlist& kwl, + const char* prefix=0)const; + + + virtual ossimObject* createObject(const ossimString& typeName)const; + + /*! + * Creates and object given a keyword list. + */ + virtual ossimObject* createObject(const ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * This should return the type name of all objects in all factories. + * This is the name used to construct the objects dynamially and this + * name must be unique. + */ + virtual void getTypeNameList(std::vector<ossimString>& typeList)const; + +protected: + ossimImageHandlerFactory(){} + ossimImageHandlerFactory(const ossimImageHandlerFactory&){} + void operator = (const ossimImageHandlerFactory&){} + + static ossimImageHandlerFactory* theInstance; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageHandlerFactoryBase.cpp b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageHandlerFactoryBase.cpp new file mode 100644 index 0000000000..9229ed7514 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageHandlerFactoryBase.cpp @@ -0,0 +1,25 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//******************************************************************* +// $Id: ossimImageHandlerFactoryBase.cpp,v 1.1 2002/03/26 20:41:04 gpotts Exp $ +#include "ossimImageHandlerFactoryBase.h" + +RTTI_DEF1(ossimImageHandlerFactoryBase, "ossimImageHandlerFactoryBase", ossimObjectFactory); diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageHandlerFactoryBase.h b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageHandlerFactoryBase.h new file mode 100644 index 0000000000..2493a05688 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageHandlerFactoryBase.h @@ -0,0 +1,44 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//******************************************************************* +// $Id: ossimImageHandlerFactoryBase.h,v 1.3 2005/05/20 20:25:19 dburken Exp $ + +#ifndef ossimImageHandlerFactoryBase_HEADER +#define ossimImageHandlerFactoryBase_HEADER + +#include "base/data_types/ossimString.h" +#include "base/factory/ossimObjectFactory.h" + +class ossimImageHandler; +class ossimFilename; +class ossimKeywordlist; + +class OSSIM_DLL ossimImageHandlerFactoryBase : public ossimObjectFactory +{ +public: + virtual ossimImageHandler* open(const ossimFilename& fileName)const = 0; + virtual ossimImageHandler* open(const ossimKeywordlist& kwl, + const char* prefix=0)const = 0; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageHandlerRegistry.cpp b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageHandlerRegistry.cpp new file mode 100644 index 0000000000..8682c95cff --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageHandlerRegistry.cpp @@ -0,0 +1,193 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Contains class definition for ImageHandlerRegistry. +// +//******************************************************************* +// $Id: ossimImageHandlerRegistry.cpp,v 1.15 2004/01/13 19:24:31 gpotts Exp $ +#include <algorithm> +#include "ossimImageHandlerRegistry.h" +#include "ossimImageHandlerFactory.h" +#include "ossimImageHandlerFactoryBase.h" +#include "base/data_types/ossimFilename.h" +#include "imaging/formats/ossimImageHandler.h" +#include "base/factory/ossimObjectFactoryRegistry.h" + +using namespace std; + +RTTI_DEF1(ossimImageHandlerRegistry, "ossimImageHandlerRegistry", ossimObjectFactory); + +ossimImageHandlerRegistry* ossimImageHandlerRegistry::theInstance = 0; + +ossimImageHandlerRegistry::ossimImageHandlerRegistry() +{ +} + +ossimImageHandlerRegistry* ossimImageHandlerRegistry::instance() +{ + if (theInstance == 0) + { + theInstance = new ossimImageHandlerRegistry(); + ossimObjectFactoryRegistry::instance()->registerFactory(theInstance); + theInstance->registerFactory(ossimImageHandlerFactory::instance()); + } + return theInstance; +} + +ossimImageHandlerRegistry::~ossimImageHandlerRegistry() +{ + clear(); + theInstance = 0; +} + +void ossimImageHandlerRegistry::registerFactory(ossimImageHandlerFactoryBase* factory) +{ + if(factory&&!findFactory(factory)) + { + theFactoryList.push_back(factory); + } +} + +void ossimImageHandlerRegistry::unregisterFactory(ossimImageHandlerFactoryBase* factory) +{ + std::vector<ossimImageHandlerFactoryBase*>::iterator iter = std::find(theFactoryList.begin(), + theFactoryList.end(), + factory); + if(iter != theFactoryList.end()) + { + theFactoryList.erase(iter); + } +} + +bool ossimImageHandlerRegistry::findFactory(ossimImageHandlerFactoryBase* factory)const +{ + return (std::find(theFactoryList.begin(), + theFactoryList.end(), + factory)!=theFactoryList.end()); +} + + +ossimObject* ossimImageHandlerRegistry::createObject(const ossimString& typeName)const +{ + ossimObject* result = NULL; + vector<ossimImageHandlerFactoryBase*>::const_iterator factory; + + factory = theFactoryList.begin(); + while((factory != theFactoryList.end()) && !result) + { + result = (*factory)->createObject(typeName); + ++factory; + } + + return result; + +} + +ossimObject* ossimImageHandlerRegistry::createObject(const ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimObject* result = NULL; + vector<ossimImageHandlerFactoryBase*>::const_iterator factory; + + factory = theFactoryList.begin(); + while((factory != theFactoryList.end()) && !result) + { + result = (*factory)->createObject(kwl, prefix); + ++factory; + } + if(!result) + { + result = open(kwl, prefix); + } + return result; +} + +void ossimImageHandlerRegistry::getTypeNameList(std::vector<ossimString>& typeList)const +{ + vector<ossimString> result; + vector<ossimImageHandlerFactoryBase*>::const_iterator iter = theFactoryList.begin(); + + while(iter != theFactoryList.end()) + { + result.clear(); + (*iter)->getTypeNameList(result); + + // now append to the end of the typeList. + typeList.insert(typeList.end(), + result.begin(), + result.end()); + ++iter; + } +} + +ossimImageHandler* ossimImageHandlerRegistry::open(const ossimFilename& fileName)const +{ + ossimImageHandler* result = NULL; + vector<ossimImageHandlerFactoryBase*>::const_iterator factory; + + factory = theFactoryList.begin(); + while((factory != theFactoryList.end()) && !result) + { + + result = (*factory)->open(fileName); + ++factory; + } + + return result; +} + +ossimImageHandler* ossimImageHandlerRegistry::open(const ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimImageHandler* result = NULL; + vector<ossimImageHandlerFactoryBase*>::const_iterator factory; + + factory = theFactoryList.begin(); + while((factory != theFactoryList.end()) && !result) + { + result = (*factory)->open(kwl, prefix); + ++factory; + } + + return result; +} + +void ossimImageHandlerRegistry::clear() +{ + theFactoryList.clear(); +} + +ossimImageHandlerRegistry::ossimImageHandlerRegistry(const ossimImageHandlerRegistry& rhs) + : ossimObjectFactory() +{} + +const ossimImageHandlerRegistry& +ossimImageHandlerRegistry::operator=(const ossimImageHandlerRegistry& rhs) +{ return rhs; } + +extern "C" +{ + void* ossimImageHandlerRegistryGetInstance() + { + return ossimImageHandlerRegistry::instance(); + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageHandlerRegistry.h b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageHandlerRegistry.h new file mode 100644 index 0000000000..38df422ac4 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageHandlerRegistry.h @@ -0,0 +1,98 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpott@imagelinks.com) +// +// Description: Contains class definition for the class +// ImageHandlerRegistry. +// +//******************************************************************* +// $Id: ossimImageHandlerRegistry.h,v 1.11 2004/05/19 17:54:51 dburken Exp $ + +#ifndef ossimImageHandlerRegistry_HEADER +#define ossimImageHandlerRegistry_HEADER + +#include <vector> +#include "base/factory/ossimObjectFactory.h" +#include "base/common/ossimRtti.h" + +class ossimImageHandler; +class ossimImageHandlerFactoryBase; +class ossimFilename; +class ossimKeywordlist; + +class OSSIMDLLEXPORT ossimImageHandlerRegistry : public ossimObjectFactory +{ +public: + ~ossimImageHandlerRegistry(); + static ossimImageHandlerRegistry* instance(); + + void addFactory(ossimImageHandlerFactoryBase* factory) + { + registerFactory(factory); + } + void registerFactory(ossimImageHandlerFactoryBase* factory); + void unregisterFactory(ossimImageHandlerFactoryBase* factory); + bool findFactory(ossimImageHandlerFactoryBase* factory)const; + + ossimImageHandler* open(const ossimFilename& fileName)const; + + + /*! + * Given a keyword list return a pointer to an ImageHandler. Returns + * null if a valid handler cannot be found. + */ + ossimImageHandler* open(const ossimKeywordlist& kwl, const char* prefix=0)const; + + /*! + * Creates an object given a type name. + */ + virtual ossimObject* createObject(const ossimString& typeName)const; + + /*! + * Creates and object given a keyword list. + */ + virtual ossimObject* createObject(const ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * This should return the type name of all objects in all factories. + * This is the name used to construct the objects dynamially and this + * name must be unique. + */ + virtual void getTypeNameList(std::vector<ossimString>& typeList)const; + +protected: + ossimImageHandlerRegistry(); + ossimImageHandlerRegistry(const ossimImageHandlerRegistry& rhs); + const ossimImageHandlerRegistry& + operator=(const ossimImageHandlerRegistry& rhs); + +private: + void clear(); + std::vector<ossimImageHandlerFactoryBase*> theFactoryList; + static ossimImageHandlerRegistry* theInstance; + +TYPE_DATA +}; + +extern "C" +{ + OSSIMDLLEXPORT void* ossimImageHandlerRegistryGetInstance(); +} +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageMetaDataWriterFactory.cpp b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageMetaDataWriterFactory.cpp new file mode 100644 index 0000000000..cc80fb0906 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageMetaDataWriterFactory.cpp @@ -0,0 +1,206 @@ +//******************************************************************* +// Copyright (C) 2003 Storage Area Networks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Kenneth Melero +// +//******************************************************************* +// $Id: ossimImageMetaDataWriterFactory.cpp,v 1.11 2005/08/09 19:10:41 dburken Exp $ + +#include <imaging/factory/ossimImageMetaDataWriterFactory.h> + +#include <imaging/metadata/ossimEnviHeaderFileWriter.h> +#include <imaging/metadata/ossimFgdcFileWriter.h> +#include <imaging/metadata/ossimGeomFileWriter.h> +#include <imaging/metadata/ossimJpegWorldFileWriter.h> +#include <imaging/metadata/ossimReadmeFileWriter.h> +#include <imaging/metadata/ossimTiffWorldFileWriter.h> + +#include <base/common/ossimKeywordNames.h> + +RTTI_DEF1(ossimImageMetaDataWriterFactory, + "ossimImageMetaDataWriterFactory", + ossimImageMetaDataWriterFactoryBase); + +ossimImageMetaDataWriterFactory* +ossimImageMetaDataWriterFactory::theInstance = NULL; + +ossimImageMetaDataWriterFactory::ossimImageMetaDataWriterFactory() +{ + theInstance = this; +} + +ossimImageMetaDataWriterFactory::~ossimImageMetaDataWriterFactory() +{ + theInstance = NULL; +} + +ossimImageMetaDataWriterFactory* ossimImageMetaDataWriterFactory::instance() +{ + if(!theInstance) + { + theInstance = new ossimImageMetaDataWriterFactory; + } + + return theInstance; +} + +ossimObject* ossimImageMetaDataWriterFactory::createObject( + const ossimString& typeName) const +{ + // Use the type name to instantiate the class. + ossimObject* result = (ossimObject*)NULL; + + if(STATIC_TYPE_NAME(ossimEnviHeaderFileWriter) == typeName) + { + result = new ossimEnviHeaderFileWriter; + } + else if(STATIC_TYPE_NAME(ossimFgdcFileWriter) == typeName) + { + result = new ossimFgdcFileWriter; + } + else if(STATIC_TYPE_NAME(ossimGeomFileWriter) == typeName) + { + result = new ossimGeomFileWriter; + } + else if(STATIC_TYPE_NAME(ossimJpegWorldFileWriter) == typeName) + { + result = new ossimJpegWorldFileWriter; + } + else if(STATIC_TYPE_NAME(ossimReadmeFileWriter) == typeName) + { + result = new ossimReadmeFileWriter; + } + else if(STATIC_TYPE_NAME(ossimTiffWorldFileWriter) == typeName) + { + result = new ossimTiffWorldFileWriter; + } + + return result; +} + +ossimObject* ossimImageMetaDataWriterFactory::createObject( + const ossimKeywordlist& kwl, const char* prefix)const +{ + //--- + // Check the type keyword found in kwl. Use the create by class name + // above and then call load state. + //--- + ossimObject* result = (ossimObject*)NULL; + + const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + + if(type) + { + result = createObject(ossimString(type)); + if(result) + { + result->loadState(kwl, prefix); + } + } + + return result; +} + +ossimRefPtr<ossimMetadataFileWriter> +ossimImageMetaDataWriterFactory::createWriter(const ossimString& type)const +{ + ossimRefPtr<ossimMetadataFileWriter> writer; + + writer = new ossimEnviHeaderFileWriter; + if ( (writer->getClassName() == type) || + (writer->hasMetadataType(type)) ) + { + return writer; + } + + writer = new ossimFgdcFileWriter; + if ( (writer->getClassName() == type) || + (writer->hasMetadataType(type)) ) + { + return writer; + } + + writer = new ossimGeomFileWriter; + if ( (writer->getClassName() == type) || + (writer->hasMetadataType(type)) ) + { + return writer; + } + + writer = new ossimJpegWorldFileWriter; + if ( (writer->getClassName() == type) || + (writer->hasMetadataType(type)) ) + { + return writer; + } + + writer = new ossimReadmeFileWriter; + if ( (writer->getClassName() == type) || + (writer->hasMetadataType(type)) ) + { + return writer; + } + + writer = new ossimTiffWorldFileWriter; + if ( (writer->getClassName() == type) || + (writer->hasMetadataType(type)) ) + { + return writer; + } + + // Not in factory. + writer = NULL; + return writer; +} + +void ossimImageMetaDataWriterFactory::getTypeNameList( + std::vector<ossimString>& typeList) const +{ + // add each object's RTTI name here + typeList.push_back(STATIC_TYPE_NAME(ossimEnviHeaderFileWriter)); + typeList.push_back(STATIC_TYPE_NAME(ossimFgdcFileWriter)); + typeList.push_back(STATIC_TYPE_NAME(ossimGeomFileWriter)); + typeList.push_back(STATIC_TYPE_NAME(ossimJpegWorldFileWriter)); + typeList.push_back(STATIC_TYPE_NAME(ossimReadmeFileWriter)); + typeList.push_back(STATIC_TYPE_NAME(ossimTiffWorldFileWriter)); +} + +void ossimImageMetaDataWriterFactory::getMetadatatypeList( + std::vector<ossimString>& metadatatypeList) const +{ + ossimRefPtr<ossimMetadataFileWriter> writer; + + writer = new ossimEnviHeaderFileWriter; + writer->getMetadatatypeList(metadatatypeList); + + writer = new ossimFgdcFileWriter; + writer->getMetadatatypeList(metadatatypeList); + + writer = new ossimGeomFileWriter; + writer->getMetadatatypeList(metadatatypeList); + + writer = new ossimJpegWorldFileWriter; + writer->getMetadatatypeList(metadatatypeList); + + writer = new ossimReadmeFileWriter; + writer->getMetadatatypeList(metadatatypeList); + + writer = new ossimTiffWorldFileWriter; + writer->getMetadatatypeList(metadatatypeList); +} + +ossimImageMetaDataWriterFactory::ossimImageMetaDataWriterFactory( + const ossimImageMetaDataWriterFactory& rhs) +{ +} + +const ossimImageMetaDataWriterFactory& +ossimImageMetaDataWriterFactory::operator=( + const ossimImageMetaDataWriterFactory& rhs) +{ + return *this; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageMetaDataWriterFactory.h b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageMetaDataWriterFactory.h new file mode 100644 index 0000000000..5bccd9656b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageMetaDataWriterFactory.h @@ -0,0 +1,87 @@ +//******************************************************************* +// Copyright (C) 2003 Storage Area Networks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Kenneth Melero (kmelero@sanz.com) +// +//******************************************************************* +// $Id: ossimImageMetaDataWriterFactory.h,v 1.5 2005/08/08 22:01:32 dburken Exp $ + +#ifndef ossimImageMetaDataWriterFactory_HEADER +#define ossimImageMetaDataWriterFactory_HEADER + +#include <imaging/factory/ossimImageMetaDataWriterFactoryBase.h> +#include <base/common/ossimRefPtr.h> + +class ossimMetadataFileWriter; + +class OSSIMDLLEXPORT ossimImageMetaDataWriterFactory: + public ossimImageMetaDataWriterFactoryBase +{ +public: + ~ossimImageMetaDataWriterFactory(); + + static ossimImageMetaDataWriterFactory* instance(); + virtual ossimObject* createObject(const ossimString& typeName)const; + virtual ossimObject* createObject(const ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Creates a writer from either a class name or a string representing the + * meta data type like "tiff_world_file". + * + * @return ossimRefPtr<ossimMetadataFileWriter> + * + * @note Return can have a null pointer if type is not found in a factory so + * the caller should always check the pointer like: + * ossimRefPtr<ossimMetadataFileWriter> mw = + * ossimImageMetaDataWriterRegistry::instance("ossim_readme"); + * if (!mw.valid()) + * { + * // not in factory + * } + */ + virtual ossimRefPtr<ossimMetadataFileWriter> createWriter( + const ossimString& type)const; + + /** + * This should return the type name of all objects in all factories. + * This is the name used to construct the objects dynamially and this + * name must be unique. + */ + virtual void getTypeNameList(std::vector<ossimString>& typeList)const; + + /** + * Satisfies pure virtual from ossimImageMetaDataWriterFactoryBase. + * + * Appends the meta data writers types from each of the supported meta + * data writers in this factor to the "metadatatypeList". + * + * This is the actual metadata type name like: + * ossim_geometry + * envi_header + * tiff_world_file + * jpeg_world_file + * + * @param metadatatypeList stl::vector<ossimString> List to append to. + */ + virtual void getMetadatatypeList( + std::vector<ossimString>& metadatatypeList) const; + +protected: + static ossimImageMetaDataWriterFactory* theInstance; + + ossimImageMetaDataWriterFactory(); + + ossimImageMetaDataWriterFactory(const ossimImageMetaDataWriterFactory& rhs); + + const ossimImageMetaDataWriterFactory& operator =( + const ossimImageMetaDataWriterFactory& rhs); + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageMetaDataWriterFactoryBase.cpp b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageMetaDataWriterFactoryBase.cpp new file mode 100644 index 0000000000..c8cfae7dda --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageMetaDataWriterFactoryBase.cpp @@ -0,0 +1,28 @@ +//---------------------------------------------------------------------------- +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +//---------------------------------------------------------------------------- +// $Id: ossimImageMetaDataWriterFactoryBase.cpp,v 1.2 2005/06/24 17:54:09 dburken Exp $ + +#include <imaging/factory/ossimImageMetaDataWriterFactoryBase.h> + +RTTI_DEF1(ossimImageMetaDataWriterFactoryBase, + "ossimImageMetaDataWriterFactoryBase", + ossimObjectFactory); + +ossimImageMetaDataWriterFactoryBase::ossimImageMetaDataWriterFactoryBase() +{ +} + +ossimImageMetaDataWriterFactoryBase::ossimImageMetaDataWriterFactoryBase( + const ossimImageMetaDataWriterFactoryBase&) +{ +} + +const ossimImageMetaDataWriterFactoryBase& +ossimImageMetaDataWriterFactoryBase::operator=( + const ossimImageMetaDataWriterFactoryBase&) +{ + return *this; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageMetaDataWriterFactoryBase.h b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageMetaDataWriterFactoryBase.h new file mode 100644 index 0000000000..30efed5fbc --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageMetaDataWriterFactoryBase.h @@ -0,0 +1,67 @@ +//---------------------------------------------------------------------------- +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +//---------------------------------------------------------------------------- +// $Id: ossimImageMetaDataWriterFactoryBase.h,v 1.3 2005/08/08 22:01:32 dburken Exp $ +#ifndef ossimImageMetaDataWriterFactoryBase_HEADER +#define ossimImageMetaDataWriterFactoryBase_HEADER +#include <base/factory/ossimObjectFactory.h> +#include <base/common/ossimRefPtr.h> + +class ossimMetadataFileWriter; + +class ossimImageMetaDataWriterFactoryBase : public ossimObjectFactory +{ +public: + /** + * Pure virtual. All ossimImageMetaDataWriterFactories must implement. + * + * Creates a writer from either a class name or a string representing the + * meta data type like "tiff_world_file". + * + * @return ossimRefPtr<ossimMetadataFileWriter> + * + * @note Return can have a null pointer if type is not found in a factory so + * the caller should always check the pointer like: + * ossimRefPtr<ossimMetadataFileWriter> mw = + * ossimImageMetaDataWriterRegistry::instance("ossim_readme"); + * if (!mw.valid()) + * { + * // not in factory + * } + */ + virtual ossimRefPtr<ossimMetadataFileWriter> createWriter( + const ossimString& type)const=0; + + /** + * Pure virtual. All ossimImageMetaDataWriterFactories must implement. + * + * Appends the meta data writers types to the "metadatatypeList". + * + * This is the actual metadata type name like: + * ossim_geometry + * envi_header + * tiff_world_file + * jpeg_world_file + * + * @param metadatatypeList stl::vector<ossimString> List to append to. + * + * @note All writers should append to the list, not, clear it and then add + * their types. + */ + virtual void getMetadatatypeList( + std::vector<ossimString>& metadatatypeList) const=0; + +protected: + ossimImageMetaDataWriterFactoryBase(); + + ossimImageMetaDataWriterFactoryBase( + const ossimImageMetaDataWriterFactoryBase&); + + const ossimImageMetaDataWriterFactoryBase& operator=( + const ossimImageMetaDataWriterFactoryBase&); + +TYPE_DATA +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageMetaDataWriterRegistry.cpp b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageMetaDataWriterRegistry.cpp new file mode 100644 index 0000000000..ff901bd424 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageMetaDataWriterRegistry.cpp @@ -0,0 +1,176 @@ +//---------------------------------------------------------------------------- +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +//---------------------------------------------------------------------------- +// $Id: ossimImageMetaDataWriterRegistry.cpp,v 1.10 2005/08/08 22:01:32 dburken Exp $ + + +#include <imaging/factory/ossimImageMetaDataWriterRegistry.h> +#include <imaging/factory/ossimImageMetaDataWriterFactory.h> +#include <imaging/metadata/ossimMetadataFileWriter.h> +#include <base/factory/ossimObjectFactoryRegistry.h> +#include <algorithm> + +ossimImageMetaDataWriterRegistry* +ossimImageMetaDataWriterRegistry::theInstance= NULL; + +ossimImageMetaDataWriterRegistry::ossimImageMetaDataWriterRegistry() +{ + theInstance = this; +} + +ossimImageMetaDataWriterRegistry::~ossimImageMetaDataWriterRegistry() +{ + ossimObjectFactoryRegistry::instance()->unregisterFactory(theInstance); + theInstance = NULL; +} + +ossimImageMetaDataWriterRegistry* ossimImageMetaDataWriterRegistry::instance() +{ + if(!theInstance) + { + theInstance = new ossimImageMetaDataWriterRegistry; + theInstance->registerFactory(ossimImageMetaDataWriterFactory::instance()); + ossimObjectFactoryRegistry::instance()->registerFactory(theInstance); + } + + return theInstance; +} + +void ossimImageMetaDataWriterRegistry::registerFactory( + ossimImageMetaDataWriterFactoryBase* factory) +{ + if(factory&&!findFactory(factory)) + { + theFactoryList.push_back(factory); + } +} + +void ossimImageMetaDataWriterRegistry::unregisterFactory( + ossimImageMetaDataWriterFactoryBase* factory) +{ + std::vector<ossimImageMetaDataWriterFactoryBase*>::iterator iter = + std::find(theFactoryList.begin(), + theFactoryList.end(), + factory); + if(iter != theFactoryList.end()) + { + theFactoryList.erase(iter); + } +} + +bool ossimImageMetaDataWriterRegistry::findFactory( + ossimImageMetaDataWriterFactoryBase* factory)const +{ + return (std::find(theFactoryList.begin(), + theFactoryList.end(), + factory)!=theFactoryList.end()); +} + + +ossimObject* ossimImageMetaDataWriterRegistry::createObject( + const ossimString& typeName) const +{ + ossimObject* result = NULL; + vector<ossimImageMetaDataWriterFactoryBase*>::const_iterator factory; + + factory = theFactoryList.begin(); + while((factory != theFactoryList.end()) && !result) + { + result = (*factory)->createObject(typeName); + ++factory; + } + + return result; +} + +ossimObject* ossimImageMetaDataWriterRegistry::createObject( + const ossimKeywordlist& kwl, + const char* prefix) const +{ + ossimObject* result = NULL; + vector<ossimImageMetaDataWriterFactoryBase*>::const_iterator factory; + + factory = theFactoryList.begin(); + while((factory != theFactoryList.end()) && !result) + { + result = (*factory)->createObject(kwl, prefix); + ++factory; + } + return result; +} + +ossimRefPtr<ossimMetadataFileWriter> +ossimImageMetaDataWriterRegistry::createWriter(const ossimString& type) const +{ + ossimRefPtr<ossimMetadataFileWriter> result = NULL; + + vector<ossimImageMetaDataWriterFactoryBase*>::const_iterator factory; + factory = theFactoryList.begin(); + while((factory != theFactoryList.end()) && !result) + { + result = (*factory)->createWriter(type); + ++factory; + } + return result; +} + +void ossimImageMetaDataWriterRegistry::getTypeNameList( + std::vector<ossimString>& typeList) const +{ + vector<ossimString> result; + vector<ossimImageMetaDataWriterFactoryBase*>::const_iterator iter = + theFactoryList.begin(); + + while(iter != theFactoryList.end()) + { + result.clear(); + (*iter)->getTypeNameList(result); + + // now append to the end of the typeList. + typeList.insert(typeList.end(), + result.begin(), + result.end()); + ++iter; + } +} + +void ossimImageMetaDataWriterRegistry::getMetadatatypeList( + std::vector<ossimString>& metadatatypeList) const +{ + //--- + // Since this is the master registry for all meta data writer factories + // we will start with a cleared list. + //--- + metadatatypeList.clear(); + + vector<ossimImageMetaDataWriterFactoryBase*>::const_iterator iter = + theFactoryList.begin(); + + while(iter != theFactoryList.end()) + { + (*iter)->getMetadatatypeList(metadatatypeList); + ++iter; + } +} + +ossimImageMetaDataWriterRegistry::ossimImageMetaDataWriterRegistry( + const ossimImageMetaDataWriterRegistry& rhs) +{ +} + +const ossimImageMetaDataWriterRegistry& +ossimImageMetaDataWriterRegistry::operator=( + const ossimImageMetaDataWriterRegistry &rhs) +{ + return *this; +} + +extern "C" +{ + void* ossimImageMetaDataWriterRegistryGetInstance() + { + return ossimImageMetaDataWriterRegistry::instance(); + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageMetaDataWriterRegistry.h b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageMetaDataWriterRegistry.h new file mode 100644 index 0000000000..3caecd25a4 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageMetaDataWriterRegistry.h @@ -0,0 +1,98 @@ +//---------------------------------------------------------------------------- +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +//---------------------------------------------------------------------------- +// $Id: ossimImageMetaDataWriterRegistry.h,v 1.6 2005/08/08 22:01:32 dburken Exp $ + +#ifndef ossimImageMetaDataWriterRegistry_HEADER +#define ossimImageMetaDataWriterRegistry_HEADER +#include <imaging/factory/ossimImageMetaDataWriterFactoryBase.h> +#include <base/common/ossimRefPtr.h> + +class ossimMetadataFileWriter; + +class OSSIMDLLEXPORT ossimImageMetaDataWriterRegistry : + public ossimImageMetaDataWriterFactoryBase +{ +public: + ~ossimImageMetaDataWriterRegistry(); + + static ossimImageMetaDataWriterRegistry* instance(); + + void registerFactory(ossimImageMetaDataWriterFactoryBase* factory); + void unregisterFactory(ossimImageMetaDataWriterFactoryBase* factory); + bool findFactory(ossimImageMetaDataWriterFactoryBase* factory)const; + /** + * Creates an object given a type name. + */ + virtual ossimObject* createObject(const ossimString& typeName)const; + + /** + * Creates and object given a keyword list. + */ + virtual ossimObject* createObject(const ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Creates a writer from either a class name or a string representing the + * meta data type like "tiff_world_file". + * + * @return ossimRefPtr<ossimMetadataFileWriter> + * + * @note Return can have a null pointer if type is not found in a factory so + * the caller should always check the pointer like: + * ossimRefPtr<ossimMetadataFileWriter> mw = + * ossimImageMetaDataWriterRegistry::instance("ossim_readme"); + * if (!mw.valid()) + * { + * // not in factory + * } + */ + virtual ossimRefPtr<ossimMetadataFileWriter> createWriter( + const ossimString& type)const; + + /** + * This should return the type name of all objects in all factories. + * This is the name used to construct the objects dynamially and this + * name must be unique. + */ + virtual void getTypeNameList(std::vector<ossimString>& typeList)const; + + /** + * Initializes list with meta data types from all registered + * metadata factories. + * + * This is the actual image type name like: + * ossim_geometry + * envi_header + * tiff_world_file + * jpeg_world_file + * + * @param metadatatypeList stl::vector<ossimString> list to append to. + * + * @note Since this is the master registry for all meta data factories + * this method starts by clearing the metadatatypeList. + */ + virtual void getMetadatatypeList( + std::vector<ossimString>& metadatatypeList)const; + +protected: + ossimImageMetaDataWriterRegistry(); + + ossimImageMetaDataWriterRegistry( + const ossimImageMetaDataWriterRegistry& rhs); + + const ossimImageMetaDataWriterRegistry& operator=( + const ossimImageMetaDataWriterRegistry &rhs); + + static ossimImageMetaDataWriterRegistry* theInstance; + std::vector<ossimImageMetaDataWriterFactoryBase*> theFactoryList; +}; + + +extern "C" +{ + OSSIMDLLEXPORT void* ossimImageMetaDataWriterRegistryGetInstance(); +} +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageReconstructionFilterFactory.cpp b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageReconstructionFilterFactory.cpp new file mode 100644 index 0000000000..f4ef8bca43 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageReconstructionFilterFactory.cpp @@ -0,0 +1,86 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimImageReconstructionFilterFactory.cpp,v 1.3 2004/08/30 11:23:26 gpotts Exp $ +#include "ossimImageReconstructionFilterFactory.h" +#include "base/common/ossimTrace.h" +#include "imaging/reconstruction/ossimMeanMedianFilter.h" +#include "base/common/ossimKeywordNames.h" + +RTTI_DEF1(ossimImageReconstructionFilterFactory, "ossimImageReconstructionFilterFactory", ossimImageSourceFactoryBase); + +ossimImageReconstructionFilterFactory* ossimImageReconstructionFilterFactory::theInstance = 0; + +ossimImageReconstructionFilterFactory::~ossimImageReconstructionFilterFactory() +{ + theInstance = NULL; +} + +ossimImageReconstructionFilterFactory* ossimImageReconstructionFilterFactory::instance() +{ + if(!theInstance) + { + theInstance = new ossimImageReconstructionFilterFactory; + } + + return theInstance; +} + +ossimImageReconstructionFilterFactory::ossimImageReconstructionFilterFactory() +{ + theInstance = this; +} + +ossimObject* ossimImageReconstructionFilterFactory::createObject(const ossimString& name)const +{ + if(STATIC_TYPE_NAME(ossimMeanMedianFilter) == name) + { + return new ossimMeanMedianFilter; + } + + return 0; +} + +ossimObject* ossimImageReconstructionFilterFactory::createObject(const ossimKeywordlist& kwl, + const char* prefix)const +{ + const char* typeKw = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + + if(typeKw) + { + ossimObject* obj = createObject(ossimString(typeKw).trim()); + + if(obj) + { + obj->loadState(kwl, + prefix); + + return obj; + } + } + + return 0; +} + +void ossimImageReconstructionFilterFactory::getTypeNameList(std::vector<ossimString>& typeList)const +{ + typeList.push_back(STATIC_TYPE_NAME(ossimMeanMedianFilter)); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageReconstructionFilterFactory.h b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageReconstructionFilterFactory.h new file mode 100644 index 0000000000..ac91f0704d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageReconstructionFilterFactory.h @@ -0,0 +1,47 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimImageReconstructionFilterFactory.h,v 1.1 2004/01/21 14:57:25 gpotts Exp $ +#ifndef ossimImageReconstructionFilterFactory_HEADER +#define ossimImageReconstructionFilterFactory_HEADER +#include "ossimImageSourceFactoryBase.h" + +class ossimImageReconstructionFilterFactory : public ossimImageSourceFactoryBase +{ +public: + virtual ~ossimImageReconstructionFilterFactory(); + static ossimImageReconstructionFilterFactory* instance(); + virtual ossimObject* createObject(const ossimString& name)const; + virtual ossimObject* createObject(const ossimKeywordlist& kwl, + const char* prefix=0)const; + virtual void getTypeNameList(std::vector<ossimString>& typeList)const; + + +protected: + ossimImageReconstructionFilterFactory(); // hide + ossimImageReconstructionFilterFactory(const ossimImageReconstructionFilterFactory&){}//hide + void operator = (ossimImageReconstructionFilterFactory&){}// hide + + static ossimImageReconstructionFilterFactory* theInstance; + +TYPE_DATA +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageReconstructionFilterRegistry.cpp b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageReconstructionFilterRegistry.cpp new file mode 100644 index 0000000000..53cf74e765 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageReconstructionFilterRegistry.cpp @@ -0,0 +1,126 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimImageReconstructionFilterRegistry.cpp,v 1.3 2005/10/17 18:42:27 gpotts Exp $ +#include <algorithm> +#include "ossimImageReconstructionFilterRegistry.h" +#include "ossimImageReconstructionFilterFactory.h" + +ossimImageReconstructionFilterRegistry* ossimImageReconstructionFilterRegistry::theInstance = 0; + +RTTI_DEF1(ossimImageReconstructionFilterRegistry, "ossimImageReconstructionFilterRegistry", ossimImageSourceFactoryBase); + +ossimImageReconstructionFilterRegistry::ossimImageReconstructionFilterRegistry() +{ + theInstance = this; +} + +ossimImageReconstructionFilterRegistry::~ossimImageReconstructionFilterRegistry() +{ + theInstance = NULL; +} + +ossimImageReconstructionFilterRegistry* ossimImageReconstructionFilterRegistry::instance() +{ + if(theInstance == NULL) + { + theInstance = new ossimImageReconstructionFilterRegistry; + theInstance->registerFactory(ossimImageReconstructionFilterFactory::instance()); + } + return theInstance; +} + +ossimObject* ossimImageReconstructionFilterRegistry::createObject(const ossimString& name)const +{ + ossimObject* result = NULL; + std::vector<ossimImageSourceFactoryBase*>::const_iterator factory; + + factory = theFactoryList.begin(); + while((factory != theFactoryList.end()) && !result) + { + result = (*factory)->createObject(name); + ++factory; + } + + return result; +} + +ossimObject* ossimImageReconstructionFilterRegistry::createObject(const ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimObject* result = NULL; + std::vector<ossimImageSourceFactoryBase*>::const_iterator factory; + + factory = theFactoryList.begin(); + while((factory != theFactoryList.end()) && !result) + { + result = (*factory)->createObject(kwl, prefix); + ++factory; + } + + return result; + +} + +void ossimImageReconstructionFilterRegistry::getTypeNameList(std::vector<ossimString>& typeList)const +{ + std::vector<ossimString> result; + std::vector<ossimImageSourceFactoryBase*>::const_iterator iter = theFactoryList.begin(); + + while(iter != theFactoryList.end()) + { + result.clear(); + (*iter)->getTypeNameList(result); + + // now append to the end of the typeList. + typeList.insert(typeList.end(), + result.begin(), + result.end()); + ++iter; + } + +} + +void ossimImageReconstructionFilterRegistry::registerFactory(ossimImageSourceFactoryBase* factory) +{ + if(factory&&!findFactory(factory)) + { + theFactoryList.push_back(factory); + } +} + +void ossimImageReconstructionFilterRegistry::unregisterFactory(ossimImageSourceFactoryBase* factory) +{ + std::vector<ossimImageSourceFactoryBase*>::iterator iter = std::find(theFactoryList.begin(), + theFactoryList.end(), + factory); + if(iter != theFactoryList.end()) + { + theFactoryList.erase(iter); + } +} + +bool ossimImageReconstructionFilterRegistry::findFactory(ossimImageSourceFactoryBase* factory)const +{ + return (std::find(theFactoryList.begin(), + theFactoryList.end(), + factory)!=theFactoryList.end()); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageReconstructionFilterRegistry.h b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageReconstructionFilterRegistry.h new file mode 100644 index 0000000000..aea8ea6ea2 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageReconstructionFilterRegistry.h @@ -0,0 +1,51 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimImageReconstructionFilterRegistry.h,v 1.1 2004/01/21 14:57:25 gpotts Exp $ +#ifndef ossimImageReconstructionFilterRegistry_HEADER +#define ossimImageReconstructionFilterRegistry_HEADER +#include "ossimImageSourceFactoryBase.h" + +class ossimImageReconstructionFilterRegistry : public ossimImageSourceFactoryBase +{ +public: + virtual ~ossimImageReconstructionFilterRegistry(); + static ossimImageReconstructionFilterRegistry* instance(); + virtual ossimObject* createObject(const ossimString& name)const; + virtual ossimObject* createObject(const ossimKeywordlist& kwl, + const char* prefix=0)const; + virtual void getTypeNameList(std::vector<ossimString>& typeList)const; + + void registerFactory(ossimImageSourceFactoryBase* factory); + void unregisterFactory(ossimImageSourceFactoryBase* factory); + bool findFactory(ossimImageSourceFactoryBase* factory)const; + +protected: + ossimImageReconstructionFilterRegistry(); // hide + ossimImageReconstructionFilterRegistry(const ossimImageReconstructionFilterRegistry&){}//hide + void operator = (ossimImageReconstructionFilterRegistry&){}// hide + + static ossimImageReconstructionFilterRegistry* theInstance; + std::vector<ossimImageSourceFactoryBase*> theFactoryList; +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageSourceFactory.cpp b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageSourceFactory.cpp new file mode 100644 index 0000000000..8c59dd272f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageSourceFactory.cpp @@ -0,0 +1,551 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: This is the image source factory. +// It will try to create image filters +// first then it will try the image writers +// and image handlers (image readers) +// +//************************************************************************* +// $Id: ossimImageSourceFactory.cpp,v 1.96 2005/12/22 15:32:59 gpotts Exp $ + +#include <imaging/factory/ossimImageSourceFactory.h> +#include <imaging/tile_sources/ossimConvolutionFilter1D.h> +#include <imaging/tile_sources/ossimImageGaussianFilter.h> +#include <imaging/tile_sources/ossimImageRenderer.h> +#include <imaging/tile_sources/ossimCacheTileSource.h> +#include <imaging/tile_sources/ossimFeatherMosaic.h> +#include <imaging/tile_sources/ossimHistogramRemapper.h> +#include <imaging/tile_sources/ossimImageMosaic.h> +#include <imaging/tile_sources/ossimClosestToCenterCombiner.h> +#include <imaging/tile_sources/ossimBlendMosaic.h> +#include <imaging/tile_sources/ossimMaxMosaic.h> +#include <imaging/tile_sources/ossimOrthoImageMosaic.h> +#include <imaging/tile_sources/ossimColorNormalizedFusion.h> +#include <imaging/tile_sources/ossimLocalCorrelationFusion.h> +#include <imaging/tile_sources/ossimSFIMFusion.h> +#include <imaging/tile_sources/ossimTopographicCorrectionFilter.h> +#include <imaging/tile_sources/ossimBandSelector.h> +#include <imaging/tile_sources/ossimNBandToIndexFilter.h> +#include <imaging/tile_sources/ossimRgbToGreyFilter.h> +#include <imaging/tile_sources/ossimRgbToJpegYCbCrSource.h> +#include <imaging/tile_sources/ossimRgbToHsvSource.h> +#include <imaging/tile_sources/ossimRgbToHsiSource.h> +#include <imaging/tile_sources/ossimHsiToRgbSource.h> +#include <imaging/tile_sources/ossimHsvToRgbSource.h> +#include <imaging/tile_sources/ossimHsiRemapper.h> +#include <imaging/tile_sources/ossimJpegYCbCrToRgbSource.h> +#include <imaging/tile_sources/ossimPolyCutter.h> +#include <imaging/tile_sources/ossimGeoPolyCutter.h> +#include <imaging/tile_sources/ossimHistogramEqualization.h> +#include <imaging/tile_sources/ossimHistogramMatchFilter.h> +#include <imaging/tile_sources/ossimHistogramThreshholdFilter.h> +#include <imaging/tile_sources/ossimConvolutionSource.h> +#include <imaging/tile_sources/ossimBrightnessContrastSource.h> +#include <imaging/tile_sources/ossimBrightnessMatch.h> +#include <imaging/tile_sources/ossimScalarRemapper.h> +#include <imaging/tile_sources/ossimBandMergeSource.h> +#include <imaging/tile_sources/ossimIndexToRgbLutFilter.h> +#include <imaging/tile_sources/ossimBumpShadeTileSource.h> +#include <imaging/tile_sources/ossimSubImageTileSource.h> +#include <imaging/tile_sources/ossimRLevelFilter.h> +#include <imaging/tile_sources/ossimBandClipFilter.h> +#include <imaging/tile_sources/ossimValueAssignImageSourceFilter.h> +#include <imaging/tile_sources/ossimImageSharpenFilter.h> +#include <imaging/tile_sources/ossim3x3ConvolutionFilter.h> +#include <imaging/tile_sources/ossimCastTileSourceFilter.h> +#include <imaging/tile_sources/ossimEquationCombiner.h> +#include <imaging/tile_sources/ossimMaskFilter.h> +#include <imaging/misc/ossimPixelFlipper.h> +#include <imaging/elevation/ossimElevImageSource.h> +#include <imaging/tile_sources/ossimLandsatTopoCorrectionFilter.h> +#include <imaging/annotation/ossimGeoAnnotationSource.h> +#include <imaging/annotation/ossimEsriShapeFileFilter.h> +#include <imaging/tile_sources/ossimEsriShapeFileCutter.h> +#include <imaging/annotation/ossimMapCompositionSource.h> +#include <imaging/tile_sources/ossimScaleFilter.h> +#include <imaging/tile_sources/ossimEastingNorthingCutter.h> +#include <imaging/tile_sources/ossimEdgeFilter.h> +#include <imaging/tile_sources/ossimFftFilter.h> +#include <imaging/tile_sources/ossimWatermarkFilter.h> +#include <imaging/tile_sources/ossimTrimFilter.h> + + +#include <imaging/tonal_balance/ossimGridRemapSource.h> + +// Not sure if we want to keep this here +#include <imaging/tonal_balance/ossimAtbController.h> + +#include <imaging/ossimImageChain.h> +#include <imaging/histogram/ossimHistogramWriter.h> +#include <imaging/tile_sources/ossimRectangleCutFilter.h> + + +#include <base/factory/ossimObjectFactoryRegistry.h> +#include <imaging/histogram/ossimImageHistogramSource.h> + +#include <imaging/tile_sources/ossimMultiBandHistogramTileSource.h> + +#include <imaging/tile_sources/ossimBandAverageFilter.h> +#include <imaging/tile_sources/ossimImageToPlaneNormalFilter.h> + +#include <imaging/atmospheric_correction/ossimAtCorrGridRemapper.h> +#include <imaging/atmospheric_correction/ossimAtCorrRemapper.h> + +#include <base/common/ossimTrace.h> + +RTTI_DEF1(ossimImageSourceFactory, "ossimImageSourceFactory", ossimImageSourceFactoryBase); + +static ossimTrace traceDebug("ossimImageSourceFactory:debug"); + +ossimImageSourceFactory* ossimImageSourceFactory::theInstance=NULL; + +ossimImageSourceFactory::~ossimImageSourceFactory() +{ + theInstance = NULL; + ossimObjectFactoryRegistry::instance()->unregisterFactory(this); +} +ossimImageSourceFactory* ossimImageSourceFactory::instance() +{ + if(!theInstance) + { + theInstance = new ossimImageSourceFactory; + } + + return theInstance; +} + +ossimObject* ossimImageSourceFactory::createObject(const ossimString& name)const +{ + + // lets do the filters first + if( name == STATIC_TYPE_NAME(ossimBandSelector) || + name == "ossimNativeBandSelectorTileSource" ) + { + //--- + // For backwards compatibility check old name: + // "ossimNativeBandSelectorTileSource" + //--- + return new ossimBandSelector; + } + else if(name == STATIC_TYPE_NAME(ossimImageRenderer)) + { + return new ossimImageRenderer; + } + else if(name == STATIC_TYPE_NAME(ossimCacheTileSource)) + { + return new ossimCacheTileSource; + } + else if(name == STATIC_TYPE_NAME(ossimColorNormalizedFusion)) + { + return new ossimColorNormalizedFusion; + } + else if(name == STATIC_TYPE_NAME(ossimLocalCorrelationFusion)) + { + return new ossimLocalCorrelationFusion; + } + else if(name == STATIC_TYPE_NAME(ossimSFIMFusion)) + { + return new ossimSFIMFusion; + } + else if(name == STATIC_TYPE_NAME(ossimBlendMosaic)) + { + return new ossimBlendMosaic; + } + else if(name == STATIC_TYPE_NAME(ossimMaxMosaic)) + { + return new ossimMaxMosaic; + } + else if(name == STATIC_TYPE_NAME(ossimHistogramRemapper)) + { + return new ossimHistogramRemapper; + } + else if(name == STATIC_TYPE_NAME(ossimImageMosaic)) + { + return new ossimImageMosaic; + } + else if(name == STATIC_TYPE_NAME(ossimClosestToCenterCombiner)) + { + return new ossimClosestToCenterCombiner; + } + else if(name == STATIC_TYPE_NAME(ossimRgbToGreyFilter)) + { + return new ossimRgbToGreyFilter; + } + else if(name == STATIC_TYPE_NAME(ossimNBandToIndexFilter)) + { + return new ossimNBandToIndexFilter; + } + else if(name == STATIC_TYPE_NAME(ossimImageChain)) + { + return new ossimImageChain; + } + else if(name == STATIC_TYPE_NAME(ossimPolyCutter)) + { + return new ossimPolyCutter; + } + else if(name == STATIC_TYPE_NAME(ossimGeoPolyCutter)) + { + return new ossimGeoPolyCutter; + } + else if(name == STATIC_TYPE_NAME(ossimJpegYCbCrToRgbSource)) + { + return new ossimJpegYCbCrToRgbSource; + } + else if(name == STATIC_TYPE_NAME(ossimRgbToJpegYCbCrSource)) + { + return new ossimRgbToJpegYCbCrSource; + } + else if(name == STATIC_TYPE_NAME(ossimHsiToRgbSource)) + { + return new ossimHsiToRgbSource; + } + else if(name == STATIC_TYPE_NAME(ossimRgbToHsiSource)) + { + return new ossimRgbToHsiSource; + } + else if(name == STATIC_TYPE_NAME(ossimHsvToRgbSource)) + { + return new ossimHsvToRgbSource; + } + else if(name == STATIC_TYPE_NAME(ossimRgbToHsvSource)) + { + return new ossimRgbToHsvSource; + } + else if(name == STATIC_TYPE_NAME(ossimHistogramEqualization)) + { + return new ossimHistogramEqualization; + } + else if(name == STATIC_TYPE_NAME(ossimHistogramMatchFilter)) + { + return new ossimHistogramMatchFilter; + } + else if(name == STATIC_TYPE_NAME(ossimHistogramThreshholdFilter)) + { + return new ossimHistogramThreshholdFilter; + } + else if(name == STATIC_TYPE_NAME(ossimGeoAnnotationSource)) + { + return new ossimGeoAnnotationSource; + } + else if(name == STATIC_TYPE_NAME(ossimConvolutionSource)) + { + return new ossimConvolutionSource; + } + else if(name == STATIC_TYPE_NAME(ossimBrightnessContrastSource)) + { + return new ossimBrightnessContrastSource; + } + else if(name == STATIC_TYPE_NAME(ossimBrightnessMatch)) + { + return new ossimBrightnessMatch; + } + else if(name == STATIC_TYPE_NAME(ossimScalarRemapper)) + { + return new ossimScalarRemapper; + } + else if(name == STATIC_TYPE_NAME(ossimBandMergeSource)) + { + return new ossimBandMergeSource; + } + else if(name == STATIC_TYPE_NAME(ossimFeatherMosaic)) + { + return new ossimFeatherMosaic; + } + else if(name == STATIC_TYPE_NAME(ossimGridRemapSource)) + { + return new ossimGridRemapSource; + } + else if(name == STATIC_TYPE_NAME(ossimEquationCombiner)) + { + return new ossimEquationCombiner; + } + // Not sure if we want to keep this here + else if(name == STATIC_TYPE_NAME(ossimAtbController)) + { + return new ossimAtbController; + } + else if(name == STATIC_TYPE_NAME(ossimIndexToRgbLutFilter)) + { + return new ossimIndexToRgbLutFilter; + } + else if(name == STATIC_TYPE_NAME(ossimBumpShadeTileSource)) + { + return new ossimBumpShadeTileSource; + } + else if(name == STATIC_TYPE_NAME(ossimSubImageTileSource)) + { + return new ossimSubImageTileSource; + } + else if(name == STATIC_TYPE_NAME(ossimRLevelFilter)) + { + return new ossimRLevelFilter; + } + else if(name == STATIC_TYPE_NAME(ossimBandClipFilter)) + { + return new ossimBandClipFilter; + } + else if(name == STATIC_TYPE_NAME(ossimHsiRemapper)) + { + return new ossimHsiRemapper; + } + else if(name == STATIC_TYPE_NAME(ossimHistogramWriter)) + { + return new ossimHistogramWriter; + } + else if(name == STATIC_TYPE_NAME(ossimImageHistogramSource)) + { + return new ossimImageHistogramSource; + } + else if(name == STATIC_TYPE_NAME(ossimRectangleCutFilter)) + { + return new ossimRectangleCutFilter; + } + else if(name == STATIC_TYPE_NAME(ossimCastTileSourceFilter)) + { + return new ossimCastTileSourceFilter; + } + // all the image handlers + else if(name == STATIC_TYPE_NAME(ossimValueAssignImageSourceFilter)) + { + return new ossimValueAssignImageSourceFilter; + } + else if(name == STATIC_TYPE_NAME(ossimImageSharpenFilter)) + { + return new ossimImageSharpenFilter; + } + else if(name == STATIC_TYPE_NAME(ossim3x3ConvolutionFilter)) + { + return new ossim3x3ConvolutionFilter; + } + else if(name == STATIC_TYPE_NAME(ossimEsriShapeFileFilter)) + { + return new ossimEsriShapeFileFilter; + } + else if(name == STATIC_TYPE_NAME(ossimEsriShapeFileCutter)) + { + return new ossimEsriShapeFileCutter; + } + else if(name == STATIC_TYPE_NAME(ossimOrthoImageMosaic)) + { + return new ossimOrthoImageMosaic; + } + else if(name == STATIC_TYPE_NAME(ossimMapCompositionSource)) + { + return new ossimMapCompositionSource; + } + else if(name == STATIC_TYPE_NAME(ossimElevImageSource)) + { + return new ossimElevImageSource; + } + else if(name == STATIC_TYPE_NAME(ossimMaskFilter)) + { + return new ossimMaskFilter; + } + else if(name == STATIC_TYPE_NAME(ossimMultiBandHistogramTileSource)) + { + return new ossimMultiBandHistogramTileSource; + } + else if(name == STATIC_TYPE_NAME(ossimBandAverageFilter)) + { + return new ossimBandAverageFilter; + } + else if(name == STATIC_TYPE_NAME(ossimPixelFlipper)) + { + return new ossimPixelFlipper(); + } + else if(name == STATIC_TYPE_NAME(ossimScaleFilter)) + { + return new ossimScaleFilter(); + } + else if(name == STATIC_TYPE_NAME(ossimImageToPlaneNormalFilter)) + { + return new ossimImageToPlaneNormalFilter(); + } + else if(name == STATIC_TYPE_NAME(ossimTopographicCorrectionFilter)) + { + return new ossimTopographicCorrectionFilter(); + } + else if(name == STATIC_TYPE_NAME(ossimLandsatTopoCorrectionFilter)) + { + return new ossimLandsatTopoCorrectionFilter(); + } + else if(name == STATIC_TYPE_NAME(ossimAtCorrRemapper)) + { + return new ossimAtCorrRemapper(); + } + else if(name == STATIC_TYPE_NAME(ossimAtCorrGridRemapper)) + { + return new ossimAtCorrGridRemapper(); + } + else if(name == STATIC_TYPE_NAME(ossimEastingNorthingCutter)) + { + return new ossimEastingNorthingCutter(); + } + else if(name == STATIC_TYPE_NAME(ossimEdgeFilter)) + { + return new ossimEdgeFilter(); + } + else if(name == STATIC_TYPE_NAME(ossimFftFilter)) + { + return new ossimFftFilter(); + } + else if(name == STATIC_TYPE_NAME(ossimWatermarkFilter)) + { + return new ossimWatermarkFilter(); + } + else if(name == STATIC_TYPE_NAME(ossimConvolutionFilter1D)) + { + return new ossimConvolutionFilter1D(); + } + else if(name == STATIC_TYPE_NAME(ossimImageGaussianFilter)) + { + return new ossimImageGaussianFilter(); + } + else if(name == STATIC_TYPE_NAME(ossimTrimFilter)) + { + return new ossimTrimFilter(); + } + return NULL; +} + +ossimObject* ossimImageSourceFactory::createObject(const ossimKeywordlist& kwl, + const char* prefix)const +{ + static const char* MODULE = "ossimImageSourceFactory::createSource"; + + ossimString copyPrefix = prefix; + ossimObject* result = NULL; + + if(traceDebug()) + { + CLOG << "looking up type keyword for prefix = " << copyPrefix << endl; + } + + const char* lookup = kwl.find(copyPrefix, "type"); + if(lookup) + { + ossimString name = lookup; + result = createObject(name); + + if(result) + { + if(traceDebug()) + { + CLOG << "found source " << result->getClassName() << " now loading state" << endl; + } + result->loadState(kwl, copyPrefix.c_str()); + } + else + { + if(traceDebug()) + { + CLOG << "type not found " << lookup << endl; + } + } + } + else + { + if(traceDebug()) + { + CLOG << "type keyword not found" << endl; + } + } + return result; +} + +void ossimImageSourceFactory::getTypeNameList(std::vector<ossimString>& typeList)const +{ + typeList.push_back(STATIC_TYPE_NAME(ossimBandSelector)); + typeList.push_back(STATIC_TYPE_NAME(ossimImageRenderer)); + typeList.push_back(STATIC_TYPE_NAME(ossimCacheTileSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimBlendMosaic)); + typeList.push_back(STATIC_TYPE_NAME(ossimMaxMosaic)); + typeList.push_back(STATIC_TYPE_NAME(ossimColorNormalizedFusion)); + typeList.push_back(STATIC_TYPE_NAME(ossimLocalCorrelationFusion)); + typeList.push_back(STATIC_TYPE_NAME(ossimSFIMFusion)); + typeList.push_back(STATIC_TYPE_NAME(ossimHistogramRemapper)); + typeList.push_back(STATIC_TYPE_NAME(ossimImageMosaic)); + typeList.push_back(STATIC_TYPE_NAME(ossimClosestToCenterCombiner)); + typeList.push_back(STATIC_TYPE_NAME(ossimRgbToGreyFilter)); + typeList.push_back(STATIC_TYPE_NAME(ossimNBandToIndexFilter)); + typeList.push_back(STATIC_TYPE_NAME(ossimImageChain)); + typeList.push_back(STATIC_TYPE_NAME(ossimPolyCutter)); + typeList.push_back(STATIC_TYPE_NAME(ossimGeoPolyCutter)); + typeList.push_back(STATIC_TYPE_NAME(ossimJpegYCbCrToRgbSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimRgbToJpegYCbCrSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimHsiToRgbSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimRgbToHsiSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimHsvToRgbSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimRgbToHsvSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimHistogramEqualization)); + typeList.push_back(STATIC_TYPE_NAME(ossimHistogramMatchFilter)); + typeList.push_back(STATIC_TYPE_NAME(ossimHistogramThreshholdFilter)); + typeList.push_back(STATIC_TYPE_NAME(ossimGeoAnnotationSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimConvolutionSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimBrightnessContrastSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimBrightnessMatch)); + typeList.push_back(STATIC_TYPE_NAME(ossimScalarRemapper)); + typeList.push_back(STATIC_TYPE_NAME(ossimBandMergeSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimFeatherMosaic)); + typeList.push_back(STATIC_TYPE_NAME(ossimGridRemapSource)); + // Not sure if we want to keep this here + typeList.push_back(STATIC_TYPE_NAME(ossimAtbController)); + typeList.push_back(STATIC_TYPE_NAME(ossimIndexToRgbLutFilter)); + typeList.push_back(STATIC_TYPE_NAME(ossimBumpShadeTileSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimSubImageTileSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimRLevelFilter)); + typeList.push_back(STATIC_TYPE_NAME(ossimBandClipFilter)); + typeList.push_back(STATIC_TYPE_NAME(ossimHsiRemapper)); + typeList.push_back(STATIC_TYPE_NAME(ossimHistogramWriter)); + typeList.push_back(STATIC_TYPE_NAME(ossimImageHistogramSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimRectangleCutFilter)); + typeList.push_back(STATIC_TYPE_NAME(ossimElevImageSource)); + + typeList.push_back(STATIC_TYPE_NAME(ossimValueAssignImageSourceFilter)); + typeList.push_back(STATIC_TYPE_NAME(ossimImageSharpenFilter)); + typeList.push_back(STATIC_TYPE_NAME(ossim3x3ConvolutionFilter)); + typeList.push_back(STATIC_TYPE_NAME(ossimEsriShapeFileFilter)); + typeList.push_back(STATIC_TYPE_NAME(ossimEsriShapeFileCutter)); + typeList.push_back(STATIC_TYPE_NAME(ossimOrthoImageMosaic)); + typeList.push_back(STATIC_TYPE_NAME(ossimMapCompositionSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimCastTileSourceFilter)); + typeList.push_back(STATIC_TYPE_NAME(ossimEquationCombiner)); + typeList.push_back(STATIC_TYPE_NAME(ossimMaskFilter)); + typeList.push_back(STATIC_TYPE_NAME(ossimMultiBandHistogramTileSource)); + typeList.push_back(STATIC_TYPE_NAME(ossimBandAverageFilter)); + typeList.push_back(STATIC_TYPE_NAME(ossimPixelFlipper)); + typeList.push_back(STATIC_TYPE_NAME(ossimScaleFilter)); + typeList.push_back(STATIC_TYPE_NAME(ossimImageToPlaneNormalFilter)); + typeList.push_back(STATIC_TYPE_NAME(ossimTopographicCorrectionFilter)); + typeList.push_back(STATIC_TYPE_NAME(ossimLandsatTopoCorrectionFilter)); + typeList.push_back(STATIC_TYPE_NAME(ossimAtCorrRemapper)); + typeList.push_back(STATIC_TYPE_NAME(ossimAtCorrGridRemapper)); + typeList.push_back(STATIC_TYPE_NAME(ossimEastingNorthingCutter)); + typeList.push_back(STATIC_TYPE_NAME(ossimEdgeFilter)); + typeList.push_back(STATIC_TYPE_NAME(ossimFftFilter)); + typeList.push_back(STATIC_TYPE_NAME(ossimWatermarkFilter)); + typeList.push_back(STATIC_TYPE_NAME(ossimConvolutionFilter1D)); + typeList.push_back(STATIC_TYPE_NAME(ossimImageGaussianFilter)); + typeList.push_back(STATIC_TYPE_NAME(ossimTrimFilter)); +} + +// Hide from use... +ossimImageSourceFactory::ossimImageSourceFactory() + :ossimImageSourceFactoryBase() +{} + +ossimImageSourceFactory::ossimImageSourceFactory(const ossimImageSourceFactory&) + :ossimImageSourceFactoryBase() +{} + +const ossimImageSourceFactory& ossimImageSourceFactory::operator=(ossimImageSourceFactory&) +{ + return *this; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageSourceFactory.h b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageSourceFactory.h new file mode 100644 index 0000000000..381ee22e3c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageSourceFactory.h @@ -0,0 +1,46 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimImageSourceFactory.h,v 1.5 2004/01/30 23:30:24 dburken Exp $ +#ifndef ossimImageSourceFactory_HEADER +#define ossimImageSourceFactory_HEADER +#include "ossimImageSourceFactoryBase.h" + +class ossimImageSourceFactory : public ossimImageSourceFactoryBase +{ +public: + virtual ~ossimImageSourceFactory(); + static ossimImageSourceFactory* instance(); + virtual ossimObject* createObject(const ossimString& name)const; + virtual ossimObject* createObject(const ossimKeywordlist& kwl, + const char* prefix=0)const; + virtual void getTypeNameList(std::vector<ossimString>& typeList)const; + +protected: + // Hide from use. + ossimImageSourceFactory(); + ossimImageSourceFactory(const ossimImageSourceFactory&); + const ossimImageSourceFactory& operator=(ossimImageSourceFactory&); + + static ossimImageSourceFactory* theInstance; +TYPE_DATA +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageSourceFactoryBase.cpp b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageSourceFactoryBase.cpp new file mode 100644 index 0000000000..0ac62c2fb3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageSourceFactoryBase.cpp @@ -0,0 +1,74 @@ +//******************************************************************* +// Copyright (C) 2004 ImageLinks Inc. All rights reserved. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken <dburken@imagelinks.com> +// +//************************************************************************* +// $Id: ossimImageSourceFactoryBase.cpp,v 1.2 2004/08/26 19:14:35 gpotts Exp $ + +#include <imaging/factory/ossimImageSourceFactoryBase.h> +#include <imaging/ossimImageSource.h> +ossimImageSourceFactoryBase::ossimImageSourceFactoryBase() + : ossimObjectFactory() +{} + +ossimImageSourceFactoryBase::ossimImageSourceFactoryBase(const ossimImageSourceFactoryBase&) + : ossimObjectFactory() +{} + +const ossimImageSourceFactoryBase& ossimImageSourceFactoryBase::operator=(const ossimImageSourceFactoryBase&) +{ + return *this; +} + +ossimImageSource* ossimImageSourceFactoryBase::createImageSource(const ossimString& name)const +{ + ossimObject* result =createObject(name); + + if(PTR_CAST(ossimImageSource, result)) + { + return (ossimImageSource*)result; + } + + if(result) + { + delete result; + result = NULL; + } + + return (ossimImageSource*)NULL; +} + +ossimImageSource* ossimImageSourceFactoryBase::createImageSource(const ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimObject* result =createObject(kwl, prefix); + + if(PTR_CAST(ossimImageSource, result)) + { + return (ossimImageSource*)result; + } + + if(result) + { + delete result; + result = NULL; + } + + return (ossimImageSource*)NULL; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageSourceFactoryBase.h b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageSourceFactoryBase.h new file mode 100644 index 0000000000..5ac16fddef --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageSourceFactoryBase.h @@ -0,0 +1,46 @@ +//******************************************************************* +// Copyright (C) 2004 ImageLinks Inc. All rights reserved. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts <gpotts@imagelinks.com> +// +//************************************************************************* +// $Id: ossimImageSourceFactoryBase.h,v 1.4 2004/08/31 19:15:57 gpotts Exp $ +#ifndef ossimImageSourceFactoryBase_HEADER +#define ossimImageSourceFactoryBase_HEADER +#include "base/factory/ossimObjectFactory.h" +class ossimImageSource; + +class OSSIMDLLEXPORT ossimImageSourceFactoryBase : public ossimObjectFactory +{ +public: + /*! + * Convenient conversion method. Gurantees an ossimImageSource is returned. Returns + * NULL otherwise + */ + virtual ossimImageSource* createImageSource(const ossimString& name)const; + virtual ossimImageSource* createImageSource(const ossimKeywordlist& kwl, + const char* prefix=0)const; + +protected: + // Hide from use. + ossimImageSourceFactoryBase(); + ossimImageSourceFactoryBase(const ossimImageSourceFactoryBase&); + const ossimImageSourceFactoryBase& operator=(const ossimImageSourceFactoryBase&); +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageSourceFactoryRegistry.cpp b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageSourceFactoryRegistry.cpp new file mode 100644 index 0000000000..cebc752f0f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageSourceFactoryRegistry.cpp @@ -0,0 +1,144 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimImageSourceFactoryRegistry.cpp,v 1.7 2005/10/17 18:42:27 gpotts Exp $ +#include <algorithm> +#include "ossimImageSourceFactoryRegistry.h" +#include "ossimImageSourceFactory.h" +#include "ossimImageReconstructionFilterRegistry.h" + +ossimImageSourceFactoryRegistry* ossimImageSourceFactoryRegistry::theInstance = NULL; + +RTTI_DEF1(ossimImageSourceFactoryRegistry, "ossimImageSourceFactoryRegistry", ossimImageSourceFactoryBase); + +ossimImageSourceFactoryRegistry::ossimImageSourceFactoryRegistry() +{ + theInstance = this; +} + +ossimImageSourceFactoryRegistry::~ossimImageSourceFactoryRegistry() +{ + theInstance->unregisterFactory(ossimImageSourceFactory::instance()); + + theInstance = NULL; +} + +ossimImageSourceFactoryRegistry* ossimImageSourceFactoryRegistry::instance() +{ + if(theInstance == NULL) + { + theInstance = new ossimImageSourceFactoryRegistry; + theInstance->registerFactory(ossimImageSourceFactory::instance()); + theInstance->registerFactory(ossimImageReconstructionFilterRegistry::instance()); + } + return theInstance; +} + +ossimObject* ossimImageSourceFactoryRegistry::createObject(const ossimString& name)const +{ + ossimObject* result = NULL; + std::vector<ossimImageSourceFactoryBase*>::const_iterator factory; + + factory = theFactoryList.begin(); + while((factory != theFactoryList.end()) && !result) + { + result = (*factory)->createObject(name); + ++factory; + } + + return result; +} + +ossimObject* ossimImageSourceFactoryRegistry::createObject(const ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimObject* result = NULL; + std::vector<ossimImageSourceFactoryBase*>::const_iterator factory; + + factory = theFactoryList.begin(); + while((factory != theFactoryList.end()) && !result) + { + result = (*factory)->createObject(kwl, prefix); + ++factory; + } + + return result; + +} + +void ossimImageSourceFactoryRegistry::getTypeNameList(std::vector<ossimString>& typeList)const +{ + std::vector<ossimString> result; + std::vector<ossimImageSourceFactoryBase*>::const_iterator iter = theFactoryList.begin(); + + while(iter != theFactoryList.end()) + { + result.clear(); + (*iter)->getTypeNameList(result); + + // now append to the end of the typeList. + typeList.insert(typeList.end(), + result.begin(), + result.end()); + ++iter; + } + +} + +void ossimImageSourceFactoryRegistry::registerFactory(ossimImageSourceFactoryBase* factory) +{ + if(factory&&!findFactory(factory)) + { + theFactoryList.push_back(factory); + } +} + +void ossimImageSourceFactoryRegistry::unregisterFactory(ossimImageSourceFactoryBase* factory) +{ + std::vector<ossimImageSourceFactoryBase*>::iterator iter = std::find(theFactoryList.begin(), + theFactoryList.end(), + factory); + if(iter != theFactoryList.end()) + { + theFactoryList.erase(iter); + } +} + +bool ossimImageSourceFactoryRegistry::findFactory(ossimImageSourceFactoryBase* factory)const +{ + return (std::find(theFactoryList.begin(), + theFactoryList.end(), + factory)!=theFactoryList.end()); +} + +void* ossimImageSourceFactoryRegistryGetInstance() +{ + return ossimImageSourceFactoryRegistry::instance(); +} + +// Hidden +ossimImageSourceFactoryRegistry::ossimImageSourceFactoryRegistry(const ossimImageSourceFactoryRegistry&) + : ossimImageSourceFactoryBase() +{} + +// Hidden +void ossimImageSourceFactoryRegistry::operator=(ossimImageSourceFactoryRegistry&) +{} diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageSourceFactoryRegistry.h b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageSourceFactoryRegistry.h new file mode 100644 index 0000000000..41c2dc141d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageSourceFactoryRegistry.h @@ -0,0 +1,55 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimImageSourceFactoryRegistry.h,v 1.5 2004/05/28 20:36:01 dburken Exp $ +#ifndef ossimImageSourceFactoryRegistry_HEADER +#define ossimImageSourceFactoryRegistry_HEADER +#include "ossimImageSourceFactoryBase.h" + +class OSSIMDLLEXPORT ossimImageSourceFactoryRegistry : public ossimImageSourceFactoryBase +{ +public: + virtual ~ossimImageSourceFactoryRegistry(); + static ossimImageSourceFactoryRegistry* instance(); + virtual ossimObject* createObject(const ossimString& name)const; + virtual ossimObject* createObject(const ossimKeywordlist& kwl, + const char* prefix=0)const; + virtual void getTypeNameList(std::vector<ossimString>& typeList)const; + + void registerFactory(ossimImageSourceFactoryBase* factory); + void unregisterFactory(ossimImageSourceFactoryBase* factory); + bool findFactory(ossimImageSourceFactoryBase* factory)const; + +protected: + ossimImageSourceFactoryRegistry(); // hide + ossimImageSourceFactoryRegistry(const ossimImageSourceFactoryRegistry&);//hide + void operator = (ossimImageSourceFactoryRegistry&);// hide + + static ossimImageSourceFactoryRegistry* theInstance; + std::vector<ossimImageSourceFactoryBase*> theFactoryList; +TYPE_DATA +}; + +extern "C" +{ + OSSIMDLLEXPORT void* ossimImageSourceFactoryRegistryGetInstance(); +} +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageWriterFactory.cpp b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageWriterFactory.cpp new file mode 100644 index 0000000000..92e91e6cb9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageWriterFactory.cpp @@ -0,0 +1,226 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimImageWriterFactory.cpp,v 1.10 2005/05/27 17:08:05 gpotts Exp $ + +#include "ossimImageWriterFactory.h" +#include "ossimImageWriterFactoryRegistry.h" +#include <base/common/ossimKeywordNames.h> +#include <imaging/formats/tiff/ossimTiffWriter.h> +#include <imaging/formats/jpeg/ossimJpegWriter.h> +#include <imaging/formats/general_raster/ossimGeneralRasterWriter.h> +#include <imaging/formats/nitf/ossimNitfWriter.h> +#include <base/misc/lookup_tables/ossimImageTypeLut.h> + +ossimImageWriterFactory* ossimImageWriterFactory::theInstance = (ossimImageWriterFactory*)NULL; + + +ossimImageWriterFactory* ossimImageWriterFactory::instance() +{ + if(!theInstance) + { + theInstance = new ossimImageWriterFactory; + ossimImageWriterFactoryRegistry::instance()-> + registerFactory(theInstance); + } + + return theInstance; +} + +ossimImageWriterFactory::~ossimImageWriterFactory() +{ + theInstance = (ossimImageWriterFactory*)NULL; +} + +ossimImageFileWriter *ossimImageWriterFactory::createWriterFromExtension(const ossimString& fileExtension)const +{ + if((fileExtension == "tif")|| + (fileExtension == "tiff")) + { + return new ossimTiffWriter; + } + else if((fileExtension == "jpg")|| + (fileExtension == "jpeg")) + { + return new ossimJpegWriter; + } + else if(fileExtension == "ras") + { + return new ossimGeneralRasterWriter; + } + else if((fileExtension == "ntf")|| + (fileExtension == "nitf")) + { + return new ossimNitfWriter; + } + + return NULL; +} + +ossimImageFileWriter* +ossimImageWriterFactory::createWriter(const ossimKeywordlist& kwl, + const char *prefix)const +{ + ossimString type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + ossimImageFileWriter* result = (ossimImageFileWriter*)NULL; + + if(type != "") + { + result = createWriter(type); + if (result) + { + if (result->hasImageType(type)) + { + ossimKeywordlist kwl2(kwl); + kwl2.add(prefix, + ossimKeywordNames::IMAGE_TYPE_KW, + type, + true); + + result->loadState(kwl2, prefix); + } + else + { + result->loadState(kwl, prefix); + } + } + } + + return result; +} + +ossimImageFileWriter* +ossimImageWriterFactory::createWriter(const ossimString& typeName)const +{ + // Check for tiff writer. + ossimImageFileWriter* writer = new ossimTiffWriter; + if (writer->getClassName() == typeName ) + { + return writer; + } + else + { + // See if the type name is supported by the writer. + if ( writer->hasImageType(typeName) ) + { + writer->setOutputImageType(typeName); + return writer; + } + } + delete writer; // Not a tiff writer. + + // Check for jpeg writer. + writer = new ossimJpegWriter; + if ( writer->getClassName() == typeName ) + { + return writer; + } + else + { + // See if the type name is supported by the writer. + if ( writer->hasImageType(typeName) ) + { + writer->setOutputImageType(typeName); + return writer; + } + } + delete writer; // Not a jpeg writer. + + // Check for general raster writer. + writer = new ossimGeneralRasterWriter; + if ( writer->getClassName() == typeName ) + { + return writer; + } + else + { + // See if the type name is supported by the writer. + if ( writer->hasImageType(typeName) ) + { + writer->setOutputImageType(typeName); + return writer; + } + } + delete writer; // Not a general raster writer. + + // Check for nitf writer. + writer = new ossimNitfWriter; + if ( writer->getClassName() == typeName ) + { + return writer; + } + else + { + // See if the type name is supported by the writer. + if ( writer->hasImageType(typeName) ) + { + writer->setOutputImageType(typeName); + return writer; + } + } + delete writer; // Not a nitf writer. + + writer = NULL; + + return writer; // Return a null writer. +} + +ossimObject* ossimImageWriterFactory::createObject(const ossimKeywordlist& kwl, + const char *prefix)const +{ + return createWriter(kwl, prefix); +} + +ossimObject* ossimImageWriterFactory::createObject(const ossimString& typeName)const +{ + return createWriter(typeName); +} + + +void ossimImageWriterFactory::getExtensions(std::vector<ossimString>& result)const +{ + result.push_back("ras"); + result.push_back("tif"); + result.push_back("jpg"); + result.push_back("ntf"); +} + +void ossimImageWriterFactory::getTypeNameList(std::vector<ossimString>& typeList)const +{ + typeList.push_back(STATIC_TYPE_NAME(ossimTiffWriter)); + typeList.push_back(STATIC_TYPE_NAME(ossimJpegWriter)); + typeList.push_back(STATIC_TYPE_NAME(ossimGeneralRasterWriter)); + typeList.push_back(STATIC_TYPE_NAME(ossimNitfWriter)); +} + +void ossimImageWriterFactory::getImageTypeList(std::vector<ossimString>& imageTypeList)const +{ + // Add the tiff writer types. + ossimImageFileWriter* writer = new ossimTiffWriter; + writer->getImageTypeList(imageTypeList); + delete writer; + + // Add the jpeg writer types. + writer = new ossimJpegWriter; + writer->getImageTypeList(imageTypeList); + delete writer; + + // Add the general raster writer types. + writer = new ossimGeneralRasterWriter; + writer->getImageTypeList(imageTypeList); + delete writer; + writer = NULL; + + // Add the nitf writer types. + writer = new ossimNitfWriter; + writer->getImageTypeList(imageTypeList); + delete writer; + writer = NULL; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageWriterFactory.h b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageWriterFactory.h new file mode 100644 index 0000000000..8c254328cb --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageWriterFactory.h @@ -0,0 +1,59 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Frank Warmerdam (warmerda@home.com) +// +//******************************************************************* +// $Id: ossimImageWriterFactory.h,v 1.6 2004/12/10 16:46:36 gpotts Exp $ + +#ifndef ossimImageWriterFactory_HEADER +#define ossimImageWriterFactory_HEADER +#include "ossimImageWriterFactoryBase.h" + +class ossimImageWriter; +class ossimKeywordlist; + +class ossimImageWriterFactory: public ossimImageWriterFactoryBase +{ +public: + virtual ~ossimImageWriterFactory(); + static ossimImageWriterFactory* instance(); + + ossimImageFileWriter *createWriterFromExtension(const ossimString& fileExtension)const; + virtual ossimImageFileWriter* createWriter(const ossimKeywordlist& kwl, + const char *prefix=0)const; + virtual ossimImageFileWriter* createWriter(const ossimString& typeName)const; + + virtual ossimObject* createObject(const ossimKeywordlist& kwl, + const char *prefix=0)const; + virtual ossimObject* createObject(const ossimString& typeName)const; + + virtual void getExtensions(std::vector<ossimString>& result)const; + + virtual void getTypeNameList(std::vector<ossimString>& typeList)const; + + /*! + * getImageTypeList. This is the actual image type name. So for + * example, ossimTiffWriter has several image types. Some of these + * include TIFF_TILED, TIFF_TILED_BAND_SEPARATE ... etc. The + * ossimGdalWriter + * may include GDAL_IMAGINE_HFA, GDAL_RGB_NITF, GDAL_JPEG20000, ... etc + * A writer should be able to be instantiated by this name as well as a + * class name + */ + virtual void getImageTypeList(std::vector<ossimString>& imageTypeList)const; + +protected: + ossimImageWriterFactory() {} + + static ossimImageWriterFactory* theInstance; + + + bool isImageTypeName(const ossimString& name)const; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageWriterFactoryBase.cpp b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageWriterFactoryBase.cpp new file mode 100644 index 0000000000..ccefb46984 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageWriterFactoryBase.cpp @@ -0,0 +1,26 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//******************************************************************* +// $Id: ossimImageWriterFactoryBase.cpp,v 1.1 2002/03/26 20:41:04 gpotts Exp $ +#include "ossimImageWriterFactoryBase.h" + +RTTI_DEF1(ossimImageWriterFactoryBase, "ossimImageWriterFactoryBase", ossimObjectFactory); + diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageWriterFactoryBase.h b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageWriterFactoryBase.h new file mode 100644 index 0000000000..f13750f8ef --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageWriterFactoryBase.h @@ -0,0 +1,55 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//******************************************************************* +// $Id: ossimImageWriterFactoryBase.h,v 1.7 2005/05/20 20:25:19 dburken Exp $ +#ifndef ossimImageWriterFactoryBase_HEADER +#define ossimImageWriterFactoryBase_HEADER +#include "base/factory/ossimObjectFactory.h" +#include "base/data_types/ossimString.h" + +#include <vector> +class ossimImageFileWriter; +class ossimKeywordlist; + +class OSSIM_DLL ossimImageWriterFactoryBase : public ossimObjectFactory +{ +public: + virtual ~ossimImageWriterFactoryBase() {} + virtual ossimImageFileWriter *createWriterFromExtension(const ossimString& fileExtension)const=0; + virtual ossimImageFileWriter* createWriter(const ossimKeywordlist& kwl, + const char *prefix=0)const=0; + virtual ossimImageFileWriter* createWriter(const ossimString& typeName)const=0; + + virtual void getExtensions(std::vector<ossimString>& result)const=0; + + /*! + * getImageTypeList. This is the actual image type name. So for + * example, ossimTiffWriter has several image types. Some of these + * include tiff_tiled, tiff_tiled_band_separate ... etc. The ossimGdalWriter + * may include gdal_imagine_hfa,gdal_nitf_rgb_band_separate, ... etc + * A writer should be able to be instantiated by this name as well as a class name + */ + virtual void getImageTypeList(std::vector<ossimString>& imageTypeList)const=0; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageWriterFactoryRegistry.cpp b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageWriterFactoryRegistry.cpp new file mode 100644 index 0000000000..ed1c6fa5e8 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageWriterFactoryRegistry.cpp @@ -0,0 +1,220 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Frank Warmerdam (warmerda@home.com) +// +//******************************************************************* +// $Id: ossimImageWriterFactoryRegistry.cpp,v 1.11 2005/05/09 12:39:38 dburken Exp $ +#include <algorithm> +#include <imaging/factory/ossimImageWriterFactory.h> +#include <imaging/factory/ossimImageWriterFactoryRegistry.h> +#include <imaging/formats/ossimImageFileWriter.h> +#include <base/factory/ossimObjectFactoryRegistry.h> +#include <base/common/ossimKeywordNames.h> + +ossimImageWriterFactoryRegistry* ossimImageWriterFactoryRegistry::theInstance = NULL; + +ossimImageWriterFactoryRegistry::ossimImageWriterFactoryRegistry() +{ +} + +ossimImageWriterFactoryRegistry* ossimImageWriterFactoryRegistry::instance() +{ + if(!theInstance) + { + theInstance = new ossimImageWriterFactoryRegistry; + ossimObjectFactoryRegistry::instance()->registerFactory(theInstance); + ossimImageWriterFactory::instance(); + } + + return theInstance; +} + +//******************************************************************* +// Public Method: +//******************************************************************* +bool ossimImageWriterFactoryRegistry::addFactory(ossimImageWriterFactoryBase* factory) +{ + return registerFactory(factory); +} + +bool ossimImageWriterFactoryRegistry::registerFactory(ossimImageWriterFactoryBase* factory) +{ + bool result = false; + if(factory&&!findFactory(factory)) + { + theFactoryList.push_back(factory); + result = true; + } + + return result; +} + +void ossimImageWriterFactoryRegistry::unregisterFactory(ossimImageWriterFactoryBase* factory) +{ + std::vector<ossimImageWriterFactoryBase*>::iterator iter = std::find(theFactoryList.begin(), + theFactoryList.end(), + factory); + if(iter != theFactoryList.end()) + { + theFactoryList.erase(iter); + } +} + +bool ossimImageWriterFactoryRegistry::findFactory(ossimImageWriterFactoryBase* factory)const +{ + return (std::find(theFactoryList.begin(), + theFactoryList.end(), + factory)!=theFactoryList.end()); +} + +ossimImageFileWriter *ossimImageWriterFactoryRegistry::createWriterFromExtension(const ossimString& fileExtension)const +{ + vector<ossimImageWriterFactoryBase*>::const_iterator factories; + ossimImageFileWriter *result = NULL; + + factories = theFactoryList.begin(); + while(factories != theFactoryList.end()) + { + result = (*factories)->createWriterFromExtension(fileExtension); + if(result) + { + return result; + } + ++factories; + } + + return result; + +} + +ossimImageFileWriter *ossimImageWriterFactoryRegistry::createWriter(const ossimKeywordlist &kwl, + const char *prefix)const +{ + // let's see if we ned to return an object based on extension. + // this is specified by the type to be a generic + // ossimImageFileWriter + // + ossimString type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + + if(type == "ossimImageFileWriter") + { + ossimFilename filename = kwl.find(prefix, ossimKeywordNames::FILENAME_KW); + + if((filename != "")&& + (filename.ext() != "")) + { + ossimImageFileWriter* writer = createWriterFromExtension(filename.ext()); + + if(writer) + { + writer->setFilename(filename); + } + return writer; + } + } + + vector<ossimImageWriterFactoryBase*>::const_iterator factories; + ossimImageFileWriter *result = NULL; + + factories = theFactoryList.begin(); + while(factories != theFactoryList.end()) + { + result = (*factories)->createWriter(kwl, prefix); + if(result) + { + return result; + } + ++factories; + } + + return result; +} + +ossimImageFileWriter *ossimImageWriterFactoryRegistry::createWriter(const ossimString& typeName)const +{ + vector<ossimImageWriterFactoryBase*>::const_iterator factories; + ossimImageFileWriter *result = NULL; + + factories = theFactoryList.begin(); + while(factories != theFactoryList.end()) + { + result = (*factories)->createWriter(typeName); + if(result) + { + return result; + } + ++factories; + } + + return result; +} + +ossimObject* ossimImageWriterFactoryRegistry::createObject(const ossimKeywordlist &kwl, + const char *prefix)const +{ + return createWriter(kwl, prefix); +} + +ossimObject* ossimImageWriterFactoryRegistry::createObject(const ossimString& typeName)const +{ + return createWriter(typeName); +} + +void ossimImageWriterFactoryRegistry::getTypeNameList(std::vector<ossimString>& typeList)const +{ + vector<ossimString> result; + vector<ossimImageWriterFactoryBase*>::const_iterator iter = theFactoryList.begin(); + + while(iter != theFactoryList.end()) + { + result.clear(); + (*iter)->getTypeNameList(result); + + // now append to the end of the typeList. + typeList.insert(typeList.end(), + result.begin(), + result.end()); + ++iter; + } +} + +void ossimImageWriterFactoryRegistry::getImageTypeList(std::vector<ossimString>& typeList)const +{ + vector<ossimString> result; + vector<ossimImageWriterFactoryBase*>::const_iterator iter = theFactoryList.begin(); + + while(iter != theFactoryList.end()) + { + result.clear(); + (*iter)->getImageTypeList(result); + + // now append to the end of the typeList. + typeList.insert(typeList.end(), + result.begin(), + result.end()); + ++iter; + } +} + +extern "C" +{ + void* ossimImageWriterFactoryRegistryGetInstance() + { + return ossimImageWriterFactoryRegistry::instance(); + } +} + +ossimImageWriterFactoryRegistry::ossimImageWriterFactoryRegistry(const ossimImageWriterFactoryRegistry&) + : + ossimObjectFactory() +{ +} + +void ossimImageWriterFactoryRegistry::operator=(const ossimImageWriterFactoryRegistry&) +{ +} diff --git a/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageWriterFactoryRegistry.h b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageWriterFactoryRegistry.h new file mode 100644 index 0000000000..2ed3ab1554 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/factory/ossimImageWriterFactoryRegistry.h @@ -0,0 +1,73 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Frank Warmerdam (warmerda@home.com) +// +//******************************************************************* +// $Id: ossimImageWriterFactoryRegistry.h,v 1.13 2004/12/10 16:46:37 gpotts Exp $ + +#ifndef ossimImageWriterFactoryRegistry_HEADER +#define ossimImageWriterFactoryRegistry_HEADER +#include "base/factory/ossimObjectFactory.h" + +#include <vector> + +#include "base/common/ossimCommon.h" + +class ossimImageFileWriter; +class ossimImageWriterFactoryBase; +class ossimKeywordlist; + +class OSSIMDLLEXPORT ossimImageWriterFactoryRegistry : public ossimObjectFactory +{ +public: + static ossimImageWriterFactoryRegistry* instance(); + bool addFactory(ossimImageWriterFactoryBase*); + bool registerFactory(ossimImageWriterFactoryBase* factory); + void unregisterFactory(ossimImageWriterFactoryBase* factory); + bool findFactory(ossimImageWriterFactoryBase* factory)const; + + ossimImageFileWriter *createWriterFromExtension(const ossimString& fileExtension)const; + ossimImageFileWriter *createWriter(const ossimKeywordlist &kwl, + const char *prefix=0)const; + ossimImageFileWriter* createWriter(const ossimString& typeName)const; + + ossimObject* createObject(const ossimKeywordlist &kwl, + const char *prefix=0)const; + ossimObject* createObject(const ossimString& typeName)const; + + /** + * getTypeNameList. This should return the class type of the object being + * used to perform the writting. + */ + virtual void getTypeNameList(std::vector<ossimString>& typeList)const; + + /** + * getImageTypeList. This is the actual image type name. So for + * example, ossimTiffWriter has several image types. Some of these + * include TIFF_TILED, TIFF_TILED_BAND_SEPARATE ... etc. + * The ossimGdalWriter + * may include GDAL_IMAGINE_HFA, GDAL_RGB_NITF, GDAL_JPEG20000, ... etc + * A writer should be able to be instantiated by this name as well as a + * class name + */ + virtual void getImageTypeList(std::vector<ossimString>& imageTypeList)const; + +protected: + ossimImageWriterFactoryRegistry(); + ossimImageWriterFactoryRegistry(const ossimImageWriterFactoryRegistry&); + void operator=(const ossimImageWriterFactoryRegistry&); + + std::vector<ossimImageWriterFactoryBase*> theFactoryList; + static ossimImageWriterFactoryRegistry* theInstance; +}; + +extern "C" +{ + OSSIMDLLEXPORT void* ossimImageWriterFactoryRegistryGetInstance(); +} +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/filters/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/filters/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/filters/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/imaging/filters/ossimDiscrete3x3HatFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/filters/ossimDiscrete3x3HatFilter.cpp new file mode 100644 index 0000000000..7b6a59712d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/filters/ossimDiscrete3x3HatFilter.cpp @@ -0,0 +1,289 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// LICENSE: LGPL +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimDiscrete3x3HatFilter.cpp,v 1.11 2004/09/21 12:41:26 gpotts Exp $ +#include "ossimDiscrete3x3HatFilter.h" +#include <base/common/ossimCommon.h> + +ossimDiscrete3x3HatFilter::ossimDiscrete3x3HatFilter() + :ossimDiscreteConvolutionKernel(3,3) +{ + // make the default be the nearest neighbor + (*theKernel)[0][0] = 0; + (*theKernel)[0][1] = 0; + (*theKernel)[0][2] = 0; + + (*theKernel)[1][0] = 0; + (*theKernel)[1][1] = 1; + (*theKernel)[1][2] = 0; + + (*theKernel)[2][0] = 0; + (*theKernel)[2][1] = 0; + (*theKernel)[2][2] = 0; +} + +void ossimDiscrete3x3HatFilter::convolve(const float* data, + double& result, + float nullPixel)const +{ + double divisor = 0; + result = 0; + + if(data[0] != nullPixel) + { + divisor += (*theKernel)[0][0]; + result += (*theKernel)[0][0] * data[0]; + } + if(data[1] != nullPixel) + { + divisor += (*theKernel)[0][1]; + result += (*theKernel)[0][1] * data[1]; + } + if(data[2] != nullPixel) + { + divisor += (*theKernel)[0][2]; + result += (*theKernel)[0][2] * data[2]; + } + if(data[3] != nullPixel) + { + divisor += (*theKernel)[1][0]; + result += (*theKernel)[1][0] * data[3]; + } + if(data[4] != nullPixel) + { + divisor += (*theKernel)[1][1]; + result += (*theKernel)[1][1] * data[4]; + } + if(data[5] != nullPixel) + { + divisor += (*theKernel)[1][2]; + result += (*theKernel)[1][2] * data[5]; + } + if(data[6] != nullPixel) + { + divisor += (*theKernel)[2][0]; + result += (*theKernel)[2][0] * data[6]; + } + if(data[7] != nullPixel) + { + divisor += (*theKernel)[2][1]; + result += (*theKernel)[2][1] * data[7]; + } + if(data[8] != nullPixel) + { + divisor += (*theKernel)[2][2]; + result += (*theKernel)[2][2] * data[8]; + } + + + if(divisor > 0) + result /= divisor; +} + +void ossimDiscrete3x3HatFilter::convolveSubImage(const float* data, + long dataWidth, + double& result, + float nullPixel)const +{ + double divisor = 0.0; + result = 0; + + if(data[0] != nullPixel) + { + divisor += (*theKernel)[0][0]; + result += (*theKernel)[0][0]*data[0]; + } + if(data[1] != nullPixel) + { + divisor += (*theKernel)[0][1]; + result += (*theKernel)[0][1]*data[1]; + } + if(data[2] != nullPixel) + { + divisor += (*theKernel)[0][2]; + result += (*theKernel)[0][2]*data[2]; + } + + data +=dataWidth; + if(data[0] != nullPixel) + { + divisor += (*theKernel)[1][0]; + result += (*theKernel)[1][0]*data[0]; + } + if(data[1] != nullPixel) + { + divisor += (*theKernel)[1][1]; + result += (*theKernel)[1][1]*data[1]; + } + if(data[2] != nullPixel) + { + divisor += (*theKernel)[1][2]; + result += (*theKernel)[1][2]*data[2]; + } + + data +=dataWidth; + if(data[0] != nullPixel) + { + divisor += (*theKernel)[2][0]; + result += (*theKernel)[2][0]*data[0]; + } + if(data[1] != nullPixel) + { + divisor += (*theKernel)[2][1]; + result += (*theKernel)[2][1]*data[1]; + } + if(data[2] != nullPixel) + { + divisor += (*theKernel)[2][2]; + result += (*theKernel)[2][2]*data[2]; + } + + if(divisor > 0) + { + result /= divisor; + } +} + +void ossimDiscrete3x3HatFilter::convolve(const unsigned char* data, + double& result, + ossim_uint8 nullPixel)const +{ + double divisor = 0; + result = 0; + + if(data[0] != nullPixel) + { + divisor += (*theKernel)[0][0]; + result += (*theKernel)[0][0] * data[0]; + } + if(data[1] != nullPixel) + { + divisor += (*theKernel)[0][1]; + result += (*theKernel)[0][1] * data[1]; + } + if(data[2] != nullPixel) + { + divisor += (*theKernel)[0][2]; + result += (*theKernel)[0][2] * data[2]; + } + if(data[3] != nullPixel) + { + divisor += (*theKernel)[1][0]; + result += (*theKernel)[1][0] * data[3]; + } + if(data[4] != nullPixel) + { + divisor += (*theKernel)[1][1]; + result += (*theKernel)[1][1] * data[4]; + } + if(data[5] != nullPixel) + { + divisor += (*theKernel)[1][2]; + result += (*theKernel)[1][2] * data[5]; + } + if(data[6] != nullPixel) + { + divisor += (*theKernel)[2][0]; + result += (*theKernel)[2][0] * data[6]; + } + if(data[7] != nullPixel) + { + divisor += (*theKernel)[2][1]; + result += (*theKernel)[2][1] * data[7]; + } + if(data[8] != nullPixel) + { + divisor += (*theKernel)[2][2]; + result += (*theKernel)[2][2] * data[8]; + } + + + if(divisor > 0) + result /= divisor; +} + + +void ossimDiscrete3x3HatFilter::convolveSubImage(const unsigned char* data, + long dataWidth, + double& result, + ossim_uint8 nullPixel)const +{ + double divisor = 0.0; + result = 0; + + if(data[0] != nullPixel) + { + divisor += (*theKernel)[0][0]; + result += (*theKernel)[0][0]*data[0]; + } + if(data[1] != nullPixel) + { + divisor += (*theKernel)[0][1]; + result += (*theKernel)[0][1]*data[1]; + } + if(data[2] != nullPixel) + { + divisor += (*theKernel)[0][2]; + result += (*theKernel)[0][2]*data[2]; + } + + data +=dataWidth; + if(data[0] != nullPixel) + { + divisor += (*theKernel)[1][0]; + result += (*theKernel)[1][0]*data[0]; + } + if(data[1] != nullPixel) + { + divisor += (*theKernel)[1][1]; + result += (*theKernel)[1][1]*data[1]; + } + if(data[2] != nullPixel) + { + divisor += (*theKernel)[1][2]; + result += (*theKernel)[1][2]*data[2]; + } + + data +=dataWidth; + if(data[0] != nullPixel) + { + divisor += (*theKernel)[2][0]; + result += (*theKernel)[2][0]*data[0]; + } + if(data[1] != nullPixel) + { + divisor += (*theKernel)[2][1]; + result += (*theKernel)[2][1]*data[1]; + } + if(data[2] != nullPixel) + { + divisor += (*theKernel)[2][2]; + result += (*theKernel)[2][2]*data[2]; + } + + if(divisor > 0) + { + result /= divisor; + } +} + +void ossimDiscrete3x3HatFilter::buildConvolution(double xLocation, + double yLocation) +{ + NEWMAT::RowVector row(3); + NEWMAT::ColumnVector col(3); + + row[0] = ossimAbs(xLocation); + row[1] = 1; + row[2] = ossimAbs(xLocation); + col[0] = ossimAbs(yLocation); + col[1] = 1; + col[2] = ossimAbs(yLocation); + + (*theKernel) = col*row; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/filters/ossimDiscrete3x3HatFilter.h b/Utilities/OSSIM/ossim_core/imaging/filters/ossimDiscrete3x3HatFilter.h new file mode 100644 index 0000000000..f1fa41429a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/filters/ossimDiscrete3x3HatFilter.h @@ -0,0 +1,64 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimDiscrete3x3HatFilter.h,v 1.6 2003/05/13 11:31:04 dburken Exp $ +#ifndef ossimDiscrete3x3HatFilter_HEADER +#define ossimDiscrete3x3HatFilter_HEADER +#include "ossimDiscreteConvolutionKernel.h" +class ossimDiscrete3x3HatFilter : public ossimDiscreteConvolutionKernel +{ +public: + ossimDiscrete3x3HatFilter(); + + /*! + * Will expect a data buffer of size width*height + * and is row ordered. + */ + virtual void convolve(const float* data, + double& result, + float nullPixel=OSSIM_FLT_NAN)const; + + virtual void convolveSubImage(const float* data, + long dataWidth, + double& result, + float nullPixel=OSSIM_FLT_NAN)const; + + virtual void convolve(const unsigned char* data, + double& result, + ossim_uint8 nullPixel=0.0)const; + /*! + * this allows you to pass a subImage to + * the convolution engine. It needs to know + * the width of the buffer so it can increment + * to the next element. + */ + virtual void convolveSubImage(const unsigned char* data, + long dataWidth, + double& result, + ossim_uint8 nullPixel=0.0)const; + + virtual void buildConvolution(double widthPercent, + double heightPercent); +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/filters/ossimDiscreteConvolutionKernel.cpp b/Utilities/OSSIM/ossim_core/imaging/filters/ossimDiscreteConvolutionKernel.cpp new file mode 100644 index 0000000000..33817595ca --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/filters/ossimDiscreteConvolutionKernel.cpp @@ -0,0 +1,557 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimDiscreteConvolutionKernel.cpp,v 1.11 2003/05/13 11:31:04 dburken Exp $ +#include "ossimDiscreteConvolutionKernel.h" + + +ossimDiscreteConvolutionKernel::ossimDiscreteConvolutionKernel(long width, + long height, + bool doWeightedAverage) + : theKernel(NULL), + theWidth(width), + theHeight(height), + theComputeWeightedAverageFlag(doWeightedAverage) +{ + theWidth = theWidth <0?1:theWidth; + theHeight = theHeight <0?1:theHeight; + + theKernel = new NEWMAT::Matrix(theHeight, theWidth); + *theKernel = (1.0/(theHeight*theWidth)); +} + +ossimDiscreteConvolutionKernel::ossimDiscreteConvolutionKernel(const NEWMAT::Matrix& kernel, + bool doWeightedAverage) + :theKernel(new NEWMAT::Matrix(kernel)), + theComputeWeightedAverageFlag(doWeightedAverage) +{ + theWidth = theKernel->Ncols(); + theHeight = theKernel->Nrows(); +} + +ossimDiscreteConvolutionKernel::~ossimDiscreteConvolutionKernel() +{ + if(theKernel) + { + delete theKernel; + theKernel = NULL; + } +} + +void ossimDiscreteConvolutionKernel::buildSymmetric(const std::vector<float>& coefficients, + NEWMAT::Matrix& result) +{ + long size = coefficients.size(); + if(size > 0) + { + + NEWMAT::RowVector row(size); + NEWMAT::ColumnVector col(size); + for(long index = 0; index < size; ++index) + { + row[index] = coefficients[index]; + col[index] = coefficients[index]; + } + result = col*row; + } +} + +void ossimDiscreteConvolutionKernel::buildSymmetric(float *coefficients, + long size, + NEWMAT::Matrix& result) +{ + if(size > 0) + { + NEWMAT::RowVector row(size); + NEWMAT::ColumnVector col(size); + for(long index = 0; index < size; ++index) + { + row[index] = coefficients[index]; + col[index] = coefficients[index]; + } + result = col*row; + } +} + +void ossimDiscreteConvolutionKernel::setKernel(const NEWMAT::Matrix& kernel) +{ + if(theKernel) + { + theKernel = new NEWMAT::Matrix; + } + *theKernel = kernel; + theWidth = theKernel->Ncols(); + theHeight = theKernel->Nrows(); +} + +void ossimDiscreteConvolutionKernel::convolve(const float* data, + double& result, + float nullPixel)const +{ + result = 0; + + if(theComputeWeightedAverageFlag) + { + double divisor = 0.0; + for(long row=0; row < theHeight; ++row) + { + for(long col=0; col < theWidth; ++col) + { + if(*data != nullPixel) + { + divisor += (*theKernel)[row][col]; + result += ((*theKernel)[row][col] * (*data)); + } + ++data; + } + } + if(divisor > 0) + { + result /= divisor; + } + } + else + { + for(long row=0; row < theHeight; ++row) + { + for(long col=0; col < theWidth; ++col) + { + if(*data != nullPixel) + { + result += ((*theKernel)[row][col] * (*data)); + } + ++data; + } + } + } +} + +void ossimDiscreteConvolutionKernel::convolveSubImage(const float* data, + long dataWidth, + double& result, + float nullPixel)const +{ + const float* dataStart = NULL; + result = 0; + + if(theComputeWeightedAverageFlag) + { + double divisor = 0.0; + for(long row=0; row < theHeight; ++row) + { + dataStart=data; + for(long col=0; col < theWidth; ++col) + { + if(*dataStart != nullPixel) + { + divisor += (*theKernel)[row][col]; + result += ((*theKernel)[row][col] * (*dataStart)); + } + ++dataStart; + } + data+=dataWidth; + } + if(divisor > 0) + { + result /= divisor; + } + } + else + { + for(long row=0; row < theHeight; ++row) + { + dataStart=data; + for(long col=0; col < theWidth; ++col) + { + if(*dataStart != nullPixel) + { + result += ((*theKernel)[row][col] * (*dataStart)); + } + ++dataStart; + } + data+=dataWidth; + } + } +} + +void ossimDiscreteConvolutionKernel::convolve(const unsigned char* data, + double& result, + ossim_uint8 nullPixel)const +{ + result = 0; + + if(theComputeWeightedAverageFlag) + { + double divisor = 0.0; + for(long row=0; row < theHeight; ++row) + { + for(long col=0; col < theWidth; ++col) + { + if(*data != nullPixel) + { + divisor += (*theKernel)[row][col]; + result += ((*theKernel)[row][col] * (*data)); + } + ++data; + } + } + if(divisor > 0) + { + result /= divisor; + } + } + else + { + for(long row=0; row < theHeight; ++row) + { + for(long col=0; col < theWidth; ++col) + { + if(*data != nullPixel) + { + result += ((*theKernel)[row][col] * (*data)); + } + ++data; + } + } + } +} + +void ossimDiscreteConvolutionKernel::convolveSubImage(const unsigned char* data, + long dataWidth, + double& result, + ossim_uint8 nullPixel)const +{ + const ossim_uint8* dataStart = NULL; + result = 0; + + if(theComputeWeightedAverageFlag) + { + double divisor = 0.0; + for(long row=0; row < theHeight; ++row) + { + dataStart=data; + for(long col=0; col < theWidth; ++col) + { + if(*dataStart != nullPixel) + { + divisor += (*theKernel)[row][col]; + result += ((*theKernel)[row][col] * (*dataStart)); + } + ++dataStart; + } + data+=dataWidth; + } + if(divisor > 0) + { + result /= divisor; + } + } + else + { + for(long row=0; row < theHeight; ++row) + { + dataStart=data; + for(long col=0; col < theWidth; ++col) + { + if(*dataStart != nullPixel) + { + result += ((*theKernel)[row][col] * (*dataStart)); + } + ++dataStart; + } + data+=dataWidth; + } + } +} + + +void ossimDiscreteConvolutionKernel::convolve(const unsigned short* data, + double& result, + ossim_uint16 nullPixel)const +{ + result = 0; + + if(theComputeWeightedAverageFlag) + { + double divisor = 0.0; + for(long row=0; row < theHeight; ++row) + { + for(long col=0; col < theWidth; ++col) + { + if(*data != nullPixel) + { + divisor += (*theKernel)[row][col]; + result += ((*theKernel)[row][col] * (*data)); + } + ++data; + } + } + if(divisor > 0) + { + result /= divisor; + } + } + else + { + for(long row=0; row < theHeight; ++row) + { + for(long col=0; col < theWidth; ++col) + { + if(*data != nullPixel) + { + result += ((*theKernel)[row][col] * (*data)); + } + ++data; + } + } + } +} + +void ossimDiscreteConvolutionKernel::convolveSubImage(const unsigned short* data, + long dataWidth, + double& result, + ossim_uint16 nullPixel)const +{ + const ossim_uint16* dataStart = NULL; + result = 0; + + if(theComputeWeightedAverageFlag) + { + double divisor = 0.0; + for(long row=0; row < theHeight; ++row) + { + dataStart=data; + for(long col=0; col < theWidth; ++col) + { + if(*dataStart != nullPixel) + { + divisor += (*theKernel)[row][col]; + result += ((*theKernel)[row][col] * (*dataStart)); + } + ++dataStart; + } + data+=dataWidth; + } + if(divisor > 0) + { + result /= divisor; + } + } + else + { + for(long row=0; row < theHeight; ++row) + { + dataStart=data; + for(long col=0; col < theWidth; ++col) + { + if(*dataStart != nullPixel) + { + result += ((*theKernel)[row][col] * (*dataStart)); + } + ++dataStart; + } + data+=dataWidth; + } + } +} + +void ossimDiscreteConvolutionKernel::convolve(const short* data, + double& result, + ossim_sint16 nullPixel)const +{ + result = 0; + + if(theComputeWeightedAverageFlag) + { + double divisor = 0.0; + for(long row=0; row < theHeight; ++row) + { + for(long col=0; col < theWidth; ++col) + { + if(*data != nullPixel) + { + divisor += (*theKernel)[row][col]; + result += ((*theKernel)[row][col] * (*data)); + } + ++data; + } + } + if(divisor > 0) + { + result /= divisor; + } + } + else + { + for(long row=0; row < theHeight; ++row) + { + for(long col=0; col < theWidth; ++col) + { + if(*data != nullPixel) + { + result += ((*theKernel)[row][col] * (*data)); + } + ++data; + } + } + } +} + +void ossimDiscreteConvolutionKernel::convolveSubImage(const short* data, + long dataWidth, + double& result, + ossim_sint16 nullPixel)const +{ + const ossim_sint16* dataStart = NULL; + result = 0; + + if(theComputeWeightedAverageFlag) + { + double divisor = 0.0; + for(long row=0; row < theHeight; ++row) + { + dataStart=data; + for(long col=0; col < theWidth; ++col) + { + if(*dataStart != nullPixel) + { + divisor += (*theKernel)[row][col]; + result += ((*theKernel)[row][col] * (*dataStart)); + } + ++dataStart; + } + data+=dataWidth; + } + if(divisor > 0) + { + result /= divisor; + } + } + else + { + for(long row=0; row < theHeight; ++row) + { + dataStart=data; + for(long col=0; col < theWidth; ++col) + { + if(*dataStart != nullPixel) + { + result += ((*theKernel)[row][col] * (*dataStart)); + } + ++dataStart; + } + data+=dataWidth; + } + } +} + + +void ossimDiscreteConvolutionKernel::convolve(const double* data, + double& result, + double nullPixel)const +{ + result = 0; + + if(theComputeWeightedAverageFlag) + { + double divisor = 0.0; + for(long row=0; row < theHeight; ++row) + { + for(long col=0; col < theWidth; ++col) + { + if(*data != nullPixel) + { + divisor += (*theKernel)[row][col]; + result += ((*theKernel)[row][col] * (*data)); + } + ++data; + } + } + if(divisor > 0) + { + result /= divisor; + } + } + else + { + for(long row=0; row < theHeight; ++row) + { + for(long col=0; col < theWidth; ++col) + { + if(*data != nullPixel) + { + result += ((*theKernel)[row][col] * (*data)); + } + ++data; + } + } + } +} + +void ossimDiscreteConvolutionKernel::convolveSubImage(const double* data, + long dataWidth, + double& result, + double nullPixel)const +{ + const double* dataStart = NULL; + result = 0; + + if(theComputeWeightedAverageFlag) + { + double divisor = 0.0; + for(long row=0; row < theHeight; ++row) + { + dataStart=data; + for(long col=0; col < theWidth; ++col) + { + if(*dataStart != nullPixel) + { + divisor += (*theKernel)[row][col]; + result += ((*theKernel)[row][col] * (*dataStart)); + } + ++dataStart; + } + data+=dataWidth; + } + if(divisor > 0) + { + result /= divisor; + } + } + else + { + for(long row=0; row < theHeight; ++row) + { + dataStart=data; + for(long col=0; col < theWidth; ++col) + { + if(*dataStart != nullPixel) + { + result += ((*theKernel)[row][col] * (*dataStart)); + } + ++dataStart; + } + data+=dataWidth; + } + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/filters/ossimDiscreteConvolutionKernel.h b/Utilities/OSSIM/ossim_core/imaging/filters/ossimDiscreteConvolutionKernel.h new file mode 100644 index 0000000000..e54c29ad3c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/filters/ossimDiscreteConvolutionKernel.h @@ -0,0 +1,151 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimDiscreteConvolutionKernel.h,v 1.12 2003/05/13 11:31:04 dburken Exp $ +#ifndef ossimDiscreteConvolutionKernel_HEADER +#define ossimDiscreteConvolutionKernel_HEADER +#include <vector> +#include "base/common/ossimConstants.h" +#include <iostream> +using namespace std; + +#include "matrix/newmat.h" +#include "matrix/newmatio.h" + +class ossimDiscreteConvolutionKernel +{ +public: + ossimDiscreteConvolutionKernel(long width, + long height, + bool doWeightedAverage=true); + ossimDiscreteConvolutionKernel(const NEWMAT::Matrix& kernel, + bool doWeightedAverage=true); + virtual ~ossimDiscreteConvolutionKernel(); + static void buildSymmetric(const std::vector<float>& coefficients, + NEWMAT::Matrix& result); + static void buildSymmetric(float* coefficients, long size, + NEWMAT::Matrix& result); + + virtual void setKernel(const NEWMAT::Matrix& kernel); + + /*! + * Will expect a data buffer of size width*height + * and is row ordered. + */ + virtual void convolve(const float* data, + double& result, + float nullPixel=OSSIM_FLT_NAN)const; + + virtual void convolveSubImage(const float* data, + long dataWidth, + double& result, + float nullPixel=OSSIM_FLT_NAN)const; + + /*! + * Will expect a data buffer of size width*height + * and is row ordered. + */ + virtual void convolve(const double* data, + double& result, + double nullPixel=OSSIM_DBL_NAN)const; + + virtual void convolveSubImage(const double* data, + long dataWidth, + double& result, + double nullPixel=OSSIM_DBL_NAN)const; + /*! + * Will expect a data buffer of size width*height + * and is row ordered. + */ + virtual void convolve(const short* data, + double& result, + ossim_sint16 nullPixel=OSSIM_SSHORT_NAN)const; + + virtual void convolveSubImage(const short* data, + long dataWidth, + double& result, + ossim_sint16 nullPixel=OSSIM_SSHORT_NAN)const; + + /*! + * Will expect a data buffer of size width*height + * and is row ordered. + */ + virtual void convolve(const unsigned short* data, + double& result, + ossim_uint16 nullPixel=OSSIM_USHORT_NAN)const; + + virtual void convolveSubImage(const unsigned short* data, + long dataWidth, + double& result, + ossim_uint16 nullPixel=OSSIM_USHORT_NAN)const; + + + virtual void convolve(const unsigned char* data, + double& result, + ossim_uint8 nullPixel=0)const; + /*! + * this allows you to pass a subImage to + * the convolution engine. It needs to know + * the width of the buffer so it can increment + * to the next element. + */ + virtual void convolveSubImage(const unsigned char* data, + long dataWidth, + double& result, + ossim_uint8 nullPixel=0)const; + /*! + * This is used to allow me to continually adjust a convolution kernel + * based on where it center lies on a pixel. The xLocation and yLocation + * are all from the center of pixel. If I am convolving at full resolution + * then xLocation and yLocation should both be 0. Let's pretend that we + * contract an image by .5 scale factor or zooming out by a factor of 2. Then + * we actually of it .5 off from cneter of pixel in both the x and y direction. + * This information can be used to allow a kernel to adjust it's waits accordingly. + * + * Typically if the xLocation and yLocation is directly on the center indicated + * by 0 vor both then the kernel defaults to 1 in the middle and all other weights + * are zero. + */ + virtual void buildConvolution(double xLocation, + double yLocation) + {} + virtual long getWidth()const + { + return theWidth; + } + virtual long getHeight()const + { + return theHeight; + } + const NEWMAT::Matrix& getKernel()const + { + return *theKernel; + } +protected: + NEWMAT::Matrix *theKernel; + long theWidth; + long theHeight; + bool theComputeWeightedAverageFlag; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/filters/ossimDiscreteNearestNeighbor.h b/Utilities/OSSIM/ossim_core/imaging/filters/ossimDiscreteNearestNeighbor.h new file mode 100644 index 0000000000..90a6317c90 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/filters/ossimDiscreteNearestNeighbor.h @@ -0,0 +1,123 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimDiscreteNearestNeighbor.h,v 1.2 2001/07/11 15:17:01 gpotts Exp $ +#ifndef ossimDiscreteNearestNeighbor_HEADER +#define ossimDiscreteNearestNeighbor_HEADER +#include "ossimDiscreteConvolutionKernel.h" +class ossimDiscreteNearestNeighbor : public ossimDiscreteConvolutionKernel +{ +public: + ossimDiscreteNearestNeighbor() + :ossimDiscreteConvolutionKernel(1, 1) + { + + } + + /*! + * We will override and optimize by unrolling the + * loop + */ + virtual void convolveFloat(const float* data, + double& result)const + { + result = *data; + } + + /*! + * We will override and optimize by unrolling the + * loop + */ + virtual void convolveSubImageFloat(const float* data, + long dataWidth, + double& result)const + { + result = *data; + } + + virtual void convolveDouble(const double* data, + double& result)const + { + result = *data; + } + + virtual void convolveSubImageDouble(const double* data, + long dataWidth, + double& result)const + { + result = *data; + } + /*! + * We will override and optimize by unrolling the + * loop + */ + virtual void convolveUchar(const unsigned char* data, + double& result)const + { + result = *data; + } + /*! + * We will override and optimize by unrolling the + * loop + */ + virtual void convolveSubImageUchar(const unsigned char* data, + long dataWidth, + double& result)const + { + result = *data; + } + + virtual void convolveSshort(const short* data, + double& result)const + { + result = *data; + } + + virtual void convolveSubImageSshort(const short* data, + long dataWidth, + double& result)const + + { + result = *data; + } + + virtual void convolveUshort(const unsigned short* data, + double& result)const + { + result = *data; + } + + virtual void convolveSubImageUshort(const unsigned short* data, + long dataWidth, + double& result)const + { + result = *data; + } + + virtual void buildConvolution(double widthPercent, + double heightPercent) + { + } +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/filters/ossimFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/filters/ossimFilter.cpp new file mode 100644 index 0000000000..69f7afc9d0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/filters/ossimFilter.cpp @@ -0,0 +1,333 @@ +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % +% ZZZZZ OOO OOO M M % +% ZZ O O O O MM MM % +% ZZZ O O O O M M M % +% ZZ O O O O M M % +% ZZZZZ OOO OOO M M % +% % +% % +% ImageMagick Image Zoom Methods % +% % +% % +% Software Design % +% John Cristy % +% July 1992 % +% % +% % +% Copyright (C) 2000 ImageMagick Studio, a non-profit organization dedicated % +% to making software imaging solutions freely available. % +% % +% Permission is hereby granted, free of charge, to any person obtaining a % +% copy of this software and associated documentation files ("ImageMagick"), % +% to deal in ImageMagick without restriction, including without limitation % +% the rights to use, copy, modify, merge, publish, distribute, sublicense, % +% and/or sell copies of ImageMagick, and to permit persons to whom the % +% ImageMagick is furnished to do so, subject to the following conditions: % +% % +% The above copyright notice and this permission notice shall be included in % +% all copies or substantial portions of ImageMagick. % +% % +% 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 % +% ImageMagick Studio 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 ImageMagick or the use or other dealings in % +% ImageMagick. % +% % +% Except as contained in this notice, the name of the ImageMagick Studio % +% shall not be used in advertising or otherwise to promote the sale, use or % +% other dealings in ImageMagick without prior written authorization from the % +% ImageMagick Studio. % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% +% +*/ +#include "base/common/ossimConstants.h" +#include "ossimFilter.h" +#include "matrix/newmat.h" +#include <iostream> + + +RTTI_DEF(ossimFilter, "ossimFilter"); +RTTI_DEF1(ossimBoxFilter, "ossimBoxFilter",ossimFilter); +RTTI_DEF1(ossimSincFilter, "ossimSincFilter",ossimFilter); +RTTI_DEF1(ossimBellFilter, "ossimBellFilter",ossimFilter); +RTTI_DEF1(ossimNearestNeighborFilter, "ossimNearestNeighborFilter",ossimFilter); +RTTI_DEF1(ossimBesselFilter, "ossimBesselFilter",ossimFilter); +RTTI_DEF1(ossimBesselOrderOneFilter, "ossimBesselOrderOneFilter",ossimFilter); +RTTI_DEF1(ossimBlackmanFilter, "ossimBlackmanFilter",ossimFilter); +RTTI_DEF1(ossimBlackmanSincFilter, "ossimBlackmanSincFilter",ossimFilter); +RTTI_DEF1(ossimBlackmanBesselFilter, "ossimBlackmanBesselFilter",ossimFilter); +RTTI_DEF1(ossimCatromFilter, "ossimCatromFilter",ossimFilter); +RTTI_DEF1(ossimCubicFilter, "ossimCubicFilter",ossimFilter); +RTTI_DEF1(ossimBSplineFilter, "ossimBSplineFilter",ossimFilter); +RTTI_DEF1(ossimGaussianFilter, "ossimGaussianFilter",ossimFilter); +RTTI_DEF1(ossimHanningFilter, "ossimHanningFilter",ossimFilter); +RTTI_DEF1(ossimHammingFilter, "ossimHammingFilter",ossimFilter); +RTTI_DEF1(ossimHermiteFilter, "ossimHermiteFilter",ossimFilter); +RTTI_DEF1(ossimLanczosFilter, "ossimLanczosFilter",ossimFilter); +RTTI_DEF1(ossimMitchellFilter, "ossimMitchellFilter",ossimFilter); +RTTI_DEF1(ossimQuadraticFilter, "ossimQuadraticFilter",ossimFilter); +RTTI_DEF1(ossimTriangleFilter, "ossimTriangleFilter",ossimFilter); +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % ++ B e s s e l O r d e r O n e % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Method BesselOrderOne computes the Bessel function of x of the first kind +% of order 0: +% +% Reduce x to |x| since j1(x)= -j1(-x), and for x in (0,8] +% +% j1(x) = x*j1(x); +% +% For x in (8,inf) +% +% j1(x) = sqrt(2/(pi*x))*(p1(x)*cos(x1)-q1(x)*sin(x1)) +% +% where x1 = x-3*pi/4. Compute sin(x1) and cos(x1) as follow: +% +% cos(x1) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4) +% = 1/sqrt(2) * (sin(x) - cos(x)) +% sin(x1) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) +% = -1/sqrt(2) * (sin(x) + cos(x)) +% +% The format of the BesselOrderOne method is: +% +% double BesselOrderOne(double x) +% +% A description of each parameter follows: +% +% o value: Method BesselOrderOne returns the Bessel function of x of the +% first kind of orders 1. +% +% o x: double value. +% +% +*/ + +static double J1(double x) +{ + double + p, + q; + + register int + i; + + static const double + Pone[] = + { + 0.581199354001606143928050809e+21, + -0.6672106568924916298020941484e+20, + 0.2316433580634002297931815435e+19, + -0.3588817569910106050743641413e+17, + 0.2908795263834775409737601689e+15, + -0.1322983480332126453125473247e+13, + 0.3413234182301700539091292655e+10, + -0.4695753530642995859767162166e+7, + 0.270112271089232341485679099e+4 + }, + Qone[] = + { + 0.11623987080032122878585294e+22, + 0.1185770712190320999837113348e+20, + 0.6092061398917521746105196863e+17, + 0.2081661221307607351240184229e+15, + 0.5243710262167649715406728642e+12, + 0.1013863514358673989967045588e+10, + 0.1501793594998585505921097578e+7, + 0.1606931573481487801970916749e+4, + 0.1e+1 + }; + + p=Pone[8]; + q=Qone[8]; + for (i=7; i >= 0; i--) + { + p=p*x*x+Pone[i]; + q=q*x*x+Qone[i]; + } + return(p/q); +} + +static double P1(double x) +{ + double + p, + q; + + register int + i; + + static const double + Pone[] = + { + 0.352246649133679798341724373e+5, + 0.62758845247161281269005675e+5, + 0.313539631109159574238669888e+5, + 0.49854832060594338434500455e+4, + 0.2111529182853962382105718e+3, + 0.12571716929145341558495e+1 + }, + Qone[] = + { + 0.352246649133679798068390431e+5, + 0.626943469593560511888833731e+5, + 0.312404063819041039923015703e+5, + 0.4930396490181088979386097e+4, + 0.2030775189134759322293574e+3, + 0.1e+1 + }; + + p=Pone[5]; + q=Qone[5]; + for (i=4; i >= 0; i--) + { + p=p*(8.0/x)*(8.0/x)+Pone[i]; + q=q*(8.0/x)*(8.0/x)+Qone[i]; + } + return(p/q); +} + +static double Q1(double x) +{ + double + p, + q; + + register int + i; + + static const double + Pone[] = + { + 0.3511751914303552822533318e+3, + 0.7210391804904475039280863e+3, + 0.4259873011654442389886993e+3, + 0.831898957673850827325226e+2, + 0.45681716295512267064405e+1, + 0.3532840052740123642735e-1 + }, + Qone[] = + { + 0.74917374171809127714519505e+4, + 0.154141773392650970499848051e+5, + 0.91522317015169922705904727e+4, + 0.18111867005523513506724158e+4, + 0.1038187585462133728776636e+3, + 0.1e+1 + }; + + p=Pone[5]; + q=Qone[5]; + for (i=4; i >= 0; i--) + { + p=p*(8.0/x)*(8.0/x)+Pone[i]; + q=q*(8.0/x)*(8.0/x)+Qone[i]; + } + return(p/q); +} + +double ossimBesselOrderOneFilter::filter(double x, double support)const +{ + double + p, + q; + + if (x == 0.0) + return(0.0); + p=x; + if (x < 0.0) + x=(-x); + if (x < 8.0) + return(p*J1(x)); + q=sqrt(2.0/(M_PI*x))*(P1(x)*(1.0/sqrt(2.0)*(sin(x)-cos(x)))-8.0/x*Q1(x)* + (-1.0/sqrt(2.0)*(sin(x)+cos(x)))); + if (p < 0.0) + q=(-q); + return(q); + +} + +void ossimFilter::createMatrix(NEWMAT::Matrix& m, + long width, + double middle, + double scale)const +{ + NEWMAT::ColumnVector colVec(width); + NEWMAT::RowVector rowVec(width); + + double t = 0.0; + double val = 0.0; + if(width == 1) + { + t = 0; + val = filter(t, getSupport()); + colVec[0] = val; + rowVec[0] = val; + } + else + { + for(long index = 0; index < width; index++) + { + t = (double)index/(double)(width-1); + t = middle + (t - .5)*scale; + val = filter(t, getSupport()); + colVec[index] = val; + rowVec[index] = val; + } + } + + // do the outer product to construct the + // filter matrix + m = colVec * rowVec; +} + + +NEWMAT::Matrix *ossimFilter::newMatrix(long width, + double middle, + double scale)const +{ + NEWMAT::Matrix *result = new NEWMAT::Matrix(width, width); + + createMatrix(*result, + width, + middle, + scale); + + return result; +} + +NEWMAT::RowVector *ossimFilter::newVector(long width, + double middle, + double scale)const +{ + NEWMAT::RowVector *result = new NEWMAT::RowVector(width); + + + double t = 0.0; + double val = 0.0; + for(long index = 0; index < width; index++) + { + t = (double)index/(double)(width-1); + t = middle + (t- .5)*scale; + val = filter(t, getSupport()); + (*result)[index] = val; + } + + return result; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/filters/ossimFilter.h b/Utilities/OSSIM/ossim_core/imaging/filters/ossimFilter.h new file mode 100644 index 0000000000..52e374bfd0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/filters/ossimFilter.h @@ -0,0 +1,486 @@ +#ifndef ossimFilter_HEADER +#define ossimFilter_HEADER +#include <math.h> +#include "matrix/newmat.h" +#include "base/common/ossimRtti.h" + + +class ossimFilter +{ +public: + ossimFilter() + {} + virtual ~ossimFilter() {} + + virtual double filter (double x, double support)const = 0; + /*! + * Will call the filter method to create a + * convolution matrix. This matrix will not + * have normalized weights. + * + * Will generate a matrix by creating an outer + * product of the 1-D filter array. This matrix + * will be square width-by-width. + * + * note: the matrix is a new matrix and needs to + * be destroyed by the caller + */ + virtual NEWMAT::Matrix *newMatrix(long width=3, + double middle=0.0, + double scale=0.0)const; + virtual void createMatrix(NEWMAT::Matrix& m, + long width=3, + double middle=0.0, + double scale=0.0)const; + + virtual NEWMAT::RowVector *newVector(long width, + double middle=0.0, + double scale = 1.0)const; + static double Sinc(double x) + { + if (x != 0.0) + { + x*=M_PI; + return(sin(x)/x); + } + + return(1.0); + } + static double Sinc(double x, double /* support */ ) + { + if (x != 0.0) + { + x*=M_PI; + return(sin(x)/x); + } + + return(1.0); + } + + virtual double getSupport()const=0; + +TYPE_DATA +}; + +class ossimBoxFilter : public ossimFilter +{ +public: + ossimBoxFilter (){} + virtual ~ossimBoxFilter() {} + + virtual double filter (double x, double /* support */ )const + { + if (x < -0.5) + return(0.0); + if (x < 0.5) + return(1.0); + return(0.0); + } + virtual double getSupport()const + { + return .5; + } +TYPE_DATA +}; + +class ossimSincFilter : public ossimFilter +{ +public: + ossimSincFilter(){} + virtual ~ossimSincFilter(){} + double filter(double x, double /* support */ )const + { + x*=M_PI; + if (x != 0.0) + return(sin(x)/x); + return(1.0); + } + virtual double getSupport()const + { + return 1.0; + } +TYPE_DATA +}; + +class ossimBellFilter : public ossimFilter +{ +public: + ossimBellFilter(){} + virtual ~ossimBellFilter(){} + virtual double getSupport()const + { + return 1.5; + } + virtual double filter(double value, double /* support */ )const + { + if(value < 0) value = -value; + if(value < .5) return(.75 - (value * value)); + if(value < 1.5) { + value = (value - 1.5); + return(.5 * (value * value)); + } + return(0.0); + } +TYPE_DATA +}; + +class ossimNearestNeighborFilter: public ossimBoxFilter +{ +public: + ossimNearestNeighborFilter (){} + virtual ~ossimNearestNeighborFilter() {} + + virtual double getSupport()const + { + return 0.0; + } +TYPE_DATA +}; + + +class ossimBesselOrderOneFilter : public ossimFilter +{ +public: + ossimBesselOrderOneFilter(){} + virtual ~ossimBesselOrderOneFilter(){} + virtual double filter(double value, double /* support */ )const; + virtual double getSupport()const + { + return 1.0; + } +TYPE_DATA +}; +class ossimBesselFilter : public ossimFilter +{ +public: + ossimBesselFilter(){} + virtual ~ossimBesselFilter(){} + virtual double filter(double x, double support)const + { + if (x == 0.0) + { + return(M_PI/4.0); + } + + return(ossimBesselOrderOneFilter().filter((M_PI*x)/(2.0*x), support)); + } + virtual double getSupport()const + { + return 1.0; + } + +TYPE_DATA +}; + +class ossimBlackmanFilter : public ossimFilter +{ +public: + ossimBlackmanFilter (){} + virtual ~ossimBlackmanFilter() {} + + virtual double filter (double x, double /* support */ ) const + { + return(0.42+0.50*cos(M_PI*x)+0.08*cos(2.0*M_PI*x)); + } + virtual double getSupport()const + { + return 1.0; + } +TYPE_DATA +}; + +class ossimBlackmanSincFilter : public ossimBlackmanFilter +{ +public: + ossimBlackmanSincFilter (){} + virtual ~ossimBlackmanSincFilter() {} + + virtual double filter (double x, double support) const + { + return ((ossimBlackmanFilter::filter(x/support,support))* + (ossimSincFilter().filter(x, support))); + } + virtual double getSupport()const + { + return 4.0; + } +TYPE_DATA +}; + +class ossimBlackmanBesselFilter : public ossimBlackmanFilter +{ +public: + ossimBlackmanBesselFilter(){} + virtual ~ossimBlackmanBesselFilter() {} + + virtual double filter (double x, double support) const + { + return ((ossimBlackmanFilter::filter(x/support,support))* + (ossimBesselFilter().filter(x, support))); + } + virtual double getSupport()const + { + return 3.2383; + } +TYPE_DATA +}; + + +class ossimCatromFilter : public ossimFilter +{ +public: + ossimCatromFilter(){} + virtual ~ossimCatromFilter(){} + double filter(double x, double /* support */ )const + { + if (x < -2.0) + return(0.0); + if (x < -1.0) + return(0.5*(4.0+x*(8.0+x*(5.0+x)))); + if (x < 0.0) + return(0.5*(2.0+x*x*(-5.0-3.0*x))); + if (x < 1.0) + return(0.5*(2.0+x*x*(-5.0+3.0*x))); + if (x < 2.0) + return(0.5*(4.0+x*(-8.0+x*(5.0-x)))); + return(0.0); + } + virtual double getSupport()const + { + return 2.0; + } +TYPE_DATA +}; + +class ossimCubicFilter : public ossimFilter +{ +public: + ossimCubicFilter(){} + virtual ~ossimCubicFilter(){} + double filter(double x, double /* support */ )const + { + if (x < -2.0) + return(0.0); + if (x < -1.0) + return((2.0+x)*(2.0+x)*(2.0+x)/6.0); + if (x < 0.0) + return((4.0+x*x*(-6.0-3.0*x))/6.0); + if (x < 1.0) + return((4.0+x*x*(-6.0+3.0*x))/6.0); + if (x < 2.0) + return((2.0-x)*(2.0-x)*(2.0-x)/6.0); + return(0.0); + } + virtual double getSupport()const + { + return 2.0; + } +TYPE_DATA +}; + +class ossimBSplineFilter : public ossimFilter +{ +public: + ossimBSplineFilter(){} + virtual ~ossimBSplineFilter(){} + virtual double filter(double value, double /* support */ )const + { + double tt; + + if(value < 0) value = -value; + if(value < 1) { + tt = value * value; + return((.5 * tt * value) - tt + (2.0 / 3.0)); + } else if(value < 2) { + value = 2 - value; + return((1.0 / 6.0) * (value * value * value)); + } + return(0.0); + } + virtual double getSupport()const + { + return 2.0; + } +TYPE_DATA +}; + +class ossimGaussianFilter : public ossimFilter +{ +public: + ossimGaussianFilter (){} + virtual ~ossimGaussianFilter() {} + + virtual double filter (double x, double /* support */ ) const + { + return(exp(-2.0*x*x)*sqrt(2.0/M_PI)); + } + virtual double getSupport()const + { + return 1.25; + } +TYPE_DATA +}; + +class ossimHanningFilter : public ossimFilter +{ +public: + ossimHanningFilter(){} + virtual ~ossimHanningFilter(){} + double filter(double x, double /* support */ )const + { + return(0.5+0.5*cos(M_PI*x)); + } + virtual double getSupport()const + { + return 1.0; + } +TYPE_DATA +}; + +class ossimHammingFilter : public ossimFilter +{ +public: + ossimHammingFilter (){} + virtual ~ossimHammingFilter() {} + + virtual double filter (double x, double /* support */ ) const + { + return(0.54+0.46*cos(M_PI*x)); + } + virtual double getSupport()const + { + return 1.0; + } +TYPE_DATA +}; + +class ossimHermiteFilter : public ossimFilter +{ +public: + ossimHermiteFilter(){} + virtual ~ossimHermiteFilter(){} + double filter(double x, double /* support */ )const + { + if (x < -1.0) + return(0.0); + if (x < 0.0) + return((2.0*(-x)-3.0)*(-x)*(-x)+1.0); + if (x < 1.0) + return((2.0*x-3.0)*x*x+1.0); + return(0.0); + } + virtual double getSupport()const + { + return 1.0; + } +TYPE_DATA +}; + + +class ossimLanczosFilter : public ossimFilter +{ +public: + ossimLanczosFilter(){} + virtual ~ossimLanczosFilter(){} + double filter(double x, double /* support */ )const + { + if (x < -3.0) + return(0.0); + if (x < 0.0) + return(Sinc(-x,getSupport())*Sinc(-x/3.0,getSupport())); + if (x < 3.0) + return(Sinc(x,getSupport())*Sinc(x/3.0,getSupport())); + return(0.0); + } + virtual double getSupport()const + { + return 3.0; + } +TYPE_DATA +}; + +class ossimMitchellFilter : public ossimFilter +{ +public: + ossimMitchellFilter(){} + virtual ~ossimMitchellFilter(){} + double filter(double x, double /* support */ )const + { +#define MITCHELL_B (1.0/3.0) +#define MITCHELL_C (1.0/3.0) +#define MITCHELL_P0 (( 6.0- 2.0*MITCHELL_B )/6.0) +#define MITCHELL_P2 ((-18.0+12.0*MITCHELL_B+ 6.0*MITCHELL_C)/6.0) +#define MITCHELL_P3 (( 12.0- 9.0*MITCHELL_B- 6.0*MITCHELL_C)/6.0) +#define MITCHELL_Q0 (( 8.0*MITCHELL_B+24.0*MITCHELL_C)/6.0) +#define MITCHELL_Q1 (( -12.0*MITCHELL_B-48.0*MITCHELL_C)/6.0) +#define MITCHELL_Q2 (( 6.0*MITCHELL_B+30.0*MITCHELL_C)/6.0) +#define MITCHELL_Q3 (( - 1.0*MITCHELL_B- 6.0*MITCHELL_C)/6.0) + + if (x < -2.0) + return(0.0); + if (x < -1.0) + return(MITCHELL_Q0-x*(MITCHELL_Q1-x*(MITCHELL_Q2-x*MITCHELL_Q3))); + if (x < 0.0) + return(MITCHELL_P0+x*x*(MITCHELL_P2-x*MITCHELL_P3)); + if (x < 1.0) + return(MITCHELL_P0+x*x*(MITCHELL_P2+x*MITCHELL_P3)); + if (x < 2.0) + return(MITCHELL_Q0+x*(MITCHELL_Q1+x*(MITCHELL_Q2+x*MITCHELL_Q3))); + return(0.0); + } + virtual double getSupport()const + { + return 2.0; + } +TYPE_DATA +}; + +class ossimQuadraticFilter : public ossimFilter +{ +public: + ossimQuadraticFilter(){} + virtual ~ossimQuadraticFilter(){} + double filter(double x, double /* support */ )const + { + if (x < -1.5) + return(0.0); + if (x < -0.5) + return(0.5*(x+1.5)*(x+1.5)); + if (x < 0.5) + return(0.75-x*x); + if (x < 1.5) + return(0.5*(x-1.5)*(x-1.5)); + return(0.0); + } + double getSupport()const + { + return 1.5; + } +TYPE_DATA +}; + +class ossimTriangleFilter : public ossimFilter +{ +public: + ossimTriangleFilter(){} + virtual ~ossimTriangleFilter() {} + + virtual double filter (double x, double /* support */ )const + { + if (x < -1.0) + return(0.0); + if (x < 0.0) + return(1.0+x); + if (x < 1.0) + return(1.0-x); + return(0.0); + } + virtual double getSupport()const + { + return 1.0; + } +TYPE_DATA +}; + + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/filters/ossimFilterTable.cpp b/Utilities/OSSIM/ossim_core/imaging/filters/ossimFilterTable.cpp new file mode 100644 index 0000000000..ef45f4e7c0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/filters/ossimFilterTable.cpp @@ -0,0 +1,149 @@ +//---------------------------------------------------------------------------- +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//---------------------------------------------------------------------------- +// $Id: ossimFilterTable.cpp,v 1.5 2005/08/12 17:08:07 dburken Exp $ +#include <iostream> +#include <imaging/filters/ossimFilterTable.h> +#include <imaging/filters/ossimFilter.h> + +ossimFilterTable::ossimFilterTable() + :theWeights(0), + theWidth(0), + theHeight(0), + theWidthHeight(0), + theXSupport(0), + theYSupport(0), + theFilterSteps(0) +{ + +} + +ossimFilterTable::~ossimFilterTable() +{ + if(theWeights) + { + delete [] theWeights; + theWeights = 0; + } +} + +void ossimFilterTable::buildTable(ossim_uint32 filterSteps, + const ossimFilter& filter) +{ + buildTable(filterSteps, filter, filter); +} + +void ossimFilterTable::buildTable(ossim_uint32 filterSteps, + const ossimFilter& xFilter, + const ossimFilter& yFilter) +{ + ossim_int32 subpixelSample=0; + ossim_int32 subpixelLine=0; + double dx = 0.0; + double dy = 0.0; + double kernelH = 0.0; + double kernelV = 0.0; + double x = 0; + double y = 0; + + double xsupport = ceil(xFilter.getSupport()); + double ysupport = ceil(yFilter.getSupport()); + double left = 0; + double right = 0; + double top = 0; + double bottom = 0; + + theXSupport = (ossim_uint32)xsupport; + theYSupport = (ossim_uint32)ysupport; + theFilterSteps = filterSteps; + theWidth = (2*theXSupport); + theHeight = (2*theYSupport); + theWidthHeight = theWidth*theHeight; + + allocateWeights(); + left = -(xsupport-1); + right = xsupport; + top = -(ysupport-1); + bottom = ysupport; + ossim_uint32 idx = 0; + + for (subpixelLine = 0; subpixelLine < (int)filterSteps; + subpixelLine++) + { + + // Calculate subpixel sample step. + // ---------------------------------- + dy = subpixelLine / (double)(filterSteps); + for (subpixelSample = 0; subpixelSample < (int)filterSteps; + subpixelSample++) + { + + // Calculate subpixel sample step. + // ---------------------------------- + dx = subpixelSample / (double)(filterSteps); + + for (kernelV=top; kernelV<=bottom; + kernelV++) + { + y = kernelV - dy; + double tempWeight = yFilter.filter(y, yFilter.getSupport()); + for(kernelH=left; kernelH<=right;++kernelH) + { + x = kernelH - dx; + + // Get the weight for the current pixel. + // ---------------------------------------- + theWeights[idx] = tempWeight*xFilter.filter(x, xFilter.getSupport()); + ++idx; + } + } + } + } +} + +ossim_uint32 ossimFilterTable::getWidthByHeight()const +{ + return theWidthHeight; +} + +ossim_uint32 ossimFilterTable::getXSupport()const +{ + return theXSupport; +} + +ossim_uint32 ossimFilterTable::getYSupport()const +{ + return theYSupport; +} + +ossim_uint32 ossimFilterTable::getWidth()const +{ + return theWidth; +} + +ossim_uint32 ossimFilterTable::getHeight()const +{ + return theHeight; +} + +void ossimFilterTable::allocateWeights() +{ + if(theWeights) + { + delete [] theWeights; + theWeights = 0; + } + + ossim_uint32 size = (theWidthHeight*(theFilterSteps*theFilterSteps)); + + if(size) + { + theWeights = new double[size]; + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/filters/ossimFilterTable.h b/Utilities/OSSIM/ossim_core/imaging/filters/ossimFilterTable.h new file mode 100644 index 0000000000..e417ad9e24 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/filters/ossimFilterTable.h @@ -0,0 +1,97 @@ +//---------------------------------------------------------------------------- +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//---------------------------------------------------------------------------- +// $Id: ossimFilterTable.h,v 1.4 2005/08/12 18:23:33 dburken Exp $ +#ifndef ossimFilterTable_HEADER +#define ossimFilterTable_HEADER + +#include <cmath> +#include <base/common/ossimConstants.h> + +class ossimFilter; + +class ossimFilterTable +{ +public: + /** default constructor */ + ossimFilterTable(); + + /** destructor */ + ~ossimFilterTable(); + + /** Builds a table with filter being used in both x and y direction. */ + void buildTable(ossim_uint32 filterSteps, + const ossimFilter& filter); + + /** Builds a table. */ + void buildTable(ossim_uint32 filterSteps, + const ossimFilter& xFilter, + const ossimFilter& yFilter); + + /** @return theWidth*theHeight */ + ossim_uint32 getWidthByHeight() const; + + /** @return theXSupport */ + ossim_uint32 getXSupport() const; + + /** @return theYSupport */ + ossim_uint32 getYSupport() const; + + /** @return theWidth */ + ossim_uint32 getWidth() const; + + /** @return theHeight */ + ossim_uint32 getHeight() const; + + /** + * Inlined below. + * + * @return const double* to the closest weight of x and y. + */ + const double* getClosestWeights(const double& x, const double& y)const; + +protected: + + /** + * Creates the weight array "theWeights". Will delete if previously + * allocated. + */ + void allocateWeights(); + + double* theWeights; + ossim_uint32 theWidth; + ossim_uint32 theHeight; + ossim_uint32 theWidthHeight; + ossim_uint32 theXSupport; + ossim_uint32 theYSupport; + ossim_uint32 theFilterSteps; +}; + +/** + * Method inlined for speed as it is used in the inner pixel loop of + * ossimFilterResampler::resampleBilinearTile method. + */ +inline const double* ossimFilterTable::getClosestWeights(const double& x, + const double& y)const +{ + // Extract the decimal part of x and y. + double intPartDummy; + double decimalPrecisionX = fabs(modf(x, &intPartDummy)); + double decimalPrecisionY = fabs(modf(y, &intPartDummy)); + + ossim_int32 kernelLine = + (ossim_int32)(theFilterSteps*decimalPrecisionY); + ossim_int32 kernelSamp = + (ossim_int32)(theFilterSteps*decimalPrecisionX); + + return &theWeights[(kernelLine*theFilterSteps + + kernelSamp)*theWidthHeight]; +} + +#endif /* End of "#ifndef ossimFilterTable_HEADER" */ diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/formats/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/adrg/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/formats/adrg/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/adrg/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimAdrgHeader.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimAdrgHeader.cpp new file mode 100644 index 0000000000..0e5ce93951 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimAdrgHeader.cpp @@ -0,0 +1,499 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Ken Melero +// Description: This class encapsulates the image parameters and +// support data for a ADRG image file(s). +// +//******************************************************************** +// $Id: ossimAdrgHeader.cpp,v 1.7 2005/02/13 16:08:04 dburken Exp $ + +#include <iostream> + +using namespace std; + +#include <imaging/formats/adrg/ossimAdrgHeader.h> +#include <imaging/formats/adrg/ossimIso8211.h> + +//************************************************************************** +// Constructor +//************************************************************************** +ossimAdrgHeader::ossimAdrgHeader(const ossimFilename& img_file) + : + theErrorStatus(OSSIM_OK), + theHeaderFile(ossimFilename("")), + theImageFile(img_file), + theValidImageRect(0,0,0,0), + thePixelType(OSSIM_UCHAR), + theInterleaveType(OSSIM_BSQ), + theNumberOfBands(3), + theLines(0), + theSamples(0), + theHeaderSize(0), + theTim(0) +{ + // Validate header file exists. + ossimFilename tmp_file; + ossimFilename tmp_path; + ossimFilename tmp_base; + ossimFilename tmp_hdr1; + ossimFilename tmp_hdr2; + + tmp_file = theImageFile.file(); + tmp_path = theImageFile.path(); + tmp_base = tmp_file.beforePos(6); + + tmp_hdr1 = tmp_path.dirCat(tmp_base); + tmp_hdr1 += "01.GEN"; + + tmp_hdr2 = tmp_path.dirCat(tmp_base); + tmp_hdr2 += "01.gen"; + + // we will force an open on the .img file + // + if(img_file.ext().downcase() != "img") + { + theErrorStatus = OSSIM_ERROR; + return; + } + if(tmp_hdr1.exists()) + { + theHeaderFile = tmp_hdr1; + } + else if(tmp_hdr2.exists()) + { + theHeaderFile = tmp_hdr2; + } + else + { + theErrorStatus = OSSIM_ERROR; + return; + } + + // Parse header for all needed support data. + parse(); +} + +//************************************************************************** +// Destructor +//************************************************************************** +ossimAdrgHeader::~ossimAdrgHeader() +{ + if(theTim) + delete [] theTim; +} + +//************************************************************************** +// Parse header +//************************************************************************** +void ossimAdrgHeader::parse() +{ + // NOTE: By default, ISO8211 library reports errors to stderr, + // so we don't bother doing it ourselves. We simply set + // the OSSIM_ERROR flag. + + ossimDDFModule oModule; + ossimDDFRecord* oRecord; + + // Open header file which is ISO8211 encoded. + if(!oModule.Open(theHeaderFile.chars()) ) + { + theErrorStatus = OSSIM_ERROR; + return; + } + + oRecord = oModule.ReadRecord(); + + ossimDDFField* oField = oRecord->FindField("DRF"); + int bytesOfData = oField->GetDataSize(); + int nBytesConsumed = 0; + const char* rawFieldData; + + ossimDDFFieldDefn* fieldDefn = oField->GetFieldDefn(); + ossimDDFSubfieldDefn* nfile = fieldDefn->FindSubfieldDefn("NOZ"); + rawFieldData = oField->GetSubfieldData(nfile); + ossimString num_img_files = nfile->ExtractStringData(rawFieldData, + bytesOfData, + &nBytesConsumed); + + // Number of ZDR images + ossim_uint32 num_ifiles = (ossim_uint32)ossimString::toInt(num_img_files); + + // Skip overview record. + oRecord = oModule.ReadRecord(); + + // Validate this is the correct record and it is an ADRG image. + ossimString img_file = ""; + ossimString img_base = theImageFile.fileNoExtension(); + img_base.downcase(); + + // Find the correct geometry record corresponding to the image file. + ossim_uint32 count = 0; + while(count < num_ifiles) + { + oField = oRecord->FindField("001"); + bytesOfData = oField->GetDataSize(); + nBytesConsumed = 0; + + fieldDefn = oField->GetFieldDefn(); + ossimDDFSubfieldDefn* rty = fieldDefn->FindSubfieldDefn("RTY"); + rawFieldData = oField->GetSubfieldData(rty); + ossimString rtype = rty->ExtractStringData(rawFieldData, + bytesOfData, + &nBytesConsumed); + + // Found general information record + if(rtype == "GIN") + { + // Validate that this is an ADRG header file. + oField = oRecord->FindField("DSI"); + bytesOfData = oField->GetDataSize(); + nBytesConsumed = 0; + + fieldDefn = oField->GetFieldDefn(); + ossimDDFSubfieldDefn* ptype = fieldDefn->FindSubfieldDefn("PRT"); + rawFieldData = oField->GetSubfieldData(ptype); + ossimString product_type = ptype->ExtractStringData(rawFieldData, + bytesOfData, + &nBytesConsumed); + + if(!(strncmp(product_type.c_str(), "ADRG", 4) == 0)) + { + cout << "File does not appear to be an ADRG header file: " + << theHeaderFile.chars() << endl; + + theErrorStatus = OSSIM_ERROR; + return; + } + + fieldDefn = oField->GetFieldDefn(); + ossimDDFSubfieldDefn* ifile = fieldDefn->FindSubfieldDefn("NAM"); + rawFieldData = oField->GetSubfieldData(ifile); + img_file = ifile->ExtractStringData(rawFieldData, bytesOfData, + &nBytesConsumed); + img_file.downcase(); + + count++; + + if(img_base == img_file) + break; + else + oRecord = oModule.ReadRecord(); + } + else + oRecord = oModule.ReadRecord(); + } + + // Find Distribution Rectangle name. + oField = oRecord->FindField("GEN"); + bytesOfData = oField->GetDataSize(); + nBytesConsumed = 0; + + fieldDefn = oField->GetFieldDefn(); + + // Find Subfield names. + ossimDDFSubfieldDefn* min_lon = fieldDefn->FindSubfieldDefn("SWO"); + ossimDDFSubfieldDefn* min_lat = fieldDefn->FindSubfieldDefn("SWA"); + ossimDDFSubfieldDefn* max_lon = fieldDefn->FindSubfieldDefn("NEO"); + ossimDDFSubfieldDefn* max_lat = fieldDefn->FindSubfieldDefn("NEA"); + + // Extract the min/max lon/lat coordinates. + rawFieldData = oField->GetSubfieldData(min_lon); + theMinLon = min_lon->ExtractStringData(rawFieldData, + bytesOfData, + &nBytesConsumed); + rawFieldData = oField->GetSubfieldData(min_lat); + theMinLat = min_lat->ExtractStringData(rawFieldData, + bytesOfData, + &nBytesConsumed); + rawFieldData = oField->GetSubfieldData(max_lon); + theMaxLon = max_lon->ExtractStringData(rawFieldData, + bytesOfData, + &nBytesConsumed); + rawFieldData = oField->GetSubfieldData(max_lat); + theMaxLat = max_lat->ExtractStringData(rawFieldData, + bytesOfData, + &nBytesConsumed); + + // Find the DATA_SET_PARAMETERS_FIELD + oField = oRecord->FindField("SPR"); + bytesOfData = oField->GetDataSize(); + nBytesConsumed = 0; + + fieldDefn = oField->GetFieldDefn(); + + // Find subfields. + ossimDDFSubfieldDefn* start_row = fieldDefn->FindSubfieldDefn("NUL"); + ossimDDFSubfieldDefn* stop_col = fieldDefn->FindSubfieldDefn("NUS"); + ossimDDFSubfieldDefn* stop_row = fieldDefn->FindSubfieldDefn("NLL"); + ossimDDFSubfieldDefn* start_col = fieldDefn->FindSubfieldDefn("NLS"); + ossimDDFSubfieldDefn* lines = fieldDefn->FindSubfieldDefn("NFL"); + ossimDDFSubfieldDefn* samples = fieldDefn->FindSubfieldDefn("NFC"); + ossimDDFSubfieldDefn* tif = fieldDefn->FindSubfieldDefn("TIF"); + + // Extract the number of lines & samples per tile. + rawFieldData = oField->GetSubfieldData(start_row); + theStartRow = atoi(start_row->ExtractStringData(rawFieldData, + bytesOfData, + &nBytesConsumed)); + rawFieldData = oField->GetSubfieldData(start_col); + theStartCol = atoi(start_col->ExtractStringData(rawFieldData, + bytesOfData, + &nBytesConsumed)); + rawFieldData = oField->GetSubfieldData(stop_row); + theStopRow = atoi(stop_row->ExtractStringData(rawFieldData, + bytesOfData, + &nBytesConsumed)); + rawFieldData = oField->GetSubfieldData(stop_col); + theStopCol = atoi(stop_col->ExtractStringData(rawFieldData, + bytesOfData, + &nBytesConsumed)); + rawFieldData = oField->GetSubfieldData(lines); + theLinesInTiles = atoi(lines->ExtractStringData(rawFieldData, + bytesOfData, + &nBytesConsumed)); + rawFieldData = oField->GetSubfieldData(samples); + theSamplesInTiles = atoi(samples->ExtractStringData(rawFieldData, + bytesOfData, + &nBytesConsumed)); + rawFieldData = oField->GetSubfieldData(tif); + theTif = tif->ExtractStringData(rawFieldData, bytesOfData, + &nBytesConsumed); + + theLines = theLinesInTiles * ADRG_TILE_SIZE; + theSamples = theSamplesInTiles * ADRG_TILE_SIZE; + + theValidImageRect = ossimIrect(0, 0, theSamples - 1, theLines - 1); + + // Initialize the TIM (tile index map). + theTim = new ossim_uint32[theLinesInTiles * theSamplesInTiles]; + + // Read in the tile index map (TIM) if it exists. + if(strncmp(theTif.c_str(), "Y", 1) == 0) + { + // Find the TILE_INDEX_MAP_FIELD + oField = oRecord->FindField("TIM"); + bytesOfData = oField->GetDataSize(); + fieldDefn = oField->GetFieldDefn(); + rawFieldData = oField->GetData(); + nBytesConsumed = 0; + + for(ossim_uint32 r = 0; r < theLinesInTiles * theSamplesInTiles; r++ ) + { + ossimDDFSubfieldDefn* tim = fieldDefn->FindSubfieldDefn("TSI"); + theTim[r] = atoi(tim->ExtractStringData(rawFieldData, bytesOfData, + &nBytesConsumed)); + bytesOfData -= nBytesConsumed; + rawFieldData += nBytesConsumed; + } + } + else + { + for(ossim_uint32 m = 0; m < (theLinesInTiles * theSamplesInTiles); m++) + theTim[m] = (m+1); + } + + // Close module used for reading encoded header file. + oModule.Close(); +} + +//********************************************************************* +// tim(int32 row, int32 col) +//********************************************************************* +ossim_uint32 ossimAdrgHeader::tim(ossim_uint32 row, ossim_uint32 col) const +{ + return ( theTim[(row * theSamplesInTiles) + col] ); +} + +//********************************************************************* +// operator << +//********************************************************************* +ostream& operator<<(ostream& os, const ossimAdrgHeader& adrg) +{ + os << "\nContents of ADRG Header file (.gen):" + << "\nImage File = " << adrg.theImageFile + << "\nHeader File = " << adrg.theHeaderFile + << "\nPixelType = " << adrg.thePixelType + << "\nInterleaveType = " << adrg.theInterleaveType + << "\nNumberOfBands = " << adrg.theNumberOfBands + << "\nLines = " << adrg.theLines + << "\nLines (tiles) = " << adrg.theLinesInTiles + << "\nSamples = " << adrg.theSamples + << "\nSamples (tiles) = " << adrg.theSamplesInTiles + << "\nHeaderSize = " << adrg.theHeaderSize + << "\nValidImageRect = " << adrg.theValidImageRect + << "\nTIF = " << adrg.theTif + << "\nMin Lon = " << adrg.theMinLon + << "\nMin Lat = " << adrg.theMinLat + << "\nMax Lon = " << adrg.theMaxLon + << "\nMax Lat = " << adrg.theMaxLat + << "\nStart Row = " << adrg.theStartRow + << "\nStart Col = " << adrg.theStartCol + << "\nStop Row = " << adrg.theStopRow + << "\nStop Col = " << adrg.theStopCol + << endl; + + for(ossim_uint32 m = 0; m < (adrg.theLinesInTiles * adrg.theSamplesInTiles); m++) + os << "\nTIM[" << m << "] = " << adrg.theTim[m]; + + os << endl; + + return(os); +} + +//********************************************************************* +// Public method: +//********************************************************************* +double ossimAdrgHeader::minLongitude() const +{ + return parseLongitudeString(theMinLon); +} + +//********************************************************************* +// Public method: +//********************************************************************* +double ossimAdrgHeader::minLatitude() const +{ + return parseLatitudeString(theMinLat); +} + +//********************************************************************* +// Public method: +//********************************************************************* +double ossimAdrgHeader::maxLongitude() const +{ + return parseLongitudeString(theMaxLon); +} + +//********************************************************************* +// Public method: +//********************************************************************* +double ossimAdrgHeader::maxLatitude() const +{ + return parseLatitudeString(theMaxLat); +} + +//********************************************************************* +// Private method: +//********************************************************************* +double ossimAdrgHeader::parseLongitudeString(const ossimString& lon) const +{ + static const char MODULE[] = "ossimAdrgHeader::parseLongitudeString"; + + // Format = +|-dddmmss.ss + + if (lon.size() != 11) + { + cerr << MODULE << " Longitude string error!" + << "Bad longitude string: " << lon.c_str() << endl; + } + + const char* cstr = lon.c_str(); + + double degrees = 0.0; + double sign = 1.0; + char tmp_str[6]; + + // Get the sign. + if (cstr[0] == '-') sign = -1.0; + + // Get the degrees. + tmp_str[3] = '\0'; + cstr++; // Increment past the sign. + strncpy(tmp_str, cstr, 3); + + if (tmp_str) + { + degrees = atof(tmp_str); + } + + // Get the minutes. + tmp_str[2] = '\0'; + cstr += 3; // Increment to the minutes. + strncpy(tmp_str, cstr, 2); + + if (tmp_str) + { + degrees += atof(tmp_str) / 60.0; + } + + // Get the seconds. + tmp_str[5] = '\0'; + cstr += 2; // Increment to seconds. + strncpy(tmp_str, cstr, 5); + + if (tmp_str) + { + degrees += atof(tmp_str) / 3600.0; + } + + // Set the sign. + degrees *= sign; + + return degrees; +} + +//********************************************************************* +// Private method: +//********************************************************************* +double ossimAdrgHeader::parseLatitudeString(const ossimString& lat) const +{ + static const char MODULE[] = "ossimAdrgHeader::parseLatitudeString"; + + // Format = +|-ddmmss.ss + + if (lat.size() != 10) + { + cerr << MODULE << " Latitude string error!" + << "Bad latitude string: " << lat.c_str() << endl; + } + + const char* cstr = lat.c_str(); + + double degrees = 0.0; + double sign = 1.0; + char tmp_str[6]; + + // Get the sign. + if (cstr[0] == '-') sign = -1.0; + + // Get the degrees. + tmp_str[2] = '\0'; + cstr++; // Increment past the sign. + strncpy(tmp_str, cstr, 2); + + if (tmp_str) + { + degrees = atof(tmp_str); + } + + // Get the minutes. + tmp_str[2] = '\0'; + cstr += 2; // Increment to the minutes. + strncpy(tmp_str, cstr, 2); + + if (tmp_str) + { + degrees += atof(tmp_str) / 60.0; + } + + // Get the seconds. + tmp_str[5] = '\0'; + cstr += 2; // Increment to seconds. + strncpy(tmp_str, cstr, 5); + + if (tmp_str) + { + degrees += atof(tmp_str) / 3600.0; + } + + // Set the sign. + degrees *= sign; + + return degrees; +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimAdrgHeader.h b/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimAdrgHeader.h new file mode 100644 index 0000000000..e8a824b6e5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimAdrgHeader.h @@ -0,0 +1,130 @@ +//******************************************************************* +// Copyright (C) 2002 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Ken Melero (kmelero@imagelinks.com) +// Description: This class encapsulates the image parameters and +// support data for a ADRG image file(s). +// +//******************************************************************** +// $Id: ossimAdrgHeader.h,v 1.3 2004/06/23 20:10:55 dburken Exp $ + +#ifndef ossimAdrgHeader_H +#define ossimAdrgHeader_H + +#include "base/common/ossimConstants.h" +#include "base/data_types/ossimFilename.h" +#include "base/data_types/ossimIrect.h" + +class OSSIMDLLEXPORT ossimAdrgHeader +{ +public: + // Instantiated with the image file (.img) + ossimAdrgHeader(const ossimFilename& img_file); + ~ossimAdrgHeader(); + + enum ErrorStatus + { + OSSIM_OK = 0, + OSSIM_ERROR = 1 + }; + + enum + { + ADRG_TILE_SIZE = 128 + }; + + int errorStatus() const { return theErrorStatus; } + + ossimFilename file() + const { return theHeaderFile; } + ossimFilename imageFile() + const { return theImageFile; } + ossimIrect validImageRect() + const { return theValidImageRect; } + + ossim_uint32 pixelType() const { return thePixelType; } + ossim_uint32 interleaveType() const { return theInterleaveType; } + ossim_uint32 numberOfBands() const { return theNumberOfBands; } + ossim_uint32 lines() const { return theLines; } + ossim_uint32 tlines() const { return theLinesInTiles; } + ossim_uint32 samples() const { return theSamples; } + ossim_uint32 tsamples() const { return theSamplesInTiles; } + ossim_uint32 headerSize() const { return theHeaderSize; } + ossim_uint32 startRow() const { return theStartRow; } + ossim_uint32 startCol() const { return theStartCol; } + ossim_uint32 stopRow() const { return theStopRow; } + ossim_uint32 stopCol() const { return theStopCol; } + + ossim_uint32 tim(ossim_uint32 row, ossim_uint32 col) const; + + ossimString minLon() const { return theMinLon; } + ossimString minLat() const { return theMinLat; } + ossimString maxLon() const { return theMaxLon; } + ossimString maxLat() const { return theMaxLat; } + + double minLongitude() const; + double minLatitude() const; + double maxLongitude() const; + double maxLatitude() const; + + friend ostream& operator<<(ostream& os, const ossimAdrgHeader& adrg); + +private: + + // Returns the longitude in decimal degrees given the formatted string. + double parseLongitudeString(const ossimString& lon) const; + + // Returns the latitude in decimal degrees given the formatted string. + double parseLatitudeString(const ossimString& lat) const; + + // prevent use. + ossimAdrgHeader(); + ossimAdrgHeader(const ossimAdrgHeader& source); + + ErrorStatus theErrorStatus; + + ossimFilename theHeaderFile; + ossimFilename theImageFile; + ossimIrect theValidImageRect; + + ossim_uint32 thePixelType; + ossim_uint32 theInterleaveType; + ossim_uint32 theNumberOfBands; + ossim_uint32 theLines; + ossim_uint32 theLinesInTiles; + ossim_uint32 theSamples; + ossim_uint32 theSamplesInTiles; + ossim_uint32 theHeaderSize; + ossim_uint32 theStartRow; + ossim_uint32 theStartCol; + ossim_uint32 theStopRow; + ossim_uint32 theStopCol; + ossim_uint32* theTim; // Tile index map value -- only valid if TIF is 'Y'. + + ossimString theMinLon; + ossimString theMinLat; + ossimString theMaxLon; + ossimString theMaxLat; + ossimString theTif; // Tile index map flag -- Y indicates there are tiles + // with no data; N indicates that all tiles contain + // RGB graphic data. + + void parse(); +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimAdrgTileSource.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimAdrgTileSource.cpp new file mode 100644 index 0000000000..250ece1f42 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimAdrgTileSource.cpp @@ -0,0 +1,782 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Ken Melero +// +// Author: Ken Melero +// +// Description: This class give the capability to access tiles from an +// ADRG file. +// +//******************************************************************** +// $Id: ossimAdrgTileSource.cpp,v 1.50 2005/02/11 15:07:30 dburken Exp $ + +#include <iostream> +using namespace std; + +#include <imaging/formats/adrg/ossimAdrgTileSource.h> +#include <base/common/ossimConstants.h> +#include <base/common/ossimCommon.h> +#include <base/common/ossimKeywordNames.h> +#include <base/common/ossimTrace.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ellipse/ossimEllipsoid.h> +#include <base/data_types/datum/ossimDatum.h> +#include <projections/map_projections/ossimMapProjection.h> +#include <projections/map_projections/ossimEquDistCylProjection.h> +#include <imaging/formats/tiff/ossimTiffTileSource.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <imaging/ossimU8ImageData.h> + +RTTI_DEF1(ossimAdrgTileSource, "ossimAdrgTileSource", ossimImageHandler) + +//*** +// Static trace for debugging +//*** +static ossimTrace traceDebug("ossimAdrgTileSource:debug"); + +//*** +// NOTE: Currently this tilesource is hard-coded to access tiles +// from the ZDR image file. This will change as I wrote support +// data classes for all the ADRG image files: ZDR, overview, +// and legend support data. Next step in development will +// be to put in flags to access overview and legend image files. +//*** + +//******************************************************************* +// Public Constructor: +//******************************************************************* +ossimAdrgTileSource::ossimAdrgTileSource() + : + ossimImageHandler(), + theTile(NULL), + theTileBuffer(NULL), + theFileStr(), + theAdrgHeader(NULL) +{ + // Construction not complete. Users should call "open" method. +} + +ossimAdrgTileSource::~ossimAdrgTileSource() +{ + if(theAdrgHeader) + { + delete theAdrgHeader; + theAdrgHeader = NULL; + } + if (theTileBuffer) + { + delete [] theTileBuffer; + theTileBuffer = NULL; + } + + close(); +} + +ossimRefPtr<ossimImageData> ossimAdrgTileSource::getTile( + const ossimIrect& rect, + ossim_uint32 resLevel) +{ + long w = rect.width(); + long h = rect.height(); + + // This tile source bypassed, or invalid res level, return a blank tile. + if (!isSourceEnabled() || !isValidRLevel(resLevel)) + { + return ossimRefPtr<ossimImageData>(); + } + + if (theOverview) + { + if (theOverview->hasR0() || resLevel) + { + return theOverview->getTile(rect, resLevel); + } + } + + long tileW = theTile->getWidth(); + long tileH = theTile->getHeight(); + if((w != tileW)|| + (h != tileH)) + { + theTile->setWidth(w); + theTile->setHeight(h); + if((w*h)!=(tileW*tileH)) + { + theTile->initialize(); + } + } + theTile->setOrigin(rect.ul()); + ossimIrect image_rect = getImageRectangle(resLevel); + + //*** + // See if any point of the requested tile is in the image. + //*** + if ( rect.intersects(image_rect) ) + { + ossimIrect clip_rect = rect.clipToRect(image_rect); + + if ( !rect.completely_within(clip_rect) ) + { + // Start with a blank tile. + theTile->makeBlank(); + } + + // Load the tile buffer with data from the adrg. + if (fillBuffer(rect, clip_rect)) + { +// theTile->setOrigin(rect.ul()); // Capture the origin... + theTile->validate(); + return theTile; + } + else + { + return ossimRefPtr<ossimImageData>(); + } + + } // End of if ( tile_rect.intersects(image_rect) ) + + // No part of requested tile within the image rectangle. + return ossimRefPtr<ossimImageData>(); +} + +//******************************************************************* +// Private Method: +//******************************************************************* +bool ossimAdrgTileSource::fillBuffer(const ossimIrect& tile_rect, + const ossimIrect& clip_rect) +{ + const ossim_uint8 NULL_PIXEL = (ossim_uint8)theTile->getNullPix(0); + const ossim_int32 TILE_SIZE_PER_BAND = theTile->getSizePerBand(); + + //*** + // Shift the upper left corner of the "clip_rect" to the an even chunk + // boundry. + //*** + ossimIpt tileOrigin = clip_rect.ul(); + adjustToStartOfTile(tileOrigin); + + //*** + // Calculate the number of tiles needed in the line/sample directions. + //*** + ossim_int32 size_in_x = clip_rect.lr().x - tileOrigin.x + 1; + ossim_int32 size_in_y = clip_rect.lr().y - tileOrigin.y + 1; + + ossim_int32 tiles_in_x_dir = size_in_x / ADRG_TILE_WIDTH + (size_in_x % ADRG_TILE_WIDTH ? 1 : 0); + ossim_int32 tiles_in_y_dir = size_in_y / ADRG_TILE_HEIGHT + (size_in_y % ADRG_TILE_HEIGHT ? 1 : 0); + + + ossimIpt ulTilePt = tileOrigin; + + // Chunk loop in line direction. + for (int32 y=0; y<tiles_in_y_dir; y++) + { + ulTilePt.x = tileOrigin.x; + + // Tile loop in sample direction. + for (int32 x=0; x<tiles_in_x_dir; x++) + { + ossimIrect adrg_tile_rect(ulTilePt.x, + ulTilePt.y, + ulTilePt.x + ADRG_TILE_SIZE - 1, + ulTilePt.y + ADRG_TILE_SIZE - 1); + + if (adrg_tile_rect.intersects(clip_rect)) + { + ossimIrect tile_clip_rect = clip_rect.clipToRect(adrg_tile_rect); + + //*** + // Some point in the chip intersect the tile so grab the + // data. + //*** + ossim_int32 row = (ossim_int32) ulTilePt.y / ADRG_TILE_HEIGHT; + ossim_int32 col = (ossim_int32) ulTilePt.x / ADRG_TILE_WIDTH; + ossim_int32 tileOffset = theAdrgHeader->tim(row, col); + + if(tileOffset != 0) + { + // Get the data. + int seek_position = (tileOffset - 1) * 49152 + 2048; + int band; + + for (band=0; band<3; band++) + { + // Seek to the chip + theFileStr.seekg(seek_position, ios::beg); + + //*** + // Read the chip from the ccf file into the chunk buffer. + // This will get all the bands. Bands are interleaved by + // chip. + //*** + if (!theFileStr.read((char*)theTileBuffer, + ADRG_TILE_SIZE)) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + return false; + } + + seek_position += BAND_OFFSET; + + //*** + // Get a pointer positioned at the first valid pixel in + // the adrg tile. + //*** + ossim_uint8* s + = theTileBuffer + + (tile_clip_rect.ul().y - adrg_tile_rect.ul().y) * + ADRG_TILE_WIDTH + tile_clip_rect.ul().x - + adrg_tile_rect.ul().x; + + //*** + // Get a pointer positioned at the first valid pixel in + // the tile. + //*** + ossim_uint8* d + = (ossim_uint8*)theTile->getBuf() + + band * TILE_SIZE_PER_BAND + + (tile_clip_rect.ul().y - tile_rect.ul().y) * + theTile->getWidth() + tile_clip_rect.ul().x - + tile_rect.ul().x; + + // Line loop through valid portion of the adrg tile. + for (ossim_int32 line = tile_clip_rect.ul().y; + line <= tile_clip_rect.lr().y; + line++) + { + // Sample loop through the adrg tile. + int i=0; + for (ossim_int32 sample = tile_clip_rect.ul().x; + sample <= tile_clip_rect.lr().x; + sample++) + { + d[i] = s[i]; + i++; + } + + // Increment the pointers by one line. + s += ADRG_TILE_WIDTH; + d += theTile->getWidth(); + } + + } // End of band loop. + + } // End of if (tileOffset != 0) + else + { + // The adrg tile is null. + + for (int band=0; band<3; band++) + { + //*** + // Get a pointer positioned at the first valid pixel in + // the tile. + //*** + ossim_uint8* d + = (ossim_uint8*)theTile->getBuf() + + band * TILE_SIZE_PER_BAND + + (tile_clip_rect.ul().y - tile_rect.ul().y) * + theTile->getWidth() + tile_clip_rect.ul().x - + tile_rect.ul().x; + + // Line loop through valid portion of the adrg tile. + for (ossim_int32 line = tile_clip_rect.ul().y; + line <= tile_clip_rect.lr().y; + line++) + { + // Sample loop through a chip. + int i=0; + for (ossim_int32 sample = tile_clip_rect.ul().x; + sample <= tile_clip_rect.lr().x; + sample++) + { + d[i] = NULL_PIXEL; + i++; + } + + // Increment the pointers by one line. + d += theTile->getWidth(); + } + + } // End of band loop. + + } // End of else. + + } // End of if (adrg_tile_rect.intersects(clip_rect)) + + ulTilePt.x += ADRG_TILE_WIDTH; + + } // End of tile loop in the sample direction. + + ulTilePt.y += ADRG_TILE_HEIGHT; + + } // End of tile loop in the line direction. + + return true; +} + +ossim_uint32 ossimAdrgTileSource::getNumberOfOutputBands()const +{ + return getNumberOfInputBands(); +} + +//******************************************************************* +// Public Method: +//******************************************************************* +ossimIrect +ossimAdrgTileSource::getImageRectangle(ossim_uint32 reduced_res_level) const +{ + return ossimIrect(0, // upper left x + 0, // upper left y + getNumberOfSamples(reduced_res_level) - 1, // lower right x + getNumberOfLines(reduced_res_level) - 1); // lower right y +} + +void ossimAdrgTileSource::close() +{ + if(theAdrgHeader) + { + delete theAdrgHeader; + theAdrgHeader = NULL; + } + if(theFileStr.is_open()) + { + theFileStr.close(); + } + theTile = NULL; +} + +//******************************************************************* +// Public method: +//******************************************************************* +bool ossimAdrgTileSource::open() +{ + static const char MODULE[] = "ossimAdrgTileSource::open"; + + if(traceDebug()) + { + CLOG << "Entered..."<<endl; + } + if(isOpen()) + { + close(); + } + if(theAdrgHeader) + { + delete theAdrgHeader; + theAdrgHeader = NULL; + } + // Instantiate support data class to parse header file. + theAdrgHeader = new ossimAdrgHeader(theImageFile); + + // Check for errors. + if (theAdrgHeader->errorStatus() == ossimErrorCodes::OSSIM_ERROR) + { + if (traceDebug()) + { + cerr << MODULE << " Error in ossimAdrg header detected." << endl; + } + + close(); + return false; + } + + theFileStr.open(theAdrgHeader->imageFile().c_str(), + ios::in | ios::binary); + + // Check the file pointer. + if(!theFileStr) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + if (traceDebug()) + { + cerr << MODULE << "\nCannot open: " + << theAdrgHeader->imageFile().c_str() << endl; + } + close(); + + return false; + } + + if(traceDebug()) + { + CLOG << "File is opened -> "<< theAdrgHeader->imageFile()<<endl; + } + + // allow the base handler to check for other overrides + completeOpen(); + // Allocate memory. + theTile = ossimImageDataFactory::instance()->create(this, this); + theTile->initialize(); + theTileBuffer = new ossim_uint8[ADRG_TILE_SIZE]; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "\nminLon: " << theAdrgHeader->minLon() + << "\nminLond: " << theAdrgHeader->minLongitude() + << "\nminLat: " << theAdrgHeader->minLat() + << "\nminLatd: " << theAdrgHeader->minLatitude() + << "\nmaxLon: " << theAdrgHeader->maxLon() + << "\nmaxLond: " << theAdrgHeader->maxLongitude() + << "\nmaxLat: " << theAdrgHeader->maxLat() + << "\nmaxLatd: " << theAdrgHeader->maxLatitude() + << endl; + } + + return true; +} + +//******************************************************************* +// Public method: +//******************************************************************* +bool ossimAdrgTileSource::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + // Currently nothing to do here. + return ossimImageHandler::saveState(kwl, prefix); +} + +//******************************************************************* +// Public method: +//******************************************************************* +bool ossimAdrgTileSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + if (ossimImageHandler::loadState(kwl, prefix)) + { + if (open()) + { + return true; + } + } + + return false; +} + +//******************************************************************* +// Public method: +//******************************************************************* +bool ossimAdrgTileSource::getImageGeometry(ossimKeywordlist& kwl, + const char* prefix) +{ + + if(ossimImageSource::getImageGeometry(kwl, prefix)) + { + return true; + } + + //*** + // NOTE: + // All these keywords are going to change. Hard coded right now for test. + //*** + + // model type. This will be going away soon and will + // be replaced with projection.type bellow. + kwl.add(prefix, + ossimKeywordNames::TYPE_KW, + "ossimEquDistCylProjection", + true); + + ossimString projPref = prefix?prefix:""; + + // origin of latitude + double lat = (theAdrgHeader->maxLatitude() + + theAdrgHeader->minLatitude()) / 2.0; + + // central meridian. + double lon = (theAdrgHeader->maxLongitude() + + theAdrgHeader->minLongitude()) / 2.0; + + //*** + // Make a projection to get the easting / northing of the tie point and + // the scale in meters. + //*** + const ossimDatum* datum = ossimDatumFactory::instance()->wgs84(); + + ossimProjection* proj + = new ossimEquDistCylProjection(*(datum->ellipsoid()), + ossimGpt(lat, lon), + 0.0, // false easting + 0.0); // false northing + proj->saveState(kwl, projPref); + + // Get the scale in meters. + ossimGpt ul_gpt(theAdrgHeader->maxLatitude(), + theAdrgHeader->minLongitude(), + OSSIM_DBL_NAN); + + // ossimDpt ul_dpt = proj->forward(ul_gpt); + + ossimGpt ur_gpt(theAdrgHeader->maxLatitude(), + theAdrgHeader->maxLongitude(), + 0.0); + + // ossimDpt ur_dpt = proj->forward(ur_gpt); + + ossimGpt ll_gpt(theAdrgHeader->minLatitude(), + theAdrgHeader->minLongitude(), + 0.0); + + // ossimDpt ll_dpt = proj->forward(ll_gpt); + + ossimGpt lr_gpt(theAdrgHeader->minLatitude(), + theAdrgHeader->maxLongitude(), + 0.0); + + // ossimDpt lr_dpt = proj->forward(lr_gpt); + + double samples = theAdrgHeader->stopCol() - theAdrgHeader->startCol() + 1; + double lines = theAdrgHeader->stopRow() - theAdrgHeader->startRow() + 1; + +// double meters_per_pix_x = (ur_dpt.x - ul_dpt.x) / samples; +// double meters_per_pix_y = (ur_dpt.y - lr_dpt.y) / lines; + + // will remove these two and replace with the next two + // we will for now just duplicate with different prefix. +// kwl.add(prefix, +// ossimKeywordNames::METERS_PER_PIXEL_X_KW, +// meters_per_pix_x, +// true); + +// kwl.add(prefix, +// ossimKeywordNames::METERS_PER_PIXEL_Y_KW, +// meters_per_pix_y, +// true); + + + //*** + // To get the tie point the padding must be accounted for... + // The min / max lat / lon is relative to the unpadded image. + //*** + double degrees_in_lat_dir = theAdrgHeader->maxLatitude() - + theAdrgHeader->minLatitude(); + double degrees_in_lon_dir = theAdrgHeader->maxLongitude() - + theAdrgHeader->minLongitude(); + + double degPerPixelY = degrees_in_lat_dir / lines; + double degPerPixelX = degrees_in_lon_dir / samples; + +// double ul_lat = theAdrgHeader->maxLatitude() + +// (theAdrgHeader->startRow() - 1.0) * degPerPixelY; +// double ul_lon = theAdrgHeader->minLongitude() - +// (theAdrgHeader->startCol() - 1.0) * degPerPixelX; + double ul_lat = (theAdrgHeader->maxLatitude() + + theAdrgHeader->startRow()*degPerPixelY) - (degPerPixelY*.5); + double ul_lon = (theAdrgHeader->minLongitude() - + theAdrgHeader->startCol()*degPerPixelX) + (degPerPixelX*.5); + +// ossimGpt ul_adjusted_gpt(ul_lat, +// ul_lon, +// 0.0); + +// ossimDpt ul_adjusted_dpt = proj->forward(ul_adjusted_gpt); + + kwl.add(prefix, + ossimKeywordNames::TIE_POINT_LAT_KW, + ul_lat, + true); + + kwl.add(prefix, + ossimKeywordNames::TIE_POINT_LON_KW, + ul_lon, + true); + + kwl.add(prefix, + ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LAT, + degPerPixelY, + true); + + kwl.add(prefix, + ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LON, + degPerPixelX, + true); + + + // will remove the first two here and replace + // with the second 2 +// kwl.add(prefix, +// ossimKeywordNames::TIE_POINT_EASTING_KW, +// ul_adjusted_dpt.x, +// true); + +// kwl.add(prefix, +// ossimKeywordNames::TIE_POINT_NORTHING_KW, +// ul_adjusted_dpt.y, +// true); + +// kwl.add(projPref, +// ossimKeywordNames::TIE_POINT_EASTING_KW, +// ul_adjusted_dpt.x, +// true); + +// kwl.add(projPref, +// ossimKeywordNames::TIE_POINT_NORTHING_KW, +// ul_adjusted_dpt.y, +// true); + + // now add the general image geometry to the + // list. + kwl.add(prefix, + ossimKeywordNames::NUMBER_LINES_KW, + getNumberOfLines()); + + kwl.add(prefix, + ossimKeywordNames::NUMBER_SAMPLES_KW, + getNumberOfSamples()); + + kwl.add(prefix, + ossimKeywordNames::NUMBER_REDUCED_RES_SETS_KW, + getNumberOfDecimationLevels()); + + kwl.add(prefix, + ossimKeywordNames::NUMBER_INPUT_BANDS_KW, + getNumberOfInputBands()); + + kwl.add(prefix, + ossimKeywordNames::NUMBER_OUTPUT_BANDS_KW, + getNumberOfOutputBands()); + + kwl.add(prefix, + ossimKeywordNames::DATUM_KW, + "WGE", + true); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "\nminLon: " << theAdrgHeader->minLon() + << "\nminLond: " << theAdrgHeader->minLongitude() + << "\nminLat: " << theAdrgHeader->minLat() + << "\nminLatd: " << theAdrgHeader->minLatitude() + << "\nmaxLon: " << theAdrgHeader->maxLon() + << "\nmaxLond: " << theAdrgHeader->maxLongitude() + << "\nmaxLat: " << theAdrgHeader->maxLat() + << "\nmaxLatd: " << theAdrgHeader->maxLatitude() + << "\nstartRow: " << theAdrgHeader->startRow() + << "\nstartCol: " << theAdrgHeader->startCol() + << "\nstopRow: " << theAdrgHeader->stopRow() + << "\nstopCol: " << theAdrgHeader->stopCol() +// << "\nul_adjusted_gpt: " << ul_adjusted_gpt + << "\nul_gpt: " << ul_gpt + << "\nur_gpt: " << ur_gpt + << "\nlr_gpt: " << lr_gpt + << "\nll_gpt: " << ll_gpt +// << "\nul_adjusted_dpt: " << ul_adjusted_dpt +// << "\nul_dpt: " << ul_dpt +// << "\nur_dpt: " << ur_dpt +// << "\nlr_dpt: " << lr_dpt +// << "\nll_dpt: " << ll_dpt +// << "\nmeters_per_pix_x: " << meters_per_pix_x +// << "\nmeters_per_pix_y: " << meters_per_pix_y + << "kwl:\n" << kwl + << endl; + } + + setImageGeometry(kwl); + + return true; +} + +//******************************************************************* +// Public method: +//******************************************************************* +ossimScalarType ossimAdrgTileSource::getOutputScalarType() const +{ + return OSSIM_UCHAR; +} + +//******************************************************************* +// Public method: +//******************************************************************* +ossim_uint32 ossimAdrgTileSource::getTileWidth() const +{ + return ( theTile.valid() ? theTile->getWidth() : 0 ); +} + +//******************************************************************* +// Public method: +//******************************************************************* +ossim_uint32 ossimAdrgTileSource::getTileHeight() const +{ + return ( theTile.valid() ? theTile->getHeight() : 0 ); +} + +//******************************************************************* +// Public method: +//******************************************************************* +ossim_uint32 ossimAdrgTileSource::getNumberOfLines(ossim_uint32 reduced_res_level) const +{ + if (reduced_res_level == 0) + { + return theAdrgHeader->lines(); + } + else if (theOverview) + { + return theOverview->getNumberOfLines(reduced_res_level); + } + + return 0; +} + +//******************************************************************* +// Public method: +//******************************************************************* +ossim_uint32 ossimAdrgTileSource::getNumberOfSamples(ossim_uint32 reduced_res_level) const +{ + if (reduced_res_level == 0) + { + return theAdrgHeader->samples(); + } + else if (theOverview) + { + return theOverview->getNumberOfSamples(reduced_res_level); + } + + return 0; +} + +ossim_uint32 ossimAdrgTileSource::getImageTileWidth() const +{ + return ADRG_TILE_WIDTH; +} + +ossim_uint32 ossimAdrgTileSource::getImageTileHeight() const +{ + return ADRG_TILE_HEIGHT; +} + +ossimString ossimAdrgTileSource::getShortName()const +{ + return ossimString("adrg"); +} + +ossimString ossimAdrgTileSource::getLongName()const +{ + return ossimString("adrg reader"); +} + +ossimString ossimAdrgTileSource::className()const +{ + return ossimString("ossimAdrgTileSource"); +} + +ossim_uint32 ossimAdrgTileSource::getNumberOfInputBands() const +{ + return theAdrgHeader->numberOfBands(); +} + +bool ossimAdrgTileSource::isOpen()const +{ + return (theAdrgHeader!=NULL); +} + +void ossimAdrgTileSource::adjustToStartOfTile(ossimIpt& pt) const +{ + pt.x &= 0xffffff80; + pt.y &= 0xffffff80; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimAdrgTileSource.h b/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimAdrgTileSource.h new file mode 100644 index 0000000000..30a9929f31 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimAdrgTileSource.h @@ -0,0 +1,175 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Ken Melero +// +// Description: This class give the capability to access tiles from an +// ADRG file. +// +//******************************************************************** +// $Id: ossimAdrgTileSource.h,v 1.21 2005/07/25 22:42:22 dburken Exp $ + +#ifndef ossimAdrgTileSource_HEADER +#define ossimAdrgTileSource_HEADER + +#include <fstream> +using namespace std; + +#include <imaging/formats/ossimImageHandler.h> +#include <imaging/formats/adrg/ossimAdrgHeader.h> + +class ossimImageData; + +class OSSIM_DLL ossimAdrgTileSource : public ossimImageHandler +{ +public: + + enum + { + ADRG_TILE_WIDTH = 128, + ADRG_TILE_HEIGHT = 128, + ADRG_TILE_SIZE = 16384, // 128 * 128, + BAND_OFFSET = 16384, // 8 * 2048, + NUMBER_OF_BANDS = 3 + }; + + enum ADRG_COLOR + { + RED_BAND = 0, // the ADRG rgb value + GREEN_BAND = 1, + BLUE_BAND = 2 + }; + + ossimAdrgTileSource(); + virtual ~ossimAdrgTileSource(); + + virtual ossimString getShortName()const; + virtual ossimString getLongName()const; + virtual ossimString className()const; + + /** + * @return Returns true on success, false on error. + * + * @note This method relies on the data member ossimImageData::theImageFile + * being set. Callers should do a "setFilename" prior to calling this + * method or use the ossimImageHandler::open that takes a file name and an + * entry index. + */ + virtual bool open(); + + /** + * Returns a pointer to a tile given an origin representing the upper + * left corner of the tile to grab from the image. + * Satisfies pure virtual requirement from TileSource class. + */ + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect, + ossim_uint32 resLevel=0); + + /** + * Returns the number of bands in the image. + * Satisfies pure virtual requirement from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfInputBands() const; + + virtual ossim_uint32 getNumberOfOutputBands()const; + + /** + * Returns the number of lines in the image. + * Satisfies pure virtual requirement from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfLines(ossim_uint32 reduced_res_level = 0) const; + + /** + * Returns the number of samples in the image. + * Satisfies pure virtual requirement from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfSamples(ossim_uint32 reduced_res_level = 0) const; + + /** + * Returns the zero based image rectangle for the reduced resolution data + * set (rrds) passed in. Note that rrds 0 is the highest resolution rrds. + */ + virtual ossimIrect getImageRectangle(ossim_uint32 reduced_res_level = 0) const; + + /** + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * Populates the keyword list with image geometry information. This + * method is used to relay projection/model information to users. + * Returns true if geometry info is present, false if not. + */ + virtual bool getImageGeometry(ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * Returns the output pixel type of the tile source. + */ + virtual ossimScalarType getOutputScalarType() const; + + /** + * Returns the width of the output tile. + */ + virtual ossim_uint32 getTileWidth() const; + + virtual void close(); + /** + * Returns the height of the output tile. + */ + virtual ossim_uint32 getTileHeight() const; + + virtual bool isOpen()const; + + /** + * Returns the tile width of the image or 0 if the image is not tiled. + * Note: this is not the same as the ossimImageSource::getTileWidth which + * returns the output tile width, which can be different than the + * internal image tile width on disk. + */ + virtual ossim_uint32 getImageTileWidth() const; + + /** + * Returns the tile width of the image or 0 if the image is not tiled. + * Note: this is not the same as the ossimImageSource::getTileHeight which + * returns the output tile width which can be different than the internal + * image tile width on disk. + */ + virtual ossim_uint32 getImageTileHeight() const; + +private: + + /** + * Adjust point to even 128 boundary. Assumes 0,0 origin. + */ + void adjustToStartOfTile(ossimIpt& pt) const; + + /** + * Returns true on success, false on error. + */ + bool fillBuffer(const ossimIrect& tile_rect, + const ossimIrect& clip_rect); + + ossimRefPtr<ossimImageData> theTile; + ossim_uint8* theTileBuffer; + ifstream theFileStr; + ossimAdrgHeader* theAdrgHeader; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimDdffield.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimDdffield.cpp new file mode 100644 index 0000000000..40056f56dd --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimDdffield.cpp @@ -0,0 +1,336 @@ +/****************************************************************************** + * Copied from "gdal" project. See licence below. + * + * Project: ISO 8211 Access + * Purpose: Implements the DDFField class. + * Author: Frank Warmerdam, warmerda@home.com + * + ****************************************************************************** + * Copyright (c) 1999, Frank Warmerdam + * + * 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 above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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. + ****************************************************************************** + * $Id: ossimDdffield.cpp,v 1.2 2005/02/13 16:08:04 dburken Exp $ + */ + +#include <imaging/formats/adrg/ossimIso8211.h> +#include <base/common/ossimCplUtil.h> +#include <base/common/ossimCommon.h> + +// #include "cpl_conv.h" + +// CPL_CVSID("$Id: ossimDdffield.cpp,v 1.2 2005/02/13 16:08:04 dburken Exp $"); + +// Note, we implement no constructor for this class to make instantiation +// cheaper. It is required that the Initialize() be called before anything +// else. + +/************************************************************************/ +/* Initialize() */ +/************************************************************************/ + +void ossimDDFField::Initialize( ossimDDFFieldDefn *poDefnIn, const char * pachDataIn, + int nDataSizeIn ) + +{ + pachData = pachDataIn; + nDataSize = nDataSizeIn; + poDefn = poDefnIn; +} + +/************************************************************************/ +/* Dump() */ +/************************************************************************/ + +/** + * Write out field contents to debugging file. + * + * A variety of information about this field, and all it's + * subfields is written to the given debugging file handle. Note that + * field definition information (ala DDFFieldDefn) isn't written. + * + * @param fp The standard io file handle to write to. ie. stderr + */ + +void ossimDDFField::Dump( FILE * fp ) + +{ + int nMaxRepeat = 8; + + if( getenv("DDF_MAXDUMP") != NULL ) + nMaxRepeat = atoi(getenv("DDF_MAXDUMP")); + + fprintf( fp, " DDFField:\n" ); + fprintf( fp, " Tag = `%s'\n", poDefn->GetName() ); + fprintf( fp, " DataSize = %d\n", nDataSize ); + + fprintf( fp, " Data = `" ); + for( int i = 0; i < MIN(nDataSize,40); i++ ) + { + if( pachData[i] < 32 || pachData[i] > 126 ) + fprintf( fp, "\\%02X", ((unsigned char *) pachData)[i] ); + else + fprintf( fp, "%c", pachData[i] ); + } + + if( nDataSize > 40 ) + fprintf( fp, "..." ); + fprintf( fp, "'\n" ); + +/* -------------------------------------------------------------------- */ +/* dump the data of the subfields. */ +/* -------------------------------------------------------------------- */ + int iOffset = 0, nLoopCount; + + for( nLoopCount = 0; nLoopCount < GetRepeatCount(); nLoopCount++ ) + { + if( nLoopCount > nMaxRepeat ) + { + fprintf( fp, " ...\n" ); + break; + } + + for( int i = 0; i < poDefn->GetSubfieldCount(); i++ ) + { + int nBytesConsumed; + + poDefn->GetSubfield(i)->DumpData( pachData + iOffset, + nDataSize - iOffset, fp ); + + poDefn->GetSubfield(i)->GetDataLength( pachData + iOffset, + nDataSize - iOffset, + &nBytesConsumed ); + + iOffset += nBytesConsumed; + } + } +} + +/************************************************************************/ +/* GetSubfieldData() */ +/************************************************************************/ + +/** + * Fetch raw data pointer for a particular subfield of this field. + * + * The passed DDFSubfieldDefn (poSFDefn) should be acquired from the + * DDFFieldDefn corresponding with this field. This is normally done + * once before reading any records. This method involves a series of + * calls to DDFSubfield::GetDataLength() in order to track through the + * DDFField data to that belonging to the requested subfield. This can + * be relatively expensive.<p> + * + * @param poSFDefn The definition of the subfield for which the raw + * data pointer is desired. + * @param pnMaxBytes The maximum number of bytes that can be accessed from + * the returned data pointer is placed in this int, unless it is NULL. + * @param iSubfieldIndex The instance of this subfield to fetch. Use zero + * (the default) for the first instance. + * + * @return A pointer into the DDFField's data that belongs to the subfield. + * This returned pointer is invalidated by the next record read + * (DDFRecord::ReadRecord()) and the returned pointer should not be freed + * by the application. + */ + +const char *ossimDDFField::GetSubfieldData( ossimDDFSubfieldDefn *poSFDefn, + int *pnMaxBytes, int iSubfieldIndex ) + +{ + int iOffset = 0; + + if( poSFDefn == NULL ) + return NULL; + + if( iSubfieldIndex > 0 && poDefn->GetFixedWidth() > 0 ) + { + iOffset = poDefn->GetFixedWidth() * iSubfieldIndex; + iSubfieldIndex = 0; + } + + while( iSubfieldIndex >= 0 ) + { + for( int iSF = 0; iSF < poDefn->GetSubfieldCount(); iSF++ ) + { + int nBytesConsumed; + ossimDDFSubfieldDefn * poThisSFDefn = poDefn->GetSubfield( iSF ); + + if( poThisSFDefn == poSFDefn && iSubfieldIndex == 0 ) + { + if( pnMaxBytes != NULL ) + *pnMaxBytes = nDataSize - iOffset; + + return pachData + iOffset; + } + + poThisSFDefn->GetDataLength( pachData+iOffset, nDataSize - iOffset, + &nBytesConsumed); + iOffset += nBytesConsumed; + } + + iSubfieldIndex--; + } + + // We didn't find our target subfield or instance! + return NULL; +} + +/************************************************************************/ +/* GetRepeatCount() */ +/************************************************************************/ + +/** + * How many times do the subfields of this record repeat? This + * will always be one for non-repeating fields. + * + * @return The number of times that the subfields of this record occur + * in this record. This will be one for non-repeating fields. + * + * @see <a href="example.html">8211view example program</a> + * for demonstation of handling repeated fields properly. + */ + +int ossimDDFField::GetRepeatCount() + +{ + if( !poDefn->IsRepeating() ) + return 1; + +/* -------------------------------------------------------------------- */ +/* The occurance count depends on how many copies of this */ +/* field's list of subfields can fit into the data space. */ +/* -------------------------------------------------------------------- */ + if( poDefn->GetFixedWidth() ) + { + return nDataSize / poDefn->GetFixedWidth(); + } + +/* -------------------------------------------------------------------- */ +/* Note that it may be legal to have repeating variable width */ +/* subfields, but I don't have any samples, so I ignore it for */ +/* now. */ +/* */ +/* The file data/cape_royal_AZ_DEM/1183XREF.DDF has a repeating */ +/* variable length field, but the count is one, so it isn't */ +/* much value for testing. */ +/* -------------------------------------------------------------------- */ + int iOffset = 0, iRepeatCount = 1; + + while( true ) + { + for( int iSF = 0; iSF < poDefn->GetSubfieldCount(); iSF++ ) + { + int nBytesConsumed; + ossimDDFSubfieldDefn * poThisSFDefn = poDefn->GetSubfield( iSF ); + + if( poThisSFDefn->GetWidth() > nDataSize - iOffset ) + nBytesConsumed = poThisSFDefn->GetWidth(); + else + poThisSFDefn->GetDataLength( pachData+iOffset, + nDataSize - iOffset, + &nBytesConsumed); + + iOffset += nBytesConsumed; + if( iOffset > nDataSize ) + return iRepeatCount - 1; + } + + if( iOffset > nDataSize - 2 ) + return iRepeatCount; + + iRepeatCount++; + } +} + +/************************************************************************/ +/* GetInstanceData() */ +/************************************************************************/ + +/** + * Get field instance data and size. + * + * The returned data pointer and size values are suitable for use with + * DDFRecord::SetFieldRaw(). + * + * @param nInstance a value from 0 to GetRepeatCount()-1. + * @param pnInstanceSize a location to put the size (in bytes) of the + * field instance data returned. This size will include the unit terminator + * (if any), but not the field terminator. This size pointer may be NULL + * if not needed. + * + * @return the data pointer, or NULL on error. + */ + +const char *ossimDDFField::GetInstanceData( int nInstance, + int *pnInstanceSize ) + +{ + int nRepeatCount = GetRepeatCount(); + const char *pachWrkData; + + if( nInstance < 0 || nInstance >= nRepeatCount ) + return NULL; + +/* -------------------------------------------------------------------- */ +/* Special case for fields without subfields (like "0001"). We */ +/* don't currently handle repeating simple fields. */ +/* -------------------------------------------------------------------- */ + if( poDefn->GetSubfieldCount() == 0 ) + { + pachWrkData = GetData(); + if( pnInstanceSize != 0 ) + *pnInstanceSize = GetDataSize(); + return pachWrkData; + } + +/* -------------------------------------------------------------------- */ +/* Get a pointer to the start of the existing data for this */ +/* iteration of the field. */ +/* -------------------------------------------------------------------- */ + int nBytesRemaining1, nBytesRemaining2; + ossimDDFSubfieldDefn *poFirstSubfield; + + poFirstSubfield = poDefn->GetSubfield(0); + + pachWrkData = GetSubfieldData(poFirstSubfield, &nBytesRemaining1, + nInstance); + +/* -------------------------------------------------------------------- */ +/* Figure out the size of the entire field instance, including */ +/* unit terminators, but not any trailing field terminator. */ +/* -------------------------------------------------------------------- */ + if( pnInstanceSize != NULL ) + { + ossimDDFSubfieldDefn *poLastSubfield; + int nLastSubfieldWidth; + const char *pachLastData; + + poLastSubfield = poDefn->GetSubfield(poDefn->GetSubfieldCount()-1); + + pachLastData = GetSubfieldData( poLastSubfield, &nBytesRemaining2, + nInstance ); + poLastSubfield->GetDataLength( pachLastData, nBytesRemaining2, + &nLastSubfieldWidth ); + + *pnInstanceSize = + nBytesRemaining1 - (nBytesRemaining2 - nLastSubfieldWidth); + } + + return pachWrkData; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimDdffielddefn.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimDdffielddefn.cpp new file mode 100644 index 0000000000..80ab350105 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimDdffielddefn.cpp @@ -0,0 +1,865 @@ +/****************************************************************************** + * Copied from "gdal" project. See licence below. + * + * Project: ISO 8211 Access + * Purpose: Implements the DDFFieldDefn class. + * Author: Frank Warmerdam, warmerdam@pobox.com + * + ****************************************************************************** + * Copyright (c) 1999, Frank Warmerdam + * + * 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 above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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. + ****************************************************************************** + * $Id: ossimDdffielddefn.cpp,v 1.5 2005/10/17 18:42:27 gpotts Exp $ + */ + +#include <imaging/formats/adrg/ossimIso8211.h> +#include <base/context/ossimNotifyContext.h> +#include <base/common/ossimCplUtil.h> +#include <base/common/ossimTrace.h> +#include <ctype.h> + +// Static trace for debugging +static ossimTrace traceDebug("ossimDDFFieldDefn:debug"); + + +/************************************************************************/ +/* DDFFieldDefn() */ +/************************************************************************/ + +ossimDDFFieldDefn::ossimDDFFieldDefn() + +{ + poModule = NULL; + pszTag = NULL; + _fieldName = NULL; + _arrayDescr = NULL; + _formatControls = NULL; + nSubfieldCount = 0; + papoSubfields = NULL; + bRepeatingSubfields = false; + nFixedWidth = 0; +} + +/************************************************************************/ +/* ~DDFFieldDefn() */ +/************************************************************************/ + +ossimDDFFieldDefn::~ossimDDFFieldDefn() + +{ + int i; + + free( pszTag ); + free( _fieldName ); + free( _arrayDescr ); + free( _formatControls ); + + for( i = 0; i < nSubfieldCount; i++ ) + delete papoSubfields[i]; + free( papoSubfields ); +} + +/************************************************************************/ +/* AddSubfield() */ +/************************************************************************/ + +void ossimDDFFieldDefn::AddSubfield( const char *pszName, + const char *pszFormat ) + +{ + ossimDDFSubfieldDefn *poSFDefn = new ossimDDFSubfieldDefn; + + poSFDefn->SetName( pszName ); + poSFDefn->SetFormat( pszFormat ); + AddSubfield( poSFDefn ); +} + +/************************************************************************/ +/* AddSubfield() */ +/************************************************************************/ + +void ossimDDFFieldDefn::AddSubfield( ossimDDFSubfieldDefn *poNewSFDefn, + int bDontAddToFormat ) + +{ + nSubfieldCount++; + papoSubfields = (ossimDDFSubfieldDefn ** ) + realloc( papoSubfields, sizeof(void*) * nSubfieldCount ); + papoSubfields[nSubfieldCount-1] = poNewSFDefn; + + if( bDontAddToFormat ) + return; + +/* -------------------------------------------------------------------- */ +/* Add this format to the format list. We don't bother */ +/* aggregating formats here. */ +/* -------------------------------------------------------------------- */ + if( _formatControls == NULL || strlen(_formatControls) == 0 ) + { + free( _formatControls ); + _formatControls = strdup( "()" ); + } + + int nOldLen = strlen(_formatControls); + + char *pszNewFormatControls = (char *) + malloc(nOldLen+3+strlen(poNewSFDefn->GetFormat())); + + strcpy( pszNewFormatControls, _formatControls ); + pszNewFormatControls[nOldLen-1] = '\0'; + if( pszNewFormatControls[nOldLen-2] != '(' ) + strcat( pszNewFormatControls, "," ); + + strcat( pszNewFormatControls, poNewSFDefn->GetFormat() ); + strcat( pszNewFormatControls, ")" ); + + free( _formatControls ); + _formatControls = pszNewFormatControls; + +/* -------------------------------------------------------------------- */ +/* Add the subfield name to the list. */ +/* -------------------------------------------------------------------- */ + if( _arrayDescr == NULL ) + _arrayDescr = strdup(""); + + _arrayDescr = (char *) + realloc(_arrayDescr, + strlen(_arrayDescr)+strlen(poNewSFDefn->GetName())+2); + if( strlen(_arrayDescr) > 0 ) + strcat( _arrayDescr, "!" ); + strcat( _arrayDescr, poNewSFDefn->GetName() ); +} + +/************************************************************************/ +/* Create() */ +/* */ +/* Initialize a new field defn from application input, instead */ +/* of from an existing file. */ +/************************************************************************/ + +int ossimDDFFieldDefn::Create( const char *pszTag, const char *pszFieldName, + const char *pszDescription, + DDF_data_struct_code eDataStructCode, + DDF_data_type_code eDataTypeCode, + const char *pszFormat ) + +{ + // assert( this->pszTag == NULL ); + poModule = NULL; + this->pszTag = strdup( pszTag ); + _fieldName = strdup( pszFieldName ); + _arrayDescr = strdup( pszDescription ); + _formatControls = strdup( "" ); + + _data_struct_code = eDataStructCode; + _data_type_code = eDataTypeCode; + + if( pszFormat != NULL ) + _formatControls = strdup( pszFormat ); + + if( pszDescription != NULL && *pszDescription == '*' ) + bRepeatingSubfields = true; + + return true; +} + +/************************************************************************/ +/* GenerateDDREntry() */ +/************************************************************************/ + +int ossimDDFFieldDefn::GenerateDDREntry( char **ppachData, + int *pnLength ) + +{ + *pnLength = 9 + strlen(_fieldName) + 1 + + strlen(_arrayDescr) + 1 + + strlen(_formatControls) + 1; + + if( strlen(_formatControls) == 0 ) + *pnLength -= 1; + + if( ppachData == NULL ) + return true; + + *ppachData = (char *) malloc( *pnLength+1 ); + + if( _data_struct_code == dsc_elementary ) + (*ppachData)[0] = '0'; + else if( _data_struct_code == dsc_vector ) + (*ppachData)[0] = '1'; + else if( _data_struct_code == dsc_array ) + (*ppachData)[0] = '2'; + else if( _data_struct_code == dsc_concatenated ) + (*ppachData)[0] = '3'; + + if( _data_type_code == dtc_char_string ) + (*ppachData)[1] = '0'; + else if( _data_type_code == dtc_implicit_point ) + (*ppachData)[1] = '1'; + else if( _data_type_code == dtc_explicit_point ) + (*ppachData)[1] = '2'; + else if( _data_type_code == dtc_explicit_point_scaled ) + (*ppachData)[1] = '3'; + else if( _data_type_code == dtc_char_bit_string ) + (*ppachData)[1] = '4'; + else if( _data_type_code == dtc_bit_string ) + (*ppachData)[1] = '5'; + else if( _data_type_code == dtc_mixed_data_type ) + (*ppachData)[1] = '6'; + + (*ppachData)[2] = '0'; + (*ppachData)[3] = '0'; + (*ppachData)[4] = ';'; + (*ppachData)[5] = '&'; + (*ppachData)[6] = ' '; + (*ppachData)[7] = ' '; + (*ppachData)[8] = ' '; + sprintf( *ppachData + 9, "%s%c%s", + _fieldName, OSSIM_DDF_UNIT_TERMINATOR, _arrayDescr ); + + if( strlen(_formatControls) > 0 ) + sprintf( *ppachData + strlen(*ppachData), "%c%s", + OSSIM_DDF_UNIT_TERMINATOR, _formatControls ); + sprintf( *ppachData + strlen(*ppachData), "%c", OSSIM_DDF_FIELD_TERMINATOR ); + + return true; +} + +/************************************************************************/ +/* Initialize() */ +/* */ +/* Initialize the field definition from the information in the */ +/* DDR record. This is called by DDFModule::Open(). */ +/************************************************************************/ + +int ossimDDFFieldDefn::Initialize( ossimDDFModule * poModuleIn, + const char * pszTagIn, + int nFieldEntrySize, + const char * pachFieldArea ) + +{ + int iFDOffset = poModuleIn->GetFieldControlLength(); + int nCharsConsumed; + + poModule = poModuleIn; + + pszTag = strdup( pszTagIn ); + +/* -------------------------------------------------------------------- */ +/* Set the data struct and type codes. */ +/* -------------------------------------------------------------------- */ + switch( pachFieldArea[0] ) + { + case '0': + _data_struct_code = dsc_elementary; + break; + + case '1': + _data_struct_code = dsc_vector; + break; + + case '2': + _data_struct_code = dsc_array; + break; + + case '3': + _data_struct_code = dsc_concatenated; + break; + + default: + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "Unrecognised data_struct_code value %c.\n" + << "Field %s initialization incorrect.\n" + << pachFieldArea[0] + << pszTag + << std::endl; + } + _data_struct_code = dsc_elementary; + } + + switch( pachFieldArea[1] ) + { + case '0': + _data_type_code = dtc_char_string; + break; + + case '1': + _data_type_code = dtc_implicit_point; + break; + + case '2': + _data_type_code = dtc_explicit_point; + break; + + case '3': + _data_type_code = dtc_explicit_point_scaled; + break; + + case '4': + _data_type_code = dtc_char_bit_string; + break; + + case '5': + _data_type_code = dtc_bit_string; + break; + + case '6': + _data_type_code = dtc_mixed_data_type; + break; + + default: + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "Unrecognised data_type_code value %c.\n" + << "Field %s initialization incorrect.\n" + << pachFieldArea[1] << pszTag << std::endl; + } + _data_type_code = dtc_char_string; + } + +/* -------------------------------------------------------------------- */ +/* Capture the field name, description (sub field names), and */ +/* format statements. */ +/* -------------------------------------------------------------------- */ + + _fieldName = + ossimDDFFetchVariable( pachFieldArea + iFDOffset, + nFieldEntrySize - iFDOffset, + OSSIM_DDF_UNIT_TERMINATOR, + OSSIM_DDF_FIELD_TERMINATOR, + &nCharsConsumed ); + iFDOffset += nCharsConsumed; + + _arrayDescr = + ossimDDFFetchVariable( pachFieldArea + iFDOffset, + nFieldEntrySize - iFDOffset, + OSSIM_DDF_UNIT_TERMINATOR, + OSSIM_DDF_FIELD_TERMINATOR, + &nCharsConsumed ); + iFDOffset += nCharsConsumed; + + _formatControls = + ossimDDFFetchVariable( pachFieldArea + iFDOffset, + nFieldEntrySize - iFDOffset, + OSSIM_DDF_UNIT_TERMINATOR, + OSSIM_DDF_FIELD_TERMINATOR, + &nCharsConsumed ); + +/* -------------------------------------------------------------------- */ +/* Parse the subfield info. */ +/* -------------------------------------------------------------------- */ + if( _data_struct_code != dsc_elementary ) + { + if( !BuildSubfields() ) + return false; + + if( !ApplyFormats() ) + return false; + } + + return true; +} + +/************************************************************************/ +/* Dump() */ +/************************************************************************/ + +/** + * Write out field definition info to debugging file. + * + * A variety of information about this field definition, and all it's + * subfields is written to the give debugging file handle. + * + * @param fp The standard io file handle to write to. ie. stderr + */ + +void ossimDDFFieldDefn::Dump( FILE * fp ) + +{ + const char *pszValue = ""; + + fprintf( fp, " DDFFieldDefn:\n" ); + fprintf( fp, " Tag = `%s'\n", pszTag ); + fprintf( fp, " _fieldName = `%s'\n", _fieldName ); + fprintf( fp, " _arrayDescr = `%s'\n", _arrayDescr ); + fprintf( fp, " _formatControls = `%s'\n", _formatControls ); + + switch( _data_struct_code ) + { + case dsc_elementary: + pszValue = "elementary"; + break; + + case dsc_vector: + pszValue = "vector"; + break; + + case dsc_array: + pszValue = "array"; + break; + + case dsc_concatenated: + pszValue = "concatenated"; + break; + + default: + // assert( false ); + pszValue = "(unknown)"; + } + + fprintf( fp, " _data_struct_code = %s\n", pszValue ); + + switch( _data_type_code ) + { + case dtc_char_string: + pszValue = "char_string"; + break; + + case dtc_implicit_point: + pszValue = "implicit_point"; + break; + + case dtc_explicit_point: + pszValue = "explicit_point"; + break; + + case dtc_explicit_point_scaled: + pszValue = "explicit_point_scaled"; + break; + + case dtc_char_bit_string: + pszValue = "char_bit_string"; + break; + + case dtc_bit_string: + pszValue = "bit_string"; + break; + + case dtc_mixed_data_type: + pszValue = "mixed_data_type"; + break; + + default: + // assert( false ); + pszValue = "(unknown)"; + break; + } + + fprintf( fp, " _data_type_code = %s\n", pszValue ); + + for( int i = 0; i < nSubfieldCount; i++ ) + papoSubfields[i]->Dump( fp ); +} + +/************************************************************************/ +/* BuildSubfields() */ +/* */ +/* Based on the _arrayDescr build a set of subfields. */ +/************************************************************************/ + +int ossimDDFFieldDefn::BuildSubfields() + +{ + char **papszSubfieldNames; + const char *pszSublist = _arrayDescr; + + if( pszSublist[0] == '*' ) + { + bRepeatingSubfields = true; + pszSublist++; + } + + papszSubfieldNames = ossimCSLTokenizeStringComplex( pszSublist, "!", + false, false ); + + int nSFCount = ossimCSLCount( papszSubfieldNames ); + for( int iSF = 0; iSF < nSFCount; iSF++ ) + { + ossimDDFSubfieldDefn *poSFDefn = new ossimDDFSubfieldDefn; + + poSFDefn->SetName( papszSubfieldNames[iSF] ); + AddSubfield( poSFDefn, true ); + } + + ossimCSLDestroy( papszSubfieldNames ); + + return true; +} + +/************************************************************************/ +/* ExtractSubstring() */ +/* */ +/* Extract a substring terminated by a comma (or end of */ +/* string). Commas in brackets are ignored as terminated with */ +/* bracket nesting understood gracefully. If the returned */ +/* string would being and end with a bracket then strip off the */ +/* brackets. */ +/* */ +/* Given a string like "(A,3(B,C),D),X,Y)" return "A,3(B,C),D". */ +/* Give a string like "3A,2C" return "3A". */ +/************************************************************************/ + +char *ossimDDFFieldDefn::ExtractSubstring( const char * pszSrc ) + +{ + int nBracket=0, i; + char *pszReturn; + + for( i = 0; + pszSrc[i] != '\0' && (nBracket > 0 || pszSrc[i] != ','); + i++ ) + { + if( pszSrc[i] == '(' ) + nBracket++; + else if( pszSrc[i] == ')' ) + nBracket--; + } + + if( pszSrc[0] == '(' ) + { + pszReturn = strdup( pszSrc + 1 ); + pszReturn[i-2] = '\0'; + } + else + { + pszReturn = strdup( pszSrc ); + pszReturn[i] = '\0'; + } + + return pszReturn; +} + +/************************************************************************/ +/* ExpandFormat() */ +/************************************************************************/ + +char *ossimDDFFieldDefn::ExpandFormat( const char * pszSrc ) + +{ + int nDestMax = 32; + char *pszDest = (char *) malloc(nDestMax+1); + int iSrc, iDst; + int nRepeat = 0; + + iSrc = 0; + iDst = 0; + pszDest[0] = '\0'; + + while( pszSrc[iSrc] != '\0' ) + { + /* This is presumably an extra level of brackets around some + binary stuff related to rescaning which we don't care to do + (see 6.4.3.3 of the standard. We just strip off the extra + layer of brackets */ + if( (iSrc == 0 || pszSrc[iSrc-1] == ',') && pszSrc[iSrc] == '(' ) + { + char *pszContents = ExtractSubstring( pszSrc+iSrc ); + char *pszExpandedContents = ExpandFormat( pszContents ); + + if( (int) (strlen(pszExpandedContents) + strlen(pszDest) + 1) + > nDestMax ) + { + nDestMax = 2 * (strlen(pszExpandedContents) + strlen(pszDest)); + pszDest = (char *) realloc(pszDest,nDestMax+1); + } + + strcat( pszDest, pszExpandedContents ); + iDst = strlen(pszDest); + + iSrc = iSrc + strlen(pszContents) + 2; + + free( pszContents ); + free( pszExpandedContents ); + } + + /* this is a repeated subclause */ + else if( (iSrc == 0 || pszSrc[iSrc-1] == ',') + && isdigit(pszSrc[iSrc]) ) + { + const char *pszNext; + nRepeat = atoi(pszSrc+iSrc); + + // skip over repeat count. + for( pszNext = pszSrc+iSrc; isdigit(*pszNext); pszNext++ ) + iSrc++; + + char *pszContents = ExtractSubstring( pszNext ); + char *pszExpandedContents = ExpandFormat( pszContents ); + + for( int i = 0; i < nRepeat; i++ ) + { + if( (int) (strlen(pszExpandedContents) + strlen(pszDest) + 1) + > nDestMax ) + { + nDestMax = + 2 * (strlen(pszExpandedContents) + strlen(pszDest)); + pszDest = (char *) realloc(pszDest,nDestMax+1); + } + + strcat( pszDest, pszExpandedContents ); + if( i < nRepeat-1 ) + strcat( pszDest, "," ); + } + + iDst = strlen(pszDest); + + if( pszNext[0] == '(' ) + iSrc = iSrc + strlen(pszContents) + 2; + else + iSrc = iSrc + strlen(pszContents); + + free( pszContents ); + free( pszExpandedContents ); + } + else + { + if( iDst+1 >= nDestMax ) + { + nDestMax = 2 * iDst; + pszDest = (char *) realloc(pszDest,nDestMax); + } + + pszDest[iDst++] = pszSrc[iSrc++]; + pszDest[iDst] = '\0'; + } + } + + return pszDest; +} + +/************************************************************************/ +/* ApplyFormats() */ +/* */ +/* This method parses the format string partially, and then */ +/* applies a subfield format string to each subfield object. */ +/* It in turn does final parsing of the subfield formats. */ +/************************************************************************/ + +int ossimDDFFieldDefn::ApplyFormats() + +{ + char *pszFormatList; + char **papszFormatItems; + +/* -------------------------------------------------------------------- */ +/* Verify that the format string is contained within brackets. */ +/* -------------------------------------------------------------------- */ + if( strlen(_formatControls) < 2 + || _formatControls[0] != '(' + || _formatControls[strlen(_formatControls)-1] != ')' ) + { + ossimNotify(ossimNotifyLevel_WARN) + << "Format controls for `%s' field missing brackets:%s\n" + << pszTag << _formatControls << std::endl; + + return false; + } + +/* -------------------------------------------------------------------- */ +/* Duplicate the string, and strip off the brackets. */ +/* -------------------------------------------------------------------- */ + + pszFormatList = ExpandFormat( _formatControls ); + +/* -------------------------------------------------------------------- */ +/* Tokenize based on commas. */ +/* -------------------------------------------------------------------- */ + papszFormatItems = + ossimCSLTokenizeStringComplex(pszFormatList, ",", false, false ); + + free( pszFormatList ); + +/* -------------------------------------------------------------------- */ +/* Apply the format items to subfields. */ +/* -------------------------------------------------------------------- */ + int iFormatItem; + + for( iFormatItem = 0; + papszFormatItems[iFormatItem] != NULL; + iFormatItem++ ) + { + const char *pszPastPrefix; + + pszPastPrefix = papszFormatItems[iFormatItem]; + while( *pszPastPrefix >= '0' && *pszPastPrefix <= '9' ) + pszPastPrefix++; + + /////////////////////////////////////////////////////////////// + // Did we get too many formats for the subfields created + // by names? This may be legal by the 8211 specification, but + // isn't encountered in any formats we care about so we just + // blow. + + if( iFormatItem >= nSubfieldCount ) + { + ossimNotify(ossimNotifyLevel_WARN) + << "Got more formats than subfields for field `%s'.\n" + << pszTag << std::endl; + break; + } + + if( !papoSubfields[iFormatItem]->SetFormat(pszPastPrefix) ) + return false; + } + +/* -------------------------------------------------------------------- */ +/* Verify that we got enough formats, cleanup and return. */ +/* -------------------------------------------------------------------- */ + ossimCSLDestroy( papszFormatItems ); + + if( iFormatItem < nSubfieldCount ) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "Got less formats than subfields for field `%s',\n" + << pszTag << std::endl; + return false; + } + +/* -------------------------------------------------------------------- */ +/* If all the fields are fixed width, then we are fixed width */ +/* too. This is important for repeating fields. */ +/* -------------------------------------------------------------------- */ + nFixedWidth = 0; + for( int i = 0; i < nSubfieldCount; i++ ) + { + if( papoSubfields[i]->GetWidth() == 0 ) + { + nFixedWidth = 0; + break; + } + else + nFixedWidth += papoSubfields[i]->GetWidth(); + } + + return true; +} + +/************************************************************************/ +/* FindSubfieldDefn() */ +/************************************************************************/ + +/** + * Find a subfield definition by it's mnemonic tag. + * + * @param pszMnemonic The name of the field. + * + * @return The subfield pointer, or NULL if there isn't any such subfield. + */ + + +ossimDDFSubfieldDefn *ossimDDFFieldDefn::FindSubfieldDefn( const char * pszMnemonic ) + +{ + for( int i = 0; i < nSubfieldCount; i++ ) + { + ossimString s = papoSubfields[i]->GetName(); + if( s == pszMnemonic ) + return papoSubfields[i]; + } + + return NULL; +} + +/************************************************************************/ +/* GetSubfield() */ +/* */ +/* Fetch a subfield by it's index. */ +/************************************************************************/ + +/** + * Fetch a subfield by index. + * + * @param i The index subfield index. (Between 0 and GetSubfieldCount()-1) + * + * @return The subfield pointer, or NULL if the index is out of range. + */ + +ossimDDFSubfieldDefn *ossimDDFFieldDefn::GetSubfield( int i ) + +{ + if( i < 0 || i >= nSubfieldCount ) + { + // assert( false ); + return NULL; + } + + return papoSubfields[i]; +} + +/************************************************************************/ +/* GetDefaultValue() */ +/************************************************************************/ + +/** + * Return default data for field instance. + */ + +char *ossimDDFFieldDefn::GetDefaultValue( int *pnSize ) + +{ +/* -------------------------------------------------------------------- */ +/* Loop once collecting the sum of the subfield lengths. */ +/* -------------------------------------------------------------------- */ + int iSubfield; + int nTotalSize = 0; + + for( iSubfield = 0; iSubfield < nSubfieldCount; iSubfield++ ) + { + int nSubfieldSize; + + if( !papoSubfields[iSubfield]->GetDefaultValue( NULL, 0, + &nSubfieldSize ) ) + return NULL; + nTotalSize += nSubfieldSize; + } + +/* -------------------------------------------------------------------- */ +/* Allocate buffer. */ +/* -------------------------------------------------------------------- */ + char *pachData = (char *) malloc( nTotalSize ); + + if( pnSize != NULL ) + *pnSize = nTotalSize; + +/* -------------------------------------------------------------------- */ +/* Loop again, collecting actual default values. */ +/* -------------------------------------------------------------------- */ + int nOffset = 0; + for( iSubfield = 0; iSubfield < nSubfieldCount; iSubfield++ ) + { + int nSubfieldSize; + + if( !papoSubfields[iSubfield]->GetDefaultValue( + pachData + nOffset, nTotalSize - nOffset, &nSubfieldSize ) ) + { + // assert( false ); + return NULL; + } + + nOffset += nSubfieldSize; + } + + // assert( nOffset == nTotalSize ); + + return pachData; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimDdfmodule.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimDdfmodule.cpp new file mode 100644 index 0000000000..56d5fdd171 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimDdfmodule.cpp @@ -0,0 +1,709 @@ +/****************************************************************************** + * Copied from "gdal" project. See licence below. + * + * Project: ISO 8211 Access + * Purpose: Implements the DDFModule class. + * Author: Frank Warmerdam, warmerdam@pobox.com + * + ****************************************************************************** + * Copyright (c) 1999, Frank Warmerdam + * + * 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 above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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. + ****************************************************************************** + * $Id: ossimDdfmodule.cpp,v 1.3 2005/10/17 18:42:27 gpotts Exp $ + */ + +#include <imaging/formats/adrg/ossimIso8211.h> +#include <base/context/ossimNotifyContext.h> +#include <base/common/ossimCplUtil.h> + + +/************************************************************************/ +/* DDFModule() */ +/************************************************************************/ + +/** + * The constructor. + */ + +ossimDDFModule::ossimDDFModule() + +{ + nFieldDefnCount = 0; + papoFieldDefns = NULL; + poRecord = NULL; + + papoClones = NULL; + nCloneCount = nMaxCloneCount = 0; + + fpDDF = NULL; + bReadOnly = true; + + _interchangeLevel = '\0'; + _inlineCodeExtensionIndicator = '\0'; + _versionNumber = '\0'; + _appIndicator = '\0'; + _fieldControlLength = '\0'; + strcpy( _extendedCharSet, " ! " ); + + _recLength = 0; + _leaderIden = 'L'; + _fieldAreaStart = 0; + _sizeFieldLength = 0; + _sizeFieldPos = 0; + _sizeFieldTag = 0; +} + +/************************************************************************/ +/* ~DDFModule() */ +/************************************************************************/ + +/** + * The destructor. + */ + +ossimDDFModule::~ossimDDFModule() + +{ + Close(); +} + +/************************************************************************/ +/* Close() */ +/* */ +/* Note that closing a file also destroys essentially all other */ +/* module datastructures. */ +/************************************************************************/ + +/** + * Close an ISO 8211 file. + */ + +void ossimDDFModule::Close() + +{ +/* -------------------------------------------------------------------- */ +/* Close the file. */ +/* -------------------------------------------------------------------- */ + if( fpDDF != NULL ) + { + fclose( fpDDF ); + fpDDF = NULL; + } + +/* -------------------------------------------------------------------- */ +/* Cleanup the working record. */ +/* -------------------------------------------------------------------- */ + if( poRecord != NULL ) + { + delete poRecord; + poRecord = NULL; + } + +/* -------------------------------------------------------------------- */ +/* Cleanup the clones. Deleting them will cause a callback to */ +/* remove them from the list. */ +/* -------------------------------------------------------------------- */ + while( nCloneCount > 0 ) + delete papoClones[0]; + + nMaxCloneCount = 0; + free( papoClones ); + papoClones = NULL; + +/* -------------------------------------------------------------------- */ +/* Cleanup the field definitions. */ +/* -------------------------------------------------------------------- */ + int i; + + for( i = 0; i < nFieldDefnCount; i++ ) + delete papoFieldDefns[i]; + free( papoFieldDefns ); + papoFieldDefns = NULL; + nFieldDefnCount = 0; +} + +/************************************************************************/ +/* Open() */ +/* */ +/* Open an ISO 8211 file, and read the DDR record to build the */ +/* field definitions. */ +/************************************************************************/ + +/** + * Open a ISO 8211 (DDF) file for reading. + * + * If the open succeeds the data descriptive record (DDR) will have been + * read, and all the field and subfield definitions will be available. + * + * @param pszFilename The name of the file to open. + * @param bFailQuietly If false a CPL Error is issued for non-8211 files, + * otherwise quietly return NULL. + * + * @return false if the open fails or true if it succeeds. Errors messages + * are issued internally with CPLError(). + */ + +int ossimDDFModule::Open( const char * pszFilename, int bFailQuietly ) + +{ + static const size_t nLeaderSize = 24; + +/* -------------------------------------------------------------------- */ +/* Close the existing file if there is one. */ +/* -------------------------------------------------------------------- */ + if( fpDDF != NULL ) + Close(); + +/* -------------------------------------------------------------------- */ +/* Open the file. */ +/* -------------------------------------------------------------------- */ + fpDDF = fopen( pszFilename, "rb" ); + + if( fpDDF == NULL ) + { + if( !bFailQuietly ) + ossimNotify(ossimNotifyLevel_WARN) + << "Unable to open DDF file `%s'." + << pszFilename << std::endl; + return false; + } + +/* -------------------------------------------------------------------- */ +/* Read the 24 byte leader. */ +/* -------------------------------------------------------------------- */ + char achLeader[nLeaderSize]; + + if( fread( achLeader, 1, nLeaderSize, fpDDF ) != nLeaderSize ) + { + fclose( fpDDF ); + fpDDF = NULL; + + if( !bFailQuietly ) + ossimNotify(ossimNotifyLevel_WARN) + << "Leader is short on DDF file `%s'." + << pszFilename << std::endl; + + return false; + } + +/* -------------------------------------------------------------------- */ +/* Verify that this appears to be a valid DDF file. */ +/* -------------------------------------------------------------------- */ + int i, bValid = true; + + for( i = 0; i < (int)nLeaderSize; i++ ) + { + if( achLeader[i] < 32 || achLeader[i] > 126 ) + bValid = false; + } + + if( achLeader[5] != '1' && achLeader[5] != '2' && achLeader[5] != '3' ) + bValid = false; + + if( achLeader[6] != 'L' ) + bValid = false; + if( achLeader[8] != '1' && achLeader[8] != ' ' ) + bValid = false; + +/* -------------------------------------------------------------------- */ +/* Extract information from leader. */ +/* -------------------------------------------------------------------- */ + + if( bValid ) + { + _recLength = ossimDDFScanInt( achLeader+0, 5 ); + _interchangeLevel = achLeader[5]; + _leaderIden = achLeader[6]; + _inlineCodeExtensionIndicator = achLeader[7]; + _versionNumber = achLeader[8]; + _appIndicator = achLeader[9]; + _fieldControlLength = ossimDDFScanInt(achLeader+10,2); + _fieldAreaStart = ossimDDFScanInt(achLeader+12,5); + _extendedCharSet[0] = achLeader[17]; + _extendedCharSet[1] = achLeader[18]; + _extendedCharSet[2] = achLeader[19]; + _extendedCharSet[3] = '\0'; + _sizeFieldLength = ossimDDFScanInt(achLeader+20,1); + _sizeFieldPos = ossimDDFScanInt(achLeader+21,1); + _sizeFieldTag = ossimDDFScanInt(achLeader+23,1); + + if( _recLength < 12 || _fieldControlLength == 0 + || _fieldAreaStart < 24 || _sizeFieldLength == 0 + || _sizeFieldPos == 0 || _sizeFieldTag == 0 ) + { + bValid = false; + } + } + +/* -------------------------------------------------------------------- */ +/* If the header is invalid, then clean up, report the error */ +/* and return. */ +/* -------------------------------------------------------------------- */ + if( !bValid ) + { + fclose( fpDDF ); + fpDDF = NULL; + + if( !bFailQuietly ) + ossimNotify(ossimNotifyLevel_WARN) + << "File `%s' does not appear to have\n" + << "a valid ISO 8211 header.\n" + << pszFilename << std::endl; + return false; + } + +/* -------------------------------------------------------------------- */ +/* Read the whole record info memory. */ +/* -------------------------------------------------------------------- */ + char *pachRecord; + + pachRecord = (char *) malloc(_recLength); + memcpy( pachRecord, achLeader, nLeaderSize ); + + if( fread( pachRecord+nLeaderSize, 1, _recLength-nLeaderSize, fpDDF ) + != _recLength - nLeaderSize ) + { + if( !bFailQuietly ) + ossimNotify(ossimNotifyLevel_WARN) + << "Header record is short on DDF file `%s'." + << pszFilename << std::endl; + + return false; + } + +/* -------------------------------------------------------------------- */ +/* First make a pass counting the directory entries. */ +/* -------------------------------------------------------------------- */ + int nFieldEntryWidth, nFDCount = 0; + + nFieldEntryWidth = _sizeFieldLength + _sizeFieldPos + _sizeFieldTag; + + for( i = nLeaderSize; i < _recLength; i += nFieldEntryWidth ) + { + if( pachRecord[i] == OSSIM_DDF_FIELD_TERMINATOR ) + break; + + nFDCount++; + } + +/* -------------------------------------------------------------------- */ +/* Allocate, and read field definitions. */ +/* -------------------------------------------------------------------- */ + for( i = 0; i < nFDCount; i++ ) + { + char szTag[128]; + int nEntryOffset = nLeaderSize + i*nFieldEntryWidth; + int nFieldLength, nFieldPos; + ossimDDFFieldDefn *poFDefn; + + strncpy( szTag, pachRecord+nEntryOffset, _sizeFieldTag ); + szTag[_sizeFieldTag] = '\0'; + + nEntryOffset += _sizeFieldTag; + nFieldLength = ossimDDFScanInt( pachRecord+nEntryOffset, _sizeFieldLength ); + + nEntryOffset += _sizeFieldLength; + nFieldPos = ossimDDFScanInt( pachRecord+nEntryOffset, _sizeFieldPos ); + + poFDefn = new ossimDDFFieldDefn(); + poFDefn->Initialize( this, szTag, nFieldLength, + pachRecord+_fieldAreaStart+nFieldPos ); + AddField( poFDefn ); + } + + free( pachRecord ); + +/* -------------------------------------------------------------------- */ +/* Record the current file offset, the beginning of the first */ +/* data record. */ +/* -------------------------------------------------------------------- */ + nFirstRecordOffset = ftell( fpDDF ); + + return true; +} + +/************************************************************************/ +/* Initialize() */ +/************************************************************************/ + +int ossimDDFModule::Initialize( char chInterchangeLevel, + char chLeaderIden, + char chCodeExtensionIndicator, + char chVersionNumber, + char chAppIndicator, + const char *pszExtendedCharSet, + int nSizeFieldLength, + int nSizeFieldPos, + int nSizeFieldTag ) + +{ + _interchangeLevel = chInterchangeLevel; + _leaderIden = chLeaderIden; + _inlineCodeExtensionIndicator = chCodeExtensionIndicator; + _versionNumber = chVersionNumber; + _appIndicator = chAppIndicator; + strcpy( _extendedCharSet, pszExtendedCharSet ); + _sizeFieldLength = nSizeFieldLength; + _sizeFieldPos = nSizeFieldPos; + _sizeFieldTag = nSizeFieldTag; + + return true; +} + +/************************************************************************/ +/* Create() */ +/************************************************************************/ + +int ossimDDFModule::Create( const char *pszFilename ) + +{ + // CPLAssert( fpDDF == NULL ); + +/* -------------------------------------------------------------------- */ +/* Create the file on disk. */ +/* -------------------------------------------------------------------- */ + fpDDF = fopen( pszFilename, "wb+" ); + if( fpDDF == NULL ) + { + ossimNotify(ossimNotifyLevel_WARN) + << "Failed to create file %s, check path and permissions." + << pszFilename << std::endl; + return false; + } + + bReadOnly = false; + +/* -------------------------------------------------------------------- */ +/* Prepare all the field definition information. */ +/* -------------------------------------------------------------------- */ + int iField; + + _fieldControlLength = 9; + _recLength = 24 + + nFieldDefnCount * (_sizeFieldLength+_sizeFieldPos+_sizeFieldTag) + + 1; + + _fieldAreaStart = _recLength; + + for( iField=0; iField < nFieldDefnCount; iField++ ) + { + int nLength; + + papoFieldDefns[iField]->GenerateDDREntry( NULL, &nLength ); + _recLength += nLength; + } + +/* -------------------------------------------------------------------- */ +/* Setup 24 byte leader. */ +/* -------------------------------------------------------------------- */ + char achLeader[25]; + + sprintf( achLeader+0, "%05d", (int) _recLength ); + achLeader[5] = _interchangeLevel; + achLeader[6] = _leaderIden; + achLeader[7] = _inlineCodeExtensionIndicator; + achLeader[8] = _versionNumber; + achLeader[9] = _appIndicator; + sprintf( achLeader+10, "%02d", (int) _fieldControlLength ); + sprintf( achLeader+12, "%05d", (int) _fieldAreaStart ); + strncpy( achLeader+17, _extendedCharSet, 3 ); + sprintf( achLeader+20, "%1d", (int) _sizeFieldLength ); + sprintf( achLeader+21, "%1d", (int) _sizeFieldPos ); + achLeader[22] = '0'; + sprintf( achLeader+23, "%1d", (int) _sizeFieldTag ); + fwrite( achLeader, 24, 1, fpDDF ); + +/* -------------------------------------------------------------------- */ +/* Write out directory entries. */ +/* -------------------------------------------------------------------- */ + int nOffset = 0; + for( iField=0; iField < nFieldDefnCount; iField++ ) + { + char achDirEntry[12]; + int nLength; + + papoFieldDefns[iField]->GenerateDDREntry( NULL, &nLength ); + + strcpy( achDirEntry, papoFieldDefns[iField]->GetName() ); + sprintf( achDirEntry + _sizeFieldTag, "%03d", nLength ); + sprintf( achDirEntry + _sizeFieldTag + _sizeFieldLength, + "%04d", nOffset ); + nOffset += nLength; + + fwrite( achDirEntry, 11, 1, fpDDF ); + } + + char chUT = OSSIM_DDF_FIELD_TERMINATOR; + fwrite( &chUT, 1, 1, fpDDF ); + +/* -------------------------------------------------------------------- */ +/* Write out the field descriptions themselves. */ +/* -------------------------------------------------------------------- */ + for( iField=0; iField < nFieldDefnCount; iField++ ) + { + char *pachData; + int nLength; + + papoFieldDefns[iField]->GenerateDDREntry( &pachData, &nLength ); + fwrite( pachData, nLength, 1, fpDDF ); + free( pachData ); + } + + return true; +} + +/************************************************************************/ +/* Dump() */ +/************************************************************************/ + +/** + * Write out module info to debugging file. + * + * A variety of information about the module is written to the debugging + * file. This includes all the field and subfield definitions read from + * the header. + * + * @param fp The standard io file handle to write to. ie. stderr. + */ + +void ossimDDFModule::Dump( FILE * fp ) + +{ + fprintf( fp, "DDFModule:\n" ); + fprintf( fp, " _recLength = %ld\n", _recLength ); + fprintf( fp, " _interchangeLevel = %c\n", _interchangeLevel ); + fprintf( fp, " _leaderIden = %c\n", _leaderIden ); + fprintf( fp, " _inlineCodeExtensionIndicator = %c\n", + _inlineCodeExtensionIndicator ); + fprintf( fp, " _versionNumber = %c\n", _versionNumber ); + fprintf( fp, " _appIndicator = %c\n", _appIndicator ); + fprintf( fp, " _extendedCharSet = `%s'\n", _extendedCharSet ); + fprintf( fp, " _fieldControlLength = %d\n", _fieldControlLength ); + fprintf( fp, " _fieldAreaStart = %ld\n", _fieldAreaStart ); + fprintf( fp, " _sizeFieldLength = %ld\n", _sizeFieldLength ); + fprintf( fp, " _sizeFieldPos = %ld\n", _sizeFieldPos ); + fprintf( fp, " _sizeFieldTag = %ld\n", _sizeFieldTag ); + + for( int i = 0; i < nFieldDefnCount; i++ ) + { + papoFieldDefns[i]->Dump( fp ); + } +} + +/************************************************************************/ +/* FindFieldDefn() */ +/************************************************************************/ + +/** + * Fetch the definition of the named field. + * + * This function will scan the DDFFieldDefn's on this module, to find + * one with the indicated field name. + * + * @param pszFieldName The name of the field to search for. The comparison is + * case insensitive. + * + * @return A pointer to the request DDFFieldDefn object is returned, or NULL + * if none matching the name are found. The return object remains owned by + * the DDFModule, and should not be deleted by application code. + */ + +ossimDDFFieldDefn *ossimDDFModule::FindFieldDefn( const char *pszFieldName ) + +{ + int i; + +/* -------------------------------------------------------------------- */ +/* This pass tries to reduce the cost of comparing strings by */ +/* first checking the first character, and by using strcmp() */ +/* -------------------------------------------------------------------- */ + for( i = 0; i < nFieldDefnCount; i++ ) + { + const char *pszThisName = papoFieldDefns[i]->GetName(); + + if( *pszThisName == *pszFieldName + && strcmp( pszFieldName+1, pszThisName+1) == 0 ) + return papoFieldDefns[i]; + } + +/* -------------------------------------------------------------------- */ +/* Now do a more general check. Application code may not */ +/* always use the correct name case. */ +/* -------------------------------------------------------------------- */ + for( i = 0; i < nFieldDefnCount; i++ ) + { + ossimString s = papoFieldDefns[i]->GetName(); + if( s == pszFieldName ) + return papoFieldDefns[i]; + } + + return NULL; +} + +/************************************************************************/ +/* ReadRecord() */ +/* */ +/* Read one record from the file, and return to the */ +/* application. The returned record is owned by the module, */ +/* and is reused from call to call in order to preserve headers */ +/* when they aren't being re-read from record to record. */ +/************************************************************************/ + +/** + * Read one record from the file. + * + * @return A pointer to a DDFRecord object is returned, or NULL if a read + * error, or end of file occurs. The returned record is owned by the + * module, and should not be deleted by the application. The record is + * only valid untill the next ReadRecord() at which point it is overwritten. + */ + +ossimDDFRecord *ossimDDFModule::ReadRecord() + +{ + if( poRecord == NULL ) + poRecord = new ossimDDFRecord( this ); + + if( poRecord->Read() ) + return poRecord; + else + return NULL; +} + +/************************************************************************/ +/* AddField() */ +/************************************************************************/ + +/** + * Add new field definition. + * + * Field definitions may only be added to DDFModules being used for + * writing, not those being used for reading. Ownership of the + * DDFFieldDefn object is taken by the DDFModule. + * + * @param poNewFDefn definition to be added to the module. + */ + +void ossimDDFModule::AddField( ossimDDFFieldDefn *poNewFDefn ) + +{ + nFieldDefnCount++; + papoFieldDefns = (ossimDDFFieldDefn **) + ossimCPLRealloc(papoFieldDefns, sizeof(void*)*nFieldDefnCount); + papoFieldDefns[nFieldDefnCount-1] = poNewFDefn; +} + +/************************************************************************/ +/* GetField() */ +/************************************************************************/ + +/** + * Fetch a field definition by index. + * + * @param i (from 0 to GetFieldCount() - 1. + * @return the returned field pointer or NULL if the index is out of range. + */ + +ossimDDFFieldDefn *ossimDDFModule::GetField(int i) + +{ + if( i < 0 || i >= nFieldDefnCount ) + return NULL; + else + return papoFieldDefns[i]; +} + +/************************************************************************/ +/* AddCloneRecord() */ +/* */ +/* We want to keep track of cloned records, so we can clean */ +/* them up when the module is destroyed. */ +/************************************************************************/ + +void ossimDDFModule::AddCloneRecord( ossimDDFRecord * poRecord ) + +{ +/* -------------------------------------------------------------------- */ +/* Do we need to grow the container array? */ +/* -------------------------------------------------------------------- */ + if( nCloneCount == nMaxCloneCount ) + { + nMaxCloneCount = nCloneCount*2 + 20; + papoClones = (ossimDDFRecord **) ossimCPLRealloc(papoClones, + nMaxCloneCount * sizeof(void*)); + } + +/* -------------------------------------------------------------------- */ +/* Add to the list. */ +/* -------------------------------------------------------------------- */ + papoClones[nCloneCount++] = poRecord; +} + +/************************************************************************/ +/* RemoveCloneRecord() */ +/************************************************************************/ + +void ossimDDFModule::RemoveCloneRecord( ossimDDFRecord * poRecord ) + +{ + int i; + + for( i = 0; i < nCloneCount; i++ ) + { + if( papoClones[i] == poRecord ) + { + papoClones[i] = papoClones[nCloneCount-1]; + nCloneCount--; + return; + } + } + + // CPLAssert( false ); +} + +/************************************************************************/ +/* Rewind() */ +/************************************************************************/ + +/** + * Return to first record. + * + * The next call to ReadRecord() will read the first data record in the file. + * + * @param nOffset the offset in the file to return to. By default this is + * -1, a special value indicating that reading should return to the first + * data record. Otherwise it is an absolute byte offset in the file. + */ + +void ossimDDFModule::Rewind( long nOffset ) + +{ + if( nOffset == -1 ) + nOffset = nFirstRecordOffset; + + if( fpDDF == NULL ) + return; + + fseek( fpDDF, nOffset, SEEK_SET ); + + if( nOffset == nFirstRecordOffset && poRecord != NULL ) + poRecord->Clear(); + +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimDdfrecord.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimDdfrecord.cpp new file mode 100644 index 0000000000..7ef774db7b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimDdfrecord.cpp @@ -0,0 +1,1850 @@ +/****************************************************************************** + * Copied from "gdal" project. See licence below. + * + * Project: ISO 8211 Access + * Purpose: Implements the DDFRecord class. + * Author: Frank Warmerdam, warmerdam@pobox.com + * + ****************************************************************************** + * Copyright (c) 1999, Frank Warmerdam + * + * 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 above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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. + ****************************************************************************** + * $Id: ossimDdfrecord.cpp,v 1.3 2005/10/17 18:42:27 gpotts Exp $ + */ + +#include <imaging/formats/adrg/ossimIso8211.h> +#include <base/context/ossimNotifyContext.h> +#include <base/common/ossimCplUtil.h> + +// CPL_CVSID("$Id: ossimDdfrecord.cpp,v 1.3 2005/10/17 18:42:27 gpotts Exp $"); + +static const size_t nLeaderSize = 24; + +/************************************************************************/ +/* DDFRecord() */ +/************************************************************************/ + +ossimDDFRecord::ossimDDFRecord( ossimDDFModule * poModuleIn ) + +{ + poModule = poModuleIn; + + nReuseHeader = false; + + nFieldOffset = 0; + + nDataSize = 0; + pachData = NULL; + + nFieldCount = 0; + paoFields = NULL; + + bIsClone = false; + + _sizeFieldTag = 4; + _sizeFieldPos = 0; + _sizeFieldLength = 0; +} + +/************************************************************************/ +/* ~DDFRecord() */ +/************************************************************************/ + +ossimDDFRecord::~ossimDDFRecord() + +{ + Clear(); + + if( bIsClone ) + poModule->RemoveCloneRecord( this ); +} + +/************************************************************************/ +/* Dump() */ +/************************************************************************/ + +/** + * Write out record contents to debugging file. + * + * A variety of information about this record, and all it's fields and + * subfields is written to the given debugging file handle. Note that + * field definition information (ala DDFFieldDefn) isn't written. + * + * @param fp The standard io file handle to write to. ie. stderr + */ + +void ossimDDFRecord::Dump( FILE * fp ) + +{ + fprintf( fp, "DDFRecord:\n" ); + fprintf( fp, " nReuseHeader = %d\n", nReuseHeader ); + fprintf( fp, " nDataSize = %d\n", nDataSize ); + fprintf( fp, + " _sizeFieldLength=%d, _sizeFieldPos=%d, _sizeFieldTag=%d\n", + _sizeFieldLength, _sizeFieldPos, _sizeFieldTag ); + + for( int i = 0; i < nFieldCount; i++ ) + { + paoFields[i].Dump( fp ); + } +} + +/************************************************************************/ +/* Read() */ +/* */ +/* Read a record of data from the file, and parse the header to */ +/* build a field list for the record (or reuse the existing one */ +/* if reusing headers). It is expected that the file pointer */ +/* will be positioned at the beginning of a data record. It is */ +/* the DDFModule's responsibility to do so. */ +/* */ +/* This method should only be called by the DDFModule class. */ +/************************************************************************/ + +int ossimDDFRecord::Read() + +{ +/* -------------------------------------------------------------------- */ +/* Redefine the record on the basis of the header if needed. */ +/* As a side effect this will read the data for the record as well.*/ +/* -------------------------------------------------------------------- */ + if( !nReuseHeader ) + { + return( ReadHeader() ); + } + +/* -------------------------------------------------------------------- */ +/* Otherwise we read just the data and carefully overlay it on */ +/* the previous records data without disturbing the rest of the */ +/* record. */ +/* -------------------------------------------------------------------- */ + size_t nReadBytes; + + nReadBytes = fread( pachData + nFieldOffset, 1, + nDataSize - nFieldOffset, + poModule->GetFP() ); + if( nReadBytes != (size_t) (nDataSize - nFieldOffset) + && nReadBytes == 0 + && feof( poModule->GetFP() ) ) + { + return false; + } + else if( nReadBytes != (size_t) (nDataSize - nFieldOffset) ) + { + ossimNotify(ossimNotifyLevel_WARN) + << "Data record is short on DDF file.\n" << std::endl; + + return false; + } + + // notdef: eventually we may have to do something at this point to + // notify the DDFField's that their data values have changed. + + return true; +} + +/************************************************************************/ +/* Write() */ +/************************************************************************/ + +/** + * Write record out to module. + * + * This method writes the current record to the module to which it is + * attached. Normally this would be at the end of the file, and only used + * for modules newly created with DDFModule::Create(). Rewriting existing + * records is not supported at this time. Calling Write() multiple times + * on a DDFRecord will result it multiple copies being written at the end of + * the module. + * + * @return true on success or false on failure. + */ + +int ossimDDFRecord::Write() + +{ + if( !ResetDirectory() ) + return false; + +/* -------------------------------------------------------------------- */ +/* Prepare leader. */ +/* -------------------------------------------------------------------- */ + char szLeader[nLeaderSize+1]; + + memset( szLeader, ' ', nLeaderSize ); + + sprintf( szLeader+0, "%05d", nDataSize + nLeaderSize ); + szLeader[5] = ' '; + szLeader[6] = 'D'; + + sprintf( szLeader + 12, "%05d", nFieldOffset + nLeaderSize ); + szLeader[17] = ' '; + + szLeader[20] = (char) ('0' + _sizeFieldLength); + szLeader[21] = (char) ('0' + _sizeFieldPos); + szLeader[22] = '0'; + szLeader[23] = (char) ('0' + _sizeFieldTag); + + /* notdef: lots of stuff missing */ + +/* -------------------------------------------------------------------- */ +/* Write the leader. */ +/* -------------------------------------------------------------------- */ + fwrite( szLeader, nLeaderSize, 1, poModule->GetFP() ); + +/* -------------------------------------------------------------------- */ +/* Write the remainder of the record. */ +/* -------------------------------------------------------------------- */ + fwrite( pachData, nDataSize, 1, poModule->GetFP() ); + + return true; +} + +/************************************************************************/ +/* Clear() */ +/* */ +/* Clear any information associated with the last header in */ +/* preparation for reading a new header. */ +/************************************************************************/ + +void ossimDDFRecord::Clear() + +{ + if( paoFields != NULL ) + delete[] paoFields; + + paoFields = NULL; + nFieldCount = 0; + + if( pachData != NULL ) + free( pachData ); + + pachData = NULL; + nDataSize = 0; + nReuseHeader = false; +} + +/************************************************************************/ +/* ReadHeader() */ +/* */ +/* This perform the header reading and parsing job for the */ +/* Read() method. It reads the header, and builds a field */ +/* list. */ +/************************************************************************/ + +int ossimDDFRecord::ReadHeader() + +{ +/* -------------------------------------------------------------------- */ +/* Clear any existing information. */ +/* -------------------------------------------------------------------- */ + Clear(); + +/* -------------------------------------------------------------------- */ +/* Read the 24 byte leader. */ +/* -------------------------------------------------------------------- */ + char achLeader[nLeaderSize]; + int nReadBytes; + + nReadBytes = fread(achLeader,1,nLeaderSize,poModule->GetFP()); + if( nReadBytes == 0 && feof( poModule->GetFP() ) ) + { + return false; + } + else if( nReadBytes != (int) nLeaderSize ) + { + ossimNotify(ossimNotifyLevel_WARN) + << "Leader is short on DDF file." << std::endl; + + return false; + } + +/* -------------------------------------------------------------------- */ +/* Extract information from leader. */ +/* -------------------------------------------------------------------- */ + int _recLength, _fieldAreaStart; + char _leaderIden; + + _recLength = ossimDDFScanInt( achLeader+0, 5 ); + _leaderIden = achLeader[6]; + _fieldAreaStart = ossimDDFScanInt(achLeader+12,5); + + _sizeFieldLength = achLeader[20] - '0'; + _sizeFieldPos = achLeader[21] - '0'; + _sizeFieldTag = achLeader[23] - '0'; + + if( _sizeFieldLength < 0 || _sizeFieldLength > 9 + || _sizeFieldPos < 0 || _sizeFieldPos > 9 + || _sizeFieldTag < 0 || _sizeFieldTag > 9 ) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ISO8211 record leader appears to be corrupt." << std::endl; + return false; + } + + if( _leaderIden == 'R' ) + nReuseHeader = true; + + nFieldOffset = _fieldAreaStart - nLeaderSize; + +/* -------------------------------------------------------------------- */ +/* Is there anything seemly screwy about this record? */ +/* -------------------------------------------------------------------- */ + if(( _recLength < 24 || _recLength > 100000000 + || _fieldAreaStart < 24 || _fieldAreaStart > 100000 ) + && (_recLength != 0)) + { + ossimNotify(ossimNotifyLevel_WARN) + << "Data record appears to be corrupt on DDF file.\n" + << " -- ensure that the files were uncompressed without modifying\n" + << "carriage return/linefeeds (by default WINZIP does this)." + << std::endl; + + return false; + } + +/* ==================================================================== */ +/* Handle the normal case with the record length available. */ +/* ==================================================================== */ + if(_recLength != 0) { +/* -------------------------------------------------------------------- */ +/* Read the remainder of the record. */ +/* -------------------------------------------------------------------- */ + nDataSize = _recLength - nLeaderSize; + pachData = (char *) malloc(nDataSize); + + if( fread( pachData, 1, nDataSize, poModule->GetFP()) != + (size_t) nDataSize ) + { + ossimNotify(ossimNotifyLevel_WARN) + << "Data record is short on DDF file." + << std::endl; + + return false; + } + +/* -------------------------------------------------------------------- */ +/* If we don't find a field terminator at the end of the record */ +/* we will read extra bytes till we get to it. */ +/* -------------------------------------------------------------------- */ + while( pachData[nDataSize-1] != OSSIM_DDF_FIELD_TERMINATOR ) + { + nDataSize++; + pachData = (char *) ossimCPLRealloc(pachData,nDataSize); + + if( fread( pachData + nDataSize - 1, 1, 1, poModule->GetFP() ) + != 1 ) + { + ossimNotify(ossimNotifyLevel_WARN) + << "Data record is short on DDF file." + << std::endl; + + return false; + } + ossimNotify(ossimNotifyLevel_DEBUG) + << "Didn't find field terminator, read one more byte." + << std::endl; + } + +/* -------------------------------------------------------------------- */ +/* Loop over the directory entries, making a pass counting them. */ +/* -------------------------------------------------------------------- */ + int i; + int nFieldEntryWidth; + + nFieldEntryWidth = _sizeFieldLength + _sizeFieldPos + _sizeFieldTag; + nFieldCount = 0; + for( i = 0; i < nDataSize; i += nFieldEntryWidth ) + { + if( pachData[i] == OSSIM_DDF_FIELD_TERMINATOR ) + break; + + nFieldCount++; + } + +/* -------------------------------------------------------------------- */ +/* Allocate, and read field definitions. */ +/* -------------------------------------------------------------------- */ + paoFields = new ossimDDFField[nFieldCount]; + + for( i = 0; i < nFieldCount; i++ ) + { + char szTag[128]; + int nEntryOffset = i*nFieldEntryWidth; + int nFieldLength, nFieldPos; + +/* -------------------------------------------------------------------- */ +/* Read the position information and tag. */ +/* -------------------------------------------------------------------- */ + strncpy( szTag, pachData+nEntryOffset, _sizeFieldTag ); + szTag[_sizeFieldTag] = '\0'; + + nEntryOffset += _sizeFieldTag; + nFieldLength = ossimDDFScanInt( pachData+nEntryOffset, _sizeFieldLength ); + + nEntryOffset += _sizeFieldLength; + nFieldPos = ossimDDFScanInt( pachData+nEntryOffset, _sizeFieldPos ); + +/* -------------------------------------------------------------------- */ +/* Find the corresponding field in the module directory. */ +/* -------------------------------------------------------------------- */ + ossimDDFFieldDefn *poFieldDefn = poModule->FindFieldDefn( szTag ); + + if( poFieldDefn == NULL ) + { + ossimNotify(ossimNotifyLevel_WARN) + << "Undefined field `%s' encountered in data record." + << szTag << std::endl; + return false; + } + +/* -------------------------------------------------------------------- */ +/* Assign info the DDFField. */ +/* -------------------------------------------------------------------- */ + paoFields[i].Initialize( poFieldDefn, + pachData + _fieldAreaStart + nFieldPos - nLeaderSize, + nFieldLength ); + } + + return true; + } +/* ==================================================================== */ +/* Handle the exceptional case where the record length is */ +/* zero. In this case we have to read all the data based on */ +/* the size of data items as per ISO8211 spec Annex C, 1.5.1. */ +/* */ +/* See Bugzilla bug 181 and test with file US4CN21M.000. */ +/* ==================================================================== */ + else { + ossimNotify(ossimNotifyLevel_WARN) + << "Record with zero length, use variant (C.1.5.1) logic." + << std::endl; + + /* ----------------------------------------------------------------- */ + /* _recLength == 0, handle the large record. */ + /* */ + /* Read the remainder of the record. */ + /* ----------------------------------------------------------------- */ + nDataSize = 0; + pachData = NULL; + + /* ----------------------------------------------------------------- */ + /* Loop over the directory entries, making a pass counting them. */ + /* ----------------------------------------------------------------- */ + int nFieldEntryWidth = _sizeFieldLength + _sizeFieldPos + _sizeFieldTag; + nFieldCount = 0; + int i=0; + char *tmpBuf = (char*)malloc(nFieldEntryWidth); + + // while we're not at the end, store this entry, + // and keep on reading... + do { + // read an Entry: + if(nFieldEntryWidth != + (int) fread(tmpBuf, 1, nFieldEntryWidth, poModule->GetFP())) { + ossimNotify(ossimNotifyLevel_WARN) + << "Data record is short on DDF file." << std::endl; + return false; + } + + // move this temp buffer into more permanent storage: + char *newBuf = (char*)malloc(nDataSize+nFieldEntryWidth); + if(pachData!=NULL) { + memcpy(newBuf, pachData, nDataSize); + free(pachData); + } + memcpy(&newBuf[nDataSize], tmpBuf, nFieldEntryWidth); + pachData = newBuf; + nDataSize += nFieldEntryWidth; + + if(OSSIM_DDF_FIELD_TERMINATOR != tmpBuf[0]) { + nFieldCount++; + } + } + while(OSSIM_DDF_FIELD_TERMINATOR != tmpBuf[0]); + + // Now, rewind a little. Only the TERMINATOR should have been read: + int rewindSize = nFieldEntryWidth - 1; + FILE *fp = poModule->GetFP(); + long pos = ftell(fp) - rewindSize; + fseek(fp, pos, SEEK_SET); + nDataSize -= rewindSize; + + // -------------------------------------------------------------------- + // Okay, now let's populate the heck out of pachData... + // -------------------------------------------------------------------- + for(i=0; i<nFieldCount; i++) { + int nEntryOffset = (i*nFieldEntryWidth) + _sizeFieldTag; + int nFieldLength = ossimDDFScanInt(pachData + nEntryOffset, + _sizeFieldLength); + char *tmpBuf = (char*)malloc(nFieldLength); + + // read an Entry: + if(nFieldLength != + (int) fread(tmpBuf, 1, nFieldLength, poModule->GetFP())) { + ossimNotify(ossimNotifyLevel_WARN) + << "Data record is short on DDF file." << std::endl; + return false; + } + + // move this temp buffer into more permanent storage: + char *newBuf = (char*)malloc(nDataSize+nFieldLength); + memcpy(newBuf, pachData, nDataSize); + free(pachData); + memcpy(&newBuf[nDataSize], tmpBuf, nFieldLength); + free(tmpBuf); + pachData = newBuf; + nDataSize += nFieldLength; + } + + /* ----------------------------------------------------------------- */ + /* Allocate, and read field definitions. */ + /* ----------------------------------------------------------------- */ + paoFields = new ossimDDFField[nFieldCount]; + + for( i = 0; i < nFieldCount; i++ ) + { + char szTag[128]; + int nEntryOffset = i*nFieldEntryWidth; + int nFieldLength, nFieldPos; + + /* ------------------------------------------------------------- */ + /* Read the position information and tag. */ + /* ------------------------------------------------------------- */ + strncpy( szTag, pachData+nEntryOffset, _sizeFieldTag ); + szTag[_sizeFieldTag] = '\0'; + + nEntryOffset += _sizeFieldTag; + nFieldLength = ossimDDFScanInt( pachData+nEntryOffset, _sizeFieldLength ); + + nEntryOffset += _sizeFieldLength; + nFieldPos = ossimDDFScanInt( pachData+nEntryOffset, _sizeFieldPos ); + + /* ------------------------------------------------------------- */ + /* Find the corresponding field in the module directory. */ + /* ------------------------------------------------------------- */ + ossimDDFFieldDefn *poFieldDefn = poModule->FindFieldDefn( szTag ); + + if( poFieldDefn == NULL ) + { + ossimNotify(ossimNotifyLevel_WARN) + << "Undefined field `%s' encountered in data record." + << szTag << std::endl; + return false; + } + + /* ------------------------------------------------------------- */ + /* Assign info the DDFField. */ + /* ------------------------------------------------------------- */ + + paoFields[i].Initialize( poFieldDefn, + pachData + _fieldAreaStart + + nFieldPos - nLeaderSize, + nFieldLength ); + } + + return true; + } +} + +/************************************************************************/ +/* FindField() */ +/************************************************************************/ + +/** + * Find the named field within this record. + * + * @param pszName The name of the field to fetch. The comparison is + * case insensitive. + * @param iFieldIndex The instance of this field to fetch. Use zero (the + * default) for the first instance. + * + * @return Pointer to the requested DDFField. This pointer is to an + * internal object, and should not be freed. It remains valid until + * the next record read. + */ + +ossimDDFField * ossimDDFRecord::FindField( const char * pszName, int iFieldIndex ) + +{ + for( int i = 0; i < nFieldCount; i++ ) + { + ossimString s = paoFields[i].GetFieldDefn()->GetName(); + if( s == pszName) + { + if( iFieldIndex == 0 ) + return paoFields + i; + else + iFieldIndex--; + } + } + + return NULL; +} + +/************************************************************************/ +/* GetField() */ +/************************************************************************/ + +/** + * Fetch field object based on index. + * + * @param i The index of the field to fetch. Between 0 and GetFieldCount()-1. + * + * @return A DDFField pointer, or NULL if the index is out of range. + */ + +ossimDDFField *ossimDDFRecord::GetField( int i ) + +{ + if( i < 0 || i >= nFieldCount ) + return NULL; + else + return paoFields + i; +} + +/************************************************************************/ +/* GetIntSubfield() */ +/************************************************************************/ + +/** + * Fetch value of a subfield as an integer. This is a convenience + * function for fetching a subfield of a field within this record. + * + * @param pszField The name of the field containing the subfield. + * @param iFieldIndex The instance of this field within the record. Use + * zero for the first instance of this field. + * @param pszSubfield The name of the subfield within the selected field. + * @param iSubfieldIndex The instance of this subfield within the record. + * Use zero for the first instance. + * @param pnSuccess Pointer to an int which will be set to true if the fetch + * succeeds, or false if it fails. Use NULL if you don't want to check + * success. + * @return The value of the subfield, or zero if it failed for some reason. + */ + +int ossimDDFRecord::GetIntSubfield( const char * pszField, int iFieldIndex, + const char * pszSubfield, int iSubfieldIndex, + int * pnSuccess ) + +{ + ossimDDFField *poField; + int nDummyErr; + + if( pnSuccess == NULL ) + pnSuccess = &nDummyErr; + + *pnSuccess = false; + +/* -------------------------------------------------------------------- */ +/* Fetch the field. If this fails, return zero. */ +/* -------------------------------------------------------------------- */ + poField = FindField( pszField, iFieldIndex ); + if( poField == NULL ) + return 0; + +/* -------------------------------------------------------------------- */ +/* Get the subfield definition */ +/* -------------------------------------------------------------------- */ + ossimDDFSubfieldDefn *poSFDefn; + + poSFDefn = poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield ); + if( poSFDefn == NULL ) + return 0; + +/* -------------------------------------------------------------------- */ +/* Get a pointer to the data. */ +/* -------------------------------------------------------------------- */ + int nBytesRemaining; + + const char *pachData = poField->GetSubfieldData(poSFDefn, + &nBytesRemaining, + iSubfieldIndex); + +/* -------------------------------------------------------------------- */ +/* Return the extracted value. */ +/* -------------------------------------------------------------------- */ + *pnSuccess = true; + + return( poSFDefn->ExtractIntData( pachData, nBytesRemaining, NULL ) ); +} + +/************************************************************************/ +/* GetFloatSubfield() */ +/************************************************************************/ + +/** + * Fetch value of a subfield as a float (double). This is a convenience + * function for fetching a subfield of a field within this record. + * + * @param pszField The name of the field containing the subfield. + * @param iFieldIndex The instance of this field within the record. Use + * zero for the first instance of this field. + * @param pszSubfield The name of the subfield within the selected field. + * @param iSubfieldIndex The instance of this subfield within the record. + * Use zero for the first instance. + * @param pnSuccess Pointer to an int which will be set to true if the fetch + * succeeds, or false if it fails. Use NULL if you don't want to check + * success. + * @return The value of the subfield, or zero if it failed for some reason. + */ + +double ossimDDFRecord::GetFloatSubfield( const char * pszField, int iFieldIndex, + const char * pszSubfield, int iSubfieldIndex, + int * pnSuccess ) + +{ + ossimDDFField *poField; + int nDummyErr; + + if( pnSuccess == NULL ) + pnSuccess = &nDummyErr; + + *pnSuccess = false; + +/* -------------------------------------------------------------------- */ +/* Fetch the field. If this fails, return zero. */ +/* -------------------------------------------------------------------- */ + poField = FindField( pszField, iFieldIndex ); + if( poField == NULL ) + return 0; + +/* -------------------------------------------------------------------- */ +/* Get the subfield definition */ +/* -------------------------------------------------------------------- */ + ossimDDFSubfieldDefn *poSFDefn; + + poSFDefn = poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield ); + if( poSFDefn == NULL ) + return 0; + +/* -------------------------------------------------------------------- */ +/* Get a pointer to the data. */ +/* -------------------------------------------------------------------- */ + int nBytesRemaining; + + const char *pachData = poField->GetSubfieldData(poSFDefn, + &nBytesRemaining, + iSubfieldIndex); + +/* -------------------------------------------------------------------- */ +/* Return the extracted value. */ +/* -------------------------------------------------------------------- */ + *pnSuccess = true; + + return( poSFDefn->ExtractFloatData( pachData, nBytesRemaining, NULL ) ); +} + +/************************************************************************/ +/* GetStringSubfield() */ +/************************************************************************/ + +/** + * Fetch value of a subfield as a string. This is a convenience + * function for fetching a subfield of a field within this record. + * + * @param pszField The name of the field containing the subfield. + * @param iFieldIndex The instance of this field within the record. Use + * zero for the first instance of this field. + * @param pszSubfield The name of the subfield within the selected field. + * @param iSubfieldIndex The instance of this subfield within the record. + * Use zero for the first instance. + * @param pnSuccess Pointer to an int which will be set to true if the fetch + * succeeds, or false if it fails. Use NULL if you don't want to check + * success. + * @return The value of the subfield, or NULL if it failed for some reason. + * The returned pointer is to internal data and should not be modified or + * freed by the application. + */ + +const char * +ossimDDFRecord::GetStringSubfield( const char * pszField, int iFieldIndex, + const char * pszSubfield, int iSubfieldIndex, + int * pnSuccess ) + +{ + ossimDDFField *poField; + int nDummyErr; + + if( pnSuccess == NULL ) + pnSuccess = &nDummyErr; + + *pnSuccess = false; + +/* -------------------------------------------------------------------- */ +/* Fetch the field. If this fails, return zero. */ +/* -------------------------------------------------------------------- */ + poField = FindField( pszField, iFieldIndex ); + if( poField == NULL ) + return NULL; + +/* -------------------------------------------------------------------- */ +/* Get the subfield definition */ +/* -------------------------------------------------------------------- */ + ossimDDFSubfieldDefn *poSFDefn; + + poSFDefn = poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield ); + if( poSFDefn == NULL ) + return NULL; + +/* -------------------------------------------------------------------- */ +/* Get a pointer to the data. */ +/* -------------------------------------------------------------------- */ + int nBytesRemaining; + + const char *pachData = poField->GetSubfieldData(poSFDefn, + &nBytesRemaining, + iSubfieldIndex); + +/* -------------------------------------------------------------------- */ +/* Return the extracted value. */ +/* -------------------------------------------------------------------- */ + *pnSuccess = true; + + return( poSFDefn->ExtractStringData( pachData, nBytesRemaining, NULL ) ); +} + +/************************************************************************/ +/* Clone() */ +/************************************************************************/ + +/** + * Make a copy of a record. + * + * This method is used to make a copy of a record that will become (mostly) + * the properly of application. However, it is automatically destroyed if + * the DDFModule it was created relative to is destroyed, as it's field + * and subfield definitions relate to that DDFModule. However, it does + * persist even when the record returned by DDFModule::ReadRecord() is + * invalidated, such as when reading a new record. This allows an application + * to cache whole DDFRecords. + * + * @return A new copy of the DDFRecord. This can be delete'd by the + * application when no longer needed, otherwise it will be cleaned up when + * the DDFModule it relates to is destroyed or closed. + */ + +ossimDDFRecord * ossimDDFRecord::Clone() + +{ + ossimDDFRecord *poNR; + + poNR = new ossimDDFRecord( poModule ); + + poNR->nReuseHeader = false; + poNR->nFieldOffset = nFieldOffset; + + poNR->nDataSize = nDataSize; + poNR->pachData = (char *) malloc(nDataSize); + memcpy( poNR->pachData, pachData, nDataSize ); + + poNR->nFieldCount = nFieldCount; + poNR->paoFields = new ossimDDFField[nFieldCount]; + for( int i = 0; i < nFieldCount; i++ ) + { + int nOffset; + + nOffset = (paoFields[i].GetData() - pachData); + poNR->paoFields[i].Initialize( paoFields[i].GetFieldDefn(), + poNR->pachData + nOffset, + paoFields[i].GetDataSize() ); + } + + poNR->bIsClone = true; + poModule->AddCloneRecord( poNR ); + + return poNR; +} + +/************************************************************************/ +/* CloneOn() */ +/************************************************************************/ + +/** + * Recreate a record referencing another module. + * + * Works similarly to the DDFRecord::Clone() method, but creates the + * new record with reference to a different DDFModule. All DDFFieldDefn + * references are transcribed onto the new module based on field names. + * If any fields don't have a similarly named field on the target module + * the operation will fail. No validation of field types and properties + * is done, but this operation is intended only to be used between + * modules with matching definitions of all affected fields. + * + * The new record will be managed as a clone by the target module in + * a manner similar to regular clones. + * + * @param poTargetModule the module on which the record copy should be + * created. + * + * @return NULL on failure or a pointer to the cloned record. + */ + +ossimDDFRecord *ossimDDFRecord::CloneOn( ossimDDFModule *poTargetModule ) + +{ +/* -------------------------------------------------------------------- */ +/* Verify that all fields have a corresponding field definition */ +/* on the target module. */ +/* -------------------------------------------------------------------- */ + int i; + + for( i = 0; i < nFieldCount; i++ ) + { + ossimDDFFieldDefn *poDefn = paoFields[i].GetFieldDefn(); + + if( poTargetModule->FindFieldDefn( poDefn->GetName() ) == NULL ) + return NULL; + } + +/* -------------------------------------------------------------------- */ +/* Create a clone. */ +/* -------------------------------------------------------------------- */ + ossimDDFRecord *poClone; + + poClone = Clone(); + +/* -------------------------------------------------------------------- */ +/* Update all internal information to reference other module. */ +/* -------------------------------------------------------------------- */ + for( i = 0; i < nFieldCount; i++ ) + { + ossimDDFField *poField = poClone->paoFields+i; + ossimDDFFieldDefn *poDefn; + + poDefn = poTargetModule->FindFieldDefn( + poField->GetFieldDefn()->GetName() ); + + poField->Initialize( poDefn, poField->GetData(), + poField->GetDataSize() ); + } + + poModule->RemoveCloneRecord( poClone ); + poClone->poModule = poTargetModule; + poTargetModule->AddCloneRecord( poClone ); + + return poClone; +} + + +/************************************************************************/ +/* DeleteField() */ +/************************************************************************/ + +/** + * Delete a field instance from a record. + * + * Remove a field from this record, cleaning up the data + * portion and repacking the fields list. We don't try to + * reallocate the data area of the record to be smaller. + * + * NOTE: This method doesn't actually remove the header + * information for this field from the record tag list yet. + * This should be added if the resulting record is even to be + * written back to disk! + * + * @param poTarget the field instance on this record to delete. + * + * @return true on success, or false on failure. Failure can occur if + * poTarget isn't really a field on this record. + */ + +int ossimDDFRecord::DeleteField( ossimDDFField *poTarget ) + +{ + int iTarget, i; + +/* -------------------------------------------------------------------- */ +/* Find which field we are to delete. */ +/* -------------------------------------------------------------------- */ + for( iTarget = 0; iTarget < nFieldCount; iTarget++ ) + { + if( paoFields + iTarget == poTarget ) + break; + } + + if( iTarget == nFieldCount ) + return false; + +/* -------------------------------------------------------------------- */ +/* Change the target fields data size to zero. This takes care */ +/* of repacking the data array, and updating all the following */ +/* field data pointers. */ +/* -------------------------------------------------------------------- */ + ResizeField( poTarget, 0 ); + +/* -------------------------------------------------------------------- */ +/* remove the target field, moving down all the other fields */ +/* one step in the field list. */ +/* -------------------------------------------------------------------- */ + for( i = iTarget; i < nFieldCount-1; i++ ) + { + paoFields[i] = paoFields[i+1]; + } + + nFieldCount--; + + return true; +} + +/************************************************************************/ +/* ResizeField() */ +/************************************************************************/ + +/** + * Alter field data size within record. + * + * This method will rearrange a DDFRecord altering the amount of space + * reserved for one of the existing fields. All following fields will + * be shifted accordingly. This includes updating the DDFField infos, + * and actually moving stuff within the data array after reallocating + * to the desired size. + * + * @param poField the field to alter. + * @param nNewDataSize the number of data bytes to be reserved for the field. + * + * @return true on success or false on failure. + */ + +int ossimDDFRecord::ResizeField( ossimDDFField *poField, int nNewDataSize ) + +{ + int iTarget, i; + int nBytesToMove; + +/* -------------------------------------------------------------------- */ +/* Find which field we are to resize. */ +/* -------------------------------------------------------------------- */ + for( iTarget = 0; iTarget < nFieldCount; iTarget++ ) + { + if( paoFields + iTarget == poField ) + break; + } + + if( iTarget == nFieldCount ) + { + // CPLAssert( false ); + return false; + } + +/* -------------------------------------------------------------------- */ +/* Reallocate the data buffer accordingly. */ +/* -------------------------------------------------------------------- */ + int nBytesToAdd = nNewDataSize - poField->GetDataSize(); + const char *pachOldData = pachData; + + // Don't realloc things smaller ... we will cut off some data. + if( nBytesToAdd > 0 ) + pachData = (char *) ossimCPLRealloc(pachData, nDataSize + nBytesToAdd ); + + nDataSize += nBytesToAdd; + +/* -------------------------------------------------------------------- */ +/* How much data needs to be shifted up or down after this field? */ +/* -------------------------------------------------------------------- */ + nBytesToMove = nDataSize + - (poField->GetData()+poField->GetDataSize()-pachOldData+nBytesToAdd); + +/* -------------------------------------------------------------------- */ +/* Update fields to point into newly allocated buffer. */ +/* -------------------------------------------------------------------- */ + for( i = 0; i < nFieldCount; i++ ) + { + int nOffset; + + nOffset = paoFields[i].GetData() - pachOldData; + paoFields[i].Initialize( paoFields[i].GetFieldDefn(), + pachData + nOffset, + paoFields[i].GetDataSize() ); + } + +/* -------------------------------------------------------------------- */ +/* Shift the data beyond this field up or down as needed. */ +/* -------------------------------------------------------------------- */ + if( nBytesToMove > 0 ) + memmove( (char *)poField->GetData()+poField->GetDataSize()+nBytesToAdd, + (char *)poField->GetData()+poField->GetDataSize(), + nBytesToMove ); + +/* -------------------------------------------------------------------- */ +/* Update the target fields info. */ +/* -------------------------------------------------------------------- */ + poField->Initialize( poField->GetFieldDefn(), + poField->GetData(), + poField->GetDataSize() + nBytesToAdd ); + +/* -------------------------------------------------------------------- */ +/* Shift all following fields down, and update their data */ +/* locations. */ +/* -------------------------------------------------------------------- */ + if( nBytesToAdd < 0 ) + { + for( i = iTarget+1; i < nFieldCount; i++ ) + { + char *pszOldDataLocation; + + pszOldDataLocation = (char *) paoFields[i].GetData(); + + paoFields[i].Initialize( paoFields[i].GetFieldDefn(), + pszOldDataLocation + nBytesToAdd, + paoFields[i].GetDataSize() ); + } + } + else + { + for( i = nFieldCount-1; i > iTarget; i-- ) + { + char *pszOldDataLocation; + + pszOldDataLocation = (char *) paoFields[i].GetData(); + + paoFields[i].Initialize( paoFields[i].GetFieldDefn(), + pszOldDataLocation + nBytesToAdd, + paoFields[i].GetDataSize() ); + } + } + + return true; +} + +/************************************************************************/ +/* AddField() */ +/************************************************************************/ + +/** + * Add a new field to record. + * + * Add a new zero sized field to the record. The new field is always + * added at the end of the record. + * + * NOTE: This method doesn't currently update the header information for + * the record to include the field information for this field, so the + * resulting record image isn't suitable for writing to disk. However, + * everything else about the record state should be updated properly to + * reflect the new field. + * + * @param poDefn the definition of the field to be added. + * + * @return the field object on success, or NULL on failure. + */ + +ossimDDFField *ossimDDFRecord::AddField( ossimDDFFieldDefn *poDefn ) + +{ +/* -------------------------------------------------------------------- */ +/* Reallocate the fields array larger by one, and initialize */ +/* the new field. */ +/* -------------------------------------------------------------------- */ + ossimDDFField *paoNewFields; + + paoNewFields = new ossimDDFField[nFieldCount+1]; + if( nFieldCount > 0 ) + { + memcpy( paoNewFields, paoFields, sizeof(ossimDDFField) * nFieldCount ); + delete[] paoFields; + } + paoFields = paoNewFields; + nFieldCount++; + +/* -------------------------------------------------------------------- */ +/* Initialize the new field properly. */ +/* -------------------------------------------------------------------- */ + if( nFieldCount == 1 ) + { + paoFields[0].Initialize( poDefn, GetData(), 0 ); + } + else + { + paoFields[nFieldCount-1].Initialize( + poDefn, + paoFields[nFieldCount-2].GetData() + + paoFields[nFieldCount-2].GetDataSize(), + 0 ); + } + +/* -------------------------------------------------------------------- */ +/* Initialize field. */ +/* -------------------------------------------------------------------- */ + CreateDefaultFieldInstance( paoFields + nFieldCount-1, 0 ); + + return paoFields + (nFieldCount - 1); +} + +/************************************************************************/ +/* SetFieldRaw() */ +/************************************************************************/ + +/** + * Set the raw contents of a field instance. + * + * @param poField the field to set data within. + * @param iIndexWithinField The instance of this field to replace. Must + * be a value between 0 and GetRepeatCount(). If GetRepeatCount() is used, a + * new instance of the field is appeneded. + * @param pachRawData the raw data to replace this field instance with. + * @param nRawDataSize the number of bytes pointed to by pachRawData. + * + * @return true on success or false on failure. + */ + +int +ossimDDFRecord::SetFieldRaw( ossimDDFField *poField, int iIndexWithinField, + const char *pachRawData, int nRawDataSize ) + +{ + int iTarget, nRepeatCount; + +/* -------------------------------------------------------------------- */ +/* Find which field we are to update. */ +/* -------------------------------------------------------------------- */ + for( iTarget = 0; iTarget < nFieldCount; iTarget++ ) + { + if( paoFields + iTarget == poField ) + break; + } + + if( iTarget == nFieldCount ) + return false; + + nRepeatCount = poField->GetRepeatCount(); + + if( iIndexWithinField < 0 || iIndexWithinField > nRepeatCount ) + return false; + +/* -------------------------------------------------------------------- */ +/* Are we adding an instance? This is easier and different */ +/* than replacing an existing instance. */ +/* -------------------------------------------------------------------- */ + if( iIndexWithinField == nRepeatCount + || !poField->GetFieldDefn()->IsRepeating() ) + { + char *pachFieldData; + int nOldSize; + + if( !poField->GetFieldDefn()->IsRepeating() && iIndexWithinField != 0 ) + return false; + + nOldSize = poField->GetDataSize(); + if( nOldSize == 0 ) + nOldSize++; // for added DDF_FIELD_TERMINATOR. + + if( !ResizeField( poField, nOldSize + nRawDataSize ) ) + return false; + + pachFieldData = (char *) poField->GetData(); + memcpy( pachFieldData + nOldSize - 1, + pachRawData, nRawDataSize ); + pachFieldData[nOldSize+nRawDataSize-1] = OSSIM_DDF_FIELD_TERMINATOR; + + return true; + } + +/* -------------------------------------------------------------------- */ +/* Get a pointer to the start of the existing data for this */ +/* iteration of the field. */ +/* -------------------------------------------------------------------- */ + const char *pachWrkData; + int nInstanceSize; + + // We special case this to avoid alot of warnings when initializing + // the field the first time. + if( poField->GetDataSize() == 0 ) + { + pachWrkData = poField->GetData(); + nInstanceSize = 0; + } + else + { + pachWrkData = poField->GetInstanceData( iIndexWithinField, + &nInstanceSize ); + } + +/* -------------------------------------------------------------------- */ +/* Create new image of this whole field. */ +/* -------------------------------------------------------------------- */ + char *pachNewImage; + int nPreBytes, nPostBytes, nNewFieldSize; + + nNewFieldSize = poField->GetDataSize() - nInstanceSize + nRawDataSize; + + pachNewImage = (char *) malloc(nNewFieldSize); + + nPreBytes = pachWrkData - poField->GetData(); + nPostBytes = poField->GetDataSize() - nPreBytes - nInstanceSize; + + memcpy( pachNewImage, poField->GetData(), nPreBytes ); + memcpy( pachNewImage + nPreBytes + nRawDataSize, + poField->GetData() + nPreBytes + nInstanceSize, + nPostBytes ); + memcpy( pachNewImage + nPreBytes, pachRawData, nRawDataSize ); + +/* -------------------------------------------------------------------- */ +/* Resize the field to the desired new size. */ +/* -------------------------------------------------------------------- */ + ResizeField( poField, nNewFieldSize ); + + memcpy( (void *) poField->GetData(), pachNewImage, nNewFieldSize ); + free( pachNewImage ); + + return true; +} + +/************************************************************************/ +/* UpdateFieldRaw() */ +/************************************************************************/ + +int +ossimDDFRecord::UpdateFieldRaw( ossimDDFField *poField, int iIndexWithinField, + int nStartOffset, int nOldSize, + const char *pachRawData, int nRawDataSize ) + +{ + int iTarget, nRepeatCount; + +/* -------------------------------------------------------------------- */ +/* Find which field we are to update. */ +/* -------------------------------------------------------------------- */ + for( iTarget = 0; iTarget < nFieldCount; iTarget++ ) + { + if( paoFields + iTarget == poField ) + break; + } + + if( iTarget == nFieldCount ) + return false; + + nRepeatCount = poField->GetRepeatCount(); + + if( iIndexWithinField < 0 || iIndexWithinField >= nRepeatCount ) + return false; + +/* -------------------------------------------------------------------- */ +/* Figure out how much pre and post data there is. */ +/* -------------------------------------------------------------------- */ + char *pachWrkData; + int nInstanceSize, nPostBytes, nPreBytes; + + pachWrkData = (char *) poField->GetInstanceData( iIndexWithinField, + &nInstanceSize ); + nPreBytes = pachWrkData - poField->GetData() + nStartOffset; + nPostBytes = poField->GetDataSize() - nPreBytes - nOldSize; + +/* -------------------------------------------------------------------- */ +/* If we aren't changing the size, just copy over the existing */ +/* data. */ +/* -------------------------------------------------------------------- */ + if( nOldSize == nRawDataSize ) + { + memcpy( pachWrkData + nStartOffset, pachRawData, nRawDataSize ); + return true; + } + +/* -------------------------------------------------------------------- */ +/* If we are shrinking, move in the new data, and shuffle down */ +/* the old before resizing. */ +/* -------------------------------------------------------------------- */ + if( nRawDataSize < nOldSize ) + { + memcpy( ((char*) poField->GetData()) + nPreBytes, + pachRawData, nRawDataSize ); + memmove( ((char *) poField->GetData()) + nPreBytes + nRawDataSize, + ((char *) poField->GetData()) + nPreBytes + nOldSize, + nPostBytes ); + } + +/* -------------------------------------------------------------------- */ +/* Resize the whole buffer. */ +/* -------------------------------------------------------------------- */ + if( !ResizeField( poField, + poField->GetDataSize() - nOldSize + nRawDataSize ) ) + return false; + +/* -------------------------------------------------------------------- */ +/* If we growing the buffer, shuffle up the post data, and */ +/* move in our new values. */ +/* -------------------------------------------------------------------- */ + if( nRawDataSize >= nOldSize ) + { + memmove( ((char *) poField->GetData()) + nPreBytes + nRawDataSize, + ((char *) poField->GetData()) + nPreBytes + nOldSize, + nPostBytes ); + memcpy( ((char*) poField->GetData()) + nPreBytes, + pachRawData, nRawDataSize ); + } + + return true; +} + +/************************************************************************/ +/* ResetDirectory() */ +/* */ +/* Re-prepares the directory information for the record. */ +/************************************************************************/ + +int ossimDDFRecord::ResetDirectory() + +{ + int iField; + +/* -------------------------------------------------------------------- */ +/* Eventually we should try to optimize the size of offset and */ +/* field length. For now we will use 5 for each which is */ +/* pretty big. */ +/* -------------------------------------------------------------------- */ + _sizeFieldPos = 5; + _sizeFieldLength = 5; + +/* -------------------------------------------------------------------- */ +/* Compute how large the directory needs to be. */ +/* -------------------------------------------------------------------- */ + int nEntrySize, nDirSize; + + nEntrySize = _sizeFieldPos + _sizeFieldLength + _sizeFieldTag; + nDirSize = nEntrySize * nFieldCount + 1; + +/* -------------------------------------------------------------------- */ +/* If the directory size is different than what is currently */ +/* reserved for it, we must resize. */ +/* -------------------------------------------------------------------- */ + if( nDirSize != nFieldOffset ) + { + char *pachNewData; + int nNewDataSize; + + nNewDataSize = nDataSize - nFieldOffset + nDirSize; + pachNewData = (char *) malloc(nNewDataSize); + memcpy( pachNewData + nDirSize, + pachData + nFieldOffset, + nNewDataSize - nDirSize ); + + for( iField = 0; iField < nFieldCount; iField++ ) + { + int nOffset; + ossimDDFField *poField = GetField( iField ); + + nOffset = poField->GetData() - pachData - nFieldOffset + nDirSize; + poField->Initialize( poField->GetFieldDefn(), + pachNewData + nOffset, + poField->GetDataSize() ); + } + + free( pachData ); + pachData = pachNewData; + nDataSize = nNewDataSize; + nFieldOffset = nDirSize; + } + +/* -------------------------------------------------------------------- */ +/* Now set each directory entry. */ +/* -------------------------------------------------------------------- */ + for( iField = 0; iField < nFieldCount; iField++ ) + { + ossimDDFField *poField = GetField( iField ); + ossimDDFFieldDefn *poDefn = poField->GetFieldDefn(); + char szFormat[128]; + + sprintf( szFormat, "%%%ds%%0%dd%%0%dd", + _sizeFieldTag, _sizeFieldLength, _sizeFieldPos ); + + sprintf( pachData + nEntrySize * iField, szFormat, + poDefn->GetName(), poField->GetDataSize(), + poField->GetData() - pachData - nFieldOffset ); + } + + pachData[nEntrySize * nFieldCount] = OSSIM_DDF_FIELD_TERMINATOR; + + return true; +} + +/************************************************************************/ +/* CreateDefaultFieldInstance() */ +/************************************************************************/ + +/** + * Initialize default instance. + * + * This method is normally only used internally by the AddField() method + * to initialize the new field instance with default subfield values. It + * installs default data for one instance of the field in the record + * using the DDFFieldDefn::GetDefaultValue() method and + * DDFRecord::SetFieldRaw(). + * + * @param poField the field within the record to be assign a default + * instance. + * @param iIndexWithinField the instance to set (may not have been tested with + * values other than 0). + * + * @return true on success or false on failure. + */ + +int ossimDDFRecord::CreateDefaultFieldInstance( ossimDDFField *poField, + int iIndexWithinField ) + +{ + int nRawSize, nSuccess; + char *pachRawData; + + pachRawData = poField->GetFieldDefn()->GetDefaultValue( &nRawSize ); + if( pachRawData == NULL ) + return false; + + nSuccess = SetFieldRaw( poField, iIndexWithinField, pachRawData, nRawSize); + + free( pachRawData ); + + return nSuccess; +} + +/************************************************************************/ +/* SetStringSubfield() */ +/************************************************************************/ + +/** + * Set a string subfield in record. + * + * The value of a given subfield is replaced with a new string value + * formatted appropriately. + * + * @param pszField the field name to operate on. + * @param iFieldIndex the field index to operate on (zero based). + * @param pszSubfield the subfield name to operate on. + * @param iSubfieldIndex the subfield index to operate on (zero based). + * @param pszValue the new string to place in the subfield. This may be + * arbitrary binary bytes if nValueLength is specified. + * @param nValueLength the number of valid bytes in pszValue, may be -1 to + * internally fetch with strlen(). + * + * @return true if successful, and false if not. + */ + +int ossimDDFRecord::SetStringSubfield( const char *pszField, int iFieldIndex, + const char *pszSubfield, int iSubfieldIndex, + const char *pszValue, int nValueLength ) + +{ +/* -------------------------------------------------------------------- */ +/* Fetch the field. If this fails, return zero. */ +/* -------------------------------------------------------------------- */ + ossimDDFField *poField; + + poField = FindField( pszField, iFieldIndex ); + if( poField == NULL ) + return false; + +/* -------------------------------------------------------------------- */ +/* Get the subfield definition */ +/* -------------------------------------------------------------------- */ + ossimDDFSubfieldDefn *poSFDefn; + + poSFDefn = poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield ); + if( poSFDefn == NULL ) + return false; + +/* -------------------------------------------------------------------- */ +/* How long will the formatted value be? */ +/* -------------------------------------------------------------------- */ + int nFormattedLen; + + if( !poSFDefn->FormatStringValue( NULL, 0, &nFormattedLen, pszValue, + nValueLength ) ) + return false; + +/* -------------------------------------------------------------------- */ +/* Get a pointer to the data. */ +/* -------------------------------------------------------------------- */ + int nMaxBytes; + char *pachSubfieldData = (char *) + poField->GetSubfieldData(poSFDefn, &nMaxBytes, + iSubfieldIndex); + +/* -------------------------------------------------------------------- */ +/* Add new instance if we have run out of data. */ +/* -------------------------------------------------------------------- */ + if( nMaxBytes == 0 + || (nMaxBytes == 1 && pachSubfieldData[0] == OSSIM_DDF_FIELD_TERMINATOR) ) + { + CreateDefaultFieldInstance( poField, iSubfieldIndex ); + + // Refetch. + pachSubfieldData = (char *) + poField->GetSubfieldData(poSFDefn, &nMaxBytes, + iSubfieldIndex); + } + +/* -------------------------------------------------------------------- */ +/* If the new length matches the existing length, just overlay */ +/* and return. */ +/* -------------------------------------------------------------------- */ + int nExistingLength; + + poSFDefn->GetDataLength( pachSubfieldData, nMaxBytes, &nExistingLength ); + + if( nExistingLength == nFormattedLen ) + { + return poSFDefn->FormatStringValue( pachSubfieldData, nFormattedLen, + NULL, pszValue, nValueLength ); + } + +/* -------------------------------------------------------------------- */ +/* We will need to resize the raw data. */ +/* -------------------------------------------------------------------- */ + const char *pachFieldInstData; + int nInstanceSize, nStartOffset, nSuccess; + char *pachNewData; + + pachFieldInstData = poField->GetInstanceData( iFieldIndex, + &nInstanceSize ); + + nStartOffset = pachSubfieldData - pachFieldInstData; + + pachNewData = (char *) malloc(nFormattedLen); + poSFDefn->FormatStringValue( pachNewData, nFormattedLen, NULL, + pszValue, nValueLength ); + + nSuccess = UpdateFieldRaw( poField, iFieldIndex, + nStartOffset, nExistingLength, + pachNewData, nFormattedLen ); + + free( pachNewData ); + + return nSuccess; +} + +/************************************************************************/ +/* SetIntSubfield() */ +/************************************************************************/ + +/** + * Set an integer subfield in record. + * + * The value of a given subfield is replaced with a new integer value + * formatted appropriately. + * + * @param pszField the field name to operate on. + * @param iFieldIndex the field index to operate on (zero based). + * @param pszSubfield the subfield name to operate on. + * @param iSubfieldIndex the subfield index to operate on (zero based). + * @param nNewValue the new value to place in the subfield. + * + * @return true if successful, and false if not. + */ + +int ossimDDFRecord::SetIntSubfield( const char *pszField, int iFieldIndex, + const char *pszSubfield, int iSubfieldIndex, + int nNewValue ) + +{ +/* -------------------------------------------------------------------- */ +/* Fetch the field. If this fails, return zero. */ +/* -------------------------------------------------------------------- */ + ossimDDFField *poField; + + poField = FindField( pszField, iFieldIndex ); + if( poField == NULL ) + return false; + +/* -------------------------------------------------------------------- */ +/* Get the subfield definition */ +/* -------------------------------------------------------------------- */ + ossimDDFSubfieldDefn *poSFDefn; + + poSFDefn = poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield ); + if( poSFDefn == NULL ) + return false; + +/* -------------------------------------------------------------------- */ +/* How long will the formatted value be? */ +/* -------------------------------------------------------------------- */ + int nFormattedLen; + + if( !poSFDefn->FormatIntValue( NULL, 0, &nFormattedLen, nNewValue ) ) + return false; + +/* -------------------------------------------------------------------- */ +/* Get a pointer to the data. */ +/* -------------------------------------------------------------------- */ + int nMaxBytes; + char *pachSubfieldData = (char *) + poField->GetSubfieldData(poSFDefn, &nMaxBytes, + iSubfieldIndex); + +/* -------------------------------------------------------------------- */ +/* Add new instance if we have run out of data. */ +/* -------------------------------------------------------------------- */ + if( nMaxBytes == 0 + || (nMaxBytes == 1 && pachSubfieldData[0] == OSSIM_DDF_FIELD_TERMINATOR) ) + { + CreateDefaultFieldInstance( poField, iSubfieldIndex ); + + // Refetch. + pachSubfieldData = (char *) + poField->GetSubfieldData(poSFDefn, &nMaxBytes, + iSubfieldIndex); + } + +/* -------------------------------------------------------------------- */ +/* If the new length matches the existing length, just overlay */ +/* and return. */ +/* -------------------------------------------------------------------- */ + int nExistingLength; + + poSFDefn->GetDataLength( pachSubfieldData, nMaxBytes, &nExistingLength ); + + if( nExistingLength == nFormattedLen ) + { + return poSFDefn->FormatIntValue( pachSubfieldData, nFormattedLen, + NULL, nNewValue ); + } + +/* -------------------------------------------------------------------- */ +/* We will need to resize the raw data. */ +/* -------------------------------------------------------------------- */ + const char *pachFieldInstData; + int nInstanceSize, nStartOffset, nSuccess; + char *pachNewData; + + pachFieldInstData = poField->GetInstanceData( iFieldIndex, + &nInstanceSize ); + + nStartOffset = pachSubfieldData - pachFieldInstData; + + pachNewData = (char *) malloc(nFormattedLen); + poSFDefn->FormatIntValue( pachNewData, nFormattedLen, NULL, + nNewValue ); + + nSuccess = UpdateFieldRaw( poField, iFieldIndex, + nStartOffset, nExistingLength, + pachNewData, nFormattedLen ); + + free( pachNewData ); + + return nSuccess; +} + +/************************************************************************/ +/* SetFloatSubfield() */ +/************************************************************************/ + +/** + * Set a float subfield in record. + * + * The value of a given subfield is replaced with a new float value + * formatted appropriately. + * + * @param pszField the field name to operate on. + * @param iFieldIndex the field index to operate on (zero based). + * @param pszSubfield the subfield name to operate on. + * @param iSubfieldIndex the subfield index to operate on (zero based). + * @param dfNewValue the new value to place in the subfield. + * + * @return true if successful, and false if not. + */ + +int ossimDDFRecord::SetFloatSubfield( const char *pszField, int iFieldIndex, + const char *pszSubfield, int iSubfieldIndex, + double dfNewValue ) + +{ +/* -------------------------------------------------------------------- */ +/* Fetch the field. If this fails, return zero. */ +/* -------------------------------------------------------------------- */ + ossimDDFField *poField; + + poField = FindField( pszField, iFieldIndex ); + if( poField == NULL ) + return false; + +/* -------------------------------------------------------------------- */ +/* Get the subfield definition */ +/* -------------------------------------------------------------------- */ + ossimDDFSubfieldDefn *poSFDefn; + + poSFDefn = poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield ); + if( poSFDefn == NULL ) + return false; + +/* -------------------------------------------------------------------- */ +/* How long will the formatted value be? */ +/* -------------------------------------------------------------------- */ + int nFormattedLen; + + if( !poSFDefn->FormatFloatValue( NULL, 0, &nFormattedLen, dfNewValue ) ) + return false; + +/* -------------------------------------------------------------------- */ +/* Get a pointer to the data. */ +/* -------------------------------------------------------------------- */ + int nMaxBytes; + char *pachSubfieldData = (char *) + poField->GetSubfieldData(poSFDefn, &nMaxBytes, + iSubfieldIndex); + +/* -------------------------------------------------------------------- */ +/* Add new instance if we have run out of data. */ +/* -------------------------------------------------------------------- */ + if( nMaxBytes == 0 || + (nMaxBytes == 1 && pachSubfieldData[0] == OSSIM_DDF_FIELD_TERMINATOR) ) + { + CreateDefaultFieldInstance( poField, iSubfieldIndex ); + + // Refetch. + pachSubfieldData = (char *) + poField->GetSubfieldData(poSFDefn, &nMaxBytes, + iSubfieldIndex); + } + +/* -------------------------------------------------------------------- */ +/* If the new length matches the existing length, just overlay */ +/* and return. */ +/* -------------------------------------------------------------------- */ + int nExistingLength; + + poSFDefn->GetDataLength( pachSubfieldData, nMaxBytes, &nExistingLength ); + + if( nExistingLength == nFormattedLen ) + { + return poSFDefn->FormatFloatValue( pachSubfieldData, nFormattedLen, + NULL, dfNewValue ); + } + +/* -------------------------------------------------------------------- */ +/* We will need to resize the raw data. */ +/* -------------------------------------------------------------------- */ + const char *pachFieldInstData; + int nInstanceSize, nStartOffset, nSuccess; + char *pachNewData; + + pachFieldInstData = poField->GetInstanceData( iFieldIndex, + &nInstanceSize ); + + nStartOffset = (int) (pachSubfieldData - pachFieldInstData); + + pachNewData = (char *) malloc(nFormattedLen); + poSFDefn->FormatFloatValue( pachNewData, nFormattedLen, NULL, + dfNewValue ); + + nSuccess = UpdateFieldRaw( poField, iFieldIndex, + nStartOffset, nExistingLength, + pachNewData, nFormattedLen ); + + free( pachNewData ); + + return nSuccess; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimDdfsubfielddefn.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimDdfsubfielddefn.cpp new file mode 100644 index 0000000000..179e4c45a4 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimDdfsubfielddefn.cpp @@ -0,0 +1,950 @@ +/****************************************************************************** + * Copied from "gdal" project. See licence below. + * + * Project: ISO 8211 Access + * Purpose: Implements the DDFSubfieldDefn class. + * Author: Frank Warmerdam, warmerda@home.com + * + ****************************************************************************** + * Copyright (c) 1999, Frank Warmerdam + * + * 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 above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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. + ****************************************************************************** + * $Id: ossimDdfsubfielddefn.cpp,v 1.3 2005/10/17 18:42:27 gpotts Exp $ + */ + +#include <imaging/formats/adrg/ossimIso8211.h> +#include <base/context/ossimNotifyContext.h> +#include <base/common/ossimCommon.h> + +/************************************************************************/ +/* DDFSubfieldDefn() */ +/************************************************************************/ + +ossimDDFSubfieldDefn::ossimDDFSubfieldDefn() + +{ + pszName = NULL; + + bIsVariable = true; + nFormatWidth = 0; + chFormatDelimeter = OSSIM_DDF_UNIT_TERMINATOR; + eBinaryFormat = NotBinary; + eType = DDFString; + + pszFormatString = strdup(""); + + nMaxBufChars = 0; + pachBuffer = NULL; +} + +/************************************************************************/ +/* ~DDFSubfieldDefn() */ +/************************************************************************/ + +ossimDDFSubfieldDefn::~ossimDDFSubfieldDefn() + +{ + free( pszName ); + free( pszFormatString ); + free( pachBuffer ); +} + +/************************************************************************/ +/* SetName() */ +/************************************************************************/ + +void ossimDDFSubfieldDefn::SetName( const char * pszNewName ) + +{ + int i; + + free( pszName ); + + pszName = strdup( pszNewName ); + + for( i = strlen(pszName)-1; i > 0 && pszName[i] == ' '; i-- ) + pszName[i] = '\0'; +} + +/************************************************************************/ +/* SetFormat() */ +/* */ +/* While interpreting the format string we don't support: */ +/* */ +/* o Passing an explicit terminator for variable length field. */ +/* o 'X' for unused data ... this should really be filtered */ +/* out by DDFFieldDefn::ApplyFormats(), but isn't. */ +/* o 'B' bitstrings that aren't a multiple of eight. */ +/************************************************************************/ + +int ossimDDFSubfieldDefn::SetFormat( const char * pszFormat ) + +{ + free( pszFormatString ); + pszFormatString = strdup( pszFormat ); + +/* -------------------------------------------------------------------- */ +/* These values will likely be used. */ +/* -------------------------------------------------------------------- */ + if( pszFormatString[1] == '(' ) + { + nFormatWidth = atoi(pszFormatString+2); + bIsVariable = nFormatWidth == 0; + } + else + bIsVariable = true; + +/* -------------------------------------------------------------------- */ +/* Interpret the format string. */ +/* -------------------------------------------------------------------- */ + switch( pszFormatString[0] ) + { + case 'A': + case 'C': // It isn't clear to me how this is different than 'A' + eType = DDFString; + break; + + case 'R': + eType = DDFFloat; + break; + + case 'I': + case 'S': + eType = DDFInt; + break; + + case 'B': + case 'b': + // Is the width expressed in bits? (is it a bitstring) + bIsVariable = false; + if( pszFormatString[1] == '(' ) + { + // CPLAssert( atoi(pszFormatString+2) % 8 == 0 ); + + nFormatWidth = atoi(pszFormatString+2) / 8; + eBinaryFormat = SInt; // good default, works for SDTS. + + if( nFormatWidth < 5 ) + eType = DDFInt; + else + eType = DDFBinaryString; + } + + // or do we have a binary type indicator? (is it binary) + else + { + eBinaryFormat = (DDFBinaryFormat) (pszFormatString[1] - '0'); + nFormatWidth = atoi(pszFormatString+2); + + if( eBinaryFormat == SInt || eBinaryFormat == UInt ) + eType = DDFInt; + else + eType = DDFFloat; + } + break; + + case 'X': + // 'X' is extra space, and shouldn't be directly assigned to a + // subfield ... I haven't encountered it in use yet though. + ossimNotify(ossimNotifyLevel_WARN) + << "Format type of `%c' not supported.\n" + << pszFormatString[0] << std::endl; + + // CPLAssert( false ); + return false; + + default: + ossimNotify(ossimNotifyLevel_WARN) + << "Format type of `%c' not recognised.\n" + << pszFormatString[0] << std::endl; + + // CPLAssert( false ); + return false; + } + + return true; +} + +/************************************************************************/ +/* Dump() */ +/************************************************************************/ + +/** + * Write out subfield definition info to debugging file. + * + * A variety of information about this field definition is written to the + * give debugging file handle. + * + * @param fp The standard io file handle to write to. ie. stderr + */ + +void ossimDDFSubfieldDefn::Dump( FILE * fp ) + +{ + fprintf( fp, " DDFSubfieldDefn:\n" ); + fprintf( fp, " Label = `%s'\n", pszName ); + fprintf( fp, " FormatString = `%s'\n", pszFormatString ); +} + +/************************************************************************/ +/* GetDataLength() */ +/* */ +/* This method will scan for the end of a variable field. */ +/************************************************************************/ + +/** + * Scan for the end of variable length data. Given a pointer to the data + * for this subfield (from within a DDFRecord) this method will return the + * number of bytes which are data for this subfield. The number of bytes + * consumed as part of this field can also be fetched. This number may + * be one longer than the length if there is a terminator character + * used.<p> + * + * This method is mainly for internal use, or for applications which + * want the raw binary data to interpret themselves. Otherwise use one + * of ExtractStringData(), ExtractIntData() or ExtractFloatData(). + * + * @param pachSourceData The pointer to the raw data for this field. This + * may have come from DDFRecord::GetData(), taking into account skip factors + * over previous subfields data. + * @param nMaxBytes The maximum number of bytes that are accessable after + * pachSourceData. + * @param pnConsumedBytes Pointer to an integer into which the number of + * bytes consumed by this field should be written. May be NULL to ignore. + * + * @return The number of bytes at pachSourceData which are actual data for + * this record (not including unit, or field terminator). + */ + +int ossimDDFSubfieldDefn::GetDataLength( const char * pachSourceData, + int nMaxBytes, int * pnConsumedBytes ) + +{ + if( !bIsVariable ) + { + if( nFormatWidth > nMaxBytes ) + { + ossimNotify(ossimNotifyLevel_WARN) + << "Only %d bytes available for subfield %s with\n" + << "format string %s ... returning shortened data." + << nMaxBytes << pszName << pszFormatString << std::endl; + + if( pnConsumedBytes != NULL ) + *pnConsumedBytes = nMaxBytes; + + return nMaxBytes; + } + else + { + if( pnConsumedBytes != NULL ) + *pnConsumedBytes = nFormatWidth; + + return nFormatWidth; + } + } + else + { + int nLength = 0; + int bCheckFieldTerminator = true; + + /* We only check for the field terminator because of some buggy + * datasets with missing format terminators. However, we have found + * the field terminator is a legal character within the fields of + * some extended datasets (such as JP34NC94.000). So we don't check + * for the field terminator if the field appears to be multi-byte + * which we established by the first character being out of the + * ASCII printable range (32-127). + */ + + if( pachSourceData[0] < 32 || pachSourceData[0] >= 127 ) + bCheckFieldTerminator = false; + + while( nLength < nMaxBytes + && pachSourceData[nLength] != chFormatDelimeter ) + { + if( bCheckFieldTerminator + && pachSourceData[nLength] == OSSIM_DDF_FIELD_TERMINATOR ) + break; + + nLength++; + } + + if( pnConsumedBytes != NULL ) + { + if( nMaxBytes == 0 ) + *pnConsumedBytes = nLength; + else + *pnConsumedBytes = nLength+1; + } + + return nLength; + } +} + +/************************************************************************/ +/* ExtractStringData() */ +/************************************************************************/ + +/** + * Extract a zero terminated string containing the data for this subfield. + * Given a pointer to the data + * for this subfield (from within a DDFRecord) this method will return the + * data for this subfield. The number of bytes + * consumed as part of this field can also be fetched. This number may + * be one longer than the string length if there is a terminator character + * used.<p> + * + * This function will return the raw binary data of a subfield for + * types other than DDFString, including data past zero chars. This is + * the standard way of extracting DDFBinaryString subfields for instance.<p> + * + * @param pachSourceData The pointer to the raw data for this field. This + * may have come from DDFRecord::GetData(), taking into account skip factors + * over previous subfields data. + * @param nMaxBytes The maximum number of bytes that are accessable after + * pachSourceData. + * @param pnConsumedBytes Pointer to an integer into which the number of + * bytes consumed by this field should be written. May be NULL to ignore. + * This is used as a skip factor to increment pachSourceData to point to the + * next subfields data. + * + * @return A pointer to a buffer containing the data for this field. The + * returned pointer is to an internal buffer which is invalidated on the + * next ExtractStringData() call on this DDFSubfieldDefn(). It should not + * be freed by the application. + * + * @see ExtractIntData(), ExtractFloatData() + */ + +const char * +ossimDDFSubfieldDefn::ExtractStringData( const char * pachSourceData, + int nMaxBytes, int * pnConsumedBytes ) + +{ + int nLength = GetDataLength( pachSourceData, nMaxBytes, + pnConsumedBytes ); + +/* -------------------------------------------------------------------- */ +/* Do we need to grow the buffer. */ +/* -------------------------------------------------------------------- */ + if( nMaxBufChars < nLength+1 ) + { + free( pachBuffer ); + + nMaxBufChars = nLength+1; + pachBuffer = (char *) malloc(nMaxBufChars); + } + +/* -------------------------------------------------------------------- */ +/* Copy the data to the buffer. We use memcpy() so that it */ +/* will work for binary data. */ +/* -------------------------------------------------------------------- */ + memcpy( pachBuffer, pachSourceData, nLength ); + pachBuffer[nLength] = '\0'; + + return pachBuffer; +} + +/************************************************************************/ +/* ExtractFloatData() */ +/************************************************************************/ + +/** + * Extract a subfield value as a float. Given a pointer to the data + * for this subfield (from within a DDFRecord) this method will return the + * floating point data for this subfield. The number of bytes + * consumed as part of this field can also be fetched. This method may be + * called for any type of subfield, and will return zero if the subfield is + * not numeric. + * + * @param pachSourceData The pointer to the raw data for this field. This + * may have come from DDFRecord::GetData(), taking into account skip factors + * over previous subfields data. + * @param nMaxBytes The maximum number of bytes that are accessable after + * pachSourceData. + * @param pnConsumedBytes Pointer to an integer into which the number of + * bytes consumed by this field should be written. May be NULL to ignore. + * This is used as a skip factor to increment pachSourceData to point to the + * next subfields data. + * + * @return The subfield's numeric value (or zero if it isn't numeric). + * + * @see ExtractIntData(), ExtractStringData() + */ + +double +ossimDDFSubfieldDefn::ExtractFloatData( const char * pachSourceData, + int nMaxBytes, int * pnConsumedBytes ) + +{ + switch( pszFormatString[0] ) + { + case 'A': + case 'I': + case 'R': + case 'S': + case 'C': + return atof(ExtractStringData(pachSourceData, nMaxBytes, + pnConsumedBytes)); + + case 'B': + case 'b': + { + unsigned char abyData[8]; + + // CPLAssert( nFormatWidth <= nMaxBytes ); + if( pnConsumedBytes != NULL ) + *pnConsumedBytes = nFormatWidth; + + // Byte swap the data if it isn't in machine native format. + // In any event we copy it into our buffer to ensure it is + // word aligned. +#ifdef CPL_LSB + if( pszFormatString[0] == 'B' ) +#else + if( pszFormatString[0] == 'b' ) +#endif + { + for( int i = 0; i < nFormatWidth; i++ ) + abyData[nFormatWidth-i-1] = pachSourceData[i]; + } + else + { + memcpy( abyData, pachSourceData, nFormatWidth ); + } + + // Interpret the bytes of data. + switch( eBinaryFormat ) + { + case UInt: + if( nFormatWidth == 1 ) + return( abyData[0] ); + else if( nFormatWidth == 2 ) + return( *((ossim_uint16 *) abyData) ); + else if( nFormatWidth == 4 ) + return( *((ossim_uint32 *) abyData) ); + else + { + // CPLAssert( false ); + return 0.0; + } + + case SInt: + if( nFormatWidth == 1 ) + return( *((signed char *) abyData) ); + else if( nFormatWidth == 2 ) + return( *((ossim_int16 *) abyData) ); + else if( nFormatWidth == 4 ) + return( *((ossim_int32 *) abyData) ); + else + { + // CPLAssert( false ); + return 0.0; + } + + case FloatReal: + if( nFormatWidth == 4 ) + return( *((float *) abyData) ); + else if( nFormatWidth == 8 ) + return( *((double *) abyData) ); + else + { + // CPLAssert( false ); + return 0.0; + } + + case NotBinary: + case FPReal: + case FloatComplex: + // CPLAssert( false ); + return 0.0; + } + break; + // end of 'b'/'B' case. + } + + default: + // CPLAssert( false ); + return 0.0; + } + + // CPLAssert( false ); + return 0.0; +} + +/************************************************************************/ +/* ExtractIntData() */ +/************************************************************************/ + +/** + * Extract a subfield value as an integer. Given a pointer to the data + * for this subfield (from within a DDFRecord) this method will return the + * int data for this subfield. The number of bytes + * consumed as part of this field can also be fetched. This method may be + * called for any type of subfield, and will return zero if the subfield is + * not numeric. + * + * @param pachSourceData The pointer to the raw data for this field. This + * may have come from DDFRecord::GetData(), taking into account skip factors + * over previous subfields data. + * @param nMaxBytes The maximum number of bytes that are accessable after + * pachSourceData. + * @param pnConsumedBytes Pointer to an integer into which the number of + * bytes consumed by this field should be written. May be NULL to ignore. + * This is used as a skip factor to increment pachSourceData to point to the + * next subfields data. + * + * @return The subfield's numeric value (or zero if it isn't numeric). + * + * @see ExtractFloatData(), ExtractStringData() + */ + +int +ossimDDFSubfieldDefn::ExtractIntData( const char * pachSourceData, + int nMaxBytes, int * pnConsumedBytes ) + +{ + switch( pszFormatString[0] ) + { + case 'A': + case 'I': + case 'R': + case 'S': + case 'C': + return atoi(ExtractStringData(pachSourceData, nMaxBytes, + pnConsumedBytes)); + + case 'B': + case 'b': + { + unsigned char abyData[8]; + + if( nFormatWidth > nMaxBytes ) + { + ossimNotify(ossimNotifyLevel_WARN) + << "Attempt to extract int subfield %s with format %s\n" + << "failed as only %d bytes available. Using zero." + << pszName << pszFormatString << nMaxBytes << std::endl; + return 0; + } + + if( pnConsumedBytes != NULL ) + *pnConsumedBytes = nFormatWidth; + + // Byte swap the data if it isn't in machine native format. + // In any event we copy it into our buffer to ensure it is + // word aligned. +#ifdef CPL_LSB + if( pszFormatString[0] == 'B' ) +#else + if( pszFormatString[0] == 'b' ) +#endif + { + for( int i = 0; i < nFormatWidth; i++ ) + abyData[nFormatWidth-i-1] = pachSourceData[i]; + } + else + { + memcpy( abyData, pachSourceData, nFormatWidth ); + } + + // Interpret the bytes of data. + switch( eBinaryFormat ) + { + case UInt: + if( nFormatWidth == 4 ) + return( (int) *((ossim_uint32 *) abyData) ); + else if( nFormatWidth == 1 ) + return( abyData[0] ); + else if( nFormatWidth == 2 ) + return( *((ossim_uint16 *) abyData) ); + else + { + // CPLAssert( false ); + return 0; + } + + case SInt: + if( nFormatWidth == 4 ) + return( *((ossim_int32 *) abyData) ); + else if( nFormatWidth == 1 ) + return( *((signed char *) abyData) ); + else if( nFormatWidth == 2 ) + return( *((ossim_int16 *) abyData) ); + else + { + // CPLAssert( false ); + return 0; + } + + case FloatReal: + if( nFormatWidth == 4 ) + return( (int) *((float *) abyData) ); + else if( nFormatWidth == 8 ) + return( (int) *((double *) abyData) ); + else + { + // CPLAssert( false ); + return 0; + } + + case NotBinary: + case FPReal: + case FloatComplex: + // CPLAssert( false ); + return 0; + } + break; + // end of 'b'/'B' case. + } + + default: + // CPLAssert( false ); + return 0; + } + + // CPLAssert( false ); + return 0; +} + +/************************************************************************/ +/* DumpData() */ +/* */ +/* Dump the instance data for this subfield from a data */ +/* record. This fits into the output dump stream of a DDFField. */ +/************************************************************************/ + +/** + * Dump subfield value to debugging file. + * + * @param pachData Pointer to data for this subfield. + * @param nMaxBytes Maximum number of bytes available in pachData. + * @param fp File to write report to. + */ + +void ossimDDFSubfieldDefn::DumpData( const char * pachData, int nMaxBytes, + FILE * fp ) + +{ + if( eType == DDFFloat ) + fprintf( fp, " Subfield `%s' = %f\n", + pszName, + ExtractFloatData( pachData, nMaxBytes, NULL ) ); + else if( eType == DDFInt ) + fprintf( fp, " Subfield `%s' = %d\n", + pszName, + ExtractIntData( pachData, nMaxBytes, NULL ) ); + else if( eType == DDFBinaryString ) + { + int nBytes, i; + ossim_uint8 *pabyBString = (ossim_uint8 *) ExtractStringData( pachData, nMaxBytes, &nBytes ); + + fprintf( fp, " Subfield `%s' = 0x", pszName ); + for( i = 0; i < MIN(nBytes,24); i++ ) + fprintf( fp, "%02X", pabyBString[i] ); + + if( nBytes > 24 ) + fprintf( fp, "%s", "..." ); + + fprintf( fp, "\n" ); + } + else + fprintf( fp, " Subfield `%s' = `%s'\n", + pszName, + ExtractStringData( pachData, nMaxBytes, NULL ) ); +} + +/************************************************************************/ +/* GetDefaultValue() */ +/************************************************************************/ + +/** + * Get default data. + * + * Returns the default subfield data contents for this subfield definition. + * For variable length numbers this will normally be "0<unit-terminator>". + * For variable length strings it will be "<unit-terminator>". For fixed + * length numbers it is zero filled. For fixed length strings it is space + * filled. For binary numbers it is binary zero filled. + * + * @param pachData the buffer into which the returned default will be placed. + * May be NULL if just querying default size. + * @param nBytesAvailable the size of pachData in bytes. + * @param pnBytesUsed will receive the size of the subfield default data in + * bytes. + * + * @return true on success or false on failure or if the passed buffer is too + * small to hold the default. + */ + +int ossimDDFSubfieldDefn::GetDefaultValue( char *pachData, int nBytesAvailable, + int *pnBytesUsed ) + +{ + int nDefaultSize; + + if( !bIsVariable ) + nDefaultSize = nFormatWidth; + else + nDefaultSize = 1; + + if( pnBytesUsed != NULL ) + *pnBytesUsed = nDefaultSize; + + if( pachData == NULL ) + return true; + + if( nBytesAvailable < nDefaultSize ) + return false; + + if( bIsVariable ) + { + pachData[0] = OSSIM_DDF_UNIT_TERMINATOR; + } + else + { + if( GetBinaryFormat() == NotBinary ) + { + if( GetType() == DDFInt || GetType() == DDFFloat ) + memset( pachData, '0', nDefaultSize ); + else + memset( pachData, ' ', nDefaultSize ); + } + else + memset( pachData, 0, nDefaultSize ); + } + + return true; +} + +/************************************************************************/ +/* FormatStringValue() */ +/************************************************************************/ + +/** + * Format string subfield value. + * + * Returns a buffer with the passed in string value reformatted in a way + * suitable for storage in a DDFField for this subfield. + */ + +int ossimDDFSubfieldDefn::FormatStringValue( char *pachData, int nBytesAvailable, + int *pnBytesUsed, + const char *pszValue, + int nValueLength ) + +{ + int nSize; + + if( nValueLength == -1 ) + nValueLength = strlen(pszValue); + + if( bIsVariable ) + { + nSize = nValueLength + 1; + } + else + { + nSize = nFormatWidth; + } + + if( pnBytesUsed != NULL ) + *pnBytesUsed = nSize; + + if( pachData == NULL ) + return true; + + if( nBytesAvailable < nSize ) + return false; + + if( bIsVariable ) + { + strncpy( pachData, pszValue, nSize-1 ); + pachData[nSize-1] = OSSIM_DDF_UNIT_TERMINATOR; + } + else + { + if( GetBinaryFormat() == NotBinary ) + { + memset( pachData, ' ', nSize ); + memcpy( pachData, pszValue, MIN(nValueLength,nSize) ); + } + else + { + memset( pachData, 0, nSize ); + memcpy( pachData, pszValue, MIN(nValueLength,nSize) ); + } + } + + return true; +} + +/************************************************************************/ +/* FormatIntValue() */ +/************************************************************************/ + +/** + * Format int subfield value. + * + * Returns a buffer with the passed in int value reformatted in a way + * suitable for storage in a DDFField for this subfield. + */ + +int ossimDDFSubfieldDefn::FormatIntValue( char *pachData, int nBytesAvailable, + int *pnBytesUsed, int nNewValue ) + +{ + int nSize; + char szWork[30]; + + sprintf( szWork, "%d", nNewValue ); + + if( bIsVariable ) + { + nSize = strlen(szWork) + 1; + } + else + { + nSize = nFormatWidth; + + if( GetBinaryFormat() == NotBinary && (int) strlen(szWork) > nSize ) + return false; + } + + if( pnBytesUsed != NULL ) + *pnBytesUsed = nSize; + + if( pachData == NULL ) + return true; + + if( nBytesAvailable < nSize ) + return false; + + if( bIsVariable ) + { + strncpy( pachData, szWork, nSize-1 ); + pachData[nSize-1] = OSSIM_DDF_UNIT_TERMINATOR; + } + else + { + ossim_uint32 nMask = 0xff; + int i; + + switch( GetBinaryFormat() ) + { + case NotBinary: + memset( pachData, '0', nSize ); + strncpy( pachData + nSize - strlen(szWork), szWork, + strlen(szWork) ); + break; + + case UInt: + case SInt: + for( i = 0; i < nFormatWidth; i++ ) + { + int iOut; + + // big endian required? + if( pszFormatString[0] == 'B' ) + iOut = nFormatWidth - i - 1; + else + iOut = i; + + pachData[iOut] = (nNewValue & nMask) >> (i*8); + nMask *= 256; + } + break; + + case FloatReal: + // CPLAssert( false ); + break; + + default: + // CPLAssert( false ); + break; + } + } + + return true; +} + +/************************************************************************/ +/* FormatFloatValue() */ +/************************************************************************/ + +/** + * Format float subfield value. + * + * Returns a buffer with the passed in float value reformatted in a way + * suitable for storage in a DDFField for this subfield. + */ + +int ossimDDFSubfieldDefn::FormatFloatValue( char *pachData, int nBytesAvailable, + int *pnBytesUsed, double dfNewValue ) + +{ + int nSize; + char szWork[120]; + + sprintf( szWork, "%.16g", dfNewValue ); + + if( bIsVariable ) + { + nSize = strlen(szWork) + 1; + } + else + { + nSize = nFormatWidth; + + if( GetBinaryFormat() == NotBinary && (int) strlen(szWork) > nSize ) + return false; + } + + if( pnBytesUsed != NULL ) + *pnBytesUsed = nSize; + + if( pachData == NULL ) + return true; + + if( nBytesAvailable < nSize ) + return false; + + if( bIsVariable ) + { + strncpy( pachData, szWork, nSize-1 ); + pachData[nSize-1] = OSSIM_DDF_UNIT_TERMINATOR; + } + else + { + if( GetBinaryFormat() == NotBinary ) + { + memset( pachData, '0', nSize ); + strncpy( pachData + nSize - strlen(szWork), szWork, + strlen(szWork) ); + } + else + { + // CPLAssert( false ); + /* implement me */ + } + } + + return true; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimDdfutils.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimDdfutils.cpp new file mode 100644 index 0000000000..f681a34cb4 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimDdfutils.cpp @@ -0,0 +1,101 @@ +/****************************************************************************** + * Copied from "gdal" project. See licence below. + * + * Project: ISO 8211 Access + * Purpose: Various utility functions. + * Author: Frank Warmerdam, warmerda@home.com + * + ****************************************************************************** + * Copyright (c) 1999, Frank Warmerdam + * + * 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 above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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. + ****************************************************************************** + * $Id: ossimDdfutils.cpp,v 1.2 2005/02/13 16:08:04 dburken Exp $ + */ + +#include <cstring> +#include <imaging/formats/adrg/ossimIso8211.h> + +/************************************************************************/ +/* DDFScanInt() */ +/* */ +/* Read up to nMaxChars from the passed string, and interpret */ +/* as an integer. */ +/************************************************************************/ + +long ossimDDFScanInt( const char * pszString, int nMaxChars ) + +{ + char szWorking[33]; + + if( nMaxChars > 32 || nMaxChars == 0 ) + nMaxChars = 32; + + memcpy( szWorking, pszString, nMaxChars ); + szWorking[nMaxChars] = '\0'; + + return( atoi(szWorking) ); +} + +/************************************************************************/ +/* DDFScanVariable() */ +/* */ +/* Establish the length of a variable length string in a */ +/* record. */ +/************************************************************************/ + +int ossimDDFScanVariable( const char *pszRecord, int nMaxChars, int nDelimChar ) + +{ + int i; + + for( i = 0; i < nMaxChars-1 && pszRecord[i] != nDelimChar; i++ ) {} + + return i; +} + +/************************************************************************/ +/* DDFFetchVariable() */ +/* */ +/* Fetch a variable length string from a record, and allocate */ +/* it as a new string (with CPLStrdup()). */ +/************************************************************************/ + +char * ossimDDFFetchVariable( const char *pszRecord, int nMaxChars, + int nDelimChar1, int nDelimChar2, + int *pnConsumedChars ) + +{ + int i; + char *pszReturn; + + for( i = 0; i < nMaxChars-1 && pszRecord[i] != nDelimChar1 + && pszRecord[i] != nDelimChar2; i++ ) {} + + *pnConsumedChars = i; + if( i < nMaxChars + && (pszRecord[i] == nDelimChar1 || pszRecord[i] == nDelimChar2) ) + (*pnConsumedChars)++; + + pszReturn = (char *) malloc(i+1); + pszReturn[i] = '\0'; + strncpy( pszReturn, pszRecord, i ); + + return pszReturn; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimIso8211.h b/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimIso8211.h new file mode 100644 index 0000000000..7714ebe270 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/adrg/ossimIso8211.h @@ -0,0 +1,527 @@ +/****************************************************************************** + * Copied from "gdal" project. See licence below. + * + * Project: ISO 8211 Access + * Purpose: Main declarations for ISO 8211. + * Author: Frank Warmerdam, warmerdam@pobox.com + * + ****************************************************************************** + * Copyright (c) 1999, Frank Warmerdam <warmerdam@pobox.com> + * + * 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 above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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. + ****************************************************************************** + * $Id: ossimIso8211.h,v 1.2 2005/02/13 16:08:04 dburken Exp $ + */ + +#ifndef ossimIso8211_HEADER +#define ossimIso8211_HEADER + +#include <cstdio> +#include <cstdlib> + + +/** + General data type + */ +typedef enum { + DDFInt, + DDFFloat, + DDFString, + DDFBinaryString +} DDFDataType; + +/************************************************************************/ +/* These should really be private to the library ... they are */ +/* mostly conveniences. */ +/************************************************************************/ + +long ossimDDFScanInt( const char *pszString, int nMaxChars ); +int ossimDDFScanVariable( const char * pszString, + int nMaxChars, int nDelimChar ); +char *ossimDDFFetchVariable( const char *pszString, int nMaxChars, + int nDelimChar1, int nDelimChar2, + int *pnConsumedChars ); + +#ifndef OSSIM_DDF_FIELD_TERMINATOR +# define OSSIM_DDF_FIELD_TERMINATOR 30 +#endif +#ifndef OSSIM_DDF_UNIT_TERMINATOR +# define OSSIM_DDF_UNIT_TERMINATOR 31 +#endif + +/************************************************************************/ +/* Predeclarations */ +/************************************************************************/ + +class ossimDDFFieldDefn; +class ossimDDFSubfieldDefn; +class ossimDDFRecord; +class ossimDDFField; + +/************************************************************************/ +/* DDFModule */ +/************************************************************************/ + +/** + The primary class for reading ISO 8211 files. This class contains all + the information read from the DDR record, and is used to read records + from the file. + +*/ + +class ossimDDFModule +{ + public: + ossimDDFModule(); + ~ossimDDFModule(); + + int Open( const char * pszFilename, int bFailQuietly = false ); + int Create( const char *pszFilename ); + void Close(); + + int Initialize( char chInterchangeLevel = '3', + char chLeaderIden = 'L', + char chCodeExtensionIndicator = 'E', + char chVersionNumber = '1', + char chAppIndicator = ' ', + const char *pszExtendedCharSet = " ! ", + int nSizeFieldLength = 3, + int nSizeFieldPos = 4, + int nSizeFieldTag = 4 ); + + void Dump( FILE * fp ); + + ossimDDFRecord *ReadRecord( void ); + void Rewind( long nOffset = -1 ); + + ossimDDFFieldDefn *FindFieldDefn( const char * ); + + /** Fetch the number of defined fields. */ + + int GetFieldCount() { return nFieldDefnCount; } + ossimDDFFieldDefn *GetField(int); + void AddField( ossimDDFFieldDefn *poNewFDefn ); + + // This is really just for internal use. + int GetFieldControlLength() { return _fieldControlLength; } + void AddCloneRecord( ossimDDFRecord * ); + void RemoveCloneRecord( ossimDDFRecord * ); + + // This is just for DDFRecord. + FILE *GetFP() { return fpDDF; } + + private: + FILE *fpDDF; + int bReadOnly; + long nFirstRecordOffset; + + char _interchangeLevel; + char _inlineCodeExtensionIndicator; + char _versionNumber; + char _appIndicator; + int _fieldControlLength; + char _extendedCharSet[4]; + + long _recLength; + char _leaderIden; + long _fieldAreaStart; + long _sizeFieldLength; + long _sizeFieldPos; + long _sizeFieldTag; + + // One DirEntry per field. + int nFieldDefnCount; + ossimDDFFieldDefn **papoFieldDefns; + + ossimDDFRecord *poRecord; + + int nCloneCount; + int nMaxCloneCount; + ossimDDFRecord **papoClones; +}; + +/************************************************************************/ +/* DDFFieldDefn */ +/************************************************************************/ + + typedef enum { dsc_elementary, dsc_vector, dsc_array, dsc_concatenated } DDF_data_struct_code; + typedef enum { dtc_char_string, + dtc_implicit_point, + dtc_explicit_point, + dtc_explicit_point_scaled, + dtc_char_bit_string, + dtc_bit_string, + dtc_mixed_data_type } DDF_data_type_code; + +/** + * Information from the DDR defining one field. Note that just because + * a field is defined for a DDFModule doesn't mean that it actually occurs + * on any records in the module. DDFFieldDefns are normally just significant + * as containers of the DDFSubfieldDefns. + */ + +class ossimDDFFieldDefn +{ + public: + ossimDDFFieldDefn(); + ~ossimDDFFieldDefn(); + + int Create( const char *pszTag, const char *pszFieldName, + const char *pszDescription, + DDF_data_struct_code eDataStructCode, + DDF_data_type_code eDataTypeCode, + const char *pszFormat = NULL ); + void AddSubfield( ossimDDFSubfieldDefn *poNewSFDefn, + int bDontAddToFormat = false ); + void AddSubfield( const char *pszName, const char *pszFormat ); + int GenerateDDREntry( char **ppachData, int *pnLength ); + + int Initialize( ossimDDFModule * poModule, const char *pszTag, + int nSize, const char * pachRecord ); + + void Dump( FILE * fp ); + + /** Fetch a pointer to the field name (tag). + * @return this is an internal copy and shouldn't be freed. + */ + const char *GetName() { return pszTag; } + + /** Fetch a longer descriptio of this field. + * @return this is an internal copy and shouldn't be freed. + */ + const char *GetDescription() { return _fieldName; } + + /** Get the number of subfields. */ + int GetSubfieldCount() { return nSubfieldCount; } + + ossimDDFSubfieldDefn *GetSubfield( int i ); + ossimDDFSubfieldDefn *FindSubfieldDefn( const char * ); + + /** + * Get the width of this field. This function isn't normally used + * by applications. + * + * @return The width of the field in bytes, or zero if the field is not + * apparently of a fixed width. + */ + int GetFixedWidth() { return nFixedWidth; } + + /** + * Fetch repeating flag. + * @see DDFField::GetRepeatCount() + * @return TRUE if the field is marked as repeating. + */ + int IsRepeating() { return bRepeatingSubfields; } + + static char *ExpandFormat( const char * ); + + /** this is just for an S-57 hack for swedish data */ + void SetRepeatingFlag( int n ) { bRepeatingSubfields = n; } + + char *GetDefaultValue( int *pnSize ); + + private: + + static char *ExtractSubstring( const char * ); + + ossimDDFModule * poModule; + char * pszTag; + + char * _fieldName; + char * _arrayDescr; + char * _formatControls; + + int bRepeatingSubfields; + int nFixedWidth; // zero if variable. + + int BuildSubfields(); + int ApplyFormats(); + + DDF_data_struct_code _data_struct_code; + + DDF_data_type_code _data_type_code; + + int nSubfieldCount; + ossimDDFSubfieldDefn **papoSubfields; +}; + +/************************************************************************/ +/* DDFSubfieldDefn */ +/* */ +/* Information from the DDR record for one subfield of a */ +/* particular field. */ +/************************************************************************/ + +/** + * Information from the DDR record describing one subfield of a DDFFieldDefn. + * All subfields of a field will occur in each occurance of that field + * (as a DDFField) in a DDFRecord. Subfield's actually contain formatted + * data (as instances within a record). + */ + +class ossimDDFSubfieldDefn +{ +public: + + ossimDDFSubfieldDefn(); + ~ossimDDFSubfieldDefn(); + + void SetName( const char * pszName ); + + /** Get pointer to subfield name. */ + const char *GetName() { return pszName; } + + /** Get pointer to subfield format string */ + const char *GetFormat() { return pszFormatString; } + int SetFormat( const char * pszFormat ); + + /** + * Get the general type of the subfield. This can be used to + * determine which of ExtractFloatData(), ExtractIntData() or + * ExtractStringData() should be used. + * @return The subfield type. One of DDFInt, DDFFloat, DDFString or + * DDFBinaryString. + */ + + DDFDataType GetType() { return eType; } + + double ExtractFloatData( const char *pachData, int nMaxBytes, + int * pnConsumedBytes ); + int ExtractIntData( const char *pachData, int nMaxBytes, + int * pnConsumedBytes ); + const char *ExtractStringData( const char *pachData, int nMaxBytes, + int * pnConsumedBytes ); + int GetDataLength( const char *, int, int * ); + void DumpData( const char *pachData, int nMaxBytes, FILE * fp ); + + int FormatStringValue( char *pachData, int nBytesAvailable, + int *pnBytesUsed, const char *pszValue, + int nValueLength = -1 ); + + int FormatIntValue( char *pachData, int nBytesAvailable, + int *pnBytesUsed, int nNewValue ); + + int FormatFloatValue( char *pachData, int nBytesAvailable, + int *pnBytesUsed, double dfNewValue ); + + /** Get the subfield width (zero for variable). */ + int GetWidth() { return nFormatWidth; } // zero for variable. + + int GetDefaultValue( char *pachData, int nBytesAvailable, + int *pnBytesUsed ); + + void Dump( FILE * fp ); + +/** + Binary format: this is the digit immediately following the B or b for + binary formats. + */ +typedef enum { + NotBinary=0, + UInt=1, + SInt=2, + FPReal=3, + FloatReal=4, + FloatComplex=5 +} DDFBinaryFormat; + + DDFBinaryFormat GetBinaryFormat(void) const { return eBinaryFormat; } + + +private: + + char *pszName; // a.k.a. subfield mnemonic + char *pszFormatString; + + DDFDataType eType; + DDFBinaryFormat eBinaryFormat; + +/* -------------------------------------------------------------------- */ +/* bIsVariable determines whether we using the */ +/* chFormatDelimeter (TRUE), or the fixed width (false). */ +/* -------------------------------------------------------------------- */ + int bIsVariable; + + char chFormatDelimeter; + int nFormatWidth; + +/* -------------------------------------------------------------------- */ +/* Fetched string cache. This is where we hold the values */ +/* returned from ExtractStringData(). */ +/* -------------------------------------------------------------------- */ + int nMaxBufChars; + char *pachBuffer; +}; + +/************************************************************************/ +/* DDFRecord */ +/* */ +/* Class that contains one DR record from a file. We read into */ +/* the same record object repeatedly to ensure that repeated */ +/* leaders can be easily preserved. */ +/************************************************************************/ + +/** + * Contains instance data from one data record (DR). The data is contained + * as a list of DDFField instances partitioning the raw data into fields. + */ + +class ossimDDFRecord +{ + public: + ossimDDFRecord( ossimDDFModule * ); + ~ossimDDFRecord(); + + ossimDDFRecord *Clone(); + ossimDDFRecord *CloneOn( ossimDDFModule * ); + + void Dump( FILE * ); + + /** Get the number of DDFFields on this record. */ + int GetFieldCount() { return nFieldCount; } + + ossimDDFField *FindField( const char *, int = 0 ); + ossimDDFField *GetField( int ); + + int GetIntSubfield( const char *, int, const char *, int, + int * = NULL ); + double GetFloatSubfield( const char *, int, const char *, int, + int * = NULL ); + const char *GetStringSubfield( const char *, int, const char *, int, + int * = NULL ); + + int SetIntSubfield( const char *pszField, int iFieldIndex, + const char *pszSubfield, int iSubfieldIndex, + int nValue ); + int SetStringSubfield( const char *pszField, int iFieldIndex, + const char *pszSubfield, int iSubfieldIndex, + const char *pszValue, int nValueLength=-1 ); + int SetFloatSubfield( const char *pszField, int iFieldIndex, + const char *pszSubfield, int iSubfieldIndex, + double dfNewValue ); + + /** Fetch size of records raw data (GetData()) in bytes. */ + int GetDataSize() { return nDataSize; } + + /** + * Fetch the raw data for this record. The returned pointer is effectively + * to the data for the first field of the record, and is of size + * GetDataSize(). + */ + const char *GetData() { return pachData; } + + /** + * Fetch the DDFModule with which this record is associated. + */ + + ossimDDFModule * GetModule() { return poModule; } + + int ResizeField( ossimDDFField *poField, int nNewDataSize ); + int DeleteField( ossimDDFField *poField ); + ossimDDFField* AddField( ossimDDFFieldDefn * ); + + int CreateDefaultFieldInstance( ossimDDFField *poField, int iIndexWithinField ); + + int SetFieldRaw( ossimDDFField *poField, int iIndexWithinField, + const char *pachRawData, int nRawDataSize ); + int UpdateFieldRaw( ossimDDFField *poField, int iIndexWithinField, + int nStartOffset, int nOldSize, + const char *pachRawData, int nRawDataSize ); + + int Write(); + + // This is really just for the DDFModule class. + int Read(); + void Clear(); + int ResetDirectory(); + + private: + + int ReadHeader(); + + ossimDDFModule *poModule; + + int nReuseHeader; + + int nFieldOffset; // field data area, not dir entries. + + int _sizeFieldTag; + int _sizeFieldPos; + int _sizeFieldLength; + + int nDataSize; // Whole record except leader with header + char *pachData; + + int nFieldCount; + ossimDDFField *paoFields; + + int bIsClone; +}; + +/************************************************************************/ +/* DDFField */ +/* */ +/* This object represents one field in a DDFRecord. */ +/************************************************************************/ + +/** + * This object represents one field in a DDFRecord. This + * models an instance of the fields data, rather than it's data definition + * which is handled by the DDFFieldDefn class. Note that a DDFField + * doesn't have DDFSubfield children as you would expect. To extract + * subfield values use GetSubfieldData() to find the right data pointer and + * then use ExtractIntData(), ExtractFloatData() or ExtractStringData(). + */ + +class ossimDDFField +{ + public: + void Initialize( ossimDDFFieldDefn *, const char *pszData, + int nSize ); + + void Dump( FILE * fp ); + + const char *GetSubfieldData( ossimDDFSubfieldDefn *, + int * = NULL, int = 0 ); + + const char *GetInstanceData( int nInstance, int *pnSize ); + + /** + * Return the pointer to the entire data block for this record. This + * is an internal copy, and shouldn't be freed by the application. + */ + const char *GetData() { return pachData; } + + /** Return the number of bytes in the data block returned by GetData(). */ + int GetDataSize() { return nDataSize; } + + int GetRepeatCount(); + + /** Fetch the corresponding DDFFieldDefn. */ + ossimDDFFieldDefn *GetFieldDefn() { return poDefn; } + + private: + ossimDDFFieldDefn *poDefn; + + int nDataSize; + + const char *pachData; +}; + +#endif /* ifndef ossimIso8211_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/aigrid/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/formats/aigrid/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/aigrid/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/aigrid/ossimArcInfoGridWriter.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/aigrid/ossimArcInfoGridWriter.cpp new file mode 100644 index 0000000000..4a85ed9ae5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/aigrid/ossimArcInfoGridWriter.cpp @@ -0,0 +1,367 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimArcInfoGridWriter.cpp,v 1.8 2006/01/06 16:46:46 dburken Exp $ + +#include <cstring> +#include <cstdio> +#include <fstream> +#include <iostream> + +#include <imaging/formats/aigrid/ossimArcInfoGridWriter.h> +#include <base/common/ossimKeywordNames.h> +#include <base/common/ossimTrace.h> +#include <base/misc/ossimEndian.h> +#include <base/data_types/ossimDpt.h> +#include <projections/map_projections/ossimMapProjection.h> +#include <imaging/ossimImageData.h> +#include <imaging/ossimImageSource.h> +#include <imaging/tile_sources/ossimCastTileSourceFilter.h> + +#include <support_data/esri/ossimAigStatistics.h> +#include <support_data/esri/ossimAigHeader.h> +#include <support_data/esri/ossimAigBounds.h> +#include <support_data/esri/ossimAigIndexFileHeader.h> +#include <support_data/esri/ossimAigDataFileHeader.h> + +#include <imaging/tile_sources/ossimCastTileSourceFilter.h> + +static const ossimTrace traceDebug("ossimArcInfoGridWriter:debug"); + +RTTI_DEF1(ossimArcInfoGridWriter, + "ossimArcInfoGridWriter", + ossimImageFileWriter); + +//******************************************************************* +// Constructor: +//******************************************************************* +ossimArcInfoGridWriter::ossimArcInfoGridWriter() + : ossimImageFileWriter(), + theOutputTileSize(256, 4) +{ +} + +ossimArcInfoGridWriter::ossimArcInfoGridWriter(ossimImageSource* inputSource, + const ossimFilename& filename) + :ossimImageFileWriter(filename, inputSource) +{ +} + +//******************************************************************* +// Destructor +//******************************************************************* +ossimArcInfoGridWriter::~ossimArcInfoGridWriter() +{ + close(); +} + +bool ossimArcInfoGridWriter::writeFile() +{ + const char* MODULE = "ossimArcInfoGridWriter::writeFile"; + + ossimCastTileSourceFilter* filter = new ossimCastTileSourceFilter; + filter->setOutputScalarType(OSSIM_FLOAT); + filter->connectMyInputTo(theInputConnection); + filter->initialize(); + + if(!theInputConnection) + { + delete filter; + + return false; + } + open(); + + // make sure we have a region of interest + if(theAreaOfInterest.hasNans()) + { + theInputConnection->initialize(); + theAreaOfInterest = theInputConnection->getAreaOfInterest(); + } + else + { + theInputConnection->setAreaOfInterest(theAreaOfInterest); + } + + if(theAreaOfInterest.hasNans()) return false; + + theInputConnection->setTileSize(theOutputTileSize); + theInputConnection->setToStartOfSequence(); + + bool result = writeBinaryAigHeader()&& + writeBinaryAigBounds()&& + writeBinaryAigStats(); + if(result) + { + ossimFilename indexFile=ossimFilename(theFilename+"/"+"w001001x.adf"); + ossimFilename dataFile=ossimFilename(theFilename+"/"+"w001001.adf"); + + std::ofstream indexFileStream(indexFile.c_str(), + ios::out|ios::binary); + std::ofstream dataFileStream(dataFile.c_str(), + ios::out|ios::binary); + ossimEndian endian; + + if(indexFileStream&&dataFileStream) + { + ossimAigIndexFileHeader aigIndexHeader; + ossimAigDataFileHeader aigDataFileHeader; + + ossimRefPtr<ossimImageData> currentTile = + theInputConnection->getNextTile(); + long tileNumber = 0; + long totalNumberOfTiles = theInputConnection->getNumberOfTiles(); + ossim_int32 tileOffsetShorts = 0; + ossim_int32 tileSizeShorts = 0; + + ossimNotify(ossimNotifyLevel_NOTICE) + << "Tile height = " << theInputConnection->getTileHeight() + << std::endl + << "Tile width = " << theInputConnection->getTileWidth() + << std::endl; + ossim_int32 tileSizeInShorts = 2*(theInputConnection->getTileHeight()* + theInputConnection->getTileWidth()); + // Note: this is in shorts + // + aigIndexHeader.theFileSize += (4*totalNumberOfTiles); + + // Note this is in shorts + // + + aigDataFileHeader.theFileSize = 50+ + (tileSizeInShorts*totalNumberOfTiles) + + totalNumberOfTiles; + aigDataFileHeader.theTileSize = tileSizeInShorts; + + aigIndexHeader.writeStream(indexFileStream); + aigDataFileHeader.writeStream(dataFileStream); + + if(traceDebug()) + { + CLOG << "AIG INDEX HEADER = \n" << aigIndexHeader << std::endl; + CLOG << "AIG DATA FILE HEADER\n" + << "file size = " << aigDataFileHeader.theFileSize + << std::endl; + } + + while(currentTile.valid()) + { + currentTile = filter->applyCast(currentTile); + + if(!currentTile->getBuf()) + { + currentTile->initialize(); + } + + tileOffsetShorts = dataFileStream.tellp()/2; + tileSizeShorts = 2*currentTile->getHeight()*currentTile->getWidth(); + ossim_int16 tileSizeShorts16 = 2*currentTile->getHeight()*currentTile->getWidth(); + if(endian.getSystemEndianType() == OSSIM_LITTLE_ENDIAN) + { + endian.swap(tileOffsetShorts); + endian.swap(tileSizeShorts); + endian.swap(tileSizeShorts16); + endian.swap((ossim_float32*)currentTile->getBuf(), + currentTile->getWidth()* + currentTile->getHeight()); + } + + indexFileStream.write((char*)(&tileOffsetShorts), 4); + indexFileStream.write((char*)(&tileSizeShorts), 4); + dataFileStream.write((char*)(&tileSizeShorts16), + 2); + dataFileStream.write((char*)(currentTile->getBuf()), + currentTile->getWidth()*currentTile->getHeight()*4); + + currentTile = theInputConnection->getNextTile(); + ++tileNumber; + } + } + } + + close(); + delete filter; + return result; +} + +bool ossimArcInfoGridWriter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + return ossimImageFileWriter::saveState(kwl, prefix); +} + +bool ossimArcInfoGridWriter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + + return ossimImageFileWriter::loadState(kwl, prefix); +} + +bool ossimArcInfoGridWriter::isOpen()const +{ + return (theFilename.isDir() && theFilename.exists()); +} + +bool ossimArcInfoGridWriter::open() +{ + if(theFilename.isDir()&& + theFilename.exists()) + { + return true; + } + else + { + theFilename = theFilename.path(); + if(theFilename.isDir()&& + theFilename.exists()) + { + return true; + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimArcInfoGridWriter::open(): Directory " + << theFilename << " doesn't exist" << std::endl; + } + + } + return false; +} + +void ossimArcInfoGridWriter::close() +{ +} + + +bool ossimArcInfoGridWriter::writeBinaryAigHeader() +{ + const char* MODULE = "ossimArcInfoGridWriter::writeBinaryAigHeader"; + ossimAigHeader aigHeader; + + ossimFilename file=ossimFilename(theFilename+"/"+"hdr.adf"); + + if(isOpen()) + { + switch(theInputConnection->getOutputScalarType()) + { + case OSSIM_UCHAR: + case OSSIM_SSHORT16: + case OSSIM_USHORT11: + case OSSIM_USHORT16: +// { +// aigHeader.setIntCoverage(); +// break; +// } + case OSSIM_DOUBLE: + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_NORMALIZED_DOUBLE: + { + aigHeader.setFloatCoverage(); + break; + } + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimArcInfoGridWriter::writeBinaryAigHeader: " + << "unkown scalar type" << std::endl; + } + } + + // need to set pixel size + // + + // code goes here + + // now setting number of tiles per row + aigHeader.theNumberOfTilesPerRow = theInputConnection->getNumberOfTilesHorizontal(); + aigHeader.theNumberOfTilesPerColumn = theInputConnection->getNumberOfTilesVertical(); + aigHeader.theWidthOfTileInPixels = theInputConnection->getTileWidth(); + aigHeader.theHeightOfTileInPixels = theInputConnection->getTileHeight(); + + std::ofstream out; + out.open(file.c_str(), ios::out|ios::binary); + + if(out) + { + if(traceDebug()) + { + CLOG << "AIG_HEADER = \n" << aigHeader << std::endl; + } + return aigHeader.writeStream(out); + } + } + + return false; +} + +bool ossimArcInfoGridWriter::writeBinaryAigBounds() +{ + const char* MODULE = "ossimArcInfoGridWriter::writeBinaryAigBounds"; + ossimAigBounds aigBounds; + + + // setup bounds + ossimIrect bounds = theInputConnection->getBoundingRect(); + if(!bounds.hasNans()) + { + aigBounds.ll_x = -.5; + aigBounds.ll_y = -.5; + aigBounds.ur_x = bounds.width()-.5; + aigBounds.ur_y = bounds.height()-.5; + + // + ossimFilename file=ossimFilename(theFilename+"/"+"dblbnd.adf"); + + if(isOpen()) + { + std::ofstream out; + out.open(file.c_str(), ios::out|ios::binary); + + if(out) + { + if(traceDebug()) + { + CLOG << "AIG BOUNDS =\n" <<aigBounds << std::endl; + } + return aigBounds.writeStream(out); + } + } + } + + return false; +} + +bool ossimArcInfoGridWriter::writeBinaryAigStats() +{ + ossimAigStatistics aigStats; + + + // setup bounds + aigStats.theMin = theInputConnection->getMinPixelValue(); + aigStats.theMax = theInputConnection->getMaxPixelValue(); + aigStats.theMean = (aigStats.theMax-aigStats.theMin)/2.0; + + // + ossimFilename file=ossimFilename(theFilename+"/"+"sta.adf"); + + if(isOpen()) + { + std::ofstream out; + out.open(file.c_str(), ios::out|ios::binary); + + if(out) + { + return aigStats.writeStream(out); + } + } + + return false; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/aigrid/ossimArcInfoGridWriter.h b/Utilities/OSSIM/ossim_core/imaging/formats/aigrid/ossimArcInfoGridWriter.h new file mode 100644 index 0000000000..7fd5feec87 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/aigrid/ossimArcInfoGridWriter.h @@ -0,0 +1,59 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimArcInfoGridWriter.h,v 1.5 2006/01/06 16:46:46 dburken Exp $ +#ifndef ossimArcInfoGridWriter_HEADER +#define ossimArcInfoGridWriter_HEADER + +#include <imaging/formats/ossimImageFileWriter.h> +#include <base/data_types/ossimKeywordlist.h> + +//******************************************************************* +// CLASS: ossimArdcInfoGridWriterFactory +//******************************************************************* + +class OSSIM_DLL ossimArcInfoGridWriter : public ossimImageFileWriter +{ +public: + ossimArcInfoGridWriter(); + virtual ~ossimArcInfoGridWriter(); + + ossimArcInfoGridWriter(ossimImageSource *inputSource, + const ossimFilename& filename); + virtual bool isOpen()const; + + virtual bool open(); + virtual void close(); + + /*! + * saves the state of the object. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +private: + virtual bool writeFile(); + + virtual bool writeBinaryAigHeader(); + virtual bool writeBinaryAigBounds(); + virtual bool writeBinaryAigStats(); + + ossimIpt theOutputTileSize; + + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/ccf/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/formats/ccf/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/ccf/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/ccf/ossimCcfHead.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/ccf/ossimCcfHead.cpp new file mode 100644 index 0000000000..e28177ce9a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/ccf/ossimCcfHead.cpp @@ -0,0 +1,767 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class definition for CcfHead. +// +//******************************************************************* +// $Id: ossimCcfHead.cpp,v 1.12 2005/05/09 12:39:38 dburken Exp $ + +#include <sstream> +#include <iostream> +#include <fstream> + +using namespace std; + +#include "ossimCcfHead.h" +#include "base/data_types/ossimIrect.h" +#include "base/misc/lookup_tables/ossimScalarTypeLut.h" +#include "base/common/ossimErrorCodes.h" +#include "base/context/ossimErrorContext.h" + +static const bool TRACE = false; // Temp until trace code implemented. + +ossimCcfHead::ossimCcfHead() + : + theCcfFile(), + theNumberOfBands(1), + thePixelType(OSSIM_UCHAR), + theFileType(), + theVersionNumber(0), + theLinesPerChip(0), + theSamplesPerChip(0), + theLineChipsPerChunk(0), + theSampleChipsPerChunk(0), + theRectInFullImageStartLine(0), + theRectInFuleImageStartSample(0), + theRectInFullImageStopLine(0), + theRectInFuleImageStopSample(0), + theNumberOfValidImageVertices(0), + theValidImageVertices(1), + theFirstBandHeaderPointer(0), + theRadiometryString(), + theBytesPerPixel(0), + theBytesPerChip(0), + theBytesPerChunk(0), + theCompressionType(), + theNumberOfRLevels(0), + theOccupiedFlag(1), + theStartOfData(1), + theNumberOfLines(1), + theNumberOfSamples(1), + theChunksInLineDir(1), + theChunksInSampleDir(1) +{} + +//*************************************************************************** +// Public Constructor: +//*************************************************************************** +ossimCcfHead::ossimCcfHead(const char* ccf_file) + : + theCcfFile(ccf_file), + theNumberOfBands(1), + thePixelType(OSSIM_UCHAR), + theFileType(), + theVersionNumber(0), + theLinesPerChip(0), + theSamplesPerChip(0), + theLineChipsPerChunk(0), + theSampleChipsPerChunk(0), + theRectInFullImageStartLine(0), + theRectInFuleImageStartSample(0), + theRectInFullImageStopLine(0), + theRectInFuleImageStopSample(0), + theNumberOfValidImageVertices(0), + theValidImageVertices(1), + theFirstBandHeaderPointer(0), + theRadiometryString(""), + theBytesPerPixel(0), + theBytesPerChip(0), + theBytesPerChunk(0), + theCompressionType(), + theNumberOfRLevels(0), + theOccupiedFlag(1), + theStartOfData(1), + theNumberOfLines(1), + theNumberOfSamples(1), + theChunksInLineDir(1), + theChunksInSampleDir(1) +{ + static const char MODULE[] = "ossimCcfHead::ossimCcfHead"; + + if (!parseCcfHeader(ccf_file)) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + + if (TRACE) + { + cerr << MODULE << " ERROR!" + << "\nError initializing from ccf_file: " << ccf_file + << "\nReturning..." << endl; + } + } +} + +//*************************************************************************** +// Destructor: +//*************************************************************************** +ossimCcfHead::~ossimCcfHead() +{} + +//*************************************************************************** +// Public Method: +//*************************************************************************** +bool ossimCcfHead::parseCcfHeader(const char* ccf_file) +{ + static const char MODULE[] = "ossimCcfHead::parseossimCcfHeader"; + + theCcfFile = ccf_file; + + ifstream *is = new ifstream(ccf_file); + + if (!(*is)) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + + if (TRACE) + { + cerr << MODULE << " ERROR!" + << "\nCannot open file: " << ccf_file << endl; + } + + is->close(); + delete is; + + return false; + } + + const ossim_uint32 MAX_LEN = 256; + char tmp[MAX_LEN]; + + // Check the first string should be "CCF" else get out... + // this might hang so I changed it to not use the + // >> operator unless it is a ccf file. If it is another + // file we might not be guranteed a whitespace or \n character + // will exist and therefore the entrie file could have + // been read in. + // + char type[4]; + is->read(type, 3); + type[3] = '\0'; + theFileType = type; + if (theFileType != "CCF") + { + if (TRACE) + { + cerr << MODULE << " ERROR!" + << "\nNot a ccf file. Returning..." << endl; + } + + is->close(); + delete is; + + return false; + } + + + // Check the version number. + (*is) >> tmp + >> theVersionNumber; + + //*** + // Call the appropriate method for the version. Currently only version 6 + // supported as that was all I had in-house. Feel free to add your own + // version reader! + //*** + bool status = false; + + switch(theVersionNumber) + { + case 5: + status = parseV5CcfHeader(*is); + break; + case 6: + status = parseV6CcfHeader(*is); + break; + default: + // Version type not supported... + if (TRACE) + { + cerr << MODULE << " ERROR!" + << "\nUsupported version: " << theVersionNumber + << " Returning..." << endl; + } + is->close(); + delete is; + status = false; + + break; + } + + // Close the stream. + is->close(); + delete is; + //*** + // Parse the radiometry string. This will initialize "theNumberOfBands" + // and the pixel type. + //*** + parseRadString(); + + return status; +} + +//*************************************************************************** +// Private Method: +//*************************************************************************** +bool ossimCcfHead::parseV5CcfHeader(istream& is) +{ + static const char MODULE[] = "CcfHead::parseV5CcfHeader"; + + // Check the stream. + if (!is) + { + if (TRACE) + { + cerr << MODULE << " Bad Stream passed to method!" + << "\nReturning..." + << endl; + } + + return false; + } + + const ossim_uint32 MAX_LEN = 256; + char tmp[MAX_LEN]; + + //*** + // These are all fixed/not used so just skip... + //*** + is.read(tmp, 1); // eat the '\n' + is.getline(tmp, MAX_LEN-1, '\n'); // skip "ccf_maker" + + is >> tmp // "LinesPerChip" + >> theLinesPerChip + >> tmp // "SamplesPerChip" + >> theSamplesPerChip + >> tmp // "LineChipsPerChunk" + >> theLineChipsPerChunk + >> tmp // "SampleChipsPerChunk" + >> theSampleChipsPerChunk; + + is.read(tmp, 1); // eat the '\n' + is.getline(tmp, MAX_LEN-1, '\n'); // skip "NumberOfBands" + is.getline(tmp, MAX_LEN-1, '\n'); // skip "RectInFullImageSpace" + + is >> tmp // skip "StartLine" + >> theRectInFullImageStartLine + >> tmp // skip "StartSample" + >> theRectInFuleImageStartSample + >> tmp // skip "StopLine" + >> theRectInFullImageStopLine + >> tmp // skip "StopSample" + >> theRectInFuleImageStopSample; + + // No valid image vertices in this version. + theNumberOfValidImageVertices = 0; + theValidImageVertices[0] = ossimIpt(0,0); + + is.read(tmp, 1); // eat the '\n' + is.getline(tmp, MAX_LEN-1, '\n'); // skip blank line + + is >> tmp // skip "FirstBandHeaderPointer" + >> theFirstBandHeaderPointer; // Offset to band header. + + // Seek to the band header record. + is.seekg(theFirstBandHeaderPointer, ios::beg); + + is.getline(tmp, MAX_LEN-1, '\n'); // skip "BAND" line + is.getline(tmp, MAX_LEN-1, '\n'); // skip "NextBandHeaderPointer" line + is.getline(tmp, MAX_LEN-1, '\n'); // skip "ChunkMapPointer" line + + is >> tmp; // skip "Radiometry" + + is.getline(tmp, MAX_LEN-1, '\n'); // Get the radiometry string. + const char* rad = tmp; + while ( *rad && (*rad == ' ')) rad++; // Eat the whitespaces... + theRadiometryString = rad; + + is >> tmp // skip "BytesPerPixel" + >> theBytesPerPixel + >> tmp // skip "BytesPerChip" + >> theBytesPerChip + >> tmp // skip "BytesPerChunk" + >> theBytesPerChunk + >> tmp // skip "CompressionType" + >> theCompressionType + >> tmp // skip "NumberOfRLevels" + >> theNumberOfRLevels; + + if ((ossim_uint32)theNumberOfRLevels > theOccupiedFlag.size()) + { + // Resize all the vectors. + theOccupiedFlag.resize(theNumberOfRLevels); + theStartOfData.resize(theNumberOfRLevels); + theNumberOfLines.resize(theNumberOfRLevels); + theNumberOfSamples.resize(theNumberOfRLevels); + theChunksInLineDir.resize(theNumberOfRLevels); + theChunksInSampleDir.resize(theNumberOfRLevels); + } + + is.read(tmp, 1); // eat the '\n' + is.getline(tmp, MAX_LEN-1, '\n'); // skip blank line + + ossim_uint32 i; + for (i=0; i<theNumberOfRLevels; i++) + { + is.getline(tmp, MAX_LEN-1, '\n'); // skip the Rlevel line + + ossim_uint32 tmp_long; + + is >> tmp // skip "Occupied" + >> tmp_long; + + theOccupiedFlag[i] = tmp_long; + + is >> tmp // skip "StartOfData" + >> tmp_long; + + theStartOfData[i] = tmp_long; + + is >> tmp // skip "NumberOfLines" + >> tmp_long; + + theNumberOfLines[i] = tmp_long; + + is >> tmp // skip "NumberOfSamples" + >> tmp_long; + + theNumberOfSamples[i] = tmp_long; + + is >> tmp // skip "ChunksInLineDir" + >> tmp_long; + + theChunksInLineDir[i] = tmp_long; + + is >> tmp // skip "ChunksInSampleDir" + >> tmp_long; + + theChunksInSampleDir[i] = tmp_long; + + is.getline(tmp, MAX_LEN-1, '\n'); // skip "LineOffset" line + is.getline(tmp, MAX_LEN-1, '\n'); // skip "LineDecimation" line + is.getline(tmp, MAX_LEN-1, '\n'); // skip "SampleOffset" line + is.getline(tmp, MAX_LEN-1, '\n'); // skip "SampleDecimation" line + is.read(tmp, 1); // Eat the '\n' + is.getline(tmp, MAX_LEN-1, '\n'); // skip blank line + is.read(tmp, 1); // Eat the '\n' + } + + // Note: The caller will close the stream. + + return true; +} + +//*************************************************************************** +// Private Method: +//*************************************************************************** +bool ossimCcfHead::parseV6CcfHeader(istream& is) +{ + static const char MODULE[] = "CcfHead::parseV6CcfHeader"; + + // Check the stream. + if (!is) + { + if (TRACE) + { + cerr << MODULE << " Bad Stream passed to method!" + << "\nReturning..." + << endl; + } + + return false; + } + + const ossim_uint32 MAX_LEN = 256; + char tmp[MAX_LEN]; + + //*** + // These are all fixed/not used so just skip... + //*** + is.read(tmp, 1); // eat the '\n' + is.getline(tmp, MAX_LEN-1, '\n'); // skip "ccf_maker" + + is >> tmp // "LinesPerChip" + >> theLinesPerChip + >> tmp // "SamplesPerChip" + >> theSamplesPerChip + >> tmp // "LineChipsPerChunk" + >> theLineChipsPerChunk + >> tmp // "SampleChipsPerChunk" + >> theSampleChipsPerChunk; + + is.read(tmp, 1); // eat the '\n' + is.getline(tmp, MAX_LEN-1, '\n'); // skip "NumberOfBands" + is.getline(tmp, MAX_LEN-1, '\n'); // skip "RectInFullImageSpace" + + is >> tmp // skip "StartLine" + >> theRectInFullImageStartLine + >> tmp // skip "StartSample" + >> theRectInFuleImageStartSample + >> tmp // skip "StopLine" + >> theRectInFullImageStopLine + >> tmp // skip "StopSample" + >> theRectInFuleImageStopSample + >> tmp // skip "ValidImageVertices" + >> theNumberOfValidImageVertices; + + // Get the valid image vertices. + ossim_uint32 i; + + if (theNumberOfValidImageVertices != theValidImageVertices.size()) + { + theValidImageVertices.resize(theNumberOfValidImageVertices); + } + + for (i=0; i<theNumberOfValidImageVertices; i++) + { + ossim_float64 tmp_dbl; // Can be doubles in header. + + is >> tmp // skip "Vertex" + >> tmp // skip Vertex number + >> tmp_dbl; // line + + theValidImageVertices[i].y = static_cast<int>(tmp_dbl); + + is >> tmp_dbl; // sample + + theValidImageVertices[i].x = static_cast<int>(tmp_dbl); + } + + is.read(tmp, 1); // eat the '\n' + is.getline(tmp, MAX_LEN-1, '\n'); // skip blank line + + is >> tmp // skip "FirstBandHeaderPointer" + >> theFirstBandHeaderPointer; // Offset to band header. + + // Seek to the band header record. + is.seekg(theFirstBandHeaderPointer, ios::beg); + + is.getline(tmp, MAX_LEN-1, '\n'); // skip "BAND" line + is.getline(tmp, MAX_LEN-1, '\n'); // skip "NextBandHeaderPointer" line + is.getline(tmp, MAX_LEN-1, '\n'); // skip "ChunkMapPointer" line + + is >> tmp; // skip "Radiometry" + + is.getline(tmp, MAX_LEN-1, '\n'); // Get the radiometry string. + + const char* rad = tmp; + while ( *rad && (*rad == ' ')) rad++; // Eat the whitespaces... + theRadiometryString = rad; + + is >> tmp // skip "BytesPerPixel" + >> theBytesPerPixel + >> tmp // skip "BytesPerChip" + >> theBytesPerChip + >> tmp // skip "BytesPerChunk" + >> theBytesPerChunk + >> tmp // skip "CompressionType" + >> theCompressionType + >> tmp // skip "NumberOfRLevels" + >> theNumberOfRLevels; + + if (theNumberOfRLevels > theOccupiedFlag.size()) + { + // Resize all the vectors. + theOccupiedFlag.resize(theNumberOfRLevels); + theStartOfData.resize(theNumberOfRLevels); + theNumberOfLines.resize(theNumberOfRLevels); + theNumberOfSamples.resize(theNumberOfRLevels); + theChunksInLineDir.resize(theNumberOfRLevels); + theChunksInSampleDir.resize(theNumberOfRLevels); + } + + is.read(tmp, 1); // eat the '\n' + is.getline(tmp, MAX_LEN-1, '\n'); // skip blank line + + for (i=0; i<theNumberOfRLevels; i++) + { + is.getline(tmp, MAX_LEN-1, '\n'); // skip the Rlevel line + + ossim_uint32 tmp_long; + + is >> tmp // skip "Occupied" + >> tmp_long; + + theOccupiedFlag[i] = tmp_long; + + is >> tmp // skip "StartOfData" + >> tmp_long; + + theStartOfData[i] = tmp_long; + + is >> tmp // skip "NumberOfLines" + >> tmp_long; + + theNumberOfLines[i] = tmp_long; + + is >> tmp // skip "NumberOfSamples" + >> tmp_long; + + theNumberOfSamples[i] = tmp_long; + + is >> tmp // skip "ChunksInLineDir" + >> tmp_long; + + theChunksInLineDir[i] = tmp_long; + + is >> tmp // skip "ChunksInSampleDir" + >> tmp_long; + + theChunksInSampleDir[i] = tmp_long; + + is.getline(tmp, MAX_LEN-1, '\n'); // skip "LineOffset" line + is.getline(tmp, MAX_LEN-1, '\n'); // skip "LineDecimation" line + is.getline(tmp, MAX_LEN-1, '\n'); // skip "SampleOffset" line + is.getline(tmp, MAX_LEN-1, '\n'); // skip "SampleDecimation" line + is.read(tmp, 1); // Eat the '\n' + is.getline(tmp, MAX_LEN-1, '\n'); // skip blank line + is.read(tmp, 1); // Eat the '\n' + } + + // Note: The caller will close the stream. + + return true; +} + +//*************************************************************************** +// Public Method: +//*************************************************************************** +std::ostream& ossimCcfHead::print(std::ostream& out) const +{ + static const char MODULE[] = "ossimCcfHead::print"; + + out << MODULE + << "\ntheErrorStatus: " << theErrorStatus + << "\ntheCcfFile: " << theCcfFile + << "\ntheNumberOfBands: " << theNumberOfBands + << "\nthePixelType: " + << (ossimScalarTypeLut::instance()->getEntryString(thePixelType)) + << "\ntheFileType: " << theFileType + << "\ntheVersionNumber: " << theVersionNumber + << "\ntheLinesPerChip: " << theLinesPerChip + << "\ntheSamplesPerChip: " << theSamplesPerChip + << "\ntheLineChipsPerChunk: " << theLineChipsPerChunk + << "\ntheSampleChipsPerChunk: " << theSampleChipsPerChunk + << "\ntheRectInFullImageStartLine: " << theRectInFullImageStartLine + << "\ntheRectInFuleImageStartSample: " << theRectInFuleImageStartSample + << "\ntheRectInFullImageStopLine: " << theRectInFullImageStopLine + << "\ntheRectInFuleImageStopSample: " << theRectInFuleImageStopSample + << "\ntheNumberOfValidImageVertices: " + << theNumberOfValidImageVertices; + + ossim_uint32 i; + + for (i=0; i<theNumberOfValidImageVertices; i++) + { + out << "\ntheValidImageVertices[" << i << "]: " + << theValidImageVertices[i]; + } + + out << "\ntheFirstBandHeaderPointer: " << theFirstBandHeaderPointer + << "\ntheRadiometryString: " << theRadiometryString + << "\ntheBytesPerPixel: " << theBytesPerPixel + << "\ntheBytestPerChip: " << theBytesPerChip + << "\ntheBytesPerChunk: " << theBytesPerChunk + << "\ntheCompressionType: " << theCompressionType + << "\ntheNumberOfRLevels: " << theNumberOfRLevels; + + for (i=0; i<theNumberOfRLevels; i++) + { + out << "\ntheOccupiedFlag[" << i << "]: " << theOccupiedFlag[i] + << "\ntheStartOfData[" << i << "]: " << theStartOfData[i] + << "\ntheNumberOfLines[" << i << "]: " << theNumberOfLines[i] + << "\ntheNumberOfSamples[" << i << "]: " << theNumberOfSamples[i] + << "\ntheChunksInLineDir[" << i << "]: " << theChunksInLineDir[i] + << "\ntheChunksInSampleDir[" << i << "]: " + << theChunksInSampleDir[i]; + } + + out << endl; + + return ossimErrorStatusInterface::print(out); +} + +//*************************************************************************** +// Public Method: +//*************************************************************************** +ossim_uint32 ossimCcfHead::numberOfLines(ossim_uint32 reduced_res_level) const +{ + static const char MODULE[] = "ossimCcfHead::numberOfLines"; + + if (reduced_res_level > highestReducedResSet() ) + { + cerr << MODULE << " ERROR!" + << "\nInvalid reduced res level: " << reduced_res_level + << "\nHighest reduced res level available: " + << highestReducedResSet() << endl; + return 0; + } + + return theNumberOfLines[reduced_res_level]; +} + +//*************************************************************************** +// Public Method: +//*************************************************************************** +ossim_uint32 ossimCcfHead::numberOfSamples(ossim_uint32 reduced_res_level) const +{ + static const char MODULE[] = "ossimCcfHead::numberOfSamples"; + + if (reduced_res_level > highestReducedResSet() ) + { + cerr << MODULE << " ERROR!" + << "\nInvalid reduced res level: " << reduced_res_level + << "\nHighest reduced res level available: " + << highestReducedResSet() << endl; + return 0; + } + + return theNumberOfSamples[reduced_res_level]; +} + +//*************************************************************************** +// Public Method: +//*************************************************************************** +ossim_uint32 ossimCcfHead::chunksInLineDir(ossim_uint32 reduced_res_level) const +{ + static const char MODULE[] = "ossimCcfHead::chunksInLineDir"; + + if (reduced_res_level > highestReducedResSet() ) + { + cerr << MODULE << " ERROR!" + << "\nInvalid reduced res level: " << reduced_res_level + << "\nHighest reduced res level available: " + << highestReducedResSet() << endl; + return 0; + } + + return theChunksInLineDir[reduced_res_level]; +} + +//*************************************************************************** +// Public Method: +//*************************************************************************** +ossim_uint32 ossimCcfHead::chunksInSampleDir(ossim_uint32 reduced_res_level) const +{ + static const char MODULE[] = "ossimCcfHead::chunksInSampleDir"; + + if (reduced_res_level > highestReducedResSet() ) + { + cerr << MODULE << " ERROR!" + << "\nInvalid reduced res level: " << reduced_res_level + << "\nHighest reduced res level available: " + << highestReducedResSet() << endl; + return 0; + } + + return theChunksInSampleDir[reduced_res_level]; +} + + +//*************************************************************************** +// Public Method: +//*************************************************************************** +streampos ossimCcfHead::startOfData(ossim_uint32 reduced_res_level) const +{ + static const char MODULE[] = "ossimCcfHead::startOfData"; + + if (reduced_res_level > highestReducedResSet() ) + { + cerr << MODULE << " ERROR!" + << "\nInvalid reduced res level: " << reduced_res_level + << "\nHighest reduced res level available: " + << highestReducedResSet() << endl; + return 0; + } + + return theStartOfData[reduced_res_level]; +} + +//*************************************************************************** +// Public Method: +//*************************************************************************** +ossimIrect ossimCcfHead::imageRect(ossim_uint32 reduced_res_level) const +{ + static const char MODULE[] = "ossimCcfHead::imageRect"; + + if (reduced_res_level > highestReducedResSet() ) + { + cerr << MODULE << " ERROR!" + << "\nInvalid reduced res level: " << reduced_res_level + << "\nHighest reduced res level available: " + << highestReducedResSet() << endl; + return ossimIrect(0,0,0,0); + } + + return ossimIrect(0, + 0, + numberOfSamples(reduced_res_level) - 1, + numberOfLines(reduced_res_level) - 1); +} + +//*************************************************************************** +// Public Method: +//*************************************************************************** +void ossimCcfHead::parseRadString() +{ + static const char MODULE[] = "ossimCcfHead::parseRadString"; + + if (theRadiometryString.contains("RadiomNBand")) + { + //*** + // Complex string, must parse. Should look like: + // "RadiomNBand (3 3 Linear8 )" + //*** + char tmp[80]; + istringstream is(theRadiometryString); + + is >> tmp; // Skip the "RadiomNBand" string. + is.get(tmp, 3); // Eat the space and the '('. + is >> theNumberOfBands; // Get the number of bands. + } + + if (theRadiometryString.contains("8")) + { + thePixelType = OSSIM_UCHAR; + } + else if(theRadiometryString.contains("16")) + { + thePixelType = OSSIM_USHORT16; + } + else if (theRadiometryString.contains("11")) + { + thePixelType = OSSIM_USHORT11; + } + else + { + cerr << MODULE << " Unknown radiometry!" + << "\ntheRadiometryString: " << theRadiometryString << endl; + } + + if (TRACE) + { + cout << MODULE + << "\ntheRadiometryString: " << theRadiometryString + << "\ntheNumberOfBands: " << theNumberOfBands + << "\nthePixelType: " + << (ossimScalarTypeLut::instance()->getEntryString(thePixelType)) + << endl; + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/ccf/ossimCcfHead.h b/Utilities/OSSIM/ossim_core/imaging/formats/ccf/ossimCcfHead.h new file mode 100644 index 0000000000..afd243320e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/ccf/ossimCcfHead.h @@ -0,0 +1,202 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// +// Description: +// +// Contains class declaration for CcfHead. +// +// Notes: +// - This is not a full blown CCF header class as it only captures the +// data needed for loading. +// - Currently only version 6 is supported. +// +//******************************************************************* +// $Id: ossimCcfHead.h,v 1.8 2004/01/12 16:32:39 dburken Exp $ +#ifndef ossimCcfHead_HEADER +#define ossimCcfHead_HEADER + +#include <vector> + +using namespace std; + +#include "base/common/ossimErrorStatusInterface.h" +#include "base/data_types/ossimString.h" +#include "base/data_types/ossimIpt.h" + +class ossimIrect; + +//*************************************************************************** +// CLASS: ossimCcfHead +//*************************************************************************** +class ossimCcfHead : public ossimErrorStatusInterface +{ +public: + + ossimCcfHead(); + + ossimCcfHead(const char* ccf_file); + + ~ossimCcfHead (); + + /*! + * Reads the ccf header and initializes data members. Returns true on + * successful read, false on error. + */ + bool parseCcfHeader(const char* ccf_file); + + virtual std::ostream& print(std::ostream& out) const; + + ossim_uint32 numberOfReducedResSets() const { return theNumberOfRLevels; } + + ossim_uint32 numberOfLines(ossim_uint32 reduced_res_level) const; + + ossim_uint32 numberOfSamples(ossim_uint32 reduced_res_level) const; + + ossim_uint32 chunksInLineDir(ossim_uint32 reduced_res_level) const; + + ossim_uint32 chunksInSampleDir(ossim_uint32 reduced_res_level) const; + + streampos startOfData(ossim_uint32 reduced_res_level) const; + + /*! + * Returns the highest available reduced resolution level. + * Zero based. + */ + ossim_uint32 highestReducedResSet() const + { return !theNumberOfRLevels ? 0 : (theNumberOfRLevels - 1); } + + /*! + * Returns the zero based image rectangle for the reduced resolution + * level passed in. Returns a rectangle of (0,0,0,0) if reduced_res_level + * is out of range. + */ + ossimIrect imageRect(ossim_uint32 reduced_res_level) const; + + /*! + * Returns the ccf file name as a String. + */ + ossimString imageFile() const { return theCcfFile; } + + /*! + * Returns the radiometry string. + */ + ossimString radiometry() const { return theRadiometryString; } + + /*! + * Returns the number of bands. + */ + ossim_uint32 numberOfBands() const { return theNumberOfBands; } + + /*! + * Returns the enumerated pixel type. + */ + ossimScalarType pixelType() const { return thePixelType; } + + /*! + * Returns the bytes per chunk. + */ + ossim_uint32 bytesPerChunk() const { return theBytesPerChunk; } + + /*! + * Returns the bytes per chip. + */ + ossim_uint32 bytesPerChip() const { return theBytesPerChip; } + + /*! + * Returns the number of chips in sample direction of a chunk. + */ + ossim_uint32 sampleChipsPerChunk() const { return theSampleChipsPerChunk; } + + /*! + * Returns the number of chips in line direction of a chunk. + */ + ossim_uint32 lineChipsPerChunk() const { return theLineChipsPerChunk; } + + /*! + * Returns the samples per chip. + */ + ossim_uint32 samplesPerChip() const { return theSamplesPerChip; } + + /*! + * Returns the lines per chip. + */ + ossim_uint32 linesPerChip() const { return theLinesPerChip; } + + /*! + * Returns the number of pixels in a single band of a chip. + * Note: This is not in bytes but in pixels. + */ + ossim_uint32 chipSizePerBand() const + { return theLinesPerChip * theSamplesPerChip; } + + const vector<ossimIpt>& getValidImageVertices()const + { + return theValidImageVertices; + } +private: + + /*! + * Parses a version five header. + */ + bool parseV5CcfHeader(istream& is); + + /*! + * Parses a version six header. + */ + bool parseV6CcfHeader(istream& is); + + /*! + * Parses the radiometry string and initializes "theNumberOfBands" and + * "thePixelType". + */ + void parseRadString(); + + ossimString theCcfFile; + ossim_uint32 theNumberOfBands; + ossimScalarType thePixelType; + ossimString theFileType; + ossim_uint32 theVersionNumber; + ossim_uint32 theLinesPerChip; + ossim_uint32 theSamplesPerChip; + ossim_uint32 theLineChipsPerChunk; + ossim_uint32 theSampleChipsPerChunk; + ossim_uint32 theRectInFullImageStartLine; + ossim_uint32 theRectInFuleImageStartSample; + ossim_uint32 theRectInFullImageStopLine; + ossim_uint32 theRectInFuleImageStopSample; + ossim_uint32 theNumberOfValidImageVertices; + vector<ossimIpt> theValidImageVertices; + ossim_uint32 theFirstBandHeaderPointer; + ossimString theRadiometryString; + ossim_uint32 theBytesPerPixel; + ossim_uint32 theBytesPerChip; + ossim_uint32 theBytesPerChunk; + ossimString theCompressionType; + ossim_uint32 theNumberOfRLevels; + vector<bool> theOccupiedFlag; + vector<streampos> theStartOfData; + vector<ossim_uint32> theNumberOfLines; + vector<ossim_uint32> theNumberOfSamples; + vector<ossim_uint32> theChunksInLineDir; + vector<ossim_uint32> theChunksInSampleDir; +}; + + +#endif // #ifndef CcfHead_HEADER diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/ccf/ossimCcfTileSource.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/ccf/ossimCcfTileSource.cpp new file mode 100644 index 0000000000..be885dee69 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/ccf/ossimCcfTileSource.cpp @@ -0,0 +1,847 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class definition for ossimCcfTileSource. +//******************************************************************* +// $Id: ossimCcfTileSource.cpp,v 1.48 2005/05/09 12:39:38 dburken Exp $ + +#include <algorithm> +#include <imaging/formats/ccf/ossimCcfTileSource.h> +#include <base/common/ossimCommon.h> +#include <base/common/ossimTrace.h> +#include <base/data_types/ossimIpt.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimIrect.h> +#include <base/data_types/ossimFilename.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimDirectory.h> +#include <base/misc/lookup_tables/ossimInterleaveTypeLut.h> +#include <base/misc/lookup_tables/ossimScalarTypeLut.h> +#include <imaging/ossimImageData.h> +#include <imaging/factory/ossimImageDataFactory.h> + +using namespace std; + +RTTI_DEF1(ossimCcfTileSource, "ossimCcfTileSource", ossimImageHandler); + +//*** +// Define Trace flags for use within this file: +//*** + +static ossimTrace traceExec ("ossimCcfTileSource:exec"); +static ossimTrace traceDebug ("ossimCcfTileSource:debug"); + +// For interleave type enum to string conversions. +static const ossimInterleaveTypeLut ILUT; + +ossimCcfTileSource::ossimCcfTileSource() + : + ossimImageHandler(), + theCcfHead(), + theTile(NULL), + theChipBuffer(NULL), + theFileStr(NULL), + theOutputBandList(1), + theByteOrder(ossimGetByteOrder()) +{} + +ossimCcfTileSource::~ossimCcfTileSource() +{ + close(); +} + +ossimRefPtr<ossimImageData> ossimCcfTileSource::getTile( + const ossimIrect& rect, ossim_uint32 resLevel) +{ + if (!isSourceEnabled() || !isOpen() || + (resLevel >= theCcfHead.numberOfReducedResSets()) ) + { + return ossimRefPtr<ossimImageData>(); + } + + theTile->setImageRectangle(rect); + + ossimIrect image_rect = theCcfHead.imageRect(resLevel); + + //*** + // See if any point of the requested tile is in the image. + //*** + if ( rect.intersects(image_rect) ) + { + ossimIrect clip_rect = rect.clipToRect(image_rect); + + if ( !rect.completely_within(clip_rect) ) + { + // Start with a blank tile. + theTile->makeBlank(); + } + + // Load the tile buffer with data from the ccf. + if (fillBuffer(rect, clip_rect, image_rect, resLevel)) + { + theTile->validate(); + return theTile; + } + else + { + // Error in filling buffer. + cerr << "ossimCcfTileSource getTile ERROR: Returning blank tile..." + << endl; + return ossimRefPtr<ossimImageData>(); + } + } + + // No part of requested tile within the image rectangle. + return ossimRefPtr<ossimImageData>(); +} + +//******************************************************************* +// Private Method: +//******************************************************************* +bool ossimCcfTileSource::fillBuffer(const ossimIrect& tile_rect, + const ossimIrect& clip_rect, + const ossimIrect& image_rect, + ossim_uint32 reduced_res_level) +{ + bool status = false; + + //*** + // Determine the pixel type and make the appropriate tiles. + //*** + switch (theCcfHead.pixelType()) + { + case OSSIM_UCHAR: + status = fillUcharBuffer(tile_rect, + clip_rect, + image_rect, + reduced_res_level); + break; + case OSSIM_USHORT11: + case OSSIM_USHORT16: + status = fillUshortBuffer(tile_rect, + clip_rect, + image_rect, + reduced_res_level); + break; + default: + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + cerr << "ossimCcfTileSource fillBuffer ERROR:" + << "\nUnsupported pixel type!" + << "\nBuffer not filled. Returning error." << endl; + break; + } + + return status; +} + +//******************************************************************* +// Private Method: +//******************************************************************* +bool ossimCcfTileSource::fillUcharBuffer(const ossimIrect& tile_rect, + const ossimIrect& clip_rect, + const ossimIrect& image_rect, + ossim_uint32 reduced_res_level) +{ + if(!isOpen()) return false; + + const ossim_uint32 TILE_SIZE_PER_BAND = theTile->getSizePerBand(); + const ossim_uint32 CHIP_SIZE_PER_BAND = theCcfHead.chipSizePerBand(); + const ossim_uint32 SAMPLES_PER_CHIP = theCcfHead.samplesPerChip(); + const ossim_uint32 LINES_PER_CHIP = theCcfHead.linesPerChip(); + const ossim_uint32 BYTES_PER_CHUNK = theCcfHead.bytesPerChunk(); + const ossim_uint32 BYTES_PER_CHIP = theCcfHead.bytesPerChip(); + const ossim_uint32 CHIPS_IN_SAMPLE_DIR = theCcfHead.sampleChipsPerChunk(); + const ossim_uint32 CHIPS_IN_LINE_DIR = theCcfHead.lineChipsPerChunk(); + const ossim_uint32 NUMBER_OF_INPUT_BANDS = theCcfHead.numberOfBands(); + const ossim_uint32 CHUNKS_IN_SAMPLE_DIR = theCcfHead.chunksInSampleDir(reduced_res_level); + const ossim_uint32 CHUNK_SIDE_SIZE = SAMPLES_PER_CHIP * + CHIPS_IN_SAMPLE_DIR; + const ossim_uint32 CHIP_OFFSET_TO_END = SAMPLES_PER_CHIP - 1; + + //*** + // Shift the upper left corner of the "clip_rect" to the an even chunk + // boundry. + //*** + ossimIpt chunkOrigin = clip_rect.ul(); + adjustToStartOfChunk(chunkOrigin); + + //*** + // Calculate the number of chunks needed in the line/sample directions. + //*** + ossim_uint32 size_in_x + = static_cast<ossim_uint32>(clip_rect.lr().x - chunkOrigin.x + 1); + ossim_uint32 size_in_y + = static_cast<ossim_uint32>(clip_rect.lr().y - chunkOrigin.y + 1); + ossim_uint32 w = (CHIPS_IN_SAMPLE_DIR*SAMPLES_PER_CHIP); + ossim_uint32 h = (CHIPS_IN_LINE_DIR*LINES_PER_CHIP); + ossim_uint32 chunks_in_x_dir = size_in_x / w + (size_in_x % w ? 1 : 0); + ossim_uint32 chunks_in_y_dir = size_in_y / h + (size_in_y % h ? 1 : 0); + + + //*** + // Get the start of data for the "reduced_res_level" passed in. + //*** + streampos startOfData = theCcfHead.startOfData(reduced_res_level); + ossimIpt ulChunkPt = chunkOrigin; + + // Chunk loop in line direction. + for (ossim_uint32 y=0; y<chunks_in_y_dir; ++y) + { + ulChunkPt.x = chunkOrigin.x; + + // Chunk loop in sample direction. + for (ossim_uint32 x=0; x<chunks_in_x_dir; ++x) + { + //*** + // Sequence through the chips in the chunk. + // Grab the ccf data and stuff the tile buffer. + //*** + ossimIpt chip_pt = ulChunkPt; + + // Chip loop in line direction. + for (ossim_uint32 y_chip=0; y_chip<CHIPS_IN_LINE_DIR; ++y_chip) + { + chip_pt.x = ulChunkPt.x; // Reset x back to front of chunk. + + // Chip loop in sample direction. + for (ossim_uint32 x_chip=0; x_chip<CHIPS_IN_SAMPLE_DIR; ++x_chip) + { + ossimIrect chip_rect(chip_pt.x, + chip_pt.y, + chip_pt.x + CHIP_OFFSET_TO_END, + chip_pt.y + CHIP_OFFSET_TO_END); + + if (chip_rect.intersects(clip_rect)) + { + //*** + // Some point in the chip intersect the tile so grab the + // data. + //*** + + //*** + // Get the seek position for the chunk. + //*** + streampos tmp_offset + = ( ulChunkPt.y / CHUNK_SIDE_SIZE * BYTES_PER_CHUNK * + CHUNKS_IN_SAMPLE_DIR ) + + ( ulChunkPt.x / CHUNK_SIDE_SIZE * BYTES_PER_CHUNK ); + + streampos seek_position = startOfData + tmp_offset; + + // Now move it to the chip. + tmp_offset + = ( y_chip * BYTES_PER_CHIP * CHIPS_IN_SAMPLE_DIR ) + + (x_chip * BYTES_PER_CHIP); + + seek_position += tmp_offset; + + // Seek to the chip + theFileStr->seekg(seek_position, ios::beg); + + //*** + // Read the chip from the ccf file into the chip buffer. + // This will get all the bands. Bands are interleaved by + // chip. + //*** + if (!theFileStr->read((char*)theChipBuffer, BYTES_PER_CHIP)) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + cerr << "ossimCcfTileSource fillUchBuffer READ ERROR!" + << "\nReturning from method." << endl; + return false; + } + + ossimIrect chip_clip_rect = clip_rect.clipToRect(chip_rect); + + //*** + // Band loop in sample direction. Bands are interleaved by + // chip. + //*** + for (ossim_uint32 band=0; band<NUMBER_OF_INPUT_BANDS; ++band) + { + //*** + // Get a pointer positioned at the first valid pixel in + // the chip. + //*** + ossim_uint8* s + = theChipBuffer + + band * CHIP_SIZE_PER_BAND + + (chip_clip_rect.ul().y - chip_rect.ul().y) * + SAMPLES_PER_CHIP + chip_clip_rect.ul().x - + chip_rect.ul().x; + + //*** + // Get a pointer positioned at the first valid pixel in + // the tile. + //*** + ossim_uint8* d + = (ossim_uint8*)theTile->getBuf() + + band * TILE_SIZE_PER_BAND + + (chip_clip_rect.ul().y - tile_rect.ul().y) * + theTile->getWidth() + chip_clip_rect.ul().x - + tile_rect.ul().x; + + // Line loop through a chip. + for (ossim_int32 chip_line = chip_clip_rect.ul().y; + chip_line <= chip_clip_rect.lr().y; + chip_line++) + { + // Sample loop through a chip. + ossim_uint32 i=0; + for (ossim_int32 chip_sample = chip_clip_rect.ul().x; + chip_sample <= chip_clip_rect.lr().x; + chip_sample++) + { + d[i] = s[i]; + i++; + } + + // Increment the pointers by one line. + s += SAMPLES_PER_CHIP; + d += theTile->getWidth(); + } + + } // End of band loop. + + } // End of if (chip_rect.intersects(clip_rect)) + + chip_pt.x += SAMPLES_PER_CHIP; + + } // End of chip loop in the sample direction. + + chip_pt.y += LINES_PER_CHIP; + + } // End of chip loop in the line direction. + + ulChunkPt.x += CHUNK_SIDE_SIZE; + + } // End of chunk loop in the sample direction. + + ulChunkPt.y += CHUNK_SIDE_SIZE; + + } // End of chunk loop in the line direction. + + return true; +} + +//******************************************************************* +// Private Method: +//******************************************************************* +bool ossimCcfTileSource::fillUshortBuffer(const ossimIrect& tile_rect, + const ossimIrect& clip_rect, + const ossimIrect& image_rect, + ossim_uint32 reduced_res_level) +{ + const ossim_uint32 TILE_SIZE_PER_BAND = theTile->getSizePerBand(); + const ossim_uint32 CHIP_SIZE_PER_BAND = theCcfHead.chipSizePerBand(); + const ossim_uint32 SAMPLES_PER_CHIP = theCcfHead.samplesPerChip(); + const ossim_uint32 LINES_PER_CHIP = theCcfHead.linesPerChip(); + const ossim_uint32 BYTES_PER_CHUNK = theCcfHead.bytesPerChunk(); + const ossim_uint32 BYTES_PER_CHIP = theCcfHead.bytesPerChip(); + const ossim_uint32 CHIPS_IN_SAMPLE_DIR = theCcfHead.sampleChipsPerChunk(); + const ossim_uint32 CHIPS_IN_LINE_DIR = theCcfHead.lineChipsPerChunk(); + const ossim_uint32 NUMBER_OF_INPUT_BANDS = theCcfHead.numberOfBands(); + const ossim_uint32 CHUNKS_IN_SAMPLE_DIR = theCcfHead. + chunksInSampleDir(reduced_res_level); + const ossim_uint32 CHUNK_SIDE_SIZE = SAMPLES_PER_CHIP * + CHIPS_IN_SAMPLE_DIR; + const ossim_uint32 CHIP_OFFSET_TO_END = SAMPLES_PER_CHIP - 1; + + //*** + // Shift the upper left corner of the "clip_rect" to the an even chunk + // boundry. + //*** + ossimIpt chunkOrigin = clip_rect.ul(); + adjustToStartOfChunk(chunkOrigin); + + //*** + // Calculate the number of chunks needed in the line/sample directions. + //*** + + ossim_uint32 size_in_x = clip_rect.lr().x - chunkOrigin.x + 1; + ossim_uint32 size_in_y = clip_rect.lr().y - chunkOrigin.y + 1; + ossim_uint32 w = (CHIPS_IN_SAMPLE_DIR*SAMPLES_PER_CHIP); + ossim_uint32 h = (CHIPS_IN_LINE_DIR*LINES_PER_CHIP); + ossim_uint32 chunks_in_x_dir = size_in_x / w + (size_in_x % w ? 1 : 0); + ossim_uint32 chunks_in_y_dir = size_in_y / h + (size_in_y % h ? 1 : 0); + //*** + // Get the start of data for the "reduced_res_level" passed in. + //*** + streampos startOfData = theCcfHead.startOfData(reduced_res_level); + ossimIpt ulChunkPt = chunkOrigin; + + // Chunk loop in line direction. + for (ossim_uint32 y=0; y<chunks_in_y_dir; ++y) + { + ulChunkPt.x = chunkOrigin.x; + + // Chunk loop in sample direction. + for (ossim_uint32 x=0; x<chunks_in_x_dir; ++x) + { + //*** + // Sequence through the chips in the chunk. + // Grab the ccf data and stuff the tile buffer. + //*** + ossimIpt chip_pt = ulChunkPt; + + // Chip loop in line direction. + for (ossim_uint32 y_chip=0; y_chip<CHIPS_IN_LINE_DIR; ++y_chip) + { + chip_pt.x = ulChunkPt.x; // Reset x back to front of chunk. + + // Chip loop in sample direction. + for (ossim_uint32 x_chip=0; x_chip<CHIPS_IN_SAMPLE_DIR; ++x_chip) + { + ossimIrect chip_rect(chip_pt.x, + chip_pt.y, + chip_pt.x + CHIP_OFFSET_TO_END, + chip_pt.y + CHIP_OFFSET_TO_END); + + if (chip_rect.intersects(clip_rect)) + { + //*** + // Some point in the chip intersect the tile so grab the + // data. + //*** + + //*** + // Get the seek position for the chunk. + //*** + streampos tmp_offset + = ( ulChunkPt.y / CHUNK_SIDE_SIZE * BYTES_PER_CHUNK * + CHUNKS_IN_SAMPLE_DIR ) + + ( ulChunkPt.x / CHUNK_SIDE_SIZE * BYTES_PER_CHUNK ); + + streampos seek_position = startOfData + tmp_offset; + + // Now move it to the chip. + tmp_offset + = ( y_chip * BYTES_PER_CHIP * CHIPS_IN_SAMPLE_DIR ) + + (x_chip * BYTES_PER_CHIP); + + seek_position += tmp_offset; + + // Seek to the chip + theFileStr->seekg(seek_position, ios::beg); + + //*** + // Read the chip from the ccf file into the chip buffer. + // This will get all the bands. Bands are interleaved by + // chip. + //*** + if (!theFileStr->read((char*)theChipBuffer, BYTES_PER_CHIP)) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + cerr << "ossimCcfTileSource fillUshortBuffer READ ERROR!" + << "Returning from method." << endl; + return false; + } + + ossimIrect chip_clip_rect = clip_rect.clipToRect(chip_rect); + + //*** + // Band loop in sample direction. Bands are interleaved by + // chip. + //*** + for (ossim_uint32 band=0; band<NUMBER_OF_INPUT_BANDS; band++) + { + //*** + // Get a pointer positioned at the first valid pixel in + // the chip. + //*** + ossim_uint16* s + = (ossim_uint16*)theChipBuffer + + band * CHIP_SIZE_PER_BAND + + (chip_clip_rect.ul().y - chip_rect.ul().y) * + SAMPLES_PER_CHIP + chip_clip_rect.ul().x - + chip_rect.ul().x; + + //*** + // Get a pointer positioned at the first valid pixel in + // the tile. + //*** + ossim_uint16* d + = (ossim_uint16*)theTile->getBuf() + + band * TILE_SIZE_PER_BAND + + (chip_clip_rect.ul().y - tile_rect.ul().y) * + theTile->getWidth() + chip_clip_rect.ul().x - + tile_rect.ul().x; + + // Line loop through a chip. + for (ossim_int32 chip_line = chip_clip_rect.ul().y; + chip_line <= chip_clip_rect.lr().y; + ++chip_line) + { + // Sample loop through a chip. + ossim_uint32 i=0; + for (ossim_int32 chip_sample = chip_clip_rect.ul().x; + chip_sample <= chip_clip_rect.lr().x; + ++chip_sample) + { + if (theByteOrder == OSSIM_LITTLE_ENDIAN) + { + //*** + // CCF data alway stored in big endian byte + // order so swap the bytes. + //*** + d[i] = (s[i] << 8) | (s[i] >> 8); + } + else + { + d[i] = s[i]; + } + + ++i; + } + + // Increment the pointers by one line. + s += SAMPLES_PER_CHIP; + d += theTile->getWidth(); + } + + } // End of band loop. + + } // End of if (chip_rect.intersects(clip_rect)) + + chip_pt.x += SAMPLES_PER_CHIP; + + } // End of chip loop in the sample direction. + + chip_pt.y += LINES_PER_CHIP; + + } // End of chip loop in the line direction. + + ulChunkPt.x += CHUNK_SIDE_SIZE; + + } // End of chunk loop in the sample direction. + + ulChunkPt.y += CHUNK_SIDE_SIZE; + + } // End of chunk loop in the line direction. + + return true; +} + + +//******************************************************************* +// Public Method: +//******************************************************************* +ossimIrect +ossimCcfTileSource::getImageRectangle(ossim_uint32 reduced_res_level) const +{ + return theCcfHead.imageRect(reduced_res_level); +} + +//******************************************************************* +// Public Method: +//******************************************************************* +bool ossimCcfTileSource::setOutputBandList(const vector<ossim_uint32>& outputBandList) +{ + static const char MODULE[] = "ossimCcfTileSource::setOutputBandList"; + if (traceExec()) CLOG << "entering..." << endl; + + if (outputBandList.size() != theOutputBandList.size()) + { + //*** + // Verify that each individual band does not bust the range of input + // bands. + //*** + for (ossim_uint32 i=0; i<outputBandList.size(); i++) + { + if (outputBandList[i] > (getNumberOfInputBands() - 1)) + { + setErrorStatus(); + + cerr << MODULE << " ERROR:" + << "\nOutput band number in list is greater than the " + << "number of bands in the image source!" + << "\noutputBandList[" << i << "]: " + << "\nHighest availabe band: " + << (getNumberOfInputBands() - 1) + << "\nError status has been set! Returning..." + << endl; + return false; + } + } + + // Remove the old tiles and reallocate with the new size. + theTile = NULL; + } + + theOutputBandList = outputBandList; // Assign the new list. + + if (traceExec()) CLOG << "returning..." << endl; + return true; +} + +//******************************************************************* +// Public method: +//******************************************************************* +bool ossimCcfTileSource::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + // Currently nothing to do here. + return ossimImageHandler::saveState(kwl, prefix); +} + +//******************************************************************* +// Public method: +//******************************************************************* +bool ossimCcfTileSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + if (ossimImageHandler::loadState(kwl, prefix)) + { + if (open()) + { + return true; + } + } + + return false; +} + +//******************************************************************* +// Public method: +//******************************************************************* +bool ossimCcfTileSource::open() +{ + static const char MODULE[] = "ossimCcfTileSource::open"; + if (traceExec()) CLOG << "entering..." << endl; + + if(isOpen()) + { + close(); + } + + if (traceDebug()) + { + CLOG << "DEBUG -- " + << "\n\t theImageFile: " << theImageFile << endl; + } + + if (theCcfHead.parseCcfHeader(theImageFile.c_str()) == false) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + if (traceExec()) CLOG << "returning with error..." << endl; + return false; + } + + if (traceDebug()) + { + CLOG << "DEBUG -- " + << "\n\t theImageFile: " << theImageFile + << "\n\t theCcfHead: " << theCcfHead + << endl; + } + + theFileStr = new std::ifstream; + // Open up the file for reading. + theFileStr->open(theImageFile.c_str(), ios::in | ios::binary); + + if (!(*theFileStr)) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + + cerr << MODULE << " ERROR!" + << "\nCould not open file: " << theImageFile.c_str() + << "\nReturning..." << endl; + if (traceExec()) CLOG << "returning with error..." << endl; + + delete theFileStr; + theFileStr = NULL; + return false; + } + + theTile = ossimImageDataFactory::instance()->create(this, this); + theTile->initialize(); + + theChipBuffer = new ossim_uint8[theCcfHead.bytesPerChip()]; + + // Initialize the output band list. + if (getNumberOfInputBands() > theOutputBandList.size()) + { + theOutputBandList.resize(getNumberOfInputBands()); + } + + for (ossim_uint32 i=0; i<getNumberOfInputBands(); ++i) + { + theOutputBandList[i] = i; // One to one for initial setup. + } + + completeOpen(); + + if (traceDebug() && theTile.valid()) + { + CLOG << "DEBUG:" + << "\ntheTile:\n" << *theTile << endl; + } + + if (traceExec()) CLOG << "returning..." << endl; + return true; +} + +void ossimCcfTileSource::close() +{ + theTile = NULL; + if (theChipBuffer) + { + delete [] theChipBuffer; + theChipBuffer = NULL; + } + if(theFileStr) + { + theFileStr->close(); + theFileStr->clear(); + delete theFileStr; + theFileStr = NULL; + } +} + +//******************************************************************* +// Public method: +//******************************************************************* +ossimScalarType ossimCcfTileSource::getOutputScalarType() const +{ + return theCcfHead.pixelType(); +} + +//******************************************************************* +// Public method: +//******************************************************************* +ossim_uint32 ossimCcfTileSource::getTileWidth() const +{ + return ( theTile.valid() ? theTile->getWidth() : 0 ); +} + +//******************************************************************* +// Public method: +//******************************************************************* +ossim_uint32 ossimCcfTileSource::getTileHeight() const +{ + return ( theTile.valid() ? theTile->getHeight() : 0 ); +} + +ossim_uint32 ossimCcfTileSource::getImageTileWidth() const +{ + return 32; +} + +ossim_uint32 ossimCcfTileSource::getImageTileHeight() const +{ + return 32; +} + +void ossimCcfTileSource::initVerticesFromHeader() +{ + theValidImageVertices.clear(); + + const vector<ossimIpt>& validImageVertices + = theCcfHead.getValidImageVertices(); + + ossim_uint32 upper = validImageVertices.size(); + if(!upper) return; + for(ossim_uint32 index = 0; index < upper; ++index) + { + theValidImageVertices.push_back(validImageVertices[index]); + } + + if (traceDebug()) + { + cout << "ossimCcfTileSource::initVerticesFromHeader DEBUG:" + << "\nValid image vertices:" + << endl; + for (ossim_uint32 i=0; i<upper; ++i) + { + cout << "\npoint[" << i << "]: " << theValidImageVertices[i]; + } + cout << endl; + } +} + +bool ossimCcfTileSource::isEcgGeom(const ossimFilename& filename)const +{ + ossimFilename file = filename; + file.setExtension("geom"); + + if(file.exists()) + { + char bytes[3]; + ifstream in(file.c_str()); + + in.read((char*)bytes, 3); + ossimString testEcg(bytes, + bytes + 3); + testEcg = testEcg.downcase(); + if(in&&(testEcg == "ecg")) + { + return true; + } + } + return false; +} + +ossimString ossimCcfTileSource::getShortName()const +{ + return ossimString("ccf"); +} + +ossimString ossimCcfTileSource::getLongName()const +{ + return ossimString("ccf reader"); +} + +ossimString ossimCcfTileSource::className()const +{ + return ossimString("ossimCcfTileSource"); +} + +ossim_uint32 ossimCcfTileSource::getNumberOfInputBands() const +{ + return theCcfHead.numberOfBands(); +} + +ossim_uint32 ossimCcfTileSource::getNumberOfOutputBands()const +{ + return getNumberOfInputBands(); +} + +ossim_uint32 ossimCcfTileSource::getNumberOfLines(ossim_uint32 reduced_res_level) const +{ + return theCcfHead.numberOfLines(reduced_res_level); +} + +ossim_uint32 ossimCcfTileSource::getNumberOfSamples(ossim_uint32 reduced_res_level) const +{ + return theCcfHead.numberOfSamples(reduced_res_level); +} + +ossim_uint32 ossimCcfTileSource::getNumberOfDecimationLevels() const +{ + return theCcfHead.numberOfReducedResSets(); +} + +bool ossimCcfTileSource::isOpen()const +{ + return (theFileStr != NULL); +} + +void ossimCcfTileSource::adjustToStartOfChunk(ossimIpt& pt) const +{ + pt.x &= 0xffffff00; + pt.y &= 0xffffff00; +} + +void ossimCcfTileSource::adjustToStartOfChip(ossimIpt& pt) const +{ + pt.x &= 0xffffffe0; + pt.y &= 0xffffffe0; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/ccf/ossimCcfTileSource.h b/Utilities/OSSIM/ossim_core/imaging/formats/ccf/ossimCcfTileSource.h new file mode 100644 index 0000000000..194c4ea7cc --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/ccf/ossimCcfTileSource.h @@ -0,0 +1,202 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class declaration for CcfTileSource. +// +// A ccf (Chip Chunk Format) is a double tiled format. Image data is +// arranged in chips and chunks. Each chip is 32 x 32 pixels. Each chunk +// is 8 x 8 chips for a single band image. Bands are interleaved by chip +// so a rgb image has a red chip a green chip, then a blue chip which +// would make the chunk 24 x 8 chips. +// +//******************************************************************* +// $Id: ossimCcfTileSource.h,v 1.26 2005/07/25 22:44:41 dburken Exp $ + +#ifndef ossimCcfTileSource_HEADER +#define ossimCcfTileSource_HEADER + +#include <fstream> +using namespace std; + +#include <imaging/formats/ossimImageHandler.h> +#include <imaging/formats/ccf/ossimCcfHead.h> + +class ossimImageData; + +class OSSIM_DLL ossimCcfTileSource : public ossimImageHandler +{ +public: + + ossimCcfTileSource(); + virtual ~ossimCcfTileSource(); + + virtual ossimString getShortName()const; + virtual ossimString getLongName()const; + virtual ossimString className()const; + + /** + * @return Returns true on success, false on error. + * + * @note This method relies on the data member ossimImageData::theImageFile + * being set. Callers should do a "setFilename" prior to calling this + * method or use the ossimImageHandler::open that takes a file name and an + * entry index. + */ + virtual bool open(); + + virtual void close(); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect, + ossim_uint32 resLevel=0); + + /** + * Returns the number of bands in the image. + * Satisfies pure virtual from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfInputBands() const; + virtual ossim_uint32 getNumberOfOutputBands()const; + + /** + * Returns the number of lines in the image. + * Satisfies pure virtual from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfLines(ossim_uint32 reduced_res_level = 0) const; + + /** + * Returns the number of samples in the image. + * Satisfies pure virtual from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfSamples(ossim_uint32 reduced_res_level = 0) const; + + /** + * Returns the number of reduced resolution data sets (rrds). + * Note: The full res image is counted as a data set so an image with no + * reduced resolution data set will have a count of one. + */ + virtual ossim_uint32 getNumberOfDecimationLevels() const; + + /** + * Returns the zero based image rectangle for the reduced resolution data + * set (rrds) passed in. Note that rrds 0 is the highest resolution rrds. + */ + virtual ossimIrect getImageRectangle(ossim_uint32 reduced_res_level = 0) const; + + /** + * Set the output band list. Use to set the number and order of output + * bands. Will set an error if out of range. + */ + bool setOutputBandList(const vector<ossim_uint32>& outputBandList); + + /** + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * Returns the output pixel type of the tile source. + */ + virtual ossimScalarType getOutputScalarType() const; + + /** + * Returns the width of the output tile. + */ + virtual ossim_uint32 getTileWidth() const; + + /** + * Returns the height of the output tile. + */ + virtual ossim_uint32 getTileHeight() const; + + /** + * Returns the tile width of the image or 0 if the image is not tiled. + * Note: this is not the same as the ossimImageSource::getTileWidth which + * returns the output tile width which can be different than the internal + * image tile width on disk. + */ + virtual ossim_uint32 getImageTileWidth() const; + + /** + * Returns the tile width of the image or 0 if the image is not tiled. + * Note: this is not the same as the ossimImageSource::getTileWidth which + * returns the output tile width which can be different than the internal + * image tile width on disk. + */ + virtual ossim_uint32 getImageTileHeight() const; + + virtual bool isOpen()const; + + + +private: + + void initVerticesFromHeader(); + + // Disallow these... + ossimCcfTileSource(const ossimCcfTileSource& source); + ossimCcfTileSource& operator=(const ossimCcfTileSource& source); + + /** + * Returns true on success, false on error. + */ + bool fillBuffer(const ossimIrect& tile_rect, + const ossimIrect& clip_rect, + const ossimIrect& image_rect, + ossim_uint32 reduced_res_level); + + /** + * Returns true on success, false on error. + */ + bool fillUshortBuffer(const ossimIrect& tile_rect, + const ossimIrect& clip_rect, + const ossimIrect& image_rect, + ossim_uint32 reduced_res_level); + + /** + * Returns true on success, false on error. + */ + bool fillUcharBuffer(const ossimIrect& tile_rect, + const ossimIrect& clip_rect, + const ossimIrect& image_rect, + ossim_uint32 reduced_res_level); + + /** + * Adjust point to even 256 boundary. Assumes 0,0 origin. + */ + void adjustToStartOfChunk(ossimIpt& pt) const; + + /** + * Adjust point to even 32 boundary. Assumes 0,0 origin. + */ + void adjustToStartOfChip(ossimIpt& pt) const; + + bool isEcgGeom(const ossimFilename& filename)const; + + ossimCcfHead theCcfHead; + ossimRefPtr<ossimImageData> theTile; + ossim_uint8* theChipBuffer; + ifstream* theFileStr; + vector<ossim_uint32> theOutputBandList; + ossim_int32 theByteOrder; + + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/cibcadrg/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/formats/cibcadrg/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/cibcadrg/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/cibcadrg/ossimCibCadrgTileSource.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/cibcadrg/ossimCibCadrgTileSource.cpp new file mode 100644 index 0000000000..8342f3872b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/cibcadrg/ossimCibCadrgTileSource.cpp @@ -0,0 +1,1423 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************** +// $Id: ossimCibCadrgTileSource.cpp,v 1.86 2005/08/29 19:56:41 gpotts Exp $ +#include <algorithm> +using namespace std; + +#include <imaging/formats/cibcadrg/ossimCibCadrgTileSource.h> + +#include <base/common/ossimStdOutProgress.h> +#include <base/common/ossimNBandLutDataObject.h> +#include <imaging/histogram/ossimHistogramWriter.h> +#include <imaging/histogram/ossimImageHistogramSource.h> +#include <base/common/ossimConstants.h> +#include <base/common/ossimCommon.h> +#include <base/common/ossimKeywordNames.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ellipse/ossimEllipsoid.h> +#include <base/data_types/datum/ossimDatum.h> +#include <support_data/rpf/ossimRpfFrame.h> +#include <support_data/rpf/ossimRpfHeader.h> +#include <support_data/rpf/ossimRpfToc.h> +#include <support_data/rpf/ossimRpfTocEntry.h> +#include <support_data/rpf/ossimRpfCompressionSection.h> +#include <imaging/formats/tiff/ossimTiffTileSource.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <projections/map_projections/ossimEquDistCylProjection.h> +#include <projections/map_projections/ossimCylEquAreaProjection.h> +#include <base/misc/ossimEndian.h> +#include <base/common/ossimTrace.h> + +static ossimTrace traceDebug = ossimTrace("ossimCibCadrgTileSource:debug"); + +#ifdef OSSIM_ID_ENABLED +static const char OSSIM_ID[] = "$Id: ossimCibCadrgTileSource.cpp,v 1.86 2005/08/29 19:56:41 gpotts Exp $"; +#endif + +RTTI_DEF1(ossimCibCadrgTileSource, "ossimCibCadrgTileSource", ossimImageHandler) + +const ossim_uint32 ossimCibCadrgTileSource::CIBCADRG_FRAME_WIDTH = 1536; +const ossim_uint32 ossimCibCadrgTileSource::CIBCADRG_FRAME_HEIGHT = 1536; + +ossimCibCadrgTileSource::ossimCibCadrgTileSource() + :ossimImageHandler(), + theCompressedBuffer(NULL), + theUncompressedBuffer(NULL), + theNumberOfLines(0), + theNumberOfSamples(0), + theTile(NULL), + theTableOfContents(NULL), + theEntryToRender(NULL), + theEntryNumberToRender(1), + theTileSize(128, 128), + theProductType(OSSIM_PRODUCT_TYPE_UNKNOWN) +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimCibCadrgTileSource::ossimCibCadrgTileSource entered...\n"; +#ifdef OSSIM_ID_ENABLED + ossimNotify(ossimNotifyLevel_DEBUG) + << "OSSIM_ID: " << OSSIM_ID << "\n"; +#endif + } + theWorkFrame = new ossimRpfFrame; + + theActualImageRect.makeNan(); + + // a CADRG and CIBis a 64*64*12 bit buffer and must divide by 8 to + // convert to bytes + theCompressedBuffer = new ossim_uint8[(64*64*12)/8]; + + // whether CIB or CADRG we will alocate the buffer + // to the larger of the 2 (CADRG is 3 bands) + theUncompressedBuffer = new ossim_uint8[256*256*3]; + +} + +ossimCibCadrgTileSource::~ossimCibCadrgTileSource() +{ + if(theCompressedBuffer) + { + delete [] theCompressedBuffer; + theCompressedBuffer = 0; + } + if(theUncompressedBuffer) + { + delete [] theUncompressedBuffer; + theUncompressedBuffer = 0; + } + if(theWorkFrame) + { + delete theWorkFrame; + theWorkFrame = 0; + } + close(); +} + +ossimString ossimCibCadrgTileSource::getShortName()const +{ + return ossimString("CIB/CADRG"); +} + +ossimString ossimCibCadrgTileSource::getLongName()const +{ + return ossimString("CIB/CADRG reader"); +} + + +void ossimCibCadrgTileSource::close() +{ + deleteAll(); +} + +bool ossimCibCadrgTileSource::isOpen()const +{ + return (theTableOfContents!=NULL); +} + +bool ossimCibCadrgTileSource::open() +{ + ossimFilename imageFile = theImageFile; + bool result = true; + if(isOpen()) + { + close(); + } + + theTableOfContents = new ossimRpfToc; + + if(theTableOfContents) + { + if(theTableOfContents->parseFile(imageFile) == ossimErrorCodes::OSSIM_OK) + { + if(theTableOfContents->getNumberOfEntries() > 0) + { + vector<ossimString> scaleList = getProductScaleList(); + if(scaleList.size() > 0) + { + vector<long> entryList = getProductEntryList(scaleList[0]); + if(entryList.size() > 0) + { + //open(imageFile, entryList[0]); + setCurrentEntry(entryList[0]); + + if(theEntryToRender) + { + // a CADRG is 1536x1536 per frame. + theNumberOfLines = theEntryToRender->getNumberOfFramesVertical()*CIBCADRG_FRAME_HEIGHT; + theNumberOfSamples = theEntryToRender->getNumberOfFramesHorizontal()*CIBCADRG_FRAME_WIDTH; + } + else // we didn't find a frame to render + { + result = false; + } + if(theEntryToRender->getProductType().trim().upcase() == "CADRG") + { + theProductType = OSSIM_PRODUCT_TYPE_CADRG; + } + else if(theEntryToRender->getProductType().trim().upcase() == "CIB") + { + theProductType = OSSIM_PRODUCT_TYPE_CIB; + } + else + { + result = false; + } + allocateForProduct(); + } + else + { + result = false; + } + } + else + { + result = false; + } + } + else + { + result = false; + } + } + else + { + result = false; + } + } + else + { + result = false; + } + + if(!result) + { + close(); + } + else + { + //--- + // Adjust image rect so not to go over the -180 to 180 and -90 to 90 + // bounds. + //--- + setActualImageRect(); + + // Set the base class image file name. + theImageFile = imageFile; + + completeOpen(); + + theTile = ossimImageDataFactory::instance()->create(this, this); + theTile->initialize(); + } + + return result; +} + +ossimRefPtr<ossimImageData> ossimCibCadrgTileSource::getTile( + const ossimIrect& rect, ossim_uint32 resLevel) +{ + ossimIpt origin = rect.ul(); + + if(!isOpen()) + { + return ossimRefPtr<ossimImageData>(); + } + ossimIrect imageRect = getImageRectangle(); + if( (!rect.intersects(imageRect) )|| + (theProductType == OSSIM_PRODUCT_TYPE_UNKNOWN) ) + { + return ossimRefPtr<ossimImageData>(); + } + + theTile->setImageRectangle(rect); + if (theOverview) + { + if (theOverview->hasR0() || resLevel) + { + return theOverview->getTile(rect, resLevel); + } + } + + vector<ossimFrameEntryData> frames = getIntersectingEntries(rect); + if(frames.size() > 0) + { + theTile->makeBlank(); + // now lets render each frame. Note we will have to find subframes + // that intersect the rectangle of interest for each frame. + // + fillTile(rect, frames); + } + else + { + return ossimRefPtr<ossimImageData>(); + } + + theTile->validate(); + + return theTile; +} + +ossim_uint32 ossimCibCadrgTileSource::getNumberOfInputBands()const +{ + switch(theProductType) + { + case OSSIM_PRODUCT_TYPE_UNKNOWN: + { + return 0; + } + case OSSIM_PRODUCT_TYPE_CIB: + { + return 1; + } + case OSSIM_PRODUCT_TYPE_CADRG: + { + return 3; + } + } + + return 0; +} + +ossim_uint32 ossimCibCadrgTileSource::getNumberOfOutputBands()const +{ + switch(theProductType) + { + case OSSIM_PRODUCT_TYPE_UNKNOWN: + { + return 0; + } + case OSSIM_PRODUCT_TYPE_CIB: + { + return 1; + } + case OSSIM_PRODUCT_TYPE_CADRG: + { + return 3; + } + } + + return 0; +} + +ossim_uint32 ossimCibCadrgTileSource::getNumberOfLines(ossim_uint32 reduced_res_level) const +{ + if (reduced_res_level == 0) + { + return theNumberOfLines; + } + else if (theOverview) + { + return theOverview->getNumberOfLines(reduced_res_level); + } + + return 0; +} + +ossim_uint32 ossimCibCadrgTileSource::getNumberOfSamples(ossim_uint32 reduced_res_level) const +{ + if (reduced_res_level == 0) + { + return theNumberOfSamples; + } + else if (theOverview) + { + return theOverview->getNumberOfSamples(reduced_res_level); + } + + return 0; +} + +void ossimCibCadrgTileSource::setActualImageRect() +{ + ossimRpfBoundaryRectRecord boundaryInfo = theEntryToRender->getBoundaryInformation(); + ossimGpt ul(boundaryInfo.getCoverage().getUlLat(), + boundaryInfo.getCoverage().getUlLon()); +// ossimGpt ll(boundaryInfo.getCoverage().getLlLat(), +// boundaryInfo.getCoverage().getLlLon()); +// ossimGpt ur(boundaryInfo.getCoverage().getUrLat(), +// boundaryInfo.getCoverage().getUrLon()); + ossimGpt lr(boundaryInfo.getCoverage().getLrLat(), + boundaryInfo.getCoverage().getLrLon()); + + double latInterval = boundaryInfo.getCoverage().getVerticalInterval(); + double lonInterval = boundaryInfo.getCoverage().getHorizontalInterval(); + + int lines = irint(fabs(ul.lat - lr.lat)/latInterval); + int samples = irint(fabs(ul.lon - lr.lon)/lonInterval); + + + theNumberOfLines = lines; + theNumberOfSamples = samples; + + theActualImageRect = ossimIrect(0,0,theNumberOfLines, theNumberOfSamples); + +} + +ossimIrect ossimCibCadrgTileSource::getImageRectangle(ossim_uint32 reduced_res_level) const +{ + return ossimIrect(0, // upper left x + 0, // upper left y + getNumberOfSamples(reduced_res_level) - 1, // lower right x + getNumberOfLines(reduced_res_level) - 1); // lower right y +} + + + +bool ossimCibCadrgTileSource::getImageGeometry(ossimKeywordlist& kwl, + const char* prefix) +{ + if(!theEntryToRender) + { + return false; + } + + if (theGeometryKwl.getSize()) + { + kwl = theGeometryKwl; + return true; + } + + // datum + // WGS 84 + kwl.add(prefix, + ossimKeywordNames::DATUM_KW, + "WGE", + true); + + ossimRpfBoundaryRectRecord boundaryInfo = theEntryToRender->getBoundaryInformation(); + + ossimGpt ul(boundaryInfo.getCoverage().getUlLat(), + boundaryInfo.getCoverage().getUlLon()); + ossimGpt ll(boundaryInfo.getCoverage().getLlLat(), + boundaryInfo.getCoverage().getLlLon()); + ossimGpt ur(boundaryInfo.getCoverage().getUrLat(), + boundaryInfo.getCoverage().getUrLon()); + ossimGpt lr(boundaryInfo.getCoverage().getLrLat(), + boundaryInfo.getCoverage().getLrLon()); + + +// double latInterval = fabs(ul.latd() - lr.latd())/ getNumberOfLines(); +// double lonInterval = fabs(ul.lond() - ur.lond())/ getNumberOfSamples(); + double latInterval = boundaryInfo.getCoverage().getVerticalInterval(); + double lonInterval = boundaryInfo.getCoverage().getHorizontalInterval(); + + + // double latInterval = boundaryInfo.getCoverage().getVerticalInterval(); + // double lonInterval = boundaryInfo.getCoverage().getHorizontalInterval(); + + kwl.add(prefix, + ossimKeywordNames::UL_LAT_KW, + ul.latd(),//-(latInterval/2.0), + true); + + kwl.add(prefix, + ossimKeywordNames::UL_LON_KW, + ul.lond(),//+(lonInterval/2.0), + true); + + kwl.add(prefix, + ossimKeywordNames::LL_LAT_KW, + ll.latd(),//+(latInterval/2.0), + true); + + kwl.add(prefix, + ossimKeywordNames::LL_LON_KW, + ll.lond(),//+(lonInterval/2.0), + true); + + kwl.add(prefix, + ossimKeywordNames::LR_LAT_KW, + lr.latd(),//+(latInterval/2.0), + true); + + kwl.add(prefix, + ossimKeywordNames::LR_LON_KW, + lr.lond(),//-(lonInterval/2.0), + true); + + kwl.add(prefix, + ossimKeywordNames::UR_LAT_KW, + ur.latd(),//-(latInterval/2.0), + true); + + kwl.add(prefix, + ossimKeywordNames::UR_LON_KW, + ur.lond(),//-(latInterval/2.0), + true); + + + kwl.add(prefix, + ossimKeywordNames::NUMBER_INPUT_BANDS_KW, + getNumberOfInputBands(), + true); + + kwl.add(prefix, + ossimKeywordNames::NUMBER_OUTPUT_BANDS_KW, + getNumberOfOutputBands(), + true); + + kwl.add(prefix, + ossimKeywordNames::NUMBER_LINES_KW, + getNumberOfLines(), + true); + + kwl.add(prefix, + ossimKeywordNames::NUMBER_SAMPLES_KW, + getNumberOfSamples(), + true); + + + //*** + // Make a projection to get the easting / northing of the tie point and + // the scale in meters. This will only be used by the CIB. + //*** +// const ossimDatum* datum = ossimDatumFactory::instance()->wgs84(); + + kwl.add(prefix, + ossimKeywordNames::DATUM_KW, + "WGE", + true); + + ossimGpt origin((ul.latd()+lr.latd())*.5, + (ul.lond()+lr.lond())*.5, + 0.0); + + double deltaLatPerPixel = latInterval; + double deltaLonPerPixel = lonInterval; + + ossimDpt tie; + + tie.lat = boundaryInfo.getCoverage().getUlLat() - deltaLatPerPixel/2.0; + tie.lon = boundaryInfo.getCoverage().getUlLon() + deltaLonPerPixel/2.0; + + kwl.add(prefix, + ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LAT, + deltaLatPerPixel, + true); + + kwl.add(prefix, + ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LON, + deltaLonPerPixel, + true); + + kwl.add(prefix, + ossimKeywordNames::ORIGIN_LATITUDE_KW, + origin.latd(), + true); + + kwl.add(prefix, + ossimKeywordNames::CENTRAL_MERIDIAN_KW, + origin.lond(), + true); + + kwl.add(prefix, + ossimKeywordNames::TIE_POINT_LAT_KW, + ul.latd()-(deltaLatPerPixel/2.0), + true); + + kwl.add(prefix, + ossimKeywordNames::TIE_POINT_LON_KW, + ul.lond()+(deltaLonPerPixel/2.0), + true); + + + int z = boundaryInfo.getZone(); + + if (z == 74) z--; // Fix J to a zone. + if (z > 64) z -= 64; // Below the equator + else z -= 48; // Above the equator + + kwl.add(prefix, + ossimKeywordNames::ZONE_KW, + z, + true); + + if(z!=9) + { + kwl.add(prefix, + ossimKeywordNames::TYPE_KW, + "ossimEquDistCylProjection", + true); + } + else + { + kwl.add(prefix, + ossimKeywordNames::TYPE_KW, + "ossimAzimEquDistProjection", + true); + } + + if(theProductType == OSSIM_PRODUCT_TYPE_CADRG) + { + + ossimString scale = boundaryInfo.getScale(); + scale = scale.after(":").upcase(); + scale = scale.trim(); + + double scaleValue = 1000000; + if(scale == "5M") + { + scaleValue = 5000000; + } + else if(scale == "2M") + { + scaleValue = 2000000; + } + else if(scale == "1M") + { + scaleValue = 1000000; + } + else if(scale == "500K") + { + scaleValue = 500000; + } + else if(scale == "250K") + { + scaleValue = 250000; + } + else if(scale == "100K") + { + scaleValue = 100000; + } + else if(scale == "50K") + { + scaleValue = 50000; + } + else if(scale == "25K") + { + scaleValue = 25000; + } + else if(scale == "20K") + { + scaleValue = 20000; + } + else if(scale == "15K") + { + scaleValue = 15000; + } + else if(scale == "12,500") + { + scaleValue = 12500; + } + else if(scale == "10K") + { + scaleValue = 10000; + } + else + { + cout << "ossimCibCadrgTileSource::getImageGeometry: scale not supported for projection --> " << scale << endl; + } + + kwl.add(prefix, + "map_scale", + scaleValue, + true); + } + else if(theProductType == OSSIM_PRODUCT_TYPE_CIB) + { + ossimString scale = boundaryInfo.getScale(); + scale = scale.upcase(); + scale = scale.trim('M'); + + // from the CIB spec the scale is equivalent to + // a CADRG by the following formula + // + // 100*10^-6/<meter product> + // + // where <meter product is 10, 5 ....etc + // + double scaleValue = 1.0/((100.0/1000000.0) / scale.toDouble()); + + kwl.add(prefix, + "map_scale", + scaleValue, + true); + } + + setImageGeometry(kwl); + + return true; +} + +ossimScalarType ossimCibCadrgTileSource::getOutputScalarType() const +{ + return OSSIM_UCHAR; +} + +ossim_uint32 ossimCibCadrgTileSource::getTileWidth() const +{ + return theTileSize.x; +} + +ossim_uint32 ossimCibCadrgTileSource::getTileHeight() const +{ + return theTileSize.y; +} + +ossim_uint32 ossimCibCadrgTileSource::getCurrentEntry()const +{ + return (ossim_uint32)theEntryNumberToRender; +} + +bool ossimCibCadrgTileSource::setCurrentEntry(ossim_uint32 entryIdx) +{ + theGeometryKwl.clear(); + if(!setEntryToRender(entryIdx)) + { + return false; + } + completeOpen(); + + return true; +} + +void ossimCibCadrgTileSource::getEntryList(std::vector<ossim_uint32>& entryList)const +{ + std::vector<ossimString> scaleList = getProductScaleList(); + ossim_uint32 scaleIdx = 0; + ossim_uint32 entryIdx = 0; + for(scaleIdx = 0; scaleIdx < scaleList.size(); ++scaleIdx) + { + std::vector<long> eList = getProductEntryList(scaleList[scaleIdx]); + + for(entryIdx = 0; entryIdx < eList.size(); ++entryIdx) + { + entryList.push_back(eList[entryIdx]); + } + } + +} + +bool ossimCibCadrgTileSource::setEntryToRender(ossim_uint32 index) +{ + if(isOpen()) + { + const ossimRpfTocEntry *temp = theTableOfContents->getTocEntry(index); + + if(temp) + { + if(!(temp->getBoundaryInformation().getCoverage().isGeographicRectNull())) + { + setTocEntryToRender(temp); + theEntryNumberToRender = index; + if(theEntryToRender) + { + if(theEntryToRender->getProductType().trim().upcase() == "CADRG") + { + theProductType = OSSIM_PRODUCT_TYPE_CADRG; + } + else if(theEntryToRender->getProductType().trim().upcase() == "CIB") + { + theProductType = OSSIM_PRODUCT_TYPE_CIB; + } + else + { + theProductType = OSSIM_PRODUCT_TYPE_UNKNOWN; + } + } + + populateLut(); + + return true; + } + } + } + + return false; +} + +void ossimCibCadrgTileSource::setTocEntryToRender(const ossimRpfTocEntry* entry) +{ + if(isOpen()&&entry) + { + // a CIB is 1536x1536 per frame. + theEntryToRender = entry; + theNumberOfLines = theEntryToRender->getNumberOfFramesVertical()*CIBCADRG_FRAME_HEIGHT; + theNumberOfSamples = theEntryToRender->getNumberOfFramesHorizontal()*CIBCADRG_FRAME_HEIGHT; + theEntryNumberToRender = theTableOfContents->getTocEntryIndex(entry); + } +} + +ossim_int32 ossimCibCadrgTileSource::getCurrentEntryIndex()const +{ + return theEntryNumberToRender; +} + +const ossimRpfTocEntry* ossimCibCadrgTileSource::getCurrentTocEntry()const +{ + return theEntryToRender; +} + +const ossimRpfToc* ossimCibCadrgTileSource::getToc()const +{ + return theTableOfContents; +} + +bool ossimCibCadrgTileSource::isValidRLevel(ossim_uint32 reduced_res_level) const +{ + if (reduced_res_level == 0) + { + return true; + } + else if (theOverview) + { + return theOverview->isValidRLevel(reduced_res_level); + } + else + { + return false; + } +} + +vector<ossimString> ossimCibCadrgTileSource::getProductScaleList()const +{ + vector<ossimString> result; + + if(isOpen()) + { + long upperBound = theTableOfContents->getNumberOfEntries(); + for(long index = 0; index < upperBound; ++index) + { + const ossimRpfTocEntry* entry = theTableOfContents->getTocEntry(index); + ossimString scale = entry->getBoundaryInformation().getScale(); + + scale = scale.trim().upcase(); + if(scale!="") + { + // CIB will have product scales like 5M or 10M + // and CADRG's will have product scales like + // 1:50K and 1:250K ... + // So if these patterns exist then add it to + // the product list. + if((std::find(scale.begin(), scale.end(), ':') != scale.end()) || + (scale[(int)scale.size()-1]=='M')) + { + // only add it if it doesn't already exist + // on the list. + if(find(result.begin(), result.end(), scale) == result.end()) + { + result.push_back(scale); + } + } + } + } + } + + return result; +} + +vector<long> ossimCibCadrgTileSource::getProductEntryList(const ossimString& productScale)const +{ + vector<long> result; + + if(isOpen()) + { + long upperBound = theTableOfContents->getNumberOfEntries(); + for(long index = 0; index < upperBound; ++index) + { + const ossimRpfTocEntry* entry = theTableOfContents->getTocEntry(index); + + if(entry) + { + // if the entry is not empty then add it to the list. + // + if(!entry->isEmpty()) + { + ossimString scale = entry->getBoundaryInformation().getScale(); + scale = scale.trim().upcase(); + if(scale==productScale) + { + result.push_back(index); + } + } + } + } + } + + return result; + +} + +vector<ossimCibCadrgTileSource::ossimFrameEntryData> ossimCibCadrgTileSource::getIntersectingEntries(const ossimIrect& rect) +{ + vector<ossimFrameEntryData> result; + + // make sure we have the Toc entry to render + if(!isOpen()) return result; + + ossimIrect imageRect = getImageRectangle(); + if(rect.intersects(imageRect)) + { + ossimIrect clipRect = rect.clipToRect(imageRect); + ossimIrect frameRect(clipRect.ul().x/CIBCADRG_FRAME_WIDTH, + clipRect.ul().y/CIBCADRG_FRAME_HEIGHT, + clipRect.lr().x/CIBCADRG_FRAME_WIDTH, + clipRect.lr().y/CIBCADRG_FRAME_HEIGHT); + + ossimRpfFrameEntry tempEntry; + + + for(long row = frameRect.ul().y; row <= frameRect.lr().y; ++row) + { + for(long col = frameRect.ul().x; col <= frameRect.lr().x; ++col) + { + if(theEntryToRender->getEntry((theEntryToRender->getNumberOfFramesVertical()-1) - row, + col, + tempEntry)) + { + if(tempEntry.exists()) + { + result.push_back(ossimFrameEntryData(row, + col, + row*CIBCADRG_FRAME_HEIGHT, + col*CIBCADRG_FRAME_WIDTH, + tempEntry)); + } + } + } + } + } + + return result; +} + +void ossimCibCadrgTileSource::fillTile(const ossimIrect& tileRect, + const vector<ossimFrameEntryData>& framesInvolved) +{ + ossim_uint32 idx = 0; + for(idx = 0; + idx < framesInvolved.size(); + ++idx) + { + + if(theWorkFrame->parseFile(framesInvolved[idx].theFrameEntry.getFullPath()) + == ossimErrorCodes::OSSIM_OK) + { + // we will fill a subtile. We pass in which frame it is and the position of the frame. + // the actual pixel will be 1536*row and 1536 *col. + if(theProductType == OSSIM_PRODUCT_TYPE_CIB) + { + fillSubTileCib(*theWorkFrame, + tileRect, + framesInvolved[idx]); + } + else + { + fillSubTileCadrg(*theWorkFrame, + tileRect, + framesInvolved[idx]); + } + } + } +} + +void ossimCibCadrgTileSource::fillSubTileCadrg(const ossimRpfFrame& aFrame, + const ossimIrect& tileRect, + const ossimFrameEntryData& frameEntryData) +{; + // first let's grab the absolute position of the frame rectangle in pixel space + ossimIrect frameRect(frameEntryData.thePixelCol, + frameEntryData.thePixelRow, + frameEntryData.thePixelCol + CIBCADRG_FRAME_WIDTH - 1, + frameEntryData.thePixelRow + CIBCADRG_FRAME_HEIGHT - 1); + + + // now clip it to the tile + ossimIrect clipRect = tileRect.clipToRect(frameRect); + + const ossimRpfCompressionSection* compressionSection = aFrame.getCompressionSection(); + + if(!compressionSection) + { + return; + } + + ossim_uint8 *tempRows[3]; + + tempRows[0] = theUncompressedBuffer; + tempRows[1] = (theUncompressedBuffer + 256*256); + tempRows[2] = (tempRows[1] + 256*256); + + // find the shift to 0,0 + ossimIpt tempDelta(clipRect.ul().x - frameEntryData.thePixelCol, + clipRect.ul().y - frameEntryData.thePixelRow); + + + // In order to compute the subframe we will need the corner offsets of + // the upper left of the frame and the upper left of the clip rect. The + // clip rect should be completely within the frame. This just translates the value + // to make the upper left of the frame be 0,0. + // + ossimIrect offsetRect(tempDelta.x, + tempDelta.y, + tempDelta.x + clipRect.width()-1, + tempDelta.y + clipRect.height()-1); + + // each subframe is 64x64. We will actually use 256x256 since + // we will be uncompressing them. Note CADRG is a 256x256 tile + // compressed to 64x64x12 bit data + // + ossimIrect subFrameRect(offsetRect.ul().x/256, + offsetRect.ul().y/256, + (offsetRect.lr().x)/256, + (offsetRect.lr().y)/256); + + ossim_uint32 readPtr = 0; + const vector<ossimRpfColorGrayscaleTable>& colorTable = + aFrame.getColorGrayscaleTable(); + + long row = 0; + long col = 0; + ossim_uint32 i = 0; + ossim_uint32 j = 0; + long upperY = subFrameRect.lr().y; + long upperX = subFrameRect.lr().x; + long lowerY = subFrameRect.ul().y; + long lowerX = subFrameRect.ul().x; + for(row = lowerY; row <= upperY; ++row) + { + for(col = lowerX; col <= upperX; ++col) + { + readPtr = 0; + if(aFrame.fillSubFrameBuffer(theCompressedBuffer, 0, row, col)) + { + for (i = 0; i < 256; i += 4) + { + for (j = 0; j < 256; j += 8) + { + ossim_uint16 firstByte = theCompressedBuffer[readPtr++] & 0xff; + ossim_uint16 secondByte = theCompressedBuffer[readPtr++] & 0xff; + ossim_uint16 thirdByte = theCompressedBuffer[readPtr++] & 0xff; + + //because dealing with half-bytes is hard, we + //uncompress two 4x4 tiles at the same time. (a + //4x4 tile compressed is 12 bits ) + // this little code was grabbed from openmap software. + + /* Get first 12-bit value as index into VQ table */ + // I think we need to swap + ossim_uint16 val1 = (firstByte << 4) | (secondByte >> 4); + + /* Get second 12-bit value as index into VQ table*/ + ossim_uint16 val2 = ((secondByte & 0x000F) << 8) | thirdByte; + + for (ossim_uint32 t = 0; t < 4; ++t) + { + for (ossim_uint32 e = 0; e < 4; ++e) + { + ossim_uint16 tableVal1 = compressionSection->getTable()[t].theData[val1*4 + e] & 0xff; + ossim_uint16 tableVal2 = compressionSection->getTable()[t].theData[val2*4 + e] & 0xff; + + ossim_uint32 pixindex = ((i+t)*256) + + (j + e); + const ossim_uint8* color1 = colorTable[0].getStartOfData(tableVal1); + const ossim_uint8* color2 = colorTable[0].getStartOfData(tableVal2); + + + tempRows[0][pixindex] = color1[0]; + tempRows[1][pixindex] = color1[1]; + tempRows[2][pixindex] = color1[2]; + + tempRows[0][pixindex+4] = color2[0]; + tempRows[1][pixindex+4] = color2[1]; + tempRows[2][pixindex+4] = color2[2]; + } //for e + } //for t + } /* for j */ + } //for i + } + else + { + memset(theUncompressedBuffer, 0, 256*256*3); + } + long tempCol = col*256; + long tempRow = row*256; + ossimIrect subRectToFill(frameRect.ul().x + tempCol, + frameRect.ul().y + tempRow, + frameRect.ul().x + tempCol + 255, + frameRect.ul().y + tempRow + 255); + theTile->loadTile(theUncompressedBuffer, + subRectToFill, + OSSIM_BSQ); + } + } +} + +void ossimCibCadrgTileSource::fillSubTileCib(const ossimRpfFrame& aFrame, + const ossimIrect& tileRect, + const ossimFrameEntryData& frameEntryData) +{ + // first let's grab the absolute position of the frame rectangle in pixel space + ossimIrect frameRect(frameEntryData.thePixelCol, + frameEntryData.thePixelRow, + frameEntryData.thePixelCol + CIBCADRG_FRAME_WIDTH - 1, + frameEntryData.thePixelRow + CIBCADRG_FRAME_HEIGHT - 1); + + + // now clip it to the tile + ossimIrect clipRect = tileRect.clipToRect(frameRect); + + const ossimRpfCompressionSection* compressionSection = aFrame.getCompressionSection(); + + if(!compressionSection) + { + return; + } + + // check to see if it does overlap. If it doesn't then the width and height + // will be a single point + { + ossim_uint8 *tempRow; + + tempRow = theUncompressedBuffer; + + // find the shift to 0,0 + ossimIpt tempDelta(clipRect.ul().x - frameEntryData.thePixelCol, + clipRect.ul().y - frameEntryData.thePixelRow); + + // In order to compute the subframe we will need the corner offsets of + // the upper left of the frame and the upper left of the clip rect. The + // clip rect should be completely within the frame. This just translates the value + // to make the upper left of the frame be 0,0. + // + ossimIrect offsetRect(tempDelta.x, + tempDelta.y, + tempDelta.x + clipRect.width()-1, + tempDelta.y + clipRect.height()-1); + + // each subframe is 64x64. We will actually use 256x256 since + // we will be uncompressing them. Note CADRG is a 256x256 tile + // compressed to 64x64x12 bit data + // + ossimIrect subFrameRect(offsetRect.ul().x/256, + offsetRect.ul().y/256, + (offsetRect.lr().x)/256, + (offsetRect.lr().y)/256); + + const vector<ossimRpfColorGrayscaleTable>& colorTable = + aFrame.getColorGrayscaleTable(); + + long row = 0; + long col = 0; + ossim_uint32 i = 0; + ossim_uint32 j = 0; + ossim_uint32 readPtr = 0; + for(row = subFrameRect.ul().y; row <= subFrameRect.lr().y; ++row) + { + for(col = subFrameRect.ul().x; col <= subFrameRect.lr().x; ++col) + { + readPtr = 0; + if(aFrame.fillSubFrameBuffer(theCompressedBuffer, 0, row, col)) + { + for (i = 0; i < 256; i += 4) + { + for (j = 0; j < 256; j += 8) + { + ossim_uint16 firstByte = theCompressedBuffer[readPtr++] & 0xff; + ossim_uint16 secondByte = theCompressedBuffer[readPtr++] & 0xff; + ossim_uint16 thirdByte = theCompressedBuffer[readPtr++] & 0xff; + + //because dealing with half-bytes is hard, we + //uncompress two 4x4 tiles at the same time. (a + //4x4 tile compressed is 12 bits ) + // this little code was grabbed from openmap software. + + /* Get first 12-bit value as index into VQ table */ + // I think we need to swap + ossim_uint16 val1 = (firstByte << 4) | (secondByte >> 4); + + /* Get second 12-bit value as index into VQ table*/ + ossim_uint16 val2 = ((secondByte & 0x000F) << 8) | thirdByte; + + for (ossim_uint32 t = 0; t < 4; ++t) + { + for (ossim_uint32 e = 0; e < 4; ++e) + { + ossim_uint16 tableVal1 = compressionSection->getTable()[t].theData[val1*4 + e] & 0xff; + ossim_uint16 tableVal2 = compressionSection->getTable()[t].theData[val2*4 + e] & 0xff; + + ossim_uint32 pixindex = ((i+t)*256) + (j + e); + const ossim_uint8* color1 = colorTable[0].getStartOfData(tableVal1); + const ossim_uint8* color2 = colorTable[0].getStartOfData(tableVal2); + + + tempRow[pixindex] = color1[0]; + tempRow[pixindex + 4] = color2[0]; + } //for e + } //for t + } /* for j */ + } //for i + } + else + { + memset(theUncompressedBuffer, 0, 256*256); + } + long tCol = col*256; + long tRow = row*256; + ossimIrect subRectToFill(frameRect.ul().x + tCol, + frameRect.ul().y + tRow, + frameRect.ul().x + tCol + 255, + frameRect.ul().y + tRow + 255); + theTile->loadTile(theUncompressedBuffer, + subRectToFill, + OSSIM_BSQ); + } + } + } +} + +void ossimCibCadrgTileSource::allocateForProduct() +{ + if(theProductType == OSSIM_PRODUCT_TYPE_UNKNOWN) + { + return; + } + if(theUncompressedBuffer) + { + delete [] theUncompressedBuffer; + theUncompressedBuffer = NULL; + } + if(theCompressedBuffer) + { + delete [] theCompressedBuffer; + theCompressedBuffer = NULL; + } + + // a CADRG and CIBis a 64*64*12 bit buffer and must divide by 8 to + // convert to bytes + theCompressedBuffer = new ossim_uint8[(64*64*12)/8]; + if(theProductType == OSSIM_PRODUCT_TYPE_CIB) + { + theUncompressedBuffer = new ossim_uint8[256*256]; + } + else + { + theUncompressedBuffer = new ossim_uint8[256*256*3]; + } + + theTile = ossimImageDataFactory::instance()->create(this, this); + theTile->initialize(); +} + +const ossimRpfTocEntry* ossimCibCadrgTileSource::findFirstFrame() +{ + vector<ossimString> products = getProductScaleList(); + vector<long> indexProducts; + + if(products.size() > 0) + { + indexProducts = getProductEntryList(products[0]); + + if(indexProducts.size()>0) + { + theEntryNumberToRender = indexProducts[0]; + + return theTableOfContents->getTocEntry(indexProducts[0]); + } + } + + return NULL; +} + + +void ossimCibCadrgTileSource::deleteAll() +{ + if(theOverview) + { + delete theOverview; + theOverview = NULL; + } + if(theTableOfContents) + { + delete theTableOfContents; + theTableOfContents = NULL; + } +} + +bool ossimCibCadrgTileSource::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + bool result = ossimImageHandler::saveState(kwl, prefix); + + kwl.add(prefix, + "entry", + theEntryNumberToRender, + true); + + return result; +} + +bool ossimCibCadrgTileSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* MODULE = "ossimCibCadrgTileSource::loadState"; + + if(traceDebug()) + { + CLOG << "Entering..." << endl; + } + bool result = ossimImageHandler::loadState(kwl, prefix); + + if(!result) + { + return false; + } + const char* lookup = NULL; + + lookup = kwl.find(prefix, "entry"); + long entry = ossimString(lookup).toLong(); + + // if an entry is specified then + // call the open with an entry number + if(lookup) + { + if(traceDebug()) + { + CLOG << "Leaving..." << endl; + } + result = ossimImageHandler::open(theImageFile); + setCurrentEntry(entry); + return result; + } + + result = ossimImageHandler::open(theImageFile); + + return result; +} + +ossim_uint32 ossimCibCadrgTileSource::getImageTileWidth() const +{ + return 256; +} + +ossim_uint32 ossimCibCadrgTileSource::getImageTileHeight() const +{ + return 256; +} + +bool ossimCibCadrgTileSource::isCib() const +{ + return (theProductType==OSSIM_PRODUCT_TYPE_CIB); +} + +bool ossimCibCadrgTileSource::isCadrg() const +{ + return (theProductType==OSSIM_PRODUCT_TYPE_CADRG); +} + +ossimString ossimCibCadrgTileSource::getProductScale() const +{ + ossimString result; + + const ossimRpfTocEntry* entry = + theTableOfContents->getTocEntry(theEntryNumberToRender); + + if (entry) + { + result = entry->getBoundaryInformation().getScale(); + } + + return result; +} + +ossimString ossimCibCadrgTileSource::getSecurityClassification()const +{ + ossimString result; + + const ossimRpfHeader* header = + theTableOfContents->getRpfHeader(); + + if (header) + { + result = header->getSecurityClassification(); + } + + return result; +} + +void ossimCibCadrgTileSource::populateLut() +{ + theLut = 0; + if(theEntryToRender) + { + ossim_uint32 w = theEntryToRender->getNumberOfFramesHorizontal(); + ossim_uint32 h = theEntryToRender->getNumberOfFramesVertical(); + ossim_uint32 wi, hi; + bool found = false; + ossimRpfFrameEntry tempEntry; + ossimRpfFrame aFrame; + for(wi = 0; ((wi < w)&&(!found)); ++wi) + { + for(hi = 0; ((hi < h)&&(!found)); ++hi) + { + theEntryToRender->getEntry(hi, + wi, + tempEntry); + if(tempEntry.getFullPath().exists()) + { + found = true; + } + } + } + if(aFrame.parseFile(tempEntry.getFullPath()) + == ossimErrorCodes::OSSIM_OK) + { + const vector<ossimRpfColorGrayscaleTable>& colorTable = + aFrame.getColorGrayscaleTable(); + + ossim_uint32 numElements = colorTable[0].getNumberOfElements(); + if(numElements > 0) + { + if((theProductType == OSSIM_PRODUCT_TYPE_CIB)|| + (theProductType == OSSIM_PRODUCT_TYPE_CADRG)) + { + theLut = new ossimNBandLutDataObject(numElements, + 3, + OSSIM_UINT8); + } + else + { + theLut = 0; + return; + } + ossim_uint32 idx = 0; + + for(idx = 0; idx < numElements;++idx) + { + const ossim_uint8* startOfData = colorTable[0].getStartOfData(idx); + switch(theProductType) + { + case OSSIM_PRODUCT_TYPE_CIB: + { + (*theLut)[idx][0] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(startOfData[0]); + (*theLut)[idx][1] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(startOfData[0]); + (*theLut)[idx][2] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(startOfData[0]); + break; + } + case OSSIM_PRODUCT_TYPE_CADRG: + { + (*theLut)[idx][0] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(startOfData[0]); + (*theLut)[idx][1] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(startOfData[1]); + (*theLut)[idx][2] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(startOfData[2]); + break; + } + default: + { + break; + } + } + } + } + } + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/cibcadrg/ossimCibCadrgTileSource.h b/Utilities/OSSIM/ossim_core/imaging/formats/cibcadrg/ossimCibCadrgTileSource.h new file mode 100644 index 0000000000..884892f575 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/cibcadrg/ossimCibCadrgTileSource.h @@ -0,0 +1,574 @@ +//----------------------------------------------------------------------- +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: This class give the capability to access tiles from an +// CADRG file. +// +//----------------------------------------------------------------------- +//$Id: ossimCibCadrgTileSource.h,v 1.39 2005/08/29 19:34:28 gpotts Exp $ +#ifndef ossimCibCadrgTileSource_HEADER +#define ossimCibCadrgTileSource_HEADER +#include <imaging/formats/ossimImageHandler.h> +#include <support_data/rpf/ossimRpfFrameEntry.h> + +class ossimRpfToc; +class ossimRpfTocEntry; +class ossimRpfFrame; + +/** + * Cib/Cadrg fromats are encoded the same except that the CIB is a grey + * scale image and the CADRG is a color image. Both are VQ compressed. + * The images are encoded into an NITF format with embedded RPF headers. + * It reads the embedded RPF tags from the NITF file and parses the data. + * It allows for you to select which CIB/CADRG entry to render. The handler + * is opened by giving it the associated a.toc file. This is a table of + * contents file that describes all the entries found in the CIB/CADARD + * product. You must set which entry you wish to render. By default it + * will render the first product it comes to. + * + * Note: This handler will eventually merge into the nitf handler. + */ +class OSSIMDLLEXPORT ossimCibCadrgTileSource : public ossimImageHandler +{ +public: + friend class ossimMultiEntryCibCadrg; + + /** + * Basic enumeration. This should + * be either a CIB or a CADRG product + * type. + */ + enum ossimCibCadrgProductType + { + OSSIM_PRODUCT_TYPE_UNKNOWN = 0, + OSSIM_PRODUCT_TYPE_CIB = 1, + OSSIM_PRODUCT_TYPE_CADRG = 2 + }; + + /** + * Default constructor. + * + * Initializes all internal attributes to a default state. + */ + ossimCibCadrgTileSource(); + + /** + * Destructor. + * + * Will return allocated memory back to the heap. + */ + virtual ~ossimCibCadrgTileSource(); + + /** + * This method is defined in the base class ossimObject. + * This class overrides the default implementation + * to return its own short name. + * + * @return The short name for this class as an ossimString. + */ + virtual ossimString getShortName()const; + + /** + * This method is defined in the base class ossimObject. + * This class overrides the default implementation + * to return its own long name. + * + * @return The long name for this class as an ossimString. + */ + virtual ossimString getLongName()const; + + /** + * Closes this image handler and deletes any allocated data. + */ + virtual void close(); + + /** + */ + virtual bool open(); + /** + * Returns a pointer to an ossimImageDataObject given a rectangluar + * region of interest. + * + * @param rect The region of interest to return. + * @param resLevel From which resolution set are we querying + * (default is 0 full res). + * + * @return The ossimImageData object to the caller. + */ + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect, + ossim_uint32 resLevel = 0); + + /** + * Satisfies pure virtual requirement from ImageHandler class. + * + * @param reduced_res_level The reduced res level to query number of lines from. + * @return The number of lines in the image. + */ + virtual ossim_uint32 getNumberOfLines(ossim_uint32 reduced_res_level = 0) const; + + /** + * Satisfies pure virtual requirement from ImageHandler class. + * + * @param reduced_res_level The reduced res level to query number of samples from. + * @return The number of samples in the image. + */ + virtual ossim_uint32 getNumberOfSamples(ossim_uint32 reduced_res_level = 0) const; + + /** + * @param reduced_res_level Which res level to get the bounds for. 0 represents + * the default and is the full resolution. + * + * @return A rectangle representing the bounds for the passed in resolution level. + */ + virtual ossimIrect getImageRectangle(ossim_uint32 reduced_res_level = 0) const; + + /** + * Method to save the state of an object to a keyword list. + * + * Saving data without a prefix. + * @code + * ossimCibCadrgTileSource* cibCadrgHandler = new ossimCibCadrgTileSource; + * ossimKeywordlist kwl; + * cibCadrgHandler->open(filename); + * cibCadrgHandler->saveState(kwl); + * @endcode + * + * and saving data with a prefix. + * @code + * ossimCibCadrgTileSource* cibCadrgHandler = new ossimCibCadrgTileSource; + * ossimKeywordlist kwl; + * cibCadrgHandler->open(filename); + * cibCadrgHandler->saveState(kwl, "handler1."); + * @endcode + * + * Saving with a prefix will help uniquely identify objects in the kwl. + * To see what is in the keywordlist after a save state then do: + * + * @code + * cout << kwl << endl; + * @endcode + * + * There is only 1 keyword for this object: + * + * entry: <entry number> + * + * where <entry number> is the index value for the current entry. + * + * @see ossimImageHandler for additional keywords. + * + * @param kwl Keywordlist to save the state of the object to. + * @param prefix prefix to prepend to the keywords. This will + * help uniquely identify each keyword if multiple + * objects are saved to the same list. + * @return True if successfully saved the state of the object and + * false otherwise. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to load the state of an object from a keyword list. + * + * Loading with a prefix. + * @code + * cibCadrgHandler->laodState(kwl, "handler1."); + * @endcode + * + * Loading without a prefix. + * @code + * cibCadrgHandler->laodState(kwl); + * @endcode + * + * Since all objects are factory created you can go through the + * registry and pass the keyword list in. + * @code + * ossimImageHandler* handler = ossimImageHandlerRegistry::instance()->open(kwl, prefix); + * @endcode + * + * @param kwl Keywordlist that holds the state information for this + * object. + * + * + * @param prefix prefix value prepended to all keywords to uniquely + * locate the state attributes for this object. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * Populates the keyword list with image geometry information. This + * method is used to relay projection/model information to users. + * Returns true if geometry info is present, false if not. + * Keywords supported by this object are: + * @verbatim + * datum: // datum code> // Datum code + * ul_lat: // upper left latitude + * ul_lon: // upper left longitude + * ll_lat: // lower left latitude + * ll_lon: // lower left longitude + * lr_lat: // lower right latitude + * lr_lon: // lower right longitude + * ur_lat: // upper right latitude + * ur_lon: // upper right longitude + * number_input_bands: + * number_output_bands: + * number_lines: + * number_samples: + * decimal_degrees_per_pixel_lat: // specifies the spacing per pixel along Y direction + * decimal_degrees_per_pixel_lon: // specifies the spacing per pixel along X direction + * origin_latitude: // specifies the origin or center of the projector for the latitude + * central_meridian: // specifies the origin or center of the projector for the longitude + * tie_point_lat: // tie point lat. Represents the latitude of the upper left center of pixel + * tie_point_lon: // tie point lon. Represents the longitude of the upper left center of pixel + * zone: // zone read from the CIB/CADRG boundary info + * type: // class name of the object for factory driven reconstruction + * map_scale: // Map scale of the image + * @endverbatim + * @see ossimImageSource for further code example on using the geometry + * information in kwl. + * @param kwl Keywordlist to populate the image geometry with. + * @param prefix A unique prefix to prepend to the keywords. + * + * @return True if image geometry is present and false otherwise. + */ + virtual bool getImageGeometry(ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * This method allows you to query the scalar type of the output data. + * This is simply the data type, i.e. whether its OSSIM_FLOAT, OSSIM_DOUBLE, + * OSSIM_UCHAR, ... etc. This means that if there are bands of different + * scalar types from a single image then they must be casted to the highest + * precision type. @see ossimConstants.h for all ossimScalarType. + * + * @return The output scalar type. + * + */ + virtual ossimScalarType getOutputScalarType() const; + + /** + * This method allows you to query the number of input bands. If an image + * is band selectable this will allow one to select the bands you wish + * to read in. This indicates that the number of input bands might not + * match the number of output bands. + * @return number of input bands. + */ + virtual ossim_uint32 getNumberOfInputBands()const; + + /** + * This method allows one to query the number of output bands. This might not + * be the same as the n umber of input bands. + * + * @see getNumberOfInputBands(). + * @return number of output bands. + */ + virtual ossim_uint32 getNumberOfOutputBands()const; + + /** + * Returns the width of the output tile. + */ + virtual ossim_uint32 getTileWidth() const; + + /** + * Returns the height of the output tile. + */ + virtual ossim_uint32 getTileHeight() const; + + /** + * Returns the tile width of the image or 0 if the image is not tiled. + * Note: this is not the same as the ossimImageSource::getTileWidth which + * returns the output tile width which can be different than the internal + * image tile width on disk. + */ + virtual ossim_uint32 getImageTileWidth() const; + + /** + * Returns the tile width of the image or 0 if the image is not tiled. + * Note: this is not the same as the ossimImageSource::getTileWidth which + * returns the output tile width which can be different than the internal + * image tile width on disk. + */ + virtual ossim_uint32 getImageTileHeight() const; + + virtual ossim_uint32 getCurrentEntry()const; + virtual bool setCurrentEntry(ossim_uint32 entryIdx); + virtual void getEntryList(std::vector<ossim_uint32>& entryList)const; + + + /** + * Returns -1 if invalid + */ + virtual ossim_int32 getCurrentEntryIndex()const; + + /** + * @return The current entry being rendered + */ + virtual const ossimRpfTocEntry* getCurrentTocEntry()const; + + /** + * @return The table of contents object. + */ + virtual const ossimRpfToc* getToc()const; + + /** + * @param reduced_res_level passed in resolution level. + * @return True if the reduced_res_level is within an acceptable range + * and false otherwise. + */ + bool isValidRLevel(ossim_uint32 reduced_res_level) const; + + /** + * Determines if its open if there eists a table of contents object. + * + * @return True if the handler is open and flase otherwise. + */ + bool isOpen()const; + + /** @return true if CIB */ + bool isCib() const; + + /** @return true if CADRG */ + bool isCadrg() const; + + /** @return Scale string ( like 1:24000 ) for current entry. */ + ossimString getProductScale() const; + + /** + * This retrieves all product scales that are within the Table of contents. + * I make no assumptions that a CIB/CADRG has only one product. A product + * here is 1meter, 5 meter, 10 meter ... etc for CIB and 1:24000, 1:50000, + * ... etc for CADRG. + * + * @return The prduct list as a vector of strings. + */ + vector<ossimString> getProductScaleList()const; + + /** + * Using the product scales from getProductScaleList() you can pass each string + * in so you can get all associated indices for a given product. + * + * @return Entry indices for a passed in product scale. + */ + vector<long> getProductEntryList(const ossimString& productScale)const; + + ossimString getSecurityClassification()const; + + /** + * CONSTANT representing the width of a Frame. This should be 1536. + */ + static const ossim_uint32 CIBCADRG_FRAME_WIDTH; + + /** + * CONSTANT representing the height of a Frame. This should be 1536. + */ + static const ossim_uint32 CIBCADRG_FRAME_HEIGHT; + +protected: + + /** + * Sets the entry to be renderer. The entry within the table + * of contents are stored in an Toc entry object. + * + * @param entry the Rpf toc entry object to set to. + */ + virtual void setTocEntryToRender(const ossimRpfTocEntry* entry); + + + /** + * Will shift the rect and clamp it so not to go outside the -180 to 180 + * degree range. + */ + void setActualImageRect(); + + /** + * Protected structure that is only used internally by this class. + * + * This is used to establish which entry data is being used. + * all we need is the ro, col of the entry. We can compute the + * image rect from this since the CibCadrg are 1536x1536 frame. + * + */ + struct ossimFrameEntryData + { + ossimFrameEntryData() + :theRow(-1), + theCol(-1), + thePixelRow(-1), + thePixelCol(-1) + {} + ossimFrameEntryData(long row, + long col, + long pixelRow, + long pixelCol, + const ossimRpfFrameEntry& entry) + :theRow(row), + theCol(col), + thePixelRow(pixelRow), + thePixelCol(pixelCol), + theFrameEntry(entry) + {} + ossimFrameEntryData(const ossimFrameEntryData& rhs) + :theRow(rhs.theRow), + theCol(rhs.theCol), + thePixelRow(rhs.thePixelRow), + thePixelCol(rhs.thePixelCol), + theFrameEntry(rhs.theFrameEntry) + {} + long theRow; + long theCol; + long thePixelRow; + long thePixelCol; + ossimRpfFrameEntry theFrameEntry; + }; + + /** + * Sets the entry to render. + * + */ + virtual bool setEntryToRender(ossim_uint32 index); + + /** + * It is important to note that each frame is organized into an easting northing + * type orientation. This means that a frame at 0,0 is at the lower left corner. + * Each frame's pixel data is has 0,0 at the upper left. + * + * It will take the curent region to render and then find all entries that intersect + * that region. + * + * @param rect the current region to render. + * @return The list of entry data objects found for this rect. + */ + vector<ossimFrameEntryData> getIntersectingEntries(const ossimIrect& rect); + + /** + * This is a wrapper for the fill cib and fill cadrg. It takes the frames + * involved that were found in the getIntersectingEntries and call the + * appropriate fill cib or fill cadrg on each frame entry data. It will + * loop through making sure that the frame file exists before calling + * the associated fill routines. + * + * @param tileRect Region to fill. + * @param framesInvolved All intersecting frames used to render the region. + */ + void fillTile(const ossimIrect& tileRect, + const vector<ossimFrameEntryData>& framesInvolved); + + /** + * Will uncompress the CIB file using a VQ decompression algorithm. + * + * @param aFrame Frame that overlaps the requested tile rect. + * @param tileRect The region requested to render. + * @param frameEntryData The frame entry data. + */ + void fillSubTileCib(const ossimRpfFrame& aFrame, + const ossimIrect& tileRect, + const ossimFrameEntryData& frameEntryData); + + /** + * Will uncompress the CADRG file using a VQ decompression algorithm. + * + * @param aFrame Frame that overlaps the requested tile rect. + * @param tileRect The region requested to render. + * @param frameEntryData The frame entry data. + */ + void fillSubTileCadrg(const ossimRpfFrame& aFrame, + const ossimIrect& tileRect, + const ossimFrameEntryData& frameEntryData); + + /** + * Will allocate an internal buffer for the given product. If the product is + * a CIB then it is a single band OSSIM_UCHAR buffer and if its a CADRG it + * is a 3 band OSSIM_UCHAR buffer. + */ + void allocateForProduct(); + + /** + * This will search each entry in the table and look for a certain + * entry. The first entry it comes to that has Geographic coverage + * will be the frame to render. This method is best here instead of + * in the ossimRpfToc. I am not sure, but I feel these types of + * searches are specific to the product (CADRG, CIB ...). This + * is called immediately after a succesful open of the ossimRpfToc + */ + const ossimRpfTocEntry* findFirstFrame(); + + void deleteAll(); + + void populateLut(); + + /** + * This holds the image bounds for the current entry. + */ + ossimIrect theActualImageRect; + + /** + * This is for storage of a single compressed buffer. + */ + unsigned char* theCompressedBuffer; + + /** + * This is used as a buffer to uncompress the data to + */ + unsigned char* theUncompressedBuffer; + + /** + * This will be computed based on the frames organized within + * the directory. The CibCadrg have fixed size frames of 1536x1536 + * and we must count how many there are. + */ + unsigned long theNumberOfLines; + + /** + * This will be computed based on the frames organized within + * the directory. The CibCadrg have fixed size frames of 1536x1536 + * and we must count how many there are. + */ + unsigned long theNumberOfSamples; + + /** + * This is the actual data returned from a getTile request. + */ + ossimRefPtr<ossimImageData> theTile; + + /** + * Will own a table of contents. This describes all entries within + * the CIB/CADRG. + */ + ossimRpfToc* theTableOfContents; + + /** + * This is the actual frame file to render. This should be + * divided into frames where each frame is 1536x1536 in + * size. + */ + const ossimRpfTocEntry* theEntryToRender; + + /** + * This will be the entry number that we are currently + * rendering. This will mainly be used when using + * overviews. + */ + long theEntryNumberToRender; + + /** + * The size of the output tile. + */ + ossimIpt theTileSize; + + /** + * Holds the enumeration specifying the product type. + * The product type can be a CIB or a CADRG product. + */ + ossimCibCadrgProductType theProductType; + + mutable ossimRpfFrame* theWorkFrame; +TYPE_DATA +}; + +#endif /* #ifndef ossimCibCadrgTileSource_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/doqq/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/formats/doqq/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/doqq/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/doqq/ossimDoqqTileSource.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/doqq/ossimDoqqTileSource.cpp new file mode 100644 index 0000000000..75d35ff52b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/doqq/ossimDoqqTileSource.cpp @@ -0,0 +1,222 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimDoqqTileSource.cpp,v 1.16 2005/11/08 18:25:52 gpotts Exp $ +#include <imaging/formats/doqq/ossimDoqqTileSource.h> +#include <support_data/doqq/ossimDoqq.h> +#include <imaging/formats/general_raster/ossimGeneralRasterInfo.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/common/ossimKeywordNames.h> + +RTTI_DEF1(ossimDoqqTileSource, + "ossimDoqqTileSource", + ossimGeneralRasterTileSource); + +ossimDoqqTileSource::ossimDoqqTileSource() + :theHeaderInformation(0) +{ +} + +ossimDoqqTileSource::~ossimDoqqTileSource() +{ + theHeaderInformation = 0; +} + +bool ossimDoqqTileSource::open(const ossimFilename& filename) +{ + bool result = false; + + theHeaderInformation = new ossimDoqq(filename); + if(theHeaderInformation->errorStatus() == ossimDoqq::OSSIM_ERROR) + { + theHeaderInformation = 0; + + return result; + } + else + { + // Set the Acquisition Date + theAcqDate = theHeaderInformation->theAcqYear; + theAcqDate += "-"; + theAcqDate += theHeaderInformation->theAcqMonth; + theAcqDate += "-"; + theAcqDate += theHeaderInformation->theAcqDay; + + vector<ossimFilename> f; + f.push_back(filename); + ossimGeneralRasterInfo genRasterInfo(f, + OSSIM_UCHAR, + OSSIM_BIP, + theHeaderInformation->theRgb, + theHeaderInformation->theLine, + theHeaderInformation->theSample, + theHeaderInformation->theHeaderSize, + ossimGeneralRasterInfo::NONE, + 0); + + result = ossimGeneralRasterTileSource::open(genRasterInfo); + } + + return result; +} + +bool ossimDoqqTileSource::getImageGeometry(ossimKeywordlist& kwl, + const char* prefix) +{ + if (theGeometryKwl.getSize()) + { + kwl = theGeometryKwl; + return true; + } + + if(theHeaderInformation.valid()) + { + ossimString proj = theHeaderInformation->theProjection.trim().upcase(); + ossimString datum = theHeaderInformation->theDatum.trim().upcase(); + + if(proj == ossimString("UTM") || proj == ossimString("1")) + { + kwl.add(prefix, + ossimKeywordNames::TYPE_KW, + "ossimUtmProjection", + true); + kwl.add(prefix, + ossimKeywordNames::ZONE_KW, + theHeaderInformation->theUtmZone, + true); + } + else + { + return false; + } + + if(datum == ossimString("NAR") || datum == ossimString("4")) + { + kwl.add(prefix, + ossimKeywordNames::DATUM_KW, + "NAR-C", // North American Conus 1983 + true); + } + else if(datum == ossimString("NAS") || datum == ossimString("1")) + { + kwl.add(prefix, + ossimKeywordNames::DATUM_KW, + "NAS-C", // North American Conus 1927 + true); + } + else if(datum == ossimString("2")) + { + kwl.add(prefix, + ossimKeywordNames::DATUM_KW, + "WGD", // WGS 72 + true); + } + else if(datum == ossimString("3")) + { + kwl.add(prefix, + ossimKeywordNames::DATUM_KW, + "WGE", // WGS 84 + true); + } + else + { + return false; + } + + kwl.add(prefix, + ossimKeywordNames::METERS_PER_PIXEL_X_KW, + theHeaderInformation->theGsd.x, + true); + + kwl.add(prefix, + ossimKeywordNames::METERS_PER_PIXEL_Y_KW, + theHeaderInformation->theGsd.y, + true); + kwl.add(prefix, + ossimKeywordNames::TIE_POINT_EASTING_KW, +// theHeaderInformation->theUE + (theHeaderInformation->theGsd/2.0), + theHeaderInformation->theEasting, + true); + + kwl.add(prefix, + ossimKeywordNames::TIE_POINT_NORTHING_KW, +// theHeaderInformation->theUN - (theHeaderInformation->theGsd/2.0), + theHeaderInformation->theNorthing, + true); + + // Capture this for next time. + setImageGeometry(kwl); + + return true; + } + return false; +} + +bool ossimDoqqTileSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* lookup = kwl.find(prefix, ossimKeywordNames::FILENAME_KW); + if(!ossimImageHandler::loadState(kwl, prefix)) + { + return false; + } + + if(lookup) + { + theHeaderInformation = new ossimDoqq(ossimFilename(lookup)); + if(theHeaderInformation->errorStatus() != ossimDoqq::OSSIM_OK) + { + theHeaderInformation = 0; + return false; + } + else + { + ossimFilename filename(lookup); + vector<ossimFilename> f; + f.push_back(filename); + ossimGeneralRasterInfo genRasterInfo(f, + OSSIM_UCHAR, + OSSIM_BIP, + theHeaderInformation->theRgb, + theHeaderInformation->theLine, + theHeaderInformation->theSample, + theHeaderInformation->theHeaderSize, + ossimGeneralRasterInfo::NONE, + 0); + return open(genRasterInfo); + } + } + else + { + return false; + } + + return true; +} + +ossimString ossimDoqqTileSource::getShortName()const +{ + return ossimString("doqq"); +} + +ossimString ossimDoqqTileSource::getLongName()const +{ + return ossimString("doqq handler"); +} + +bool ossimDoqqTileSource::open(const ossimGeneralRasterInfo& info) +{ + return ossimGeneralRasterTileSource::open(info); +} + +ossimString ossimDoqqTileSource::acqdate() const +{ + return theAcqDate; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/doqq/ossimDoqqTileSource.h b/Utilities/OSSIM/ossim_core/imaging/formats/doqq/ossimDoqqTileSource.h new file mode 100644 index 0000000000..9d419cfbb5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/doqq/ossimDoqqTileSource.h @@ -0,0 +1,43 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimDoqqTileSource.h,v 1.10 2005/11/14 13:47:01 gpotts Exp $ +#ifndef ossimDoqqTileSource_HEADER +#define ossimDoqqTileSource_HEADER +#include <imaging/formats/general_raster/ossimGeneralRasterTileSource.h> +#include <support_data/doqq/ossimDoqq.h> + +class OSSIM_DLL ossimDoqqTileSource: public ossimGeneralRasterTileSource +{ +public: + ossimDoqqTileSource(); + virtual ~ossimDoqqTileSource(); + + ossimString getShortName()const; + ossimString getLongName()const; + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix = NULL); + + virtual bool getImageGeometry(ossimKeywordlist& kwl, + const char* prefix=0); + bool open(const ossimFilename& filename); + bool open(const ossimGeneralRasterInfo& info); + + ossimString acqdate() const; + +protected: + ossimRefPtr<ossimDoqq> theHeaderInformation; + ossimString theAcqDate; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/dted/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/formats/dted/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/dted/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/dted/ossimDtedElevationImageSource.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/dted/ossimDtedElevationImageSource.cpp new file mode 100644 index 0000000000..497f927e08 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/dted/ossimDtedElevationImageSource.cpp @@ -0,0 +1,719 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2005 David Burken, all rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class declaration of ossimDtedElevationImageSource. +// +// $Id: ossimDtedElevationImageSource.cpp,v 1.4 2005/02/11 15:07:31 dburken Exp $ +//---------------------------------------------------------------------------- + +#include <vector> +#include <sstream> +using namespace std; + +#include <base/common/ossimTrace.h> +#include <base/factory/ossimObjectFactoryRegistry.h> +#include <base/data_types/ossimIrect.h> +#include <elevation/formats/dted_cell/ossimDtedHandler.h> +#include <projections/ossimImageViewProjectionTransform.h> +#include <projections/map_projections/ossimMapProjection.h> +#include <imaging/formats/dted/ossimDtedElevationImageSource.h> +#include <imaging/formats/dted/ossimDtedTileSource.h> +#include <imaging/factory/ossimImageHandlerRegistry.h> +#include <imaging/tile_sources/ossimImageRenderer.h> +#include <imaging/ossimImageData.h> +#include <imaging/ossimImageChain.h> + +static ossimTrace traceDebug("ossimDtedElevationImageSource:degug"); + +ossimDtedElevationImageSource::ossimDtedElevationImageSource() + : + theDirectory(), + theCellExtension("dt2"), + theResamplerType(ossimDtedElevationImageSource::BILINEAR) +{ +} + +ossimDtedElevationImageSource::~ossimDtedElevationImageSource() +{ +} + +ossimRefPtr<ossimImageData> ossimDtedElevationImageSource::getBlock( + const ossimGrect& rect, + ossim_uint32 lines, + ossim_uint32 samples) const +{ + + ossimDpt postSpacing; + getPostSpacing(rect, lines, samples, postSpacing); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimDtedElevationImageSource::getBlock DEBUG:" + << "\nrect: " << rect + << "\nlines: " << lines + << "\nsamples: " << samples + << "\npost spacing: " << postSpacing + << "\ntheDirectory: " << theDirectory + << endl; + } + + // Get a list of needed cells. + vector<ossimFilename> vf; + findCells(rect, vf); + + // Create a mosaic of them. + ossimImageChain* mosaic = createMosaic(vf); + if (!mosaic) + { + return NULL; + } + + // Get the view. + ossimMapProjection* view = getView(mosaic); + if (!view) + { + delete mosaic; + return NULL; + } + + // Set the output resolution. + view->setDecimalDegreesPerPixel(postSpacing); + + // Set the tie point to be the upper left of the requested rect. + view->setUlGpt(rect.ul()); + + // Convert the ground rectangle to the view's image space. + ossimIrect tileRect; + computeImageRect(view, rect, tileRect); + + cout << "tileRect: " << tileRect << endl; + + ossimRefPtr<ossimImageData> result = mosaic->getTile(tileRect); + + delete mosaic; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimDtedElevationImageSource::getBlock DEBUG:" + << *result + << "\nReturning..." + << endl; + } + + return result; +} + +void ossimDtedElevationImageSource::setDirectory(const ossimFilename& directory) +{ + theDirectory = directory; +} + +void ossimDtedElevationImageSource::getDirectory(ossimFilename& directory) const +{ + directory = theDirectory; +} + +void ossimDtedElevationImageSource::findCells( + const ossimGrect& rect, + vector<ossimFilename>& vf) const +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimDtedElevationImageSource::findCells entered..." << endl; + } + + // Clear the vector of filenames passed to us. + vf.clear(); + + if (!theDirectory.isDir()) + { + return; + } + + //--- + // Expand out the rectangle to even degree boundaries. + // Handle wrapping??? + //--- + + ossimGrect expandedRect = rect.stretchToEvenBoundary(1.0, 1.0); + + + ossim_int32 startLat = static_cast<ossim_int32>(expandedRect.ll().latd()); + ossim_int32 startLon = static_cast<ossim_int32>(expandedRect.ll().lond()); + ossim_int32 stopLat = + static_cast<ossim_int32>(expandedRect.ur().latd()-1); + ossim_int32 stopLon = + static_cast<ossim_int32>(expandedRect.ur().lond()-1); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG:" + << "\nepandedRect: " << expandedRect + << "\nstartLat: " << startLat + << "\nstartLon: " << startLon + << "\nstopLat: " << stopLat + << "\nstopLon: " << stopLon + + << endl; + } + + + for (ossim_int32 lon = startLon; lon <= stopLon; ++lon) + { + // Build up a dted file name. + ossimString lonBase; + if (lon < 0) + { + lonBase = "w"; + } + else + { + lonBase = "e"; + } + + ossim_int32 tmpLon = abs(lon); + ostringstream s1; + s1<< setfill('0')<<setw(3)<< tmpLon; + + lonBase += s1.str().c_str(); + lonBase += "/"; + + for (ossim_int32 lat = startLat; lat <= stopLat; ++lat) + { + ossimFilename dtedFile = theDirectory.dirCat(lonBase); + if (lat >= 0) + { + dtedFile += "n"; + } + else + { + dtedFile += "s"; + } + + ossim_int32 tmpLat = abs(lat); + ostringstream s2; + s2<< setfill('0')<<setw(2)<<tmpLat; + dtedFile += s2.str().c_str(); + + dtedFile.setExtension(theCellExtension); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "\nSearching for: " << dtedFile + << endl; + } + + if (dtedFile.exists()) + { + vf.push_back(dtedFile); + } + } + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "Cell list:\n"; + + vector<ossimFilename>::const_iterator i = vf.begin(); + while (i != vf.end()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << (*i) << "\n"; + ++i; + } + ossimNotify(ossimNotifyLevel_DEBUG) << endl; + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimDtedElevationImageSource::findCells exited..." << endl; + } +} + +void ossimDtedElevationImageSource::resampleCell( + const ossimGrect& rect, + const ossimFilename& dtedFile, + ossimImageData& id, + const ossimDpt& postSpacing) const +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimDtedElevationImageSource::resampleCell DEBUG: Entered..." + << endl; + } + + switch (theResamplerType) + { + case NEAREST_NEIGHBOR: + resampleCellNearestNeighbor(rect, dtedFile, id, postSpacing); + break; + + case BILINEAR: + resampleCellBilinear(rect, dtedFile, id, postSpacing); + break; + + default: + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimDtedElevationImageSource::resampleCell type not handled!" + << endl; + break; + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimDtedElevationImageSource::resampleCell DEBUG: Exited..." + << endl; + } +} + +void ossimDtedElevationImageSource::resampleCellBilinear( + const ossimGrect& rect, + const ossimFilename& dtedFile, + ossimImageData& id, + const ossimDpt& postSpacing) const +{ + cout << dtedFile << endl; + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimDtedElevationImageSource::resampleCellBilinear DEBUG:" + << " Entered..." + << endl; + } + + ossimDtedHandler* dh = new ossimDtedHandler(dtedFile); + if (!dh) + { + return; + } + if (dh->getErrorStatus() != ossimErrorCodes::OSSIM_OK) + { + delete dh; + return; + } + + ossim_float32* buf = id.getFloatBuf(); + if (!buf) + { + delete dh; + return; + } + + // Get the clip rectangle. + const ossimGrect clipRect = rect.clipToRect(dh->getBoundingGndRect()); + const ossimGpt STOP_GPT = clipRect.lr(); + ossimGpt gpt = clipRect.ul(); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "clipRect: " << clipRect + << "\nSTOP_GPT: " << STOP_GPT + << "\nStarting gpt: " << gpt + << endl; + } + + // Walk in the latitude (line) direction. + while (gpt.lat >= STOP_GPT.lat) + { + // Walk in longitude (sample) direction. + gpt.lon = clipRect.ul().lon; + while (gpt.lon <= STOP_GPT.lon) + { + ossim_uint32 index = computeIndex(id, rect, gpt, postSpacing); +// cout << "index: " << index << endl; + if (index != OSSIM_UINT_NAN) + { + ossim_float32 hgt = + static_cast<ossim_float32>(dh->getHeightAboveMSL(gpt)); +// cout << "index: " << index +// << "\ngpt: " << gpt +// << "\nhgt: " << hgt +// << endl; + buf[index] = hgt; + if (hgt == -32767.0) + { + cout << gpt << endl; + } + // static_cast<ossim_float32>(dh->getHeightAboveMSL(gpt)); + } + else + { + cout << "nan index for gpt:\n" << gpt << endl; + } + + gpt.lon = gpt.lon + postSpacing.x; + } + gpt.lat = gpt.lat - postSpacing.y; + } +// cout << "Ending gpt: " << gpt << endl; + +// // Walk in the latitude direction +// while (gpt.lat <= STOP_GPT.lat) +// { +// while (gpt.lon <= STOP_GPT.lon) +// { +// gpt.lon += postSpacing.x; +// } +// gpt.lat += postSpacing.y; +// } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimDtedElevationImageSource::resampleCellBilinear DEBUG:" + << " Exited..." + << endl; + } + + delete dh; +} + +void ossimDtedElevationImageSource::resampleCellNearestNeighbor( + const ossimGrect& rect, + const ossimFilename& dtedFile, + ossimImageData& id, + const ossimDpt& requestedPostSpacing) const +{ + // Open the cell. + ossimImageHandler* dts = new ossimDtedTileSource(); + dts->open(dtedFile); + + if (dts->isOpen() == false) + { + delete dts; + return; + } + + // Get the post spacing of the cell. + ossimDpt cellPostSpacing; + ((ossimDtedTileSource*)dts)->getPostSpacing(cellPostSpacing); + +// // Compute the rlevel to grab from. +// ossim_uint32 rLevel = computeRLevel(dts->getNumberOfDecimationLevels(), +// requestedPostSpacing, +// cellPostSpacing); + + +} + +void ossimDtedElevationImageSource::getPostSpacing(const ossimGrect& rect, + ossim_uint32 lines, + ossim_uint32 samples, + ossimDpt& result) const +{ + result.lat = (rect.ul().lat - rect.ll().lat) / (lines - 1); + result.lon = (rect.lr().lon - rect.ll().lon) / (samples - 1); +} + +void ossimDtedElevationImageSource::snap(const ossimGrect& rect, + const ossimDpt& postSpacing, + ossimGrect& clipRect) const +{ + ossim_float64 d; + + // upper left latitude + d = (rect.ul().lat - clipRect.ul().lat) / postSpacing.y; + if (d != 0.0) + { + clipRect.ul().lat = floor(d) * postSpacing.y; + } + + // upper left longitude + d = (rect.ul().lon - clipRect.ul().lon) / postSpacing.x; + if (d != 0.0) + { + clipRect.ul().lon = ceil(d) * postSpacing.x; + } + + // upper right latitude + d = (rect.ul().lat - clipRect.ur().lat) / postSpacing.y; + if (d != 0.0) + { + clipRect.ur().lat = floor(d) * postSpacing.y; + } + + // upper right longitude + d = (rect.ul().lon - clipRect.ur().lon) / postSpacing.x; + if (d != 0.0) + { + clipRect.ul().lon = floor(d) * postSpacing.x; + } + + // lower right latitude + d = (rect.ul().lat - clipRect.lr().lat) / postSpacing.y; + if (d != 0.0) + { + clipRect.lr().lat = ceil(d) * postSpacing.y; + } + + // lower right longitude + d = (rect.ul().lon - clipRect.lr().lon) / postSpacing.x; + if (d != 0.0) + { + clipRect.ul().lon = floor(d) * postSpacing.x; + } + + // lower left latitude + d = (rect.ul().lat - clipRect.ll().lat) / postSpacing.y; + if (d != 0.0) + { + clipRect.ll().lat = ceil(d) * postSpacing.y; + } + + // lower left longitude + d = (rect.ul().lon - clipRect.ll().lon) / postSpacing.x; + if (d != 0.0) + { + clipRect.ul().lon = ceil(d) * postSpacing.x; + } +} + +ossim_uint32 ossimDtedElevationImageSource::computeIndex( + const ossimImageData& id, + const ossimGrect& idRect, + const ossimGpt& gpt, + const ossimDpt& postSpacing) const +{ + if ( ! idRect.pointWithin(gpt) ) + { + return OSSIM_INT_NAN; + } + + ossim_uint32 line = static_cast<ossim_uint32>( (idRect.ul().lat - gpt.lat) + / postSpacing.y ); + ossim_uint32 samp = static_cast<ossim_uint32>( (gpt.lon - idRect.ul().lon) + / postSpacing.x ); + return ( (line * id.getWidth()) + samp ); +} + +ossim_uint32 ossimDtedElevationImageSource::computeRLevel( + ossim_uint32 numberOfRLevels, + const ossimDpt& requestedPostSpacing, + const ossimDpt& cellPostSpacing) const +{ + if (numberOfRLevels == 1) + { + return 0; + } + + // Start the check at r1 postspacing. + ossimDpt rLevelPostSpacing(cellPostSpacing.x * 2.0, + cellPostSpacing.y * 2.0); + ossim_uint32 level = 0; + + for (ossim_uint32 i = 1; i < numberOfRLevels; ++i) + { + if ( (rLevelPostSpacing.x > requestedPostSpacing.x) && + (rLevelPostSpacing.y > requestedPostSpacing.y) ) + { + break; + } + + rLevelPostSpacing.x = rLevelPostSpacing.x * 2.0; + rLevelPostSpacing.y = rLevelPostSpacing.y * 2.0; + ++level; + } + + return level; +} + +void ossimDtedElevationImageSource::setCellExtension(const ossimString& ext) +{ + theCellExtension = ext; +} + +void ossimDtedElevationImageSource::getCellExtension(ossimString& ext) const +{ + ext = theCellExtension; +} + +ossimConnectableObject* ossimDtedElevationImageSource::createRawChain( + const ossimFilename& file) const +{ + ossimImageHandler* ih = ossimImageHandlerRegistry::instance()->open(file); + ossimConnectableObject* result = NULL; + if(ih) + { + ossimImageChain* chain = new ossimImageChain; + chain->add(ih); + chain->setDescription(file); + result = chain; + } + + return result; +} + +ossimImageChain* ossimDtedElevationImageSource::createMosaic( + const std::vector<ossimFilename>& inputs) const +{ + std::vector<ossimConnectableObject*> inputObjects; + for(int idx = 0; idx < (int)inputs.size();++idx) + { + ossimConnectableObject* obj = createRawChain(inputs[idx]); + if(obj) + { + inputObjects.push_back(obj); + } + } + return createMosaic(inputObjects); +} + +ossimImageChain* ossimDtedElevationImageSource::createMosaic( + const std::vector<ossimConnectableObject*>& inputs) const +{ + if(!inputs.size()) + { + return NULL; + } + + std::vector<ossimConnectableObject*> inputList; + ossim_uint32 idx = 0; + + for(idx = 0; idx < inputs.size(); ++idx) + { + ossimImageChain* chain = PTR_CAST(ossimImageChain, inputs[idx]); + if(chain) + { + inputList.push_back(chain); + } + } + if(!inputList.size()) + { + return NULL; + } + + ossimImageChain* chainResult = NULL; + ossimString defaultDescription="ossimOrthoImageMosaic";; + ossimKeywordlist kwl; + + kwl.add("type", + "ossimImageChain", + true); + + kwl.add("id", + 0, + true); + + kwl.add("object1.type", + "ossimOrthoImageMosaic", + true); + kwl.add("object1.id", + 1, + true); + + + kwl.add("object10.type", + "ossimCacheTileSource", + true); + kwl.add("object10.id", + 10, + true); + kwl.add("object10.input_connection1", + 1, + true); + + kwl.add("object20.type", + "ossimImageRenderer", + true); + kwl.add("object20.id", + 20, + true); + kwl.add("object20.input_connection1", + 10, + true); + + ossimObject* objResult = + ossimObjectFactoryRegistry::instance()->createObject(kwl); + chainResult = PTR_CAST(ossimImageChain, objResult); + if(chainResult) + { + chainResult->makeUniqueIds(); + chainResult->setDescription(defaultDescription); + for(idx = 0; idx < inputList.size(); ++idx) + { + chainResult->connectMyInputTo(inputList[idx]); + } + } + else if(objResult) + { + delete objResult; + } + + return chainResult; +} + +ossimMapProjection* ossimDtedElevationImageSource::getView( + ossimConnectableObject* container) const +{ + if (!container) + { + cerr << "a..." << endl; + return NULL; + } + + // Find the resampler. + ossimImageRenderer* rs = + (ossimImageRenderer*)container-> + findObjectOfType("ossimImageRenderer", + ossimConnectableObject::CONNECTABLE_DIRECTION_INPUT); + + if (!rs) + { + cerr << "b..." << endl; + return NULL; + } + + const ossimObject* obj = rs->getView(); + if (!obj) + { + cerr << "b2..." << endl; + } + + return PTR_CAST(ossimMapProjection, obj); +} + +void ossimDtedElevationImageSource::computeImageRect( + const ossimMapProjection* view, + const ossimGrect& grect, + ossimIrect& irect) const +{ + if (!view) + { + return; + } + + ossimDpt dpt; + view->worldToLineSample(grect.ul(), dpt); + irect.set_ul(dpt); + view->worldToLineSample(grect.lr(), dpt); + irect.set_lr(dpt); +} + +void ossimDtedElevationImageSource::setResamplerType(ossimDtedElevationImageSource::ResamplerType type) +{ + theResamplerType = type; +} + +ossimDtedElevationImageSource::ResamplerType ossimDtedElevationImageSource::getResamplerType() const +{ + return theResamplerType; +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/dted/ossimDtedElevationImageSource.h b/Utilities/OSSIM/ossim_core/imaging/formats/dted/ossimDtedElevationImageSource.h new file mode 100644 index 0000000000..ec8098b21a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/dted/ossimDtedElevationImageSource.h @@ -0,0 +1,226 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2005 David Burken, all rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class declaration of ossimDtedElevationImageSource. +// +// $Id: ossimDtedElevationImageSource.h,v 1.4 2005/02/11 15:07:31 dburken Exp $ +//---------------------------------------------------------------------------- +#ifndef ossimDtedElevationImageSource_HEADER +#define ossimDtedElevationImageSource_HEADER + +#include <base/common/ossimConstants.h> +#include <base/common/ossimRefPtr.h> +#include <base/data_types/ossimFilename.h> +#include <base/data_types/ossimGrect.h> + + +// Forward class declarations. +class ossimImageData; +class ossimImageChain; +class ossimDtedTileSource; +class ossimConnectableObject; +class ossimMapProjection; +class ossimIrect; + + +/** + * Class to return large area blocks of data as an ossimImageData object from + * multiple dted cells. Source dted cells must be of the same resolution and + * in the standard dted directory stucture. + * + * Example directory structure: + * + * dted_level2_directory + * / \ + * / \ + * w099 w100 + * / \ / \ + * / \ / \ + * n32.dt2 n33.dt2 n32.dt2 n33.dt2 + */ +class OSSIMDLLEXPORT ossimDtedElevationImageSource +{ +public: + + enum ResamplerType + { + NEAREST_NEIGHBOR = 0, + BILINEAR = 1 + }; + + /** + * Default constructor + */ + ossimDtedElevationImageSource(); + + /** + * Destructor + */ + virtual ~ossimDtedElevationImageSource(); + + /** + * @param rect Requested rectangle. + * + * @param lines Number of lines. This will determine the + * post spacing in the latitude direction. + * + * @param samples Number of samples. This will determine the post spacing + * in the longitude direction. + */ + ossimRefPtr<ossimImageData> getBlock(const ossimGrect& rect, + ossim_uint32 lines, + ossim_uint32 samples) const; + + /** + * @param directory Directory to search for dted cells. + * + * @note Directory should be in a standard dted format. + * + * @note All cells in the directory should be of same resolution. + */ + void setDirectory(const ossimFilename& directory); + + /** + * @param directory Will be initialized to the current dted directory. + */ + void getDirectory(ossimFilename& directory) const; + + /** + * @param ext Should be the extension of cells in the directory like + * "dt1", "dt2". + * + * @note All cells in the directory should have same extension. + */ + void setCellExtension(const ossimString& ext); + + /** + * @param ext Will be initialized to the current cell extension. + */ + void getCellExtension(ossimString& ext) const; + + /** + * @param type Enumerated resampler type. + */ + void setResamplerType(ossimDtedElevationImageSource::ResamplerType type); + + /** + * @return Resampler type. + */ + ossimDtedElevationImageSource::ResamplerType getResamplerType() const; + + +private: + + /** + * Finds all cells in "theDirectory" for rectangle passed in. + * + * @param rect Rectangle of requested elevation block. + * + * @param vf Vector of ossimFilenames to initialize with cells that are + * present and overlap rect. + * + * @note vf will be cleared upon entring this method, so if vf.empty() is + * true than no cells were found. + */ + void findCells(const ossimGrect& rect, + vector<ossimFilename>& vf) const; + + /** + * Main resample method. + * + * @param rect Rectangle of requested elevation block. + * + */ + void resampleCell(const ossimGrect& rect, + const ossimFilename& dtedFile, + ossimImageData& id, + const ossimDpt& postSpacing) const; + + /** + * Specialized resample method. Uses ossimDtedHandler and its + * getHeightAboveMSL method to fill rect. + */ + void resampleCellBilinear(const ossimGrect& rect, + const ossimFilename& dtedFile, + ossimImageData& id, + const ossimDpt& postSpacing) const; + + /** + * Specialized resample method. Uses ossimDtedTileSource to fill a patch, + * then resamples to post spacing using nearest neighbor. + */ + void resampleCellNearestNeighbor(const ossimGrect& rect, + const ossimFilename& dtedFile, + ossimImageData& id, + const ossimDpt& requestedPostSpacing)const; + + /** + * @param rect Ground rectangle. + * + * @param lines Number of desired lines in latitude direction. + * + * @param samples Number of desired samples in the longitude direction. + * + * @param result + * result.y = (rect.ul().latd - rect.ll().latd) / lines + * result.x = (rect.lr().lond - rect.ll().lond) / samples + */ + void getPostSpacing(const ossimGrect& rect, + ossim_uint32 lines, + ossim_uint32 samples, + ossimDpt& result) const; + + /** + * Aligns clip rect to requested rect with respect to post spacing. + */ + void snap(const ossimGrect& rect, + const ossimDpt& postSpacing, + ossimGrect& clipRect) const; + + /** + * @return The index for gpt into id's buf. If point does not intersect + * the rectangle an "OSSIM_UINT_NAN" is returned. + */ + ossim_uint32 computeIndex(const ossimImageData& id, + const ossimGrect& idRect, + const ossimGpt& gpt, + const ossimDpt& postSpacing) const; + + /** + * @return Returns the rLevel that is equal to, or greater than the + * requestedPostSpacing. + */ + ossim_uint32 computeRLevel(ossim_uint32 numberOfRLevels, + const ossimDpt& requestedPostSpacing, + const ossimDpt& cellPostSpacing) const; + + ossimConnectableObject* createRawChain(const ossimFilename& file) const; + + ossimImageChain* createMosaic( + const std::vector<ossimFilename>& inputs) const; + + ossimImageChain* createMosaic( + const std::vector<ossimConnectableObject*>& inputs) const; + + ossimMapProjection* getView(ossimConnectableObject* container) const; + + void computeImageRect(const ossimMapProjection* view, + const ossimGrect& grect, + ossimIrect& irect) const; + + ossimFilename theDirectory; + ossimString theCellExtension; + ResamplerType theResamplerType; + +}; + +#endif /* End of #ifndef ossimDtedElevationImageSource_HEADER */ + diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/dted/ossimDtedTileSource.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/dted/ossimDtedTileSource.cpp new file mode 100644 index 0000000000..8a1cf23150 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/dted/ossimDtedTileSource.cpp @@ -0,0 +1,739 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class declaration for ossimDtedTileSource. +// +//******************************************************************** +// $Id: ossimDtedTileSource.cpp,v 1.37 2005/02/11 15:07:31 dburken Exp $ + +#include <iostream> +#include <fstream> +using namespace std; + +#include <imaging/formats/dted/ossimDtedTileSource.h> +#include <base/common/ossimConstants.h> +#include <base/common/ossimCommon.h> +#include <base/common/ossimKeywordNames.h> +#include <base/common/ossimTrace.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ellipse/ossimEllipsoid.h> +#include <base/data_types/datum/ossimDatum.h> +#include <projections/map_projections/ossimMapProjection.h> +#include <projections/map_projections/ossimEquDistCylProjection.h> +#include <imaging/formats/tiff/ossimTiffTileSource.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <imaging/ossimImageData.h> +#include <imaging/ossimS16ImageData.h> +#include <support_data/dted/ossimDtedVol.h> +#include <support_data/dted/ossimDtedHdr.h> +#include <support_data/dted/ossimDtedUhl.h> +#include <support_data/dted/ossimDtedDsi.h> +#include <support_data/dted/ossimDtedAcc.h> + +RTTI_DEF1(ossimDtedTileSource, "ossimDtedTileSource", ossimImageHandler) + +// Static trace for debugging +static ossimTrace traceDebug("ossimDtedTileSource:debug"); + + +ossimDtedTileSource::ossimDtedTileSource() + : + ossimImageHandler(), + theTile(NULL), + theFileStr(), + theTileWidth(0), + theTileHeight(0), + theNumberOfLines(0), + theNumberOfSamps(0), + theOffsetToFirstDataRecord(0), + theDataRecordSize(0), + theMinHeight(0), + theMaxHeight(0), + thePostSpacing(0.0, 0.0), + theSwapBytesFlag(false) +{ + if (ossimGetByteOrder() == OSSIM_LITTLE_ENDIAN) + { + theSwapBytesFlag = true; + } + + // Set the tile size to the default. + ossimIpt defaultTileSize; + ossimGetDefaultTileSize(defaultTileSize); + theTileWidth = static_cast<ossim_uint32>(defaultTileSize.x); + theTileHeight = static_cast<ossim_uint32>(defaultTileSize.y); + + // Construction not complete. Users should call "open" method. +} + +ossimDtedTileSource::~ossimDtedTileSource() +{ + theFileStr.close(); +} + +ossimString ossimDtedTileSource::getShortName()const +{ + return ossimString("dted"); +} + +ossimString ossimDtedTileSource::getLongName()const +{ + return ossimString("dted reader"); +} + +ossimString ossimDtedTileSource::className()const +{ + return ossimString("ossimDtedTileSource"); +} + +ossimRefPtr<ossimImageData> ossimDtedTileSource::getTile( + const ossimIrect& tile_rect, ossim_uint32 resLevel) +{ + if (!theTile.valid()) + { + allocate(); // First getTile call or after changeTileSize. + if (!theTile.valid()) + { + return ossimRefPtr<ossimImageData>(); // Throw exception??? + } + } + + // This tile source bypassed, or invalid res level, return a blank tile. + if (!isOpen()||!isSourceEnabled() || !isValidRLevel(resLevel)) + { + return ossimRefPtr<ossimImageData>(); + } + + if (theOverview) + { + if (theOverview->hasR0() || resLevel) + { + ossimRefPtr<ossimImageData> temp = + theOverview->getTile(tile_rect, resLevel); + if(temp.valid() && temp->getBuf()) + { + temp->setMinPix(theTile->getMinPix(), theTile->getNumberOfBands()); + temp->setMaxPix(theTile->getMaxPix(), theTile->getNumberOfBands()); + temp->setNullPix(theTile->getNullPix(), + theTile->getNumberOfBands()); + } + else + { + return ossimRefPtr<ossimImageData>(); + } + return temp; + } + } + + // Set the origing and resize if needed... + theTile->setImageRectangle(tile_rect); + + ossimIrect image_rect = getImageRectangle(resLevel); + + //*** + // See if any point of the requested tile is in the image. + //*** + if ( tile_rect.intersects(image_rect) ) + { + ossimIrect clip_rect = tile_rect.clipToRect(image_rect); + + if ( !tile_rect.completely_within(clip_rect) ) + { + // Start with a blank tile. + theTile->makeBlank(); + } + + // Load the tile buffer with data from the dted cell. + if (fillBuffer(tile_rect, clip_rect)) + { + theTile->validate(); + return theTile; + } + else + { + return ossimRefPtr<ossimImageData>(); + } + + } // End of if ( tile_rect.intersects(image_rect) ) + + // No part of requested tile within the image rectangle. + return ossimRefPtr<ossimImageData>(); + +} + +//******************************************************************* +// Private Method: +//******************************************************************* +bool ossimDtedTileSource::fillBuffer(const ossimIrect& tile_rect, + const ossimIrect& clip_rect) +{ + //*** + // NOTE: + // Elevation posts are organized positive line up. + // The "tile_rect" and "clip_rect" is organized positive line down. + //*** + + const ossim_int32 TILE_WIDTH = theTile->getWidth(); + + //*** + // Position the file pointer to the first record needed. + // Posts are organized positive line up so we're going to start at + // the lower left side of the cell so all reads are going forward in + // the file. + //*** + ossim_int32 seek_position = theOffsetToFirstDataRecord + + (clip_rect.ul().x * theDataRecordSize); + seek_position += DATA_RECORD_OFFSET_TO_POST + + (theNumberOfLines - 1 - clip_rect.lr().y) * 2; + + //*** + // Get a pointer positioned at the first valid pixel in + // the tile. Tiles are organized positive line down. + //*** + ossim_sint16* d = static_cast<ossim_sint16*>(theTile->getBuf()); + + // Loop in the longitude or sample direction. + for (ossim_int32 samp = clip_rect.ul().x; samp <= clip_rect.lr().x; samp++) + { + ossim_int32 d_offset = (clip_rect.lr().y - tile_rect.ul().y) * + TILE_WIDTH + + (samp - tile_rect.ul().x); + + theFileStr.seekg(seek_position, ios::beg); // Seek to the first post. + + for (ossim_int32 line = clip_rect.lr().y; line >= clip_rect.ul().y; line--) + { + // Grab all the post needed from the column. + ossim_uint16 temp; + ossim_sint16 s; + theFileStr.read((char*)&temp, POST_SIZE); + s = convertSignedMagnitude(temp); + d[d_offset] = s; + d_offset -= TILE_WIDTH; + } + seek_position += theDataRecordSize; + } + + + return true; +} + +ossim_uint32 ossimDtedTileSource::getNumberOfOutputBands()const +{ + return getNumberOfInputBands(); +} + +ossimIrect +ossimDtedTileSource::getImageRectangle(ossim_uint32 reduced_res_level) const +{ + return ossimIrect(0, + 0, + getNumberOfSamples(reduced_res_level) - 1, + getNumberOfLines(reduced_res_level) - 1); +} + +bool ossimDtedTileSource::isOpen()const +{ + return theFileStr.is_open(); +} + +bool ossimDtedTileSource::open() +{ + static const char MODULE[] = "ossimDtedTileSource::open"; + + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nAttempting to parse file: " << theImageFile.c_str() + << endl; + } + + if (!theImageFile.exists()) // See if file exists. + { + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nFile " << theImageFile.c_str() << " does not exist!" + << endl; + } + return false; + } + + // Open up the file for reading. + theFileStr.open(theImageFile.c_str(), ios::in | ios::binary); + if (!theFileStr) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + + ossimNotify(ossimNotifyLevel_WARN) << MODULE << " ERROR!" + << "\nCould not open file: " << theImageFile.c_str() + << "\nReturning..." << endl; + if (traceDebug()) CLOG << "returning with error..." << endl; + return false; + } + + if(!theFileStr) + { + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nCannot open: " << theImageFile.c_str() + << endl; + } + theFileStr.close(); + return false; + } + + // Attempt to parse. + ossimDtedVol vol(theFileStr, 0); + ossimDtedHdr hdr(theFileStr, vol.stopOffset()); + ossimDtedUhl uhl(theFileStr, hdr.stopOffset()); + ossimDtedDsi dsi(theFileStr, uhl.stopOffset()); + ossimDtedAcc acc(theFileStr, dsi.stopOffset()); + + //*** + // Check for errors. Must have uhl, dsi and acc records. vol and hdr + // are for magnetic tape only; hence, may or may not be there. + //*** + if (uhl.getErrorStatus() == ossimErrorCodes::OSSIM_ERROR || + dsi.getErrorStatus() == ossimErrorCodes::OSSIM_ERROR || + acc.getErrorStatus() == ossimErrorCodes::OSSIM_ERROR) + { + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nError parsing file: " << theImageFile.c_str() + << "\nPossibly not a dted file." + << endl; + } + + theFileStr.close(); + return false; + } + + // Get the cell specific info needed for later. + theNumberOfLines = uhl.numLatPoints(); + theNumberOfSamps = uhl.numLonLines(); + thePostSpacing.x = uhl.lonInterval(); + thePostSpacing.y = uhl.latInterval(); + theOffsetToFirstDataRecord = acc.stopOffset(); + theDataRecordSize = DATA_RECORD_OFFSET_TO_POST + + (theNumberOfLines * sizeof(ossim_sint16)) + + DATA_RECORD_CHECKSUM_SIZE; + + // Scan the file to get the min / max post. + gatherStatistics(); + + completeOpen(); + + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nNull pix: " << getNullPixelValue(0) + << "\nMin pix: " << getMinPixelValue(0) + << "\nMax pix: " << getMaxPixelValue(0) + << "\ntheNumberOfLines: " << theNumberOfLines + << "\ntheNumberOfSamps: " << theNumberOfSamps + << "\ntheOffsetToFirstDataRecord: " << theOffsetToFirstDataRecord + << "\ntheDataRecordSize: " << theDataRecordSize + << endl; + } + + + return true; +} + +void ossimDtedTileSource::allocate() +{ + //--- + // Set up the tiles. Note the blank tile will not get initialized to save + // memory. This includes setting the min and max pixel value gathered + // from the statistics. + //--- + theTile = ossimImageDataFactory::instance()->create(this, this); + theTile->initialize(); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG:" + << "\ntheTile:\n" << *theTile + << endl; + } +} + +bool ossimDtedTileSource::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + // Currently nothing to do here. + return ossimImageHandler::saveState(kwl, prefix); +} + +bool ossimDtedTileSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + if (ossimImageHandler::loadState(kwl, prefix)) + { + if (ossimImageHandler::open(theImageFile)) + { + return true; + } + } + + return false; +} + +bool ossimDtedTileSource::getImageGeometry(ossimKeywordlist& kwl, + const char* prefix) +{ + static const char MODULE[] = "ossimDtedTileSource::getImageGeometry"; + + if (traceDebug()) CLOG << " Entered..." << endl; + + // Previously saved... + if (theGeometryKwl.getSize()) + { + kwl = theGeometryKwl; + return true; + } + + if(!theFileStr) + { + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nCannot open: " << theImageFile.c_str() + << endl; + } + + return false; + } + + // Attempt to parse. + ossimDtedVol vol(theFileStr, (ossim_int32)0); + ossimDtedHdr hdr(theFileStr, vol.stopOffset()); + ossimDtedUhl uhl(theFileStr, hdr.stopOffset()); + ossimDtedDsi dsi(theFileStr, uhl.stopOffset()); + ossimDtedAcc acc(theFileStr, dsi.stopOffset()); + + //*** + // Check for errors. Must have uhl, dsi and acc records. vol and hdr + // are for magnetic tape only; hence, may or may not be there. + //*** + if (uhl.getErrorStatus() == ossimErrorCodes::OSSIM_ERROR || + dsi.getErrorStatus() == ossimErrorCodes::OSSIM_ERROR || + acc.getErrorStatus() == ossimErrorCodes::OSSIM_ERROR) + { + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nError parsing file: " << theImageFile.c_str() + << "\nPossibly not a dted file." + << endl; + } + return false; + } + + //*** + // Make an Equidistant Cylindrical projection with a origin at the equator + // since the DTED post spacing is considered to be square. Save its + // state to the keyword list. + //*** + ossimString projPref = prefix?prefix:""; +// const ossimDatum* datum = ossimDatumFactory::instance()->wgs84(); +// ossimProjection* proj +// = new ossimEquDistCylProjection(*(datum->ellipsoid()), +// ossimGpt(0.0, 0.0), +// 0.0, // false easting +// 0.0); // false northing +// proj->saveState(kwl, projPref); + +// delete proj; +// proj = NULL; + + //*** + // Get the latitude origin. DTED uses the South West corner as the origin + // so the latitude must be shifted to the upper left for the purpose of + // a tie point. + //*** + double lat = uhl.latOrigin() + + (uhl.latInterval() * (uhl.numLatPoints()-1.0)); + + // Add the tie point. + kwl.add(prefix, + ossimKeywordNames::TYPE_KW, + "ossimEquDistCylProjection", + true); + + kwl.add(prefix, + ossimKeywordNames::ORIGIN_LATITUDE_KW, + 0.0, + true); + + kwl.add(prefix, + ossimKeywordNames::CENTRAL_MERIDIAN_KW, + 0.0, + true); + + kwl.add(prefix, + ossimKeywordNames::TIE_POINT_LAT_KW, + lat, + true); + + kwl.add(prefix, + ossimKeywordNames::TIE_POINT_LON_KW, + uhl.lonOrigin(), + true); + + // Add the pixel scale. + kwl.add(prefix, + ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LAT, + uhl.latInterval(), + true); + + kwl.add(prefix, + ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LON, + uhl.lonInterval(), + true); + + //*** + // The projection code will save a meters_per_pixel of 1.0 off so remove it + // since we want it to use the DECIMAL_DEGREES_PER_PIXEL keyword instead. + //*** +// kwl.remove(prefix, ossimKeywordNames::METERS_PER_PIXEL_X_KW); +// kwl.remove(prefix, ossimKeywordNames::METERS_PER_PIXEL_Y_KW); + + // Add the datum. (always WGS-84 per spec) + kwl.add(prefix, + ossimKeywordNames::DATUM_KW, + ossimDatumFactory::instance()->wgs84()->code(), + true); + + // Add the number of lines and samples. + kwl.add(prefix, + ossimKeywordNames::NUMBER_LINES_KW, + static_cast<int>(uhl.numLatPoints())); + + kwl.add(prefix, + ossimKeywordNames::NUMBER_SAMPLES_KW, + static_cast<int>(uhl.numLonLines())); + + // Add the number of reduced resolution sets. + kwl.add(prefix, + ossimKeywordNames::NUMBER_REDUCED_RES_SETS_KW, + getNumberOfDecimationLevels()); + + // Add the number of bands. (alway one...) + kwl.add(prefix, + ossimKeywordNames::NUMBER_INPUT_BANDS_KW, + 1); + + kwl.add(prefix, + ossimKeywordNames::NUMBER_OUTPUT_BANDS_KW, + 1); + + if (traceDebug()) ossimNotify(ossimNotifyLevel_DEBUG) << "kwl:\n" << kwl << MODULE << " Exited..." << endl; + + // Capture for next time. + setImageGeometry(kwl); + + return true; +} + +ossimScalarType +ossimDtedTileSource::getOutputScalarType() const +{ + return OSSIM_SSHORT16; // Always signed 16 bit. +} + +ossim_uint32 ossimDtedTileSource::getTileWidth() const +{ + return theTileWidth; +} + +ossim_uint32 ossimDtedTileSource::getTileHeight() const +{ + return theTileHeight; +} + +ossim_uint32 ossimDtedTileSource::getNumberOfLines(ossim_uint32 reduced_res_level) const +{ + if (reduced_res_level == 0) + { + return theNumberOfLines; + } + else if (theOverview) + { + return theOverview->getNumberOfLines(reduced_res_level); + } + + return 0; +} + +ossim_uint32 ossimDtedTileSource::getNumberOfSamples(ossim_uint32 reduced_res_level) const +{ + if (reduced_res_level == 0) + { + return theNumberOfSamps; + } + else if (theOverview) + { + return theOverview->getNumberOfSamples(reduced_res_level); + } + + return 0; +} + +void ossimDtedTileSource::gatherStatistics() +{ + //*** + // Check to see if there is a statistics file already. If so; do a lookup + // for the min and max values. + //*** + ossimFilename stats_file = theImageFile.path(); + stats_file = stats_file.dirCat(theImageFile.fileNoExtension()); + stats_file += ".statistics"; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "Looking for " << stats_file + << " statistics file..." << std::endl; + } + + ossimKeywordlist kwl; + const char* min_str = NULL; + const char* max_str = NULL; + + if (stats_file.exists()) + { + if (kwl.addFile(stats_file)) + { + // Look for the min_pixel_value keyword. + min_str = kwl.find(ossimKeywordNames::MIN_VALUE_KW); + max_str = kwl.find(ossimKeywordNames::MAX_VALUE_KW); + } + } + + if (min_str && max_str) + { + theMinHeight = atoi(min_str); + theMaxHeight = atoi(max_str); + } + else // Scan the cell and gather the statistics... + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimDtedTileSource::gatherStatistics() scanning for min/max" + << "\nThis may take a while..." + << std::endl; + + // Start off with the min and max pegged. + theMinHeight = 32767; + theMaxHeight = -32767; + + // Put the file pointer at the start of the first elevation post. + theFileStr.seekg(theOffsetToFirstDataRecord, ios::beg); + + //*** + // Loop through all records and scan for lowest min and highest max. + // Each record contains a row of latitude points for a given longitude. + // There are eight bytes in front of the post and four checksum bytes at + // the end so ignore them. + //*** + for (ossim_uint32 i=0; i<theNumberOfSamps; i++) // longitude direction + { + theFileStr.seekg(DATA_RECORD_OFFSET_TO_POST, ios::cur); + + for (ossim_uint32 j=0; j<theNumberOfLines; j++) // latitude direction + { + ossim_uint16 temp; + ossim_sint16 s; + theFileStr.read((char*)&temp, POST_SIZE); + s = convertSignedMagnitude(temp); + if (s < theMinHeight && s != NULL_PIXEL) theMinHeight = s; + if (s > theMaxHeight) theMaxHeight = s; + } + + theFileStr.seekg(DATA_RECORD_CHECKSUM_SIZE, ios::cur); + } + + // Add the stats to the keyword list. + kwl.add(ossimKeywordNames::MIN_VALUE_KW, theMinHeight); + kwl.add(ossimKeywordNames::MAX_VALUE_KW, theMaxHeight); + + // Write out the statistics file. + kwl.write(stats_file.c_str()); + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimDtedTileSource::gatherStatistics DEBUG:" + << "\ntheMinHeight: " << theMinHeight + << "\ntheMaxHeight: " << theMaxHeight + << std::endl; + } +} + +ossim_uint32 ossimDtedTileSource::getImageTileWidth() const +{ + return 0; +} + +ossim_uint32 ossimDtedTileSource::getImageTileHeight() const +{ + return 0; +} + +ossim_uint32 ossimDtedTileSource::getNumberOfInputBands() const +{ + return 1; +} + +double ossimDtedTileSource::getNullPixelValue(ossim_uint32 band)const +{ + if(theMetaData.getNumberOfBands()) + { + return theMetaData.getNullPix(0); + } + return -32767.0; +} +double ossimDtedTileSource::getMinPixelValue(ossim_uint32 band)const +{ + if(theMetaData.getNumberOfBands()) + { + return theMetaData.getMinPix(band); + } + return theMinHeight; +} + + double ossimDtedTileSource::getMaxPixelValue(ossim_uint32 band)const +{ + if(theMetaData.getNumberOfBands()) + { + return theMetaData.getMaxPix(band); + } + return theMaxHeight; +} + +void ossimDtedTileSource::getPostSpacing(ossimDpt& postSpacing) const +{ + postSpacing.x = thePostSpacing.x; + postSpacing.y = thePostSpacing.y; +} + +const ossimDtedTileSource& ossimDtedTileSource::operator=(const ossimDtedTileSource& rhs) +{ + return rhs; +} + +ossimDtedTileSource::ossimDtedTileSource(const ossimDtedTileSource&) +{ +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/dted/ossimDtedTileSource.h b/Utilities/OSSIM/ossim_core/imaging/formats/dted/ossimDtedTileSource.h new file mode 100644 index 0000000000..517b597f55 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/dted/ossimDtedTileSource.h @@ -0,0 +1,209 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class declaration of ossimDtedTileSource. The ossimDtedTileSource +// class is derived from ossimImageHandler and is intended to be an image +// handler for DTED files. +// +//******************************************************************** +// $Id: ossimDtedTileSource.h,v 1.20 2005/07/25 22:46:29 dburken Exp $ + +#ifndef ossimDtedTileSource_HEADER +#define ossimDtedTileSource_HEADER + +#include <fstream> +using namespace std; + +#include <imaging/formats/ossimImageHandler.h> + +class ossimImageData; + +class OSSIM_DLL ossimDtedTileSource : public ossimImageHandler +{ +public: + + ossimDtedTileSource(); + virtual ~ossimDtedTileSource(); + + enum + { + DATA_RECORD_OFFSET_TO_POST = 8, // bytes + DATA_RECORD_CHECKSUM_SIZE = 4, // bytes + POST_SIZE = 2, // bytes + NULL_PIXEL = -32767 + }; + + virtual ossimString getShortName()const; + virtual ossimString getLongName()const; + virtual ossimString className()const; + + /** + * Returns true if "theImageFile" can be opened and is a valid adrg file. + */ + virtual bool open(); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tile_rect, + ossim_uint32 resLevel=0); + + /** + * Returns the number of bands in the image. + * Satisfies pure virtual requirement from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfInputBands() const; + + virtual ossim_uint32 getNumberOfOutputBands()const; + + /** + * Returns the number of lines in the image. + * Satisfies pure virtual requirement from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfLines( + ossim_uint32 reduced_res_level = 0) const; + + /** + * Returns the number of samples in the image. + * Satisfies pure virtual requirement from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfSamples( + ossim_uint32 reduced_res_level = 0) const; + + virtual double getNullPixelValue(ossim_uint32 band=0)const; + virtual double getMinPixelValue(ossim_uint32 band=0)const; + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + + /** + * Returns the zero based image rectangle for the reduced resolution data + * set (rrds) passed in. Note that rrds 0 is the highest resolution rrds. + */ + virtual ossimIrect getImageRectangle( + ossim_uint32 reduced_res_level = 0) const; + + /** + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * Populates the keyword list with image geometry information. This + * method is used to relay projection/model information to users. + * Returns true if geometry info is present, false if not. + */ + virtual bool getImageGeometry(ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * Returns the output pixel type of the tile source. + */ + virtual ossimScalarType getOutputScalarType() const; + + /** + * Returns the width of the output tile. + */ + virtual ossim_uint32 getTileWidth() const; + + /** + * Returns the height of the output tile. + */ + virtual ossim_uint32 getTileHeight() const; + + /** + * Returns the tile width of the image or 0 if the image is not tiled. + * Note: this is not the same as the ossimImageSource::getTileWidth which + * returns the output tile width which can be different than the internal + * image tile width on disk. + */ + virtual ossim_uint32 getImageTileWidth() const; + + /** + * Returns the tile width of the image or 0 if the image is not tiled. + * Note: this is not the same as the ossimImageSource::getTileWidth which + * returns the output tile width which can be different than the internal + * image tile width on disk. + */ + virtual ossim_uint32 getImageTileHeight() const; + + virtual bool isOpen()const; + + /** + * Initializes spacing to the post spacing of the cell. + * + * @param postSpacing ossimDpt to initialize with spacing where + * postspacing.x = longitude interval and postspacing.y = latitude interval. + */ + void getPostSpacing(ossimDpt& postSpacing) const; + +private: + // Disallow operator= and copy constrution... + const ossimDtedTileSource& operator=(const ossimDtedTileSource& rhs); + ossimDtedTileSource(const ossimDtedTileSource&); + + /** + * Allocated the tiles. + */ + void allocate(); + + /** + * Returns true on success, false on error. + */ + bool fillBuffer(const ossimIrect& tile_rect, + const ossimIrect& clip_rect); + + void gatherStatistics(); + ossim_sint16 convertSignedMagnitude(ossim_uint16& s) const; + + ossimRefPtr<ossimImageData> theTile; + mutable ifstream theFileStr; + ossim_uint32 theTileWidth; + ossim_uint32 theTileHeight; + ossim_uint32 theNumberOfLines; + ossim_uint32 theNumberOfSamps; + ossim_uint32 theOffsetToFirstDataRecord; + ossim_uint32 theDataRecordSize; + ossim_sint16 theMinHeight; + ossim_sint16 theMaxHeight; + ossimDpt thePostSpacing; + + /** + * DTED data is always stored as BIG_ENDIAN. This flag indicates that + * byte swapping is needed (LITTLE_ENDIAN machine). + */ + bool theSwapBytesFlag; + +TYPE_DATA +}; + +inline ossim_sint16 ossimDtedTileSource::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 << 8) | (s >> 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/Utilities/OSSIM/ossim_core/imaging/formats/ers/ossimERSTileSource.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/ers/ossimERSTileSource.cpp new file mode 100644 index 0000000000..d3aaa2206a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/ers/ossimERSTileSource.cpp @@ -0,0 +1,199 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Chong-Ket Chuah +// +// Description: +// +// Implementation for the class "ossimERSTileSource". ossimERSTileSource +// is used for reading ER Mapper raster file format. The format consists +// of a raster file with no extension and a header file with the same name +// as the raster file but with an .ers extension. +// +//******************************************************************* +// $Id: ossimERSTileSource.cpp,v 1.16 2005/05/09 12:39:38 dburken Exp $ + +#include <imaging/formats/ers/ossimERSTileSource.h> +#include <support_data/ers/ossimERS.h> + +#include <base/data_types/ossimDirectory.h> +#include <base/common/ossimTrace.h> +#include <base/common/ossimKeywordNames.h> + + +RTTI_DEF1(ossimERSTileSource, "ossimERSTileSource", ossimGeneralRasterTileSource); + +//******************************************************************* +// Public Constructor: +//******************************************************************* +ossimERSTileSource::ossimERSTileSource() + : ossimGeneralRasterTileSource(), + theHdr(NULL) +{ +} + +//******************************************************************* +// Public Constructor: +//******************************************************************* +ossimERSTileSource::ossimERSTileSource(const ossimKeywordlist& kwl, + const char* prefix) + : ossimGeneralRasterTileSource(), + theHdr(NULL) +{ + if (loadState(kwl, prefix) == false) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + } +} + +//******************************************************************* +// Destructor: +//******************************************************************* +ossimERSTileSource::~ossimERSTileSource() +{ + if (theHdr) + { + delete theHdr; + theHdr = NULL; + } +} + +bool ossimERSTileSource::open(const ossimFilename& fileName) +{ + // Open and parse the header file + theHdr = new ossimERS(fileName); + +// theHdr->dump(cout); + + if(theHdr->errorStatus() == ossimErrorCodes::OSSIM_ERROR) + { + delete theHdr; + theHdr = NULL; + return false; + } + else + { + vector<ossimFilename> f; + ossimFilename fne; + ossimFilename fpath = fileName.path(); + if (fpath.empty()) + fne = fileName.fileNoExtension(); + else + fne = fpath+"/"+fileName.fileNoExtension(); + f.push_back(fne); + ossimGeneralRasterInfo genRasterInfo(f, + theHdr->theCelltype, + OSSIM_BIL, + theHdr->theBands, + theHdr->theLine, + theHdr->theSample, + 0, + ossimGeneralRasterInfo::NONE, + 0); + if(theHdr->theHasNullCells) + { + ossim_uint32 i = 0; + ossim_uint32 bands = static_cast<ossim_uint32>(theHdr->theBands); + for(i = 0; i < bands; ++i) + { + genRasterInfo.setNullPixelValue(i, theHdr->theNullCell); + } + } + ossimFilename metadataFile = fne; + metadataFile = metadataFile + ".omd"; + + if(metadataFile.exists()) + { + ossimKeywordlist kwl; + + kwl.addFile(metadataFile.c_str()); + + theMetaData.loadState(kwl); + ossim_uint32 i = 0; + ossim_uint32 bands = static_cast<ossim_uint32>(theHdr->theBands); + for(i = 0; i < bands; ++i) + { + if(theMetaData.getMinValuesValidFlag()) + { + genRasterInfo.setMinPixelValue(i, theMetaData.getMinPix(i)); + } + if(theMetaData.getMaxValuesValidFlag()) + { + genRasterInfo.setMaxPixelValue(i, theMetaData.getMaxPix(i)); + } + if(theMetaData.getNullValuesValidFlag()) + { + genRasterInfo.setNullPixelValue(i, theMetaData.getNullPix(i)); + } + } + } + ossimNotify(ossimNotifyLevel_INFO) + << "general raster info is\n"; + genRasterInfo.print(ossimNotify(ossimNotifyLevel_INFO)); + ossimGeneralRasterTileSource::open(genRasterInfo); + } + + return true; +} + + +bool ossimERSTileSource::getImageGeometry(ossimKeywordlist& kwl, + const char* prefix) +{ + if (theGeometryKwl.getSize()) + { + kwl = theGeometryKwl; + return true; + } + + if(theHdr) + { + + bool result = theHdr->toOssimProjectionGeom(kwl, prefix); + if (result == true) + { + // Capture for next time. + setImageGeometry(kwl); + } + return result; + } + + return false; +} + +bool ossimERSTileSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* lookup = kwl.find(prefix, ossimKeywordNames::FILENAME_KW); + + if (lookup) + { + ossimFilename fileName = lookup; + + bool result = open(fileName); + ossimImageSource::loadState(kwl, prefix); + return result; + } + + return ossimGeneralRasterTileSource::loadState(kwl, prefix); +} + +ossimString ossimERSTileSource::getShortName() const +{ + return ossimString("ERS"); +} + +ossimString ossimERSTileSource::getLongName() const +{ + return ossimString("ER Mapper Raster"); +} + +ossimString ossimERSTileSource::className() const +{ + return ossimString("ossimERSTileSource"); +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/ers/ossimERSTileSource.h b/Utilities/OSSIM/ossim_core/imaging/formats/ers/ossimERSTileSource.h new file mode 100644 index 0000000000..640b8b3f2a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/ers/ossimERSTileSource.h @@ -0,0 +1,59 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Chong-Ket Chuah +// +// Description: +// +// Contains class definition for the class "ossimERSTileSource". +// +//******************************************************************* +// $Id: ossimERSTileSource.h,v 1.6 2005/07/25 22:47:29 dburken Exp $ + +#ifndef ossimERSTileSource_HEADER +#define ossimERSTileSource_HEADER + +#include <imaging/formats/general_raster/ossimGeneralRasterTileSource.h> +#include <support_data/ers/ossimERS.h> + + +class OSSIM_DLL ossimERSTileSource : public ossimGeneralRasterTileSource +{ +public: + ossimERSTileSource(); + + ossimERSTileSource(const ossimKeywordlist& kwl, const char* prefix=0); + + virtual ~ossimERSTileSource(); + + virtual ossimString getShortName() const; + virtual ossimString getLongName() const; + virtual ossimString className() const; + + virtual bool open(const ossimFilename& filename); + + /*! + * Populates the keyword list with image geometry information. This + * method is used to relay projection/model information to users. + * Returns true if geometry info is present, false if not. + */ + virtual bool getImageGeometry(ossimKeywordlist& kwl, + const char* prefix=0); + + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix = NULL); +private: + + void openHeader(const ossimFilename& file); + + ossimERS* theHdr; + + TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/general_raster/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/formats/general_raster/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/general_raster/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/general_raster/ossimGeneralRasterInfo.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/general_raster/ossimGeneralRasterInfo.cpp new file mode 100644 index 0000000000..6a274137e5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/general_raster/ossimGeneralRasterInfo.cpp @@ -0,0 +1,611 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +//******************************************************************* +// $Id: ossimGeneralRasterInfo.cpp,v 1.26 2005/06/15 19:44:03 gpotts Exp $ + +#include <stdlib.h> +#include <iostream> +#include <iomanip> + +#include <imaging/formats/general_raster/ossimGeneralRasterInfo.h> +#include <base/common/ossimTrace.h> +#include <base/common/ossimKeywordNames.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimString.h> +#include <base/misc/lookup_tables/ossimInterleaveTypeLut.h> +#include <base/misc/lookup_tables/ossimScalarTypeLut.h> + +static const ossimKeyword +NUMBER_LINES("number_lines", + "Number of lines in the raster image."); + +static const ossimKeyword +NUMBER_SAMPLES("number_samples", + "Number of samples in the raster image."); + +static const ossimKeyword +VALID_START_LINE("valid_start_line", + "First valid line of raster image(zero based)."); + +static const ossimKeyword +VALID_STOP_LINE("valid_stop_line", + "Last valid line of raster image(zero based)."); + +static const ossimKeyword +VALID_START_SAMPLE("valid_start_sample", + "First valid sample of raster image(zero based)."); + +static const ossimKeyword +VALID_STOP_SAMPLE("valid_stop_sample", + "Last valid sample of raster image(zero based)."); + +static const ossimKeyword +SUB_IMAGE_OFFSET_LINE( + "sub_image_offset_line", + "Pixel line offset of sub-image in the full-image pixel space."); + +static const ossimKeyword +SUB_IMAGE_OFFSET_SAMP( + "sub_image_offset_samp", + "Pixel sample offset of sub-image in the full-image pixel space."); + +static const ossimKeyword +HEADER_SIZE("header_size", + "Header size in bytes."); + +static const ossimKeyword +SET_NULLS("set_fill_to_nulls_mode", + "0 = do nothing to pixels,\n1 = all zeroes to min values,\ +\n2 = zeroes to null on edges only."); + +static const ossimKeyword +PIXELS_TO_CHOP("pixels_to_chop", + "Ammount of pixels to chop from edge."); + +static const ossimInterleaveTypeLut INTERLEAVE_TYPE_LUT; + +static ossimTrace traceDebug("ossimGeneralRasterInfo:debug"); + +ossimGeneralRasterInfo::ossimGeneralRasterInfo() + : + theImageFileList(), + theInterleaveType(OSSIM_BIL), + theRawImageRect(0,0,0,0), + theValidImageRect(0,0,0,0), + theImageRect(0,0,0,0), + theSubImageOffset(0,0), + theHeaderSize(0), + theSetNullsMode(NONE), + thePixelsToChop(0), + theImageDataByteOrder(OSSIM_LITTLE_ENDIAN) +{} + +ossimGeneralRasterInfo::ossimGeneralRasterInfo(const vector<ossimFilename>& imageFileList, + ossimScalarType pixelType, + ossimInterleaveType il_type, + ossim_uint32 numberOfBands, + ossim_uint32 lines, + ossim_uint32 samples, + ossim_uint32 headerSize, + ossimFillMode nullsMode, + ossim_uint32 pixelsToChop) + : + theMetaData(pixelType, + numberOfBands), + theImageFileList(imageFileList), + theInterleaveType(il_type), + theRawImageRect(0,0,0,0), + theValidImageRect(0,0,0,0), + theImageRect(0,0,0,0), + theSubImageOffset(0,0), + theHeaderSize(headerSize), + theSetNullsMode(nullsMode), + thePixelsToChop(pixelsToChop), + theImageDataByteOrder(OSSIM_LITTLE_ENDIAN) +{ + theRawImageRect.set_lry(lines - 1); + theRawImageRect.set_lrx(samples - 1); + theValidImageRect = theRawImageRect; + theImageRect = theRawImageRect; +} + +ossimGeneralRasterInfo::ossimGeneralRasterInfo(const ossimKeywordlist& kwl, + const char* prefix) + : + theImageFileList(), + theInterleaveType(OSSIM_BIL), + theRawImageRect(0,0,0,0), + theValidImageRect(0,0,0,0), + theImageRect(0,0,0,0), + theSubImageOffset(0,0), + theHeaderSize(0), + theSetNullsMode(NONE), + thePixelsToChop(0), + theImageDataByteOrder(OSSIM_LITTLE_ENDIAN) +{ + loadState(kwl, prefix); +} + +ossimGeneralRasterInfo::~ossimGeneralRasterInfo() +{ +} + +std::ostream& ossimGeneralRasterInfo::print(std::ostream& out) const +{ + //*** + // This will print in a keyword format that can be read by the constructor. + // that takes a keyword list. + //*** + out << setiosflags(ios::left); + ossim_uint32 i; + for (i=0; i<theImageFileList.size(); ++i) + { + out << ossimKeywordNames::FILENAME_KW << (i+1) << ": " + << theImageFileList[i].c_str() << endl; + } + + out << ossimScalarTypeLut::instance()->getKeyword().key() << ": " + << ossimScalarTypeLut::instance()->getEntryString(getScalarType()) + << "\n" << INTERLEAVE_TYPE_LUT.getKeyword().key() << ": " + << INTERLEAVE_TYPE_LUT.getEntryString(theInterleaveType) + << "\n" << ossimKeywordNames::NUMBER_BANDS_KW << ": " + << numberOfBands() + << "\n" << NUMBER_LINES.key() << ": " + << rawLines() + << "\n" << NUMBER_SAMPLES.key() << ": " + << rawSamples() + << "\n" << VALID_START_LINE.key() << ": " + << theValidImageRect.ul().y + << "\n" << VALID_STOP_LINE.key() << ": " + << theValidImageRect.lr().y + << "\n" << VALID_START_SAMPLE.key() << ": " + << theValidImageRect.ul().x + << "\n" << VALID_STOP_SAMPLE.key() << ": " + << theValidImageRect.lr().x + << "\n" << SUB_IMAGE_OFFSET_LINE.key() << ": " + << theSubImageOffset.line + << "\n" << SUB_IMAGE_OFFSET_SAMP.key() << ": " + << theSubImageOffset.samp + << "\n" << HEADER_SIZE.key() << ": " + << theHeaderSize + << "\n" << SET_NULLS.key() << ": " + << (ossim_uint32)theSetNullsMode + << "\n" << PIXELS_TO_CHOP.key() << ": " + << thePixelsToChop + << endl; + + if (bytesPerPixel() > 1) + { + out << ossimKeywordNames::BYTE_ORDER_KW << ": " + << (theImageDataByteOrder == OSSIM_LITTLE_ENDIAN ? "little_endian" : + "big_endian") + << endl; + } + for (i=0; i<numberOfBands(); ++i) + { + out << "band" << i+1 << ".min_value: " << theMetaData.getMinPix(i) + << "\nband" << i+1 << ".max_value: " << theMetaData.getMaxPix(i) + << "\nband" << i+1 << ".null_value: " << theMetaData.getNullPix(i) + << endl; + } + + return ossimErrorStatusInterface::print(out); +} + +void ossimGeneralRasterInfo::setFillToNullsMode(ossim_uint32 mode) +{ + static const char MODULE[] = "ossimGeneralRasterInfo::setFillToNullMode"; + if(mode < 3) + { + theSetNullsMode = (ossimFillMode)mode; + } + else + { + cerr << MODULE << " ERROR:" + << "\nmode out of bounds(0 - 2): " << mode << endl + << "\nmode has not been changed." << endl; + } +} + +ossim_uint32 ossimGeneralRasterInfo::bytesPerPixel(ossimScalarType type) const +{ + ossim_uint32 bpp; + + switch (type) + { + case OSSIM_UCHAR: + bpp = 1; + break; + case OSSIM_USHORT16: + case OSSIM_SSHORT16: + case OSSIM_USHORT11: + bpp = 2; + break; + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + bpp = 4; + break; + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_DOUBLE: + bpp = 8; + break; + default: + bpp = 0; + break; + } + + return bpp; +} + +void ossimGeneralRasterInfo::setImageDataByteOrder(ossimByteOrder byteOrder) +{ + theImageDataByteOrder = byteOrder; +} + +bool ossimGeneralRasterInfo::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + for (ossim_uint32 i=0; i<theImageFileList.size(); ++i) + { + ossimString kw = ossimKeywordNames::FILENAME_KW; + kw += ossimString::toString(i+1); + kwl.add(prefix, theImageFileList[i].c_str()); + } + + theMetaData.saveState(kwl, prefix); + + kwl.add(prefix, + NUMBER_LINES, + rawLines(), + true); + kwl.add(prefix, + NUMBER_SAMPLES, + rawSamples(), + true); + kwl.add(prefix, + HEADER_SIZE, + theHeaderSize, + true); + kwl.add(prefix, + SUB_IMAGE_OFFSET_LINE, + theSubImageOffset.line, + true); + kwl.add(prefix, + SUB_IMAGE_OFFSET_SAMP, + theSubImageOffset.samp, + true); + kwl.add(prefix, + VALID_START_LINE, + theValidImageRect.ul().y, + true); + kwl.add(prefix, + VALID_STOP_LINE, + theValidImageRect.lr().y, + true); + kwl.add(prefix, + VALID_START_SAMPLE, + theValidImageRect.ul().x, + true); + kwl.add(prefix, + VALID_STOP_SAMPLE, + theValidImageRect.ur().x, + true); + kwl.add(prefix, + ossimKeywordNames::INTERLEAVE_TYPE_KW, + INTERLEAVE_TYPE_LUT.getEntryString(theInterleaveType), + true); + + kwl.add(prefix, + PIXELS_TO_CHOP, + thePixelsToChop, + true); + + kwl.add(prefix, + SET_NULLS, + theSetNullsMode, + true); + + + if (bytesPerPixel() > 1) + { + kwl.add(prefix, + ossimKeywordNames::BYTE_ORDER_KW, + (theImageDataByteOrder == OSSIM_LITTLE_ENDIAN ? "little_endian" : + "big_endian"), + true); + } + + return true; +} + +bool ossimGeneralRasterInfo::loadState(const ossimKeywordlist& kwl, const char* prefix) +{ + static const char MODULE[] = "ossimGeneralRasterInfo::loadState"; + // Check for errors in the ossimKeywordlist. + if(kwl.getErrorStatus() == ossimErrorCodes::OSSIM_ERROR) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + cerr << MODULE << " ERROR:\n" + << "Detected an error in the keywordlist: " << kwl + << endl; + return false; + } + + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nprefix: " << (prefix ? prefix : "") + << "\nInput keyword list\n" + << kwl + << endl; + } + + const char* kwlLookup = 0; // Use for keyword list lookups. + + if(!theMetaData.loadState(kwl, prefix)) + { + return false; + } + + int tmp = INTERLEAVE_TYPE_LUT.getEntryNumber(kwl); + if (tmp == ossimLookUpTable::NOT_FOUND) + { + theInterleaveType = OSSIM_BIL; + } + else + { + theInterleaveType = static_cast<ossimInterleaveType>(tmp); + } + + // Get the image files. + + theImageFileList.clear(); // Start with a clean list. + + if (theInterleaveType != OSSIM_BSQ_MULTI_FILE) + { + // Look for "filename" first, then deprecated "image_file". + kwlLookup = kwl.find(ossimKeywordNames::FILENAME_KW); + if (!kwlLookup) + { + // deprecated keyword... + kwlLookup = kwl.find(ossimKeywordNames::IMAGE_FILE_KW); + } + + if (kwlLookup) + { + theImageFileList.push_back(ossimFilename(kwlLookup)); + } + else + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + if (traceDebug()) + { + cerr << "ERROR:\n" + << "Required keyword not found: " + << ossimKeywordNames::FILENAME_KW << endl; + } + return false; + } + } + else + { + // multiple file names. + ossim_uint32 count = 0; + + // look for image file key word with no number. + // Required to have this. + kwlLookup = kwl.find(ossimKeywordNames::FILENAME_KW); + if (!kwlLookup) + { + // deprecated keyword... + kwlLookup = kwl.find(ossimKeywordNames::IMAGE_FILE_KW); + } + + if (kwlLookup) + { + theImageFileList.push_back(ossimFilename(kwlLookup)); + ++count; + } + + ossim_int32 i = 0; + while ( (count < numberOfBands()) && (i < 1000) ) + { + ossimString kw = ossimKeywordNames::FILENAME_KW; + kw += ossimString::toString(i); + kwlLookup = kwl.find(kw); + if (!kwlLookup) + { + // Lookup for deprecated keyword. + kw = ossimKeywordNames::IMAGE_FILE_KW; + kw += ossimString::toString(i); + kwlLookup = kwl.find(kw); + } + + if (kwlLookup) + { + theImageFileList.push_back(ossimFilename(kwlLookup)); + ++count; + } + ++i; + } + + if (count != numberOfBands()) // Error, count should equal bands! + { + if (traceDebug()) + { + cerr << " ERROR:\n" + << "Required keyword not found: " + << ossimKeywordNames::FILENAME_KW + << "\nInterleave type is multi file; however," + << " not enough were pick up!" << endl; + } + return false; + } + } + + kwlLookup = kwl.find(NUMBER_LINES); // Required to have this. + if (kwlLookup) + { + theRawImageRect.set_lry(atoi(kwlLookup) - 1); + } + else + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + if (traceDebug()) + { + cerr << " ERROR:\n" + << "Required keyword not found: " << NUMBER_LINES << endl; + } + return false; + } + + kwlLookup = kwl.find(NUMBER_SAMPLES); // Required to have this. + if (kwlLookup) + { + theRawImageRect.set_lrx(atoi(kwlLookup) - 1); + } + else + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + if (traceDebug()) + { + cerr << " ERROR:\n" + << "Required keyword not found: " << NUMBER_SAMPLES << endl; + } + return false; + } + + kwlLookup = kwl.find(VALID_START_LINE); // Default is zero. + if (kwlLookup) + { + theValidImageRect.set_uly(atoi(kwlLookup)); + } + + kwlLookup = kwl.find(VALID_STOP_LINE); // Default is last line. + if (kwlLookup) + { + theValidImageRect.set_lry(atoi(kwlLookup)); + } + else + { + theValidImageRect.set_lry(theRawImageRect.lr().y); + } + + if (theValidImageRect.lr().y < theValidImageRect.ul().y) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + cerr << " ERROR:" + << "\nValid stop line < start line." + << "\nValid start line: " << theValidImageRect.ul().y + << "\nValid stop line: " << theValidImageRect.lr().y + << "\nError status has been set. Returning." << endl; + return false; + } + + kwlLookup = kwl.find(VALID_START_SAMPLE); // Default is zero. + if (kwlLookup) + { + theValidImageRect.set_ulx(atoi(kwlLookup)); + } + + kwlLookup = kwl.find(VALID_STOP_SAMPLE); // Default is last sample. + if (kwlLookup) + { + theValidImageRect.set_lrx(atoi(kwlLookup)); + } + else + { + theValidImageRect.set_lrx(theRawImageRect.lr().x); + } + + if (theValidImageRect.lr().x < theValidImageRect.ul().x) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + cerr << " ERROR:" + << "\nValid stop samp < start samp." + << "\nValid start samp: " << theValidImageRect.ul().x + << "\nValid stop samp: " << theValidImageRect.lr().x + << "\nError status has been set. Returning." << endl; + return false; + } + + theImageRect.set_lry(theValidImageRect.lr().y - + theValidImageRect.ul().y); + theImageRect.set_lrx(theValidImageRect.lr().x - + theValidImageRect.ul().x); + + kwlLookup = kwl.find(SUB_IMAGE_OFFSET_LINE); // Default is zero. + if (kwlLookup) + theSubImageOffset.line = atoi(kwlLookup); + + kwlLookup = kwl.find(SUB_IMAGE_OFFSET_SAMP); // Default is zero. + if (kwlLookup) + theSubImageOffset.samp = atoi(kwlLookup); + + kwlLookup = kwl.find(HEADER_SIZE); // Default is zero. + if (kwlLookup) + { + theHeaderSize = atoi(kwlLookup); + } + + kwlLookup = kwl.find(SET_NULLS); // Default is 2. + if (kwlLookup) + { + int tmp; + tmp = atoi(kwlLookup); + if ((tmp < 3) && (tmp > -1)) + { + theSetNullsMode = (ossimFillMode)tmp; + } + else + { + theSetNullsMode = ZEROES_TO_NULL_EDGES_ONLY; // 2 + ossimNotify(ossimNotifyLevel_WARN) + << " WARNING:" + << "\nset_fill_to_nulls_mode value out of range." + << "\nDefaulted to 2" << endl; + } + } + + kwlLookup = kwl.find(PIXELS_TO_CHOP); // Default is zero. + if (kwlLookup) + { + thePixelsToChop = atoi(kwlLookup); + } + + if (bytesPerPixel() > 1) + { + // get the byte order of the data. + kwlLookup = kwl.find(ossimKeywordNames::BYTE_ORDER_KW); + if (kwlLookup) + { + ossimString s(kwlLookup); + if (s.trim() != "") // Check for empty string. + { + s.downcase(); + if (s.contains("big")) + { + theImageDataByteOrder = OSSIM_BIG_ENDIAN; + } + else if(s.contains("little")) + { + theImageDataByteOrder = OSSIM_LITTLE_ENDIAN; + } + } + } + } + if (traceDebug()) + { + CLOG << "Exiting....." << endl; + } + return true; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/general_raster/ossimGeneralRasterInfo.h b/Utilities/OSSIM/ossim_core/imaging/formats/general_raster/ossimGeneralRasterInfo.h new file mode 100644 index 0000000000..299dd18076 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/general_raster/ossimGeneralRasterInfo.h @@ -0,0 +1,367 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class declaration for ossimGeneralRasterInfo +//******************************************************************* +// $Id: ossimGeneralRasterInfo.h,v 1.18 2005/04/18 14:17:52 dburken Exp $ + +#ifndef ossimGeneralRasterInfo_HEADER +#define ossimGeneralRasterInfo_HEADER + +#include <base/common/ossimObject.h> +#include <base/common/ossimErrorStatusInterface.h> +#include <base/common/ossimConstants.h> +#include <base/data_types/ossimIrect.h> +#include <base/data_types/ossimDrect.h> +#include <base/data_types/ossimFilename.h> +#include <base/context/ossimErrorContext.h> +#include <imaging/ossimImageMetaData.h> + +//*** +// Forward class declarations. +//*** +class ossimKeywordlist; +class ossimIect; +class ossimDrect; +class ossimString; + + +//*************************************************************************** +// CLASS: ossimGeneralRasterInfo +//*************************************************************************** +class OSSIMDLLEXPORT ossimGeneralRasterInfo : public ossimObject, + public ossimErrorStatusInterface +{ +public: + + enum ossimFillMode + { + NONE, + ZEROES_TO_MIN, + ZEROES_TO_NULL_EDGES_ONLY + }; + + enum + { + UNKNOWN = -1 + }; + + ossimGeneralRasterInfo(); + + ossimGeneralRasterInfo(const vector<ossimFilename>& imageFileList, + ossimScalarType pixelType, + ossimInterleaveType il_type, + ossim_uint32 numberOfBands, + ossim_uint32 lines, + ossim_uint32 samples, + ossim_uint32 headerSize, + ossimFillMode nullsMode, + ossim_uint32 pixelsToChop); + + ossimGeneralRasterInfo(const ossimKeywordlist& kwl, const char* prefix=0); + + ~ossimGeneralRasterInfo (); + + /*! + * Zero based rectangle of the valid image. + */ + ossimIrect imageRect() const { return theImageRect; } + + /*! + * Returns the rectangle of where the image is within the raster file. + * In most cases this will be the same as the rawImageRect. (zero based) + */ + ossimIrect validImageRect() const { return theValidImageRect; } + + /*! + * Zero based rectangle of the raw image. + */ + ossimIrect rawImageRect() const { return theRawImageRect; } + + /*! + * Returns the offset of this image's origin to a full-image's origin, in + * the case where this image is a sub-image of a larger full-image. + */ + ossimIpt subImageOffset() const { return theSubImageOffset; } + + /*! + * Returns the size of header in bytes. + */ + ossim_uint32 headerSize() const { return theHeaderSize; } + + /*! + * Returns the fill mode. This is used to flip values on ingest. + * Valid Mode Enumerations: + * - 0 Do nothing to the pixels on ingest. + * - 1 Flip all zeroes to the minimum pixel value. + * - 2 Flip zeroes within the image line to minimum pixel value. + * This is used by edge walking code. + */ + ossim_uint32 fillToNullsMode() const { return theSetNullsMode; } + + /*! + * Sets theSetNullsMode. + */ + void setFillToNullsMode(ossim_uint32 mode); + + void setMinPixelValue(ossim_uint32 band, double value) + { + theMetaData.setMinPix(band, value); + } + double getMinPixelValue(ossim_uint32 band)const + { + return theMetaData.getMinPix(band); + } + void setMaxPixelValue(ossim_uint32 band, double value) + { + theMetaData.setMaxPix(band, value); + } + double getMaxPixelValue(ossim_uint32 band)const + { + return theMetaData.getMaxPix(band); + } + void setNullPixelValue(ossim_uint32 band, double value) + { + theMetaData.setNullPix(band, value); + } + double getNullPixelValue(ossim_uint32 band)const + { + return theMetaData.getNullPix(band); + } + /*! + * Sets theNumberOfBands. + */ + void setNumberOfBands(ossim_uint32 bands) { theMetaData.setNumberOfBands(bands); } + + /*! + * Returns the number of pixels from the edge of a line + * to set to the fill value. This can be used to eliminate + * resampling error on the edge of an image and still keep + * the image demensions relative to the geometry file. + */ + ossim_uint32 pixelsToChop() const { return thePixelsToChop; } + + /*! + * Number of bands. Defaulted to one. + */ + ossim_uint32 numberOfBands() const { return theMetaData.getNumberOfBands(); } + + /*! + * Enumerated in InterleaveTypeLUT. Should be either bip, + * bil or bsq. Defaulted to bip. + */ + ossimInterleaveType interleaveType() const { return theInterleaveType; } + + /*! + * Returns the pixel type represented as a "PixelType" enumeration. + * See "constants.h" file for PixelType enumerations. + */ + ossimScalarType getScalarType() const { return theMetaData.getScalarType(); } + + /*! + * Returns the number of lines within "theValidImageRect". + */ + ossim_uint32 validLines() const; + + /*! + * Returns the number of lines within "theRawImageRect". + */ + ossim_uint32 rawLines() const; + + /*! + * Returns the number of bytes in a raw line. + */ + ossim_uint32 bytesPerRawLine() const; + + /*! + * Returns the number of bytes in a valid line. + */ + ossim_uint32 bytesPerValidLine() const; + + /*! + * Returns the number of samples within "theValidImageRect". + */ + ossim_uint32 validSamples() const; + + /*! + * Returns the number of samples within "theRawImageRect". + */ + ossim_uint32 rawSamples() const; + + /*! + * Returns the offset in bytes to the first valid sample in the image. + */ + ossim_uint32 offsetToFirstValidSample() const; + + vector<ossimFilename> getImageFileList() const { return theImageFileList; } + + void setImageFileList(const vector<ossimFilename>& list) + { theImageFileList = list; } + void setHeaderSize(ossim_uint32 headerSize) {theHeaderSize = headerSize;} + void setInterleaveType(ossimInterleaveType il_type) + {theInterleaveType = il_type;} + virtual std::ostream& print(std::ostream& out) const; + void setImageRect(const ossimIrect& imageRect){theImageRect = imageRect;} + void setValidImageRect(const ossimIrect &imageRect) + {theValidImageRect = imageRect;} + void setRawImageRect(const ossimIrect &imageRect) + {theRawImageRect=imageRect;} + void setSubImageOffset(const ossimIpt& d) { theSubImageOffset = d; } + + ossim_uint32 bytesPerPixel(ossimScalarType type) const; + ossim_uint32 bytesPerPixel() const; + + ossimByteOrder getImageDataByteOrder() const + { return theImageDataByteOrder; } + + void setImageDataByteOrder(ossimByteOrder byteOrder); + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +private: + ossimImageMetaData theMetaData; + vector<ossimFilename> theImageFileList; + ossimInterleaveType theInterleaveType; + ossim_uint32 theNumberOfBands; + + /*! + * The zero based rectangle of the entire image not including any header. + */ + ossimIrect theRawImageRect; + + /*! + * The rectangle representing where the valid part of the image lies + * within "theRawImageRect". + */ + ossimIrect theValidImageRect; + + /*! + * The valid image rectangle normalized to be zero based. + */ + ossimIrect theImageRect; + + /*! + * The offset from the full-image origin to this image's origin + */ + ossimIpt theSubImageOffset; + + /*! + * Size of header in bytes. + */ + ossim_uint32 theHeaderSize; + + /*! + * Mode of how to handle pixels on import. + * 0 = Do nothing the pixels. + * 1 = Set any zeroes to min value of radiometry. + * 2 = Set zeroes on line edges only to nulls; any other zeroes are + * set to min value of radiometry. + */ + ossimFillMode theSetNullsMode; + + /*! + * Amount of pixels to chop for each line edge. + */ + ossim_uint32 thePixelsToChop; + + /*! + * The byte order the image data is stored in. + */ + ossimByteOrder theImageDataByteOrder; +}; + + +//*** +// Inlines +//*** +inline ossim_uint32 ossimGeneralRasterInfo::validLines() const +{ + return theValidImageRect.lr().y - theValidImageRect.ul().y + 1; +} + +inline ossim_uint32 ossimGeneralRasterInfo::rawLines() const +{ + return theRawImageRect.lr().y - theRawImageRect.ul().y + 1; +} + +inline ossim_uint32 ossimGeneralRasterInfo::bytesPerRawLine() const +{ + if (interleaveType() == OSSIM_BIP) + { + return rawSamples() * bytesPerPixel() * numberOfBands(); + } + else + { + return rawSamples() * bytesPerPixel(); + } +} + +inline ossim_uint32 ossimGeneralRasterInfo::bytesPerValidLine() const +{ + if (interleaveType() == OSSIM_BIP) + { + return validSamples() * bytesPerPixel() * numberOfBands(); + } + else + { + return validSamples() * bytesPerPixel(); + } +} + +inline ossim_uint32 ossimGeneralRasterInfo::validSamples() const +{ + return theValidImageRect.lr().x - theValidImageRect.ul().x + 1; +} + +inline ossim_uint32 ossimGeneralRasterInfo::rawSamples() const +{ + return theRawImageRect.lr().x - theRawImageRect.ul().x + 1; +} + +inline ossim_uint32 ossimGeneralRasterInfo::bytesPerPixel() const +{ + return bytesPerPixel((ossimScalarType)theMetaData.getScalarType()); +} + +inline ossim_uint32 ossimGeneralRasterInfo::offsetToFirstValidSample() const +{ + if (interleaveType() == OSSIM_BIP) + { + return headerSize() + + ( bytesPerRawLine() * validImageRect().ul().y ) + + ( validImageRect().ul().x * numberOfBands() * bytesPerPixel() ); + } + else if (interleaveType() == OSSIM_BIL) + { + return headerSize() + + ( bytesPerRawLine() * validImageRect().ul().y * numberOfBands() ) + + ( validImageRect().ul().x * bytesPerPixel()); + } + else // BSQ + { + return headerSize() + + ( bytesPerRawLine() * validImageRect().ul().y ) + + ( validImageRect().ul().x * bytesPerPixel() ); + } +} + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/general_raster/ossimGeneralRasterTileSource.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/general_raster/ossimGeneralRasterTileSource.cpp new file mode 100644 index 0000000000..fe1428b98c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/general_raster/ossimGeneralRasterTileSource.cpp @@ -0,0 +1,1192 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class definition for ossimGeneralRasterTileSource. +//******************************************************************* +// $Id: ossimGeneralRasterTileSource.cpp,v 1.73 2005/11/17 15:05:57 gpotts Exp $ + +#include <imaging/formats/general_raster/ossimGeneralRasterTileSource.h> +#include <base/common/ossimConstants.h> +#include <base/context/ossimErrorContext.h> +#include <base/misc/lookup_tables/ossimInterleaveTypeLut.h> +#include <base/misc/lookup_tables/ossimScalarTypeLut.h> +#include <base/misc/ossimEndian.h> +#include <base/data_types/ossimIpt.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimIrect.h> +#include <base/data_types/ossimFilename.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/common/ossimKeywordNames.h> +#include <base/common/ossimTrace.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <imaging/formats/tiff/ossimTiffTileSource.h> +#include <base/factory/ossimStreamFactoryRegistry.h> + +RTTI_DEF1_INST(ossimGeneralRasterTileSource, + "ossimGeneralRasterTileSource", + ossimImageHandler) + +static ossimTrace traceDebug("ossimGeneralRasterTileSource:debug"); + +// For interleave type enum to string conversions. +static const ossimInterleaveTypeLut ILUT; + +//******************************************************************* +// Public Constructor: +//******************************************************************* +ossimGeneralRasterTileSource::ossimGeneralRasterTileSource() + : + ossimImageHandler(), + theTile(NULL), + theBuffer(NULL), + theBufferInterleave(OSSIM_BIL), + theFileStrList(0), + theImageData(), + theBufferRect(0, 0, 0, 0), + theSwapBytesFlag(false), + theBufferSizeInPixels(0) +{} + +//******************************************************************* +// Public Constructor: +//******************************************************************* +ossimGeneralRasterTileSource:: +ossimGeneralRasterTileSource(const ossimKeywordlist& kwl, + const char* prefix) + : + ossimImageHandler(), + theTile(NULL), + theBuffer(NULL), + theBufferInterleave(OSSIM_BIL), + theFileStrList(0), + theImageData(), + theBufferRect(0, 0, 0, 0), + theSwapBytesFlag(false), + theBufferSizeInPixels(0) +{ + if (loadState(kwl, prefix) == false) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + } +} + +//******************************************************************* +// Public Constructor: +//******************************************************************* +ossimGeneralRasterTileSource::ossimGeneralRasterTileSource(const ossimGeneralRasterInfo& id) + : + ossimImageHandler(), + theTile(NULL), + theBuffer(NULL), + theBufferInterleave(OSSIM_BIL), + theFileStrList(0), + theImageData(id), + theBufferRect(0, 0, 0, 0), + theSwapBytesFlag(false), + theBufferSizeInPixels(0) +{ + open(id); + +} + +//******************************************************************* +// Destructor: +//******************************************************************* +ossimGeneralRasterTileSource::~ossimGeneralRasterTileSource() +{ + if (theBuffer) + { + delete [] theBuffer; + theBuffer = NULL; + } + + // Delete the list of input streams and clear the list. +// std::vector<ossimRefPtr<ossimIStream> >::iterator is = theFileStrList.begin(); +// while (is != theFileStrList.end()) +// { +// (*is)->close(); +// *is = 0; +// (*is)->close(); +// delete *is; +// *is = NULL; +// ++is; +// } + + theFileStrList.clear(); +} + +ossimRefPtr<ossimImageData> ossimGeneralRasterTileSource::getTile( + const ossimIrect& tile_rect, ossim_uint32 resLevel) +{ + if( !isOpen() || !isSourceEnabled() || !isValidRLevel(resLevel) ) + { + return ossimRefPtr<ossimImageData>(); + } + + // general rasters can have a subimage as an offset so let's make sure we + // shift it if its in the header + ossimIrect theShiftedImageRect = tile_rect - theImageData.subImageOffset(); + + if (theOverview) + { + if (resLevel || theOverview->hasR0()) + { + return theOverview->getTile(theShiftedImageRect, resLevel); + } + } + + theTile->setImageRectangle(theShiftedImageRect); + + ossimIrect image_rect = ossimIrect(0, + 0, + getNumberOfSamples(resLevel) - 1, + getNumberOfLines(resLevel) - 1); + + ossimIrect clip_rect = theShiftedImageRect.clipToRect(image_rect); + + checkBuffer(tile_rect); + + //*** + // Check origin to see if it falls with the image. If not, return a + // blank chip. + //*** + if ( theShiftedImageRect.intersects(image_rect) ) + { + if ( ! theShiftedImageRect.completely_within(theBufferRect) ) + { + // A new buffer must be loaded. + if ( !theShiftedImageRect.completely_within(clip_rect) ) + { + //*** + // Start with a blank tile since the whole tile buffer will not be + // filled. + //*** + theTile->makeBlank(); + } + + if(!fillBuffer(clip_rect.ul())) + { + ossimNotify(ossimNotifyLevel_WARN) + << "Error from fill buffer..." + << endl; + //*** + // Error in filling buffer. + //*** + setErrorStatus(); + return ossimRefPtr<ossimImageData>(); + } + } + + theTile->loadTile(theBuffer, + theBufferRect, + clip_rect, + theBufferInterleave); + theTile->validate(); + } + else + { + // tile does not intersect the image rectangle. + return ossimRefPtr<ossimImageData>(); + } + + return theTile; + +} + +//******************************************************************* +// Private Method: +//******************************************************************* +bool ossimGeneralRasterTileSource::fillBuffer(const ossimIpt& origin) +{ + static const char MODULE[] = "ossimGeneralRasterTileSource::fillBuffer"; + + // Note: InterleaveType enumerations in "constants.h" file. + bool status = false; + switch (theImageData.interleaveType()) + { + case OSSIM_BIP: + status = fillBIP(origin); + break; + case OSSIM_BIL: + status = fillBIL(origin); + break; + case OSSIM_BSQ: + status = fillBSQ(origin); + break; + case OSSIM_BSQ_MULTI_FILE: + status = fillBsqMultiFile(origin); + break; + default: + ossimNotify(ossimNotifyLevel_WARN) << MODULE << " ERROR:\n" + << " Unsupported interleave type: " + << ILUT.getEntryString(theImageData.interleaveType()) + << endl; + } + + if (status && theSwapBytesFlag) + { + ossimEndian oe; + oe.swap(theImageData.getScalarType(), + theBuffer, + theBufferSizeInPixels); + } + + return status; +} + +//******************************************************************* +// Private Method: +//******************************************************************* +bool ossimGeneralRasterTileSource::fillBIP(const ossimIpt& origin) +{ + static const char MODULE[] = "ossimGeneralRasterTileSource::fillBIP"; + + //*** + // This will fill a buffer the full width of valid samples * getHeight(). + //*** + theBufferRect.set_ul(origin); + + theBufferRect.set_lry(min( (origin.y + (ossim_int32)theTile->getHeight() -1), + theImageData.imageRect().lr().y)); + theBufferRect.set_lrx(min( (origin.x + (ossim_int32)theTile->getWidth() -1), + theImageData.imageRect().lr().x)); + + ossim_int32 currentLine = origin.y; + + //*** + // Seek position. The seek position must take into account: + // 1). Any header offset "theOffsetInBytes". + // 2). Any line offset "theLineOffset." + // 3). Number of bands. + // + // NOTE: seekPos is in bytes so theBytesPerPixel must be taken into + // account also. + //*** + std::streampos offset = theImageData.offsetToFirstValidSample() + + currentLine * theImageData.bytesPerRawLine() + + origin.x * theImageData.bytesPerPixel() * + theImageData.numberOfBands(); + +#if 0 + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "\nDEBUG:" + << "\norigin: " << origin + << "\nSeek position: " << offset + << "\nStarting line number: " << currentLine << endl; + } +#endif + + //*** + // Loop through and process lines. + //*** + ossim_int32 linesProcessed = 0; + + size_t buffer_width = theBufferRect.width() * theImageData.numberOfBands() * + theImageData.bytesPerPixel(); + + + ossim_uint8* buf = theBuffer; + + ossim_sint32 height = theTile->getHeight(); + + while (currentLine <= theImageData.imageRect().lr().y && + linesProcessed < height) + { + //*** + // Seek to line. + //*** + theFileStrList[0]->seekg(offset, ios::beg); + if (!(*theFileStrList[0])) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_WARN) << MODULE << " ERROR:\n" + << " Seek error! Returning with error..." << endl; + return false; + } + + //*** + // Read the line of image data. + //*** + theFileStrList[0]->read((char*)buf, buffer_width); + if ((long)theFileStrList[0]->gcount() != (long)buffer_width) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_WARN) << MODULE << "\nERROR: Reading image line." << endl; + return false; + } + + ++currentLine; + ++linesProcessed; + buf += buffer_width; + offset += theImageData.bytesPerRawLine(); + } + + return true; +} + +//******************************************************************* +// Private Method: +//******************************************************************* +bool ossimGeneralRasterTileSource::fillBIL(const ossimIpt& origin) +{ + static const char MODULE[] = "ossimGeneralRasterTileSource::fillBIL"; + + //*** + // This will fill a buffer the full width of valid samples * tileHeight(). + //*** + theBufferRect.set_ul(origin); + theBufferRect.set_lry(min((origin.y + (ossim_int32)theTile->getHeight() - 1), + theImageData.imageRect().lr().y)); + theBufferRect.set_lrx(min((origin.x + (ossim_int32)theTile->getWidth() - 1), + theImageData.imageRect().lr().x)); + + ossim_int32 currentLine = origin.y; + + // Start seek position. + std::streampos offset = theImageData.offsetToFirstValidSample() + + currentLine * theImageData.bytesPerRawLine() * + theImageData.numberOfBands() + + origin.x * theImageData.bytesPerPixel(); + + //*** + // Loop through and process lines. + //*** + ossim_int32 linesProcessed = 0; + + size_t buffer_width = theBufferRect.width() * theImageData.bytesPerPixel(); + + ossim_uint8* buf = theBuffer; + +#if 0 + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "\nDEBUG:" + << "\norigin: " << origin + << "\nSeek position: " << offset + << "\nStarting line number: " << currentLine + << "\nbuffer_width: " << buffer_width << endl; + } +#endif + + ossim_int32 height = theTile->getHeight(); + ossim_int32 num_bands = theImageData.numberOfBands(); + + while (currentLine <= theImageData.imageRect().lr().y && + linesProcessed < height) + { + for (ossim_int32 band = 0; band < num_bands; ++band) + { + //*** + // Seek to line. + //*** + theFileStrList[0]->seekg(offset, ios::beg); + if (!theFileStrList[0]) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_WARN) << MODULE << " ERROR:\n" + << " Seek error! Returning with error..." << endl; + return false; + } + + //*** + // Read the line of image data. + //*** + theFileStrList[0]->read((char*)buf, buffer_width); + if ((long)theFileStrList[0]->gcount() != (long)buffer_width) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_WARN) << MODULE << "\nERROR: Reading image line." + << "\ncurrentLine: " << currentLine << endl; + return false; + } + + buf += buffer_width; + offset += theImageData.bytesPerRawLine(); + + } // End of band loop. + + ++linesProcessed; + ++currentLine; + } + + return true; +} + +//******************************************************************* +// Private Method: +//******************************************************************* +bool ossimGeneralRasterTileSource::fillBSQ(const ossimIpt& origin) +{ + static const char MODULE[] = "ossimGeneralRasterTileSource::fillBSQ"; + + //*** + // This will fill a buffer the full width of valid samples * tileHeight(). + //*** + theBufferRect.set_ul(origin); + + theBufferRect.set_lry(min((origin.y + (ossim_int32)theTile->getHeight() -1), + theImageData.imageRect().lr().y)); + theBufferRect.set_lrx(min((origin.x + (ossim_int32)theTile->getWidth() - 1), + theImageData.imageRect().lr().x)); + + //*** + // Start seek position. + //*** + std::streampos startSeekPosition + = theImageData.offsetToFirstValidSample() + + origin.y * theImageData.bytesPerRawLine() + + origin.x * theImageData.bytesPerPixel(); + + //*** + // Loop through and process lines. + //*** + size_t buffer_width = theBufferRect.width() * theImageData.bytesPerPixel(); + + ossim_uint8* buf = (ossim_uint8*)theBuffer; + +#if 0 + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "\nDEBUG:" + << "\norigin: " << origin + << "\nSeek position: " << startSeekPosition + << "\nStarting line number: " << origin.y + << "\nbuffer_width: " << buffer_width + << "\nbytesPerRawLine(): " + << theImageData.bytesPerRawLine() + << "\ntheImageData.offsetToFirstValidSample(): " + << theImageData.offsetToFirstValidSample() << endl; + } +#endif + + std::streampos bandOffset + = theImageData.bytesPerRawLine() * theImageData.rawLines(); + + ossim_int32 num_bands = theImageData.numberOfBands(); + ossim_int32 height = theTile->getHeight(); + + for (ossim_int32 band = 0; band < num_bands; ++band) + { + ossim_int32 currentLine = origin.y; + ossim_int32 linesProcessed = 0; + + std::streampos offset = startSeekPosition + (band * bandOffset); + + while (currentLine <= theImageData.imageRect().lr().y && + linesProcessed < height) + { + //*** + // Seek to line. + //*** + theFileStrList[0]->seekg(offset, ios::beg); + if (!theFileStrList[0]) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_WARN) << MODULE << " ERROR:\n" + << " Seek error! Returning with error..." << endl; + return false; + } + + //*** + // Read the line of image data. + //*** + theFileStrList[0]->read((char*)buf, buffer_width); + if ((long)theFileStrList[0]->gcount() != (long)buffer_width) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_WARN) << MODULE << "\nERROR: Reading image line." + << "\ncurrentLine: " << currentLine << endl; + return false; + } + + // Increment everybody accordingly. + buf += buffer_width; + offset += theImageData.bytesPerRawLine(); + ++linesProcessed; + ++currentLine; + + } // End of line loop. + + } // End of band loop. + + return true; +} + +//******************************************************************* +// Private Method: +//******************************************************************* +bool ossimGeneralRasterTileSource::fillBsqMultiFile(const ossimIpt& origin) +{ + static const char MODULE[] + = "ossimGeneralRasterTileSource::fillBsqMultiFile"; + + if (traceDebug()) CLOG << " Entered..." << endl; + + + //*** + // This will fill a buffer the full width of valid samples * tileHeight(). + //*** + theBufferRect.set_ul(origin); + + theBufferRect.set_lry(min((origin.y + (ossim_int32)theTile->getHeight() -1), + theImageData.imageRect().lr().y)); + theBufferRect.set_lrx(min((origin.x + (ossim_int32)theTile->getWidth() - 1), + theImageData.imageRect().lr().x)); + + //*** + // Start seek position. + //*** + std::streampos startSeekPosition + = theImageData.offsetToFirstValidSample() + + origin.y * theImageData.bytesPerRawLine() + + origin.x * theImageData.bytesPerPixel(); + + //*** + // Loop through and process lines. + //*** + size_t buffer_width = theBufferRect.width() * theImageData.bytesPerPixel(); + + ossim_uint8* buf = (ossim_uint8*)theBuffer; + +#if 0 + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "\nDEBUG:" + << "\norigin: " << origin + << "\nSeek position: " << startSeekPosition + << "\nStarting line number: " << origin.y + << "\nbuffer_width: " << buffer_width + << "\nbuffer_rect: " << theBufferRect + << "\nbytesPerRawLine(): " + << theImageData.bytesPerRawLine() + << "\ntheImageData.offsetToFirstValidSample(): " + << theImageData.offsetToFirstValidSample() << endl; + } +#endif + + ossim_int32 num_bands = theImageData.numberOfBands(); + ossim_int32 height = theTile->getHeight(); + + for (ossim_int32 band = 0; band < num_bands; ++band) + { + ossim_int32 currentLine = origin.y; + ossim_int32 linesProcessed = 0; + + ossim_int64 offset = startSeekPosition; + + while (currentLine <= theImageData.imageRect().lr().y && + linesProcessed < height) + { + //*** + // Seek to line. + //*** + theFileStrList[band]->seekg(offset, ios::beg); + if (!theFileStrList[band]) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_WARN) << MODULE << " ERROR:\n" + << " Seek error! Returning with error..." << endl; + return false; + } + + //*** + // Read the line of image data. + //*** + theFileStrList[band]->read((char*)buf, buffer_width); + if ((long)theFileStrList[band]->gcount() != (long)buffer_width) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_WARN) << MODULE << "\nERROR: Reading image line." + << "\ncurrentLine: " << currentLine << endl; + return false; + } + + // Increment everybody accordingly. + buf += buffer_width; + offset += theImageData.bytesPerRawLine(); + ++linesProcessed; + ++currentLine; + + } // End of line loop. + + } // End of band loop. + + return true; +} + +//******************************************************************* +// Public Method: +//******************************************************************* +// ossimIrect +// ossimGeneralRasterTileSource::getImageRectangle(ossim_uint32 reduced_res_level) const +// { +// if(reduced_res_level < getNumberOfDecimationLevels()) +// { +// ossimDpt decimation; +// getDecimationFactor(reduced_res_level, decimation); +// ossimIpt offset = theImageData.subImageOffset(); +// offset.x = irint(offset.x*decimation.x); +// offset.y = irint(offset.y*decimation.y); + +// return ossimIrect(offset.x, // upper left x +// offset.y, // upper left y +// offset.x + getNumberOfSamples(reduced_res_level) - 1, // lower right x +// offset.y + getNumberOfLines(reduced_res_level) - 1); // lower right y +// } +// ossimIrect result; +// result.makeNan(); +// return result; +// } +//******************************************************************* +// Public method: +//******************************************************************* +bool ossimGeneralRasterTileSource::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + theImageData.saveState(kwl, prefix); + + return ossimImageHandler::saveState(kwl, prefix); +} + +//******************************************************************* +// Public method: +//******************************************************************* +bool ossimGeneralRasterTileSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimGeneralRasterTileSource::loadState DEBUG: entered ... " + << std::endl; + } + + if(isOpen()) + { + close(); + } + + const char* filename = kwl.find(prefix, ossimKeywordNames::FILENAME_KW); + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "Trying to open filename " << filename << std::endl; + } + if(filename) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "leaving with open... " << filename << std::endl; + } + if (ossimImageHandler::open(ossimFilename(filename))) + { + // Must call to pick up id for connections. + return ossimImageSource::loadState(kwl, prefix); + } + } + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimGeneralRasterTileSource::loadState DEBUG: " + << "leaving without open... " << std::endl; + } + return false; +} + +//******************************************************************* +// Public method: +//******************************************************************* +ossimScalarType ossimGeneralRasterTileSource::getOutputScalarType() const +{ + return ( theTile.valid() ? theTile->getScalarType() + : OSSIM_SCALAR_UNKNOWN ); +} + +//******************************************************************* +// Public method: +//******************************************************************* +ossim_uint32 ossimGeneralRasterTileSource::getTileWidth() const +{ + return ( theTile.valid() ? theTile->getWidth() : 0 ); +} + +//******************************************************************* +// Public method: +//******************************************************************* +ossim_uint32 ossimGeneralRasterTileSource::getTileHeight() const +{ + return ( theTile.valid() ? theTile->getHeight() : 0 ); +} + +//******************************************************************* +// Public method: +//******************************************************************* +bool +ossimGeneralRasterTileSource::isValidRLevel(ossim_uint32 reduced_res_level) const +{ + static const char MODULE[] = "ossimGeneralRasterTileSource::isValidRLevel"; + + if (reduced_res_level == 0) + { + return true; + } + else if (theOverview) + { + return theOverview->isValidRLevel(reduced_res_level); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE + << " Invalid reduced_res_level: " << reduced_res_level + << "\nHighest available: " << (getNumberOfDecimationLevels() - 1) + << endl; + return false; + } +} + + + +//******************************************************************* +// Public method: +//******************************************************************* +ossim_uint32 +ossimGeneralRasterTileSource::getNumberOfLines(ossim_uint32 reduced_res_level) const +{ + if (reduced_res_level == 0) + { + return theImageData.validLines(); + } + else if (theOverview) + { + return theOverview->getNumberOfLines(reduced_res_level); + } + + return 0; +} + +//******************************************************************* +// Public method: +//******************************************************************* +ossim_uint32 ossimGeneralRasterTileSource:: +getNumberOfSamples(ossim_uint32 reduced_res_level) const +{ + if (reduced_res_level == 0) + { + return theImageData.validSamples(); + } + else if (theOverview) + { + return theOverview->getNumberOfSamples(reduced_res_level); + } + + return 0; +} + +double ossimGeneralRasterTileSource::getNullPixelValue(ossim_uint32 band) const +{ + return theImageData.getNullPixelValue(band); +} + +double ossimGeneralRasterTileSource::getMinPixelValue(ossim_uint32 band)const +{ + return theImageData.getMinPixelValue(band); +} + +double ossimGeneralRasterTileSource::getMaxPixelValue(ossim_uint32 band)const +{ + return theImageData.getMaxPixelValue(band); +} + +bool ossimGeneralRasterTileSource::open() +{ + if(isOpen()) + { + close(); + } + static const char MODULE[] = "ossimGeneralRasterTileSource::open"; + + if (traceDebug()) CLOG << " Entered..." << endl; + + if(isOpen()) + { + close(); + } + + // + // A general raster image requires a keyword list to get essential image + // information or meta data as its sometimes called. The meta data file + // can have three types of extensions: ".omd", ".hdr" and ".kwl" + // Look for them in that order. + // Note that the ".omd" extension is for "Ossim Meta Data" and was made + // up to avoid conflicting with other software packages ".hdr" files. + // + + ossimFilename hdr = theImageFile; + + hdr.setExtension("omd"); + + // See if it's readable. + if ( ! hdr.isReadable() ) + { + hdr.setExtension("hdr"); + + // See if this one's readable. + if ( ! hdr.isReadable() ) + { + // Ok try .kwl extension. + hdr.setExtension("kwl"); + if ( ! hdr.isReadable() ) + { + // No header file so get out. + return false; + } + } + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << "\nHeader file: " << hdr.c_str() << endl; + } + + // Give the header file to the keyword list object. + ossimKeywordlist kwl(hdr); + + // Check for errors. + if (kwl.getErrorStatus() == ossimErrorCodes::OSSIM_ERROR) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_WARN) << MODULE << " Keywordlist open error detected." << endl; + } + + return false; + } + + // + // If the file name passed to us was the header it's assumed the image_file + // keyword is present else assume it's the image file and add if to the + // keyword list. This will overwrite the "image_file" in the header if + // it's in there. + // + if (theImageFile != hdr) + { + kwl.add(ossimKeywordNames::FILENAME_KW, + theImageFile.c_str(), + true); + } + + ossimGeneralRasterInfo generalRasterInfo; + + bool status = generalRasterInfo.loadState(kwl); + theMetaData.loadState(kwl); + // Let the load state do the rest... + // bool status = loadState(kwl); + if(status) + { + status = open(generalRasterInfo); + } + + if (traceDebug()) CLOG << " Exited..." << endl; + + return status; +} + +bool ossimGeneralRasterTileSource::open(const ossimGeneralRasterInfo& info) +{ + if(isOpen()) + { + close(); + } + + theImageData = info; + + if(initializeHandler()) + { + completeOpen(); + } + else + { + return false; + } + + return true; +} + +bool ossimGeneralRasterTileSource::initializeHandler() +{ + //*** + // This private method assumes that "theImageData" object has been + // initialized. Note that "close() should have already been called if + // there was an open file prior to this. + //*** + if(isOpen()) + { + ossimNotify(ossimNotifyLevel_WARN) << "ossimGeneralRasterTileSource::initialize() Coding Error!" + << "\nFile was not closed prior to initialize call!" + << "\nReturning false..." + << endl; + return false; + } + + theSubImageOffset = theImageData.subImageOffset(); + + ossim_uint32 number_of_bands = theImageData.numberOfBands(); + + std::streampos expectedSizeInBytes; + + if (theImageData.interleaveType() != OSSIM_BSQ_MULTI_FILE) + { + expectedSizeInBytes = theImageData.validSamples() * + theImageData.validLines() * + number_of_bands * + theImageData.bytesPerPixel(); + } + else + { + expectedSizeInBytes = theImageData.validSamples() * + theImageData.validLines() * + theImageData.bytesPerPixel(); + } + + vector<ossimFilename> aList = theImageData.getImageFileList(); + + for (ossim_uint32 i=0; i<aList.size(); ++i) + { + // Check the file size. + + + ossimRefPtr<ossimIStream> is = ossimStreamFactoryRegistry::instance()->createNewInputStream(aList[i], std::ios::in|std::ios::binary);//new ifstream(aList[i].c_str(), ios::in | ios::binary); + if ((!is->isCompressed()) && + (aList[i].fileSize() < expectedSizeInBytes)) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_WARN) << "ossimGeneralRasterTileSource::open" << " ERROR:" + << "\nFile size not big enough!\n" + << "\nExpected: " << expectedSizeInBytes + << "\nGot: " << aList[i].fileSize() + << "\nReturning with error..." << endl; + return false; + } + if(is.valid()) + { + // Check the file stream. + if ( is->fail() ) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_WARN) << "ossimGeneralRasterTileSource::open" << " ERROR:\n" + << "Cannot open: " << aList[i].c_str() << endl; + is = 0; + return false; + } + } + + theFileStrList.push_back(is); // Add it to the list... + } + + if(aList.size()==1) + { + theImageFile = aList[0]; + } + + //*** + // Determine the pixel type and make the appropriate tiles. + //*** + ossimScalarType scalar = theImageData.getScalarType(); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimGeneralRasterTileSource::open DEBUG:" + << "\nScalar type: " + << ossimScalarTypeLut::instance()-> + getEntryString(theImageData.getScalarType()) + << endl; + } + + // Make the tiles for the getTile return. + + ossimImageDataFactory* idf = ossimImageDataFactory::instance(); + + theTile = idf->create(this, + scalar, + number_of_bands); + + theTile->initialize(); + + // These values can be overridden by loadState... + for(ossim_uint32 band = 0; band < number_of_bands; ++ band) + { + theTile->setNullPix(theImageData.getNullPixelValue(band), band); + theTile->setMinPix(theImageData.getMinPixelValue(band), band); + theTile->setMaxPix(theImageData.getMaxPixelValue(band), band); + } + theTile->makeBlank(); + // Store the size of the buffer in pixels for swapping bytes. + theBufferSizeInPixels = theTile->getWidth() * theTile->getHeight() * + number_of_bands; + + // Get the buffer size. This is bytes, not pixels. + ossim_int32 buffer_size = theBufferSizeInPixels * theImageData.bytesPerPixel(); + + theBuffer = new ossim_uint8[buffer_size]; + + // Set the buffer interleave type. + theBufferInterleave = theImageData.interleaveType(); + if (theBufferInterleave == OSSIM_BSQ_MULTI_FILE) + { + theBufferInterleave = OSSIM_BSQ; + } + + // Zero out the buffer rect. + theBufferRect = ossimIrect(0, 0, 0, 0); + +// // Check for an overview if not already initialized. +// if (!theOverview) +// { +// openOverview(); +// } + +// // Check for valid image vertices file if not already initialized. +// if (theValidImageVertices.size() == 0) +// { +// openValidVertices(); +// } + + //*** + // Get the byte order of the image data and host machine. If different, + // set the swap bytes flag... + //*** + if (theImageData.getImageDataByteOrder() != ossimGetByteOrder()) + { + theSwapBytesFlag = true; + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimGeneralRasterTileSource::open" << " DEBUG:" + << "\nByte swapping is " + << (theSwapBytesFlag?"enabled.":"not enabled.") + << "\ntheBufferSizeInPixels: " << theBufferSizeInPixels + << "\nbuffer size: " << buffer_size + << "\nImageData:\n"; + theImageData.print(ossimNotify(ossimNotifyLevel_DEBUG)); + } + + return true; +} + +void ossimGeneralRasterTileSource::checkBuffer(const ossimIrect& rect) +{ + if((theBufferRect.width()*theBufferRect.height()) != + (rect.width()*rect.height())) + { + if(theBuffer) + { + delete [] theBuffer; + theBuffer = NULL; + } + } + + if(!theBuffer) + { + ossim_uint32 number_of_bands = theImageData.numberOfBands(); + theBufferSizeInPixels = rect.width()*rect.height()*number_of_bands; + + // Get the buffer size. This is bytes, not pixels. + ossim_int32 buffer_size = theBufferSizeInPixels * theImageData.bytesPerPixel(); + + theBuffer = new ossim_uint8[buffer_size]; + theBufferRect = ossimIrect(0,0,0,0); + } +} + + +bool ossimGeneralRasterTileSource::isOpen() const +{ + if (theFileStrList.size() > 0) + { + if(theFileStrList[0].valid()) + { + return !(theFileStrList[0]->fail()); + } +// return const_cast<ifstream*>(theFileStrList[0])->is_open(); + } + + return false; +} + +void ossimGeneralRasterTileSource::close() +{ + ossimImageHandler::close(); // base class + + theTile = NULL; + if (theBuffer) + { + delete [] theBuffer; + theBuffer = NULL; + } + + // Delete the list of input streams and clear the list. +// vector<istream*>::iterator is = theFileStrList.begin(); +// while (is != theFileStrList.end()) +// { +// delete *is; +// *is = NULL; +// ++is; +// } + + theFileStrList.clear(); +} + +ossim_uint32 ossimGeneralRasterTileSource::getImageTileWidth() const +{ + return 0; +} + +ossim_uint32 ossimGeneralRasterTileSource::getImageTileHeight() const +{ + return 0; +} + +ossimString ossimGeneralRasterTileSource::getShortName()const +{ + return ossimString("ras"); +} + +ossimString ossimGeneralRasterTileSource::getLongName()const +{ + return ossimString("general raster reader"); +} + +ossimString ossimGeneralRasterTileSource::className()const +{ + return ossimString("ossimGeneralRasterTileSource"); +} + +ossim_uint32 ossimGeneralRasterTileSource::getNumberOfInputBands() const +{ + return theImageData.numberOfBands(); +} + +ossim_uint32 ossimGeneralRasterTileSource::getNumberOfOutputBands() const +{ + return getNumberOfInputBands(); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/general_raster/ossimGeneralRasterTileSource.h b/Utilities/OSSIM/ossim_core/imaging/formats/general_raster/ossimGeneralRasterTileSource.h new file mode 100644 index 0000000000..366c08e89a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/general_raster/ossimGeneralRasterTileSource.h @@ -0,0 +1,168 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class declaration for ossimGeneralRasterTileSource. +// ossimGeneralRasterTileSource is derived from ImageHandler which is +// derived from ossimTileSource. +//******************************************************************* +// $Id: ossimGeneralRasterTileSource.h,v 1.38 2005/11/10 14:15:33 gpotts Exp $ + +#ifndef ossimGeneralRasterTileSource_HEADER +#define ossimGeneralRasterTileSource_HEADER + +#include <fstream> +#include <base/common/ossimIoStream.h> + //using namespace std; + +#include <imaging/formats/ossimImageHandler.h> +#include <imaging/formats/general_raster/ossimGeneralRasterInfo.h> + +class ossimImageData; + +class OSSIM_DLL ossimGeneralRasterTileSource : public ossimImageHandler +{ +public: + + ossimGeneralRasterTileSource(); + + explicit ossimGeneralRasterTileSource(const ossimKeywordlist& kwl, + const char* prefix=0); + + explicit ossimGeneralRasterTileSource(const ossimGeneralRasterInfo& id); + + virtual ~ossimGeneralRasterTileSource(); + + virtual ossimString getShortName()const; + virtual ossimString getLongName()const; + virtual ossimString className()const; + + /** + * Returns a pointer to a tile given an origin representing the upper + * left corner of the tile to grab from the image. + * Satisfies pure virtual from TileSource class. + */ + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tile_rect, + ossim_uint32 resLevel=0); + + /** + * Returns the number of bands in the image. + * Satisfies pure virtual from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfInputBands() const; + + /** + * Returns the number of bands in a tile returned from this TileSource. + * Note: we are supporting sources that can have multiple data objects. + * If you want to know the scalar type of an object you can pass in the + */ + virtual ossim_uint32 getNumberOfOutputBands() const; + + /** + * Returns the number of lines in the image. + * Satisfies pure virtual from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfLines(ossim_uint32 reduced_res_level = 0) const; + + /** + * Returns the number of samples in the image. + * Satisfies pure virtual from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfSamples(ossim_uint32 reduced_res_level = 0) const; + + /** + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * Returns the output pixel type of the tile source. + */ + virtual ossimScalarType getOutputScalarType() const; + + /** + * Returns the width of the output tile. + */ + virtual ossim_uint32 getTileWidth() const; + + /** + * Returns the height of the output tile. + */ + virtual ossim_uint32 getTileHeight() const; + + /** + * Returns the tile width of the image or 0 if the image is not tiled. + * Note: this is not the same as the ossimImageSource::getTileWidth which + * returns the output tile width which can be different than the internal + * image tile width on disk. + * Note: This handler will always return 0 for this method. + */ + virtual ossim_uint32 getImageTileWidth() const; + + /** + * Returns the tile width of the image or 0 if the image is not tiled. + * Note: this is not the same as the ossimImageSource::getTileWidth which + * returns the output tile width which can be different than the internal + * image tile width on disk. + * Note: This handler will always return 0 for this method. + */ + virtual ossim_uint32 getImageTileHeight() const; + + bool isValidRLevel(ossim_uint32 reduced_res_level) const; + + virtual void close(); + virtual bool isOpen() const; + virtual bool open(); + virtual bool open(const ossimGeneralRasterInfo& info); + + /** + * Override base getXXXXPixValue methods since the null/min/max can be set + * to something different. Currently returns the same value for all bands. + */ + virtual double getNullPixelValue(ossim_uint32 band=0)const; + virtual double getMinPixelValue(ossim_uint32 band=0)const; + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + +protected: + /** + * Methods return true on succes false on error. + */ + virtual bool fillBuffer(const ossimIpt& origin); + virtual bool fillBIP(const ossimIpt& origin); + virtual bool fillBIL(const ossimIpt& origin); + virtual bool fillBSQ(const ossimIpt& origin); + virtual bool fillBsqMultiFile(const ossimIpt& origin); + + virtual bool initializeHandler(); + virtual void checkBuffer(const ossimIrect& rect); + ossimRefPtr<ossimImageData> theTile; + ossim_uint8* theBuffer; + ossimInterleaveType theBufferInterleave; + std::vector<ossimRefPtr<ossimIStream> > theFileStrList; +// vector<istream*> theFileStrList; + ossimGeneralRasterInfo theImageData; + ossimIrect theBufferRect; + bool theSwapBytesFlag; + ossim_uint32 theBufferSizeInPixels; + +TYPE_DATA +}; + +#endif + diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/general_raster/ossimGeneralRasterWriter.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/general_raster/ossimGeneralRasterWriter.cpp new file mode 100644 index 0000000000..744f558942 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/general_raster/ossimGeneralRasterWriter.cpp @@ -0,0 +1,829 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: David Burken +// +//******************************************************************* +// $Id: ossimGeneralRasterWriter.cpp,v 1.57 2006/01/06 16:46:46 dburken Exp $ + +#include <fstream> + +#include <imaging/formats/general_raster/ossimGeneralRasterWriter.h> +#include <imaging/ossimImageData.h> +#include <imaging/formats/ossimImageHandler.h> +#include <imaging/metadata/ossimEnviHeaderFileWriter.h> +#include <projections/map_projections/ossimMapProjection.h> +#include <base/common/ossimKeywordNames.h> +#include <base/common/ossimTrace.h> +#include <base/context/ossimNotifyContext.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/misc/lookup_tables/ossimScalarTypeLut.h> +#include <base/misc/ossimEndian.h> + + +static ossimTrace traceDebug("ossimGeneralRasterWriter:debug"); + +RTTI_DEF1(ossimGeneralRasterWriter, + "ossimGeneralRasterWriter", + ossimImageFileWriter) + +static const char DEFAULT_FILE_NAME[] = "output.ras"; + +ossimGeneralRasterWriter::ossimGeneralRasterWriter() + : + ossimImageFileWriter(), + theRlevel(0) +{ + setOutputImageType(OSSIM_GENERAL_RASTER_BSQ); + + // Since there is no internal geometry set the flag to write out one. + setWriteExternalGeometryFlag(true); + theOutputByteOrder = ossimEndian().getSystemEndianType(); +} + +ossimGeneralRasterWriter::ossimGeneralRasterWriter( + ossimImageSource* inputSource, const ossimFilename& file) + : + ossimImageFileWriter(file, + inputSource, + NULL), + theRlevel(0) +{ + setOutputImageType(OSSIM_GENERAL_RASTER_BSQ); + + // Since there is no internal geometry set the flag to write out one. + setWriteExternalGeometryFlag(true); + theOutputByteOrder = ossimEndian().getSystemEndianType(); +} + +ossimGeneralRasterWriter::~ossimGeneralRasterWriter() +{ + if(isOpen()) + { + close(); + } +} + +bool ossimGeneralRasterWriter::isOpen()const +{ + // fstream::is_open not const; hence, the messy code... + return const_cast<std::ofstream*>(&theFileStream)->is_open(); +} + +bool ossimGeneralRasterWriter::open() +{ + if(isOpen()) + { + close(); + } + + theFileStream.open(theFilename.c_str(), ios::out | ios::binary); + + if(theFileStream) + { + return true; + } + + return false; +} + +void ossimGeneralRasterWriter::close() +{ + if (theFileStream.is_open()) + { + theFileStream.close(); + } + theFileStream.clear(); +} + +bool ossimGeneralRasterWriter::writeFile() +{ + static const char MODULE[] = "ossimGeneralRasterWriter::writeFile"; + + if( getErrorStatus() != ossimErrorCodes::OSSIM_OK ) + { + ossimNotify(ossimNotifyLevel_FATAL) + << MODULE << " ERROR:" + << "\nError status previously set!" << std::endl; + return false; + } + + if(!theInputConnection->isMaster()) + { + theInputConnection->slaveProcessTiles(); + return true; + } + + open(); + + if(!theFileStream) + { + ossimNotify(ossimNotifyLevel_FATAL) + << MODULE << " ERROR:" + << "\nOutput file not open: " << theFilename.c_str() + << "\nReturning from method." << std::endl; + setErrorStatus(); + return false; + } + + bool result = true; + // Write the file with the image data. + if ( (theOutputImageType == "general_raster_bip") || + (theOutputImageType == "general_raster_bip_envi") ) + { + result = writeToBip(); + } + else if ( (theOutputImageType == "general_raster_bil") || + (theOutputImageType == "general_raster_bil_envi") ) + { + result = writeToBil(); + } + else if ( (theOutputImageType == "general_raster_bsq") || + (theOutputImageType == "general_raster_bsq_envi") ) + { + result = writeToBsq(); + } + else + { + ossimNotify(ossimNotifyLevel_FATAL) + << MODULE << " ERROR:" + << "\nUnsupported output type: " << theOutputImageType << std::endl; + result = false; + } + + if (result) + { + // Flush the stream to disk... + theFileStream.flush(); + + // Do this only on the master process. Note left to right precedence! + if (getSequencer() && getSequencer()->isMaster()) + { + //--- + // Write the header out. We do this last since we must + // compute min max pixel while we are writting the image. + // since the header is an external text file this is Ok + // to do. + //--- + writeHeader(); + + if (theOutputImageType.contains("envi")) + { + writeEnviHeader(); + } + } + } + + if (traceDebug()) CLOG << " Exited..." << std::endl; + + close(); + + return result; +} + + +bool ossimGeneralRasterWriter::writeToBip() +{ + ossimEndian endian; + static const char* const MODULE = "ossimGeneralRasterWriter::writeToBip"; + + if (traceDebug()) CLOG << " Entered." << std::endl; + + + //--- + // Get an arbitrary tile just to get the size in bytes! + // This should be changed later... An ossimImageSourceInterface should know + // this. + //--- + ossimRefPtr<ossimImageData> id; + + // Start the sequence at the first tile. + theInputConnection->setToStartOfSequence(); + + ossim_uint32 bands = theInputConnection->getNumberOfOutputBands(); + ossim_uint32 tilesWide = theInputConnection->getNumberOfTilesHorizontal(); + ossim_uint32 tilesHigh = theInputConnection->getNumberOfTilesVertical(); + ossim_uint32 tileHeight = theInputConnection->getTileHeight(); + ossim_uint32 numberOfTiles = theInputConnection->getNumberOfTiles(); + ossim_uint32 width = theAreaOfInterest.width(); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "\nossimGeneralRasterWriter::writeToBip DEBUG:" + << "\nbands: " << bands + << "\ntilesWide: " << tilesWide + << "\ntilesHigh: " << tilesHigh + << "\ntileHeight: " << tileHeight + << "\nnumberOfTiles: " << numberOfTiles + << "\nwidth: " << width + << std::endl; + } + + //--- + // Buffer to hold one line x tileHeight + //--- + ossim_uint32 bufferSizeInBytes = 0; + ossim_uint32 bytesInLine = 0; + unsigned char* buffer = NULL; + + theMinPerBand.clear(); + theMaxPerBand.clear(); + int tileNumber = 0; + bool wroteSomethingOut = false; + ossimScalarType scalarType = theInputConnection->getOutputScalarType(); + for(ossim_uint32 i = 0; ((i < tilesHigh)&&(!needsAborting())); ++i) + { + // Clear the buffer. + if(buffer) + { + memset(buffer, 0, bufferSizeInBytes); + } + + ossimIrect bufferRect(theAreaOfInterest.ul().x, + theAreaOfInterest.ul().y + i*tileHeight, + theAreaOfInterest.ul().x + (width - 1), + theAreaOfInterest.ul().y + i*tileHeight + (tileHeight - 1)); + // Tile loop in the sample (width) direction. + for(ossim_uint32 j = 0; ((j < tilesWide)&&(!needsAborting())); ++j) + { + // Get the tile and copy it to the buffer. + id = theInputConnection->getNextTile(); + if(id.valid()) + { + id->computeMinMaxPix(theMinPerBand, theMaxPerBand); + if(!buffer) + { + bytesInLine = id->getScalarSizeInBytes() * width * bands; + + //--- + // Buffer to hold one line x tileHeight + //--- + bufferSizeInBytes = bytesInLine * tileHeight; + buffer = new unsigned char[bufferSizeInBytes]; + memset(buffer, 0, bufferSizeInBytes); + } + id->unloadTile(buffer, + bufferRect, + OSSIM_BIP); + } + ++tileNumber; + } + + // Get the number of lines to write from the buffer. + ossim_uint32 linesToWrite = + min(tileHeight, + static_cast<ossim_uint32>(theAreaOfInterest.lr().y - + bufferRect.ul().y + 1)); + // Write the buffer out to disk. + ossim_uint8* buf = buffer; + if(buf) + { + for (ossim_uint32 ii=0; ((ii<linesToWrite)&&(!needsAborting())); ++ii) + { + std::streamsize lineBytes = bytesInLine; + wroteSomethingOut = true; + + if(endian.getSystemEndianType() != theOutputByteOrder) + { + endian.swap(scalarType, + buf, + lineBytes/ossimGetScalarSizeInBytes(scalarType)); + } + theFileStream.write((char*)buf, lineBytes); + if (!theFileStream) + { + ossimNotify(ossimNotifyLevel_FATAL) + << MODULE << " ERROR:" + << "Error returned writing line!" << std::endl; + setErrorStatus(); + if(buffer) + { + // Free the memory. + delete [] buffer; + } + return false; + } + + buf += bytesInLine; + + } // End of loop to write lines from buffer to tiff file. + } + double tile = tileNumber; + double numTiles = numberOfTiles; + setPercentComplete(tile / numTiles * 100); + if(needsAborting()) + { + setPercentComplete(100.0); + } + + } // End of loop in the line (height) direction. + if(buffer) + { + // Free the memory. + delete [] buffer; + } + + if (traceDebug()) CLOG << " Exited." << std::endl; + + return wroteSomethingOut; +} + +bool ossimGeneralRasterWriter::writeToBil() +{ + ossimEndian endian; + static const char* const MODULE = "ossimGeneralRasterWriter::writeToBil"; + + if (traceDebug()) CLOG << " Entered." << std::endl; + + //*** + // Get an arbitrary tile just to get the size in bytes! + // This should be changed later... An ossimImageSourceInterface should know + // this. + //*** + ossimRefPtr<ossimImageData> id; + theInputConnection->setToStartOfSequence(); + + ossim_uint32 bands = theInputConnection->getNumberOfOutputBands(); + ossim_uint32 tilesWide = theInputConnection->getNumberOfTilesHorizontal(); + ossim_uint32 tilesHigh = theInputConnection->getNumberOfTilesVertical(); + ossim_uint32 tileHeight = theInputConnection->getTileHeight(); + ossim_uint32 numberOfTiles = theInputConnection->getNumberOfTiles(); + ossim_uint32 width = theAreaOfInterest.width(); + ossim_uint32 bufferSizeInBytes = 0; + ossim_uint32 bytesInLine = 0; + unsigned char* buffer = NULL; + + // Start with a clean min/max. + theMinPerBand.clear(); + theMaxPerBand.clear(); + + int tileNumber = 0; + bool wroteSomethingOut = false; + ossimScalarType scalarType = theInputConnection->getOutputScalarType(); + for(ossim_uint32 i = 0; ((i < tilesHigh)&&(!needsAborting())); ++i) + { + // Clear the buffer. + // Clear the buffer. + if(buffer) + { + memset(buffer, 0, bufferSizeInBytes); + } + + ossimIrect bufferRect(theAreaOfInterest.ul().x, + theAreaOfInterest.ul().y + i*tileHeight, + theAreaOfInterest.ul().x + (width - 1), + theAreaOfInterest.ul().y + i * + tileHeight + (tileHeight - 1)); + + // Tile loop in the sample (width) direction. + for(ossim_uint32 j = 0; ((j < tilesWide)&&(!needsAborting())); ++j) + { + // Get the tile and copy it to the buffer. + id = theInputConnection->getNextTile(); + if(id.valid()) + { + id->computeMinMaxPix(theMinPerBand, theMaxPerBand); + + if(!buffer) + { + bytesInLine = id->getScalarSizeInBytes() * width; + + // Buffer to hold one line x tileHeight + bufferSizeInBytes = bytesInLine * tileHeight * bands; + buffer = new unsigned char[bufferSizeInBytes]; + memset(buffer, 0, bufferSizeInBytes); + } + id->unloadTile(buffer, + bufferRect, + OSSIM_BIL); + } + ++tileNumber; + } + + // Get the number of lines to write from the buffer. + ossim_uint32 linesToWrite = + min(tileHeight, + static_cast<ossim_uint32>(theAreaOfInterest.lr().y - + bufferRect.ul().y + 1)); + + // Write the buffer out to disk. + ossim_uint8* buf = buffer; + for (ossim_uint32 ii=0; ((ii<linesToWrite)&(!needsAborting())); ++ii) + { + for (ossim_uint32 band = 0; + ((band < bands)&&(!needsAborting())); + ++band) + { + wroteSomethingOut = true; + if(endian.getSystemEndianType() != theOutputByteOrder) + { + endian.swap(scalarType, + buf, + bytesInLine/ossimGetScalarSizeInBytes(scalarType)); + } + theFileStream.write((char*)buf, bytesInLine); + if (!theFileStream) + { + ossimNotify(ossimNotifyLevel_FATAL) + << MODULE << " ERROR:" + << "Error returned writing line!" << std::endl; + setErrorStatus(); + if(buffer) + { + // Free the memory. + delete [] buffer; + } + return false; + } + + buf += bytesInLine; + } + + } // End of loop to write lines from buffer to tiff file. + + double tile = tileNumber; + double numTiles = numberOfTiles; + setPercentComplete(tile / numTiles * 100); + + if(needsAborting()) + { + setPercentComplete(100.0); + } + + } // End of loop in the line (height) direction. + + if(buffer) + { + // Free the memory. + delete [] buffer; + } + + if (traceDebug()) CLOG << " Exited." << std::endl; + + return wroteSomethingOut; +} + +bool ossimGeneralRasterWriter::writeToBsq() +{ + ossimEndian endian; + static const char* const MODULE = "ossimGeneralRasterWriter::writeToBsq"; + + if (traceDebug()) CLOG << " Entered." << std::endl; + + //*** + // Get an arbitrary tile just to get the size in bytes! + // This should be changed later... An ossimImageSourceInterface should know + // this. + //*** + ossimRefPtr<ossimImageData> id; + + // Start the sequence at the first tile. + theInputConnection->setToStartOfSequence(); + + ossim_uint32 bands = theInputConnection->getNumberOfOutputBands(); + ossim_uint32 tilesWide = theInputConnection->getNumberOfTilesHorizontal(); + ossim_uint32 tilesHigh = theInputConnection->getNumberOfTilesVertical(); + ossim_uint32 tileHeight = theInputConnection->getTileHeight(); + ossim_uint32 numberOfTiles = theInputConnection->getNumberOfTiles(); + ossim_uint32 width = theAreaOfInterest.width(); + ossim_uint32 height = theAreaOfInterest.height(); + + ossim_uint32 bytesInLine = 0; + ossim_uint32 buf_band_offset = 0; + + // Use the system "streampos" typedef for future 64 bit seeks (long long). + streampos file_band_offset = 0; + + //*** + // Buffer to hold one line x tileHeight + //*** + ossim_uint32 bufferSizeInBytes = 0; + unsigned char* buffer = NULL; + + theMinPerBand.clear(); + theMaxPerBand.clear(); + + int tileNumber = 0; + bool wroteSomethingOut = false; + ossimScalarType scalarType = theInputConnection->getOutputScalarType(); + for(ossim_uint32 i = 0; ((i < tilesHigh)&&(!needsAborting())); ++i) + { + if(buffer) + { + // Clear the buffer. + memset(buffer, 0, bufferSizeInBytes); + } + + ossimIrect bufferRect(theAreaOfInterest.ul().x, + theAreaOfInterest.ul().y + i*tileHeight, + theAreaOfInterest.ul().x + (width - 1), + theAreaOfInterest.ul().y + i * + tileHeight + (tileHeight - 1)); + + // Tile loop in the sample (width) direction. + for(ossim_uint32 j = 0; ((j < tilesWide)&&(!needsAborting())); ++j) + { + // Get the tile and copy it to the buffer. + id = theInputConnection->getNextTile(); + if(id.valid()) + { + id->computeMinMaxPix(theMinPerBand, theMaxPerBand); + if(!buffer) + { + bytesInLine = id->getScalarSizeInBytes() * width; + buf_band_offset = bytesInLine * tileHeight; + file_band_offset = height * bytesInLine; + bufferSizeInBytes = bytesInLine * tileHeight * bands; + buffer = new unsigned char[bufferSizeInBytes]; + memset(buffer, 0, bufferSizeInBytes); + } + id->unloadTile(buffer, + bufferRect, + OSSIM_BSQ); + } + ++tileNumber; + } + + // Get the number of lines to write from the buffer. + ossim_uint32 linesToWrite = + min(tileHeight, + static_cast<ossim_uint32>(theAreaOfInterest.lr().y - + bufferRect.ul().y + 1)); + + // Write the buffer out to disk. + ossim_uint32 start_line = + static_cast<ossim_uint32>(bufferRect.ul().y - + theAreaOfInterest.ul().y); + for (ossim_uint32 band = 0; ((band < bands)&&(!needsAborting())); ++band) + { + ossim_uint8* buf = buffer; + buf += buf_band_offset * band; + + // Put the file pointer in the right spot. + streampos pos = file_band_offset * band + start_line * bytesInLine; + theFileStream.seekp(pos, ios::beg); + if (!theFileStream) + { + ossimNotify(ossimNotifyLevel_FATAL) << MODULE << " ERROR:" + << "Error returned seeking to image data position!" << std::endl; + setErrorStatus(); + return false; + } + + for (ossim_uint32 ii=0; ((ii<linesToWrite)&&(!needsAborting())); ++ii) + { + wroteSomethingOut = true; + if(endian.getSystemEndianType() != theOutputByteOrder) + { + endian.swap(scalarType, + buf, + bytesInLine/ossimGetScalarSizeInBytes(scalarType)); + } + + theFileStream.write((char*)buf, bytesInLine); + + if (!theFileStream) + { + ossimNotify(ossimNotifyLevel_FATAL) << MODULE << " ERROR:" + << "Error returned writing line!" << std::endl; + setErrorStatus(); + return false; + } + + buf += bytesInLine; + } + + } // End of loop to write lines from buffer to tiff file. + + double tile = tileNumber; + double numTiles = numberOfTiles; + setPercentComplete(tile / numTiles * 100); + + if(needsAborting()) + { + setPercentComplete(100.0); + } + + } // End of loop in the line (height) direction. + + // Free the memory. + delete [] buffer; + + if (traceDebug()) CLOG << " Exited." << std::endl; + + return wroteSomethingOut; +} + +bool ossimGeneralRasterWriter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + ossimKeywordNames::BYTE_ORDER_KW, + ((theOutputByteOrder==OSSIM_LITTLE_ENDIAN)?"little_endian":"big_endian"), + true); + return ossimImageFileWriter::saveState(kwl, + prefix); +} + +bool ossimGeneralRasterWriter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* value; + + value = kwl.find(prefix, ossimKeywordNames::FILENAME_KW); + if(value) + { + setFilename(ossimFilename(value)); + } + + value = kwl.find(prefix, ossimKeywordNames::INPUT_RR_LEVEL_KW); + if(value) + { + theRlevel = atoi(value); + } + + if(ossimImageFileWriter::loadState(kwl, prefix)) + { + if( (theOutputImageType!="general_raster_bip") && + (theOutputImageType!="general_raster_bil") && + (theOutputImageType!="general_raster_bsq") && + (theOutputImageType!="general_raster_bip_envi") && + (theOutputImageType!="general_raster_bil_envi") && + (theOutputImageType!="general_raster_bsq_envi") + ) + { + theOutputImageType = "general_raster_bsq"; + } + } + else + { + return false; + } + const char* outputByteOrder = kwl.find(prefix, ossimKeywordNames::BYTE_ORDER_KW); + theOutputByteOrder = ossimEndian().getSystemEndianType(); + if(outputByteOrder) + { + ossimString byteOrder = outputByteOrder; + byteOrder = byteOrder.downcase(); + if(byteOrder.contains("little")) + { + theOutputByteOrder = OSSIM_LITTLE_ENDIAN; + } + else if(byteOrder.contains("big")) + { + theOutputByteOrder = OSSIM_BIG_ENDIAN; + } + } + + return true; +} + +void ossimGeneralRasterWriter::writeHeader() const +{ + static const char MODULE[] = "ossimGeneralRasterWriter::writeHeader"; + + if (traceDebug()) CLOG << " Entered..." << std::endl; + + // Make a header file name from the image file. + ossimFilename headerFile = theFilename; + headerFile.setExtension(".omd"); // ossim meta data + + std::ofstream os; + os.open(headerFile.c_str(), ios::out); + if (!os) + { + ossimNotify(ossimNotifyLevel_FATAL) << MODULE << " Error:\n" + << "Could not open: " << headerFile << std::endl; + return; + } + + ossimString interleaveType = getInterleaveString(); + + ossimString scalar = + ossimScalarTypeLut::instance()->getEntryString(theInputConnection-> + getOutputScalarType()); + + os << "// *** ossim meta data general raster header file ***\n" + << ossimKeywordNames::IMAGE_FILE_KW << ": " + << theFilename.file().c_str() << "\n" + << ossimKeywordNames::IMAGE_TYPE_KW << ": " + << getOutputImageTypeString() << "\n" + << ossimKeywordNames::INTERLEAVE_TYPE_KW << ": " + << interleaveType.c_str() << "\n" + << ossimKeywordNames::NUMBER_BANDS_KW << ": " + << theInputConnection->getNumberOfOutputBands() << "\n" + << ossimKeywordNames::NUMBER_LINES_KW << ": " + << (theAreaOfInterest.lr().y - theAreaOfInterest.ul().y + 1) << "\n" + << ossimKeywordNames::NUMBER_SAMPLES_KW << ": " + << (theAreaOfInterest.lr().x - theAreaOfInterest.ul().x + 1) << "\n" + << ossimKeywordNames::SCALAR_TYPE_KW << ": " + << scalar.c_str() << "\n" + << ossimKeywordNames::BYTE_ORDER_KW <<": " + << ((theOutputByteOrder==OSSIM_BIG_ENDIAN)?"big_endian":"little_endian") + << "\n" + << std::endl; + + // Output the null/min/max for each band. + os << "\n// NOTE: Bands are one based, band1 is the first band." + << std::endl; + + for (ossim_uint32 i=0; i<theInputConnection->getNumberOfOutputBands(); ++i) + { + ossimString prefix = ossimKeywordNames::BAND_KW + + ossimString::toString(i+1) + "."; + + ossimString null_pix = ossimString::toString(theInputConnection-> + getNullPixelValue(i)); + ossimString min_pix; + ossimString max_pix; + + if(!theMinPerBand.size()||!theMaxPerBand.size()) + { + min_pix = ossimString::toString(theInputConnection-> + getMinPixelValue(i)); + max_pix = ossimString::toString(theInputConnection-> + getMaxPixelValue(i)); + } + else + { + min_pix = ossimString::toString(theMinPerBand[i]); + max_pix = ossimString::toString(theMaxPerBand[i]); + } + + os << prefix.c_str() << ossimKeywordNames::NULL_VALUE_KW << ": " + << null_pix.c_str() << "\n" + << prefix << ossimKeywordNames::MIN_VALUE_KW << ": " + << min_pix.c_str() << "\n" + << prefix << ossimKeywordNames::MAX_VALUE_KW << ": " + << max_pix.c_str() << std::endl; + } + + os.close(); + + if (traceDebug()) CLOG << " Exited..." << endl; +} + +void ossimGeneralRasterWriter::writeEnviHeader() const +{ + static const char MODULE[] = "ossimGeneralRasterWriter::writeEnviHeader"; + + if (traceDebug()) CLOG << " Entered..." << endl; + + if (!theInputConnection) + { + return; + } + + // Make a header file name from the image file. + ossimFilename headerFile = theFilename; + headerFile.setExtension(".hdr"); // ossim meta data + + ossimString interleaveType = getInterleaveString(); + ossimKeywordlist kwl; + kwl.add(ossimKeywordNames::INTERLEAVE_TYPE_KW, interleaveType.c_str()); + + ossimEnviHeaderFileWriter hdr; + hdr.connectMyInputTo(0, theInputConnection); + hdr.initialize(); + hdr.setFilename(headerFile); + hdr.loadState(kwl); + hdr.setAreaOfInterest(theAreaOfInterest); + hdr.execute(); + + if (traceDebug()) CLOG << " Exited..." << endl; +} + +void ossimGeneralRasterWriter::getImageTypeList(std::vector<ossimString>& imageTypeList)const +{ + imageTypeList.push_back(ossimString("general_raster_bip")); + imageTypeList.push_back(ossimString("general_raster_bil")); + imageTypeList.push_back(ossimString("general_raster_bsq")); + imageTypeList.push_back(ossimString("general_raster_bip_envi")); + imageTypeList.push_back(ossimString("general_raster_bil_envi")); + imageTypeList.push_back(ossimString("general_raster_bsq_envi")); +} + +ossimString ossimGeneralRasterWriter::getInterleaveString() const +{ + ossimString interleaveType = "unknown"; + if ( (theOutputImageType == "general_raster_bip") || + (theOutputImageType == "general_raster_bip_envi") ) + { + interleaveType = "bip"; + } + else if ( (theOutputImageType == "general_raster_bil") || + (theOutputImageType == "general_raster_bil_envi") ) + { + interleaveType = "bil"; + } + else if ( (theOutputImageType == "general_raster_bsq") || + (theOutputImageType == "general_raster_bsq") ) + { + interleaveType = "bsq"; + } + return interleaveType; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/general_raster/ossimGeneralRasterWriter.h b/Utilities/OSSIM/ossim_core/imaging/formats/general_raster/ossimGeneralRasterWriter.h new file mode 100644 index 0000000000..089c43db28 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/general_raster/ossimGeneralRasterWriter.h @@ -0,0 +1,120 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: David Burken +// +// Description: +// +// Contains class declaration for ossimGeneralRasterWriter. +// +//******************************************************************* +// $Id: ossimGeneralRasterWriter.h,v 1.27 2006/01/06 16:46:46 dburken Exp $ + +#ifndef ossimGeneralRasterWriter_HEADER +#define ossimGeneralRasterWriter_HEADER + +#include "imaging/formats/ossimImageFileWriter.h" +#include "base/data_types/ossimIrect.h" +#include "base/data_types/ossimFilename.h" +#include "base/data_types/ossimKeywordlist.h" +#include "base/data_types/ossimKeyword.h" + +class ossimGeneralRasterWriter : public ossimImageFileWriter +{ +public: + ossimGeneralRasterWriter(); + ossimGeneralRasterWriter(ossimImageSource* inputSource, + const ossimFilename& file=ossimFilename("")); + virtual ~ossimGeneralRasterWriter(); + + /** + * void getImageTypeList(std::vector<ossimString>& imageTypeList)const + * + * Appends this writer image types to list "imageTypeList". + * + * This writer has the following types: + * general_raster_bip + * general_raster_bil + * general_raster_bsq + * + * @param imageTypeList stl::vector<ossimString> list to append to. + */ + virtual void getImageTypeList(std::vector<ossimString>& imageTypeList)const; + + virtual void set_rr_level(ossim_uint32 rr) { theRlevel = rr; } + virtual bool isOpen()const; + virtual bool open(); + virtual void close(); + + /** + * saves the state of the object. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +private: + virtual bool writeFile(); + + /** + * Writes image data to output file in BIP(Band Interleaved by Pixel) + * format. + * @return true on success, false on error. + */ + bool writeToBip(); + + /** + * Writes image data to output file in BIL(Band Interleaved by Line) + * format. + * @return true on success, false on error. + */ + bool writeToBil(); + + /** + * Writes image data to output file in BSQ(Band Sequential) format. + * @return true on success, false on error. + */ + bool writeToBsq(); + + /** + * Writes an ossim header file which can be used to load file in ossim. + * Returns true on success, false on error. + */ + void writeHeader() const; + + /** + * Writes an envi header file which can be used to load file in envi. + * If the output image file is "foo.ras" then the ossim header file will + * be "foo.hdr". + */ + void writeEnviHeader() const; + + /** + * @return The interleave as a string of either: bil, bip, or bsq + */ + ossimString getInterleaveString() const; + + + std::ofstream theFileStream; + bool theOverviewFlag; + ossim_uint32 theRlevel; + ossimByteOrder theOutputByteOrder; + + /** + * Populated while writting the data + */ + std::vector<double> theMinPerBand; + std::vector<double> theMaxPerBand; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/jpeg/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/formats/jpeg/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/jpeg/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/jpeg/ossimJpegTileSource.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/jpeg/ossimJpegTileSource.cpp new file mode 100644 index 0000000000..532f597f47 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/jpeg/ossimJpegTileSource.cpp @@ -0,0 +1,606 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class definition for JpegTileSource. +//******************************************************************* +// $Id: ossimJpegTileSource.cpp,v 1.28 2005/10/20 19:58:37 gpotts Exp $ + +#include <imaging/formats/jpeg/ossimJpegTileSource.h> +#include <imaging/formats/tiff/ossimTiffTileSource.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <base/common/ossimConstants.h> +#include <base/data_types/ossimIpt.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimIrect.h> +#include <base/data_types/ossimFilename.h> +#include <base/data_types/ossimKeywordlist.h> +#include <imaging/ossimU8ImageData.h> +#include <base/common/ossimTrace.h> +#include <base/context/ossimNotifyContext.h> + + +RTTI_DEF1_INST(ossimJpegTileSource, "ossimJpegTileSource", ossimImageHandler) + +static ossimTrace traceDebug("ossimJpegTileSource:degug"); + +//******************************************************************* +// Public Constructor: +//******************************************************************* +ossimJpegTileSource::ossimJpegTileSource() + : + ossimImageHandler(), + theTile(NULL), + theCacheTile(NULL), + theLineBuffer(NULL), + theFilePtr(0), + theBufferRect(0, 0, 0, 0), + theImageRect(0, 0, 0, 0), + theNumberOfBands(0), + theCacheSize (0), + theCinfo(), + theJerr(), + theCacheId(-1) +{} + +//******************************************************************* +// Public Constructor: +//******************************************************************* +ossimJpegTileSource::ossimJpegTileSource(const ossimKeywordlist& kwl, + const char* prefix) + : + ossimImageHandler(), + theTile(NULL), + theCacheTile(NULL), + theLineBuffer(NULL), + theFilePtr(0), + theBufferRect(0, 0, 0, 0), + theImageRect(0, 0, 0, 0), + theNumberOfBands(0), + theCacheSize (0), + theCinfo(), + theJerr(), + theCacheId(-1) +{ + if (loadState(kwl, prefix) == false) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + } +} + +//******************************************************************* +// Public Constructor: +//******************************************************************* +ossimJpegTileSource::ossimJpegTileSource(const char* jpeg_file) + : + ossimImageHandler(), + theTile(NULL), + theCacheTile(NULL), + theLineBuffer(NULL), + theFilePtr(0), + theBufferRect(0, 0, 0, 0), + theImageRect(0, 0, 0, 0), + theNumberOfBands(0), + theCacheSize(0), + theCinfo(), + theJerr(), + theCacheId(-1) +{ + static const char MODULE[] + = "ossimJpegTileSource::ossimJpegTileSource"; + + if (!open()) + { + + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_WARN) + << MODULE + << "\nCannot open: " << jpeg_file + << endl; + } +} + +//******************************************************************* +// Destructor: +//******************************************************************* +ossimJpegTileSource::~ossimJpegTileSource() +{ + destroy(); +} + +void ossimJpegTileSource::destroy() +{ + ossimAppFixedTileCache::instance()->deleteCache(theCacheId); + + theTile = NULL; + theCacheTile = NULL; + + if (theLineBuffer) + { + delete [] theLineBuffer; + theLineBuffer = NULL; + } + if (theFilePtr) + { + fclose(theFilePtr); + theFilePtr = NULL; + } + jpeg_destroy_decompress( &theCinfo ); +} + +void ossimJpegTileSource::allocate() +{ + if(theLineBuffer) + { + delete [] theLineBuffer; + theLineBuffer = 0; + } + // Make the cache tile the height of one tile by the image width. + ossimGetDefaultTileSize(theCacheSize); + theCacheSize.x = theImageRect.width(); + + ossimAppFixedTileCache::instance()->deleteCache(theCacheId); + theCacheId = ossimAppFixedTileCache::instance()->newTileCache(theImageRect, theCacheSize); + + theTile = ossimImageDataFactory::instance()->create(this, this); + theCacheTile = (ossimImageData*)theTile->dup(); + theTile->initialize(); + + ossimIrect cache_rect(theImageRect.ul().x, + theImageRect.ul().y, + theImageRect.ul().x + (theCacheSize.x-1), + theImageRect.ul().y + (theCacheSize.y-1)); + + theCacheTile->setImageRectangle(cache_rect); + theCacheTile->initialize(); + + theLineBuffer = new ossim_uint8[theImageRect.width() * theNumberOfBands]; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimJpegTileSource::allocate DEBUG:" + << "\ncache tile size: " << theCacheSize + << "\nimage width: " << theImageRect.width() + << "\nimage height: " << theImageRect.height() + << "\nnumber of bands: " << theNumberOfBands + << endl; + } +} + +ossimRefPtr<ossimImageData> ossimJpegTileSource::getTile( + const ossimIrect& tile_rect, ossim_uint32 resLevel) +{ + if(!isSourceEnabled()||!isOpen()||!isValidRLevel(resLevel)) + { + return ossimRefPtr<ossimImageData>(); + } + + if (theOverview) + { + if (theOverview->hasR0() || resLevel) + { + return theOverview->getTile(tile_rect, resLevel); + } + } + + if (!theTile.valid()) + { + return ossimRefPtr<ossimImageData>(); + } + + theTile->setImageRectangle(tile_rect); + if (getImageRectangle(0).intersects(tile_rect)) + { + // Make a clip rect. + ossimIrect clip_rect = tile_rect.clipToRect(getImageRectangle(0)); + + fillTile(clip_rect); + } + else + { + // No point in requested tile within the image rectangle. + return ossimRefPtr<ossimImageData>(); + } + + return theTile; +} + +void ossimJpegTileSource::fillTile(const ossimIrect& clip_rect) +{ + if (!theTile || !theFilePtr) return; + + ossimIrect buffer_rect = clip_rect; + buffer_rect.stretchToTileBoundary(theCacheSize); + buffer_rect.set_ulx(0); + buffer_rect.set_lrx(getImageRectangle(0).lr().x); + + // Check for a partial tile. + if ( ! theTile->getImageRectangle().completely_within(buffer_rect) ) + { + theTile->makeBlank(); + } + + ossim_int32 number_of_cache_tiles = buffer_rect.height()/theCacheSize.y; + +#if 0 + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "tiles high: " << number_of_cache_tiles + << endl; + } +#endif + + ossimIpt origin = buffer_rect.ul(); + + for (int tile = 0; tile < number_of_cache_tiles; ++tile) + { + // See if it's in the cache already. + ossimRefPtr<ossimImageData> tempTile; + tempTile = ossimAppFixedTileCache::instance()-> + getTile(theCacheId, origin); + if (tempTile.valid()) + { + theTile->loadTile(tempTile.get()); + } + else + { + // Have to read from the jpeg file. + ossim_uint32 start_line = static_cast<ossim_uint32>(origin.y); + ossim_uint32 stop_line = + static_cast<ossim_uint32>( min(origin.y+theCacheSize.y-1, + getImageRectangle().lr().y) ); + ossimIrect cache_rect(origin.x, + origin.y, + origin.x+theCacheSize.x-1, + origin.y+theCacheSize.y-1); + + theCacheTile->setImageRectangle(cache_rect); + + if ( !theCacheTile->getImageRectangle(). + completely_within(getImageRectangle()) ) + { + theCacheTile->makeBlank(); + } + + if (start_line < theCinfo.output_scanline) + { + // Must restart the compression process again. + restart(); + } + + // Get pointers to the cache tile buffers. + JSAMPROW jbuf[1]; +// ossim_uint8* buf[3] = new ossim_uint8*[theNumberOfBands]; + ossim_uint8* buf[3]; + ossim_uint32 band = 0; + for (band = 0; band < theNumberOfBands; ++band) + { + buf[band] = theCacheTile->getUcharBuf(band); + } + + const ossim_uint32 SAMPLES = getNumberOfSamples(); + jbuf[0] = (JSAMPROW) theLineBuffer; + + // Gobble any not needed lines. + while (theCinfo.output_scanline < start_line) + { + jpeg_read_scanlines(&theCinfo, jbuf, 1); + } + + while (theCinfo.output_scanline <= stop_line) + { + // Read a line from the jpeg file. + jpeg_read_scanlines(&theCinfo, jbuf, 1); + + //--- + // Copy the line which if band interleaved by pixel the the band + // separate buffers. + //--- + ossim_uint32 index = 0; + for (ossim_uint32 sample = 0; sample < SAMPLES; ++sample) + { + for (band = 0; band < theNumberOfBands; ++band) + { + buf[band][sample] = theLineBuffer[index]; + ++index; + } + } + + for (band = 0; band < theNumberOfBands; ++band) + { + buf[band] += SAMPLES; + } + } + theCacheTile->validate(); + + theTile->loadTile(theCacheTile.get()); + + // Add it to the cache for the next time. + ossimAppFixedTileCache::instance()->addTile(theCacheId, theCacheTile); + + +// delete[] buf; + + } // End of reading for jpeg file. + + origin.y += theCacheSize.y; + + } // for (int tile = 0; tile < number_of_cache_tiles; ++tile) + + theTile->validate(); +} + +//******************************************************************* +// Public Method: +//******************************************************************* +ossimIrect +ossimJpegTileSource::getImageRectangle(ossim_uint32 reduced_res_level) const +{ + return ossimIrect(0, + 0, + getNumberOfSamples(reduced_res_level) - 1, + getNumberOfLines(reduced_res_level) - 1); +} + +//******************************************************************* +// Public method: +//******************************************************************* +bool ossimJpegTileSource::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + return ossimImageHandler::saveState(kwl, prefix); +} + +//******************************************************************* +// Public method: +//******************************************************************* +bool ossimJpegTileSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + if (ossimImageHandler::loadState(kwl, prefix)) + { + return open(); + } + + return false; +} + + +//******************************************************************* +// Public method: +//******************************************************************* +bool ossimJpegTileSource::open(const ossimFilename& jpeg_file) +{ + theImageFile = jpeg_file; + + return open(); +} + +//******************************************************************* +// Private method: +//******************************************************************* +bool ossimJpegTileSource::open() +{ + static const char MODULE[] = "ossimJpegTileSource::open"; + + // Start with a clean slate. + destroy(); + + // Open Jpeg file. + if((theFilePtr = fopen(theImageFile.c_str(), "rb")) == NULL) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << "\nERROR:\n" + << "Could not open: " << theImageFile.c_str() + << endl; + } + + return false; + } + + //*** + // Verify the file is a jpeg by checking the first two bytes. + //*** + ossim_uint8 c[2]; + fread(c, 2, 1, theFilePtr); + if( c[0] != 0xFF || c[1] != 0xD8 ) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " NOTICE:\n" + << "Not a jpeg file..." << endl; + } + + fclose(theFilePtr); + theFilePtr = NULL; + return false; + } + + rewind(theFilePtr); + + //--- + // Step 1: allocate and initialize JPEG decompression object + // We set up the normal JPEG error routines, then override error_exit. + //--- + theCinfo.err = jpeg_std_error(&theJerr); + + // Initialize the JPEG decompression object. + jpeg_create_decompress(&theCinfo); + + // Specify data source. + jpeg_stdio_src(&theCinfo, theFilePtr); + + // Read the file parameters with jpeg_read_header. + jpeg_read_header(&theCinfo, TRUE); + + jpeg_start_decompress(&theCinfo); + + theNumberOfBands = theCinfo.output_components; + + theImageRect = ossimIrect(0, + 0, + theCinfo.output_width - 1, + theCinfo.output_height - 1); + + theBufferRect.set_lrx(theCinfo.output_width - 1); + + completeOpen(); + + // Allocate memory... + allocate(); + + return true; +} + +//******************************************************************* +// Public method: +//******************************************************************* +ossim_uint32 ossimJpegTileSource::getTileWidth() const +{ + return ( theTile.valid() ? theTile->getWidth() : 0 ); +} + +//******************************************************************* +// Public method: +//******************************************************************* +ossim_uint32 ossimJpegTileSource::getTileHeight() const +{ + return ( theTile.valid() ? theTile->getHeight() : 0 ); +} + +//******************************************************************* +// Public method: +//******************************************************************* +bool ossimJpegTileSource::isValidRLevel(ossim_uint32 reduced_res_level) const +{ + static const char MODULE[] = "ossimJpegTileSource::isValidRLevel"; + + if (reduced_res_level == 0) + { + return true; + } + else if (theOverview) + { + return theOverview->isValidRLevel(reduced_res_level); + } + else + { + cerr << MODULE << " Invalid reduced_res_level: " << reduced_res_level + << "\nHighest available: " << (getNumberOfDecimationLevels() - 1) + << endl; + return false; + } +} + +//******************************************************************* +// Public method: +//******************************************************************* +ossim_uint32 ossimJpegTileSource::getNumberOfLines(ossim_uint32 reduced_res_level) const +{ + if (reduced_res_level == 0) + { + return theImageRect.lr().y - theImageRect.ul().y + 1; + } + else if (theOverview) + { + return theOverview->getNumberOfLines(reduced_res_level); + } + + return 0; +} + +//******************************************************************* +// Public method: +//******************************************************************* +ossim_uint32 ossimJpegTileSource::getNumberOfSamples(ossim_uint32 reduced_res_level) const +{ + if (reduced_res_level == 0) + { + return theImageRect.lr().x - theImageRect.ul().x + 1;; + } + else if (theOverview) + { + return theOverview->getNumberOfSamples(reduced_res_level); + } + + return 0; +} + +ossim_uint32 ossimJpegTileSource::getImageTileWidth() const +{ + return 0; +} + +ossim_uint32 ossimJpegTileSource::getImageTileHeight() const +{ + return 0; +} + +ossimString ossimJpegTileSource::getShortName()const +{ + return ossimString("jpg"); +} + +ossimString ossimJpegTileSource::getLongName()const +{ + return ossimString("jpg reader"); +} + +ossimString ossimJpegTileSource::className()const +{ + return ossimString("ossimJpegTileSource"); +} + +ossim_uint32 ossimJpegTileSource::getNumberOfInputBands() const +{ + return theNumberOfBands; +} + +ossim_uint32 ossimJpegTileSource::getNumberOfOutputBands()const +{ + return getNumberOfInputBands(); +} + +ossimScalarType ossimJpegTileSource::getOutputScalarType() const +{ + return OSSIM_UCHAR; +} + +bool ossimJpegTileSource::isOpen()const +{ + return (theFilePtr != NULL); +} + +void ossimJpegTileSource::restart() +{ + jpeg_abort_decompress( &theCinfo ); + jpeg_destroy_decompress( &theCinfo ); + + // Put the theFilePtr back to the start... + rewind(theFilePtr); + + // Initialize the JPEG decompression object. + jpeg_create_decompress(&theCinfo); + + // Specify data source. + jpeg_stdio_src(&theCinfo, theFilePtr); + + // Read the file parameters with jpeg_read_header. + jpeg_read_header(&theCinfo, TRUE); + + jpeg_start_decompress(&theCinfo); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/jpeg/ossimJpegTileSource.h b/Utilities/OSSIM/ossim_core/imaging/formats/jpeg/ossimJpegTileSource.h new file mode 100644 index 0000000000..04a3a1e9a4 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/jpeg/ossimJpegTileSource.h @@ -0,0 +1,198 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class declaration for JpegTileSource. +// JpegTileSource is derived from ImageHandler which is derived from +// TileSource. +//******************************************************************* +// $Id: ossimJpegTileSource.h,v 1.23 2005/07/25 22:49:06 dburken Exp $ + +#ifndef ossimJpegTileSource_HEADER +#define ossimJpegTileSource_HEADER + +#include <cstdio> + +//--- +// Using windows .NET compiler there is a conflict in the libjpeg with INT32 +// in the file jmorecfg.h. Defining XMD_H fixes this. +//--- +#if defined(__BORLANDC__) +#include <iostream> +using std::size_t; +#include <stdlib.h> +#include <stdio.h> +#endif +extern "C" +{ +#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__BORLANDC__) +# ifndef XMD_H +# define XMD_H +# endif +#endif +#include <jpeglib.h> +#include <setjmp.h> +} + +#include <imaging/formats/ossimImageHandler.h> +#include <imaging/cache/ossimAppFixedTileCache.h> + +class ossimImageData; + +class OSSIM_DLL ossimJpegTileSource : public ossimImageHandler +{ +public: + + ossimJpegTileSource(); + + ossimJpegTileSource(const ossimKeywordlist& kwl, + const char* prefix=0); + + ossimJpegTileSource(const char* jpeg_file); + + virtual ~ossimJpegTileSource(); + + virtual ossimString getShortName() const; + virtual ossimString getLongName() const; + virtual ossimString className() const; + + /** + * Returns a pointer to a tile given an origin representing the upper + * left corner of the tile to grab from the image. + * Satisfies pure virtual from TileSource class. + */ + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tile_rect, + ossim_uint32 resLevel=0); + + /** + * Returns the number of bands in the image. + * Satisfies pure virtual from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfInputBands() const; + + /** + * Returns the number of bands in a tile returned from this TileSource. + * Note: we are supporting sources that can have multiple data objects. + * If you want to know the scalar type of an object you can pass in the + */ + virtual ossim_uint32 getNumberOfOutputBands()const; + + /** + * Returns the number of lines in the image. + * Satisfies pure virtual from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfLines(ossim_uint32 reduced_res_level = 0) const; + + /** + * Returns the number of samples in the image. + * Satisfies pure virtual from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfSamples(ossim_uint32 reduced_res_level = 0) const; + + /** + * Returns the zero based image rectangle for the reduced resolution data + * set (rrds) passed in. Note that rrds 0 is the highest resolution rrds. + */ + virtual ossimIrect getImageRectangle(ossim_uint32 reduced_res_level = 0) const; + + /** + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * Returns the output pixel type of the tile source. + */ + virtual ossimScalarType getOutputScalarType() const; + + /** + * Returns the width of the output tile. + */ + virtual ossim_uint32 getTileWidth() const; + + /** + * Returns the height of the output tile. + */ + virtual ossim_uint32 getTileHeight() const; + + /** + * Returns the tile width of the image or 0 if the image is not tiled. + * Note: this is not the same as the ossimImageSource::getTileWidth which + * returns the output tile width which can be different than the internal + * image tile width on disk. + */ + virtual ossim_uint32 getImageTileWidth() const; + + /** + * Returns the tile width of the image or 0 if the image is not tiled. + * Note: this is not the same as the ossimImageSource::getTileWidth which + * returns the output tile width which can be different than the internal + * image tile width on disk. + */ + virtual ossim_uint32 getImageTileHeight() const; + + bool isValidRLevel(ossim_uint32 reduced_res_level) const; + + + bool isOpen()const; + /** + * Returns true if the image_file can be opened and is a valid tiff file. + */ + bool open(const ossimFilename& jpeg_file); + +protected: + /** + * Returns true if no errors initializing object. + * + * Notes: + * - Callers of this method must ensure "theTiffPtr" data member + * is initialized. + * - This method was added to consolidate object initialization code + * between constructor and public open method. + */ + virtual bool open(); + + void allocate(); + void destroy(); + void restart(); + + /** + * @note this method assumes that setImageRectangle has been called on + * theTile. + */ + void fillTile(const ossimIrect& clip_rect); + + ossimRefPtr<ossimImageData> theTile; + ossimRefPtr<ossimImageData> theCacheTile; + ossim_uint8* theLineBuffer; + FILE* theFilePtr; + ossimIrect theBufferRect; + ossimIrect theImageRect; + ossim_uint32 theNumberOfBands; + ossimIpt theCacheSize; + + struct jpeg_decompress_struct theCinfo; + struct jpeg_error_mgr theJerr; + + ossimAppFixedTileCache::ossimAppFixedCacheId theCacheId; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/jpeg/ossimJpegWriter.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/jpeg/ossimJpegWriter.cpp new file mode 100644 index 0000000000..d833f13dfa --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/jpeg/ossimJpegWriter.cpp @@ -0,0 +1,469 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: David Burken +// +//******************************************************************* +// $Id: ossimJpegWriter.cpp,v 1.51 2006/01/06 16:46:46 dburken Exp $ + +#include <cstdio> + +//--- +// Using windows .NET compiler there is a conflict in the libjpeg with INT32 +// in the file jmorecfg.h. Defining XMD_H fixes this. +extern "C" +{ +#if defined(_MSC_VER) || defined(__MINGW32__) +# ifndef XMD_H +# define XMD_H +# endif +#endif +#include <jpeglib.h> +} + +#include <imaging/formats/jpeg/ossimJpegWriter.h> +#include <base/common/ossimKeywordNames.h> +#include <base/common/ossimTrace.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/misc/lookup_tables/ossimScalarTypeLut.h> +#include <base/property/ossimNumericProperty.h> +#include <projections/map_projections/ossimMapProjection.h> +#include <imaging/ossimImageData.h> +#include <imaging/ossimImageSource.h> +#include <imaging/tile_sources/ossimScalarRemapper.h> + +RTTI_DEF1_INST(ossimJpegWriter, "ossimJpegWriter", ossimImageFileWriter) + +static const char DEFAULT_FILE_NAME[] = "output.jpg"; +static const ossim_int32 DEFAULT_JPEG_QUALITY = 75; +static ossimTrace traceDebug("ossimJpegWriter:debug"); + + +//******************************************************************* +// Constructor: +//******************************************************************* +ossimJpegWriter::ossimJpegWriter() + : ossimImageFileWriter(), + theQuality(DEFAULT_JPEG_QUALITY), + theRlevel(0), + theOutputFilePtr(NULL) +{ + // Since there is no internal geometry set the flag to write out one. + setWriteExternalGeometryFlag(true); +} + +ossimJpegWriter::ossimJpegWriter(ossimImageSource* inputSource, + const ossimFilename& filename) + :ossimImageFileWriter(filename, inputSource), + theQuality(DEFAULT_JPEG_QUALITY), + theRlevel(0), + theOutputFilePtr(NULL) +{ + // Since there is no internal geometry set the flag to write out one. + setWriteExternalGeometryFlag(true); +} +//******************************************************************* +// Destructor +//******************************************************************* +ossimJpegWriter::~ossimJpegWriter() +{ + close(); +} + +bool ossimJpegWriter::writeFile() +{ + static const char MODULE[] = "ossimJpegWriter::writeFile"; + + if( getErrorStatus() != ossimErrorCodes::OSSIM_OK ) + { + return false; + } + + bool needToDeleteInput = false; + + if(theInputConnection->getOutputScalarType() != OSSIM_UINT8) + { + ossimImageSource* inputSource=new ossimScalarRemapper; + + inputSource->connectMyInputTo(0, theInputConnection->getInput(0)); + theInputConnection->connectMyInputTo(0, inputSource); + theInputConnection->initialize(); + needToDeleteInput = true; + } + + if(theInputConnection->isMaster()) + { + if (!isOpen()) + { + open(); + } + + if (!theOutputFilePtr) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR:" + << "\nCannot open: " << theFilename.c_str() + << "\nReturning from method." << endl; + + return false; + } + + if (traceDebug()) + { + CLOG << " DEBUG:" + << "\nOutput Rect: " << theAreaOfInterest << endl; + } + + // Get the number of bands. Must be one or three for this writer. + ossim_int32 components = theInputConnection->getNumberOfOutputBands(); + + if (components != 1 && components != 3) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Range Error:" + << "\nInvalid number of input bands! Must be one or three." + << "\nInput bands = " << components + << "\nReturning from method." << endl; + + return false; + } + + // + // There should be a check to see if "theRlevel" is out of range. + // + // if (theRlevel < theImageSource + + ossim_int32 image_height + = theAreaOfInterest.lr().y - theAreaOfInterest.ul().y + 1; + ossim_int32 image_width + = theAreaOfInterest.lr().x - theAreaOfInterest.ul().x + 1; + ossim_int32 tileWidth = theInputConnection->getTileWidth(); + ossim_int32 tileHeight = theInputConnection->getTileHeight(); + + // Allocate a buffer to hold a row of tiles. + ossim_int32 buf_size = tileHeight*image_width*components; + + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nbuf_size: " << buf_size + << endl; + } + + ossim_uint8* buf = new ossim_uint8[buf_size]; + ossimImageData* blankTile = new ossimImageData(NULL, + OSSIM_UINT8, + components, + tileWidth, + tileHeight); + blankTile->initialize(); + // + // Stuff needed for the jpeg library. + // Taken from "example.c" file of the "jpeg-6b" package. + // + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + JSAMPROW row_pointer[1]; // pointer to JSAMPLE row[s] + + // physical row width in image buffer + int row_stride = image_width * components; + + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + jpeg_stdio_dest(&cinfo, theOutputFilePtr); + cinfo.image_width = image_width; // image width and height, in pixels + cinfo.image_height = image_height; + cinfo.input_components = components; // # of color components per pixel + + // colorspace of input image + if (components == 3) + { + cinfo.in_color_space = JCS_RGB; + } + else + { + cinfo.in_color_space = JCS_GRAYSCALE; + } + + jpeg_set_defaults(&cinfo); + jpeg_set_quality(&cinfo, theQuality, TRUE); //limit to baseline-JPEG values + jpeg_start_compress(&cinfo, TRUE); + + theInputConnection->setAreaOfInterest(theAreaOfInterest); + theInputConnection->setToStartOfSequence(); + long maxY = (long)theInputConnection->getNumberOfTilesVertical(); + long maxX = (long)theInputConnection->getNumberOfTilesHorizontal(); + + ossimProcessInterface::ossimProcessStatus processStatus = getProcessStatus(); + + double tileCount = 0.0; + double totalTiles = theInputConnection->getNumberOfTiles(); + // + // Ok the jpeg stuff should be set. Loop through and grab a row of tiles + // and copy to the buffer. Then write the buffer to the jpeg file. + // Get the next row... until finished. + // + for (ossim_int32 i=0; + ((i<maxY)&& + (!needsAborting())); + ++i) + { + ossimIrect buf_rect = theAreaOfInterest; + buf_rect.set_uly(theAreaOfInterest.ul().y+i*tileHeight); + buf_rect.set_lry(buf_rect.ul().y + tileHeight - 1); + + for (ossim_int32 j=0; + ((j<maxX)&& + (!needsAborting())); + ++j) + { + // Grab the tile. + const ossimRefPtr<ossimImageData> t = + theInputConnection->getNextTile(); + + if ( t.valid() ) + { + if (t->getDataObjectStatus() != OSSIM_NULL) + { + // Copy the tile to the buffer. + t->unloadTile(buf, buf_rect, OSSIM_BIP); + } + else + { + blankTile->setOrigin(t->getOrigin()); + blankTile->unloadTile(buf, buf_rect, OSSIM_BIP); + } + } + ++tileCount; + setPercentComplete((100.0*(tileCount/totalTiles))); + + } // End of loop through tiles in the x direction. + + // Copy the buffer to the jpeg file. + ossim_int32 lines_to_copy = + min( (buf_rect.lr().y-buf_rect.ul().y+1), + (theAreaOfInterest.lr().y-buf_rect.ul().y+1) ); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE + << "buf_rect: " << buf_rect + << "lines_to_copy: " << lines_to_copy << endl; + } + + processStatus = getProcessStatus(); + if(!needsAborting()) + { + // Now copy the buffer that should be full to the jpeg file. + ossim_int32 buf_offset = 0; + for (ossim_int32 line=0; line<lines_to_copy; ++line) + { + row_pointer[0] = &buf[buf_offset]; + jpeg_write_scanlines(&cinfo, row_pointer, 1); + buf_offset += row_stride; + } + } + + } // End of loop through tiles in the y direction. + + // Free memory. + if(!needsAborting()) + { + jpeg_finish_compress(&cinfo); + } + + fclose(theOutputFilePtr); + theOutputFilePtr = NULL; + + jpeg_destroy_compress(&cinfo); + + delete [] buf; + delete blankTile; + blankTile = NULL; + } + else + { + theInputConnection->slaveProcessTiles(); + } + if(needToDeleteInput) + { + ossimConnectableObject* obj = theInputConnection->getInput(0); + if(obj) + { + theInputConnection->connectMyInputTo(0, obj->getInput(0)); + delete obj; + obj = NULL; + } + } + + return true; +} + +bool ossimJpegWriter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + return ossimImageFileWriter::saveState(kwl, prefix); +} + +bool ossimJpegWriter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* value; + + value = kwl.find(prefix, ossimKeywordNames::FILENAME_KW); + if(value) + { + setFilename(value); + } + + value = kwl.find(prefix, ossimKeywordNames::COMPRESSION_QUALITY_KW); + if(value) + { + setQuality(atoi(value)); + } + + value = kwl.find(prefix, ossimKeywordNames::OVERVIEW_FILE_KW); + if(value) + { + theOverviewFlag = (atoi(value)) ? true : false; + } + + value = kwl.find(prefix, ossimKeywordNames::REDUCED_RES_LEVEL_KW); + if(value) + { + theRlevel = atoi(value); + } + theOutputImageType = "jpeg"; + + return ossimImageFileWriter::loadState(kwl, prefix); +} + +void ossimJpegWriter::setQuality(ossim_int32 quality) +{ + static const char MODULE[] = "ossimJpegWriter::setQuality"; + + // Range 1 to 100 with 100 being best. + if (quality > 0 && quality < 101) + { + theQuality = quality; + } + else + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " DEBUG:" + << "\nquality out of range: " << quality + << "\nquality has been set to default: " + << DEFAULT_JPEG_QUALITY + << "\nvalid range: 1 to 100 with 100 being best." + << endl; + } + + theQuality = DEFAULT_JPEG_QUALITY; + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " DEBUG:" + << "\nQuality set to: " + << theQuality << endl; + } +} + +void ossimJpegWriter::set_rr_level(ossim_uint32 rr) +{ + theRlevel = rr; +} + +bool ossimJpegWriter::isOpen() const +{ + return (theOutputFilePtr!=NULL); +} + +bool ossimJpegWriter::open() +{ + close(); + theOutputFilePtr = fopen(theFilename.c_str(), "wb"); + if(theOutputFilePtr) + { + return true; + } + return false; +} + +void ossimJpegWriter::close() +{ + if(theOutputFilePtr) + { + fclose(theOutputFilePtr); + theOutputFilePtr = NULL; + } +} + +void ossimJpegWriter::getImageTypeList(std::vector<ossimString>& imageTypeList)const +{ + imageTypeList.push_back(ossimString("jpeg")); +} + +bool ossimJpegWriter::hasImageType(const ossimString& imageType) const +{ + if((imageType == "image/jpeg")|| + (imageType == "image/jpg")) + { + return true; + } + + return ossimImageFileWriter::hasImageType(imageType); +} + +void ossimJpegWriter::setProperty(ossimRefPtr<ossimProperty> property) +{ + if (!property) + { + return; + } + + if(property->getName() == ossimKeywordNames::COMPRESSION_QUALITY_KW) + { + ossimNumericProperty* numericProperty = PTR_CAST(ossimNumericProperty, + property.get()); + if (numericProperty) + { + setQuality( numericProperty->asInt32() ); + } + } + else + { + ossimImageFileWriter::setProperty(property); + } +} + +ossimRefPtr<ossimProperty> ossimJpegWriter::getProperty(const ossimString& name)const +{ + if (name == ossimKeywordNames::COMPRESSION_QUALITY_KW) + { + ossimNumericProperty* prop = + new ossimNumericProperty(name, + ossimString::toString(theQuality), + 1.0, + 100.0); + prop->setNumericType(ossimNumericProperty::ossimNumericPropertyType_INT); + return prop; + } + + return ossimImageFileWriter::getProperty(name); +} + +void ossimJpegWriter::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + ossimString name = ossimKeywordNames::COMPRESSION_QUALITY_KW; + propertyNames.push_back(name); + + ossimImageFileWriter::getPropertyNames(propertyNames); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/jpeg/ossimJpegWriter.h b/Utilities/OSSIM/ossim_core/imaging/formats/jpeg/ossimJpegWriter.h new file mode 100644 index 0000000000..fc6ef3a26d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/jpeg/ossimJpegWriter.h @@ -0,0 +1,110 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: David Burken +// +// Description: +// +// Contains class definition for JpegWriter. +// +//******************************************************************* +// $Id: ossimJpegWriter.h,v 1.18 2006/01/06 16:46:46 dburken Exp $ +#ifndef ossimJpegWriter_HEADER +#define ossimJpegWriter_HEADER + +#include <imaging/formats/ossimImageFileWriter.h> +#include <base/data_types/ossimKeywordlist.h> + +//******************************************************************* +// CLASS: ossimJpegWriterFactory +//******************************************************************* + +class OSSIMDLLEXPORT ossimJpegWriter : public ossimImageFileWriter +{ +public: + + ossimJpegWriter(); + + virtual ~ossimJpegWriter(); + + ossimJpegWriter(ossimImageSource *inputSource, + const ossimFilename& filename); + + /** + * void getImageTypeList(std::vector<ossimString>& imageTypeList)const + * + * Appends this writer image types to list "imageTypeList". + * + * This writer only has one type "jpeg". + * + * @param imageTypeList stl::vector<ossimString> list to append to. + */ + virtual void getImageTypeList(std::vector<ossimString>& imageTypeList)const; + + /** + * Sets the jpeg compression quality. + * + * @param quality Compression quality. (valid range is 1 to 100) + */ + virtual void setQuality(ossim_int32 quality); + + virtual void set_rr_level(ossim_uint32 rr); + + virtual bool isOpen()const; + + virtual bool open(); + + virtual void close(); + + /** + * saves the state of the object. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * Will set the property whose name matches the argument + * "property->getName()". + * + * @param property Object containing property to set. + */ + virtual void setProperty(ossimRefPtr<ossimProperty> property); + + /** + * @param name Name of property to return. + * + * @returns A pointer to a property object which matches "name". + */ + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + + /** + * Pushes this's names onto the list of property names. + * + * @param propertyNames array to add this's property names to. + */ + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + + bool hasImageType(const ossimString& imageType) const; + + +private: + virtual bool writeFile(); + + ossim_int32 theQuality; + bool theOverviewFlag; + ossim_uint32 theRlevel; + FILE* theOutputFilePtr; + +TYPE_DATA +}; + +#endif /* #ifndef ossimJpegWriter_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/landsat/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/formats/landsat/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/landsat/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/landsat/ossimLandsatTileSource.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/landsat/ossimLandsatTileSource.cpp new file mode 100644 index 0000000000..a05c73da8b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/landsat/ossimLandsatTileSource.cpp @@ -0,0 +1,450 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +// Contains class implementaiton for the class "ossim LandsatTileSource". +// +//******************************************************************* +// $Id: ossimLandsatTileSource.cpp,v 1.27 2005/11/10 15:07:49 gpotts Exp $ + +#include <imaging/formats/landsat/ossimLandsatTileSource.h> +#include <base/data_types/ossimDirectory.h> +#include <base/common/ossimTrace.h> +#include <base/common/ossimKeywordNames.h> +#include <support_data/ff_l7/ossimFfL7.h> +#include <support_data/ff_l7/ossimFfL5.h> +#include <projections/sensor_modeling/landsat/ossimLandSatModel.h> + +RTTI_DEF1_INST(ossimLandsatTileSource, + "ossimLandsatTileSource", + ossimGeneralRasterTileSource) + +static ossimTrace traceDebug("ossimLandsatTileSource:debug"); + + +//******************************************************************* +// Public Constructor: +//******************************************************************* +ossimLandsatTileSource::ossimLandsatTileSource() + : + ossimGeneralRasterTileSource(), + theFfHdr(NULL) +{ +} + +//******************************************************************* +// Public Constructor: +//******************************************************************* +ossimLandsatTileSource::ossimLandsatTileSource(const ossimKeywordlist& kwl, + const char* prefix) + : + ossimGeneralRasterTileSource(), + theFfHdr(NULL) +{ + if (loadState(kwl, prefix) == false) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + } +} + +//******************************************************************* +// Destructor: +//******************************************************************* +ossimLandsatTileSource::~ossimLandsatTileSource() +{ + if (theFfHdr) + { + delete theFfHdr; + theFfHdr = NULL; + } +} + +bool ossimLandsatTileSource::open() +{ + static const char MODULE[] = "ossimLandsatTileSource::open"; + + if (traceDebug()) CLOG << " Entered..." << endl + << " trying to open file " << theImageFile << std::endl; + + ossimFilename tempFilename = theImageFile; + // See if the file passed in is a header file. + + openHeader(theImageFile); + + if (!theFfHdr) return false; + + // Start building the keyword list for the general raster base class. + ossimKeywordlist kwl; + + //*** + // There can be up to seven (six for L7) files that belong to the header. + // Note that it seems the file names in the header are always upper case. + // So test the file given to us to see if they should be downcased. This + // is assuming that all files in the directory have the same case. + //*** + ossimFilename f1 = theImageFile.file(); + vector<ossimFilename> fileList; + + const char* c = f1.c_str(); + bool downcase = false; + if ((c[0]<='z') && (c[0]>='a')) downcase = true; + for (ossim_uint32 i=0; i<theFfHdr->getBandCount(); ++i) + { + f1 = theFfHdr->theBandFileNames[i]; + if (f1.trim() != "") + { + if (downcase) f1.downcase(); + + // Make the file name. + ossimFilename f2 = theImageFile.path(); + f2 = f2.dirCat(f1); + + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nfile[" << i << "] " << f2.c_str() << endl; + } + + // See if it exists. + if (f2.exists()) + { + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nAdding file: " << f2 << endl; + } + fileList.push_back(f2); + } + } + } + if(fileList.size() == 0) + { + close(); + return false; + } + ossimGeneralRasterInfo generalRasterInfo(fileList, + OSSIM_UINT8, + OSSIM_BSQ_MULTI_FILE, + fileList.size(), + theFfHdr->theLinesPerBand, + theFfHdr->thePixelsPerLine, + 0, + ossimGeneralRasterInfo::NONE, + 0); + if(fileList.size() == 1) + { + generalRasterInfo = ossimGeneralRasterInfo(fileList, + OSSIM_UINT8, + OSSIM_BSQ, + fileList.size(), + theFfHdr->theLinesPerBand, + theFfHdr->thePixelsPerLine, + 0, + ossimGeneralRasterInfo::NONE, + 0); + } + theMetaData.clear(); + theMetaData.setScalarType(OSSIM_UINT8); + theMetaData.setNumberOfBands(fileList.size()); + theImageData = generalRasterInfo; + if(initializeHandler()) + { + theImageFile = tempFilename; + + completeOpen(); + } + else + { + if (traceDebug()) CLOG << " Exited..." << endl; + return false; + } + + if (traceDebug()) CLOG << " Exited..." << endl; + + return true; +} + +void ossimLandsatTileSource::openHeader(const ossimFilename& file) +{ + //*** + // Landsat file name example: l71024031_03119990929_hpn.fst + // Three header header file type substrings: + // HPN = Pan + // HRF = VNIR/SWIR (visible near infrared/shortwave infrared) + // HTM = Thermal + //*** + ossimFilename hdr = file.file(); + hdr.downcase(); + if ( hdr.contains("hpn") || hdr.contains("hrf") || hdr.contains("htm") ) + { + theFfHdr = new ossimFfL7(file.c_str()); + } else if (hdr.contains("header.dat")) + { + theFfHdr = new ossimFfL5(file.c_str()); + } else { + theFfHdr = NULL; + return; + } + if (theFfHdr->getErrorStatus() != ossimErrorCodes::OSSIM_OK) + { + delete theFfHdr; + theFfHdr = NULL; + } + return; + + // I had to force the open to go with a header since there are duplicate entries when scanning + // landsat directories. + // For now I am commenting this code out. + // +#if 0 + //*** + // User may have passed in an image file name in which case the header file + // must be derived from it. + //*** + if (hdr.size() < 25) + { + // file name not long enough... + if (traceDebug()) + { + cout << "ossimLandsatTileSource::openHeader DEBUG:" + << "\nNot a standard landsat 7 file name: " << hdr << endl; + return; + } + } + + char substr[4]; + const char* f = hdr.c_str(); + strncpy(substr, (f+22), 3); + substr[3] = '\0'; + ossimString s1 = substr; + ossimString s2; + s1.downcase(); + if (s1 == "b80") + { + s2 = "hpn"; + } + else if (s1 == "b61" || s1 == "b62") + { + s2 = "htm"; + } + else if (s1 == "b10" || s1 == "b20" || s1 == "b30" || + s1 == "b40" || s1 == "b50" || s1 == "b70") + { + s2 = "hrf"; + } + else + { + // Not of any format we know of... + if (traceDebug()) + { + cout << "ossimLandsatTileSource::openHeader DEBUG:" + << "\nCould not derive header name from: " << file + << endl; + } + + return; + } + + // Set the case to be the same as the file passed in. + if (substr[0] == 0x42) // ascii "B" + { + s1.upcase(); + s2.upcase(); + hdr.upcase(); + + // Header files alway start with "L71" + hdr = hdr.substitute(ossimString("L72"), ossimString("L71")); + } + else + { + // Header files alway start with "l71" + hdr = hdr.substitute(ossimString("l72"), ossimString("l71")); + } + + // Make the hdr file name. + hdr = hdr.substitute(s1, s2); + + ossimFilename f1 = file.drive(); + f1 += file.path(); + hdr = f1.dirCat(hdr); + theFfHdr = new ossimFfL7(hdr.c_str()); + + if (theFfHdr->getErrorStatus() != ossimErrorCodes::OSSIM_OK) + { + delete theFfHdr; + theFfHdr = NULL; + } +#endif +} + +bool ossimLandsatTileSource::getImageGeometry(ossimKeywordlist& kwl, + const char* prefix) +{ + // Check for override for an external geometry file, or a previous save. + if(ossimImageHandler::getImageGeometry(kwl, prefix)) + { + return true; + } + + if (!theFfHdr) return false; + + // Make a model + ossimLandSatModel model(*theFfHdr); + + if (model.getErrorStatus() != ossimErrorCodes::OSSIM_OK) + { + + return false; + } + + bool result = model.saveState(kwl, prefix); + if (result) + { + // Capture for next time... + setImageGeometry(kwl); + } + return result; +} + +bool ossimLandsatTileSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* lookup = kwl.find(prefix, ossimKeywordNames::FILENAME_KW); + + if (lookup) + { + ossimFilename fileName = lookup; + + ossimString ext = fileName.ext(); + + if((ext.upcase() == "FST") || (ext.upcase() == "DAT")) + { + bool result = ossimImageHandler::open(fileName); + ossimImageSource::loadState(kwl, prefix); + return result; + } + } + + return ossimGeneralRasterTileSource::loadState(kwl, prefix); +} + +ossimString ossimLandsatTileSource::getShortName() const +{ + return ossimString("Landsat"); +} + +ossimString ossimLandsatTileSource::getLongName() const +{ + return ossimString("Landsat reader"); +} + +ossimString ossimLandsatTileSource::className() const +{ + return ossimString("ossimLandsatTileSource"); +} + +double ossimLandsatTileSource::getNullPixelValue(ossim_uint32)const +{ + return 0.0; +} + +double ossimLandsatTileSource::getMinPixelValue(ossim_uint32)const +{ + return 1.0; +} + +double ossimLandsatTileSource::getMaxPixelValue(ossim_uint32)const +{ + return 255.0; +} + +ossimScalarType ossimLandsatTileSource::getOutputScalarType() const +{ + return OSSIM_UINT8; +} + +bool ossimLandsatTileSource::getAcquisitionDate(ossimDate& date)const +{ + if(!theFfHdr) return false; + + std::cout << "Date = " << theFfHdr->theAcquisitionDate << std::endl; + + ossimString y = ossimString(theFfHdr->theAcquisitionDate, + theFfHdr->theAcquisitionDate+4); + ossimString m = ossimString(theFfHdr->theAcquisitionDate+4, + theFfHdr->theAcquisitionDate+6); + ossimString d = ossimString(theFfHdr->theAcquisitionDate+6, + theFfHdr->theAcquisitionDate+8); + + date = ossimDate(m.toInt(), + d.toInt(), + y.toInt()); + + return true; +} + +ossimString ossimLandsatTileSource::getSatelliteName()const +{ + if(!theFfHdr) return ""; + + return theFfHdr->theSatName; +} + +ossimFilename ossimLandsatTileSource::getBandFilename(ossim_uint32 idx)const +{ + ossim_uint32 maxIdx = getNumberOfInputBands(); + + if(!theFfHdr||(idx > maxIdx)) + { + return ""; + } + + ossimFilename path = getFilename().path(); + ossimString filename = theFfHdr->theBandFileNames[idx]; + filename = filename.trim(); + ossimFilename file = path.dirCat(filename); + + if (file.exists()) + { + return file; + } + + // Try downcased name. + file = path.dirCat(filename.downcase()); + if (file.exists()) + { + return file; + } + + // Try upcase name. + file = path.dirCat(filename.upcase()); + if (file.exists()) + { + return file; + } + + return ossimFilename(); +} + +bool ossimLandsatTileSource::isPan()const +{ + return (getNumberOfInputBands() == 1); +} + +bool ossimLandsatTileSource::isVir()const +{ + return (getNumberOfInputBands() == 6); +} + +bool ossimLandsatTileSource::isTm()const +{ + return (getNumberOfInputBands() == 2); +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/landsat/ossimLandsatTileSource.h b/Utilities/OSSIM/ossim_core/imaging/formats/landsat/ossimLandsatTileSource.h new file mode 100644 index 0000000000..5af9e52267 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/landsat/ossimLandsatTileSource.h @@ -0,0 +1,83 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +// Contains class definition for the class "ossimLandsatTileSource". +// ossimLandsatTileSource is derived from ImageHandler which is derived from +// TileSource. +// +//******************************************************************* +// $Id: ossimLandsatTileSource.h,v 1.13 2005/07/25 22:49:54 dburken Exp $ + +#ifndef ossimLandsatTileSource_HEADER +#define ossimLandsatTileSource_HEADER + +#include <imaging/formats/general_raster/ossimGeneralRasterTileSource.h> +#include <base/common/ossimDate.h> + +class ossimFfL7; + +class OSSIM_DLL ossimLandsatTileSource : public ossimGeneralRasterTileSource +{ +public: + ossimLandsatTileSource(); + + ossimLandsatTileSource(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual ~ossimLandsatTileSource(); + + virtual ossimString getShortName() const; + + virtual ossimString getLongName() const; + + virtual ossimString className() const; + + virtual bool open(); + + virtual double getNullPixelValue(ossim_uint32 band=0)const; + + virtual double getMinPixelValue(ossim_uint32 band=0)const; + + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + + virtual ossimScalarType getOutputScalarType() const; + + bool getAcquisitionDate(ossimDate& date)const; + ossimString getSatelliteName()const; + + ossimFilename getBandFilename(ossim_uint32 idx)const; + + bool isPan()const; + bool isVir()const; + bool isTm()const; + + /*! + * Populates the keyword list with image geometry information. This + * method is used to relay projection/model information to users. + * Returns true if geometry info is present, false if not. + */ + virtual bool getImageGeometry(ossimKeywordlist& kwl, + const char* prefix=0); + + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix = NULL); + +private: + + void openHeader(const ossimFilename& file); + + ossimFfL7* theFfHdr; + + TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/nitf/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/formats/nitf/.cvsignore new file mode 100644 index 0000000000..42d2532435 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/nitf/.cvsignore @@ -0,0 +1,2 @@ +*.d + diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/nitf/ossimNitfTileSource.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/nitf/ossimNitfTileSource.cpp new file mode 100644 index 0000000000..091ebca0a4 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/nitf/ossimNitfTileSource.cpp @@ -0,0 +1,2175 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: Contains class definition for ossimNitfTileSource. +// +//******************************************************************* +// $Id: ossimNitfTileSource.cpp,v 1.88 2006/01/05 15:00:01 dburken Exp $ + +#include <imaging/formats/nitf/ossimNitfTileSource.h> + +#include <support_data/nitf/ossimNitfPackedBits.h> +#include <support_data/nitf/ossimNitfFile.h> +#include <support_data/nitf/ossimNitfFileHeader.h> +#include <support_data/nitf/ossimNitfImageHeader.h> +#include <support_data/nitf/ossimNitfImageHeaderV2_0.h> +#include <support_data/nitf/ossimNitfImageHeaderV2_1.h> +#include <support_data/nitf/ossimNitfVqCompressionHeader.h> + +#include <base/common/ossimConstants.h> +#include <base/common/ossimCommon.h> +#include <base/common/ossimTrace.h> +#include <base/context/ossimNotifyContext.h> +#include <base/data_types/ossimIpt.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimIrect.h> +#include <base/data_types/ossimFilename.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/misc/lookup_tables/ossimInterleaveTypeLut.h> +#include <base/misc/lookup_tables/ossimScalarTypeLut.h> +#include <base/misc/ossimEndian.h> +#include <base/property/ossimBooleanProperty.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <imaging/formats/tiff/ossimTiffTileSource.h> +RTTI_DEF1_INST(ossimNitfTileSource, "ossimNitfTileSource", ossimImageHandler) + +#ifdef OSSIM_ID_ENABLED + static const char OSSIM_ID[] = "$Id: ossimNitfTileSource.cpp,v 1.88 2006/01/05 15:00:01 dburken Exp $"; +#endif + +//--- +// NOTE: This should match the enumerations for ReadMode. +//--- +static const char* READ_MODE[] = { "READ_MODE_UNKNOWN", + "READ_BIB_BLOCK", + "READ_BIP_BLOCK", + "READ_BIR_BLOCK", + "READ_BSQ_BLOCK", + "READ_BIB", + "READ_BIP", + "READ_BIR" }; + +//*** +// Static trace for debugging +//*** +static ossimTrace traceDebug("ossimNitfTileSource:debug"); + +// 64x64*12bits +// divide by 8 bits to get bytes gives you 6144 bytes +static const ossim_uint32 OSSIM_NITF_VQ_BLOCKSIZE = 6144; + +ossimNitfTileSource::ossimNitfTileSource() + : + ossimImageHandler(), + theTile(NULL), + theCacheTile(NULL), + theNitfFile(new ossimNitfFile()), + theNitfImageHeader(0), + theReadMode(READ_MODE_UNKNOWN), + theScalarType(OSSIM_SCALAR_UNKNOWN), + theSwapBytesFlag(false), + theNumberOfInputBands(0), + theNumberOfOutputBands(0), + theBlockSizeInBytes(0), + theReadBlockSizeInBytes(0), + theNumberOfImages(0), + theCurrentEntry(0), + theImageRect(0,0,0,0), + theFileStr(), + theOutputBandList(), + theCacheSize(0, 0), + theCacheTileInterLeaveType(OSSIM_INTERLEAVE_UNKNOWN), + theCacheEnabledFlag(false), + theCacheId(-1), + thePackedBitsFlag(false), + theCompressedBuf(NULL) +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimNitfTileSource::ossimNitfTileSource entered..." << endl; +#ifdef OSSIM_ID_ENABLED + ossimNotify(ossimNotifyLevel_DEBUG)<< "OSSIM_ID: " << OSSIM_ID << endl; +#endif + } + +} + +ossimNitfTileSource::~ossimNitfTileSource() +{ + destroy(); +} + +void ossimNitfTileSource::destroy() +{ + if (theCacheId != -1) + { + ossimAppFixedTileCache::instance()->deleteCache(theCacheId); + theCacheId = -1; + } + + // Delete the list of image headers. + vector<ossimNitfImageHeader*>::iterator i = theNitfImageHeader.begin(); + while (i != theNitfImageHeader.end()) + { + if(*i) + { + delete *i; + (*i) = 0; + } + ++i; + } + theNitfImageHeader.clear(); + + if(theFileStr.is_open()) + { + theFileStr.close(); + } + if (theNitfFile) + { + delete theNitfFile; + theNitfFile = NULL; + } + + theCacheTile = NULL; + theTile = NULL; + + if(theOverview) + { + delete theOverview; + theOverview = NULL; + } + if(theCompressedBuf) + { + delete [] theCompressedBuf; + theCompressedBuf = NULL; + } +} + +bool ossimNitfTileSource::isOpen()const +{ + return (theNitfImageHeader.size() > 0); +} + +bool ossimNitfTileSource::open() +{ + if(isOpen()) + { + close(); + } + + theErrorStatus = ossimErrorCodes::OSSIM_OK; + + if ( !parseFile() ) + { + return false; + } + return allocate(); +} + +void ossimNitfTileSource::close() +{ + destroy(); +} + +bool ossimNitfTileSource::parseFile() +{ + static const char MODULE[] = "ossimNitfTileSource::parseFile"; + + ossimFilename file = getFilename(); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " DEBUG: Nitf file = " << file << endl; + } + + if (file.empty()) + { + setErrorStatus(); + return false; + } + + if ( !theNitfFile ) // A close deletes "theNitfFile". + { + theNitfFile = new ossimNitfFile(); + } + + if ( !theNitfFile->parseFile(file) ) + { + setErrorStatus(); + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << "DEBUG:" << "\nError parsing file!" << endl; + } + + return false; + } + + // Get the number of images within the file. + theNumberOfImages = theNitfFile->getHeader()->getNumberOfImages(); + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << "DEBUG:\nNumber of images " + <<theNumberOfImages << std::endl; + } + + if ( theNumberOfImages == 0 ) + { + setErrorStatus(); + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << "DEBUG:\nNo images in file!" << endl; + } + + return false; + } + theEntryList.clear(); + //--- + // Get image header pointers. Note there can be multiple images in one + // image file. + //--- + for (ossim_uint32 i = 0; i < theNumberOfImages; ++i) + { + ossimNitfImageHeader* hdr = theNitfFile->getNewImageHeader(i); + if (!hdr) + { + setErrorStatus(); + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " ERROR:\nNull image header!" << endl; + } + + return false; + } + if (traceDebug()) + { + if(hdr) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << "DEBUG:" + << "\nImage header[" << i << "]:\n" << *hdr + << endl; + } + } + if(!hdr->isCompressed()) + { + theEntryList.push_back(i); + } + else + { + if(isVqCompressed(hdr->getCompressionCode())&& + (hdr->getCompressionHeader().valid())) + { + // we will only support single band vq compressed NITFS + // basically CIB and CADRG products are single band code words. + // + if(hdr->getNumberOfBands() == 1) + { + theEntryList.push_back(i); + } + theCacheEnabledFlag = true; + } + else + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "Entry " << i + <<" has an unsupported compression code = " + << hdr->getCompressionCode() << std::endl; + } + } + } + theNitfImageHeader.push_back(hdr); + } + if(theEntryList.size()<1) + { + return false; + } + if(theNitfImageHeader.size() == 1) + { + theLut = theNitfImageHeader[0]->createLut(0); + } + if(theEntryList.size()>0) + { + theCurrentEntry = theEntryList[0]; + } + + theNumberOfImages = theNitfImageHeader.size(); + + if (theNitfImageHeader.size() != theNumberOfImages) + { + setErrorStatus(); + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE + << "DEBUG:\nNumber of header not equal number of images!" + << endl; + } + + return false; + } + + // Check the current entry range. + if ( theCurrentEntry >= theNumberOfImages ) + { + if(theEntryList.size()) + { + theCurrentEntry = theEntryList[0]; + } + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " DEBUG:" + << "\nCurrent entry: " << theCurrentEntry + << endl; + } + + + // Open up a stream to the file. + theFileStr.open(file.c_str(), ios::in | ios::binary); + if (!theFileStr) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " ERROR:" + << "\nCannot open: " << file.c_str() << endl; + } + return false; + } + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " leaving with true..." << endl; + + } + + return true; +} + +bool ossimNitfTileSource::allocate() +{ + // Clear out the cache if there was any. + if (theCacheId != -1) + { + ossimAppFixedTileCache::instance()->deleteCache(theCacheId); + theCacheId = -1; + } + + // Set the scalar type. + initializeScalarType(); + if (theScalarType == OSSIM_SCALAR_UNKNOWN) + { + return false; + } + + // Set the swap bytes flag. + initializeSwapBytesFlag(); + + // Set the read mode. + initializeReadMode(); + if (theReadMode == READ_MODE_UNKNOWN) + { + return false; + } + + // Set the number of bands. + initializeBandCount(); + if (theNumberOfInputBands == 0) + { + return false; + } + + // Initialize the image rectangle. before the cache size is done + // + initializeImageRect(); + if (theImageRect.hasNans()) + { + return false; + } + + // Initialize the cache size. Must be done before + // setting the blocksize. Since bit encoded data may very + // and we need to know if the nitf file needs to be accessed + // like a general raster. + // + initializeCacheSize(); + if ( (theCacheSize.x == 0) || (theCacheSize.y == 0) ) + { + return false; + } + + // Initialize the block size. + initializeBlockSize(); + if (theBlockSizeInBytes == 0) + { + return false; + } + + + // Initialize the cache tile interleave type. + initializeCacheTileInterLeaveType(); + if (theCacheTileInterLeaveType == OSSIM_INTERLEAVE_UNKNOWN) + { + return false; + } + + //--- + // Initialize the cache tile. This will be used for a block buffer even + // if the cache is disabled. + //--- + initializeCacheTile(); + if (!theCacheTile.valid()) + { + return false; + } + + // Initialize the cache if enabled. + if (theCacheEnabledFlag) + { + theCacheId = ossimAppFixedTileCache::instance()-> + newTileCache(theBlockImageRect, theCacheSize); + } + + // Make the tiles. Note the blank tile is intentionally left blank. + ossimImageDataFactory* idf = ossimImageDataFactory::instance(); + theTile = idf->create(this, this); + theTile->initialize(); + + // Call base class complete open. + completeOpen(); + + return true; +} + +void ossimNitfTileSource::initializeReadMode() +{ + // Initialize the read mode. + theReadMode = READ_MODE_UNKNOWN; + + const ossimNitfImageHeader* hdr = getCurrentImageHeader(); + if (!hdr) + { + return; + } + + ossim_uint32 numberOfBlocks = getNumberOfBlocks(); + ossimString imode = hdr->getIMode(); + if (numberOfBlocks > 1) + { + if (imode == "B") + { + theReadMode = READ_BIB_BLOCK; + } + else if (imode == "P") + { + theReadMode = READ_BIP_BLOCK; + } + else if (imode == "R") + { + theReadMode = READ_BIR_BLOCK; + } + else if (imode == "S") + { + theReadMode = READ_BSQ_BLOCK; + } + } + else // The entire image comprises one block. + { + if ( (imode == "B") || (imode == "S")) + { + theReadMode = READ_BIB; + } + else if (imode == "P") + { + theReadMode = READ_BIP; + } + else if (imode == "R") + { + theReadMode = READ_BIR; + } + } + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimNitfTileSource::initializeReadMode DEBUG:" + << "\nnumberOfBlocks: " << numberOfBlocks + << "\nIMODE: " << imode + << "\nRead Mode: " << READ_MODE[theReadMode] + << endl; + } +} + +void ossimNitfTileSource::initializeScalarType() +{ + thePackedBitsFlag = false; + // Initialize the read mode. + theScalarType = OSSIM_SCALAR_UNKNOWN; + + const ossimNitfImageHeader* hdr = getCurrentImageHeader(); + if (!hdr) + { + return; + } + + ossim_int32 bitsPerPixel = hdr->getActualBitsPerPixelPerBand(); + if (bitsPerPixel < 1) + { + bitsPerPixel = hdr->getBitsPerPixelPerBand(); + } + + ossimString pixelValueType = hdr->getPixelValueType().upcase(); + + switch (bitsPerPixel) + { + case 8: + { + theScalarType = OSSIM_UCHAR; + break; + } + case 11: + { + theScalarType = OSSIM_USHORT11; + break; + } + case 16: + { + if(pixelValueType == "SI") + { + theScalarType = OSSIM_SSHORT16; + } + else + { + theScalarType = OSSIM_USHORT16; + } + break; + } + case 32: + { + if(pixelValueType == "R") + { + theScalarType = OSSIM_FLOAT; + } + + break; + } + case 64: + { + if(pixelValueType == "R") + { + theScalarType = OSSIM_DOUBLE; + } + + break; + } + default: + { + if(!hdr->isCompressed()) + { + thePackedBitsFlag = true; + if(bitsPerPixel < 8) + { + theScalarType = OSSIM_UCHAR; + } + else if(bitsPerPixel < 16) + { + theScalarType = OSSIM_USHORT16; + } + else if(bitsPerPixel < 32) + { + theScalarType = OSSIM_FLOAT; + } + } + break; + } + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimNitfTileSource::initializeScalarType DEBUG:" + << "\nScalar type: " + << (ossimScalarTypeLut::instance()->getEntryString(theScalarType)) + << "\nPacked bits: " << (thePackedBitsFlag?"true":"false") + << endl; + } +} + +void ossimNitfTileSource::initializeSwapBytesFlag() +{ + if ( (theScalarType != OSSIM_UCHAR) && + (ossimGetByteOrder() == OSSIM_LITTLE_ENDIAN) ) + { + theSwapBytesFlag = true; + } + else + { + theSwapBytesFlag = false; + } +} + +void ossimNitfTileSource::initializeBandCount() +{ + // Initialize the read mode. + theNumberOfInputBands = 0; + theNumberOfOutputBands = 0; + theOutputBandList.clear(); + + const ossimNitfImageHeader* hdr = getCurrentImageHeader(); + if (!hdr) + { + return; + } + + if(!isVqCompressed(hdr->getCompressionCode())) + { + theNumberOfInputBands = hdr->getNumberOfBands(); + theNumberOfOutputBands = hdr->getNumberOfBands(); + } + else + { + theNumberOfInputBands = 1; + theNumberOfOutputBands = 3; +// const ossimRefPtr<ossimNitfCompressionHeader> header = hdr->getCompressionHeader(); + +// ossimNitfVqCompressionHeader* header = PTR_CAST(ossimNitfVqCompressionHeader, +// header.get()); + +// if(header) +// { + +// } + } + + theOutputBandList.resize(theNumberOfOutputBands); + + for (ossim_uint32 i=0; i < theNumberOfOutputBands; ++i) + { + theOutputBandList[i] = i; // One to one for initial setup. + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimNitfTileSource::initializeBandCount DEBUG:" + << "\nInput Band count: " << theNumberOfInputBands + << "\nOutput Band count: " << theNumberOfOutputBands + << endl; + } +} + +void ossimNitfTileSource::initializeBlockSize() +{ + theBlockSizeInBytes = 0; + theReadBlockSizeInBytes = 0; + + const ossimNitfImageHeader* hdr = getCurrentImageHeader(); + if (!hdr) + { + return; + } + + + + // This returns block size in bytes. + // ossim_uint32 bytesPerPixel = + // static_cast<ossim_uint32>(ceil(hdr->getBitsPerPixelPerBand()/8.0)); + + ossim_uint32 bytesRowCol = 0; + ossim_uint32 bytesRowColCacheTile = 0; + + if(isVqCompressed(hdr->getCompressionCode())) + { + bytesRowCol = OSSIM_NITF_VQ_BLOCKSIZE; + } + else + { + bytesRowCol = (hdr->getNumberOfPixelsPerBlockHoriz()* + hdr->getNumberOfPixelsPerBlockVert()* + hdr->getBitsPerPixelPerBand()) / 8; + } + + bytesRowColCacheTile = (theCacheSize.x* + theCacheSize.y* + hdr->getBitsPerPixelPerBand())/8; + +#if 0 + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG:" + << "\ncompressionHeader: " << compressionHeader + << "\ngetNumberOfPixelsPerBlockHoriz(): " + << hdr->getNumberOfPixelsPerBlockHoriz() + << "\ngetNumberOfPixelsPerBlockVert(): " + << hdr->getNumberOfPixelsPerBlockVert() + << "\ngetBitsPerPixelPerBand(): " + << hdr->getBitsPerPixelPerBand() + << "\nbytesRowCol: " << bytesRowCol + << "\nbytesRowColCacheTile: " << bytesRowColCacheTile + << endl; + } +#endif + + theBlockSizeInBytes = bytesRowCol; + theReadBlockSizeInBytes = theBlockSizeInBytes; + switch (theReadMode) + { + case READ_BSQ_BLOCK: + case READ_BIB_BLOCK: + { + break; + } + case READ_BIB: + { + theReadBlockSizeInBytes = bytesRowColCacheTile; + + break; + } + + case READ_BIP_BLOCK: + case READ_BIR_BLOCK: + { + theBlockSizeInBytes *= theNumberOfInputBands; + theReadBlockSizeInBytes *= theNumberOfInputBands; + break; + } + case READ_BIP: + case READ_BIR: + { + theBlockSizeInBytes *= theNumberOfInputBands; + theReadBlockSizeInBytes = bytesRowColCacheTile*theNumberOfInputBands; + break; + } + + default: + { + break; + } + } + +//#if 0 + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimNitfTileSource::initializeBlockSize DEBUG:" + << "\nNumber of input bands: " << theNumberOfInputBands + << "\nNumber of output bands: " << theNumberOfOutputBands + << "\nBlock size in bytes: " << theBlockSizeInBytes + << "\nRead block size in bytes: " << theReadBlockSizeInBytes + << endl; + } +//#endif +} + +void ossimNitfTileSource::initializeImageRect() +{ + const ossimNitfImageHeader* hdr = getCurrentImageHeader(); + if (!hdr) + { + theImageRect.makeNan(); + return; + } + + theBlockImageRect = hdr->getBlockImageRect(); + theImageRect = hdr->getImageRect(); + theSubImageOffset = theImageRect.ul(); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimNitfTileSource::initializeImageRect DEBUG:" + << "\nImage Rect: " << theImageRect + << "\nSub image offset: " << theSubImageOffset + << endl; + } +} + +void ossimNitfTileSource::initializeCacheSize() +{ + theCacheSize.x = 0; + theCacheSize.y = 0; + + const ossimNitfImageHeader* hdr = getCurrentImageHeader(); + if (!hdr) + { + return; + } + switch (theReadMode) + { + case READ_BIB_BLOCK: + case READ_BIP_BLOCK: + case READ_BIR_BLOCK: + case READ_BSQ_BLOCK: + theCacheSize.x = hdr->getNumberOfPixelsPerBlockHoriz(); + theCacheSize.y = hdr->getNumberOfPixelsPerBlockVert(); + break; + + case READ_BIB: + case READ_BIP: + case READ_BIR: + theCacheSize.x = getNumberOfSamples(0); + theCacheSize.y = getTileHeight(); + if(theCacheSize.y > hdr->getNumberOfPixelsPerBlockVert()) + { + theCacheSize.y = hdr->getNumberOfPixelsPerBlockVert(); + } + break; + + default: + break; + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimNitfTileSource::initializeCacheSize DEBUG:" + << "\nCache size: " << theCacheSize + << endl; + } +} +void ossimNitfTileSource::initializeCacheTileInterLeaveType() +{ + theCacheTileInterLeaveType = OSSIM_INTERLEAVE_UNKNOWN; + + const ossimNitfImageHeader* hdr = getCurrentImageHeader(); + if (!hdr) + { + return; + } + + switch (theReadMode) + { + case READ_BIB_BLOCK: + case READ_BSQ_BLOCK: + case READ_BIB: + theCacheTileInterLeaveType = OSSIM_BSQ; + break; + + case READ_BIP_BLOCK: + case READ_BIP: + theCacheTileInterLeaveType = OSSIM_BIP; + break; + + case READ_BIR_BLOCK: + case READ_BIR: + theCacheTileInterLeaveType = OSSIM_BIL; + break; + + default: + break; + } + + if (traceDebug()) + { + ossimInterleaveTypeLut lut; + + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimNitfTileSource::initializeCacheTileInterLeaveType DEBUG:" + << "\nCache tile interleave type: " + << lut.getEntryString(theCacheTileInterLeaveType) + << endl; + } +} + +void ossimNitfTileSource::initializeCacheTile() +{ + const ossimNitfImageHeader* hdr = getCurrentImageHeader(); + if (!hdr) + { + return; + } + + if(theCompressedBuf) + { + delete [] theCompressedBuf; + theCompressedBuf = NULL; + } + + ossimImageDataFactory* idf = ossimImageDataFactory::instance(); + theCacheTile = idf->create(this, + theScalarType, + theNumberOfOutputBands, + theCacheSize.x, + theCacheSize.y); + theCacheTile->initialize(); + + if(hdr->getRepresentation().upcase().contains("LUT")) + { + theCompressedBuf = new ossim_uint8[theReadBlockSizeInBytes]; + memset(theCompressedBuf, '\0', theReadBlockSizeInBytes); + } + else if(isVqCompressed(hdr->getCompressionCode())) + { + theCompressedBuf = new ossim_uint8[theReadBlockSizeInBytes]; + memset(theCompressedBuf, '\0', theReadBlockSizeInBytes); + } +} + +ossimRefPtr<ossimImageData> ossimNitfTileSource::getTile( + const ossimIrect& tileRect, ossim_uint32 resLevel) +{ + // This tile source bypassed, or invalid res level, return a blank tile. + if(!isSourceEnabled() || !isOpen() || !isValidRLevel(resLevel)) + { + return ossimRefPtr<ossimImageData>(); + } + + if (theOverview) + { + if (theOverview->hasR0() || resLevel) + { + // Subtract any offsets since the overview doesn't know about them. + ossimIrect rr_rect = tileRect - getSubImageOffset(resLevel); + + //--- + // If there is a sub image offset then we will not be requesting + // the same rectangle as was requested from us. For this reason, + // we'll do a setOrigin, rather than just returning the getTile + // result. + //--- + ossimRefPtr<ossimImageData> tileData = theOverview->getTile(rr_rect, + resLevel); + if(tileData.valid()) + { + tileData->setImageRectangle(tileRect); + } + + if(getOutputScalarType() == OSSIM_USHORT11) + { + //--- + // Temp fix: + // The overview handler could return a tile of OSSIM_UINT16 if + // the max sample value was not set to 2047. + //--- + tileData->setScalarType(OSSIM_USHORT11); + } + + return tileData; + } + } + + if (!theTile.valid()) + { + return theTile; + } + + theTile->setImageRectangle(tileRect); + + ossimIrect cacheRect = theCacheTile->getImageRectangle(); + + //--- + // See if any point of the requested tile is in the image. + //--- + if ( tileRect.intersects(theBlockImageRect) ) + { + ossimIrect clipRect = tileRect.clipToRect(theImageRect); + + //--- + // See if the whole tile is going to be filled, if not, start out with + // a blank tile so data from a previous load gets wiped out. + //--- + if ( !tileRect.completely_within(clipRect) ) + { + // Start with a blank tile. + if (theTile->getDataObjectStatus() != OSSIM_EMPTY) + { + theTile->makeBlank(); + } + } + + // See if the requested clip rect is already in the cache tile. + bool status = true; + if ( (clipRect.completely_within(theCacheTile->getImageRectangle()))&& + (theCacheTile->getDataObjectStatus() != OSSIM_EMPTY)&& + (theCacheTile->getBuf())) + { + theTile->loadTile(theCacheTile->getBuf(), + theCacheTile->getImageRectangle(), + theCacheTileInterLeaveType); + } + else + { + + status = loadTile(clipRect); + } + + if (status) + { + //--- + // Validate the tile. This will set the status to full, partial + // or empty. Must be performed if any type of combining is to be + // performed down the chain. + //--- + theTile->validate(); + return theTile; + } + + } // End of if ( tileRect.intersects(image_rect) ) + + // No part of requested tile within the image rectangle or loadTile failed. + return ossimRefPtr<ossimImageData>(); +} + +bool ossimNitfTileSource::loadTile(const ossimIrect& clipRect) +{ + // Subtract any offsets and work in zero based image space. + ossimIrect zbClipRect = clipRect - theSubImageOffset; + + const ossim_uint32 BLOCK_HEIGHT = theCacheSize.y; + const ossim_uint32 BLOCK_WIDTH = theCacheSize.x; + + zbClipRect.stretchToTileBoundary(ossimIpt(BLOCK_WIDTH, BLOCK_HEIGHT)); + + //--- + // Shift the upper left corner of the "clip_rect" to the an even nitf + // block boundry. + //--- + ossimIpt nitfBlockOrigin = zbClipRect.ul(); +// adjustToStartOfBlock(nitfBlockOrigin, BLOCK_HEIGHT, BLOCK_WIDTH); + + // Vertical block loop. + ossim_int32 y = nitfBlockOrigin.y; + while (y < zbClipRect.lr().y) + { + // Horizontal block loop. + ossim_int32 x = nitfBlockOrigin.x; + while (x < zbClipRect.lr().x) + { + if (loadBlock(x, y)) + { + theTile->loadTile(theCacheTile->getBuf(), + theCacheTile->getImageRectangle(), + theCacheTileInterLeaveType); + } + else + { + // Error loading... + return false; + } + + x += BLOCK_WIDTH; // Go to next block. + } + + y += BLOCK_HEIGHT; // Go to next row of blocks. + } + + return true; +} + +bool ossimNitfTileSource::loadBlock(ossim_uint32 x, ossim_uint32 y) +{ +#if 0 + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimNitfTileSource::loadBlock DEBUG:" + << " x: " << x << " y: " << y << endl; + } +#endif + + //--- + // The origin set in the cache tile must have the sub image offset in it + // since "theTile" is relative to any sub image offset. This is so that + // "theTile->loadTile(theCacheTile)" will work. + //--- + ossimIpt origin(x, y); + origin = origin + theSubImageOffset; + + if (theCacheEnabledFlag) + { + // See if it's in the cache already. + ossimRefPtr<ossimImageData> tempTile = NULL; + tempTile = ossimAppFixedTileCache::instance()-> + getTile(theCacheId, origin); + if (tempTile.valid()) + { + theTile->loadTile(tempTile.get()); + return true; + } + } + const ossimNitfImageHeader* hdr = getCurrentImageHeader(); + theCacheTile->setOrigin(origin); + ossim_uint32 readSize = theReadBlockSizeInBytes; + if(!theCacheTile->getImageRectangle().completely_within(theBlockImageRect)) + { + readSize = getPartialReadSize(origin); + } + if((hdr->hasBlockMaskRecords())|| + (readSize != theReadBlockSizeInBytes)) + { + theCacheTile->makeBlank(); + } + + switch (theReadMode) + { + case READ_BIR: + case READ_BIR_BLOCK: + case READ_BIP: + case READ_BIP_BLOCK: + { + std::streampos p; + if(getPosition(p, x, y, 0)) + { + theFileStr.seekg(p, ios::beg); + char* buf = (char*)(theCacheTile->getBuf()); + if (!theFileStr.read(buf, readSize)) + { + theFileStr.clear(); + ossimNotify(ossimNotifyLevel_FATAL) + << "ossimNitfTileSource::loadBlock BIP Read Error!" + << "\nReturning error..." << endl; + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + + return false; + } + } + break; + } + case READ_BSQ_BLOCK: + case READ_BIB_BLOCK: + case READ_BIB: + { + //--- + // NOTE: + // With some of these types we could do one read and get all bands. + // The reads are done per for future enabling on band selection + // at the image handler level. + //--- + for (ossim_uint32 band = 0; band < theNumberOfInputBands; ++band) + { + ossim_uint8* buf =0; + if(isVqCompressed(hdr->getCompressionCode())|| + hdr->getRepresentation().upcase().contains("LUT")) + { + buf = theCompressedBuf; + } + else + { + buf = (ossim_uint8*)(theCacheTile->getBuf(band)); + } + std::streampos p; + if(getPosition(p, x, y, band)) + { + theFileStr.seekg(p, ios::beg); + if (!theFileStr.read((char*)buf, readSize)) + { + theFileStr.clear(); + ossimNotify(ossimNotifyLevel_FATAL) + << "ossimNitfTileSource::loadBlock Read Error!" + << "\nReturning error..." << endl; + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + return false; + } + else if(isVqCompressed(hdr->getCompressionCode())) + { + vqUncompress(theCacheTile, theCompressedBuf); + } + else if(hdr->getRepresentation().upcase().contains("LUT")) + { + lutUncompress(theCacheTile, theCompressedBuf); + } + } + } + break; + } + + default: + break; + } + + if(thePackedBitsFlag) + { + explodePackedBits(theCacheTile); + } + // Check for swap bytes. + if (theSwapBytesFlag) + { + ossimEndian swapper; + swapper.swap(theScalarType, + theCacheTile->getBuf(), + theCacheTile->getSize()); + } + convertTransparentToNull(theCacheTile); + + // Set the origin of the cache tile. + theCacheTile->validate(); + if (theCacheEnabledFlag) + { + // Add it to the cache for the next time. + ossimAppFixedTileCache::instance()->addTile(theCacheId, theCacheTile); + } + + return true; +} + +void ossimNitfTileSource::explodePackedBits(ossimRefPtr<ossimImageData> packedBuffer)const +{ + ossim_uint8* tempBuf = new ossim_uint8[packedBuffer->getSizePerBandInBytes()]; + ossim_uint32 idx = 0; + ossim_uint32 bandIdx = 0; + ossim_uint32 h = packedBuffer->getHeight(); + ossim_uint32 w = packedBuffer->getWidth(); + ossim_uint32 maxIdx = w*h; + ossim_uint32 bandCount = packedBuffer->getNumberOfBands(); + switch(packedBuffer->getScalarType()) + { + case OSSIM_UCHAR: + { + + ossim_uint8* outputBuf = (ossim_uint8*)tempBuf; + for(bandIdx = 0; bandIdx < bandCount; ++bandIdx) + { + ossimNitfPackedBits packedBits((ossim_uint8*)packedBuffer->getBuf(bandIdx), + getCurrentImageHeader()->getBitsPerPixelPerBand()); + for(idx = 0; idx < maxIdx; ++idx) + { + *outputBuf = (ossim_uint8)packedBits.getValueAsUint32(idx); + ++outputBuf; + } + + memcpy((char*)packedBuffer->getBuf(bandIdx), + (char*)tempBuf, + theCacheTile->getSizePerBandInBytes()*bandCount); + } + break; + } + case OSSIM_USHORT16: + { + + ossim_uint16* outputBuf = (ossim_uint16*)tempBuf; + for(bandIdx = 0; bandIdx < bandCount; ++bandIdx) + { + ossimNitfPackedBits packedBits((ossim_uint8*)packedBuffer->getBuf(bandIdx), + getCurrentImageHeader()->getBitsPerPixelPerBand()); + for(idx = 0; idx < maxIdx; ++idx) + { + *outputBuf = (ossim_uint16)packedBits.getValueAsUint32(idx); + ++outputBuf; + } + + memcpy((char*)packedBuffer->getBuf(bandIdx), + (char*)tempBuf, + theCacheTile->getSizePerBandInBytes()*bandCount); + } + break; + } + case OSSIM_FLOAT: + { + ossim_float32* outputBuf = (ossim_float32*)tempBuf; + for(bandIdx = 0; bandIdx < bandCount; ++bandIdx) + { + ossimNitfPackedBits packedBits((ossim_uint8*)packedBuffer->getBuf(bandIdx), + getCurrentImageHeader()->getBitsPerPixelPerBand()); + for(idx = 0; idx < maxIdx; ++idx) + { + *outputBuf = (ossim_float32)packedBits.getValueAsUint32(idx); + ++outputBuf; + } + + memcpy((char*)packedBuffer->getBuf(bandIdx), + (char*)tempBuf, + theCacheTile->getSizePerBandInBytes()*bandCount); + } + break; + } + default: + { + break; + } + } + delete [] tempBuf; +} + +void ossimNitfTileSource::convertTransparentToNull(ossimRefPtr<ossimImageData> tile)const +{ + const ossimNitfImageHeader* hdr = getCurrentImageHeader(); + + if(!hdr||!tile) return; + + if(!tile->getBuf()) return; + ossimIpt tempOrigin = tile->getOrigin()-theSubImageOffset; + ossim_uint32 blockNumber = getBlockNumber(tempOrigin); + ossim_uint32 numberOfBands = tile->getNumberOfBands(); + ossim_uint32 band = 0; + if(hdr->hasPadPixelMaskRecords()) + { + if(hdr->hasTransparentCode()) + { + ossim_uint32 idx = 0; + ossim_uint32 maxIdx = tile->getWidth()*tile->getHeight(); + + for (band = 0; band < numberOfBands; ++band) + { + if(hdr->getPadPixelMaskRecordOffset(blockNumber, + band)!=0xffffffff) + { + switch(tile->getScalarType()) + { + case OSSIM_UCHAR: + { + ossim_uint8 transparentValue = hdr->getTransparentCode(); + ossim_uint8* buf = (ossim_uint8*)tile->getBuf(band); + ossim_uint8 nullPix = (ossim_uint8)tile->getNullPix(band); + for(idx = 0; idx < maxIdx; ++idx) + { + if(*buf == transparentValue) + { + *buf = nullPix; + } + ++buf; + } + break; + } + case OSSIM_USHORT11: + case OSSIM_USHORT16: + { + ossim_uint16 transparentValue = hdr->getTransparentCode(); + ossim_uint16* buf = (ossim_uint16*)tile->getBuf(band); + ossim_uint16 nullPix = (ossim_uint16)tile->getNullPix(band); + for(idx = 0; idx < maxIdx; ++idx) + { + if(*buf == transparentValue) + { + *buf = nullPix; + } + ++buf; + } + break; + } + case OSSIM_SSHORT16: + { + ossim_sint16 transparentValue = hdr->getTransparentCode(); + ossim_sint16* buf = (ossim_sint16*)tile->getBuf(band); + ossim_sint16 nullPix = (ossim_sint16)tile->getNullPix(band); + for(idx = 0; idx < maxIdx; ++idx) + { + if(*buf == transparentValue) + { + *buf = nullPix; + } + ++buf; + } + break; + } + default: + { + break; + } + } + } + } + } + } +} + + +double ossimNitfTileSource::getMinPixelValue(ossim_uint32 band)const +{ + double result = ossimImageHandler::getMinPixelValue(band); + + if(thePackedBitsFlag) + { + if(result < 1.0) result = 1.0; + } + + return result; +} + +double ossimNitfTileSource::getMaxPixelValue(ossim_uint32 band)const +{ + double result = ossimImageHandler::getMaxPixelValue(band); + const ossimNitfImageHeader* hdr = getCurrentImageHeader(); + + if(hdr) + { + if(thePackedBitsFlag) + { + double test = 1<<(hdr->getBitsPerPixelPerBand()); + + if(result > test) result = test; + } + } + + return result; +} + +double ossimNitfTileSource::getNullPixelValue(ossim_uint32 band)const +{ + double result = ossimImageHandler::getNullPixelValue(band); + + if(thePackedBitsFlag) + { + if((result < 0) || + (result > getMaxPixelValue(band))) + { + result = 0.0; + } + } + + + return result; +} + + +bool ossimNitfTileSource::getPosition(std::streampos& streamPosition, + ossim_uint32 x, + ossim_uint32 y, + ossim_uint32 band) const +{ + // + // NOTE: "theCacheSize is always relative to a block size except in + // the case where a block is the entire image. + // + streamPosition = 0; + + + const ossimNitfImageHeader* hdr = getCurrentImageHeader(); + if (!hdr) + { + return streamPosition; + } + + ossim_uint32 blockNumber = getBlockNumber(ossimIpt(x,y)); + +#if 0 + cout << "ossimNitfTileSource::getPosition blockNumber: " + << blockNumber << endl; +#endif + + streamPosition = hdr->getDataLocation(); // Position to first block. + if(hdr->hasBlockMaskRecords()) + { + ossim_uint32 blockOffset = hdr->getBlockMaskRecordOffset(blockNumber, + band); + if(blockOffset == 0xffffffff) + { + return false; + } + streamPosition += blockOffset; + } + + switch (theReadMode) + { + case READ_BIB_BLOCK: + { + if(!hdr->hasBlockMaskRecords()) + { + streamPosition += + (blockNumber * getBlockOffset()) + + (getBandOffset() * band); + } + else + { + streamPosition += (getBandOffset() * band); + + } + break; + } + + case READ_BIB: + { + streamPosition += + (blockNumber * theReadBlockSizeInBytes)+ + (getBandOffset() * band); + break; + } + + case READ_BSQ_BLOCK: + { + + if(!hdr->hasBlockMaskRecords()) + { + streamPosition += (blockNumber * getBlockOffset()) + + (getBandOffset() * band); + } + + break; + } + default: + { + if(!hdr->hasBlockMaskRecords()) + { + streamPosition += (blockNumber*getBlockOffset()); + } + + break; + } + } + + return true; +} + +std::streampos ossimNitfTileSource::getBandOffset() const +{ + std::streampos bandOffset = 0; + + switch (theReadMode) + { + case READ_BIB_BLOCK: + case READ_BIP_BLOCK: + case READ_BIR_BLOCK: + case READ_BIB: + case READ_BIP: + case READ_BIR: + bandOffset = theBlockSizeInBytes; + break; + + case READ_BSQ_BLOCK: + bandOffset = getNumberOfBlocks() * theBlockSizeInBytes; + break; + + default: + break; + } + + return bandOffset; +} + +std::streampos ossimNitfTileSource::getBlockOffset() const +{ + std::streampos blockOffset = 0; + std::streampos blockSizeInBytes = 0; + if (getNumberOfBlocks() == 1) + { + blockSizeInBytes = theReadBlockSizeInBytes; + } + else + { + blockSizeInBytes = theBlockSizeInBytes; + } + + switch (theReadMode) + { + case READ_BIB_BLOCK: + case READ_BIB: + // Band interleaved by block. + blockOffset = blockSizeInBytes * theNumberOfInputBands; + break; + + case READ_BIR_BLOCK: + case READ_BSQ_BLOCK: + case READ_BIP_BLOCK: + case READ_BIP: + case READ_BIR: + // Blocks side by side. + blockOffset = blockSizeInBytes; + break; + + default: + break; + } + + return blockOffset; +} + +ossim_uint32 ossimNitfTileSource::getNumberOfBlocks() const +{ + const ossimNitfImageHeader* hdr = getCurrentImageHeader(); + if (!hdr) + { + return 0; + } + + return static_cast<ossim_uint32>( hdr->getNumberOfBlocksPerRow() * + hdr->getNumberOfBlocksPerCol() ); +} + +bool ossimNitfTileSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + if ( !ossimImageHandler::loadState(kwl, prefix) ) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimNitfTileSource::loadState(kwl, prefix) DEBUG:" + << "\nUnable to load, exiting..." << std::endl; + } + return false; + } + + const char* lookup = kwl.find(prefix, "entry"); + if (lookup) + { + ossimString s(lookup); + theCurrentEntry = s.toUInt32(); + } + + lookup = kwl.find(prefix,ossimKeywordNames::ENABLE_CACHE_KW); + if (lookup) + { + ossimString s(lookup); + theCacheEnabledFlag = s.toBool(); + } + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimNitfTileSource::loadState(kwl, prefix) DEBUG:" + << "\nCurrent entry: " << theCurrentEntry + << "\nCache enable flag: " << theCacheEnabledFlag + << std::endl; + } + + return open(); +} + +bool ossimNitfTileSource::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + // Add the entry number. + kwl.add(prefix, "entry", theCurrentEntry, true); + + // Add the cache_enable flag. + kwl.add(prefix, ossimKeywordNames::ENABLE_CACHE_KW, theCacheEnabledFlag, true); + + // Call the base class save state. + return ossimImageHandler::saveState(kwl, prefix); +} + +ossimScalarType ossimNitfTileSource::getOutputScalarType() const +{ + return theScalarType; +} + +ossim_uint32 ossimNitfTileSource::getTileWidth() const +{ + if (theTile.valid()) + { + return theTile->getWidth(); + } + + ossimIpt tileSize; + ossimGetDefaultTileSize(tileSize); + return static_cast<ossim_uint32>(tileSize.x); +} + +ossim_uint32 ossimNitfTileSource::getTileHeight() const +{ + if (theTile.valid()) + { + return theTile->getHeight(); + } + + ossimIpt tileSize; + ossimGetDefaultTileSize(tileSize); + return static_cast<ossim_uint32>(tileSize.y); +} + +ossim_uint32 ossimNitfTileSource::getNumberOfInputBands() const +{ + return theNumberOfInputBands; +} + +ossim_uint32 ossimNitfTileSource::getNumberOfOutputBands() const +{ + return theNumberOfOutputBands; +} + +ossim_uint32 ossimNitfTileSource::getNumberOfLines(ossim_uint32 resLevel) const +{ + if (resLevel == 0) + { + const ossimNitfImageHeader* hdr = getCurrentImageHeader(); + if (!hdr) + { + return 0; + } + return hdr->getNumberOfRows(); + } + else if (theOverview) + { + return theOverview->getNumberOfLines(resLevel); + } + return 0; +} + +ossim_uint32 ossimNitfTileSource::getNumberOfSamples(ossim_uint32 resLevel) const +{ + if (resLevel == 0) + { + const ossimNitfImageHeader* hdr = getCurrentImageHeader(); + if (!hdr) + { + return 0; + } + return hdr->getNumberOfCols(); + } + else if (theOverview) + { + return theOverview->getNumberOfSamples(resLevel); + } + return 0; +} + +void ossimNitfTileSource::adjustToStartOfBlock(ossimIpt& pt, + ossim_int32 tile_height, + ossim_int32 tile_width) const +{ + if (pt.x > 0) + { + pt.x = pt.x/tile_width*tile_width; + } + else if (pt.x < 0) + { + pt.x = (pt.x-tile_width)/tile_width*tile_width; + } + + if (pt.y > 0) + { + pt.y = pt.y/tile_height*tile_height; + } + else if (pt.y < 0) + { + pt.y = (pt.y-tile_height)/tile_height*tile_height; + } +} + +ossim_uint32 ossimNitfTileSource::getBlockNumber(const ossimIpt& block_origin) const +{ + ossim_uint32 blockNumber = 0; + + const ossimNitfImageHeader* hdr = getCurrentImageHeader(); + if (!hdr) + { + return blockNumber; + } + + ossim_uint32 blockY; + ossim_uint32 blockX; + blockX = (block_origin.x / + theCacheSize.x); + blockY= (block_origin.y / + theCacheSize.y); + + switch (theReadMode) + { + case READ_BIB_BLOCK: + case READ_BIP_BLOCK: + case READ_BIR_BLOCK: + case READ_BSQ_BLOCK: + + blockNumber = ((blockY*hdr->getNumberOfBlocksPerRow()) + + blockX); + break; + case READ_BIB: + case READ_BIP: + case READ_BIR: + //--- + // These read modes are for a single block image. The cache size will + // be set to the width of the image (block) by the height of one tile. + // + // This is to avoid reading an entire large image with a single block + // into memory. + //--- + blockNumber = blockY; + break; + + default: + break; + } + return blockNumber; +} + +ossim_uint32 ossimNitfTileSource::getPartialReadSize(const ossimIpt& blockOrigin)const +{ + ossim_uint32 result = 0; + const ossimNitfImageHeader* hdr = getCurrentImageHeader(); + if (!hdr) + { + return result; + } + + if(theCacheTile->getImageRectangle().completely_within(theBlockImageRect)) + { + return theReadBlockSizeInBytes; + } + ossimIrect clipRect = theCacheTile->getImageRectangle().clipToRect(theBlockImageRect); + + result = (theCacheSize.x* + clipRect.height()* + hdr->getBitsPerPixelPerBand())/8; + + switch (theReadMode) + { + case READ_BSQ_BLOCK: + case READ_BIB_BLOCK: + case READ_BIB: + { + // purposely left blank. only hear for clarity. + break; + } + + case READ_BIP_BLOCK: + case READ_BIR_BLOCK: + case READ_BIP: + case READ_BIR: + { + result *= theNumberOfInputBands; + break; + } + default: + { + break; + } + } + return result; +} + +bool ossimNitfTileSource::isVqCompressed(const ossimString& compressionCode)const +{ + return((compressionCode == "C4")|| + (compressionCode == "M4")); +} + + +ossim_uint32 ossimNitfTileSource::getImageTileWidth() const +{ + const ossimNitfImageHeader* hdr = getCurrentImageHeader(); + if (!hdr) + { + return 0; + } + return hdr->getNumberOfPixelsPerBlockHoriz(); +} + +ossim_uint32 ossimNitfTileSource::getImageTileHeight() const +{ + const ossimNitfImageHeader* hdr = getCurrentImageHeader(); + if (!hdr) + { + return 0; + } + return hdr->getNumberOfPixelsPerBlockVert(); +} + +ossimString ossimNitfTileSource::getShortName()const +{ + return ossimString("nitf"); +} + +ossimString ossimNitfTileSource::getLongName()const +{ + return ossimString("nitf reader"); +} + +ossimString ossimNitfTileSource::className()const +{ + return ossimString("ossimNitfTileSource"); +} + +ossim_uint32 ossimNitfTileSource::getCurrentEntry() const +{ + return theCurrentEntry; +} + +ossim_uint32 ossimNitfTileSource::getNumberOfEntries() const +{ + return theEntryList.size(); +} + +void ossimNitfTileSource::getEntryList(std::vector<ossim_uint32>& entryList)const +{ + entryList = theEntryList; +// entryList.resize(theNumberOfImages); +// for (ossim_uint32 i = 0; i < theNumberOfImages; ++i) +// { +// entryList[i] = i; +// } +} + +bool ossimNitfTileSource::setCurrentEntry(ossim_uint32 entryIdx) +{ + if (theCurrentEntry == entryIdx) + { + return true; // Nothing to change. + } + + if ( isOpen() ) + { + if ( entryIdx < theNumberOfImages ) + { + theCurrentEntry = entryIdx; + //--- + // Since we were previously open and the the entry has changed we + // need to reinitialize some things. + //--- + allocate(); + } + else + { + return false; + } + } + else + { + //--- + // Not open. + // Allow this know that the parseFile will check for out of range. + //--- + theCurrentEntry = entryIdx; + } + + return true; +} + +bool ossimNitfTileSource::getCacheEnabledFlag() const +{ + return theCacheEnabledFlag; +} + +void ossimNitfTileSource::setCacheEnabledFlag(bool flag) +{ + if (flag != theCacheEnabledFlag) + { + // State of caching has changed... + + theCacheEnabledFlag = flag; + + if ( theCacheEnabledFlag) // Cache enabled. + { + theCacheId = ossimAppFixedTileCache::instance()-> + newTileCache(theBlockImageRect, theCacheSize); + } + else // Cache disabled... + { + // Clean out the cache if there was one. + if (theCacheId != -1) + { + ossimAppFixedTileCache::instance()->deleteCache(theCacheId); + theCacheId = -1; + } + } + } +} + +const ossimNitfImageHeader* ossimNitfTileSource::getCurrentImageHeader() const +{ + return theNitfImageHeader[theCurrentEntry]; +} + +void ossimNitfTileSource::setBoundingRectangle(const ossimIrect& imageRect) +{ + theImageRect = imageRect; + theSubImageOffset = theImageRect.ul(); + + // now shift the internal block rect as well + theBlockImageRect = (theBlockImageRect - theBlockImageRect.ul()) + theSubImageOffset; +} + +ossimRefPtr<ossimProperty> ossimNitfTileSource::getProperty(const ossimString& name)const +{ + if (name == ossimKeywordNames::ENABLE_CACHE_KW) + { + ossimProperty* p = new ossimBooleanProperty(name, theCacheEnabledFlag); + return ossimRefPtr<ossimProperty>(p); + } + + return ossimImageHandler::getProperty(name); +} + +void ossimNitfTileSource::setProperty(ossimRefPtr<ossimProperty> property) +{ + if (!property) return; + + ossimString name = property->getName(); + + if (name == ossimKeywordNames::ENABLE_CACHE_KW) + { + ossimBooleanProperty* obj = PTR_CAST(ossimBooleanProperty, + property.get()); + if (obj) + { + setCacheEnabledFlag(obj->getBoolean()); + } + } + else + { + ossimImageHandler::setProperty(property); + } +} + +void ossimNitfTileSource::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + propertyNames.push_back(ossimKeywordNames::ENABLE_CACHE_KW); + + ossimImageHandler::getPropertyNames(propertyNames); +} + +ossimString ossimNitfTileSource::getSecurityClassification() const +{ + if(getCurrentImageHeader()) + { + return getCurrentImageHeader()->getSecurityClassification(); + } + + return "U"; +} + +void ossimNitfTileSource::lutUncompress(ossimRefPtr<ossimImageData> destination, ossim_uint8* source) +{ + const ossimNitfImageHeader* hdr = getCurrentImageHeader(); + if (!hdr||!destination) + { + return; + } + if((destination->getNumberOfBands()<3)|| + (!destination->getBuf())|| + (destination->getScalarType()!=OSSIM_UCHAR)|| + (!theLut.valid())) + { + return; + } + + if(destination->getNumberOfBands()!=theLut->getNumberOfBands()) + { + return; + } + + ossim_uint8* tempRows[3]; + tempRows[0] = (ossim_uint8*)destination->getBuf(0); + tempRows[1] = (ossim_uint8*)destination->getBuf(1); + tempRows[2] = (ossim_uint8*)destination->getBuf(2); + + ossim_uint8* srcPtr = source; + ossim_uint32 compressionYidx = 0; + ossim_uint32 compressionXidx = 0; + ossim_uint32 uncompressIdx = 0; + ossim_uint32 h = destination->getHeight(); + ossim_uint32 w = destination->getWidth(); + + for(compressionYidx = 0; compressionYidx < h; ++compressionYidx) + { + for(compressionXidx = 0; compressionXidx < w; ++compressionXidx) + { + tempRows[0][uncompressIdx] = (*theLut)[*srcPtr][0]; + tempRows[1][uncompressIdx] = (*theLut)[*srcPtr][1]; + tempRows[2][uncompressIdx] = (*theLut)[*srcPtr][2]; + ++srcPtr; + ++uncompressIdx; + } + } +} + +void ossimNitfTileSource::vqUncompress(ossimRefPtr<ossimImageData> destination, ossim_uint8* source) +{ + const ossimNitfImageHeader* hdr = getCurrentImageHeader(); + if (!hdr||!destination) + { + return; + } + if((destination->getNumberOfBands()<3)|| + (!destination->getBuf())|| + (destination->getScalarType()!=OSSIM_UCHAR)) + { + return; + } + ossimNitfVqCompressionHeader* compressionHeader = PTR_CAST(ossimNitfVqCompressionHeader, + hdr->getCompressionHeader().get()); + + if(!compressionHeader) + { + return; + } + const std::vector<ossimNitfVqCompressionOffsetTableData>& table = compressionHeader->getTable(); + ossimRefPtr<ossimNitfImageBand> bandInfo = hdr->getBandInformation(0); + +// if(!bandInfo.valid()) return; + +// if(!theLut.valid()) return; +// if(theLut->getNumberOfBands() != 3) return; + std::vector<ossimRefPtr<ossimNitfImageLut> > luts(destination->getNumberOfBands()); + + if(bandInfo->getNumberOfLuts() == 1) + { + luts[0] = bandInfo->getLut(0); + luts[1] = bandInfo->getLut(0); + luts[2] = bandInfo->getLut(0); + } + else + { + luts[0] = bandInfo->getLut(0); + luts[1] = bandInfo->getLut(1); + luts[2] = bandInfo->getLut(2); + } + + if(!luts[0].valid()|| + !luts[1].valid()|| + !luts[2].valid()) + { + return; + } + ossim_uint8* tempRows[3]; + tempRows[0] = (ossim_uint8*)destination->getBuf(0); + tempRows[1] = (ossim_uint8*)destination->getBuf(1); + tempRows[2] = (ossim_uint8*)destination->getBuf(2); + + ossim_uint32 destWidth = destination->getWidth(); + ossimNitfPackedBits bits(source, + compressionHeader->getImageCodeBitLength()); +// ossimNitfPackedBits bits(source, +// 12); // vq is 12 bits + + ossim_uint32 compressionYidx = 0; + ossim_uint32 compressionXidx = 0; + ossim_uint32 compressionIdx = 0; + ossim_uint32 uncompressIdx = 0; + ossim_uint32 uncompressYidx = 0; + ossim_uint32 rows = table.size(); + ossim_uint32 cols = 0; + ossim_uint32 rowIdx = 0; + ossim_uint32 colIdx = 0; + if(rows) + { + cols = table[0].theNumberOfValuesPerCompressionLookup; + } + ossim_uint32 compressionHeight = compressionHeader->getNumberOfImageRows(); + ossim_uint32 compressionWidth = compressionHeader->getNumberOfImageCodesPerRow(); + ossim_uint8 lutValue = 0; + ossim_uint8* data=0; + + for(compressionYidx = 0; compressionYidx < compressionHeight; ++compressionYidx) + { + uncompressYidx = compressionYidx*rows*destWidth; + for(compressionXidx = 0; compressionXidx < compressionWidth; ++compressionXidx) + { + uncompressIdx = uncompressYidx + cols*compressionXidx; + ossim_uint32 codeWord = bits.getValueAsUint32(compressionIdx); + + codeWord *= cols; + for(rowIdx = 0; rowIdx < rows; ++rowIdx) + { + data = &table[rowIdx].theData[codeWord]; + for(colIdx = 0; colIdx < cols; ++colIdx) + { + lutValue = (*data)&0xff; + tempRows[0][uncompressIdx+colIdx] = (*theLut)[lutValue][0]; + tempRows[1][uncompressIdx+colIdx] = (*theLut)[lutValue][1]; + tempRows[2][uncompressIdx+colIdx] = (*theLut)[lutValue][2]; + ++data; + } + uncompressIdx += destWidth; + } + ++compressionIdx; + } + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/nitf/ossimNitfTileSource.h b/Utilities/OSSIM/ossim_core/imaging/formats/nitf/ossimNitfTileSource.h new file mode 100644 index 0000000000..d678293cc7 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/nitf/ossimNitfTileSource.h @@ -0,0 +1,416 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class declaration for NitfTileSource. +// +//******************************************************************* +// $Id: ossimNitfTileSource.h,v 1.42 2005/11/09 16:07:43 dburken Exp $ +#ifndef ossimNitfTileSource_HEADER +#define ossimNitfTileSource_HEADER + +#include <fstream> +using namespace std; + +#include <imaging/formats/ossimImageHandler.h> +#include <imaging/cache/ossimAppFixedTileCache.h> + +class ossimNitfFile; +class ossimNitfImageHeader; + +class OSSIM_DLL ossimNitfTileSource : public ossimImageHandler +{ +public: + + enum ReadMode + { + READ_MODE_UNKNOWN = 0, + + /** IMODE = B "Band Interleaved By Block or a single band" */ + READ_BIB_BLOCK = 1, + + /** IMODE = P "Band Interleaved By Pixel" */ + READ_BIP_BLOCK = 2, + + /** IMODE = R "Band Interleaved By Row" */ + READ_BIR_BLOCK = 3, + + /** IMODE = S "Band Sequential" */ + READ_BSQ_BLOCK = 4, + + /** IMODE = B of S "single block or one block for each band" */ + READ_BIB = 5, + + /** IMODE = P "single block Band Interleaved By Pixel" */ + READ_BIP = 6, + + /** IMODE = R "single block Band Interleaved By Row" */ + READ_BIR = 7 + }; + + ossimNitfTileSource(); + + virtual ~ossimNitfTileSource(); + + virtual ossimString getShortName() const; + virtual ossimString getLongName() const; + virtual ossimString className() const; + + /** + * Returns true if the image_file can be opened and is a valid nitf file. + */ + virtual bool open(); + + /** + * Closes file and destroys all memory allocated. + */ + virtual void close(); + + /** + * @param tileRect Requested rectangle. + * + * @param resLevel Reduced resolution level to grab tileRect from. + * Default = 0 or the full resolution data set. + * + * @return Returns an image data object with requested rectangle from the + * image. Depending on the overlap of tileRect with respect to the image + * rectangle, the returned tile could be full, partial, or an empty(blank) + * tile. + */ + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + + /** + * @return Returns the number of bands in the image. + * Satisfies pure virtual from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfInputBands() const; + + /** + * @return Number of output bands. + */ + virtual ossim_uint32 getNumberOfOutputBands() const; + + /** + * Returns the number of lines in the image. + * Satisfies pure virtual from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel = 0) const; + + /** + * Returns the number of samples in the image. + * Satisfies pure virtual from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel = 0) const; + + /** + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * Returns the output pixel type of the tile source. + */ + virtual ossimScalarType getOutputScalarType() const; + + /** + * Returns the width of the output tile. + */ + virtual ossim_uint32 getTileWidth() const; + + /** + * Returns the height of the output tile. + */ + virtual ossim_uint32 getTileHeight() const; + + /** + * Returns the tile width of the image or 0 if the image is not tiled. + * Note: this is not the same as the ossimImageSource::getTileWidth which + * returns the output tile width which can be different than the internal + * image tile width on disk. + */ + virtual ossim_uint32 getImageTileWidth() const; + + /** + * Returns the tile width of the image or 0 if the image is not tiled. + * Note: this is not the same as the ossimImageSource::getTileWidth which + * returns the output tile width which can be different than the internal + * image tile width on disk. + */ + virtual ossim_uint32 getImageTileHeight() const; + + virtual bool isOpen()const; + + /** + * @return The current entry number. + * + * @note NITF's can contain multiple images in a single file. This returns + * the index of the current image being read. + */ + virtual ossim_uint32 getCurrentEntry() const; + + /** + * @param entryList This is the list to initialize with entry indexes. + */ + virtual void getEntryList(std::vector<ossim_uint32>& entryList) const; + + /** + * @return Returns the number of entries (or images) within the nitf + * file. + */ + ossim_uint32 getNumberOfEntries() const; + + /** + * @param entryIdx Zero base entry number to select. Sets data member + * "theCurrentEntry". + * + * @note "theCurrentEntry" will not be set if "entryIdx" is out of range. + */ + virtual bool setCurrentEntry(ossim_uint32 entryIdx); + + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + + ossimString getSecurityClassification()const; + + /** + * @return Returns theCacheEnabledFlag. + */ + bool getCacheEnabledFlag() const; + + /** + * @param flag Sets theCacheEnabledFlag and disables/enables caching + * accordingly. If cache is disabled it is also flushed at the same time. + * If cache is enabled, blocks read from the image will be cached. + */ + void setCacheEnabledFlag(bool flag); + +protected: + + /** + * @param imageRect The full resolution image rectangle. + * + * @note Should contain offsets if there are any. + */ + void setBoundingRectangle(const ossimIrect& imageRect); + + /** + * @return The image header for the current entry. + */ + const ossimNitfImageHeader* getCurrentImageHeader() const; + +private: + + /** Copy constructor, disallow... */ + ossimNitfTileSource(const ossimNitfTileSource& source); + + /** Operator=, disallow... */ + ossimNitfTileSource& operator=(const ossimNitfTileSource& source); + + /** + * Returns true on success, false on error. + */ + bool loadTile(const ossimIrect& clipRect); + + /** + * @param pt Point to adjust. This will be modified by the method to fall + * on an even block boundary. Behavior is to snap to the nearest upper + * left block corner. + * + * @param tileHeight Height of one tile in pixels. + * + * @param tileWidth Width of one tile in pixels. + */ + void adjustToStartOfBlock(ossimIpt& pt, + ossim_int32 tileHeight, + ossim_int32 tileWidth) const; + + /** + * @return Returns the block number given an origin. + */ + ossim_uint32 getBlockNumber(const ossimIpt& block_origin) const; + + /** + * Deletes all memory allocated by this object. + */ + void destroy(); + + /** + * Parses "theImageFile" and initializes all nitf headers. + * + * @return true on success, false on error. + * + * @note parseFile() and initialize() are separated so initialize() can + * be called on a entry change to an already open nitf file. + */ + bool parseFile(); + + /** + * Allocates all memory with the exception of headers. + * + * @note parseFile() and allocate() are separated so allocate() can + * be called on a entry change to an already open nitf file. + */ + bool allocate(); + + /** + * Initializes the data member "theScalarType" from the current entry. + */ + void initializeScalarType(); + + /** + * Initializes the data member "theSwapBytesFlag" from the current entry. + */ + void initializeSwapBytesFlag(); + + /** + * Initializes the data member "theReadMode" from the current entry. + */ + void initializeReadMode(); + + /** + * Initializes the data member "theNumberOfBands" from the current entry. + */ + void initializeBandCount(); + + /** + * Initializes the data member "theBlockSize" from the current entry. + * + * @note This should be performed after setting the read mode and + * band count. + * + * @note This is the size of a single block read. So if the bands are + * separated by block, a read of this size will get one block. + */ + void initializeBlockSize(); + + /** + * Initializes the data members "theImageRect" and "theSubImageOffset" + * from the current entry. + */ + void initializeImageRect(); + + /** + * Initializes the data member "theCacheSize". + */ + void initializeCacheSize(); + + /** + * Initializes the data member "theCacheTileInterLeaveType". + */ + void initializeCacheTileInterLeaveType(); + + /** + * Initializes the cache tile size(width and height). For block images + * this will be the size of one block. For images that are a single block, + * this will be the image width by the height of one tile. + */ + void initializeCacheTile(); + + /** + * Loads a block of data to theCacheTile. + * + * @param x Starting x position of block to load. + * + * @param y Starting y position of block to load. + * + * @return true on success, false on error. + * + * @note x and y are zero based relative to the upper left corner so any + * sub image offset should be subtracted off. + */ + bool loadBlock(ossim_uint32 x, ossim_uint32 y); + + /** + * @param x Horizontal upper left pixel position of the requested block. + * + * @param y Vertical upper left pixel position of the requested block. + * + * @param band Band of block. Only relative with IMODES that have bands + * in separate blocks. + * + * @return true if the stream position was settable and false otherwise. + */ + bool getPosition(std::streampos& position, + ossim_uint32 x, + ossim_uint32 y, + ossim_uint32 band) const; + + /** + * @return the total number of blocks for the current entry. + * + * @note For band separated blocks, all bands will be counted as on block. + */ + ossim_uint32 getNumberOfBlocks() const; + + /** + * @return The number of bytes to get from one block band to the next band. + */ + std::streampos getBandOffset() const; + + /** + * @return The number of bytes to get from one block to the next block. + */ + std::streampos getBlockOffset() const; + + + void explodePackedBits(ossimRefPtr<ossimImageData> packedBuffer)const; + + void convertTransparentToNull(ossimRefPtr<ossimImageData> tile)const; + + virtual double getMinPixelValue(ossim_uint32 band=0)const; + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + virtual double getNullPixelValue(ossim_uint32 band=0)const; + ossim_uint32 getPartialReadSize(const ossimIpt& blockOrigin)const; + bool isVqCompressed(const ossimString& compressionCode)const; + void vqUncompress(ossimRefPtr<ossimImageData> destination, + ossim_uint8* source); + + void lutUncompress(ossimRefPtr<ossimImageData> destination, + ossim_uint8* source); + + ossimRefPtr<ossimImageData> theTile; + ossimRefPtr<ossimImageData> theCacheTile; + ossimNitfFile* theNitfFile; + vector<ossimNitfImageHeader*> theNitfImageHeader; + ReadMode theReadMode; + ossimScalarType theScalarType; + bool theSwapBytesFlag; + ossim_uint32 theNumberOfInputBands; + ossim_uint32 theNumberOfOutputBands; + ossim_uint32 theBlockSizeInBytes; + ossim_uint32 theReadBlockSizeInBytes; + ossim_uint32 theNumberOfImages; + ossim_uint32 theCurrentEntry; + ossimIrect theImageRect; + ifstream theFileStr; + vector<ossim_uint32> theOutputBandList; + ossimIpt theCacheSize; + ossimInterleaveType theCacheTileInterLeaveType; + bool theCacheEnabledFlag; + std::vector<ossim_uint32> theEntryList; + ossimAppFixedTileCache::ossimAppFixedCacheId theCacheId; + bool thePackedBitsFlag; + ossimIrect theBlockImageRect; + ossim_uint8* theCompressedBuf; +TYPE_DATA +}; + +#endif /* #ifndef ossimNitfTileSource_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/nitf/ossimNitfWriter.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/nitf/ossimNitfWriter.cpp new file mode 100644 index 0000000000..3587cab9a9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/nitf/ossimNitfWriter.cpp @@ -0,0 +1,1045 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimNitfWriter.cpp,v 1.41 2006/01/06 16:46:46 dburken Exp $ +#include <algorithm> +#include <sstream> +#include <iomanip> +#include <tiffio.h> +#include <imaging/formats/nitf/ossimNitfWriter.h> +#include <base/common/ossimDate.h> +#include <base/common/ossimPreferences.h> +#include <base/common/ossimRefPtr.h> +#include <base/common/ossimTrace.h> +#include <base/misc/ossimEndian.h> +#include <projections/ossimProjection.h> +#include <projections/ossimRpcSolver.h> +#include <projections/map_projections/ossimUtmProjection.h> +#include <projections/map_projections/ossimMapProjectionInfo.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <imaging/tile_sources/ossimRectangleCutFilter.h> +#include <base/property/ossimProperty.h> +#include <base/property/ossimContainerProperty.h> +#include <base/property/ossimStringProperty.h> +#include <base/property/ossimNumericProperty.h> +#include <base/property/ossimBooleanProperty.h> +#include <support_data/nitf/ossimNitfGeoPositioningTag.h> +#include <support_data/nitf/ossimNitfLocalGeographicTag.h> +#include <support_data/nitf/ossimNitfLocalCartographicTag.h> +#include <support_data/nitf/ossimNitfProjectionParameterTag.h> +#include <support_data/nitf/ossimNitfNameConversionTables.h> +#include <support_data/nitf/ossimNitfBlockaTag.h> + +RTTI_DEF1(ossimNitfWriter, "ossimNitfWriter", ossimImageFileWriter); + +static ossimTrace traceDebug(ossimString("ossimNitfWriter:debug")); + +ossimNitfWriter::ossimNitfWriter(const ossimFilename& filename, + ossimImageSource* inputSource) + : ossimImageFileWriter(filename, inputSource, NULL), + theOutputStream(NULL), + theFileHeader(), + theImageHeader(), + theEnableRpcbTagFlag(false), + theEnableBlockaTagFlag(true) +{ + //--- + // Since the internal nitf tags are not very accurate, write an external + // geometry out as default behavior. Users can disable this via the + // property interface or keyword list. + //--- + setWriteExternalGeometryFlag(true); + + theFileHeader = new ossimNitfFileHeaderV2_1; + theImageHeader = new ossimNitfImageHeaderV2_1; + theOutputImageType = "nitf_block_band_separate"; +} + +ossimNitfWriter::~ossimNitfWriter() +{ + //--- + // This looks like a leak but it's not as both of these are ossimRefPtr's. + //--- + theFileHeader=NULL; + theImageHeader=NULL; + + close(); +} + +bool ossimNitfWriter::isOpen()const +{ + return (theOutputStream != NULL); +} + +bool ossimNitfWriter::open() +{ + if(isOpen()) + { + close(); + } + theOutputStream = new std::ofstream; + theOutputStream->open(theFilename.c_str(), ios::out|ios::binary); + + return theOutputStream->good(); +} + +void ossimNitfWriter::close() +{ + if(theOutputStream) + { + theOutputStream->close(); + delete theOutputStream; + theOutputStream = (std::ofstream*)NULL; + } +} + +bool ossimNitfWriter::writeFile() +{ + if(!theInputConnection->isMaster()) + { + theInputConnection->slaveProcessTiles(); + + return true; + } + + open(); + + if (!isOpen()) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimNitfWriter::writeFile ERROR:" + << " Could not open! Returning..." + << std::endl; + } + + return false; + } + + // Write out the geometry info. + writeGeometry(); + + // addStandardTags(); + + bool result = false; + if((theOutputImageType == "nitf_block_band_separate")|| + (theOutputImageType == "image/nitf")) + { + result = writeBlockBandSeparate(); + } + else if(theOutputImageType == "nitf_block_band_sequential") + { + result = writeBlockBandSequential(); + } + + close(); + + return result; +} + +void ossimNitfWriter::getImageTypeList(std::vector<ossimString>& imageTypeList)const +{ + imageTypeList.push_back(ossimString("nitf_block_band_separate")); + imageTypeList.push_back(ossimString("nitf_block_band_sequential")); +} + +void ossimNitfWriter::setProperty(ossimRefPtr<ossimProperty> property) +{ + if(!property) return; + + ossimString name = property->getName(); + + if(name == "file_header") + { + ossimContainerProperty* containerProperty = PTR_CAST(ossimContainerProperty, + property.get()); + if(containerProperty) + { + std::vector<ossimRefPtr<ossimProperty> > propertyList; + containerProperty->getPropertyList(propertyList); + theFileHeader->setProperties(propertyList); + } + } + else if(name == "image_header") + { + ossimContainerProperty* containerProperty = PTR_CAST(ossimContainerProperty, + property.get()); + if(containerProperty) + { + std::vector<ossimRefPtr<ossimProperty> > propertyList; + containerProperty->getPropertyList(propertyList); + theImageHeader->setProperties(propertyList); + } + } + else if (name == "enable_rpcb_tag") + { + ossimBooleanProperty* boolProperty = PTR_CAST(ossimBooleanProperty, + property.get()); + if (boolProperty) + { + theEnableRpcbTagFlag = boolProperty->getBoolean(); + } + } + else if (name == "enable_blocka_tag") + { + ossimBooleanProperty* boolProperty = PTR_CAST(ossimBooleanProperty, + property.get()); + if (boolProperty) + { + theEnableBlockaTagFlag = boolProperty->getBoolean(); + } + } + else + { + ossimImageFileWriter::setProperty(property); + } +} + +ossimRefPtr<ossimProperty> ossimNitfWriter::getProperty(const ossimString& name)const +{ + ossimRefPtr<ossimProperty> result = NULL; + + if(name == "file_header") + { + ossimContainerProperty* container = new ossimContainerProperty(name); + std::vector<ossimRefPtr<ossimProperty> > propertyList; + + theFileHeader->getPropertyList(propertyList); + container->addChildren(propertyList); + + result = container; + } + else if(name == "image_header") + { + ossimContainerProperty* container = new ossimContainerProperty(name); + std::vector<ossimRefPtr<ossimProperty> > propertyList; + + theImageHeader->getPropertyList(propertyList); + container->addChildren(propertyList); + + result = container; + } + else if(name == "enable_rpcb_tag") + { + ossimBooleanProperty* boolProperty = + new ossimBooleanProperty(name, theEnableRpcbTagFlag); + + result = boolProperty; + } + else if(name == "enable_blocka_tag") + { + ossimBooleanProperty* boolProperty = + new ossimBooleanProperty(name, theEnableBlockaTagFlag); + + result = boolProperty; + } + else + { + return ossimImageFileWriter::getProperty(name); + } + + return result; +} + +void ossimNitfWriter::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + ossimImageFileWriter::getPropertyNames(propertyNames); + + propertyNames.push_back("file_header"); + propertyNames.push_back("image_header"); + propertyNames.push_back("enable_rpcb_tag"); + propertyNames.push_back("enable_blocka_tag"); +} + +bool ossimNitfWriter::writeBlockBandSeparate() +{ + ossimScalarType scalarType = theInputConnection->getOutputScalarType(); + ossim_uint32 byteSize = ossimGetScalarSizeInBytes(scalarType); + ossimIrect rect = theInputConnection->getBoundingRect(); + ossim_uint32 bands = theInputConnection->getNumberOfOutputBands(); + ossim_uint32 idx = 0; + ossim_uint64 headerStart = (ossim_uint64)theOutputStream->tellp(); + + ossimNitfImageInfoRecordV2_1 imageInfoRecord; + imageInfoRecord.setSubheaderLength(439); // ok if no tags + imageInfoRecord.setImageLength(bands*byteSize*rect.width()*rect.height()); + + + ossimString pixelType = "INT"; + ossim_uint32 bitsPerPixel = 8; + ossim_uint32 actualBitsPerPixel = 8; + switch(scalarType) + { + case OSSIM_UCHAR: + { + // already set to this type by default + break; + } + case OSSIM_USHORT11: + { + actualBitsPerPixel = 11; + bitsPerPixel = 16; + break; + } + case OSSIM_USHORT16: + { + actualBitsPerPixel = 16; + bitsPerPixel = 16; + break; + } + case OSSIM_SSHORT16: + { + actualBitsPerPixel = 16; + bitsPerPixel = 16; + pixelType = "SI"; + break; + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + actualBitsPerPixel = 32; + bitsPerPixel = 32; + pixelType = "R"; + break; + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + actualBitsPerPixel = 64; + bitsPerPixel = 64; + pixelType = "R"; + break; + } + default: + { + // ERROR + return false; + } + } + ossimDate currentDate; + + theFileHeader->setDate(currentDate); + theFileHeader->addImageInfoRecord(imageInfoRecord); + theFileHeader->writeStream(*theOutputStream); // this makes space for the file header; it is written again at the end of this method with updated values + + // need a better way to get the length. This should be queried on the header before writing + // + ossim_uint64 headerLength = ((ossim_uint64)theOutputStream->tellp() - headerStart) /* + 1 */; + + ossimString representation; + theImageHeader->setActualBitsPerPixel(actualBitsPerPixel); + theImageHeader->setBitsPerPixel(bitsPerPixel); + theImageHeader->setPixelType(pixelType); + theImageHeader->setNumberOfBands(bands); + theImageHeader->setImageMode('B');// blocked + theImageHeader->setNumberOfRows(rect.height()); + theImageHeader->setNumberOfCols(rect.width()); + + ossimIpt blockSize(64, 64); + ossim_uint32 blocksHorizontal = (ossim_uint32)ceil(((double)rect.width()/(double)blockSize.x)); + ossim_uint32 blocksVertical = (ossim_uint32)ceil(((double)rect.height()/(double)blockSize.y)); + +#if 0 + + ossimKeywordlist kwl; + theInputConnection->getImageGeometry(kwl); + ossimRefPtr<ossimProjection> proj = ossimProjectionFactoryRegistry::instance()->createProjection(kwl); + + +// while((ceil(((double)rect.width()/(double)blockSize.x)) < 2) && +// (blockSize.x > 4)) +// { +// blockSize.x >>= 1; +// blockSize.y >>= 1; +// } + + /* + * Geo encode the image using the simple igeolo field for NITF. + */ + if(proj.valid()) + { + ossimUtmProjection* utmProj = PTR_CAST(ossimUtmProjection, proj.get()); + if(utmProj) + { + ossimMapProjectionInfo mapInfo(utmProj, + rect); + mapInfo.setPixelType(OSSIM_PIXEL_IS_AREA); + + ossimDpt ul = mapInfo.ulEastingNorthingPt(); + ossimDpt ur = mapInfo.urEastingNorthingPt(); + ossimDpt lr = mapInfo.lrEastingNorthingPt(); + ossimDpt ll = mapInfo.llEastingNorthingPt(); + + if(utmProj->getHemisphere() == 'N') + { + theImageHeader->setUtmNorth(utmProj->getZone(), ul, ur, lr, ll); + } + else + { + theImageHeader->setUtmSouth(utmProj->getZone(), ul, ur, lr, ll); + } + } + else + { + ossimMapProjection* tempProj = PTR_CAST(ossimMapProjection, + proj.get()); + if(tempProj) + { + ossimMapProjectionInfo mapInfo(tempProj, + rect); + + mapInfo.setPixelType(OSSIM_PIXEL_IS_AREA); + ossimGpt ul = mapInfo.ulGroundPt(); + ossimGpt ur = mapInfo.urGroundPt(); + ossimGpt lr = mapInfo.lrGroundPt(); + ossimGpt ll = mapInfo.llGroundPt(); + theImageHeader->setGeographicLocationDms(ul, ur, lr, ll); + } + else + { + ossimGpt ul; + ossimGpt ur; + ossimGpt lr; + ossimGpt ll; + proj->lineSampleToWorld(rect.ul(), ul); + proj->lineSampleToWorld(rect.ur(), ur); + proj->lineSampleToWorld(rect.lr(), lr); + proj->lineSampleToWorld(rect.ll(), ll); + theImageHeader->setGeographicLocationDms(ul, ur, lr, ll); + } + } + } + +#endif + + if((bands == 3)&& + (scalarType == OSSIM_UCHAR)) + { + theImageHeader->setRepresentation("RGB"); + theImageHeader->setCategory("VIS"); + } + else if(bands == 1) + { + theImageHeader->setRepresentation("MONO"); + theImageHeader->setCategory("MS"); + } + else + { + theImageHeader->setRepresentation("MULTI"); + theImageHeader->setCategory("MS"); + } + + theImageHeader->setBlocksPerRow(blocksHorizontal); + theImageHeader->setBlocksPerCol(blocksVertical); + theImageHeader->setNumberOfPixelsPerBlockRow(blockSize.x); + theImageHeader->setNumberOfPixelsPerBlockCol(blockSize.y); +// theImageHeader->setNumberOfRows(blockSize.y*blocksVertical); +// theImageHeader->setNumberOfCols(blockSize.x*blocksHorizontal); + theImageHeader->setNumberOfRows(rect.height()); + theImageHeader->setNumberOfCols(rect.width()); + + ossimNitfImageBandV2_1 bandInfo; + for(idx = 0; idx < bands; ++idx) + { + std::ostringstream out; + + out << std::setfill('0') + << std::setw(2) + << idx; + + bandInfo.setBandRepresentation(out.str().c_str()); + theImageHeader->setBandInfo(idx, + bandInfo); + } + + int imageHeaderStart = theOutputStream->tellp(); + theImageHeader->writeStream(*theOutputStream); + int imageHeaderEnd = theOutputStream->tellp(); + int imageHeaderSize = imageHeaderEnd - imageHeaderStart; + + theInputConnection->setTileSize(blockSize); + ossim_uint32 numberOfTiles = theInputConnection->getNumberOfTiles(); + theInputConnection->setToStartOfSequence(); + ossimRefPtr<ossimImageData> data = theInputConnection->getNextTile(); + ossim_uint32 tileNumber = 1; + ossimEndian endian; + + + while( data.valid() && !needsAborting()) + { + if(endian.getSystemEndianType() == OSSIM_LITTLE_ENDIAN) + { + switch(data->getScalarType()) + { + case OSSIM_USHORT16: + case OSSIM_USHORT11: + { + endian.swap((ossim_uint16*)data->getBuf(), + data->getWidth()*data->getHeight()*data->getNumberOfBands()); + break; + } + case OSSIM_SSHORT16: + { + endian.swap((ossim_sint16*)data->getBuf(), + data->getWidth()*data->getHeight()*data->getNumberOfBands()); + break; + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + endian.swap((ossim_float32*)data->getBuf(), + data->getWidth()*data->getHeight()*data->getNumberOfBands()); + break; + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + endian.swap((ossim_float64*)data->getBuf(), + data->getWidth()*data->getHeight()*data->getNumberOfBands()); + break; + } + default: + break; + } + } + + theOutputStream->write((char*)(data->getBuf()), + data->getSizeInBytes()); + + setPercentComplete(((double)tileNumber / (double)numberOfTiles) * 100); + + if(!needsAborting()) + { + data = theInputConnection->getNextTile(); + } + ++tileNumber; + } + ossim_uint64 pos = theOutputStream->tellp(); + + /* + * Need to change the way I compute file length and header length later + * We need to figure out a better way to compute. + */ + theFileHeader->setFileLength(pos); + theFileHeader->setHeaderLength(headerLength); + theOutputStream->seekp(0, ios::beg); + imageInfoRecord.setSubheaderLength(imageHeaderSize); + theFileHeader->replaceImageInfoRecord(0, imageInfoRecord); + theFileHeader->writeStream(*theOutputStream); + + return true; +} + +bool ossimNitfWriter::writeBlockBandSequential() +{ + ossimScalarType scalarType = theInputConnection->getOutputScalarType(); + ossim_uint32 byteSize = ossimGetScalarSizeInBytes(scalarType); + ossimIrect rect = theInputConnection->getBoundingRect(); + ossim_uint32 bands = theInputConnection->getNumberOfOutputBands(); + ossim_uint32 idx = 0; + ossim_uint64 headerStart = (ossim_uint64)theOutputStream->tellp(); + + ossimIpt blockSize(64, 64); + +// while((ceil(((double)rect.width()/(double)blockSize.x)) < 2) && +// (blockSize.x > 4)) +// { +// blockSize.x >>= 1; +// blockSize.y >>= 1; +// } + ossim_uint32 blocksHorizontal = theInputConnection->getNumberOfTilesHorizontal(); + ossim_uint32 blocksVertical = theInputConnection->getNumberOfTilesVertical(); + theInputConnection->setTileSize(blockSize); + ossim_uint32 numberOfTiles = theInputConnection->getNumberOfTiles(); + theInputConnection->setToStartOfSequence(); + + ossimNitfImageInfoRecordV2_1 imageInfoRecord; + imageInfoRecord.setSubheaderLength(439); + imageInfoRecord.setImageLength(bands*byteSize*rect.width()*rect.height()); + + + ossimString pixelType = "INT"; + ossim_uint32 bitsPerPixel = 8; + switch(scalarType) + { + case OSSIM_UCHAR: + { + // already set to this type by default + break; + } + case OSSIM_USHORT16: + case OSSIM_USHORT11: + { + bitsPerPixel = 16; + break; + } + case OSSIM_SSHORT16: + { + bitsPerPixel = 16; + pixelType = "SI"; + break; + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + bitsPerPixel = 32; + pixelType = "R"; + break; + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + bitsPerPixel = 64; + pixelType = "R"; + break; + } + default: + { + // ERROR + return false; + } + } + ossimDate currentDate; + + theFileHeader->setDate(currentDate); + theFileHeader->addImageInfoRecord(imageInfoRecord); + theFileHeader->writeStream(*theOutputStream); + + // need a better way to get the length. This should be queried on the header before writing + // + ossim_uint64 headerLength = ((ossim_uint64)theOutputStream->tellp() - headerStart) /* + 1 */; + + ossimString representation; + theImageHeader->setBitsPerPixel(bitsPerPixel); + theImageHeader->setPixelType(pixelType); + theImageHeader->setNumberOfBands(bands); + theImageHeader->setImageMode('S');// blocked + theImageHeader->setNumberOfRows(rect.height()); + theImageHeader->setNumberOfCols(rect.width()); + +#if 0 + + ossimKeywordlist kwl; + theInputConnection->getImageGeometry(kwl); + ossimRefPtr<ossimProjection> proj = ossimProjectionFactoryRegistry::instance()->createProjection(kwl); + + /* + * Geo encode the image using the simple igeolo field for NITF. + */ + if(proj.valid()) + { + ossimUtmProjection* utmProj = PTR_CAST(ossimUtmProjection, proj.get()); + if(utmProj) + { + ossimDpt ul; + ossimDpt ur; + ossimDpt lr; + ossimDpt ll; + + utmProj->lineSampleToEastingNorthing(rect.ul(), ul); + utmProj->lineSampleToEastingNorthing(rect.ur(), ur); + utmProj->lineSampleToEastingNorthing(rect.lr(), lr); + utmProj->lineSampleToEastingNorthing(rect.ll(), ll); + if(utmProj->getHemisphere() == 'N') + { + theImageHeader->setUtmNorth(utmProj->getZone(), ul, ur, lr, ll); + } + else + { + theImageHeader->setUtmSouth(utmProj->getZone(), ul, ur, lr, ll); + } + } + else + { + ossimGpt ul; + ossimGpt ur; + ossimGpt lr; + ossimGpt ll; + proj->lineSampleToWorld(rect.ul(), ul); + proj->lineSampleToWorld(rect.ur(), ur); + proj->lineSampleToWorld(rect.lr(), lr); + proj->lineSampleToWorld(rect.ll(), ll); + theImageHeader->setGeographicLocationDms(ul, ur, lr, ll); + } + } + +#endif + + if((bands == 3)&& + (scalarType == OSSIM_UCHAR)) + { + theImageHeader->setRepresentation("RGB"); + theImageHeader->setCategory("VIS"); + } + else if(bands == 1) + { + theImageHeader->setRepresentation("MONO"); + theImageHeader->setCategory("MS"); + } + else + { + theImageHeader->setRepresentation("MULTI"); + theImageHeader->setCategory("MS"); + } + theImageHeader->setBlocksPerRow(blocksHorizontal); + theImageHeader->setBlocksPerCol(blocksVertical); + theImageHeader->setNumberOfPixelsPerBlockRow(blockSize.x); + theImageHeader->setNumberOfPixelsPerBlockCol(blockSize.y); + theImageHeader->setNumberOfRows(blockSize.y*blocksVertical); + theImageHeader->setNumberOfCols(blockSize.x*blocksHorizontal); + + ossimNitfImageBandV2_1 bandInfo; + for(idx = 0; idx < bands; ++idx) + { + std::ostringstream out; + + out << std::setfill('0') + << std::setw(2) + << idx; + + bandInfo.setBandRepresentation(out.str().c_str()); + theImageHeader->setBandInfo(idx, + bandInfo); + } + + theImageHeader->writeStream(*theOutputStream); + ossimIpt ul = rect.ul(); + ossimRefPtr<ossimImageData> data = theInputConnection->getNextTile(); + ossim_uint32 tileNumber = 0; + ossimEndian endian; + + // get the start to the first band of data block + // + ossim_uint64 streamOffset = theOutputStream->tellp(); + + // holds the total pixels to the next band + + ossim_uint32 blockSizeInBytes = blockSize.x*blockSize.y*ossimGetScalarSizeInBytes(data->getScalarType()); + ossim_uint64 bandOffsetInBytes = (blockSizeInBytes*blocksHorizontal*blocksVertical); + + bool needSwapping = endian.getSystemEndianType() == OSSIM_LITTLE_ENDIAN; + while(data.valid() && !needsAborting()) + { + if(needSwapping) + { + switch(data->getScalarType()) + { + case OSSIM_USHORT16: + case OSSIM_USHORT11: + { + endian.swap((ossim_uint16*)data->getBuf(), + data->getWidth()*data->getHeight()*data->getNumberOfBands()); + break; + } + case OSSIM_SSHORT16: + { + endian.swap((ossim_sint16*)data->getBuf(), + data->getWidth()*data->getHeight()*data->getNumberOfBands()); + break; + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + endian.swap((ossim_float32*)data->getBuf(), + data->getWidth()*data->getHeight()*data->getNumberOfBands()); + break; + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + endian.swap((ossim_float64*)data->getBuf(), + data->getWidth()*data->getHeight()*data->getNumberOfBands()); + break; + } + default: + break; + } + } + + for(idx = 0; idx < bands; ++idx) + { + theOutputStream->seekp(streamOffset+ // start of image stream + tileNumber*blockSizeInBytes + // start of block for band separate output + bandOffsetInBytes*idx, // which band offset is it + ios::beg); + + theOutputStream->write((char*)(data->getBuf(idx)), + blockSizeInBytes); + } + ++tileNumber; + + setPercentComplete(((double)tileNumber / (double)numberOfTiles) * 100); + + if(!needsAborting()) + { + data = theInputConnection->getNextTile(); + } + } + ossim_uint64 pos = theOutputStream->tellp(); + + /* + * Need to change the way I compute file length and header length later + * We need to figure out a better way to compute. + */ + theFileHeader->setFileLength(pos); + theFileHeader->setHeaderLength(headerLength); + theOutputStream->seekp(0, ios::beg); + theFileHeader->writeStream(*theOutputStream); + + return true; +} + + +void ossimNitfWriter::addRegisteredTag( + ossimRefPtr<ossimNitfRegisteredTag> registeredTag) +{ + ossimNitfTagInformation tagInfo; + tagInfo.setTagData(registeredTag.get()); + theImageHeader->addTag(tagInfo); +} + +void ossimNitfWriter::writeGeometry() +{ + if ( (theImageHeader.valid() == false) || !theInputConnection ) + { + return; + } + + ossimKeywordlist kwl; + theInputConnection->getImageGeometry(kwl); + ossimRefPtr<ossimProjection> proj = + ossimProjectionFactoryRegistry::instance()->createProjection(kwl); + + if(proj.valid() == false) + { + // No projection info. + return; + } + + // Get the requested bounding rectangles. + ossimIrect rect = theInputConnection->getBoundingRect(); + + // See if it's a map projection; else, a sensor model. + ossimMapProjection* mapProj = PTR_CAST(ossimMapProjection, proj.get()); + if (mapProj) + { + // Use map info to get the corners. + ossimMapProjectionInfo mapInfo(mapProj, rect); + mapInfo.setPixelType(OSSIM_PIXEL_IS_AREA); + + // See if it's utm. + ossimUtmProjection* utmProj = PTR_CAST(ossimUtmProjection, proj.get()); + if(utmProj) + { + ossimDpt ul = mapInfo.ulEastingNorthingPt(); + ossimDpt ur = mapInfo.urEastingNorthingPt(); + ossimDpt lr = mapInfo.lrEastingNorthingPt(); + ossimDpt ll = mapInfo.llEastingNorthingPt(); + + if(utmProj->getHemisphere() == 'N') + { + theImageHeader->setUtmNorth(utmProj->getZone(), ul, ur, lr, ll); + } + else + { + theImageHeader->setUtmSouth(utmProj->getZone(), ul, ur, lr, ll); + } + } + else + { + ossimGpt ul = mapInfo.ulGroundPt(); + ossimGpt ur = mapInfo.urGroundPt(); + ossimGpt lr = mapInfo.lrGroundPt(); + ossimGpt ll = mapInfo.llGroundPt(); + theImageHeader->setGeographicLocationDms(ul, ur, lr, ll); + } + + if (theEnableBlockaTagFlag) + { + addBlockaTag(mapInfo); + } + } + + if (theEnableRpcbTagFlag) + { + addRpcbTag(rect, proj); + } +} + +#if 0 +void ossimNitfWriter::addStandardTags() +{ + + if(!theInputConnection) + { + return; + } + + // commenting this out for now. For some reason the pixels + // are off when I add this tag. I checked the parsing and it + // appears to be the correct length??? So, I am not sure + // why we are off when reading the output back in. + // + // first lets do the projection tag. I REALLY need to add + // parameter support soon or this tag is useless. + // + ossimKeywordlist kwl; + theInputConnection->getImageGeometry(kwl); + ossimRefPtr<ossimProjection> proj = ossimProjectionFactoryRegistry::instance()->createProjection(kwl); + ossimNitfNameConversionTables table; + ossimMapProjection* mapProj = PTR_CAST(ossimMapProjection, proj.get()); + ossimNitfTagInformation tagInfo; + + if(mapProj) + { + + if(!PTR_CAST(ossimUtmProjection, mapProj)) + { + ossimRefPtr<ossimNitfProjectionParameterTag> parameterTag = new ossimNitfProjectionParameterTag; + + ossimString nitfCode = table.convertMapProjectionNameToNitfCode(proj->getClassName()); + ossimString nitfName = table.convertNitfCodeToNitfProjectionName(nitfCode); + + parameterTag->setName(nitfName); + parameterTag->setCode(nitfCode); + parameterTag->setFalseX(mapProj->getFalseEasting()); + parameterTag->setFalseY(mapProj->getFalseNorthing()); + + tagInfo.setTagData(parameterTag.get()); + theImageHeader->addTag(tagInfo); + } + } +} +#endif + +void ossimNitfWriter::addBlockaTag(ossimMapProjectionInfo& mapInfo) +{ + if (!theImageHeader) + { + return; + } + + // Capture the current pixel type. + ossimPixelType originalPixelType = mapInfo.getPixelType(); + + // This tag wants corners as area: + mapInfo.setPixelType(OSSIM_PIXEL_IS_AREA); + + // Stuff the blocka tag which has six digit precision. + ossimNitfBlockaTag* blockaTag = new ossimNitfBlockaTag(); + + // Set the block number. + blockaTag->setBlockInstance(1); + + // Set the number of lines. + blockaTag->setLLines(mapInfo.linesPerImage()); + + // Set first row, first column. + blockaTag->setFrfcLoc(ossimDpt(mapInfo.ulGroundPt())); + + // Set first row, last column. + blockaTag->setFrlcLoc(ossimDpt(mapInfo.urGroundPt())); + + // Set last row, last column. + blockaTag->setLrlcLoc(ossimDpt(mapInfo.lrGroundPt())); + + // Set last row, first column. + blockaTag->setLrfcLoc(ossimDpt(mapInfo.llGroundPt())); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimNitfWriter::writeGeometry DEBUG:" + << "\nBLOCKA Tag:" << *((ossimObject*)(blockaTag)) + << std::endl; + } + + // Add the tag to the header. + ossimRefPtr<ossimNitfRegisteredTag> blockaTagRp = blockaTag; + ossimNitfTagInformation blockaTagInfo(blockaTagRp); + theImageHeader->addTag(blockaTagInfo); + + // Reset the pixel type to original value + mapInfo.setPixelType(originalPixelType); +} + +void ossimNitfWriter::addRpcbTag(const ossimIrect& rect, + ossimRefPtr<ossimProjection> proj) +{ + if (!proj.valid()) + { + return; + } + + bool useElevation = false; + + if (PTR_CAST(ossimMapProjection, proj.get())) + { + // If we're already map projected turn the elevation off. + useElevation = false; + } + + // Make an rpc solver. + ossimRpcSolver rs(useElevation); + + // Compute the coefficients. + rs.solveCoefficients(ossimDrect(rect), + *proj.get(), + 64, + 64); + + // Add the tag. + ossimRefPtr<ossimNitfRegisteredTag> tag = rs.getNitfRpcBTag(); + ossimNitfTagInformation tagInfo(tag); + theImageHeader->addTag(tagInfo); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimNitfWriter::addRpcbTag DEBUG:" + << "\nRPCB Tag:" << *((ossimObject*)(tag.get())) + << "\nProjection:" << std::endl; + + proj->print(ossimNotify(ossimNotifyLevel_DEBUG)); + + ossimNotify(ossimNotifyLevel_DEBUG) + << "\nRect: " << rect << std::endl; + } +} + +bool ossimNitfWriter::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + kwl.add(prefix, "enable_rpcb_tag", theEnableRpcbTagFlag, true); + kwl.add(prefix, "enable_blocka_tag", theEnableBlockaTagFlag, true); + + return ossimImageFileWriter::saveState(kwl, prefix); +} + +bool ossimNitfWriter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + // Look for the rpcb enable flag keyword. + const char* lookup = kwl.find(prefix, "enable_rpcb_tag"); + if(lookup) + { + ossimString os = lookup; + theEnableRpcbTagFlag = os.toBool(); + } + + // Look for the blocka enable flag keyword. + lookup = kwl.find(prefix, "enable_blocka_tag"); + if(lookup) + { + ossimString os = lookup; + theEnableBlockaTagFlag = os.toBool(); + } + + return ossimImageFileWriter::loadState(kwl, prefix); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/nitf/ossimNitfWriter.h b/Utilities/OSSIM/ossim_core/imaging/formats/nitf/ossimNitfWriter.h new file mode 100644 index 0000000000..d8b1d4db07 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/nitf/ossimNitfWriter.h @@ -0,0 +1,166 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimNitfWriter.h,v 1.17 2006/01/06 16:46:46 dburken Exp $ +#ifndef ossimNitfWriter_HEADER +#define ossimNitfWriter_HEADER + +#include <fstream> +#include <imaging/formats/ossimImageFileWriter.h> +#include <base/data_types/ossimKeywordlist.h> +#include <projections/map_projections/ossimMapProjectionInfo.h> +#include <base/common/ossimRgbLutDataObject.h> +#include <base/common/ossimRefPtr.h> +#include <support_data/nitf/ossimNitfFileHeaderV2_1.h> +#include <support_data/nitf/ossimNitfImageHeaderV2_1.h> + +class ossimProjection; + +class OSSIM_DLL ossimNitfWriter : public ossimImageFileWriter +{ +public: + ossimNitfWriter(const ossimFilename& filename=ossimFilename(""), + ossimImageSource* inputSource = (ossimImageSource*)NULL); + virtual ~ossimNitfWriter(); + virtual bool isOpen()const; + virtual bool open(); + virtual void close(); + + /** + * void getImageTypeList(std::vector<ossimString>& imageTypeList)const + * + * Appends this writer image types to list "imageTypeList". + * + * This writer has the following types: + * nitf_block_band_separate + * nitf_block_band_sequential + * + * @param imageTypeList stl::vector<ossimString> list to append to. + */ + virtual void getImageTypeList(std::vector<ossimString>& imageTypeList)const; + + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual ossimRefPtr<ossimProperty> getProperty( + const ossimString& name)const; + + /** + * @param propertyNames Array to populate with property names. + * + * @note The following names are handled: + * file_header + * image_header + * enable_rpcb_tag + * enable_blocka_tag + */ + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + + void addRegisteredTag(ossimRefPtr<ossimNitfRegisteredTag> registeredTag); + + /** + * Saves the state of the writer to kwl with prefix then calls + * base class ossimImageFileWriter::saveState + * + * @param kwl Keyword list to save to. + * + * @param prefix Usually something like: "object2." + + * @return true on success, false on failure. + * + * Keywords saved by saveState: + * + * enable_rpcb_tag: true + * + * enable_blocka_tag: true + */ + virtual bool saveState(ossimKeywordlist& kwl, const char* prefix=0) const; + + /** + * Initializes the state of the writer from kwl with prefix then calls + * base class ossimImageFileWriter::loadState + * + * @param kwl Keyword list to initialize from. + * + * @param prefix Usually something like: "object2." + + * @return true on success, false on failure. + * + * Keywords picked up by loadState: + * + * enable_rpcb_tag: true + * + * enable_blocka_tag: true + */ + virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix=0); + +protected: + + /** + * @return true on success false on error. + */ + virtual bool writeFile(); + + /** + * write out block band separate + * + * @return true on success and false on error + */ + virtual bool writeBlockBandSeparate(); + + /** + * Outputs in band sequential format. Band 1 is followed by band + * 2, ... etc. + */ + virtual bool writeBlockBandSequential(); + + /** + * Populates tags with geometry info from projection. Will write an + * rpcb tag if theEnableRpcbTagFlag if set to true. + */ + void writeGeometry(); + + /** Currently disabled... */ + // virtual void addStandardTags(); + + /** + * Adds the BLOCKA tag. + * + * @param mapInfo ossimMapProjectionInfo to use to set tag with. + * + * @note Currently only used with map projected images. + */ + void addBlockaTag(ossimMapProjectionInfo& mapInfo); + + /** + * Adds the RPC00B tag. + * + * @param rect Requested rectangle of image to write. + * + * @param proj The output projection. + */ + void addRpcbTag(const ossimIrect& rect, + ossimRefPtr<ossimProjection> proj); + + + std::ofstream* theOutputStream; + + ossimRefPtr<ossimNitfFileHeaderV2_1> theFileHeader; + ossimRefPtr<ossimNitfImageHeaderV2_1> theImageHeader; + + /** If true user wants to set RPC00B tag. (DEFAULT = false) */ + bool theEnableRpcbTagFlag; + + /** + * If true user wants to set BLOCKA tag. (DEFAULT = true) + * Currently only valid for map projected images. + */ + bool theEnableBlockaTagFlag; + +TYPE_DATA +}; + +#endif /* #ifndef ossimNitfWriter_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/nitf/ossimQuickbirdNitfTileSource.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/nitf/ossimQuickbirdNitfTileSource.cpp new file mode 100644 index 0000000000..6a3a6cf9eb --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/nitf/ossimQuickbirdNitfTileSource.cpp @@ -0,0 +1,187 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +//******************************************************************* +// $Id: ossimQuickbirdNitfTileSource.cpp,v 1.12 2005/11/09 16:08:26 dburken Exp $ +#include <imaging/formats/nitf/ossimQuickbirdNitfTileSource.h> +#include <support_data/qb/ossimQuickbirdTile.h> +#include <base/common/ossimTrace.h> +#include "support_data/nitf/ossimNitfImageHeader.h" + +RTTI_DEF1(ossimQuickbirdNitfTileSource, "ossimQuickbirdNitfTileSource", ossimNitfTileSource); + +static const ossimTrace traceDebug("ossimQuickbirdNitfTileSource:debug"); + +bool ossimQuickbirdNitfTileSource::open() +{ + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimQuickbirdNitfTileSource::open(file) DEBUG: entered ..." + << std::endl; + } + + ossimFilename file = theImageFile; + file = file.replaceAllThatMatch("_R[0-9]+C[0-9]+"); + ossimQuickbirdTile tileFile; + bool openedTileFile = false; + file.setExtension("TIL"); + + if(!tileFile.open(file)) + { + file.setExtension("TIL"); + if(tileFile.open(file)) + { + openedTileFile = true; + } + else + { + file.setExtension("til"); + if(tileFile.open(file)) + { + openedTileFile = true; + } + } + } + else + { + openedTileFile = true; + } + + if(openedTileFile) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimQuickbirdNitfTileSource::open(file) DEBUG:" + << "\nOpened tile file" << std::endl; + } + + // Call the base class open... + if(!ossimNitfTileSource::open()) + { + return false; + } + + ossimQuickbirdTileInfo info; + ossimIrect tempBounds = getCurrentImageHeader()->getImageRect(); + + + tempBounds = ossimIrect(0, + 0, + tempBounds.width() - 1, + tempBounds.height() - 1); + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimQuickbirdNitfTileSource::open(file) DEBUG:" + << "\nheader rectangle = " << tempBounds << std::endl; + } + + ossimIpt ulPt; + ossimIpt urPt; + ossimIpt lrPt; + ossimIpt llPt; + + if(tileFile.getInfo(info, theImageFile.file().upcase())) + { + ulPt.makeNan(); + urPt.makeNan(); + lrPt.makeNan(); + llPt.makeNan(); + + if((info.theUlXOffset != OSSIM_INT_NAN) && + (info.theUlYOffset != OSSIM_INT_NAN)) + { + theSubImageOffset = ossimIpt(info.theUlXOffset, info.theUlYOffset); + } + else + { + theSubImageOffset = ossimIpt(0,0); + } + + ulPt = theSubImageOffset; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimQuickbirdNitfTileSource::open(file) DEBUG:" + << "\nSub image offset = " << theSubImageOffset + << std::endl; + } + + if((info.theUrXOffset != OSSIM_INT_NAN) && + (info.theUrYOffset != OSSIM_INT_NAN)) + { + urPt = ossimIpt(info.theUrXOffset, + info.theUrYOffset); + } + else + { + urPt = tempBounds.ur() + ulPt; + } + + if((info.theLrXOffset != OSSIM_INT_NAN) && + (info.theLrYOffset != OSSIM_INT_NAN)) + { + lrPt = ossimIpt(info.theLrXOffset, + info.theLrYOffset); + } + else + { + lrPt = tempBounds.lr() + ulPt; + } + + if((info.theLlXOffset != OSSIM_INT_NAN) && + (info.theLlYOffset != OSSIM_INT_NAN)) + { + llPt = ossimIpt(info.theLlXOffset, + info.theLlYOffset); + } + else + { + llPt = tempBounds.ll() + ulPt; + } + } + + //--- + // Set the base class image rectangle in case a sub image offset was + // picked up here. + //--- + setBoundingRectangle(ossimIrect(ulPt, urPt, lrPt, llPt)); + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimQuickbirdNitfTileSource::open(file) DEBUG:" + << "\nUl = " << ulPt + << "\nUr = " << urPt + << "\nLr = " << lrPt + << "\nLl = " << llPt + << "\ntheImageRect: " << getImageRectangle(0) + << "\nExiting..." + << std::endl; + } + } + else + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimQuickbirdNitfTileSource::open(file) DEBUG" + << "Not opened..." + << std::endl; + } + } + + return openedTileFile; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/nitf/ossimQuickbirdNitfTileSource.h b/Utilities/OSSIM/ossim_core/imaging/formats/nitf/ossimQuickbirdNitfTileSource.h new file mode 100644 index 0000000000..ae76023750 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/nitf/ossimQuickbirdNitfTileSource.h @@ -0,0 +1,27 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimQuickbirdNitfTileSource.h,v 1.7 2004/10/28 18:27:18 dburken Exp $ +#ifndef ossimQuickbirdNitfTileSource_HEADER +#define ossimQuickbirdNitfTileSource_HEADER +#include "ossimNitfTileSource.h" + +class ossimQuickbirdNitfTileSource : public ossimNitfTileSource +{ +public: + virtual bool open(); + + protected: + +TYPE_DATA +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/ossimImageFileWriter.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/ossimImageFileWriter.cpp new file mode 100644 index 0000000000..2a49f638b2 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/ossimImageFileWriter.cpp @@ -0,0 +1,1123 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: Frank Warmerdam (warmerdam@pobox.com) +// +// Description: +// +// Contains class declaration for ossimImageFileWriter. +//******************************************************************* +// $Id: ossimImageFileWriter.cpp,v 1.45 2005/12/27 16:09:10 dburken Exp $ + +#include <ossimConfig.h> +#include <imaging/formats/ossimImageFileWriter.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimFilename.h> +#include <base/data_types/ossimMultiResLevelHistogram.h> +#include <base/data_types/ossimMultiBandHistogram.h> +#include <base/data_types/ossimHistogram.h> +#include <base/common/ossimKeywordNames.h> +#include <base/context/ossimErrorContext.h> +#include <base/misc/lookup_tables/ossimImageTypeLut.h> +#include <imaging/formats/tiff/ossimTiffOverviewBuilder.h> +#include <imaging/factory/ossimImageHandlerRegistry.h> +#include <imaging/formats/ossimImageHandler.h> +#include <imaging/histogram/ossimHistogramWriter.h> +#include <imaging/histogram/ossimImageHistogramSource.h> +#include <imaging/metadata/ossimMetadataFileWriter.h> +#include <imaging/metadata/ossimGeomFileWriter.h> +#include <imaging/metadata/ossimEnviHeaderFileWriter.h> +#include <imaging/metadata/ossimFgdcFileWriter.h> +#include <imaging/metadata/ossimJpegWorldFileWriter.h> +#include <imaging/metadata/ossimReadmeFileWriter.h> +#include <imaging/metadata/ossimTiffWorldFileWriter.h> +#include <base/common/ossimStdOutProgress.h> +#include <base/property/ossimFilenameProperty.h> +#include <base/property/ossimBooleanProperty.h> +#include <base/common/ossimTrace.h> +#include <projections/map_projections/ossimMapProjection.h> +#include <projections/map_projections/ossimMapProjectionInfo.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> + +static ossimTrace traceDebug("ossimImageFileWriter:debug"); + +#if OSSIM_ID_ENABLED +static const char OSSIM_ID[] = "$Id: ossimImageFileWriter.cpp,v 1.45 2005/12/27 16:09:10 dburken Exp $"; +#endif + +RTTI_DEF3(ossimImageFileWriter, + "ossimImageFileWriter", + ossimImageWriter, + ossimProcessInterface, + ossimConnectableObjectListener); + +ossimImageFileWriter::ossimImageFileWriter(const ossimFilename& file, + ossimImageSource* inputSource, + ossimObject* owner) + : ossimImageWriter(owner, + 1, + 0, + true, + false), + ossimProcessInterface(), + ossimConnectableObjectListener(), + theViewController(NULL), + theProgressListener(NULL), + theFilename(file), + theOutputImageType(ossimImageTypeLut().getEntryString(OSSIM_IMAGE_TYPE_UNKNOWN)), + theWriteImageFlag(true), + theWriteOverviewFlag(false), + theWriteHistogramFlag(false), + theOverviewCompressType(COMPRESSION_NONE), + theOverviewJpegCompressQuality(75), + + theWriteEnviHeaderFlag(false), + theWriteExternalGeometryFlag(false), + theWriteFgdcFlag(false), + theWriteJpegWorldFileFlag(false), + theWriteReadmeFlag(false), + theWriteTiffWorldFileFlag(false) +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimImageFileWriter::ossimImageFileWriter entered..." + << std::endl; +#ifdef OSSIM_ID_ENABLED + ossimNotify(ossimNotifyLevel_DEBUG) + << "OSSIM_ID: " << OSSIM_ID << std::endl; +#endif + } + + theInputConnection = new ossimImageSourceSequencer(inputSource); + + // now map the sequencer to the same input + connectMyInputTo(0, inputSource); + initialize(); + + // make sure we listen to our input changes so we can change + // it for the sequencer as well. + // + ossimImageWriter::addListener((ossimConnectableObjectListener*)this); + + theInputConnection->connectMyInputTo(0, inputSource, false); + theAreaOfInterest.makeNan(); +} + +ossimImageFileWriter::~ossimImageFileWriter() +{ + if(theInputConnection) + { + delete theInputConnection; + theInputConnection = NULL; + } + theProgressListener = NULL; + removeListener((ossimConnectableObjectListener*)this); +} + +void ossimImageFileWriter::initialize() +{ + if(theInputConnection) + { + theInputConnection->initialize(); + setAreaOfInterest(theInputConnection->getBoundingRect()); + } +} + +void ossimImageFileWriter::changeSequencer(ossimImageSourceSequencer* sequencer) +{ + if(!sequencer) return; + if(theInputConnection) + { + sequencer->setAreaOfInterest(theInputConnection->getAreaOfInterest()); + } + + if(theInputConnection) + { + delete theInputConnection; + } + theInputConnection = sequencer; + theInputConnection->connectMyInputTo(0, getInput(0)); +} + + +bool ossimImageFileWriter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + ossimKeywordNames::TYPE_KW, + TYPE_NAME(this), + true); + + kwl.add(prefix, + ossimKeywordNames::FILENAME_KW, + theFilename.c_str(), + true); + + kwl.add(prefix, + "create_envi_hdr", + (ossim_uint32)theWriteEnviHeaderFlag, + true); + + kwl.add(prefix, + ossimKeywordNames::CREATE_EXTERNAL_GEOMETRY_KW, + (ossim_uint32)theWriteExternalGeometryFlag, + true); + + kwl.add(prefix, + "create_fgdc", + (ossim_uint32)theWriteFgdcFlag, + true); + + kwl.add(prefix, + "create_jpeg_world_file", + (ossim_uint32)theWriteJpegWorldFileFlag, + true); + + kwl.add(prefix, + "create_readme", + (ossim_uint32)theWriteReadmeFlag, + true); + + kwl.add(prefix, + "create_tiff_world_file", + (ossim_uint32)theWriteTiffWorldFileFlag, + true); + + kwl.add(prefix, + ossimKeywordNames::CREATE_IMAGE_KW, + (ossim_uint32)theWriteImageFlag, + true); + + kwl.add(prefix, + ossimKeywordNames::CREATE_OVERVIEW_KW, + (ossim_uint32)theWriteOverviewFlag, + true); + + kwl.add(prefix, + ossimKeywordNames::CREATE_HISTOGRAM_KW, + (ossim_uint32)theWriteHistogramFlag, + true); + + kwl.add(prefix, + ossimKeywordNames::OVERVIEW_COMPRESSION_TYPE_KW, + theOverviewCompressType, + true); + + kwl.add(prefix, + ossimKeywordNames::OVERVIEW_COMPRESSION_QUALITY_KW, + theOverviewJpegCompressQuality, + true); + + ossimImageTypeLut lut; + kwl.add(prefix, + ossimKeywordNames::IMAGE_TYPE_KW, + theOutputImageType, + true); + + return ossimSource::saveState(kwl, prefix); +} + +bool ossimImageFileWriter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + // Load the state of the base class. + bool result = ossimSource::loadState(kwl, prefix); + + // Get the filename... + const char* lookup = kwl.find(prefix, ossimKeywordNames::FILENAME_KW); + if(lookup) + { + ossimString filename = lookup; + + lookup = kwl.find(prefix, ossimKeywordNames::FILEPATH_KW); + if(lookup) + { + filename = ossimString(lookup) + filename; + } + + setFilename(filename); + } + + lookup = kwl.find(prefix, ossimKeywordNames::CREATE_EXTERNAL_GEOMETRY_KW); + if(lookup) + { + ossimString s = lookup; + theWriteExternalGeometryFlag = s.toBool(); + } + + lookup = kwl.find(prefix, "create_envi_hdr"); + if(lookup) + { + ossimString s = lookup; + theWriteEnviHeaderFlag = s.toBool(); + } + + lookup = kwl.find(prefix, "create_fgdc"); + if(lookup) + { + ossimString s = lookup; + theWriteFgdcFlag = s.toBool(); + } + + lookup = kwl.find(prefix, "create_jpeg_world_file"); + if(lookup) + { + ossimString s = lookup; + theWriteJpegWorldFileFlag = s.toBool(); + } + + lookup = kwl.find(prefix, "create_readme"); + if(lookup) + { + ossimString s = lookup; + theWriteReadmeFlag = s.toBool(); + } + + lookup = kwl.find(prefix, "create_tiff_world_file"); + if(lookup) + { + ossimString s = lookup; + theWriteTiffWorldFileFlag = s.toBool(); + } + + lookup = kwl.find(prefix, ossimKeywordNames::CREATE_IMAGE_KW); + if(lookup) + { + ossimString s = lookup; + theWriteImageFlag = s.toBool(); + } + + lookup = kwl.find(prefix, ossimKeywordNames::CREATE_OVERVIEW_KW); + if(lookup) + { + ossimString s = lookup; + theWriteOverviewFlag = s.toBool(); + } + + lookup = kwl.find(prefix, ossimKeywordNames::CREATE_HISTOGRAM_KW); + if(lookup) + { + ossimString s = lookup; + theWriteHistogramFlag = s.toBool(); + } + + lookup = kwl.find(prefix, ossimKeywordNames::OVERVIEW_COMPRESSION_TYPE_KW); + if(lookup) + { + ossimString s = lookup; + theOverviewCompressType = static_cast<ossim_uint16>(s.toUInt32()); + } + + lookup = kwl.find(prefix, ossimKeywordNames::OVERVIEW_COMPRESSION_QUALITY_KW); + if(lookup) + { + ossimString s = lookup; + theOverviewJpegCompressQuality = s.toInt32(); + } + + const char* outputImageType = kwl.find(prefix, ossimKeywordNames::IMAGE_TYPE_KW); + if(outputImageType) + { + theOutputImageType = outputImageType; + } + + if(theInputObjectList.size() != 2) + { + theInputObjectList.resize(2); + theInputListIsFixedFlag = true; + } + + theOutputListIsFixedFlag = false; + + return result; +} + +bool ossimImageFileWriter::writeOverviewFile(ossim_uint16 tiff_compress_type, + ossim_int32 jpeg_compress_quality) const +{ + if(theFilename == "") return false; + + // Get an image handler for the source file. + ossimImageHandler* ih + = ossimImageHandlerRegistry::instance()->open(theFilename); + + if (!ih) + { + if (ih) delete ih; + + // Set the error... + return false; + } + + ossimTiffOverviewBuilder ob(ih); + + if (ob.getErrorStatus() != ossimErrorCodes::OSSIM_ERROR) + { + // Give the listener to the overview builder if set. + if (theProgressListener) + { + ob.addListener(theProgressListener); + } + + // Build a new file name for the overview. + ossimFilename overview_file = theFilename; + overview_file.setExtension(ossimString("ovr")); + ob.setCompressionType(tiff_compress_type); + ob.setJpegCompressionQuality(jpeg_compress_quality); + ob.buildOverview(overview_file, 0); + + // Remove the listener from the overview builder. + if (theProgressListener) + { + ob.removeListener(theProgressListener); + } + } + + delete ih; + + return true; +} + +bool ossimImageFileWriter::writeEnviHeaderFile() const +{ + if( (theFilename == "") || !theInputConnection || + theAreaOfInterest.hasNans()) + { + return false; + } + + // Make the file name. + ossimFilename outputFile = theFilename; + outputFile.setExtension(ossimString("hdr")); + + // Make the writer. + ossimRefPtr<ossimMetadataFileWriter> writer = + new ossimEnviHeaderFileWriter(); + + // Set things up. + writer->connectMyInputTo(0, theInputConnection); + writer->initialize(); + writer->setFilename(outputFile); + writer->setAreaOfInterest(theAreaOfInterest); + + // Write it to disk. + return writer->execute(); +} + +bool ossimImageFileWriter::writeExternalGeometryFile() const +{ + if( (theFilename == "") || !theInputConnection || + theAreaOfInterest.hasNans()) + { + return false; + } + + // Make the file name. + ossimFilename geomFile = theFilename; + geomFile.setExtension(ossimString("geom")); + + // Make the writer. + ossimRefPtr<ossimMetadataFileWriter> writer = new ossimGeomFileWriter(); + + // Set things up. + writer->connectMyInputTo(0, theInputConnection); + writer->initialize(); + writer->setFilename(geomFile); + writer->setAreaOfInterest(theAreaOfInterest); + + // Write it to disk. + return writer->execute(); +} + +bool ossimImageFileWriter::writeFgdcFile() const +{ + if( (theFilename == "") || !theInputConnection || + theAreaOfInterest.hasNans()) + { + return false; + } + + // Make the file name. + ossimFilename outputFile = theFilename; + outputFile.setExtension(ossimString("xml")); + + // Make the writer. + ossimRefPtr<ossimMetadataFileWriter> writer = new ossimFgdcFileWriter(); + + // Set things up. + writer->connectMyInputTo(0, theInputConnection); + writer->initialize(); + writer->setFilename(outputFile); + writer->setAreaOfInterest(theAreaOfInterest); + + // Write it to disk. + return writer->execute(); +} + +bool ossimImageFileWriter::writeJpegWorldFile() const +{ + if( (theFilename == "") || !theInputConnection || + theAreaOfInterest.hasNans()) + { + return false; + } + + // Make the file name. + ossimFilename outputFile = theFilename; + outputFile.setExtension(ossimString("jpw")); // jpw??? + + // Make the writer. + ossimRefPtr<ossimMetadataFileWriter> writer = + new ossimJpegWorldFileWriter(); + + // Set things up. + writer->connectMyInputTo(0, theInputConnection); + writer->initialize(); + writer->setFilename(outputFile); + writer->setAreaOfInterest(theAreaOfInterest); + + // Write it to disk. + return writer->execute(); +} + +bool ossimImageFileWriter::writeReadmeFile() const +{ + if( (theFilename == "") || !theInputConnection || + theAreaOfInterest.hasNans()) + { + return false; + } + + // Make the file name. + ossimFilename outputFile = theFilename.noExtension(); + + outputFile += "_readme.txt"; + + // Make the writer. + ossimRefPtr<ossimMetadataFileWriter> writer = + new ossimReadmeFileWriter(); + + // Set things up. + writer->connectMyInputTo(0, theInputConnection); + writer->initialize(); + writer->setFilename(outputFile); + writer->setAreaOfInterest(theAreaOfInterest); + + // Write it to disk. + return writer->execute(); +} + +bool ossimImageFileWriter::writeTiffWorldFile() const +{ + if( (theFilename == "") || !theInputConnection || + theAreaOfInterest.hasNans()) + { + return false; + } + + // Make the file name. + ossimFilename outputFile = theFilename; + outputFile.setExtension(ossimString("tfw")); + + // Make the writer. + ossimRefPtr<ossimMetadataFileWriter> writer = + new ossimTiffWorldFileWriter(); + + // Set things up. + writer->connectMyInputTo(0, theInputConnection); + writer->initialize(); + writer->setFilename(outputFile); + writer->setAreaOfInterest(theAreaOfInterest); + + // Write it to disk. + return writer->execute(); +} + +bool ossimImageFileWriter::writeMetaDataFiles() const +{ + bool status = true; + + if(theWriteEnviHeaderFlag) + { + if(writeEnviHeaderFile() == false) + { + status = false; + + ossimNotify(ossimNotifyLevel_WARN) + << "Write of envi header file failed!" << endl; + } + } + + if (theWriteExternalGeometryFlag) + { + if( writeExternalGeometryFile() == false) + { + status = false; + + ossimNotify(ossimNotifyLevel_WARN) + << "Write of geometry file failed!" << endl; + } + } + if(theWriteFgdcFlag) + { + if(writeFgdcFile() == false) + { + status = false; + + ossimNotify(ossimNotifyLevel_WARN) + << "Write of fgdc file failed!" << endl; + } + } + if(theWriteJpegWorldFileFlag) + { + if(writeJpegWorldFile() == false) + { + status = false; + + ossimNotify(ossimNotifyLevel_WARN) + << "Write of jpeg world file failed!" << endl; + } + } + if(theWriteReadmeFlag) + { + if(writeReadmeFile() == false) + { + status = false; + + ossimNotify(ossimNotifyLevel_WARN) + << "Write of readme file failed!" << endl; + } + } + if(theWriteTiffWorldFileFlag) + { + if(writeTiffWorldFile() == false) + { + status = false; + + ossimNotify(ossimNotifyLevel_WARN) + << "Write of tiff world file failed!" << endl; + } + } + + if (theWriteOverviewFlag) + { + if (!writeOverviewFile(theOverviewCompressType, + theOverviewJpegCompressQuality)) + { + status = false; + + ossimNotify(ossimNotifyLevel_WARN) + << "Write of overview file failed!" << endl; + } + } + + if (theWriteHistogramFlag) + { + if (!writeHistogramFile()) + { + status = false; + + ossimNotify(ossimNotifyLevel_WARN) + << "Write of histogram file failed!" << endl; + } + } + + return status; +} + +bool ossimImageFileWriter::writeHistogramFile() const +{ + if(theFilename == "") return false; + + ossimFilename histogram_file = theFilename; + histogram_file.setExtension(ossimString("his")); + + ossimImageHandler* handler = ossimImageHandlerRegistry::instance()-> + open(theFilename); + + if (!handler) + { + return false; + } + + ossimImageHistogramSource* histoSource = new ossimImageHistogramSource; + + ossimHistogramWriter* writer = new ossimHistogramWriter; + histoSource->setMaxNumberOfRLevels(1); // Only compute for r0. + histoSource->connectMyInputTo(0, handler); + histoSource->enableSource(); + writer->connectMyInputTo(0, histoSource); + writer->setFilename(histogram_file); + writer->addListener(&theStdOutProgress); + writer->execute(); + + delete handler; + delete writer; + + return true; +} + +void ossimImageFileWriter::disconnectInputEvent(ossimConnectionEvent& event) +{ + if(!getInput(0)) + { + theInputConnection->disconnectMyInput((ossim_int32)0, false); + } + theViewController = PTR_CAST(ossimViewController, getInput(1)); + + initialize(); +} + +void ossimImageFileWriter::connectInputEvent(ossimConnectionEvent& event) +{ + theInputConnection->connectMyInputTo((ossim_int32)0, + getInput(0), + false); + theViewController = PTR_CAST(ossimViewController, getInput(1)); + initialize(); +} + +void ossimImageFileWriter::propertyEvent(ossimPropertyEvent& event) +{ + initialize(); +} + +void ossimImageFileWriter::setOutputImageType(const ossimString& type) +{ + theOutputImageType = type; +} + +void ossimImageFileWriter::setOutputImageType(ossim_int32 type) +{ + ossimImageTypeLut lut; + theOutputImageType = lut.getEntryString(type); +} + +ossimString ossimImageFileWriter::getOutputImageTypeString() const +{ + return theOutputImageType; + +} + +ossim_int32 ossimImageFileWriter::getOutputImageType() const +{ + ossimImageTypeLut lut; + return lut.getEntryNumber(theOutputImageType); +} + + +bool ossimImageFileWriter::getWriteImageFlag() const +{ + return theWriteImageFlag; +} + +bool ossimImageFileWriter::getWriteHistogramFlag() const +{ + return theWriteHistogramFlag; +} + +bool ossimImageFileWriter::getWriteOverviewFlag() const +{ + return theWriteOverviewFlag; +} + +bool ossimImageFileWriter::getWriteEnviHeaderFlag() const +{ + return theWriteEnviHeaderFlag; +} + +bool ossimImageFileWriter::getWriteExternalGeometryFlag() const +{ + return theWriteExternalGeometryFlag; +} + +bool ossimImageFileWriter::getWriteFgdcFlag() const +{ + return theWriteFgdcFlag; +} + +bool ossimImageFileWriter::getWriteJpegWorldFileFlag() const +{ + return theWriteJpegWorldFileFlag; +} + +bool ossimImageFileWriter::getWriteReadmeFlag() const +{ + return theWriteReadmeFlag; +} + +bool ossimImageFileWriter::getWriteTiffWorldFileFlag() const +{ + return theWriteTiffWorldFileFlag; +} + + +void ossimImageFileWriter::setWriteOverviewFlag(bool flag) +{ + theWriteOverviewFlag = flag; +} + +void ossimImageFileWriter::setWriteImageFlag(bool flag) +{ + theWriteImageFlag = flag; +} + +void ossimImageFileWriter::setWriteHistogramFlag(bool flag) +{ + theWriteHistogramFlag = flag; +} + +void ossimImageFileWriter::setWriteEnviHeaderFlag(bool flag) +{ + theWriteEnviHeaderFlag = flag; +} + +void ossimImageFileWriter::setWriteExternalGeometryFlag(bool flag) +{ + theWriteExternalGeometryFlag = flag; +} + +void ossimImageFileWriter::setWriteFgdcFlag(bool flag) +{ + theWriteFgdcFlag = flag; +} + +void ossimImageFileWriter::setWriteJpegWorldFile(bool flag) +{ + theWriteJpegWorldFileFlag = flag; +} + +void ossimImageFileWriter::setWriteReadme(bool flag) +{ + theWriteReadmeFlag = flag; +} + +void ossimImageFileWriter::setWriteTiffWorldFile(bool flag) +{ + theWriteTiffWorldFileFlag = flag; +} + +ossimObject* ossimImageFileWriter::getObject() +{ + return this; +} + +const ossimObject* ossimImageFileWriter::getObject() const +{ + return this; +} + +void ossimImageFileWriter::setAreaOfInterest(const ossimIrect& inputRect) +{ + ossimImageWriter::setAreaOfInterest(inputRect); + if(theInputConnection) + { + theInputConnection->setAreaOfInterest(inputRect); + } +} + +ossimImageSourceSequencer* ossimImageFileWriter::getSequencer() +{ + return theInputConnection; +} + +bool ossimImageFileWriter::execute() +{ + static const char MODULE[] = "ossimImageFileWriter::execute"; + + if (!theInputConnection) // Must have a sequencer... + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " DEBUG:\ntheInputConnection is NULL!" << endl; + } + return false; + } + + if (theFilename == "") // Must have a filename... + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " DEBUG:\ntheFilename is empty!" << endl; + } + return false; + } + + // make sure we have a region of interest + if(theAreaOfInterest.hasNans()) + { + theInputConnection->initialize(); + theAreaOfInterest = theInputConnection->getAreaOfInterest(); + } + else + { + theInputConnection->setAreaOfInterest(theAreaOfInterest); + } + + if(theAreaOfInterest.hasNans()) // Must have an area of interest... + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " ERROR: Area of interest has nans!" + << "Area of interest: " + << theAreaOfInterest + << "\nReturning..." << endl; + } + + return false; + } + + setProcessStatus(ossimProcessInterface::PROCESS_STATUS_EXECUTING); + setPercentComplete(0.0); + bool wroteFile = true; + if (theWriteImageFlag) + { + wroteFile = writeFile(); + } + + if(needsAborting()) + { + setProcessStatus(ossimProcessInterface::PROCESS_STATUS_ABORTED); + } + else + { + setProcessStatus(ossimProcessInterface::PROCESS_STATUS_NOT_EXECUTING); + } + + if(getProcessStatus() != ossimProcessInterface::PROCESS_STATUS_ABORTED) + { + // Do these only on the master process. Note left to right precedence! + if (getSequencer() && getSequencer()->isMaster()) + { + if (wroteFile) + { + if (writeMetaDataFiles() == false) + { + ossimNotify(ossimNotifyLevel_WARN) + << "Write of overview file failed!" << endl; + return false; + } + } + + } // End of "if (getSequencer() && getSequencer()->isMaster())) + } + + return true; +} + +void ossimImageFileWriter::setPercentComplete(double percentComplete) +{ + ossimProcessInterface::setPercentComplete(percentComplete); + ossimProcessProgressEvent event(this, percentComplete); + fireEvent(event); +} + +void ossimImageFileWriter::setOutputName(const ossimString& outputName) +{ + ossimImageWriter::setOutputName(outputName); + setFilename(ossimFilename(outputName)); +} + +void ossimImageFileWriter::setFilename(const ossimFilename& file) +{ + theFilename = file; +} + +const ossimFilename& ossimImageFileWriter::getFilename()const +{ + return theFilename; +} + +bool ossimImageFileWriter::canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const +{ + return (object&& + ( (PTR_CAST(ossimImageSourceInterface, object)&&inputIndex == 0)|| + (PTR_CAST(ossimViewController, object)&&inputIndex == 1)) ); +} + +ossim_uint16 ossimImageFileWriter::getOverviewCompressType() const +{ + return theOverviewCompressType; +} + +ossim_int32 ossimImageFileWriter::getOverviewJpegCompressQuality() const +{ + return theOverviewJpegCompressQuality; +} + +void ossimImageFileWriter::setOverviewCompressType(ossim_uint16 type) +{ + theOverviewCompressType = type; +} + +void ossimImageFileWriter::setOverviewJpegCompressQuality(ossim_int32 quality) +{ + theOverviewJpegCompressQuality = quality; +} + +void ossimImageFileWriter::setProperty(ossimRefPtr<ossimProperty> property) +{ + if(!property) return; + + if(property->getName() == ossimKeywordNames::FILENAME_KW) + { + theFilename = property->valueToString(); + } + else if (property->getName() == "create_envi_hdr") + { + theWriteEnviHeaderFlag = property->valueToString().toBool(); + } + else if (property->getName() == + ossimKeywordNames::CREATE_EXTERNAL_GEOMETRY_KW) + { + theWriteExternalGeometryFlag = property->valueToString().toBool(); + } + else if (property->getName() == "create_fgdc") + { + theWriteFgdcFlag = property->valueToString().toBool(); + } + else if (property->getName() == "create_jpeg_world_file") + { + theWriteJpegWorldFileFlag = property->valueToString().toBool(); + } + else if (property->getName() == "create_readme") + { + theWriteReadmeFlag = property->valueToString().toBool(); + } + else if (property->getName() == "create_tiff_world_file") + { + theWriteTiffWorldFileFlag = property->valueToString().toBool(); + } + else if (property->getName() == ossimKeywordNames::CREATE_IMAGE_KW) + { + theWriteImageFlag = property->valueToString().toBool(); + } + else if (property->getName() == ossimKeywordNames::CREATE_OVERVIEW_KW) + { + theWriteOverviewFlag = property->valueToString().toBool(); + } + else if (property->getName() == ossimKeywordNames::CREATE_HISTOGRAM_KW) + { + theWriteHistogramFlag = property->valueToString().toBool(); + } + else + { + ossimImageWriter::setProperty(property); + } +} + +ossimRefPtr<ossimProperty> ossimImageFileWriter::getProperty(const ossimString& name)const +{ + if(name == ossimKeywordNames::FILENAME_KW) + { + ossimFilenameProperty* filenameProp = + new ossimFilenameProperty(name, theFilename); + + filenameProp->setIoType(ossimFilenameProperty::ossimFilenamePropertyIoType_OUTPUT); + + return filenameProp; + } + else if (name == "create_envi_hdr") + { + return new ossimBooleanProperty(name, theWriteEnviHeaderFlag); + } + else if (name == ossimKeywordNames::CREATE_EXTERNAL_GEOMETRY_KW) + { + return new ossimBooleanProperty(name, theWriteExternalGeometryFlag); + } + else if (name == "create_fgdc") + { + return new ossimBooleanProperty(name, theWriteFgdcFlag); + } + else if (name == "create_jpeg_world_file") + { + return new ossimBooleanProperty(name, theWriteJpegWorldFileFlag); + } + else if (name == "create_readme") + { + return new ossimBooleanProperty(name, theWriteReadmeFlag); + } + else if (name == "create_tiff_world_file") + { + return new ossimBooleanProperty(name, theWriteTiffWorldFileFlag); + } + else if (name == ossimKeywordNames::CREATE_IMAGE_KW) + { + return new ossimBooleanProperty(name, theWriteImageFlag); + } + else if (name == ossimKeywordNames::CREATE_OVERVIEW_KW) + { + return new ossimBooleanProperty(name, theWriteOverviewFlag); + } + else if (name == ossimKeywordNames::CREATE_HISTOGRAM_KW) + { + return new ossimBooleanProperty(name, theWriteHistogramFlag); + } + + return ossimImageWriter::getProperty(name); +} + +void ossimImageFileWriter::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + ossimImageWriter::getPropertyNames(propertyNames); + + propertyNames.push_back(ossimString(ossimKeywordNames::FILENAME_KW)); + propertyNames.push_back(ossimString("create_envi_hdr")); + propertyNames.push_back(ossimString(ossimKeywordNames::CREATE_EXTERNAL_GEOMETRY_KW)); + propertyNames.push_back(ossimString("create_fgdc")); + propertyNames.push_back(ossimString("create_jpeg_world_file")); + propertyNames.push_back(ossimString("create_readme")); + propertyNames.push_back(ossimString("create_tiff_world_file")); + propertyNames.push_back(ossimString(ossimKeywordNames::CREATE_IMAGE_KW)); + propertyNames.push_back(ossimString(ossimKeywordNames::CREATE_OVERVIEW_KW)); + propertyNames.push_back(ossimString(ossimKeywordNames::CREATE_HISTOGRAM_KW)); +} + +bool ossimImageFileWriter::hasImageType(const ossimString& imageType) const +{ + std::vector<ossimString> imageTypeList; + getImageTypeList(imageTypeList); + + std::vector<ossimString>::const_iterator i = imageTypeList.begin(); + + while (i != imageTypeList.end()) + { + if ( (*i) == imageType ) + { + return true; + } + ++i; + } + + return false; // not found... +} + +bool ossimImageFileWriter::addListener(ossimListener* listener) +{ + theProgressListener = listener; + return ossimImageWriter::addListener(listener); +} + +bool ossimImageFileWriter::removeListener(ossimListener* listener) +{ + if (listener == theProgressListener) + { + theProgressListener = NULL; + } + return ossimImageWriter::removeListener(listener); +} + +void ossimImageFileWriter::setTileSize(const ossimIpt& tileSize) +{ + if (theInputConnection) + { + theInputConnection->setTileSize(tileSize); + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/ossimImageFileWriter.h b/Utilities/OSSIM/ossim_core/imaging/formats/ossimImageFileWriter.h new file mode 100644 index 0000000000..f6774fd0f2 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/ossimImageFileWriter.h @@ -0,0 +1,319 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Frank Warmerdam (warmerdam@pobox.com) +// +// Description: +// +// Contains class declaration for ossimImageWriter +//******************************************************************* +// $Id: ossimImageFileWriter.h,v 1.39 2006/01/06 16:46:46 dburken Exp $ + +#ifndef ossimImageFileWriter_HEADER +#define ossimImageFileWriter_HEADER +#include <fstream> +#include <imaging/ossimImageWriter.h> +#include <base/data_types/ossimFilename.h> +#include <base/common/events/ossimConnectableObjectListener.h> +#include <base/common/ossimProcessInterface.h> +#include <base/common/events/ossimObjectEvents.h> +#include <base/common/events/ossimProcessProgressEvent.h> +#include <base/common/ossimViewController.h> + +/** + * Pure virtual base class for image file writers. + * + * There is normally one subclass of this class for each format supported + * for writing. This class roughly corresponds to the ImageHandler class + * used for reading images. Format specific ossimImageWriter's are normally + * instantiated by the ossimImageWriterFactory::createWriterInstance() method. + * ossimImageWriters should not be directly instantiated by application code. + */ + +class OSSIMDLLEXPORT ossimImageFileWriter + : public ossimImageWriter, + public ossimProcessInterface, + public ossimConnectableObjectListener +{ +public: + + /** + * The writer will own the sequencer. + */ + ossimImageFileWriter(const ossimFilename& filename = ossimFilename(), + ossimImageSource* inputSource=0, + ossimObject* owner=0); + + virtual ~ossimImageFileWriter(); + + virtual ossimObject* getObject(); + + virtual const ossimObject* getObject()const; + + /** + * void getImageTypeList(std::vector<ossimString>& imageTypeList)const + * + * pure virtual + * + * Appends the writers image types to the "imageTypeList". + * + * This is the actual image type name. So for + * example, ossimTiffWriter has several image types. Some of these + * include TIFF_TILED, TIFF_TILED_BAND_SEPARATE ... etc. + * The ossimGdalWriter + * may include GDAL_IMAGINE_HFA, GDAL_RGB_NITF, GDAL_JPEG20000, ... etc. + * + * @param imageTypeList stl::vector<ossimString> list to append to. + * + * @note All writers should append to the list, not, clear it and then add + * their types. + */ + virtual void getImageTypeList(std::vector<ossimString>& imageTypeList)const=0; + + /** + * bool hasImageType(const ossimString& imageType) const + * + * @param imageType string representing image type. + * + * @return true if "imageType" is supported by writer. + */ + virtual bool hasImageType(const ossimString& imageType) const; + + /** + * Sets the output image tiling size if supported by the writer. If not + * supported this simply sets the sequencer(input) tile size. + */ + virtual void setTileSize(const ossimIpt& tileSize); + + /** + * Will write an envi header file. If "theFilename" is "foo.tif" + * then this will write out "foo.hdr". + */ + virtual bool writeEnviHeaderFile() const; + + /** + * Will write an external geometry file. If "theFilename" is "foo.tif" + * then this will write out "foo.geom". + */ + virtual bool writeExternalGeometryFile() const; + + /** + * Will write an fgdc file. If "theFilename" is "foo.tif" + * then this will write out "foo.xml". + */ + virtual bool writeFgdcFile() const; + + /** + * Returns true on success, false on error. + */ + virtual bool writeHistogramFile() const; + + /** + * Will write a jpeg world file. If "theFilename" is "foo.tif" + * then this will write out "foo.jpw". + */ + virtual bool writeJpegWorldFile() const; + + /** + * Write out an ossim overview file from the source_file. + * If source file is "foo.tif", this will create a "foo.ovr" in + * the same directory. + * + * @param source_file The file to create overview from. + * + * @param tiff_compress_type valid types: + * - COMPRESSION_JPEG + * - COMPRESSION_DEFLATE + * - COMPRESSION_PACKBITS + * - COMPRESSION_NONE=1 (default) + * + * @param jpeg_compress_quality Compression quality. Only valid with + * COMPRESSION_JPEG. Range 1 to 100 with 100 being the best. + * default = 75 + * + * @return true on success, false on error. + */ + virtual bool writeOverviewFile(ossim_uint16 tiff_compress_type = 1, + ossim_int32 jpeg_compress_quality = 75)const; + + /** + * Will write a readme file. If "theFilename" is "foo.tif" + * then this will write out "foo_readme.txt". + */ + virtual bool writeReadmeFile() const; + + /** + * Will write a readme file. If "theFilename" is "foo.tif" + * then this will write out "foo.tfw". + */ + virtual bool writeTiffWorldFile() const; + + /** + * Convenience method that calls meta data write methods that are flagged + * to be called. Attempts to write all files flagged to be written even + * if one file writer returns false. + * + * Currently calls these methods if flagged: + * writeEnviHeaderFile + * writeExternalGeometryFile + * writeFgdcFile + * writeJpegWorldFile + * writeReadmeFile + * writeTiffWorldFile + * writeOverviewFile + * writeHistogramFile + * + * @return true if all files flagged are written, false if not. + */ + virtual bool writeMetaDataFiles() const; + + virtual void setAreaOfInterest(const ossimIrect& inputRect); + + virtual void changeSequencer(ossimImageSourceSequencer* sequencer); + + virtual ossimImageSourceSequencer* getSequencer(); + + virtual void initialize(); + + /** + * Calls: + * writeFile() + * writeMetaDataFiles() + * + * @return true on success, false on error. + */ + virtual bool execute(); + + virtual void setPercentComplete(double percentComplete); + + virtual void setOutputImageType(ossim_int32 type); + virtual void setOutputImageType(const ossimString& type); + virtual ossim_int32 getOutputImageType() const; + virtual ossimString getOutputImageTypeString() const; + + virtual void setOutputName(const ossimString& outputName); + + virtual void setFilename(const ossimFilename& file); + + virtual const ossimFilename& getFilename()const; + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + + virtual bool canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const; + + virtual void disconnectInputEvent(ossimConnectionEvent& event); + virtual void connectInputEvent(ossimConnectionEvent& event); + virtual void propertyEvent(ossimPropertyEvent& event); + + /** + * Control flags... + */ + + virtual bool getWriteImageFlag() const; + virtual bool getWriteHistogramFlag() const; + virtual bool getWriteOverviewFlag() const; + + virtual bool getWriteEnviHeaderFlag() const; + virtual bool getWriteExternalGeometryFlag() const; + virtual bool getWriteFgdcFlag() const; + virtual bool getWriteJpegWorldFileFlag() const; + virtual bool getWriteReadmeFlag() const; + virtual bool getWriteTiffWorldFileFlag() const; + + virtual void setWriteImageFlag(bool flag); + virtual void setWriteOverviewFlag(bool flag); + virtual void setWriteHistogramFlag(bool flag); + + virtual void setWriteEnviHeaderFlag(bool flag); + virtual void setWriteExternalGeometryFlag(bool flag); + virtual void setWriteFgdcFlag(bool flag); + virtual void setWriteJpegWorldFile(bool flag); + virtual void setWriteReadme(bool flag); + virtual void setWriteTiffWorldFile(bool flag); + + virtual ossim_uint16 getOverviewCompressType() const; + virtual ossim_int32 getOverviewJpegCompressQuality() const; + + virtual void setOverviewCompressType(ossim_uint16 type); + virtual void setOverviewJpegCompressQuality(ossim_int32 quality); + + + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + + /** + * Overrides base "addListener" this will capture the pointer and then call + * the base class "addListener". If overview building is enabled, the + * listener will be passed to the overview builder::addListener, and + * subsequently removed from the overview builder after the build overview + * call is complete. This it transparent to the caller of this method. + * + * @param listener The listener to add. + * + * @return Currently always returns true. + * + * @note Callers still should call "removeListener" after the writing + * process is complete. + * + * @note If called more than once, theProgressListener will contain + * the latest listener. + */ + virtual bool addListener(ossimListener* listener); + + /** + * Overrides base "removeListener". Calls base "removeListener which will + * find and removes the listener. + * If "theProgressListener" pointer matches listener "theProgressListener" + * will be set to NULL. + * + * @param listener The listener to remove. + * + * @return Currently always returns true. + */ + virtual bool removeListener(ossimListener* listener); + +protected: + /** + * Write out the file. + * @return true on success, false on error. + */ + virtual bool writeFile() = 0; + + ossimImageSourceSequencer* theInputConnection; + ossimViewController* theViewController; + ossimListener* theProgressListener; + ossimFilename theFilename; + ossimString theOutputImageType; + bool theWriteImageFlag; + bool theWriteOverviewFlag; + bool theWriteHistogramFlag; + ossim_uint16 theOverviewCompressType; + ossim_int32 theOverviewJpegCompressQuality; + + /** + * External meta data writer flags. Not really part of an image writer, put + * here for convenience. If true the writer will do the connection work + * for you. + */ + bool theWriteEnviHeaderFlag; + bool theWriteExternalGeometryFlag; + bool theWriteFgdcFlag; + bool theWriteJpegWorldFileFlag; + bool theWriteReadmeFlag; + bool theWriteTiffWorldFileFlag; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/ossimImageHandler.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/ossimImageHandler.cpp new file mode 100644 index 0000000000..226c2e8077 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/ossimImageHandler.cpp @@ -0,0 +1,1228 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See LICENSE.txt file in the top level directory. +// +// Author: David Burken +// +// Description: +// +// This class defines an abstract image handler which all loaders should +// derive from. +// +//******************************************************************* +// $Id: ossimImageHandler.cpp,v 1.100 2005/12/06 20:58:29 dburken Exp $ + +#include <algorithm> + +#include <imaging/formats/ossimImageHandler.h> +#include <base/property/ossimStringProperty.h> +#include <base/common/ossimKeywordNames.h> +#include <base/common/ossimTrace.h> +#include <base/common/events/ossimEventIds.h> +#include <base/common/events/ossimContainerEvent.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimFilename.h> +#include <imaging/formats/tiff/ossimTiffTileSource.h> +#include <imaging/formats/tiff/ossimTiffOverviewBuilder.h> +#include <imaging/histogram/ossimHistogramWriter.h> +#include <imaging/histogram/ossimImageHistogramSource.h> +#include <base/common/ossimStdOutProgress.h> +#include <base/data_types/ossimPolygon.h> +#include <projections/ossimProjection.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <base/property/ossimFilenameProperty.h> +#include <imaging/factory/ossimImageHandlerRegistry.h> + +RTTI_DEF1(ossimImageHandler, "ossimImageHandler", ossimImageSource) + +//*** +// Static trace for debugging +//*** +static ossimTrace traceDebug("ossimImageHandler:debug"); + +#ifdef OSSIM_ID_ENABLED +static const char OSSIM_ID[] = "$Id: ossimImageHandler.cpp,v 1.100 2005/12/06 20:58:29 dburken Exp $"; +#endif + + +ossimImageHandler::ossimImageHandler() + : + ossimImageSource(NULL, + 0, + 0, + true, + false),// output list is not fixed + theImageFile(ossimFilename::NIL), + theOverview(NULL), + theSubImageOffset(0, 0), + theValidImageVertices(0), + theMetaData(), + theGeometryKwl() +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimImageHandler::ossimImageHandler() DEBUG:" << std::endl; +#ifdef OSSIM_ID_ENABLED + ossimNotify(ossimNotifyLevel_DEBUG) + << "OSSIM_ID: " + << OSSIM_ID + << std::endl; +#endif + } +} + +ossimImageHandler::~ossimImageHandler() +{ + + if (theOverview) + { + delete theOverview; + theOverview = NULL; + } + +} + +void ossimImageHandler::initialize() +{ +} + +//******************************************************************* +// Public method: +//******************************************************************* +bool ossimImageHandler::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + static const char MODULE[] = "ossimImageHandler::saveState"; + + ossimImageSource::saveState(kwl, prefix); + if (kwl.getErrorStatus() == ossimErrorCodes::OSSIM_ERROR) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE + << " ERROR detected in keyword list! State not saved." + << std::endl; + return false; + } + + kwl.add(prefix, + ossimKeywordNames::FILENAME_KW, + theImageFile.c_str(), + true); + + return true; +} + +//******************************************************************* +// Public method: +//******************************************************************* +bool ossimImageHandler::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimImageHandler::loadState(kwl, prefix) DEBUG: entered ..." + << std::endl; + } + static const char MODULE[] = "ossimImageHandler::loadState"; + + ossimImageSource::loadState(kwl, prefix); + + if (kwl.getErrorStatus() == ossimErrorCodes::OSSIM_ERROR) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE + << "WARNING: error detected in keyword list! State not load." + << std::endl; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimImageHandler::loadState(kwl, prefix) DEBUG: " + << "leaving with error in kwl ..." << std::endl; + } + return false; + } + + const char* lookup = kwl.find(prefix, ossimKeywordNames::FILENAME_KW); + if (!lookup) + { + // Deprecated... + lookup = kwl.find(prefix, ossimKeywordNames::IMAGE_FILE_KW); + } + + if (lookup) + { + theImageFile = lookup; + + } + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "filename = " << theImageFile << std::endl; + } + + // Check for an valid image vetices file. + lookup = kwl.find(prefix, "valid_vertices_file"); + if (lookup) + { + initVertices(lookup); + } + + if(getNumberOfInputs()) + { + theInputObjectList.clear(); + } + theInputListIsFixedFlag = true; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimImageHandler::loadState(kwl, prefix) DEBUG: Leaving Ok ..." + << std::endl; + } + return true; +} + +bool ossimImageHandler::initVertices(const char* file) +{ + static const char MODULE[] = "ossimImageHandler::initVertices"; + + ossimFilename f = file; + if (!f.exists()) return false; + + ossimKeywordlist kwl(file); + + if (kwl.getErrorStatus() != ossimErrorCodes::OSSIM_OK) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimImageHandler::initVertices NOTICE:" + << "\nError reading valid vertice file: " << file << std::endl; + } + return false; + } + + // Clean out any old vertices... + theValidImageVertices.clear(); + + int32 number_of_points = kwl.numberOf("point", "x"); + + for (int32 i=0; i<number_of_points; ++i) + { + ossimIpt pt; + const char* lookup; + ossimString p = "point"; + p += ossimString::toString(i); + + ossimString px = p + ".x"; + lookup = kwl.find(px.c_str()); + if (lookup) + { + pt.x = atoi(lookup); + } + else + { + if (traceDebug()) + { + CLOG << " ERROR:" + << "\nlookup failed for: " << px.c_str() + << "\nReturning..." + << std::endl; + } + return false; + } + + ossimString py = p + ".y"; + lookup = kwl.find(py.c_str()); + if (lookup) + { + pt.y = atoi(lookup); + } + else + { + if (traceDebug()) + { + CLOG << " ERROR:" + << "\nLookup failed for: " << py.c_str() + << "\nReturning..." + << std::endl; + } + return false; + } + + theValidImageVertices.push_back(pt); + } + + + if (traceDebug()) + { + CLOG << " DEBUG:" + << "\nVertices file: " << f + << "\nValid image vertices:" + << std::endl; + for (ossim_uint32 i=0; i<theValidImageVertices.size(); ++i) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "\npoint[" << i << "]: " << theValidImageVertices[i]; + } + ossimNotify(ossimNotifyLevel_DEBUG) << std::endl; + } + + return true; +} + +ossim_uint32 ossimImageHandler::getNumberOfDecimationLevels() const +{ + return (theOverview?theOverview->getNumberOfDecimationLevels():1); +} + +ossim_uint32 ossimImageHandler::getNumberOfReducedResSets() const +{ + return getNumberOfDecimationLevels(); +} + +ossimIrect ossimImageHandler::getImageRectangle(ossim_uint32 resLevel) const +{ + ossimIrect result; + + if( !isOpen() ) + { + result.makeNan(); + return result; + } + + if( isValidRLevel(resLevel) ) + { + ossim_int32 lines = getNumberOfLines(resLevel); + ossim_int32 samples = getNumberOfSamples(resLevel); + if(ossimIsNan(lines) || ossimIsNan(samples)) + { + result.makeNan(); + } + else + { + result = ossimIrect(0, 0, samples-1, lines-1); + } + } + + //--- + // Special case to handle overviews with no R0. + //--- + else if( isValidRLevel(resLevel+1) ) + { + ossim_int32 lines = getNumberOfLines(resLevel+1); + ossim_int32 samples = getNumberOfSamples(resLevel+1); + if( (ossimIsNan(lines)== false) && (ossimIsNan(samples) == false) ) + { + result = ossimIrect(0, 0, samples*2-1, lines*2-1); + } + else + { + result.makeNan(); + } + } + + return result; +} + +ossimIrect ossimImageHandler::getBoundingRect(ossim_uint32 resLevel) const +{ + ossimIrect result = getImageRectangle(resLevel); + + if (result.isNan() == false) + { + ossimIpt offset = getSubImageOffset(resLevel); + if (offset.isNan() == false) + { + result = result + offset; + } + } + + return result; +} + + +void ossimImageHandler::getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result) const +{ + if (resLevel == 0) + { + result.x = 1.0; + result.y = 1.0; + } + else + { + result.x = 1.0 / pow((double)2, (double)resLevel); + result.y = result.x; + } +} + +void ossimImageHandler::getDecimationFactors(vector<ossimDpt>& decimations) const +{ + const ossim_uint32 LEVELS = getNumberOfDecimationLevels(); + decimations.resize(LEVELS); + for (ossim_uint32 level = 0; level < LEVELS; ++level) + { + getDecimationFactor(level, decimations[level]); + } +} + +bool ossimImageHandler::buildHistogram(int numberOfRLevels) +{ + if(isOpen()) + { + ossimFilename file = + getFilenameWithThisExtension(ossimString(".his")); + + ossimImageHistogramSource* histoSource = new ossimImageHistogramSource; + ossimHistogramWriter* writer = new ossimHistogramWriter; + + if(numberOfRLevels) + { + histoSource->setMaxNumberOfRLevels(numberOfRLevels); + } + else + { + histoSource->setMaxNumberOfRLevels(getNumberOfDecimationLevels()); + } + histoSource->connectMyInputTo(0, this); + histoSource->enableSource(); + writer->connectMyInputTo(0, histoSource); + writer->setFilename(file); + writer->addListener(&theStdOutProgress); + writer->execute(); + + delete histoSource; + delete writer; + } + else + { + return false; + } + + return true; +} + +bool ossimImageHandler::buildAllHistograms(int numberOfRLevels) +{ + ossim_uint32 currentEntry = getCurrentEntry(); + std::vector<ossim_uint32> entryList; + getEntryList(entryList); + ossim_uint32 idx = 0; + for(idx = 0; idx < entryList.size(); ++idx) + { + setCurrentEntry(entryList[idx]); + if(!buildHistogram(numberOfRLevels)) + { + setCurrentEntry(currentEntry); + return false; + } + } + + setCurrentEntry(currentEntry); + return true; +} + +bool ossimImageHandler::buildOverview(ossimImageHandlerOverviewCompressionType compressionType, + ossim_uint32 quality, + ossimFilterResampler::ossimFilterResamplerType resampleType, + bool includeFullResFlag) +{ + ossimFilename file = getFilenameWithThisExtension(ossimString(".ovr")); + + if(buildOverview(file, compressionType, quality, resampleType, includeFullResFlag)) + { + openOverview(); + } + + return true; +} + +bool ossimImageHandler::buildAllOverviews(ossimImageHandlerOverviewCompressionType compressionType, + ossim_uint32 quality, + ossimFilterResampler::ossimFilterResamplerType resampleType, + bool includeFullResFlag) +{ + ossim_uint32 currentEntry = getCurrentEntry(); + std::vector<ossim_uint32> entryList; + getEntryList(entryList); + ossim_uint32 idx = 0; + for(idx = 0; idx < entryList.size(); ++idx) + { + setCurrentEntry(entryList[idx]); + if(!buildOverview(compressionType, quality, resampleType, includeFullResFlag)) + { + setCurrentEntry(currentEntry); + return false; + } + } + + setCurrentEntry(currentEntry); + return true; +} + + +bool ossimImageHandler::buildOverview(const ossimFilename& filename, + ossimImageHandlerOverviewCompressionType compressionType, + ossim_uint32 quality, + ossimFilterResampler::ossimFilterResamplerType resampleType, + bool includeFullResFlag) +{ + closeOverview(); + if(!isOpen()) + { + return false; + } + + ossimTiffOverviewBuilder tiffBuilder(this); + ossim_uint16 cType = COMPRESSION_NONE; + switch(compressionType) + { + case OSSIM_OVERVIEW_COMPRESSION_NONE: + { + cType = COMPRESSION_NONE; + break; + } + case OSSIM_OVERVIEW_COMPRESSION_JPEG: + { + cType = COMPRESSION_JPEG; + break; + } + case OSSIM_OVERVIEW_COMPRESSION_LZW: + { + cType = COMPRESSION_LZW; + break; + } + case OSSIM_OVERVIEW_COMPRESSION_DEFLATE: + { + + cType = COMPRESSION_DEFLATE; + break; + } + case OSSIM_OVERVIEW_COMPRESSION_PACKBITS: + { + cType = COMPRESSION_PACKBITS; + break; + } + } + tiffBuilder.setJpegCompressionQuality(quality); + tiffBuilder.setCompressionType(cType); + tiffBuilder.setResampleType(resampleType); + tiffBuilder.buildOverview(filename, includeFullResFlag); + + return true; +} + +//******************************************************************* +// Public method: +//******************************************************************* +bool ossimImageHandler::getImageGeometry(ossimKeywordlist& kwl, + const char* prefix) +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimImageHandler::getImageGeometry DEBUG: entered..." + << std::endl; + } + + if (theGeometryKwl.getSize()) + { + kwl = theGeometryKwl; + return true; + } + + bool result = false; + ossimProjection* proj = NULL; + ossimFilename filename = getFilenameWithThisExtension(ossimString(".geom")); + if(!filename.exists()) + { + // Try tacking on the entry like "foo_e0.hdf". + filename = getFilenameWithThisExtension(ossimString(".geom"), true); + } + if(filename.exists()) + { + if(kwl.addFile(filename)) + { + ossimString tempPrefix = + "image"+ossimString::toString(getCurrentEntry())+"."; + kwl.stripPrefixFromAll(tempPrefix); + + if(kwl.find(ossimKeywordNames::TYPE_KW)) + { + ossimKeywordlist kwlTemp(kwl); + + kwlTemp.add(ossimKeywordNames::GEOM_FILE_KW, + filename.c_str(), + true); + + proj = ossimProjectionFactoryRegistry::instance()-> + createProjection(kwlTemp); + if(proj) + { +// proj->saveState(kwl, prefix); + delete proj; + proj = NULL; + + result = true; + kwl = kwlTemp; + } + } + } + } + + if(!result) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimImageHandler::getImageGeometry DEBUG:" + << "\nCalling createProjection" + << "\ngetFilename(): " << getFilename() + << "\ngetCurrentEntry(): " << getCurrentEntry() + << std::endl; + } + + proj = ossimProjectionFactoryRegistry::instance()-> + createProjection(getFilename(), + getCurrentEntry()); + if(proj) + { + result = proj->saveState(kwl, prefix); + delete proj; + proj = NULL; + + result = true; + } + } + + if (result == true) + { + // Capture the geometry for next time. + theGeometryKwl = kwl; + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimImageHandler::getImageGeometry DEBUG:" + << "boolean return: " << result + << std::endl; + } + + return result; +} + +void ossimImageHandler::setImageGeometry(const ossimKeywordlist& kwl) +{ + theGeometryKwl = kwl; +} + +void ossimImageHandler::saveImageGeometry() const +{ + ossimFilename geometryFile = + getFilenameWithThisExtension(ossimString(".geom")); + saveImageGeometry(geometryFile); +} + +void ossimImageHandler::saveImageGeometry( + const ossimFilename& geometry_file) const +{ + theGeometryKwl.write(geometry_file.c_str()); +} + +void ossimImageHandler::closeOverview() +{ + if(theOverview) + { + delete theOverview; + theOverview = NULL; + } +} + +// const ossimFilename& ossimImageHandler::getOverviewFile()const +// { +// return theOverviewFile; +// } + +bool ossimImageHandler::hasOverviews() const +{ + return (getNumberOfDecimationLevels() > 1); +} + +bool ossimImageHandler::openOverview(const ossimFilename& overview_file) +{ + closeOverview(); + + // make sure we don't open ourselves. + if(theImageFile == overview_file) return false; + + theOverview = new ossimTiffTileSource; + + if ( theOverview->open(overview_file) ) + { + //--- + // This is not really a container event; however, using for now. + //--- + ossimContainerEvent event(this, theOverview, OSSIM_EVENT_ADD_OBJECT_ID); + fireEvent(event); + + return true; + } + + delete theOverview; + theOverview = NULL; + return false; +} + +bool ossimImageHandler::openOverview() +{ + closeOverview(); + + ossimFilename overviewFilename = createOverviewFilename(); + + // 1) If the current over file exists see if if can be opened. + if( overviewFilename.exists() ) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "Looking for " << overviewFilename + << " overview file..." << std::endl; + } + + if ( openOverview(overviewFilename) ) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "Opened overview " << overviewFilename + << std::endl; + } + return true; + } + } + + // For backward compatibility check if single entry and _e0.ovr + overviewFilename = getFilenameWithThisExtension(ossimString(".ovr"), true); + if ( overviewFilename.exists() ) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "Looking for " << overviewFilename + << " overview file..." << std::endl; + } + + if ( openOverview(overviewFilename) ) + { + return true; + } + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimImageHandler::openOverview NOTICE:" + << "\nCould not find an overview." << std::endl; + } + + return false; +} + + +bool ossimImageHandler::writeValidImageVertices(const std::vector<ossimIpt>& vertices, const ossimFilename& file) +{ + ossimFilename tempFile = file; + if(tempFile == "") + { + tempFile = createValidVerticesFilename(); + } + ossim_uint32 i = 0; + ossimKeywordlist tempKwl; + ossimPolygon poly(vertices); + + poly.checkOrdering(); + + // Capture the vertices. + theValidImageVertices = vertices; + + if(poly.getOrdering() == OSSIM_COUNTERCLOCKWISE_ORDER) + { + std::reverse(theValidImageVertices.begin(), theValidImageVertices.end()); + } + + if(theValidImageVertices.size()) + { + for(i = 0; i < theValidImageVertices.size(); ++i) + { + ossimString prefix = ossimString("point") + ossimString::toString(i) + "."; + tempKwl.add(prefix.c_str(), + "x", + theValidImageVertices[i].x, + true); + tempKwl.add(prefix.c_str(), + "y", + theValidImageVertices[i].y, + true); + } + + tempKwl.write(tempFile.c_str()); + } + + if ( tempFile.exists() ) + { + return true; + } + + return false; // Write of file failed. +} + +bool ossimImageHandler::openValidVertices(const ossimFilename& vertices_file) +{ + return initVertices(vertices_file); +} + +bool ossimImageHandler::openValidVertices() +{ + ossimFilename vertices_file; + vertices_file = theImageFile.path(); + vertices_file = vertices_file.dirCat(theImageFile.fileNoExtension()); + if(getNumberOfEntries() > 1) + { + vertices_file += ossimString("_vertices") + "_e" + ossimString::toString(getCurrentEntry()) + ".kwl"; + } + else + { + vertices_file += "_vertices.kwl"; + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "Looking for " << vertices_file + << " vertices file..." << std::endl; + } + + return openValidVertices(vertices_file); +} + +bool ossimImageHandler::open(const ossimFilename& imageFile) +{ + if(isOpen()) + { + close(); + } + + setFilename(imageFile); + + return open(); +} + +bool ossimImageHandler::open(const ossimFilename& imageFile, + ossim_uint32 entryIndex) +{ + if(isOpen()) + { + close(); + } + setFilename(imageFile); + + bool result = open(); + + if(result) + { + return setCurrentEntry(entryIndex); + } + + return result; +} + +bool ossimImageHandler::isValidRLevel(ossim_uint32 resLevel) const +{ + if (resLevel < getNumberOfDecimationLevels()) + { + return true; + } + + return false; +} + +void ossimImageHandler::getValidImageVertices(vector<ossimIpt>& validVertices, + ossimVertexOrdering ordering, + ossim_uint32 resLevel) const +{ + ossimDpt decimation; + getDecimationFactor(resLevel, decimation); + if(decimation.hasNans()) + { + return; + } + if (theValidImageVertices.size() != 0) + { + validVertices.clear(); + for (ossim_uint32 i=0; i<theValidImageVertices.size(); ++i) + { + ossimIpt pt(irint(theValidImageVertices[i].x*decimation.x), + irint(theValidImageVertices[i].y*decimation.y)); + validVertices.push_back(pt); + } + + if(ordering == OSSIM_COUNTERCLOCKWISE_ORDER) + { + std::reverse(validVertices.begin()+1, validVertices.end()); + } + } + else + { + // Call the base class method which will set to bounding rectangle. + ossimImageSource::getValidImageVertices(validVertices, ordering, resLevel); + } +} + +void ossimImageHandler::close() +{ + if (theOverview) + { + delete theOverview; + theOverview = NULL; + } + + theValidImageVertices.clear(); +} + +bool ossimImageHandler::isBandSelector() const +{ + return false; +} + +bool ossimImageHandler::setOutputBandList(const std::vector<ossim_uint32>& band_list) +{ + return false; +} + +bool ossimImageHandler::isImageTiled() const +{ + return (getImageTileWidth() && getImageTileHeight()); +} + +void ossimImageHandler::loadMetaData() +{ + theMetaData.clear(); + + ossimFilename filename = getFilenameWithThisExtension(ossimString(".omd")); + if(filename.exists()) + { + ossimKeywordlist kwl; + + kwl.addFile(filename.c_str()); + + theMetaData.loadState(kwl); + } + else + { + theMetaData.setScalarType(getOutputScalarType()); + } +} + +double ossimImageHandler::getMinPixelValue(ossim_uint32 band)const +{ + if(theMetaData.getNumberOfBands()) + { + return theMetaData.getMinPix(band); + } + return ossimGetDefaultMin(getOutputScalarType()); +} + +double ossimImageHandler::getMaxPixelValue(ossim_uint32 band)const +{ + if(theMetaData.getNumberOfBands()) + { + return theMetaData.getMaxPix(band); + } + return ossimGetDefaultMax(getOutputScalarType()); +} + +double ossimImageHandler::getNullPixelValue(ossim_uint32 band)const +{ + if(theMetaData.getNumberOfBands()) + { + return theMetaData.getNullPix(band); + } + + return ossimGetDefaultNull(getOutputScalarType()); +} + + +ossim_uint32 ossimImageHandler::getCurrentEntry()const +{ + return 0; +} + +bool ossimImageHandler::setCurrentEntry(ossim_uint32 /* entryIdx */) +{ + return true; +} + +void ossimImageHandler::getEntryList(std::vector<ossim_uint32>& entryList)const +{ + entryList.push_back(0); +} + +void ossimImageHandler::getEntryStringList( + std::vector<ossimString>& entryStringList) const +{ + std::vector<ossim_uint32> entryList; + getEntryList(entryList); + + if (entryList.size()) + { + entryStringList.resize(entryList.size()); + for (ossim_uint32 i = 0; i < entryList.size(); ++i) + { + entryStringList[i] = ossimString::toString(entryList[i]); + } + } +} + +ossim_uint32 ossimImageHandler::getNumberOfEntries()const +{ + std::vector<ossim_uint32> tempList; + getEntryList(tempList); + + return tempList.size(); +} + + +void ossimImageHandler::completeOpen() +{ + loadMetaData(); + openOverview(); + openValidVertices(); +} + +bool ossimImageHandler::canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* /* object */)const +{ + return false; +} + +bool ossimImageHandler::hasMetaData()const +{ + return theMetaData.isValid(); +} + +ossimIpt ossimImageHandler::getSubImageOffset(ossim_uint32 resLevel) const +{ + if (resLevel == 0) + { + return theSubImageOffset; + } + + ossimIpt offset; + offset.makeNan(); + if (isValidRLevel(resLevel)) + { + ossimDpt decimation; + getDecimationFactor(resLevel, decimation); + if(!decimation.hasNans()) // Should never have nans... + { + offset.x = irint(theSubImageOffset.x*decimation.x); + offset.y = irint(theSubImageOffset.y*decimation.y); + } + } + return offset; +} + +void ossimImageHandler::setSubImageOffset(const ossimIpt& p) +{ + theSubImageOffset = p; +} + +void ossimImageHandler::setFilename(const ossimFilename& filename) +{ + theImageFile = filename; +} + +const ossimFilename& ossimImageHandler::getFilename()const +{ + return theImageFile; +} + + +void ossimImageHandler::setProperty(ossimRefPtr<ossimProperty> property) +{ + if(property->getName() == ossimKeywordNames::ENTRY_KW) + { + setCurrentEntry(property->valueToString().toUInt32()); + } + else + { + ossimImageSource::setProperty(property); + } +} + +ossimRefPtr<ossimProperty> ossimImageHandler::getProperty(const ossimString& name)const +{ + + if(name == ossimKeywordNames::ENTRY_KW) + { + std::vector<ossim_uint32> entryList; + getEntryList(entryList); + + ossimStringProperty* stringProperty = new ossimStringProperty(name, + ossimString::toString(getCurrentEntry())); + ossim_uint32 idx = 0; + for(idx = 0; idx < entryList.size(); ++idx) + { + stringProperty->addConstraint(ossimString::toString(entryList[idx])); + } + stringProperty->setFullRefreshBit(); + stringProperty->setEditableFlag(false); + + return stringProperty; + } + if(name == "histogram_filename") + { + ossimFilenameProperty* filenameProp = + new ossimFilenameProperty(name, createHistogramFilename()); + + filenameProp->setIoType(ossimFilenameProperty::ossimFilenamePropertyIoType_INPUT); + filenameProp->setCacheRefreshBit(); + + return filenameProp; + + } + if(name == "geometry_filename") + { + ossimFilenameProperty* filenameProp = + new ossimFilenameProperty(name, createGeometryFilename()); + + filenameProp->setIoType(ossimFilenameProperty::ossimFilenamePropertyIoType_INPUT); + filenameProp->setCacheRefreshBit(); + + return filenameProp; + + } + if(name == "valid_vertices_filename") + { + ossimFilenameProperty* filenameProp = + new ossimFilenameProperty(name, createValidVerticesFilename()); + + filenameProp->setIoType(ossimFilenameProperty::ossimFilenamePropertyIoType_INPUT); + filenameProp->setCacheRefreshBit(); + + return filenameProp; + } + if(name == "metadata_filename") + { + ossimFilenameProperty* filenameProp = + new ossimFilenameProperty(name, createMetadataFilename()); + + filenameProp->setIoType(ossimFilenameProperty::ossimFilenamePropertyIoType_INPUT); + filenameProp->setCacheRefreshBit(); + + return filenameProp; + } + if(name == "overview_filename") + { + ossimFilenameProperty* filenameProp = + new ossimFilenameProperty(name, createOverviewFilename()); + + filenameProp->setIoType(ossimFilenameProperty::ossimFilenamePropertyIoType_INPUT); + filenameProp->setCacheRefreshBit(); + + return filenameProp; + } + if(name == "filename") + { + ossimFilenameProperty* filenameProp = + new ossimFilenameProperty(name, getFilename()); + + filenameProp->setIoType(ossimFilenameProperty::ossimFilenamePropertyIoType_INPUT); + filenameProp->setFullRefreshBit(); + + return filenameProp; + } + + return ossimImageSource::getProperty(name); +} + +void ossimImageHandler::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + ossimImageSource::getPropertyNames(propertyNames); + propertyNames.push_back(ossimKeywordNames::ENTRY_KW); +} + +ossimFilename ossimImageHandler::getFilenameWithThisExtension( + const ossimString& ext, + bool set_e0_prefix) const +{ + // Get the image file. + ossimFilename f = getFilename(); + + // Wipe out the extension. + f.setExtension(""); + + if (set_e0_prefix || (getNumberOfEntries() > 1)) + { + f += "_e"; + f += ossimString::toString(getCurrentEntry()); + } + if (ext.size()) + { + if (ext[0] != '.') + { + f += "."; + } + f += ext; + } + return f; +} + +ossimRefPtr<ossimNBandLutDataObject> ossimImageHandler::getLut()const +{ + return theLut; +} + +ossimFilename ossimImageHandler::createOverviewFilename() const +{ + return getFilenameWithThisExtension("ovr"); +} + +ossimFilename ossimImageHandler::createGeometryFilename() const +{ + return getFilenameWithThisExtension("geom"); +} + +ossimFilename ossimImageHandler::createMetadataFilename() const +{ + return getFilenameWithThisExtension("omd"); +} + +ossimFilename ossimImageHandler::createHistogramFilename() const +{ + return getFilenameWithThisExtension("his"); +} + +ossimFilename ossimImageHandler::createValidVerticesFilename() const +{ + ossimFilename result; + + result = theImageFile.path(); + result = result.dirCat(theImageFile.fileNoExtension()); + result += "_vertices"; + if(getNumberOfEntries() > 1) + { + result += "_e"; + result += ossimString::toString(getCurrentEntry()); + } + result += ".kwl"; + + return result; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/ossimImageHandler.h b/Utilities/OSSIM/ossim_core/imaging/formats/ossimImageHandler.h new file mode 100644 index 0000000000..d5bd307b1a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/ossimImageHandler.h @@ -0,0 +1,564 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +// This class defines an abstract image handler which all loaders should +// derive from. +// +//******************************************************************** +// $Id: ossimImageHandler.h,v 1.67 2005/10/13 13:30:33 gpotts Exp $ +#ifndef ossimImageHandler_HEADER +#define ossimImageHandler_HEADER + +#include <imaging/ossimImageSource.h> +#include <imaging/ossimImageMetaData.h> +#include <base/common/ossimConstants.h> +#include <base/common/ossimNBandLutDataObject.h> +#include <base/data_types/ossimIrect.h> +#include <base/data_types/ossimFilename.h> +#include <imaging/resample/ossimFilterResampler.h> +class ossimTiffTileSource; + +/** + * This class defines an abstract Handler which all image handlers(loaders) + * should derive from. + */ +class OSSIMDLLEXPORT ossimImageHandler : public ossimImageSource +{ +public: + + enum ossimImageHandlerOverviewCompressionType + { + OSSIM_OVERVIEW_COMPRESSION_NONE= 0, + OSSIM_OVERVIEW_COMPRESSION_JPEG, + OSSIM_OVERVIEW_COMPRESSION_LZW, + OSSIM_OVERVIEW_COMPRESSION_DEFLATE, + OSSIM_OVERVIEW_COMPRESSION_PACKBITS + }; + + /** + * Constructor (default): + */ + ossimImageHandler(); + + /** + * Destructor: + * Derived classes should implement. + */ + virtual ~ossimImageHandler(); + + //virtual ossimObject* dup()const; + /** + * initialize + * Does nothing in this class. Implemented to satisfy pure virtual. + */ + virtual void initialize(); + + /** + * Searches for an overview. Uses theImageFile as a key. + * If theImageFile = "foo.tif" it will look for "foo.ovr" first, + * then "foo_ovr.tif" next. + * Calls openOverview(const ossimFilename& overview_file) + * @return true on success, false on error. + * @see openOverview(const ossimFilename& overview_file) + */ + virtual bool openOverview(); + + /** + * Calls closeOverview(), then attempts to open the overview_file. + * On success, theOverviewFile will be set and theOverview will be + * initialized. On failure, theOverviewFile will be cleared and + * theOverview deleted and set to NULL. + * @param overview_file ossimFilename representing overview file. + * @return true on success, false on error. + * @see closeOverview() + */ + virtual bool openOverview(const ossimFilename& overview_file); + + /** + * If theOverview is initialized it will be deleted and set to NULL. Also + * clears theOverviewFile. + * @return void + */ + virtual void closeOverview(); + + /** + * @return true if getNumberOfReducedResSets > 1, false if not. + * @see getNumberOfReducedResSets() + */ + virtual bool hasOverviews() const; + + /** + * @return ossimFilename represents an external OSSIM overview filename. + */ + virtual ossimFilename createOverviewFilename() const; + + /** + * @return ossimFilename represents an external OSSIM geometry filename. + */ + virtual ossimFilename createGeometryFilename() const; + + /** + * @return ossimFilename represents an external OSSIM metadata filename. + */ + virtual ossimFilename createMetadataFilename() const; + + + + /** + * @return ossimFilename represents an external OSSIM histogram filename. + */ + virtual ossimFilename createHistogramFilename() const; + + /** + * @return ossimFilename represents an external OSSIM valid vertices filename. + */ + virtual ossimFilename createValidVerticesFilename() const; + + + /** + * Outputs vertices to file and updates the internal vertex + * array variable "theValidImageVertices". + * @param vertices Array of ossimIpts to write. + * @param file Name of output file to write to. If file is empty, the + * output file will be the image file with no extension + _vertices.kwl. + * So if the image is "foo.tif" you'll get "foo_vertices.kwl". + * @return true on success, false on error. + */ + virtual bool writeValidImageVertices(const std::vector<ossimIpt>& vertices, + const ossimFilename& file=ossimFilename("")); + + /** + * Opens the valid image vertices file and sets theValidImageVerticesFile + * variable. + * @param vertices_file File name containing valid vertices for image. + * @return true on success, false on error. + */ + virtual bool openValidVertices(const ossimFilename& vertices_file); + + /** + * Creates vertices file name based on image, then tries to open. + * If theImageFile = "foo.tif" it will look for "foo_vertices.kwl". + * @return true on success, false on error. + */ + virtual bool openValidVertices(); + + + /** + * Pure virtual open. Derived classes must implement. + * + * @return Returns true on success, false on error. + * + * @note This method relies on the data member ossimImageData::theImageFile + * being set. Callers should do a "setFilename" prior to calling this + * method or use the ossimImageHandler::open that takes a file name and an + * entry index. + */ + virtual bool open() = 0; + + /** + * Opens the image file. + * + * @param imageFile File to open. + * + * @param entryIndex + * @return true on success, false on error. + */ + virtual bool open(const ossimFilename& imageFile, + ossim_uint32 entryIndex); + + virtual bool open(const ossimFilename& imageFile); + + /** + * Deletes the overview and clears the valid image vertices. Derived + * classes should implement. + */ + virtual void close(); + + /** + * Derived classes must implement this method to be concrete. + * + * @return true if open, false if not. + */ + virtual bool isOpen()const=0; + + /** + * Build a histogram for image file. + * + * @param numberOfRLevels sets the maximum number of reduced resolution + * level to compute histogram for. + * + * @return true on success, false if not open. + */ + virtual bool buildHistogram(int numberOfRLevels=0); + virtual bool buildAllHistograms(int numberOfRLevels=0); + + /** + * Will build over file for theImageFile. + * + * @param includeFullResFlag if true the full resolution layer will also + * be put in the overview format. This is handly for inefficeint formats. + */ + virtual bool buildOverview(ossimImageHandlerOverviewCompressionType compressionType = OSSIM_OVERVIEW_COMPRESSION_NONE, + ossim_uint32 quality = 75, + ossimFilterResampler::ossimFilterResamplerType resampleType = ossimFilterResampler::ossimFilterResampler_BOX, + bool includeFullResFlag=false); + + virtual bool buildAllOverviews(ossimImageHandlerOverviewCompressionType compressionType = OSSIM_OVERVIEW_COMPRESSION_NONE, + ossim_uint32 quality = 75, + ossimFilterResampler::ossimFilterResamplerType resampleType = ossimFilterResampler::ossimFilterResampler_BOX, + bool includeFullResFlag=false); + + /** + * Will build an over file for filename. + * @param filename Name of image file. + * + * @param includeFullResFlag if true the full resolution layer will also + * be put in the overview format. This is handly for inefficeint formats. + */ + virtual bool buildOverview(const ossimFilename& filename, + ossimImageHandlerOverviewCompressionType compressionType = OSSIM_OVERVIEW_COMPRESSION_NONE, + ossim_uint32 quality = 75, + ossimFilterResampler::ossimFilterResamplerType resampleType = ossimFilterResampler::ossimFilterResampler_BOX, + bool includeFullResFlag=false); + + /** + * Populates the keyword list with image geometry information. This + * method is used to relay projection/model information to users. + * + * @param kwl Keyword list that will be initialized with geometry info. + * Returns true if geometry info is present, false if not. + * + * @param prefix The prefix is added to the resulting keyword list + * keywords. So is you if you pass in a prefix of "image01.", the + * keyword ul_lat will be like: "image01.ul_lat: -40.00000" + */ + virtual bool getImageGeometry(ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * Sets the image geometry keyword list. + * + * @note Callers should note that this will override any existing + * geometry. + * + * @note This does not write the geometry to disk, to do so call + * one of the saveImageGeometry methods. + */ + virtual void setImageGeometry(const ossimKeywordlist& kwl); + + /** + * Saves the image geometry to a file that will be made based on the image + * file name. + */ + virtual void saveImageGeometry() const; + + /** + * Saves the image geometry to a file that will be made based on the image + * file name. + */ + virtual void saveImageGeometry(const ossimFilename& geometry_file) const; + + /** + * Pure virtual, derived classes must implement. + * + * @param resLevel Reduced resolution level to return lines of. + * Default = 0 + * + * @return The number of lines for specified reduced resolution level. + */ + virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel = 0) const = 0; + + /** + * Pure virtual, derived classes must implement. + * + * @param resLevel Reduced resolution level to return samples of. + * Default = 0 + * + * @return The number of samples for specified reduced resolution level. + */ + virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel = 0) const = 0; + + /** + * Returns the zero-based (relative) image rectangle for the reduced + * resolution data set (rrds) passed in. Note that rrds 0 is the highest + * resolution rrds. + */ + virtual ossimIrect getImageRectangle(ossim_uint32 resLevel = 0) const; + + /** + * Returns the absolute bounding rectangle of the image. The upper left + * corner may be non-zero if this is a subimage. + */ + virtual ossimIrect getBoundingRect(ossim_uint32 resLevel = 0) const; + + /** + * @param resLevel Reduced resolution set for requested decimation. + * + * @param result ossimDpt to initialize with requested decimation. + * + * @note Initialized "result" with the decimation factor for the passed in + * resLevel. + * Most of the time the returned factor is a square decimation along x + * and y indicated by result.x and .y = 1.0/(resLevel^2) where ^ + * means rasing to the power of. If the resLevel is 1 then the return + * decimation .5, .5. this is not the decimation to each resolution + * level but the total decimation from res level 0. + * So if resLevel is 2 then the return is .25, .25. + * + * @note Derived classes should override if the decimation is anything other + * than a power of two change in each direction per res level. + */ + virtual void getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result) const; + + /** + * This returns all decimation for all levels. + */ + virtual void getDecimationFactors(vector<ossimDpt>& decimations) const; + + /** + * This returns the total number of decimation levels. It is important to + * note that res level 0 or full resolution is included in the list and has + * decimation values 1.0, 1.0 + */ + virtual ossim_uint32 getNumberOfDecimationLevels()const; + + /** + * This method is obsolete. Please use getNumberOfDecimationLevels. + * + * For backwards compatibility this calls getNumberOfDecimationLevels. + */ + virtual ossim_uint32 getNumberOfReducedResSets()const; + + /** + * @param resLevel Reduced resolution set for requested offset. + * + * @return Returns the offset between the relative image rectangle and + * the absolute, or full, image rectangle. This is typically (0,0) unless + * this is a sub-image. If a resLevel other than zero is requested the + * decimation factor will be applied to offset. If resLevel is not valid + * an the ossimIpt returned will be nan's. + */ + ossimIpt getSubImageOffset(ossim_uint32 resLevel) const; + + /** + * Permits initializing this sub-image's offset relative to full image space. + */ + void setSubImageOffset(const ossimIpt& p); + + /** + * Sets the filename + */ + virtual void setFilename(const ossimFilename& filename); + + /** + * Returns the filename + */ + virtual const ossimFilename& getFilename()const; + + /** + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * Determines if the passed in reslution level is valid + */ + virtual bool isValidRLevel(ossim_uint32 resLevel) const; + + /** + * Connection rule. Since image handler currently don't have any + * inputs this will just return false saying we can't connect anything + * to an image handler. + */ + bool canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object) const; + + /** + * ordering specifies how the vertices should be arranged. + * valid image vertices is basically the tightly fit convex hull + * of the image. Usually an image has NULL values and are + * internally not upright rectangular. This can cause + * problems some spatial filters. + * + * The default implementation is to return the bounding rect. + */ + virtual void getValidImageVertices(vector<ossimIpt>& validVertices, + ossimVertexOrdering ordering=OSSIM_CLOCKWISE_ORDER, + ossim_uint32 resLevel=0)const; + + /** + * Indicates whether or not the image handler can control output + * band selection via the setOutputBandList method. + */ + virtual bool isBandSelector() const; + + /** + * If the image handler "isBandSeletor()" then the band selection + * of the output chip can be controlled. + * Returns true on success, false on error. + */ + virtual bool setOutputBandList(const std::vector<ossim_uint32>& band_list); + + /** + * Indicates whether or not the image is tiled internally. + * This implementation returns true if (getImageTileWidth() && + * getImageTileHeight()) are both non zero. + * Override in the image handler if something else is desired. + * Returns true if tiled, false if not. + */ + virtual bool isImageTiled() const; + + /** + * Returns the tile width of the image or 0 if the image is not tiled. + * Note: this is not the same as the ossimImageSource::getTileWidth which + * returns the output tile width which can be different than the internal + * image tile width on disk. + */ + virtual ossim_uint32 getImageTileWidth() const = 0; + + /** + * Returns the tile width of the image or 0 if the image is not tiled. + * Note: this is not the same as the ossimImageSource::getTileWidth which + * returns the output tile width which can be different than the internal + * image tile width on disk. + */ + virtual ossim_uint32 getImageTileHeight() const = 0; + + virtual bool hasMetaData() const; + + virtual ossimRefPtr<ossimNBandLutDataObject> getLut()const; + + /** + * There is an external file with an omd extension. this file contains + * additional information about the image such as the null pixel, min and + * max values. + * For general raster it will contain much more than that. + */ + void loadMetaData(); + + /** + * Retuns the min pixel value. If there was an external eta data file + * then use the meta data from that file. If not given then we will + * return the default min + */ + virtual double getMinPixelValue(ossim_uint32 band=0)const; + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + virtual double getNullPixelValue(ossim_uint32 band=0)const; + + /** + * @return The current entry number. + * + * @note This implementation returns 0. Derived classes should override + * if of multiple entry image type. + */ + virtual ossim_uint32 getCurrentEntry()const; + + /** + * @return The number of entries (images) in the image file. + */ + virtual ossim_uint32 getNumberOfEntries()const; + + /** + * @param entryList This is the list to initialize with entry indexes. + * + * @note This implementation returns puts one entry "0" in the list. + */ + virtual void getEntryList(std::vector<ossim_uint32>& entryList) const; + + /** + * @param entryStringList List to initialize with strings associated with + * entries. + * + * @note This implementation calls getEntryList and converts entries in + * the list to strings. Derived classes that support multiple entries + * with associated strings should re-implement. + */ + virtual void getEntryStringList( + std::vector<ossimString>& entryStringList) const; + + /** + * @param entryIdx Entry number to select. + * + * @note The implementation does nothing. Derived classes that handle + * multiple images should override. + * + * @return true if it was able to set the current entryadn false otherwise + */ + virtual bool setCurrentEntry(ossim_uint32 entryIdx); + + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + + /** + * Returns the image file with extension set. + * + * Examples: + * + * - theImageFile = "foo.hdf" + * - The number of entries = 1 + * - ext parameter = "geom" + * - return of method will = "foo.geom" + * + * - theImageFile = "foo.hdf" + * - The number of entries = 12 + * - The current entry = 3 + * - ext parameter = "geom" + * - return of method will = "foo_e3.geom" + * + * @param ext Extension to tack onto file. Can have or have not ".", it will + * be added if "." is not the first character. + * + * @param set_e0_prefix If true and the number of entries = 1 then + * "foo.geom" would come out "foo_e0.geom" instead. Default = false. + * + * @return theImageFile with sent extension. + */ + ossimFilename getFilenameWithThisExtension(const ossimString& ext, + bool set_e0_prefix=false) const; + +protected: + /** + * Opens file and attempts to initialize the valid image vertices. + * Returns true on success, false on error. + */ + bool initVertices(const char* file); + + /** + * Will complete the opening process. + * If there are overviews it will open them. + * If there is meta data it will open that and if there + * is valid vertices it will open that. + */ + void completeOpen(); + + ossimFilename theImageFile; + ossimTiffTileSource* theOverview; + ossimIpt theSubImageOffset; + vector<ossimIpt> theValidImageVertices; + ossimImageMetaData theMetaData; + ossimKeywordlist theGeometryKwl; + ossimRefPtr<ossimNBandLutDataObject> theLut; + +TYPE_DATA +}; + +#endif /* #ifndef ossimImageHandler_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/srtm/ossimSrtmTileSource.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/srtm/ossimSrtmTileSource.cpp new file mode 100644 index 0000000000..4e9b3adad7 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/srtm/ossimSrtmTileSource.cpp @@ -0,0 +1,145 @@ +//---------------------------------------------------------------------------- +// Copyright (c) 2005, David Burken, all rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Image handler class for a Shuttle Radar Topography Mission (SRTM) file. +// +//---------------------------------------------------------------------------- +// $Id: ossimSrtmTileSource.cpp,v 1.4 2005/06/15 14:15:22 gpotts Exp $ + +#include <imaging/formats/srtm/ossimSrtmTileSource.h> +#include <base/data_types/ossimDirectory.h> +#include <base/common/ossimTrace.h> +#include <support_data/srtm/ossimSrtmSupportData.h> + +RTTI_DEF1_INST(ossimSrtmTileSource, + "ossimSrtmTileSource", + ossimGeneralRasterTileSource) + +static ossimTrace traceDebug("ossimSrtmTileSource:debug"); + + +//******************************************************************* +// Public Constructor: +//******************************************************************* +ossimSrtmTileSource::ossimSrtmTileSource() + : + ossimGeneralRasterTileSource(), + theSrtmSupportData() +{ +} + +//******************************************************************* +// Public Constructor: +//******************************************************************* +ossimSrtmTileSource::ossimSrtmTileSource(const ossimKeywordlist& kwl, + const char* prefix) + : + ossimGeneralRasterTileSource(), + theSrtmSupportData() +{ + if (loadState(kwl, prefix) == false) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + } +} + +//******************************************************************* +// Destructor: +//******************************************************************* +ossimSrtmTileSource::~ossimSrtmTileSource() +{ +} + +bool ossimSrtmTileSource::open() +{ + static const char MODULE[] = "ossimSrtmTileSource::open"; + + if (traceDebug()) + { + CLOG << " Entered..." << endl + << " trying to open file " << theImageFile << std::endl; + } + + if (!theSrtmSupportData.setFilename(theImageFile, true)) + { + if (traceDebug()) CLOG << " Unable to set filename"<< std::endl; + + return false; + } + + bool result = ossimGeneralRasterTileSource::open(); + + if (traceDebug()) CLOG << " Exited with " << (result?"true":"false") << " ..."<< std::endl; + + return result; +} + +bool ossimSrtmTileSource::getImageGeometry(ossimKeywordlist& kwl, + const char* prefix) +{ + // Check for override for an external geometry file, or a previous save. + if(ossimImageHandler::getImageGeometry(kwl, prefix)) + { + return true; + } + + if (theSrtmSupportData.getImageGeometry(kwl, prefix)) + { + // Capture for next time... + setImageGeometry(kwl); + return true; + } + + return false; +} + +bool ossimSrtmTileSource::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + if (theSrtmSupportData.saveState(kwl, prefix)) + { + return ossimImageHandler::saveState(kwl,prefix); + } + return false; +} + +bool ossimSrtmTileSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + if (theSrtmSupportData.loadState(kwl, prefix)) + { + setFilename(theSrtmSupportData.getFilename()); + + if (ossimGeneralRasterTileSource::open()) + { + // Must call to pick up id for connections. + return ossimImageSource::loadState(kwl, prefix); + } + } + + return false; +} + +ossimString ossimSrtmTileSource::getShortName() const +{ + return ossimString("SRTM"); +} + +ossimString ossimSrtmTileSource::getLongName() const +{ + return ossimString("SRTM reader"); +} + +ossimString ossimSrtmTileSource::className() const +{ + return ossimString("ossimSrtmTileSource"); +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/srtm/ossimSrtmTileSource.h b/Utilities/OSSIM/ossim_core/imaging/formats/srtm/ossimSrtmTileSource.h new file mode 100644 index 0000000000..bf74e6a484 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/srtm/ossimSrtmTileSource.h @@ -0,0 +1,72 @@ +//---------------------------------------------------------------------------- +// Copyright (c) 2005, David Burken, all rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Image handler class for a Shuttle Radar Topography Mission (SRTM) file. +// +//---------------------------------------------------------------------------- +// $Id: ossimSrtmTileSource.h,v 1.2 2005/03/14 21:47:33 dburken Exp $ +#ifndef ossimSrtmTileSource_HEADER +#define ossimSrtmTileSource_HEADER + +#include <imaging/formats/general_raster/ossimGeneralRasterTileSource.h> +#include <support_data/srtm/ossimSrtmSupportData.h> + + +class OSSIMDLLEXPORT ossimSrtmTileSource : public ossimGeneralRasterTileSource +{ +public: + ossimSrtmTileSource(); + + ossimSrtmTileSource(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual ~ossimSrtmTileSource(); + + virtual ossimString getShortName() const; + + virtual ossimString getLongName() const; + + virtual ossimString className() const; + + virtual bool open(); + + /** + * Populates the keyword list with image geometry information. This + * method is used to relay projection/model information to users. + * + * @return true if geometry info is present, false if not. + */ + virtual bool getImageGeometry(ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * Method to save the state of an object to a keyword list. + * @return true on success, false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. + * + * @return true on success, false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix = NULL); + +private: + ossimSrtmSupportData theSrtmSupportData; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/tiff/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/formats/tiff/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/tiff/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimQuickbirdTiffTileSource.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimQuickbirdTiffTileSource.cpp new file mode 100644 index 0000000000..c9da02fc88 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimQuickbirdTiffTileSource.cpp @@ -0,0 +1,88 @@ +//---------------------------------------------------------------------------- +// Copyright (c) 2005, David Burken, all rights reserved. +// +// License: See top level LICENSE.txt file. +// +// Author: David Burken +// +// Copied from ossimQuickbirdTiffTileSource written by Garrett Potts. +// +// Description: +// +// Class definition for specialized image handler to pick up offsets from +// Quick Bird ".TIL" files. +// +//---------------------------------------------------------------------------- +// $Id: ossimQuickbirdTiffTileSource.cpp,v 1.3 2006/01/06 16:46:46 dburken Exp $ + +#include <imaging/formats/tiff/ossimQuickbirdTiffTileSource.h> +#include <support_data/qb/ossimQuickbirdTile.h> +#include <base/common/ossimTrace.h> + +RTTI_DEF1(ossimQuickbirdTiffTileSource, + "ossimQuickbirdTiffTileSource", + ossimTiffTileSource); + +static const ossimTrace traceDebug("ossimQuickbirdTiffTileSource:debug"); + +bool ossimQuickbirdTiffTileSource::open() +{ + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimQuickbirdTiffTileSource::open() DEBUG: entered ..." + << std::endl; + } + + ossimFilename file = theImageFile; + file = file.replaceAllThatMatch("_R[0-9]+C[0-9]+"); + ossimQuickbirdTile tileFile; + + file.setExtension("TIL"); + if(!tileFile.open(file)) + { + file.setExtension("til"); + if(!tileFile.open(file)) + { + return false; + } + } + + // Call the base class open... + if(!ossimTiffTileSource::open()) + { + return false; + } + + ossimQuickbirdTileInfo info; + + // try upcase... + if(!tileFile.getInfo(info, theImageFile.file().upcase())) + { + // try downcase... + if(!tileFile.getInfo(info, theImageFile.file().downcase())) + { + return false; + } + } + + if((info.theUlXOffset != OSSIM_INT_NAN) && + (info.theUlYOffset != OSSIM_INT_NAN)) + { + theSubImageOffset = ossimIpt(info.theUlXOffset, info.theUlYOffset); + } + else + { + theSubImageOffset = ossimIpt(0,0); + } + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimQuickbirdTiffTileSource::open() DEBUG:" + << "\nSub image offset = " << theSubImageOffset + << std::endl; + } + + return true; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimQuickbirdTiffTileSource.h b/Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimQuickbirdTiffTileSource.h new file mode 100644 index 0000000000..b4e8a0bd45 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimQuickbirdTiffTileSource.h @@ -0,0 +1,33 @@ +//---------------------------------------------------------------------------- +// Copyright (c) 2005, David Burken, all rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Copied from ossimQuickbirdNitfTileSource written by Garrett Potts. +// +// Description: +// +// Class declaration for specialized image handler to pick up offsets from +// Quick Bird ".TIL" files. +// +//---------------------------------------------------------------------------- +// $Id: ossimQuickbirdTiffTileSource.h,v 1.1 2005/11/08 21:52:47 dburken Exp $ +#ifndef ossimQuickbirdTiffTileSource_HEADER +#define ossimQuickbirdTiffTileSource_HEADER + +#include <imaging/formats/tiff/ossimTiffTileSource.h> + +class ossimQuickbirdTiffTileSource : public ossimTiffTileSource +{ +public: + virtual bool open(); + + protected: + +TYPE_DATA +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimTiffOverviewBuilder.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimTiffOverviewBuilder.cpp new file mode 100644 index 0000000000..a89d1a271c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimTiffOverviewBuilder.cpp @@ -0,0 +1,1580 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class definition for TiffOverviewBuilder +//******************************************************************* +// $Id: ossimTiffOverviewBuilder.cpp,v 1.44 2005/09/27 10:57:36 gpotts Exp $ + +#include <cstring> +#include <sstream> +using namespace std; + +#include <tiffio.h> + +#include <imaging/formats/tiff/ossimTiffOverviewBuilder.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <base/common/ossimCommon.h> +#include <base/common/ossimErrorCodes.h> +#include <base/context/ossimErrorContext.h> +#include <base/common/ossimStdOutProgress.h> +#include <base/data_types/ossimIpt.h> +#include <base/data_types/ossimDpt3d.h> +#include <base/data_types/ossimIrect.h> +#include <base/data_types/ossimFilename.h> +#include <imaging/formats/ossimImageHandler.h> +#include <imaging/ossimImageData.h> +#include <imaging/ossimImageMetaData.h> +#include <base/common/ossimTrace.h> +#include <base/misc/lookup_tables/ossimScalarTypeLut.h> + +RTTI_DEF3(ossimTiffOverviewBuilder, "ossimTiffOverviewBuilder", ossimSource, ossimProcessInterface, ossimConnectableObjectListener) + +static ossimTrace traceDebug("ossimTiffOverviewBuilder:degug"); + + +//******************************************************************* +// Public Constructor: +//******************************************************************* +ossimTiffOverviewBuilder:: +ossimTiffOverviewBuilder(ossimImageHandler* imageHandler) + : + ossimSource(), + ossimProcessInterface(), + ossimConnectableObjectListener(), + theImageHandler(imageHandler), + theOutputFile(ossimFilename::NIL), + theNullDataBuffer(NULL), + theBytesPerPixel(1), + theBitsPerSample(8), + theTileWidth(0), + theTileHeight(0), + theTileSizeInBytes(0), + theSampleFormat(0), + theCurrentTiffDir(0), + theTiffCompressType(COMPRESSION_NONE), + theJpegCompressQuality(DEFAULT_COMPRESS_QUALITY), + theResampleType(ossimFilterResampler::ossimFilterResampler_BOX) +{ + static const char MODULE[] + = "ossimTiffOverviewBuilder::ossimTiffOverviewBuilder"; + + if (!theImageHandler) + { + // Set the error... + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR:" + << "\nNull image handler pointer passed to constructor! Returning..." + << endl; + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "%s File %s line %d\nNULL pointer passed to constructor!", + MODULE, + __FILE__, + __LINE__); + return; + } + else if (theImageHandler->getErrorStatus() == + ossimErrorCodes::OSSIM_ERROR) + { + // Set the error... + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR:" + << "\nError detected in image handler! Returning..." + << endl; + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "%s file %s line %d\nImageHandler error detected!", + MODULE, + __FILE__, + __LINE__); + return; + } + + // Note: Need a default overview tile size in preferences... + ossimIpt tileSize; + ossimGetDefaultTileSize(tileSize); + theTileWidth = tileSize.x; + theTileHeight = tileSize.y; + + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\ntheTileWidth: " << theTileWidth + << "\ntheTileHeight: " << theTileHeight + << "\nSource image is tiled: " + << (theImageHandler->isImageTiled()?"true":"false") + << "\ntheImageHandler->getTileWidth(): " + << theImageHandler->getTileWidth() + << "\ntheImageHandler->getTileHeight(): " + << theImageHandler->getTileHeight() + << "\ntheImageHandler->getImageTileWidth(): " + << theImageHandler->getImageTileWidth() + << "\ntheImageHandler->getImageTileHeight(): " + << theImageHandler->getImageTileHeight() + << endl; + } + + switch(theImageHandler->getOutputScalarType()) + { + case OSSIM_UINT8: + theBitsPerSample = 8; + theBytesPerPixel = 1; + theSampleFormat = SAMPLEFORMAT_UINT; + break; + + case OSSIM_USHORT11: + case OSSIM_UINT16: + theBitsPerSample = 16; + theBytesPerPixel = 2; + theSampleFormat = SAMPLEFORMAT_UINT; + break; + + case OSSIM_SINT16: + theBitsPerSample = 16; + theBytesPerPixel = 2; + theSampleFormat = SAMPLEFORMAT_INT; + break; + + case OSSIM_UINT32: + theBitsPerSample = 32; + theBytesPerPixel = 4; + theSampleFormat = SAMPLEFORMAT_UINT; + break; + + case OSSIM_FLOAT32: + theBitsPerSample = 32; + theBytesPerPixel = 4; + theSampleFormat = SAMPLEFORMAT_IEEEFP; + break; + + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_FLOAT64: + theBitsPerSample = 64; + theBytesPerPixel = 8; + theSampleFormat = SAMPLEFORMAT_IEEEFP; + break; + + default: + // Set the error... + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR:" + << "\nUnknow pixel type: " + << (ossimScalarTypeLut::instance()-> + getEntryString(theImageHandler->getOutputScalarType())) + << endl; + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "Unknown pixel type!", + __FILE__, + __LINE__); + return; + } + + theTileSizeInBytes = theTileWidth * theTileHeight * theBytesPerPixel; + + //*** + // Make a buffer to pass to pass to the write tile methods when an image + // handler returns a null tile. + //*** + theNullDataBuffer = new ossim_uint8[theTileSizeInBytes]; + + memset(theNullDataBuffer, 0, theTileSizeInBytes); // Fill it with zeroes. + + // Set the output filename to a default. + theOutputFile = theImageHandler->getFilename(); + if(theImageHandler->getNumberOfEntries() > 1) + { + ossim_uint32 currentEntry = theImageHandler->getCurrentEntry(); + theOutputFile.setExtension(""); + theOutputFile += "_e"; + theOutputFile += ossimString::toString(currentEntry); + + //--- + // Note: Set extension was not used here deliberately to avoid messing + // up a MODIS file in hdf format with multiple '.'s in the file + // name. + //--- + theOutputFile += ".ovr"; + } + else + { + theOutputFile.setExtension("ovr"); + } + + if (theOutputFile == theImageHandler->getFilename()) + { + // Don't allow this. + theOutputFile = ossimFilename::NIL; + } +} + +//******************************************************************* +// Destructor: +//******************************************************************* +ossimTiffOverviewBuilder::~ossimTiffOverviewBuilder() +{ + if (theNullDataBuffer) + { + delete [] theNullDataBuffer; + theNullDataBuffer = NULL; + } +} + +void ossimTiffOverviewBuilder::setResampleType(ossimFilterResampler::ossimFilterResamplerType resampleType) +{ + theResampleType = resampleType; +} + +//******************************************************************* +// Public Method: +//******************************************************************* +bool +ossimTiffOverviewBuilder::buildOverview(const ossimFilename& overview_file, + bool copy_all) +{ + static const char MODULE[] = "ossimTiffOverviewBuilder::buildOverview"; + + if (theErrorStatus == ossimErrorCodes::OSSIM_ERROR) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR:" + << "\nError status has been previously set! Returning..." + << endl; + return false; + } + + if (overview_file == theImageHandler->getFilename() || + overview_file == ossimFilename::NIL) + { + return false; + } + else + { + theOutputFile = overview_file; + } + + //*** + // See if the file can be opened for writing. + // Note: If this file existed previously it will be overwritten. + //*** + TIFF* tif = TIFFOpen(overview_file.c_str(), "w"); + if (!tif) + { + // Set the error... + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_OPEN_FILE_ERROR, + "%s file %s line %d\nCannot open file: %s", + MODULE, + __FILE__, + __LINE__, + overview_file.c_str()); + return false; + } + + //--- + // Check for a listeners. If the list is empty, add a standard out listener + // so that command line apps like img2rr will get some progress. + //--- + ossimStdOutProgress* progressListener = NULL; + if (theListenerList.empty()) + { + progressListener = new ossimStdOutProgress(0, true); + addListener(progressListener); + } + + setProcessStatus(ossimProcessInterface::PROCESS_STATUS_EXECUTING); + setPercentComplete(0.0); + + if (copy_all) + { + if (!writeR0(tif)) + { + // Set the error... + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "File %s line %d\nError copying image!", + __FILE__, + __LINE__); + TIFFClose(tif); + if (progressListener) + { + removeListener(progressListener); + delete progressListener; + progressListener = NULL; + } + return false; + } + } + + if (needsAborting()) + { + TIFFClose(tif); + if (progressListener) + { + removeListener(progressListener); + delete progressListener; + progressListener = NULL; + } + return false; + } + + //*** + // Calculate the number of reduced resolution data sets (rrds). + // The image will be reduced until the smallest dimension is + // It will go all the way to a 1x1 pixel. + //*** + ossim_int32 number_of_sets = getNumberOfSets(); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " Number of reduced res sets: " << number_of_sets + << endl; + } + + if (!number_of_sets) + { + ossimNotify(ossimNotifyLevel_INFO) + << MODULE << " NOTICE:" + << "\nFile size not large enough to require reduced resolution" + << " data sets." + << "\nReturning..." << endl; + TIFFClose(tif); + if (progressListener) + { + removeListener(progressListener); + delete progressListener; + progressListener = NULL; + } + return false; + } + + if (!writeR1(tif)) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Error copying image!" << endl; + TIFFClose(tif); + if (progressListener) + { + removeListener(progressListener); + delete progressListener; + progressListener = NULL; + } + return false; + } + + if (needsAborting()) + { + TIFFClose(tif); + if (progressListener) + { + removeListener(progressListener); + delete progressListener; + progressListener = NULL; + } + return false; + } + + if (number_of_sets > 1) + { + for (ossim_int32 i=2; i<=number_of_sets; ++i) + { + if (!writeRn(tif, overview_file, i)) + { + // Set the error... + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_WRITE_FILE_ERROR, + "\ +%s file %s line %d\nError creating reduced res set!", + MODULE, + __FILE__, + __LINE__); + TIFFClose(tif); + if (progressListener) + { + removeListener(progressListener); + delete progressListener; + progressListener = NULL; + } + return false; + } + if (needsAborting()) + { + TIFFClose(tif); + if (progressListener) + { + removeListener(progressListener); + delete progressListener; + progressListener = NULL; + } + return false; + } + } + } + + // Close the tif file out. + TIFFClose(tif); + + ossimFilename file=overview_file; + file = file.setExtension("omd"); + ossimKeywordlist kwl; + if(file.exists()) + { + kwl.addFile(file.c_str()); + + } + ossimImageMetaData metaData(theImageHandler->getOutputScalarType(), + theImageHandler->getNumberOfInputBands()); + + uint32 i= 0; + + for(i = 0; i < metaData.getNumberOfBands(); ++i) + { + metaData.setMinPix(i, theImageHandler->getMinPixelValue(i)); + metaData.setMaxPix(i, theImageHandler->getMaxPixelValue(i)); + metaData.setNullPix(i, theImageHandler->getNullPixelValue(i)); + } + metaData.saveState(kwl); + kwl.write(file.c_str()); + + setCurrentMessage(ossimString("Finished...")); + + // Remove the listener if we had one. + if (progressListener) + { + removeListener(progressListener); + delete progressListener; + progressListener = NULL; + } + + return true; +} + +//******************************************************************* +// Private Method: +//******************************************************************* +bool ossimTiffOverviewBuilder::writeR0(TIFF* tif) +{ + static const char MODULE[] = "ossimTiffOverviewBuilder::writeR0"; + + if (!setTags(tif, 0)) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Error writing tags!" << endl; + return false; + } + + ossim_int32 samples = theImageHandler->getNumberOfSamples(); + ossim_int32 lines = theImageHandler->getNumberOfLines(); + ossim_int32 tilesWide = samples % theTileWidth ? + samples / theTileWidth + 1 : samples / theTileWidth; + ossim_int32 tilesHigh = lines % theTileHeight ? + lines / theTileHeight + 1 : lines / theTileHeight; + ossim_int32 numberOfTiles = tilesWide * tilesHigh; + + int tileNumber = 0; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimTiffOverviewBuilder::writeR0 DEBUG:" + << "\nsamples: " << samples + << "\nlines: " << lines + << "\ntilesWide: " << tilesWide + << "\ntilesHigh: " << tilesHigh + << "\nnumberOfTiles: " << numberOfTiles + << endl; + } + + setCurrentMessage(ossimString("Copying r0...")); + + //*** + // Tile loop in the line direction. + //*** + for(int i = 0; i < tilesHigh; ++i) + { + ossimIpt origin(0, 0); + origin.y = i * theTileHeight; + + //*** + // Tile loop in the sample (width) direction. + //*** + for(int j = 0; j < tilesWide; ++j) + { + origin.x = j * theTileWidth; + + ossimRefPtr<ossimImageData> t = + theImageHandler->getTile(ossimIrect(origin.x, + origin.y, + origin.x +(theTileWidth-1), + origin.y +(theTileHeight-1))); + + //*** + // Band loop. + //*** + for (uint32 band=0; + band<theImageHandler->getNumberOfInputBands(); + ++band) + { + tdata_t data; + + if ( t.valid() && (t->getDataObjectStatus() != OSSIM_NULL) ) + { + // Grab a pointer to the tile for the band. + data = static_cast<tdata_t>(t->getBuf(band)); + } + else + { + data = static_cast<tdata_t>(theNullDataBuffer); + } + + // Write the tile. + int bytesWritten = 0; + bytesWritten = TIFFWriteTile(tif, + data, + origin.x, + origin.y, + 0, // z + band); // sample + + if (bytesWritten != theTileSizeInBytes) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR:" + << "Error returned writing tiff tile: " << i + << "\nExpected bytes written: " << theTileSizeInBytes + << "\nBytes written: " << bytesWritten + << endl; + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + return false; + } + + } // End of band loop. + + ++tileNumber; + + } // End of tile loop in the sample (width) direction. + + if (needsAborting()) + { + setPercentComplete(100.0); + break; + } + else + { + double tile = tileNumber; + double numTiles = numberOfTiles; + setPercentComplete(tile / numTiles * 100.0); + } + + } // End of tile loop in the line (height) direction. + + //*** + // Write the current dirctory. + //*** + if (!TIFFWriteDirectory(tif)) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Error writing directory!" << endl; + return false; + } + + ++theCurrentTiffDir; + + return true; +} + +//******************************************************************* +// Private Method: +//******************************************************************* +bool ossimTiffOverviewBuilder::writeR1(TIFF* tif) +{ + static const char MODULE[] = "ossimTiffOverviewBuilder::writeR1"; + + //--- + // Resample the original full res data from the ImageHandler to the + // first reduced res set. + //--- + setCurrentMessage(ossimString("creating r1...")); + if (!setTags(tif, 1)) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Error writing tags!" << endl; + return false; + } + + ossimRefPtr<ossimImageData> imageBuffer = ossimImageDataFactory::instance()->create(0, theImageHandler); + if(!imageBuffer.valid()) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR:" + << "Error returned allocating tile buffer at line " << __LINE__ << " in file " << __FILE__ + << endl; + return false; + } +// ossimIrect rect = theImageHandler->getBoundingRect(1); + ossimIrect rect = theImageHandler->getBoundingRect(); + ossim_int32 samples = theImageHandler->getNumberOfSamples(); + ossim_int32 lines = theImageHandler->getNumberOfLines(); + ossim_int32 outputSamples = samples / 2; + ossim_int32 outputLines = lines / 2; + ossim_int32 outputTilesWide = (outputSamples % theTileWidth ? + outputSamples / theTileWidth + 1 : + outputSamples / theTileWidth); + ossim_int32 outputTilesHigh = (outputLines % theTileHeight ? + outputLines / theTileHeight + 1 : + outputLines / theTileHeight); + + ossim_int32 numberOfTiles = outputTilesWide * outputTilesHigh; + imageBuffer->initialize(); + imageBuffer->setImageRectangle(ossimIrect(0, 0, theTileWidth-1, theTileHeight-1)); + // Allocate buffers for the output tiles. +// ossim_uint8** buf = new ossim_uint8*[theImageHandler->getNumberOfInputBands()]; + uint32 band; +// for(band=0; band<theImageHandler->getNumberOfInputBands(); ++band) +// { +// buf[band] = new ossim_uint8[theTileSizeInBytes]; +// } + +// if (outputLines < theTileHeight || outputSamples < theTileWidth) +// { +// // The full tile will not be filled so make sure it's blank. +// for(band=0; band<theImageHandler->getNumberOfInputBands(); ++band) +// { +// memset((void*)buf[band], 0, theTileSizeInBytes); +// } +// } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimTiffOverviewBuilder::writeR1 DEBUG:" + << "\nsamples: " << samples + << "\nlines: " << lines + << "\noutputTilesWide: " << outputTilesWide + << "\noutputTilesHigh: " << outputTilesHigh + << "\nnumberOfTiles: " << numberOfTiles + << "\nrect: " << rect + << endl; + } + + theNullPixelValues.resize(theImageHandler->getNumberOfOutputBands()); + int tileNumber = 0; + ossim_uint32 idx = 0; + + for(idx = 0; idx < theNullPixelValues.size(); ++idx) + { + theNullPixelValues[idx] = theImageHandler->getNullPixelValue(idx); + + } + //*** + // Tile loop in the line direction. + //*** + for(int i = 0; i < outputTilesHigh; ++i) + { + //*** + // Tile loop in the sample (width) direction. + //*** + for(int j = 0; j < outputTilesWide; ++j) + { + //*** + // For each output tile, four source tiles must be grabbed. + //*** + + // Get the upper left tile. + ossimIpt origin(j * 2 * theTileWidth, + i * 2 * theTileHeight); + + origin = origin + rect.ul(); + ossimRefPtr<ossimImageData> t = + theImageHandler->getTile(ossimIrect(origin.x, + origin.y, + origin.x +(theTileWidth-1), + origin.y +(theTileHeight-1))); + imageBuffer->setDataObjectStatus(OSSIM_FULL); + imageBuffer->makeBlank(); + if(t.valid()&&(t->getBuf())&&(t->getDataObjectStatus()!=OSSIM_EMPTY)) + { + // Band loop. + for (band=0; band<theImageHandler->getNumberOfInputBands(); band++) + { + tdata_t data; + data = static_cast<tdata_t>(t->getBuf(band)); + resampleTile(data, + imageBuffer->getBuf(band), + UL, + theNullPixelValues[band]); + } + } + origin.x += theTileWidth; + + t = theImageHandler->getTile(ossimIrect(origin.x, + origin.y, + origin.x +(theTileWidth-1), + origin.y +(theTileHeight-1))); + + if(t.valid()&&(t->getBuf())&&(t->getDataObjectStatus()!=OSSIM_EMPTY)) + { + // Band loop. + for (band=0; band<theImageHandler->getNumberOfInputBands(); ++band) + { + tdata_t data; + + // Grab a pointer to the tile for the band. + data = static_cast<tdata_t>(t->getBuf(band)); + resampleTile(data, + imageBuffer->getBuf(band), + UR, + theNullPixelValues[band]); + } + } + + // Get the lower left tile. + origin.x -= theTileWidth; + origin.y += theTileHeight; + + t = theImageHandler->getTile(ossimIrect(origin.x, + origin.y, + origin.x +(theTileWidth-1), + origin.y +(theTileHeight-1))); + + // Band loop. + if(t.valid()&&(t->getBuf())&&(t->getDataObjectStatus()!=OSSIM_EMPTY)) + { + for (band=0; band<theImageHandler->getNumberOfInputBands(); ++band) + { + tdata_t data; + + data = static_cast<tdata_t>(t->getBuf(band)); + + resampleTile(data, + imageBuffer->getBuf(band), + LL, + theNullPixelValues[band]); + } + } + + // Get the lower right tile. + origin.x += theTileWidth; + + t = theImageHandler->getTile(ossimIrect(origin.x, + origin.y, + origin.x +(theTileWidth-1), + origin.y +(theTileHeight-1))); + + // + // Band loop. + // Since this is the last quadrant the tile can be written to the + // tif file in the band loop. + // + for (band=0; band<theImageHandler->getNumberOfInputBands(); ++band) + { + tdata_t data; + + if ( t.valid() && t->getBuf() &&(t->getDataObjectStatus() != OSSIM_EMPTY)) + { + // Grab a pointer to the tile for the band. + data = static_cast<tdata_t>(t->getBuf(band)); + resampleTile(data, + imageBuffer->getBuf(band), + LR, + theNullPixelValues[band]); + } + + + // Write the tile. + int bytesWritten = 0; + bytesWritten = TIFFWriteTile(tif, + imageBuffer->getBuf(band), + j*theTileWidth, + i*theTileHeight, + 0, // z + band); // sample + + if (bytesWritten != theTileSizeInBytes) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR:" + << "Error returned writing tiff tile: " << i + << "\nExpected bytes written: " << theTileSizeInBytes + << "\nBytes written: " << bytesWritten + << endl; + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + + return false; + } + + } + + ++tileNumber; + + } // End of tile loop in the sample (width) direction. + + if (needsAborting()) + { + setPercentComplete(100.0); + break; + } + else + { + double tile = tileNumber; + double numTiles = numberOfTiles; + setPercentComplete(tile / numTiles * 100.0); + } + + } // End of tile loop in the line (height) direction. + + //*** + // Write the current dirctory. + //*** + if (!TIFFWriteDirectory(tif)) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Error writing directory!" << endl; + return false; + } + + theCurrentTiffDir++; + + return true; +} + +//******************************************************************* +// Private Method: +//******************************************************************* +bool ossimTiffOverviewBuilder::writeRn(TIFF* tif, + const ossimFilename& overview_file, + ossim_int32 rrds_level) +{ + static const char MODULE[] = "ossimTiffOverviewBuilder::writeRn"; + + //--- + // Resample a previous reduced res level to the next level from the + // same tif file. + //--- + ostringstream os; + os << "creating r" << rrds_level << "..."; + setCurrentMessage(os.str()); + + TIFF* tifr = NULL; + + ossimRefPtr<ossimImageData> imageBuffer = ossimImageDataFactory::instance()->create(0, theImageHandler); + if(!imageBuffer.valid()) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR:" + << "Error returned allocating tile buffer at line " << __LINE__ << " in file " << __FILE__ + << endl; + return false; + } + if (theCurrentTiffDir) + { + //*** + // Open up the same tif file being written to read only to grab the + // tiles from the previous reduced res set. + // + // NOTE: The 'm' in "rm" is to not memory map the image; hence, + // saving memory. + //*** + tifr = TIFFOpen(overview_file.c_str(), "rm"); + if (!tifr) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR!" + << "\nCannot open file: " << overview_file.c_str() + << "\nReturning..." << endl; + return false; + } + + //*** + // Set the directory of the read only tiff. + //*** + if (!TIFFSetDirectory(tifr, theCurrentTiffDir - 1)) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR setting directory " + << ossim_int32(theCurrentTiffDir - 1) << "!" << endl; + TIFFClose(tifr); + return false; + } + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR:" + << "No previous reduced res set to copy from!" + << endl; + return false; + } + + if (!setTags(tif, rrds_level)) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Error writing tags!" << endl; + TIFFClose(tifr); + return false; + } + + ossim_int32 samples; + ossim_int32 lines; + TIFFGetField( tifr, TIFFTAG_IMAGEWIDTH, &samples ); + TIFFGetField( tifr, TIFFTAG_IMAGELENGTH, &lines ); + +// ossim_int32 outputSamples = (ossim_int32)ceil(samples / 2.0); +// ossim_int32 outputLines = (ossim_int32)ceil(lines / 2.0); + ossim_int32 outputSamples = samples / 2; + ossim_int32 outputLines = lines / 2; + ossim_int32 outputTilesWide = outputSamples % theTileWidth ? + outputSamples / theTileWidth + 1 : + outputSamples / theTileWidth; + ossim_int32 outputTilesHigh = outputLines % theTileHeight ? + outputLines / theTileHeight + 1 : + outputLines / theTileHeight; + + ossim_int32 numberOfTiles = outputTilesWide * outputTilesHigh; + + imageBuffer->initialize(); + imageBuffer->setImageRectangle(ossimIrect(0, 0, theTileWidth-1, theTileHeight-1)); + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_INFO) + << MODULE << " DEBUG:" + << "\nrrds_level: " << rrds_level + << "\noutputSamples: " << outputSamples + << "\noutputLines: " << outputLines + << "\nnumberOfTiles: " << numberOfTiles + << endl; + } + + // Allocate buffers for the output tiles. +// ossim_uint8** buf = +// new ossim_uint8*[theImageHandler->getNumberOfInputBands()]; + ossim_uint32 band; +// for(band=0; band<theImageHandler->getNumberOfInputBands(); band++) +// { +// buf[band] = new ossim_uint8[theTileSizeInBytes]; +// } + + ossim_uint8* tbuf = new ossim_uint8[theTileSizeInBytes]; + +// if (outputLines < theTileHeight || outputSamples < theTileWidth) +// { +// // The full tile will not be filled so make sure it's blank. +// for(band=0; band<theImageHandler->getNumberOfInputBands(); band++) +// { +// memset((void*)buf[band], 0, theTileSizeInBytes); +// } +// } + + int tileNumber = 0; + + //*** + // Tile loop in the line direction. + //*** + for(int i = 0; i < outputTilesHigh; i++) + { + //*** + // Tile loop in the sample (width) direction. + //*** + for(int j = 0; j < outputTilesWide; j++) + { + //*** + // For each output tile, four source tiles must be grabbed. + // + // NOTE: + // Because the output tile bounds can be greater than the source + // data grabbed from, the origin bounds must be checked after + // the upper left tile is copied. + //*** + + // Get the upper left tile. + ossimIpt origin(j * 2 * theTileWidth, i * 2 * theTileHeight); + + // Get the tiles. + + // Band loop. + for (band=0; band<theImageHandler->getNumberOfInputBands(); band++) + { + // Grab the upper left source tile for the band. + int bytes = TIFFReadTile(tifr, + (void*)tbuf, + origin.x, + origin.y, + 0, + band); + + if (bytes != theTileSizeInBytes) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Read Error!" + << "\nBytes expected: " << theTileSizeInBytes + << "\nBytes read: " << bytes + << "\nReturning error..." << endl; + TIFFClose(tifr); + delete [] tbuf; + tbuf = NULL; + return false; + } + + resampleTile((void*)tbuf, + imageBuffer->getBuf(band), + UL, + theNullPixelValues[band]); + } + + // Get the upper right tile. + origin.x += theTileWidth; + + if (origin.x < samples && origin.y < lines) + { + // Get the tiles. + + // Band loop. + for (band=0; band<theImageHandler->getNumberOfInputBands(); band++) + { + // Grab the upper right source tile for the band. + int bytes = TIFFReadTile(tifr, + (void*)tbuf, + origin.x, + origin.y, + 0, + band); + + if (bytes != theTileSizeInBytes) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Read Error!" + << "\nBytes expected: " << theTileSizeInBytes + << "\nBytes read: " << bytes + << "\nReturning error..." << endl; + TIFFClose(tifr); + delete [] tbuf; + tbuf = NULL; + return false; + } + + resampleTile((void*)tbuf, + imageBuffer->getBuf(band), + UR, + theNullPixelValues[band]); + } + + } // End of if (origin.x <= samples && origin.y <= lines) + + // Get the lower left tile. + origin.x -= theTileWidth; + origin.y += theTileHeight; + + if (origin.x < samples && origin.y < lines) + { + // Get the tiles. + + // Band loop. + for (band=0; band<theImageHandler->getNumberOfInputBands(); band++) + { + // Grab the lower left source tile for the band. + int bytes = TIFFReadTile(tifr, + (void*)tbuf, + origin.x, + origin.y, + 0, + band); + + if (bytes != theTileSizeInBytes) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Read Error!" + << "\nBytes expected: " << theTileSizeInBytes + << "\nBytes read: " << bytes + << "\nReturning error..." << endl; + delete [] tbuf; + tbuf = NULL; + TIFFClose(tifr); + return false; + } + + resampleTile((void*)tbuf, + imageBuffer->getBuf(band), + LL, + theNullPixelValues[band]); + } + + } // End of if (origin.x <= samples && origin.y <= lines) + + // Get the lower right tile. + origin.x += theTileWidth; + + if (origin.x < samples && origin.y < lines) + { + // Get the tiles. + + // Band loop. + for (band=0; band<theImageHandler->getNumberOfInputBands(); band++) + { + // Grab the lower right source tile for the band. + int bytes = TIFFReadTile(tifr, + (void*)tbuf, + origin.x, + origin.y, + 0, + band); + + if (bytes != theTileSizeInBytes) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Read Error!" + << "\nBytes expected: " << theTileSizeInBytes + << "\nBytes read: " << bytes + << "\nReturning error..." << endl; + + // Free memory. + delete [] tbuf; + tbuf = NULL; + + TIFFClose(tifr); + return false; + } + + resampleTile((void*)tbuf, + imageBuffer->getBuf(band), + LR, + theNullPixelValues[band]); + } + + } // End of if (origin.x <= samples && origin.y <= lines) + + for (band=0; band<theImageHandler->getNumberOfInputBands(); band++) + { + // Write the tile. + int bytesWritten = 0; + bytesWritten = TIFFWriteTile(tif, + imageBuffer->getBuf(band), + j*theTileWidth, + i*theTileHeight, + 0, // z + band); // sample + + if (bytesWritten != theTileSizeInBytes) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR:" + << "Error returned writing tiff tile: " << i + << "\nExpected bytes written: " << theTileSizeInBytes + << "\nBytes written: " << bytesWritten + << endl; + + delete [] tbuf; + tbuf = NULL; + + TIFFClose(tifr); + return false; + } + } + + tileNumber++; + + } // End of tile loop in the sample (width) direction. + + + if (needsAborting()) + { + setPercentComplete(100.0); + break; + } + else + { + double tile = tileNumber; + double numTiles = numberOfTiles; + setPercentComplete(tile / numTiles * 100.0); + } + } // End of tile loop in the line (height) direction. + + delete [] tbuf; + tbuf = NULL; + TIFFClose(tifr); + + //*** + // Write the current dirctory. + //*** + if (!TIFFWriteDirectory(tif)) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Error writing directory!" << endl; + return false; + } + + theCurrentTiffDir++; + + return true; +} + +//******************************************************************* +// Private Method: +//******************************************************************* +ossim_int32 ossimTiffOverviewBuilder::getNumberOfSets() const +{ + ossim_int32 a = theImageHandler->getNumberOfSamples(0) < + theImageHandler->getNumberOfLines(0) ? + theImageHandler->getNumberOfSamples(0) : + theImageHandler->getNumberOfLines(0); + + ossim_int32 n = 0; + + while(a > 2) + { + a /= 2; + ++n; + } + + return n; +} + +//******************************************************************* +// Private Method: +//******************************************************************* +bool ossimTiffOverviewBuilder::setTags(TIFF* tif, ossim_int32 rrds_level) const +{ + ossim_int32 imageWidth = theImageHandler->getNumberOfSamples(); + ossim_int32 imageHeight = theImageHandler->getNumberOfLines(); + int16 samplesPerPixel = theImageHandler->getNumberOfOutputBands(); + ossim_float64 minSampleValue = theImageHandler->getMinPixelValue(); + ossim_float64 maxSampleValue = theImageHandler->getMaxPixelValue(); + + if (rrds_level) + { + imageWidth = imageWidth >> rrds_level; + imageHeight = imageHeight >> rrds_level; + TIFFSetField( tif, TIFFTAG_SUBFILETYPE, FILETYPE_REDUCEDIMAGE ); + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimTiffOverviewBuilder::setTags DEBUG:" + << "\nrrds_level: " << rrds_level + << "\nimageWidth: " << imageWidth + << "\nimageHeight: " << imageHeight + << "\nminSampleValue: " << minSampleValue + << "\nmaxSampleValue: " << maxSampleValue + << endl; + } + TIFFSetField( tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_SEPARATE ); + TIFFSetField( tif, TIFFTAG_IMAGEWIDTH, imageWidth); + TIFFSetField( tif, TIFFTAG_IMAGELENGTH, imageHeight); + TIFFSetField( tif, TIFFTAG_BITSPERSAMPLE, theBitsPerSample ); + TIFFSetField( tif, TIFFTAG_SAMPLEFORMAT, theSampleFormat ); + TIFFSetField( tif, TIFFTAG_SAMPLESPERPIXEL, samplesPerPixel ); + + if( theImageHandler->getNumberOfInputBands() == 3 ) + TIFFSetField( tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB ); + else + TIFFSetField( tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK ); + + TIFFSetField( tif, TIFFTAG_TILEWIDTH, theTileWidth ); + TIFFSetField( tif, TIFFTAG_TILELENGTH, theTileHeight ); + + // Set the compression related tags... + TIFFSetField( tif, TIFFTAG_COMPRESSION, theTiffCompressType ); + if (theTiffCompressType == COMPRESSION_JPEG) + { + TIFFSetField( tif, TIFFTAG_JPEGQUALITY, theJpegCompressQuality); + } + + // Set the min/max values. + switch( theImageHandler->getOutputScalarType() ) + { + case OSSIM_SINT16: + case OSSIM_FLOAT32: + case OSSIM_FLOAT64: + case OSSIM_NORMALIZED_DOUBLE: + TIFFSetField( tif, TIFFTAG_SMINSAMPLEVALUE, minSampleValue ); + TIFFSetField( tif, TIFFTAG_SMAXSAMPLEVALUE, maxSampleValue ); + break; + + case OSSIM_UINT8: + case OSSIM_USHORT11: + case OSSIM_UINT16: + case OSSIM_UINT32: + default: + TIFFSetField( tif, TIFFTAG_MINSAMPLEVALUE, + static_cast<int>(minSampleValue) ); + TIFFSetField( tif, TIFFTAG_MAXSAMPLEVALUE, + static_cast<int>(maxSampleValue) ); + break; + } + + return true; +} + +//******************************************************************* +// Private Method: +//******************************************************************* +void ossimTiffOverviewBuilder::resampleTile(void* source_tile, + void* output_tile, + Quadrant quadrant, + double nullPix) +{ + static const char MODULE[] = "ossimTiffOverviewBuilder::resampleTile"; + + switch(theImageHandler->getOutputScalarType()) + { + case OSSIM_UINT8: + { + resampleTile((ossim_uint8*)source_tile, + (ossim_uint8*)output_tile, + quadrant, + (ossim_uint8)nullPix); + break; + } + + case OSSIM_USHORT11: + case OSSIM_UINT16: + { + resampleTile((ossim_uint16*)source_tile, + (ossim_uint16*)output_tile, + quadrant, + (ossim_uint16)nullPix); + break; + } + case OSSIM_SINT16: + { + resampleTile((ossim_sint16*)source_tile, + (ossim_sint16*)output_tile, + quadrant, + (ossim_sint16)nullPix); + break; + } + + case OSSIM_UINT32: + { + resampleTile((ossim_uint32*)source_tile, + (ossim_uint32*)output_tile, + quadrant, + (ossim_uint32)nullPix); + break; + } + + case OSSIM_FLOAT32: + { + resampleTile((ossim_float32*)source_tile, + (ossim_float32*)output_tile, + quadrant, + (ossim_float32)nullPix); + break; + } + + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_FLOAT64: + { + resampleTile((ossim_float64*)source_tile, + (ossim_float64*)output_tile, + quadrant, + (ossim_float64)nullPix); + break; + } + default: + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Unkown pixel type!" << endl; + return; + } +} + +template <class T> +void ossimTiffOverviewBuilder::resampleTile(T* source_tile, + T* output_tile, + Quadrant quadrant, + T nullPixel) +{ + //*** + // Buffers are assumed to be tiles. This will fill one quarter of the + // output tile + //*** + ossim_int32 lines = theTileHeight / 2; + ossim_int32 samples = theTileWidth / 2; + + T* s = (T*)source_tile; // source buffer + T* d = (T*)output_tile; // destination buffer + + // Adjust the d pointer to the start of data. + switch (quadrant) + { + case ossimTiffOverviewBuilder::UR: + d += theTileWidth / 2; + break; + case ossimTiffOverviewBuilder::LL: + d += theTileHeight / 2 * theTileWidth; + break; + case ossimTiffOverviewBuilder::LR: + d += theTileHeight / 2 * theTileWidth + theTileWidth / 2; + case ossimTiffOverviewBuilder::UL: + default: + break; + } + + double weight=0.0; + double value=0.0; + for (ossim_int32 i=0; i<lines; i++) + { + for (ossim_int32 j=0; j<samples; j++) + { + switch(theResampleType) + { + case ossimFilterResampler::ossimFilterResampler_NEAREST_NEIGHBOR: + { + weight = 1.0; + value = *(s + i*2*theTileWidth + j*2); + break; + } + case ossimFilterResampler::ossimFilterResampler_BOX: + { + weight = 0; + value = 0; + + // Grab four pixels from the source, average, and assign to output. + ossim_float64 ul = *(s + i*2*theTileWidth + j*2); + ossim_float64 ur = *(s + i*2*theTileWidth + j*2+1); + ossim_float64 ll = *(s + (i*2+1)*theTileWidth + j*2); + ossim_float64 lr = *(s + (i*2+1)*theTileWidth + j*2+1); + + if(ul != nullPixel) + { + ++weight; + value += ul; + } + if(ur != nullPixel) + { + ++weight; + value += ur; + } + if(ll != nullPixel) + { + ++weight; + value += ll; + } + if(lr != nullPixel) + { + ++weight; + value += lr; + } + break; + } + default: + { + weight = 1.0; + value = *(s + i*2*theTileWidth + j*2); + break; + } + + } + if(weight) + { + d[j] = (T)( value/weight ); + } + else + { + d[j] = nullPixel; + } + } + d += theTileWidth; + } +} + +void ossimTiffOverviewBuilder::setCompressionType(ossim_uint16 compression_type) +{ + switch (compression_type) + { + case COMPRESSION_JPEG: + case COMPRESSION_LZW: + case COMPRESSION_DEFLATE: + case COMPRESSION_PACKBITS: + theTiffCompressType = compression_type; + break; + default: + theTiffCompressType = COMPRESSION_NONE; + if (traceDebug()) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_WARNING, + "\ +ossimTiffOverviewBuilder::setCompressionType\nfile %s line %d\n\ +Unsupported compression type: %d Defaulting to none.", + __FILE__, + __LINE__, + compression_type); + } + break; + } +} + +void ossimTiffOverviewBuilder::setJpegCompressionQuality(ossim_int32 quality) +{ + if (quality > 1 && quality < 101) + { + theJpegCompressQuality = quality; + } + else + { + theJpegCompressQuality = DEFAULT_COMPRESS_QUALITY; + + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_WARNING, + "\ +ossimTiffOverviewBuilder::setJpegCompressionQuality\n%s file %s \ +line %d Compression quality of %d is out of range!\nis out of range!\n\ +Range is 100 to 1. Current quality set to default of 75.", + __FILE__, + __LINE__, + quality); + } +} + +ossimObject* ossimTiffOverviewBuilder::getObject() +{ + return this; +} + +const ossimObject* ossimTiffOverviewBuilder::getObject() const +{ + return this; +} + +bool ossimTiffOverviewBuilder::execute() +{ + return buildOverview(theOutputFile); +} + +ossimFilename ossimTiffOverviewBuilder::getOutputFile() const +{ + return theOutputFile; +} + +void ossimTiffOverviewBuilder::setOutputFile(const ossimFilename& file) +{ + + theOutputFile = file; +} + +bool ossimTiffOverviewBuilder::canConnectMyInputTo( + ossim_int32 index, + const ossimConnectableObject* obj) const +{ + if ( (index == 0) && + PTR_CAST(ossimImageHandler, obj) ) + { + return true; + } + + return false; +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimTiffOverviewBuilder.h b/Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimTiffOverviewBuilder.h new file mode 100644 index 0000000000..4326f41f50 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimTiffOverviewBuilder.h @@ -0,0 +1,208 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class declaration for TiffOverviewBuilder. +// +//******************************************************************* +// $Id: ossimTiffOverviewBuilder.h,v 1.14 2005/08/29 18:47:40 gpotts Exp $ + +#ifndef ossimTiffOverviewBuilder_HEADER +#define ossimTiffOverviewBuilder_HEADER + +#include <base/common/ossimConstants.h> +#include <base/common/ossimSource.h> +#include <base/common/ossimErrorStatusInterface.h> +#include <base/common/ossimProcessInterface.h> +#include <base/common/events/ossimConnectableObjectListener.h> +#include <imaging/resample/ossimFilterResampler.h> +#include <base/data_types/ossimFilename.h> +#include <tiffio.h> +#include <tiff.h> + +class ossimImageHandler; +class ossimFilename; +class ossimConnectableObject; + +class OSSIM_DLL ossimTiffOverviewBuilder + : + public ossimSource, + public ossimProcessInterface, + public ossimConnectableObjectListener +{ +public: + + enum + { + DEFAULT_COMPRESS_QUALITY=75 + }; + + ossimTiffOverviewBuilder(ossimImageHandler* imageHanderler); + + ~ossimTiffOverviewBuilder(); + + enum Quadrant + { + UL, + UR, + LL, + LR + }; + + /** + * Supports BOX or NEAREST NEIGHBOR. When indexed you should probably use nearest neighbor + */ + void setResampleType(ossimFilterResampler::ossimFilterResamplerType resampleType); + + /*! + * Builds overview file and sets "theOutputFile" to that of + * the overview_file. + * + * @param overview_file The overview file name to output. + * + * @param copy_all If set to true the entire image will be + * copied. This can be used to convert an image to a tiled tif. + * + * @return true on success, false on error. + */ + bool buildOverview(const ossimFilename& overview_file, + bool copy_all=false); + + /*! + * Calls buildOverview. This method uses "theOutputFile" for the file + * name. + * + * If the copy_all flag is set the entire image will be copied. This can + * be used to convert an image to a tiled tif. + * + * @return true on success, false on error. + * + * @note If setOutputFile was not called the output name will be derived + * from the image name. If image was "foo.tif" the overview file will + * be "foo.ovr". + */ + virtual bool execute(); + + /*! + * Sets the compression type to use when building overviews. + * + * @param compression_type Current supported types: + * - COMPRESSION_JPEG + * - COMPRESSION_LZW + * - COMPRESSION_DEFLATE + * - COMPRESSION_PACKBITS + * - COMPRESSION_NONE (default) + */ + void setCompressionType(uint16 compression_type); + + /*! + * Sets the compression quality for use when using a compression type + * of COMPRESSION_JPEG. + * + * @param quality Range 1 to 100 with 100 being best quality. + */ + void setJpegCompressionQuality(ossim_int32 quality); + + /*! + * @return ossimObject* to this object. + */ + virtual ossimObject* getObject(); + + /*! + * @return const ossimObject* to this object. + */ + virtual const ossimObject* getObject() const; + + /*! + * @return The output filename. This will be derived from the image + * handlers filename unless the method buildOverview has been called which + * takes a filename. + */ + ossimFilename getOutputFile() const; + + /*! + * Sets the output filename. + */ + void setOutputFile(const ossimFilename& file); + + /*! + * @return true if input is an image handler. + */ + virtual bool canConnectMyInputTo(ossim_int32 index, + const ossimConnectableObject* obj) const; + +private: + + /*! + * Returns the number of reduced resolution data sets to get the smallest + * dimension >= 32 && < 64. + */ + ossim_int32 getNumberOfSets() const; + + /*! + * Copy the full resolution image data to the output tif image. + */ + bool writeR0(TIFF* tif); + + /*! + * Write the first reduced resolution data set to the tif file. + */ + bool writeR1(TIFF* tif); + + /*! + * Write reduced resolution data set to the tif file. "rrds_level" must + * be greater than 1 for this method as it uses subsequent rrds_levels + * from the tif file. + */ + bool writeRn(TIFF* tif, + const ossimFilename& overview_file, + ossim_int32 rrds_level); + + /*! + * Resamples a patch of data. + */ + void resampleTile(void* source_tile, + void* output_tile, + Quadrant quadrant, + double nullPix); + + template <class T> void resampleTile(T* source_tile, + T* output_tile, + Quadrant quadrant, + T nullPixel); + + /*! + * Set the tiff tags for the appropriate rrds_level. Level zero is the + * full resolution image. + */ + bool setTags(TIFF* tif, ossim_int32 rrds_level) const; + + // Disallow these... + ossimTiffOverviewBuilder(const ossimTiffOverviewBuilder& source); + ossimTiffOverviewBuilder& operator=(const ossimTiffOverviewBuilder& rhs); + + ossimImageHandler* theImageHandler; + ossimFilename theOutputFile; + ossim_uint8* theNullDataBuffer; + ossim_int32 theBytesPerPixel; + ossim_int32 theBitsPerSample; + ossim_int32 theTileWidth; + ossim_int32 theTileHeight; + ossim_int32 theTileSizeInBytes; + ossim_int32 theSampleFormat; + ossim_int32 theCurrentTiffDir; + ossim_uint16 theTiffCompressType; + ossim_int32 theJpegCompressQuality; + ossimFilterResampler::ossimFilterResamplerType theResampleType; + vector<double> theNullPixelValues; +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimTiffTileSource.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimTiffTileSource.cpp new file mode 100644 index 0000000000..e0cdeeabff --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimTiffTileSource.cpp @@ -0,0 +1,1825 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See LICENSE.txt file in the top level directory. +// +// Author: David Burken +// Frank Warmerdam (warmerdam@pobox.com) +// +// Description: +// +// Contains class definition for TiffTileSource. +// +//******************************************************************* +// $Id: ossimTiffTileSource.cpp,v 1.104 2006/01/05 14:59:29 dburken Exp $ + +#include <imaging/formats/tiff/ossimTiffTileSource.h> +#include <support_data/tiff/ossimGeoTiff.h> +#include <base/common/ossimConstants.h> +#include <base/common/ossimTrace.h> +#include <base/data_types/ossimIpt.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimFilename.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ellipse/ossimEllipsoid.h> +#include <base/data_types/datum/ossimDatum.h> +#include <base/property/ossimBooleanProperty.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <projections/map_projections/ossimEquDistCylProjection.h> +#include <projections/map_projections/ossimAlbersProjection.h> +#include <projections/map_projections/ossimCylEquAreaProjection.h> +#include <projections/map_projections/ossimEquDistCylProjection.h> +#include <projections/map_projections/ossimVanDerGrintenProjection.h> +#include <projections/map_projections/ossimLambertConformalConicProjection.h> +#include <projections/map_projections/ossimMercatorProjection.h> +#include <projections/map_projections/ossimMillerProjection.h> +#include <projections/map_projections/ossimOrthoGraphicProjection.h> +#include <projections/map_projections/ossimPolyconicProjection.h> +#include <projections/map_projections/ossimSinusoidalProjection.h> +#include <projections/map_projections/ossimTransMercatorProjection.h> +#include <projections/map_projections/ossimCassiniProjection.h> +#include <projections/map_projections/ossimUtmProjection.h> + +RTTI_DEF1(ossimTiffTileSource, "ossimTiffTileSource", ossimImageHandler) + +static ossimTrace traceDebug("ossimTiffTileSource:degug"); + +#ifndef MAX +# define MIN(a,b) ((a<b) ? a : b) +# define MAX(a,b) ((a>b) ? a : b) +#endif + +#define OSSIM_TIFF_UNPACK_R4(value) ( (value)&0x000000FF) +#define OSSIM_TIFF_UNPACK_G4(value) ( ((value)>>8)&0x000000FF) +#define OSSIM_TIFF_UNPACK_B4(value) ( ((value)>>16)&0x000000FF) +#define OSSIM_TIFF_UNPACK_A4(value) ( ((value)>>24)&0x000000FF) + +//******************************************************************* +// Public Constructor: +//******************************************************************* +ossimTiffTileSource::ossimTiffTileSource() + : + ossimImageHandler(), + theTile(0), + theBuffer(0), + theBufferSize(0), + theBufferRect(0, 0, 0, 0), + theBufferRLevel(0), + theTiffPtr(0), + theSamplesPerPixel(0), + theBitsPerSample(0), + theSampleFormatUnit(0), + theMaxSampleValue(0), + theMinSampleValue(0), + theNumberOfDirectories(0), + theCurrentDirectory(0), + theR0isFullRes(false), + theBytesPerPixel(0), + theScalarType(OSSIM_SCALAR_UNKNOWN), + theApplyColorPaletteFlag(true), + theImageWidth(0), + theImageLength(0), + theReadMethod(0), + thePlanarConfig(0), + thePhotometric(0), + theRowsPerStrip(0), + theImageTileWidth(0), + theImageTileLength(0) +{} + +ossimTiffTileSource::~ossimTiffTileSource() +{ + close(); +} + +ossimRefPtr<ossimImageData> ossimTiffTileSource::getTile( + const ossimIrect& tile_rect, + ossim_uint32 resLevel) +{ + static const char MODULE[] ="ossimTiffTileSource::getTile(rect, res)"; + + //--- + // Not open, this tile source bypassed, or invalid res level, + // return a blank tile. + //--- + if( !isOpen() || !isSourceEnabled() || !isValidRLevel(resLevel) ) + { + return ossimRefPtr<ossimImageData>(); + } + + //--- + // Subtract an sub image offset to work in zero based image space from + // here on out. + //--- + ossimIrect zeroBasedTileRect = tile_rect - getSubImageOffset(resLevel); + + //--- + // If there is an overview and the current rr level is not at "0" then + // send the getTile call to the overview image handler. + //--- + if (resLevel&&theOverview) + { + //--- + // Overviews are not aware of sub image offsets so request a zero based + // rectangle. + //--- + ossimRefPtr<ossimImageData> tile = + theOverview->getTile(zeroBasedTileRect, resLevel); + if (tile.valid()) + { + //--- + // Since the overview request was zero based we must reset the + // rectangle to be relative to any sub image offset. + //--- + tile->setImageRectangle(tile_rect); + } + + if(getOutputScalarType() == OSSIM_USHORT11) + { + //--- + // Temp fix: + // The overview handler could return a tile of OSSIM_UINT16 if + // the max sample value was not set to 2047. + //--- + tile->setScalarType(OSSIM_USHORT11); + } + + return tile; + } + + bool reallocateBuffer = false; + if ( (tile_rect.width() != theTile->getWidth()) || + (tile_rect.height() != theTile->getHeight()) ) + { + reallocateBuffer = true; + } + + if (getCurrentTiffRLevel() != resLevel) + { + // Change the tiff directory to the requested level. + ossim_uint32 dir = 0; + if (resLevel) + { + dir = theR0isFullRes ? resLevel : resLevel - 1; + } + + if (setTiffDirectory(dir) == false) + { + return ossimRefPtr<ossimImageData>(); + } + reallocateBuffer = true; + } + + //--- + // The tile's internal rectangle should be relative to any sub image. + // + // Note: + // + // Since the allocate buffer method relies on theTile->getHeight() it is + // important to do this prior to the allocateBuffer call. + //--- + theTile->setImageRectangle(tile_rect); + + if (reallocateBuffer) + { + allocateBuffer(); + } + + // This should be the zero base image rectangle for this res level. + ossimIrect image_rect = getImageRectangle(resLevel); + + //--- + // See if any point of the requested tile is in the image. + //--- + if ( zeroBasedTileRect.intersects(image_rect) ) + { + ossimIrect clip_rect = zeroBasedTileRect.clipToRect(image_rect); + + if ( !zeroBasedTileRect.completely_within(clip_rect) ) + { + // Start with a blank tile. + theTile->makeBlank(); + } + + // Load the tile buffer with data from the tif. + if (loadTile(zeroBasedTileRect, clip_rect)) + { + theTile->validate(); + return theTile; + } + else + { + // Error in filling buffer. + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Returning blank tile..." << endl; + return ossimRefPtr<ossimImageData>(); + } + } + + // No part of requested tile within the image rectangle. + return ossimRefPtr<ossimImageData>(); +} + +//******************************************************************* +// Public method: +//******************************************************************* +bool ossimTiffTileSource::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + kwl.add(prefix, + "apply_color_palette_flag", + theApplyColorPaletteFlag, + true); + // Currently nothing to do here. + return ossimImageHandler::saveState(kwl, prefix); +} + +//******************************************************************* +// Public method: +//******************************************************************* +bool ossimTiffTileSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + if (ossimImageHandler::loadState(kwl, prefix)) + { + ossimString flag = kwl.find(prefix, + "apply_color_palette_flag"); + if(flag != "") + { + theApplyColorPaletteFlag = flag.toBool(); + } + else + { + theApplyColorPaletteFlag = true; + } + + return open(theImageFile); + } + + return false; +} + +bool ossimTiffTileSource::open(const ossimFilename& image_file) +{ + if (theTiffPtr) + { + close(); + } + theImageFile = image_file; + return open(); +} + +void ossimTiffTileSource::close() +{ + if(theTiffPtr) + { + TIFFClose(theTiffPtr); + theTiffPtr = 0; + } + theImageWidth.clear(); + theImageLength.clear(); + theReadMethod.clear(); + thePlanarConfig.clear(); + thePhotometric.clear(); + theRowsPerStrip.clear(); + theImageTileWidth.clear(); + theImageTileLength.clear(); + if (theBuffer) + { + delete [] theBuffer; + theBuffer = NULL; + } +} + +bool ossimTiffTileSource::open() +{ + static const char MODULE[] = "ossimTiffTileSource::open"; + + if(isOpen()) + { + close(); + } + //*** + // First we do a quick test to see if the file looks like a tiff file. + //*** + FILE *fp; + unsigned char header[2]; + + fp = fopen( theImageFile.c_str(), "rb" ); + if( fp == NULL ) + return false; + + fread( header, 2, 1, fp ); + fclose( fp ); + + if( (header[0] != 'M' || header[1] != 'M') + && (header[0] != 'I' || header[1] != 'I') ) + return false; + + //--- + // Note: The 'm' in "rm" is to tell TIFFOpen to not memory map the file. + //--- + theTiffPtr = TIFFOpen(theImageFile.c_str(), "rm"); + + // Check for errors. + if (!theTiffPtr) + { + return false; + } + + if (!theTiffPtr) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR:\n" + << "Object has null tiff descriptor." << endl; + return false; + } + + //*** + // Get the general tiff info. + //*** + + //*** + // See if the first directory is of FILETYPE_REDUCEDIMAGE; if not, + // the first level is considered to be full resolution data. + // Note: If the tag is not present, consider the first level full + // resolution. + //*** + long sub_file_type; + if ( !TIFFGetField( theTiffPtr, + TIFFTAG_SUBFILETYPE , + &sub_file_type ) ) + { + sub_file_type = 0; + } + + if (sub_file_type == FILETYPE_REDUCEDIMAGE) + { + theR0isFullRes = false; + } + else + { + theR0isFullRes = true; + } + + if( !TIFFGetField(theTiffPtr, TIFFTAG_BITSPERSAMPLE, &(theBitsPerSample)) ) + { + theBitsPerSample = 8; + } + + if( !TIFFGetField(theTiffPtr, + TIFFTAG_SAMPLESPERPIXEL, + &theSamplesPerPixel ) ) + { + theSamplesPerPixel = 1; + } + + if ( !TIFFGetField( theTiffPtr, + TIFFTAG_SAMPLEFORMAT, + &theSampleFormatUnit ) ) + { + theSampleFormatUnit = 0; + } + + if ( !TIFFGetField( theTiffPtr, + TIFFTAG_SMAXSAMPLEVALUE, + &theMaxSampleValue ) ) + { + uint16 maxValue = 0; + if(!TIFFGetField( theTiffPtr, + TIFFTAG_MAXSAMPLEVALUE, + &maxValue)) + { + theMaxSampleValue = OSSIM_DBL_NAN; + } + else + { + theMaxSampleValue = maxValue; + } + } + + if ( !TIFFGetField( theTiffPtr, + TIFFTAG_SMINSAMPLEVALUE, + &theMinSampleValue ) ) + { + uint16 minValue = 0; + if(!TIFFGetField( theTiffPtr, + TIFFTAG_MINSAMPLEVALUE, + &minValue)) + { + theMinSampleValue = OSSIM_DBL_NAN; + } + else + { + theMinSampleValue = minValue; + } + } + + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\ntheMinSampleValue: " << theMinSampleValue + << "\ntheMaxSampleValue: " << theMaxSampleValue + << endl; + } + + //*** + // Get the number of directories. + //*** + theNumberOfDirectories = 0; + do + { + theNumberOfDirectories++; + } while (TIFFReadDirectory(theTiffPtr)); + + theImageWidth.resize(theNumberOfDirectories); + theImageLength.resize(theNumberOfDirectories); + theReadMethod.resize(theNumberOfDirectories); + thePlanarConfig.resize(theNumberOfDirectories); + thePhotometric.resize(theNumberOfDirectories); + theRowsPerStrip.resize(theNumberOfDirectories); + theImageTileWidth.resize(theNumberOfDirectories); + theImageTileLength.resize(theNumberOfDirectories); + + for (ossim_uint32 dir=0; dir<theNumberOfDirectories; ++dir) + { + if (setTiffDirectory(dir) == false) + { + return false; + } + + if( !TIFFGetField( theTiffPtr, TIFFTAG_PLANARCONFIG, + &(thePlanarConfig[dir]) ) ) + { + thePlanarConfig[dir] = PLANARCONFIG_CONTIG; + } + + if( !TIFFGetField( theTiffPtr, TIFFTAG_PHOTOMETRIC, + &(thePhotometric[dir]) ) ) + { + thePhotometric[dir] = PHOTOMETRIC_MINISBLACK; + } + theLut = 0; + // Check for palette. + uint16* red; + uint16* green; + uint16* blue; + if(TIFFGetField(theTiffPtr, TIFFTAG_COLORMAP, &red, &green, &blue)) + { + if(theApplyColorPaletteFlag) + { + thePhotometric[dir] = PHOTOMETRIC_PALETTE; + theSamplesPerPixel = 3; + } + populateLut(); + } + + if( TIFFIsTiled(theTiffPtr)) + { + theRowsPerStrip[dir] = 0; + if ( !TIFFGetField( theTiffPtr, + TIFFTAG_TILEWIDTH, + &theImageTileWidth[dir] ) ) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_WARN) + << "ossimTiffTileSource::getTiffTileWidth ERROR:" + << "\nCannot determine tile width." << endl; + theImageTileWidth[dir] = 0; + } + if ( !TIFFGetField( theTiffPtr, + TIFFTAG_TILELENGTH, + &theImageTileLength[dir] ) ) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_WARN) + << "ossimTiffTileSource::getTiffTileLength ERROR:" + << "\nCannot determine tile length." << endl; + theImageTileLength[dir] = 0; + } + } + else + { + theImageTileWidth[dir] = 0; + theImageTileLength[dir] = 0; + if( !TIFFGetField( theTiffPtr, TIFFTAG_ROWSPERSTRIP, + &(theRowsPerStrip[dir]) ) ) + { + theRowsPerStrip[dir] = 1; + } + } + + if ( !TIFFGetField( theTiffPtr, + TIFFTAG_IMAGELENGTH, + &theImageLength[dir] ) ) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Cannot determine image length." + << endl; + } + + if ( !TIFFGetField( theTiffPtr, + TIFFTAG_IMAGEWIDTH, + &theImageWidth[dir] ) ) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Cannot determine image width." + << endl; + } + + } // End of "for (ossim_uint32 dir=0; dir<theNumberOfDirectories; dir++)" + + // Reset the directory back to "0". + if (setTiffDirectory(0) == false) + { + return false; + } + + //--- + // Get the scalar type. + //--- + theScalarType = OSSIM_SCALAR_UNKNOWN; + + if (theBitsPerSample == 16) + { + theBytesPerPixel = 2; + theScalarType = OSSIM_USHORT16; // Default to unsigned... + + if (theMaxSampleValue == 2047) // 2^11-1 + { + theScalarType = OSSIM_USHORT11; // IKONOS probably... + } + else if (theSampleFormatUnit == SAMPLEFORMAT_INT) + { + theScalarType = OSSIM_SSHORT16; + } + } + else if ( (theBitsPerSample == 32) && + (theSampleFormatUnit == SAMPLEFORMAT_UINT) ) + { + theBytesPerPixel = 4; + theScalarType = OSSIM_UINT32; + } + else if (theBitsPerSample == 32 && + theSampleFormatUnit == SAMPLEFORMAT_IEEEFP) + { + theBytesPerPixel = 4; + theScalarType = OSSIM_FLOAT; + } + else if(theBitsPerSample == 64 && + theSampleFormatUnit == SAMPLEFORMAT_IEEEFP) + { + theBytesPerPixel = 8; + theScalarType = OSSIM_DOUBLE; + } + else if (theBitsPerSample <= 8) + { + theBytesPerPixel = 1; + theScalarType = OSSIM_UCHAR; + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Error:\nCannot determine scalar type.\n" + << "Trace dump follows:\n"; + print(ossimNotify(ossimNotifyLevel_WARN)); + + return false; + } + double tempMax = ossimGetDefaultMax(theScalarType); + double tempMin = ossimGetDefaultMin(theScalarType); + + if(theMinSampleValue == OSSIM_DBL_NAN) + { + theMinSampleValue = tempMin; + } + if(theMaxSampleValue == OSSIM_DBL_NAN) + { + theMaxSampleValue = tempMax; + } + + setReadMethod(); + + // Check for an overview file... + if (theOverview == NULL) + { + openOverview(); + } + + openValidVertices(); + loadMetaData(); + + initializeBuffers(); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " Debug:"; + print(ossimNotify(ossimNotifyLevel_DEBUG)); + } + + // Finished... + return true; +} + +ossim_uint32 ossimTiffTileSource::getNumberOfLines(ossim_uint32 reduced_res_level) const +{ + if(!theTiffPtr) return OSSIM_ULONG_NAN; + + if (isValidRLevel(reduced_res_level)) + { + if (reduced_res_level && theOverview) + { + return theOverview->getNumberOfLines(reduced_res_level); + } + + return (theR0isFullRes ? + theImageLength[reduced_res_level] : + theImageLength[reduced_res_level - 1]); + } + + return OSSIM_ULONG_NAN; +} + +ossim_uint32 +ossimTiffTileSource::getNumberOfSamples(ossim_uint32 reduced_res_level) const +{ + if(!theTiffPtr) return OSSIM_ULONG_NAN; + if (isValidRLevel(reduced_res_level)) + { + if (reduced_res_level && theOverview) + { + return theOverview->getNumberOfSamples(reduced_res_level); + } + + return (theR0isFullRes ? + theImageWidth[reduced_res_level] : + theImageWidth[reduced_res_level-1]); + } + + return OSSIM_ULONG_NAN; +} + +ossim_uint32 ossimTiffTileSource::getNumberOfDecimationLevels() const +{ + if (theOverview) + { + return theOverview->getNumberOfDecimationLevels(); + } + + return ( theR0isFullRes ? theNumberOfDirectories : + theNumberOfDirectories+1 ); +} + +//******************************************************************* +// Public method: +//******************************************************************* +ossimScalarType ossimTiffTileSource::getOutputScalarType() const +{ + return theScalarType; +} + +//******************************************************************* +// Public method: +//******************************************************************* +ossim_uint32 ossimTiffTileSource::getTileWidth() const +{ + return ( theTile.valid() ? theTile->getWidth() : 0 ); +} + +//******************************************************************* +// Public method: +//******************************************************************* +ossim_uint32 ossimTiffTileSource::getTileHeight() const +{ + return ( theTile.valid() ? theTile->getHeight() : 0 ); +} + +bool ossimTiffTileSource::loadTile(const ossimIrect& tile_rect, + const ossimIrect& clip_rect) +{ + static const char MODULE[] = "ossimTiffTileSource::loadTile"; + + bool status = false; + + switch(theReadMethod[theCurrentDirectory]) + { + case READ_TILE: + status = loadFromTile(clip_rect); + break; + + case READ_SCAN_LINE: + status = loadFromScanLine(clip_rect); + break; + + case READ_RGBA_U8_TILE: + status = loadFromRgbaU8Tile(tile_rect, clip_rect); + break; + + case READ_RGBA_U8_STRIP: + status = loadFromRgbaU8Strip(tile_rect, clip_rect); + break; + + case READ_RGBA_U8A_STRIP: + status = loadFromRgbaU8aStrip(tile_rect, clip_rect); + break; + + default: + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Unsupported tiff type!" << endl; + status = false; + break; + } + + return status; +} + +bool ossimTiffTileSource::loadFromScanLine(const ossimIrect& clip_rect) +{ + ossimInterleaveType type = + (thePlanarConfig[theCurrentDirectory] == PLANARCONFIG_CONTIG) ? + OSSIM_BIP : OSSIM_BIL; + + if ( theBufferRLevel != getCurrentTiffRLevel() || + !clip_rect.completely_within(theBufferRect) ) + { + //*** + // Must reload the buffer. Grab enough lines to fill the depth of the + // clip rectangle. + //*** + theBufferRLevel = getCurrentTiffRLevel(); + theBufferRect = getImageRectangle(theBufferRLevel); + theBufferRect.set_uly(clip_rect.ul().y); + theBufferRect.set_lry(clip_rect.lr().y); + ossim_uint32 startLine = clip_rect.ul().y; + ossim_uint32 stopLine = clip_rect.lr().y; + ossim_uint8* buf = theBuffer; + + if (thePlanarConfig[theCurrentDirectory] == PLANARCONFIG_CONTIG) + { + ossim_uint32 lineSizeInBytes = getNumberOfSamples(theBufferRLevel) * + theBytesPerPixel * theSamplesPerPixel; + + for (ossim_uint32 line = startLine; line <= stopLine; ++line) + { + TIFFReadScanline(theTiffPtr, (void*)buf, line, 0); + buf += lineSizeInBytes; + } + } + else + { + ossim_uint32 lineSizeInBytes = getNumberOfSamples(theBufferRLevel) * + theBytesPerPixel; + + for (ossim_uint32 line = startLine; line <= stopLine; ++line) + { + for (ossim_uint32 band = 0; band < theSamplesPerPixel; ++band) + { + TIFFReadScanline(theTiffPtr, (void*)buf, line, band); + buf += lineSizeInBytes; + } + } + } + } + + theTile->loadTile(theBuffer, + theBufferRect, + clip_rect, + type); + return true; +} + +bool ossimTiffTileSource::loadFromTile(const ossimIrect& clip_rect) +{ + static const char MODULE[] = "ossimTiffTileSource::loadFromTile"; + + //*** + // Shift the upper left corner of the "clip_rect" to the an even tile + // boundary. Note this will shift in the upper left direction. + //*** + ossimIpt tileOrigin = clip_rect.ul(); + adjustToStartOfTile(tileOrigin); + + //--- + // Calculate the number of tiles needed in the line/sample directions. + //--- + + + ossim_uint32 tiles_in_v_dir = (clip_rect.lr().x-tileOrigin.x+1) / + theImageTileWidth[theCurrentDirectory]; + ossim_uint32 tiles_in_u_dir = (clip_rect.lr().y-tileOrigin.y+1) / + theImageTileLength[theCurrentDirectory]; + + if ( (clip_rect.lr().x-tileOrigin.x+1) % + theImageTileWidth[theCurrentDirectory] ) ++tiles_in_v_dir; + if ( (clip_rect.lr().y-tileOrigin.y+1) % + theImageTileLength[theCurrentDirectory] ) ++tiles_in_u_dir; + + ossimInterleaveType type = + (thePlanarConfig[theCurrentDirectory] == PLANARCONFIG_CONTIG) ? + OSSIM_BIP : OSSIM_BIL; + + ossimIpt ulTilePt = tileOrigin; + + // Tile loop in line direction. + for (ossim_uint32 u=0; u<tiles_in_u_dir; ++u) + { + ulTilePt.x = tileOrigin.x; + + // Tile loop in sample direction. + for (ossim_uint32 v=0; v<tiles_in_v_dir; ++v) + { + ossimIrect tiff_tile_rect(ulTilePt.x, + ulTilePt.y, + ulTilePt.x + + theImageTileWidth[theCurrentDirectory] - 1, + ulTilePt.y + + theImageTileLength[theCurrentDirectory] - 1); + + if (tiff_tile_rect.intersects(clip_rect)) + { + ossimIrect tiff_tile_clip_rect + = tiff_tile_rect.clipToRect(clip_rect); + + if (thePlanarConfig[theCurrentDirectory] == PLANARCONFIG_CONTIG) + { + if (TIFFReadTile(theTiffPtr, + theBuffer, + ulTilePt.x, + ulTilePt.y, + 0, + 0) == -1) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Read Error!" + << "\nReturning error... " << endl; + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + return false; + } + + theTile->loadTile(theBuffer, + tiff_tile_rect, + tiff_tile_clip_rect, + type); + } + else + { + // band separate tiles... + for (ossim_uint32 band=0; band<theSamplesPerPixel; ++band) + { + // Read a tile into the buffer. + if (TIFFReadTile(theTiffPtr, + theBuffer, + ulTilePt.x, + ulTilePt.y, + 0, + band) == -1) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Read Error!" + << "\nReturning error... " << endl; + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + return false; + } + + theTile->loadBand(theBuffer, + tiff_tile_rect, + tiff_tile_clip_rect, + band); + } + } + + } // End of if (tiff_tile_rect.intersects(clip_rect)) + + ulTilePt.x += theImageTileWidth[theCurrentDirectory]; + + } // End of tile loop in the sample direction. + + ulTilePt.y += theImageTileLength[theCurrentDirectory]; + + } // End of tile loop in the line direction. + + return true; +} + +bool ossimTiffTileSource::loadFromRgbaU8Tile(const ossimIrect& tile_rect, + const ossimIrect& clip_rect) +{ + static const char MODULE[] = "ossimTiffTileSource::loadFromRgbaTile"; + + if (theSamplesPerPixel != 3 || theBytesPerPixel!=1) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Error:" + << "\nInvalid number of bands or bytes per pixel!" << endl; + } + + //*** + // Shift the upper left corner of the "clip_rect" to the an even tile + // boundary. Note this will shift in the upper left direction. + //*** + ossimIpt tileOrigin = clip_rect.ul(); + adjustToStartOfTile(tileOrigin); + + //--- + // Calculate the number of tiles needed in the line/sample directions + // to fill the tile. + //--- + ossim_uint32 tiles_in_v_dir = (clip_rect.lr().x-tileOrigin.x+1) / + theImageTileWidth[theCurrentDirectory]; + ossim_uint32 tiles_in_u_dir = (clip_rect.lr().y-tileOrigin.y+1) / + theImageTileLength[theCurrentDirectory]; + + if ( (clip_rect.lr().x-tileOrigin.x+1) % + theImageTileWidth[theCurrentDirectory] ) ++tiles_in_v_dir; + if ( (clip_rect.lr().y-tileOrigin.y+1) % + theImageTileLength[theCurrentDirectory] ) ++tiles_in_u_dir; + + ossimIpt ulTilePt = tileOrigin; + +#if 0 + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\ntile_rect: " << tile_rect + << "\nclip_rect: " << clip_rect + << "\ntiles_in_v_dir: " << tiles_in_v_dir + << "\ntiles_in_u_dir: " << tiles_in_u_dir + << endl; + } +#endif + + + // Tile loop in line direction. + for (ossim_uint32 u=0; u<tiles_in_u_dir; u++) + { + ulTilePt.x = tileOrigin.x; + + // Tile loop in sample direction. + for (ossim_uint32 v=0; v<tiles_in_v_dir; v++) + { + ossimIrect tiff_tile_rect + = ossimIrect(ulTilePt.x, + ulTilePt.y, + ulTilePt.x + + theImageTileWidth[theCurrentDirectory] - 1, + ulTilePt.y + + theImageTileLength[theCurrentDirectory] - 1); + + if ( getCurrentTiffRLevel() != theBufferRLevel || + tiff_tile_rect != theBufferRect) + { + // Need to grab a new tile. + // Read a tile into the buffer. + if ( !TIFFReadRGBATile(theTiffPtr, + ulTilePt.x, + ulTilePt.y, + (uint32*)theBuffer) ) // use tiff typedef + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Read Error!" + << "\nReturning error..." << endl; + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + return false; + } + + // Capture the rectangle. + theBufferRect = tiff_tile_rect; + theBufferRLevel = getCurrentTiffRLevel(); + } + + ossimIrect tile_clip_rect = clip_rect.clipToRect(theBufferRect); + + //*** + // Get the offset to the first valid pixel. + // + // Note: The data in the tile buffer is organized bottom up. So the + // coordinate must be negated in the line direction since + // the met assumes an origin of upper left. + //*** + ossim_uint32 in_buf_offset = + (tiff_tile_rect.lr().y-tile_clip_rect.ul().y)* + theImageTileWidth[theCurrentDirectory]*4 + + ((tile_clip_rect.ul().x - ulTilePt.x)*4); + + ossim_uint32 out_buf_offset = + (tile_clip_rect.ul().y - tile_rect.ul().y) * + ((ossim_int32)theTile->getWidth()) + + tile_clip_rect.ul().x - tile_rect.ul().x; + + // + // Get a pointer positioned at the first valid pixel in buffers. + // + ossim_uint32* s = (ossim_uint32*)(theBuffer + in_buf_offset); // s for source... +// ossim_uint8* s = theBuffer + in_buf_offset; // s for source... + ossim_uint8* r = static_cast<ossim_uint8*>(theTile->getBuf(0))+ + out_buf_offset; + ossim_uint8* g = static_cast<ossim_uint8*>(theTile->getBuf(1))+ + out_buf_offset; + ossim_uint8* b = static_cast<ossim_uint8*>(theTile->getBuf(2))+ + out_buf_offset; + + ossim_uint32 lines2copy = tile_clip_rect.lr().y-tile_clip_rect.ul().y+1; + ossim_uint32 samps2copy = tile_clip_rect.lr().x-tile_clip_rect.ul().x+1; + + // Line loop through valid portion of the tiff tile. + for (ossim_uint32 line = 0; line < lines2copy; line++) + { + // Sample loop through the tiff tile. + ossim_uint32 i=0; + ossim_uint32 j=0; + + // note the bands from the TIFF READ are stored in a, b, g, r ordering. + // we must reverse the bands and skip the first byte. + for (ossim_uint32 sample = 0; sample < samps2copy; sample++) + { + r[i] = (ossim_uint8)OSSIM_TIFF_UNPACK_R4(s[j]); + g[i] = (ossim_uint8)OSSIM_TIFF_UNPACK_G4(s[j]); + b[i] = (ossim_uint8)OSSIM_TIFF_UNPACK_B4(s[j]); + i++; + ++j; + } + + // Increment the pointers by one line. + const ossim_uint32 OUTPUT_TILE_WIDTH = theTile->getWidth(); + r += OUTPUT_TILE_WIDTH; + g += OUTPUT_TILE_WIDTH; + b += OUTPUT_TILE_WIDTH; + s -= theImageTileWidth[theCurrentDirectory]; + } + + ulTilePt.x += theImageTileWidth[theCurrentDirectory]; + + } // End of tile loop in the sample direction. + + ulTilePt.y += theImageTileLength[theCurrentDirectory]; + + } // End of tile loop in the line direction. + + return true; +} + +bool ossimTiffTileSource::loadFromRgbaU8Strip(const ossimIrect& tile_rect, + const ossimIrect& clip_rect) +{ + static const char MODULE[] = "ossimTiffTileSource::loadFromRgbaU8Strip"; + + if (theSamplesPerPixel > 4 || theBytesPerPixel != 1) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Error:" + << "\nInvalid number of bands or bytes per pixel!" << endl; + } + + //*** + // Calculate the number of strips to read. + //*** + const ossim_uint32 OUTPUT_TILE_WIDTH = theTile->getWidth(); + + ossim_uint32 starting_strip = clip_rect.ul().y / + theRowsPerStrip[theCurrentDirectory]; + ossim_uint32 ending_strip = clip_rect.lr().y / + theRowsPerStrip[theCurrentDirectory]; + ossim_uint32 strip_width = theImageWidth[theCurrentDirectory]*4; + ossim_uint32 output_tile_offset = (clip_rect.ul().y - tile_rect.ul().y) * + OUTPUT_TILE_WIDTH + clip_rect.ul().x - + tile_rect.ul().x; + +#if 0 + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nsamples: " << theSamplesPerPixel + << "\ntile_rect: " << tile_rect + << "\nclip_rect: " << clip_rect + << "\nstarting_strip: " << starting_strip + << "\nending_strip: " << ending_strip + << "\nstrip_width: " << strip_width + << "\noutput_tile_offset: " << output_tile_offset + + << endl; + } +#endif + + //*** + // Get the pointers positioned at the first valid pixel in the buffers. + // s = source + // d = destination + //*** + ossim_uint32 band; + + ossim_uint8** d = new ossim_uint8*[theSamplesPerPixel]; + for (band = 0; band < theSamplesPerPixel; band++) + { + d[band] = static_cast<ossim_uint8*>(theTile->getBuf(band))+output_tile_offset; + } + + // Loop through strips... + for (ossim_uint32 strip=starting_strip; strip<=ending_strip; strip++) + { + if (TIFFReadRGBAStrip(theTiffPtr, + (strip*theRowsPerStrip[theCurrentDirectory]), + (uint32*)theBuffer) == 0) // use tiff typedef + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Error reading strip!" <<endl; + delete [] d; + return false; + } + + //*** + // If the last strip is a partial strip then the first line of the + // strip will be the last line of the image. + //*** + ossim_uint32 last_line = theImageLength[theCurrentDirectory] - 1; + + ossim_uint32 strip_offset + = ((strip * theRowsPerStrip[theCurrentDirectory]) + + theRowsPerStrip[theCurrentDirectory] - 1) < + last_line ? 0 : + ((strip * theRowsPerStrip[theCurrentDirectory]) + + theRowsPerStrip[theCurrentDirectory] - 1) - last_line; + + ossim_uint32 total_rows = theRowsPerStrip[theCurrentDirectory] - + strip_offset; + + for (ossim_uint32 row=0; row<total_rows; row++) + { + // Write the line if it's in the clip rectangle. + ossim_int32 current_line = strip * theRowsPerStrip[theCurrentDirectory] + + row; + if (current_line >= clip_rect.ul().y && + current_line <= clip_rect.lr().y) + { + // + // Position the stip pointer to the correct spot. + // + // Note: + // A strip is organized from bottom to top and the raster buffer is + // orgainized from top to bottom so the lineBuf must be offset + // accordingly. + // + ossim_uint32* s = (ossim_uint32*)(theBuffer+ ((theRowsPerStrip[theCurrentDirectory] - row - + strip_offset - 1) * strip_width + clip_rect.ul().x * 4)); + + // Copy the data to the output buffer. + ossim_uint32 i=0; + + for (int32 sample=clip_rect.ul().x; + sample<=clip_rect.lr().x; + sample++) + { + d[0][i] = OSSIM_TIFF_UNPACK_R4(*s); + d[1][i] = OSSIM_TIFF_UNPACK_G4(*s); + d[2][i] = OSSIM_TIFF_UNPACK_B4(*s); + ++i; + ++s; + } + + for (band = 0; band < theSamplesPerPixel; band++) + { + d[band] += OUTPUT_TILE_WIDTH; + } + } + } // End of loop through rows in a strip. + + } // End of loop through strips. + + delete [] d; + + return true; +} + +//******************************************************************* +// Private Method: +//******************************************************************* +bool ossimTiffTileSource::loadFromRgbaU8aStrip(const ossimIrect& tile_rect, + const ossimIrect& clip_rect) +{ + static const char MODULE[] = "ossimTiffTileSource::loadFromRgbaU8aStrip"; + + //*** + // Specialized for one bit data to handle null values. + //*** + const ossim_uint32 OUTPUT_TILE_WIDTH = theTile->getWidth(); + const ossim_uint8 NULL_PIX = static_cast<ossim_uint8>(theTile->getNullPix(0)); + const ossim_uint8 MIN_PIX = static_cast<ossim_uint8>(theTile->getMinPix(0)); + + if (theSamplesPerPixel > 4 || theBytesPerPixel!= 1) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Error:" + << "\nInvalid number of bands or bytes per pixel!" << endl; + } + + //*** + // Calculate the number of strips to read. + //*** + ossim_uint32 starting_strip = clip_rect.ul().y / + theRowsPerStrip[theCurrentDirectory]; + ossim_uint32 ending_strip = clip_rect.lr().y / + theRowsPerStrip[theCurrentDirectory]; + ossim_uint32 output_tile_offset = (clip_rect.ul().y - tile_rect.ul().y) * + OUTPUT_TILE_WIDTH + clip_rect.ul().x - + tile_rect.ul().x; + +#if 0 + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\ntile_rect: " << tile_rect + << "\nclip_rect: " << clip_rect + << "\nstarting_strip: " << starting_strip + << "\nending_strip: " << ending_strip + << "\nstrip_width: " << strip_width + << "\noutput_tile_offset: " << output_tile_offset + << "\nsamples: " << theSamplesPerPixel + << endl; + } +#endif + + //*** + // Get the pointers positioned at the first valid pixel in the buffers. + // s = source + // d = destination + //*** + ossim_uint32 band; + + ossim_uint8** d = new ossim_uint8*[theSamplesPerPixel]; + for (band = 0; band < theSamplesPerPixel; band++) + { + d[band] = static_cast<ossim_uint8*>(theTile->getBuf(band))+output_tile_offset; + } + + // Loop through strips... + for (ossim_uint32 strip=starting_strip; strip<=ending_strip; strip++) + { + if (TIFFReadRGBAStrip(theTiffPtr, + (strip*theRowsPerStrip[theCurrentDirectory]), + (uint32*)theBuffer) == 0) // use tiff typedef + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Error reading strip!" <<endl; + delete [] d; + return false; + } + + //*** + // If the last strip is a partial strip then the first line of the + // strip will be the last line of the image. + //*** + ossim_uint32 last_line = theImageLength[theCurrentDirectory] - 1; + + ossim_uint32 strip_offset + = ((strip * theRowsPerStrip[theCurrentDirectory]) + + theRowsPerStrip[theCurrentDirectory] - 1) < last_line ? 0 : + ((strip * theRowsPerStrip[theCurrentDirectory]) + + theRowsPerStrip[theCurrentDirectory] - 1) - last_line; + + ossim_uint32 total_rows = theRowsPerStrip[theCurrentDirectory] - + strip_offset; + + for (ossim_uint32 row=0; row<total_rows; row++) + { + // Write the line if it's in the clip rectangle. + ossim_int32 current_line = strip * theRowsPerStrip[theCurrentDirectory] + + row; + if (current_line >= clip_rect.ul().y && + current_line <= clip_rect.lr().y) + { + //*** + // Position the stip pointer to the correct spot. + // + // Note: + // A strip is organized from bottom to top and the raster buffer is + // orgainized from top to bottom so the lineBuf must be offset + // accordingly. + //*** + ossim_uint8* s = theBuffer; + s += (theRowsPerStrip[theCurrentDirectory] - row - + strip_offset - 1) * + theImageWidth[theCurrentDirectory] * 4 + + clip_rect.ul().x * 4; + + // Copy the data to the output buffer. + ossim_uint32 i=0; + ossim_uint32 j=0; + for (int32 sample=clip_rect.ul().x; + sample<=clip_rect.lr().x; + sample++) + { + for (band = 0; band < theSamplesPerPixel; band++) + { + ossim_uint8 pix = s[j + band]; + d[band][i] = pix != NULL_PIX ? pix : MIN_PIX; + } + ++i; + j += 4; + } + + for (band = 0; band < theSamplesPerPixel; band++) + { + d[band] += OUTPUT_TILE_WIDTH; + } + } + } // End of loop through rows in a strip. + + } // End of loop through strips. + + delete [] d; + + return true; +} + +void ossimTiffTileSource::adjustToStartOfTile(ossimIpt& pt) const +{ + //*** + // Notes: + // - Assumes an origin of (0,0) + // - Shifts in to the upper left direction. + //*** + ossim_int32 tw = + static_cast<ossim_int32>(theImageTileWidth[theCurrentDirectory]); + ossim_int32 th = + static_cast<ossim_int32>(theImageTileLength[theCurrentDirectory]); + + if (pt.x > 0) + { + pt.x = (pt.x/tw) * tw; + } + else if (pt.x < 0) + { + pt.x = ossimAbs(pt.x) < tw ? -tw : (pt.x/tw)*tw; + } + + if (pt.y > 0) + { + pt.y = (pt.y/th) * th; + } + else if (pt.y < 0) + { + pt.y = ossimAbs(pt.y) < th ? -th : (pt.y/th)*th; + } +} + +bool ossimTiffTileSource::isValidRLevel(ossim_uint32 reduced_res_level) const +{ + if ( ( reduced_res_level > getHighestReducedResSet() ) || + ( !theR0isFullRes && (reduced_res_level == 0) ) ) + { +#if 0 + ossimNotify(ossimNotifyLevel_WARN) + << "ossimTiffTileSource::isValidRLevel Invalid reduced_res_level: " + << reduced_res_level + << "\nHighest available: " << getHighestReducedResSet() + << "\nR0 is " + << (theR0isFullRes ? "valid level." : "not a valid level.") + << endl; +#endif + return false; + } + + return true; +} + +ossim_uint32 ossimTiffTileSource::getHighestReducedResSet() const +{ + if (theOverview) + { + return theOverview->getHighestReducedResSet(); + } + + return (theR0isFullRes ? + theNumberOfDirectories-1 : + theNumberOfDirectories); +} + +ossim_uint32 ossimTiffTileSource::getCurrentTiffRLevel() const +{ + return (theR0isFullRes ? theCurrentDirectory : theCurrentDirectory + 1); +} + +ossimString ossimTiffTileSource::getReadMethod(ossim_uint32 directory) const +{ + switch (theReadMethod[directory]) + { + case READ_RGBA_U8_TILE: + return ossimString("READ_RGBA_U8_TILE"); + case READ_RGBA_U8_STRIP: + return ossimString("READ_RGBA_U8_STRIP"); + case READ_RGBA_U8A_STRIP: + return ossimString("READ_RGBA_U8A_STRIP"); + case READ_SCAN_LINE: + return ossimString("READ_SCAN_LINE"); + case READ_TILE: + return ossimString("READ_TILE"); + case UNKNOWN: + default: + return ossimString("UNKNOWN"); + } +} + +bool ossimTiffTileSource::allocateBuffer() +{ + //*** + // Allocate memory for a buffer to hold data grabbed from the tiff file. + //*** + ossim_uint32 buffer_size=0; + switch (theReadMethod[theCurrentDirectory]) + { + case READ_RGBA_U8_TILE: + buffer_size = theImageTileWidth[theCurrentDirectory]* + theImageTileWidth[theCurrentDirectory]*theBytesPerPixel*4; + break; + + case READ_TILE: + if (thePlanarConfig[theCurrentDirectory] == PLANARCONFIG_CONTIG) + { + buffer_size = theImageTileWidth[theCurrentDirectory] * + theImageTileLength[theCurrentDirectory] * + theBytesPerPixel * theSamplesPerPixel; + } + else + { + buffer_size = theImageTileWidth[theCurrentDirectory] * + theImageTileLength[theCurrentDirectory] * + theBytesPerPixel; + } + break; + + case READ_RGBA_U8_STRIP: + case READ_RGBA_U8A_STRIP: + buffer_size = theImageWidth[0]*theRowsPerStrip[theCurrentDirectory]* + theBytesPerPixel*4; + break; + + case READ_SCAN_LINE: + buffer_size = theImageWidth[0] * theBytesPerPixel * + theSamplesPerPixel * theTile->getHeight(); + break; + + default: + ossimNotify(ossimNotifyLevel_WARN) + << "Unknown read method!" << endl; + print(ossimNotify(ossimNotifyLevel_WARN)); + return false; + break; + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimTiffTileSource::allocateBuffer DEBUG:" + << "\nbuffer_size: " << buffer_size + << endl; + } + + theBufferRect.makeNan(); + theBufferRLevel = theCurrentDirectory; + + if (buffer_size != theBufferSize) + { + theBufferSize = buffer_size; + if (theBuffer) + { + delete [] theBuffer; + } + theBuffer = new ossim_uint8[buffer_size]; + } + + return true; +} + +ossim_uint32 ossimTiffTileSource::getNumberOfDirectories() const +{ + return theNumberOfDirectories; +} + +ossim_uint32 ossimTiffTileSource::getImageTileWidth() const +{ + return theImageTileLength[theCurrentDirectory]; +} + +ossim_uint32 ossimTiffTileSource::getImageTileHeight() const +{ + return theImageTileLength[theCurrentDirectory]; +} + +void ossimTiffTileSource::setApplyColorPaletteFlag(bool flag) +{ + theApplyColorPaletteFlag = flag; + + if(isColorMapped()) + { + if(theApplyColorPaletteFlag) + { + thePhotometric[0] = PHOTOMETRIC_PALETTE; + theSamplesPerPixel = 3; + } + else + { + thePhotometric[0] = PHOTOMETRIC_MINISBLACK; + theSamplesPerPixel = 1; + } + + setReadMethod(); + + initializeBuffers(); + } +} + +bool ossimTiffTileSource::getApplyColorPaletteFlag()const +{ + return theApplyColorPaletteFlag; +} + +ossimString ossimTiffTileSource::getLongName()const +{ + return ossimString("TIFF Image Handler"); +} + +ossimString ossimTiffTileSource::getShortName()const +{ + return ossimString("TIFF Image Handler"); +} + + +std::ostream& ossimTiffTileSource::print(std::ostream& os) const +{ + //*** + // Use a keyword format. + //*** + os << "image_file: " << theImageFile + << "\nsamples_per_pixel: " << theSamplesPerPixel + << "\nbits_per_sample: " << theBitsPerSample + << "\nsample_format_unit: " << theSampleFormatUnit + << "\nmin_sample_value: " << theMinSampleValue + << "\nmax_sample_value: " << theMaxSampleValue + << "\ntheNumberOfDirectories: " << theNumberOfDirectories + << "\nr0_is_full_res: " << theR0isFullRes; + + + for (ossim_uint32 i=0; i<theNumberOfDirectories; ++i) + { + os << "\ndirectory[" << i << "]" + << "\nimage width: " << theImageWidth[i] + << "\nimage_length: " << theImageLength[i] + << "\nread method: " << getReadMethod(i).c_str() + << "\nplanar: " << thePlanarConfig[i] + << "\nphotometric: " << thePhotometric[i]; + if (theRowsPerStrip[i]) + { + os << "\nrows per strip: " << theRowsPerStrip[i]; + } + if (theImageTileWidth[i]) + { + os << "\ntile_width: " << theImageTileWidth[i]; + } + if (theImageTileLength[i]) + { + os << "\ntile_length: " << theImageTileLength[i]; + } + os << endl; + } + + if (theTile.valid()) + { + os << "\nOutput tile dump:\n" << *theTile << endl; + } + + if (theOverview) + { + os << "\nOverview file:\n"; + theOverview->print(os); + } + + os << endl; + + return ossimSource::print(os); +} + +ossim_uint32 ossimTiffTileSource::getNumberOfInputBands() const +{ + return theSamplesPerPixel; +} + +ossim_uint32 ossimTiffTileSource::getNumberOfOutputBands () const +{ + return getNumberOfInputBands(); +} + +bool ossimTiffTileSource::isOpen()const +{ + return (theTiffPtr!=NULL); +} + +bool ossimTiffTileSource::hasR0() const +{ + return theR0isFullRes; +} + +double ossimTiffTileSource::getMinPixelValue(ossim_uint32 band)const +{ + if(theMetaData.getNumberOfBands()) + { + return ossimImageHandler::getMinPixelValue(band); + } + return theMinSampleValue; +} + +double ossimTiffTileSource::getMaxPixelValue(ossim_uint32 band)const +{ + if(theMetaData.getNumberOfBands()) + { + return ossimImageHandler::getMaxPixelValue(band); + } + return theMaxSampleValue; +} + +bool ossimTiffTileSource::isColorMapped() const +{ + uint16* red; + uint16* green; + uint16* blue; + + return static_cast<bool>(TIFFGetField(theTiffPtr, + TIFFTAG_COLORMAP, + &red, &green, &blue)); +} + +void ossimTiffTileSource::setReadMethod() +{ + for (ossim_uint32 dir=0; dir<theNumberOfDirectories; ++dir) + { + if (setTiffDirectory(dir) == false) + { + return; + } + + //--- + // Establish how this tiff directory will be read. + //--- + if (TIFFIsTiled(theTiffPtr)) + { + if ( ( thePhotometric[dir] == PHOTOMETRIC_YCBCR || + thePhotometric[dir] == PHOTOMETRIC_PALETTE ) && + (theSamplesPerPixel <= 3) && + (theBitsPerSample <= 8 )) + { + theReadMethod[dir] = READ_RGBA_U8_TILE; + } + else + { + theReadMethod[dir] = READ_TILE; + } + } + else // Not tiled... + { + if ( (thePhotometric[dir] == PHOTOMETRIC_PALETTE || + thePhotometric[dir] == PHOTOMETRIC_YCBCR ) && + theSamplesPerPixel <= 3 && + theBitsPerSample <= 8 ) + { + theReadMethod[dir] = READ_RGBA_U8_STRIP; + } + else if (theSamplesPerPixel <= 3 && theBitsPerSample == 1) + { + //--- + // Note: One bit data expands to zeroes and 255's so run it through + // a specialized method to flip zeroes to one's since zeroes + // are usually reserved for null value. + //--- + theReadMethod[dir] = READ_RGBA_U8A_STRIP; + } + else + { + theReadMethod[dir] = READ_SCAN_LINE; + } + } + + } // End of loop through directories. + + // Reset the directory back to "0". + setTiffDirectory(0); +} + +void ossimTiffTileSource::initializeBuffers() +{ + if(theBuffer) + { + delete [] theBuffer; + theBuffer = 0; + } + + ossimImageDataFactory* idf = ossimImageDataFactory::instance(); + + theTile = idf->create(this, + this); + + // + // Tiles are constructed with no buffer storage. Call initialize for + // "theTile" to allocate memory. Leave "theBlankTile" with a + // ossimDataObjectStatus of OSSIM_NULL since no data will ever be + // stuffed in it. + // + theTile->initialize(); + allocateBuffer(); +} + + +void ossimTiffTileSource::setProperty(ossimRefPtr<ossimProperty> property) +{ + if(!property.valid()) + { + return; + } + if(property->getName() == "apply_color_palette_flag") + { + // Assuming first directory... + setApplyColorPaletteFlag(property->valueToString().toBool()); + } + else + { + ossimImageHandler::setProperty(property); + } +} + +ossimRefPtr<ossimProperty> ossimTiffTileSource::getProperty(const ossimString& name)const +{ + if(name == "apply_color_palette_flag") + { + ossimBooleanProperty* property = new ossimBooleanProperty("apply_color_palette_flag", + theApplyColorPaletteFlag); + property->clearChangeType(); + property->setFullRefreshBit(); + return property; + } + + return ossimImageHandler::getProperty(name); +} + +void ossimTiffTileSource::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + ossimImageHandler::getPropertyNames(propertyNames); + + // Assuming first directory... + if(isColorMapped()) + { + propertyNames.push_back("apply_color_palette_flag"); + } +} + +bool ossimTiffTileSource::setTiffDirectory(ossim_uint32 directory) +{ + bool status = TIFFSetDirectory(theTiffPtr, directory); + if (status == true) + { + theCurrentDirectory = directory; + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimTiffTileSource::setTiffDirectory ERROR setting directory " + << directory << "!" << endl; + } + return status; +} + +void ossimTiffTileSource::populateLut() +{ + ossim_uint16* r; + ossim_uint16* g; + ossim_uint16* b; + if(TIFFGetField(theTiffPtr, TIFFTAG_COLORMAP, &r, &g, &b)) + { + ossim_uint32 numEntries = 256; + ossimScalarType scalarType = OSSIM_UINT8; + if(theBitsPerSample == 16) + { + numEntries = 65536; + scalarType = OSSIM_UINT16; + } + theLut = new ossimNBandLutDataObject(numEntries, + 3, + scalarType, + 0); + ossim_uint32 entryIdx = 0; + for(entryIdx = 0; entryIdx < numEntries; ++entryIdx) + { + if(scalarType == OSSIM_UINT8) + { + (*theLut)[entryIdx][0] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(((*r)/65535.0)*255.0); + (*theLut)[entryIdx][1] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(((*g)/65535.0)*255.0); + (*theLut)[entryIdx][2] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(((*b)/65535.0)*255.0); + } + else + { + (*theLut)[entryIdx][0] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(*r); + (*theLut)[entryIdx][1] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(*g); + (*theLut)[entryIdx][2] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(*b); + } + ++r;++g;++b; + } + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimTiffTileSource.h b/Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimTiffTileSource.h new file mode 100644 index 0000000000..799f7a2325 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimTiffTileSource.h @@ -0,0 +1,268 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// Frank Warmerdam (warmerdam@pobox.com) +// +// Description: +// +// Contains class declaration for ossimTiffTileSource. +// ossimTiffTileSource is derived from ImageHandler which is derived from +// TileSource. +//******************************************************************* +// $Id: ossimTiffTileSource.h,v 1.37 2005/11/08 21:50:21 dburken Exp $ + +#ifndef ossimTiffTileSource_HEADER +#define ossimTiffTileSource_HEADER + +#include <tiffio.h> + +#include <imaging/formats/ossimImageHandler.h> +#include <base/data_types/ossimIrect.h> + +class ossimImageData; +class ossimTiffOverviewTileSource; + +class OSSIMDLLEXPORT ossimTiffTileSource : public ossimImageHandler +{ +public: + + enum ReadMethod + { + UNKNOWN, + READ_RGBA_U8_TILE, + READ_RGBA_U8_STRIP, + READ_RGBA_U8A_STRIP, + READ_SCAN_LINE, + READ_TILE + }; + + ossimTiffTileSource(); + + virtual ~ossimTiffTileSource(); + + virtual ossimString getLongName() const; + virtual ossimString getShortName() const; + + /*! + * Returns true if the image_file can be opened and is a valid tiff file. + */ + virtual bool open(const ossimFilename& image_file); + virtual void close(); + + /*! + * Returns a pointer to a tile given an origin representing the upper left + * corner of the tile to grab from the image. + * Satisfies pure virtual from TileSource class. + */ + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect, + ossim_uint32 resLevel=0); + + /*! + * Returns the number of bands in the image. + * Satisfies pure virtual from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfInputBands() const; + virtual ossim_uint32 getNumberOfOutputBands () const; + + /*! + * Returns the number of lines in the image. + * Satisfies pure virtual from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfLines(ossim_uint32 reduced_res_level = 0) const; + + /*! + * Returns the number of samples in the image. + * Satisfies pure virtual from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfSamples(ossim_uint32 reduced_res_level = 0) const; + + /*! + * Returns the number of image file directories in the tiff image. + */ + virtual ossim_uint32 getNumberOfDirectories() const; + + /*! + * Returns the number of reduced resolution data sets (rrds). + * Notes: + * + * - The full res image is counted as a data set so an image with no + * reduced resolution data set will have a count of one. + * - This method counts R0 as a res set even if it does not have one. + * This was done deliberately so as to not screw up code down the + * line. + */ + virtual ossim_uint32 getNumberOfDecimationLevels() const; + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual bool isOpen()const; + + /*! + * Returns the output pixel type of the tile source. + */ + virtual ossimScalarType getOutputScalarType() const; + + /*! + * Returns the width of the output tile. + */ + virtual ossim_uint32 getTileWidth() const; + + /*! + * Returns the height of the output tile. + */ + virtual ossim_uint32 getTileHeight() const; + + /*! + * Returns true if the first directory of the tiff image did not have + * the reduced resolution file type set. + */ + bool hasR0() const; + + virtual double getMinPixelValue(ossim_uint32 band=0)const; + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + + virtual bool isValidRLevel(ossim_uint32 reduced_res_level) const; + + /*! + * Returns the highest available reduced resolution data sets (rrds). + * Note: zero based + */ + ossim_uint32 getHighestReducedResSet() const; + + /*! + * @return The tile width of the image or 0 if the image is not tiled. + * Note: this is not the same as the ossimImageSource::getTileWidth which + * returns the output tile width, which can be different than the + * internal image tile width on disk. + */ + virtual ossim_uint32 getImageTileWidth() const; + + /*! + * @return The tile width of the image or 0 if the image is not tiled. + * Note: this is not the same as the ossimImageSource::getTileHeight which + * returns the output tile width which can be different than the internal + * image tile width on disk. + */ + virtual ossim_uint32 getImageTileHeight() const; + + void setApplyColorPaletteFlag(bool flag); + bool getApplyColorPaletteFlag()const; + + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + bool isColorMapped() const; + + virtual std::ostream& print(std::ostream& os) const; + +protected: + /*! + * Returns true if no errors initializing object. + * + * Notes: + * - Callers of this method must ensure "theTiffPtr" data member + * is initialized. + * - This method was added to consolidate object initialization code + * between constructor and public open method. + */ + bool open(); + +private: + + /*! + * Adjust point to even tile boundary. Assumes 0,0 origin. + * Shifts in the upper left direction. + */ + void adjustToStartOfTile(ossimIpt& pt) const; + + /*! + * If the tiff source has R0 then this returns the current tiff directory + * that the tiff pointer is pointing to; else, it returns the current + * directory + 1. + */ + ossim_uint32 getCurrentTiffRLevel() const; + + ossimString getReadMethod(ossim_uint32 directory) const; + + bool allocateBuffer(); + + bool loadTile(const ossimIrect& tile_rect, + const ossimIrect& clip_rect); + + bool loadFromRgbaU8Tile(const ossimIrect& tile_rect, + const ossimIrect& clip_rect); + + bool loadFromRgbaU8Strip(const ossimIrect& tile_rect, + const ossimIrect& clip_rect); + + bool loadFromRgbaU8aStrip(const ossimIrect& tile_rect, + const ossimIrect& clip_rect); + + bool loadFromScanLine(const ossimIrect& clip_rect); + + bool loadFromTile(const ossimIrect& clip_rect); + + void setReadMethod(); + virtual void initializeBuffers(); + + /** + * Change tiff directory and sets theCurrentDirectory. + * + * @return true on success, false on error. + */ + bool setTiffDirectory(ossim_uint32 directory); + + void populateLut(); + + ossimRefPtr<ossimImageData> theTile; + + ossim_uint8* theBuffer; + ossim_uint32 theBufferSize; + ossimIrect theBufferRect; + ossim_uint32 theBufferRLevel; + TIFF* theTiffPtr; + + ossim_uint16 theSamplesPerPixel; + ossim_uint16 theBitsPerSample; + ossim_uint16 theSampleFormatUnit; + double theMaxSampleValue; + double theMinSampleValue; + ossim_uint32 theNumberOfDirectories; + ossim_uint32 theCurrentDirectory; + bool theR0isFullRes; + ossim_uint32 theBytesPerPixel; + ossimScalarType theScalarType; + bool theApplyColorPaletteFlag; + + // Things we need from each directory as they can be different. + vector<ossim_uint32> theImageWidth; + vector<ossim_uint32> theImageLength; + vector<ReadMethod> theReadMethod; + vector<ossim_uint16> thePlanarConfig; + vector<ossim_uint16> thePhotometric; + vector<ossim_uint32> theRowsPerStrip; + vector<ossim_uint32> theImageTileWidth; + vector<ossim_uint32> theImageTileLength; + + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimTiffWriter.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimTiffWriter.cpp new file mode 100644 index 0000000000..ee06f77eca --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimTiffWriter.cpp @@ -0,0 +1,2316 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: Frank Warmerdam (warmerda@home.com) +// +//******************************************************************* +// $Id: ossimTiffWriter.cpp,v 1.145 2006/01/06 16:46:46 dburken Exp $ + +#include <algorithm> +#include <sstream> + +#include <ossimConfig.h> + +#include <imaging/formats/tiff/ossimTiffWriter.h> +#include <base/common/ossimKeywordNames.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/datum/ossimDatum.h> +#include <base/common/ossimTrace.h> +#include <base/property/ossimNumericProperty.h> +#include <base/property/ossimStringProperty.h> +#include <base/property/ossimBooleanProperty.h> +#include <base/property/ossimFilenameProperty.h> +#include <projections/map_projections/ossimMapProjection.h> +#include <projections/map_projections/ossimMapProjectionInfo.h> +#include <imaging/ossimImageData.h> +#include <imaging/ossimImageSource.h> +#include <projections/map_projections/ossimUtmProjection.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <base/misc/lookup_tables/ossimUnitTypeLut.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <base/property/ossimFilenameProperty.h> + +static ossimTrace traceDebug("ossimTiffWriter:debug"); + +#ifdef OSSIM_HAS_GEOTIFF +# if OSSIM_HAS_GEOTIFF +# include <xtiffio.h> +# include <geotiff.h> +# include <geo_normalize.h> +# include <geovalues.h> +# endif +#endif + +static const char* TIFF_WRITER_OUTPUT_TILE_SIZE_X_KW = "output_tile_size_x"; +static const char* TIFF_WRITER_OUTPUT_TILE_SIZE_Y_KW = "output_tile_size_y"; +static const int PCS_BRITISH_NATIONAL_GRID = 27700; +static const long DEFAULT_JPEG_QUALITY = 75; + +RTTI_DEF1(ossimTiffWriter, "ossimTiffWriter", ossimImageFileWriter); + +ossimTiffWriter::ossimTiffWriter() + : + ossimImageFileWriter(), + theTif(NULL), + thePixelType(OSSIM_PIXEL_IS_POINT), + theProjectionUnits(OSSIM_METERS), + theCompressionType("none"), + theJpegQuality(DEFAULT_JPEG_QUALITY), + theOutputGeotiffTagsFlag(true), + theImagineNad27Flag(false), + theColorLutFlag(false), + theProjectionInfo(NULL), + theOutputTileSize(OSSIM_DEFAULT_TILE_WIDTH, OSSIM_DEFAULT_TILE_HEIGHT) +{ + ossimGetDefaultTileSize(theOutputTileSize); + theOutputImageType = "tiff_tiled_band_separate"; +} + +ossimTiffWriter::~ossimTiffWriter() +{ + if(isOpen()) + { + closeTiff(); + } + if(theProjectionInfo) + { + delete theProjectionInfo; + theProjectionInfo = NULL; + } +} + +bool ossimTiffWriter::openTiff() +{ + static const char* MODULE = "ossimTiffWriter::openTiff()"; + + if (theTif) // Close the existing file pointer. + { + +#ifdef OSSIM_HAS_GEOTIFF +# if OSSIM_HAS_GEOTIFF + XTIFFClose( theTif ); +# else + TIFFClose( theTif ); +# endif +#else + TIFFClose( theTif ); +#endif + + } + + // Open the new file. +#ifdef OSSIM_HAS_GEOTIFF +# if OSSIM_HAS_GEOTIFF + theTif = XTIFFOpen( theFilename.c_str(), "w" ); +# else + theTif = TIFFOpen( theFilename.c_str(), "w" ); +# endif +#else + theTif = TIFFOpen( theFilename.c_str(), "w" ); +#endif + + if (!theTif) + { + setErrorStatus(); // base class + ossimSetError(getClassName().c_str(), + ossimErrorCodes::OSSIM_ERROR, + "File %s line %d Module %s Error:\n\ +Error opening file: %s\n", + __FILE__, + __LINE__, + MODULE, + theFilename.c_str()); + + return false; + } + return true; +} + +bool ossimTiffWriter::closeTiff() +{ + if (theTif) + { +#ifdef OSSIM_HAS_GEOTIFF +# if OSSIM_HAS_GEOTIFF + XTIFFClose( theTif ); +# else + TIFFClose( theTif ); +# endif +#else + TIFFClose( theTif ); +#endif + theTif = NULL; + } + + return true; +} + +bool ossimTiffWriter::writeTiffTags() +{ + static const char MODULE[] = "ossimTiffWriter::writeTiffTags"; + + if (!theTif) + { + setErrorStatus(); // base class + ossimSetError(getClassName().c_str(), + ossimErrorCodes::OSSIM_ERROR, + "File %s line %d %s\nError: Tiff pointer is null!\n\ +Call setFilename method.\n", + __FILE__, + __LINE__, + MODULE); + return false; + } + + //*** + // NOTE: + // Since the tiff library uses the variable argument list function "va_arg" + // it is important to use the correct data type. If in doubt see the + // code for libtiff's _TIFFVSetField in "tif_dir.c" in the libtiff package. + //*** + + int bitsPerSample = 0; + int sampleFormat = 0; + switch( theInputConnection->getOutputScalarType() ) + { + case OSSIM_UINT8: + bitsPerSample = 8; + sampleFormat = SAMPLEFORMAT_UINT; + break; + + case OSSIM_UINT16: + case OSSIM_USHORT11: + bitsPerSample = 16; + sampleFormat = SAMPLEFORMAT_UINT; + break; + + case OSSIM_SINT16: + bitsPerSample = 16; + sampleFormat = SAMPLEFORMAT_INT; + break; + + case OSSIM_FLOAT32: + case OSSIM_NORMALIZED_FLOAT: + bitsPerSample = 32; + sampleFormat = SAMPLEFORMAT_IEEEFP; + break; + + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_FLOAT64: + bitsPerSample = 64; + sampleFormat = SAMPLEFORMAT_IEEEFP; + break; + + default: + return false; + } + + // Set the pixel type. + TIFFSetField( theTif, TIFFTAG_BITSPERSAMPLE, bitsPerSample ); + TIFFSetField( theTif, TIFFTAG_SAMPLEFORMAT, sampleFormat ); + + // Set the image dimensions. + ossim_uint32 width = theAreaOfInterest.width(); + ossim_uint32 height = theAreaOfInterest.height(); + TIFFSetField( theTif, TIFFTAG_IMAGEWIDTH, width); + TIFFSetField( theTif, TIFFTAG_IMAGELENGTH, height); + if (isTiled()) + { + ossim_uint32 tileXSize = theOutputTileSize.x; + ossim_uint32 tileYSize = theOutputTileSize.y; + TIFFSetField(theTif, TIFFTAG_TILEWIDTH, tileXSize); + TIFFSetField(theTif, TIFFTAG_TILELENGTH, tileYSize); + } + else + { + TIFFSetField(theTif, TIFFTAG_ROWSPERSTRIP, ossim_uint32(1)); + } + + ossim_uint32 numberOfBands = theInputConnection->getNumberOfOutputBands(); + + // Set the min/max values. + std::vector<ossim_float64> minBand(numberOfBands); + std::vector<ossim_float64> maxBand(numberOfBands); + for(ossim_uint32 idx = 0; idx < numberOfBands; ++idx) + { + maxBand[idx] = theInputConnection->getMaxPixelValue(idx); + minBand[idx] = theInputConnection->getMinPixelValue(idx); + } + + writeMinMaxTags(minBand, maxBand); + + // Set the planar configuration. + if ( (theOutputImageType == "tiff_strip") || + (theOutputImageType == "tiff_tiled") || + (theOutputImageType == "image/tiff") || + (theOutputImageType == "image/tif") || + (theOutputImageType == "image/gtif") || + (theOutputImageType == "image/gtiff") ) + { + TIFFSetField( theTif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + } + else + { + TIFFSetField( theTif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_SEPARATE); + } + + // Set the compression type: + uint16 tiffCompressType = COMPRESSION_NONE; + theCompressionType.downcase(); + if( theCompressionType == "jpeg") + { + tiffCompressType = COMPRESSION_JPEG; + + // Set the jpeg quality. + TIFFSetField( theTif, TIFFTAG_JPEGQUALITY, theJpegQuality); + } + else if(theCompressionType == "packbits") + { + tiffCompressType = COMPRESSION_PACKBITS; + } + else if((theCompressionType == "deflate") || + (theCompressionType == "zip")) + { + tiffCompressType = COMPRESSION_DEFLATE; + } + TIFFSetField( theTif, TIFFTAG_COMPRESSION, tiffCompressType); + TIFFSetField(theTif, TIFFTAG_SAMPLESPERPIXEL, (int)theInputConnection->getNumberOfOutputBands()); + + ossimScalarType scalarType = theInputConnection->getOutputScalarType(); + bool lutEnabled = (theColorLutFlag&& + ((scalarType == OSSIM_UINT8)|| + (scalarType == OSSIM_UINT16)|| + (scalarType == OSSIM_USHORT11))&& + (theColorLut.getNumberOfEntries() > 0)&& + (theInputConnection->getNumberOfOutputBands() == 1)); + if(lutEnabled) + { + TIFFSetField( theTif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE ); + TIFFSetField( theTif, TIFFTAG_INDEXED, (ossim_uint16)1); + + if(scalarType == OSSIM_UINT8) + { + ossim_uint16 r[256], g[256], b[256]; + + memset(r, '\0', sizeof(ossim_uint16)*256); + memset(g, '\0', sizeof(ossim_uint16)*256); + memset(b, '\0', sizeof(ossim_uint16)*256); + + for(ossim_uint32 i = 0; i < theColorLut.getNumberOfEntries(); i++) + { + r[i] = (ossim_uint16) ((theColorLut[i][0]/255.0)*65535); + g[i] = (ossim_uint16) ((theColorLut[i][1]/255.0)*65535); + b[i] = (ossim_uint16) ((theColorLut[i][2]/255.0)*65535); + } + TIFFSetField(theTif, TIFFTAG_COLORMAP, r, g ,b); + } + else + { + ossim_uint16 r[65536], g[65536], b[65536]; + memset(r, '\0', sizeof(ossim_uint16)*65536); + memset(g, '\0', sizeof(ossim_uint16)*65536); + memset(b, '\0', sizeof(ossim_uint16)*65536); + + for(ossim_uint32 i = 0; i < theColorLut.getNumberOfEntries(); i++) + { + r[i] = (ossim_uint16) (theColorLut[i][0]); + g[i] = (ossim_uint16) (theColorLut[i][1]); + b[i] = (ossim_uint16) (theColorLut[i][2]); + } + TIFFSetField(theTif, TIFFTAG_COLORMAP, r, g ,b); + } + } + else if( (theInputConnection->getNumberOfOutputBands() == 3 || + theInputConnection->getNumberOfOutputBands() == 4 || + (thePhotoMetric == "rgb"))&& + (scalarType == OSSIM_UCHAR)) + { + TIFFSetField( theTif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB ); + } + else + { + TIFFSetField( theTif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK ); + } + + return true; +} + +bool ossimTiffWriter::writeGeotiffTags(ossimMapProjectionInfo* projectionInfo) +{ + static const char MODULE[] = "ossimTiffWriter::writeGeotiffTags"; + + if (!theTif) + { + setErrorStatus(); // base class + ossimSetError(getClassName().c_str(), + ossimErrorCodes::OSSIM_ERROR, + "File %s line %d %s\nError: Tiff pointer is null!\n\ +Call setFilename method.\n", + __FILE__, + __LINE__, + MODULE); + return false; + } + +#ifdef OSSIM_HAS_GEOTIFF +# if OSSIM_HAS_GEOTIFF + + ossimKeywordlist kwl; + projectionInfo->setPixelType(thePixelType); + + if(projectionInfo && projectionInfo->getProjection()) + { + projectionInfo->getProjection()->saveState(kwl); + } + const char* pcs_code = kwl.find(ossimKeywordNames::PCS_CODE_KW); + const char* stdParallel1 = kwl.find(ossimKeywordNames::STD_PARALLEL_1_KW); + const char* stdParallel2 = kwl.find(ossimKeywordNames::STD_PARALLEL_2_KW); + const char* scaleFactor = kwl.find(ossimKeywordNames::SCALE_FACTOR_KW); + const char* origin = kwl.find(ossimKeywordNames::ORIGIN_LATITUDE_KW); + const char* false_easting = kwl.find(ossimKeywordNames::FALSE_EASTING_KW); + const char* false_northing = kwl.find(ossimKeywordNames::FALSE_NORTHING_KW); + const char* central_meridian = kwl.find(ossimKeywordNames::CENTRAL_MERIDIAN_KW); + + GTIF* gtif = GTIFNew(theTif); + + // Get a pointer to the projection. + const ossimMapProjection* proj = projectionInfo->getProjection(); + if(theProjectionUnits == OSSIM_US_SURVEY_FEET) + { + projectionInfo->setOutputFeetFlag(true); + } + ossimString proj_name = proj->getClassName(); + + UnitType units = LINEAR_METER; + + if (projectionInfo->unitsInFeet()) + { + units = LINEAR_FOOT_US_SURVEY; + } + else if ( ( proj_name == "ossimCylEquAreaProjection" ) || + ( proj_name == "ossimEquDistCylProjection" ) || + ( proj_name == "ossimLlxyProjection" ) ) + { + units = ANGULAR_DEGREES; + } + + // Set the model type. + if (units == ANGULAR_DEGREES) + { + GTIFKeySet(gtif, + GTModelTypeGeoKey, + TYPE_SHORT, + 1, + ModelTypeGeographic); + + // Set the units key. + GTIFKeySet(gtif, + GeogAngularUnitsGeoKey, + TYPE_SHORT, + 1, + units); + } + else + { + GTIFKeySet(gtif, + GTModelTypeGeoKey, + TYPE_SHORT, + 1, + ModelTypeProjected); + + // Set the units key. + GTIFKeySet(gtif, + ProjLinearUnitsGeoKey, + TYPE_SHORT, + 1, + units); + } + + // Set the tie point and scale. + double tiePoints[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + double pixScale[3] = { 0.0, 0.0, 0.0 }; + + switch (units) + { + case LINEAR_METER: + { + tiePoints[3] = projectionInfo->ulEastingNorthingPt().x; + tiePoints[4] = projectionInfo->ulEastingNorthingPt().y; + pixScale[0] = projectionInfo->getMetersPerPixel().x; + pixScale[1] = projectionInfo->getMetersPerPixel().y; + break; + } + case LINEAR_FOOT_US_SURVEY: + { + tiePoints[3] = projectionInfo->ulEastingNorthingPtInFt().x; + tiePoints[4] = projectionInfo->ulEastingNorthingPtInFt().y; + pixScale[0] = projectionInfo->getUsSurveyFeetPerPixel().x; + pixScale[1] = projectionInfo->getUsSurveyFeetPerPixel().y; + break; + } + case ANGULAR_DEGREES: + { + tiePoints[3] = projectionInfo->ulGroundPt().lond(); + tiePoints[4] = projectionInfo->ulGroundPt().latd(); + pixScale[0] = projectionInfo->getDecimalDegreesPerPixel().x; + pixScale[1] = projectionInfo->getDecimalDegreesPerPixel().y; + break; + } + } // End of "switch (units)" + + TIFFSetField( theTif, TIFFTAG_GEOTIEPOINTS, 6, tiePoints ); + TIFFSetField( theTif, TIFFTAG_GEOPIXELSCALE, 3, pixScale ); + + if (projectionInfo->getPixelType() == OSSIM_PIXEL_IS_POINT) + { + // Tie point relative to center of pixel. + GTIFKeySet(gtif, GTRasterTypeGeoKey, TYPE_SHORT, 1, RasterPixelIsPoint); + } + else + { + // Tie point relative to upper left corner of pixel + GTIFKeySet(gtif, GTRasterTypeGeoKey, TYPE_SHORT, 1, RasterPixelIsArea); + } + + ossimString datumCode = "WGE"; + ossimString datumName = "WGE"; + // Attemp to get the datum code + const ossimDatum* datum = proj->getDatum(); + if(datum) + { + datumCode = datum->code(); + datumName = datum->name(); + } + + short gcs = USER_DEFINED; + + if (datumCode == "WGE") gcs = GCS_WGS_84; + else if (datumCode == "WGD") gcs = GCS_WGS_72; + else if (datumCode == "NAR-C") gcs = GCS_NAD83; + else if (datumCode == "NAR") gcs = GCS_NAD83; + else if (datumCode == "NAS-C") gcs = GCS_NAD27; + else if (datumCode == "NAS") gcs = GCS_NAD27; + else if (datumCode == "ADI-M") gcs = GCS_Adindan; + else if (datumCode == "ARF-M") gcs = GCS_Arc_1950; + else if (datumCode == "ARS-M") gcs = GCS_Arc_1960; + else if (datumCode == "EUR-7" || datumCode == "EUR-M") gcs = GCS_ED50; + else if ((datumCode == "OGB-7") || + (datumCode == "OGB-M") || + (datumCode == "OGB-A") || + (datumCode == "OGB-B") || + (datumCode == "OGB-C") || + (datumCode == "OGB-D")) gcs = GCS_OSGB_1936; + else if (datumCode == "TOY-M") gcs = GCS_Tokyo; + else + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DATUM = " << datumCode << " tag not written " << std::endl + << "Please let us know so we can add it" << std::endl; + } + } + + GTIFKeySet( gtif, GeographicTypeGeoKey, TYPE_SHORT, 1, gcs ); + + // *** + // ERDAS Imagine < v8.7 has a NAD27 Conus Bug. They are not using the + // proper GCS code. They use user-defined fields and Geog cititaion tag to + // define. Sucks! It is an open issue at Leica. This is a work around + // flag for this issue. + // *** + if((datumCode == "NAS-C") && theImagineNad27Flag) + { + gcs = USER_DEFINED; + + std::ostringstream os; + os << "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile: ossimTiffWriter.cpp,v $ $Revision: 1.145 $ $Date: 2006/01/06 16:46:46 $\nUnable to match Ellipsoid (Datum) to a GeographicTypeGeoKey value\nEllipsoid = Clarke 1866\nDatum = NAD27 (CONUS)"; + + GTIFKeySet(gtif, + GeogCitationGeoKey, + TYPE_ASCII, + 1, + os.str().c_str()); + + // User-Defined + GTIFKeySet(gtif, GeogGeodeticDatumGeoKey, TYPE_SHORT, 1, + KvUserDefined ); + // User-Defined + GTIFKeySet(gtif, GeogEllipsoidGeoKey, TYPE_SHORT, 1, + KvUserDefined ); + } + else + GTIFKeySet( gtif, GeographicTypeGeoKey, TYPE_SHORT, 1, gcs ); + + // Set the ellipsoid major/minor axis. + GTIFKeySet(gtif, + GeogSemiMajorAxisGeoKey, + TYPE_DOUBLE, + 1, + proj->getA()); + + GTIFKeySet(gtif, + GeogSemiMinorAxisGeoKey, + TYPE_DOUBLE, + 1, + proj->getB()); + + // Write the projection parameters. + + + + if (proj_name == "ossimUtmProjection") + { + //*** + // UTM tags needed example from the geo tiff spec page: + // ModelTiepointTag = (0, 0, 0, 350807.4, 5316081.3, 0.0) + // ModelPixelScaleTag = (100.0, 100.0, 0.0) + // GeoKeyDirectoryTag: + // GTModelTypeGeoKey = 1 (ModelTypeProjected) + // GTRasterTypeGeoKey = 1 (RasterPixelIsArea) + // ProjectedCSTypeGeoKey = 32660 (PCS_WGS84_UTM_zone_60N) + // PCSCitationGeoKey = "UTM Zone 60 N with WGS84" + // + // NOTE: + // The "ProjectedCSTypeGeoKey" can be constructed using the map zone + // and the datum. + //*** + const ossimUtmProjection* utmProjection + = PTR_CAST(ossimUtmProjection, proj); + + // Attempt to get the pcs key. + int mapZone = utmProjection->getZone(); + ossimString hemisphere = utmProjection->getHemisphere(); + bool use_pcs_key = true; + short projSysCode=0; + + switch ( gcs ) + { + case GCS_WGS_84: + { + if (hemisphere == "N") // Northern hemisphere. + { + projSysCode = 32600 + mapZone; + } + else // Southern hemisphere. + { + projSysCode = 32700 + mapZone; + } + break; + } + + case GCS_WGS_72: + { + if (hemisphere == "N") // Northern hemisphere. + { + projSysCode = 32200 + mapZone; + } + else // Southern hemisphere. + { + projSysCode = 32300 + mapZone; + } + break; + } + + case GCS_NAD27: + { + if (hemisphere == "N") // Northern hemisphere. + { + projSysCode = 26700 + mapZone; + } + else // Southern hemisphere. + { + projSysCode = 32000 + mapZone; + } + break; + } + + case GCS_NAD83: + if (hemisphere == "N") // Northern hemisphere. + { + projSysCode = 26900 + mapZone; + } + else // Southern hemisphere. + { + projSysCode = 32100 + mapZone; + } + break; + + default: + { + //*** + // Use a projection code that does not imply a datum. + // See section "6.3.3.2 Projection Codes" for definition. + //*** + use_pcs_key = false; + if (mapZone > 0) // Northern hemisphere. + { + projSysCode = 16000 + mapZone; + } + else if (mapZone < 0) // Southern hemisphere. + { + hemisphere = "S"; + projSysCode = 16100 + abs(mapZone); + } + + // Set the Projected Coordinate System Type to be user defined. + GTIFKeySet(gtif, + ProjectedCSTypeGeoKey, + TYPE_SHORT, + 1, + USER_DEFINED); + + // Set the geographic type to be user defined. + GTIFKeySet(gtif, + GeographicTypeGeoKey, + TYPE_SHORT, + 1, + USER_DEFINED); + + // Set the ProjectionGeoKey in place of the ProjectedCSTypeGeoKey. + GTIFKeySet(gtif, + ProjectionGeoKey, + TYPE_SHORT, + 1, + projSysCode); + break; + } + + } // End of "switch ( gcs )" + + if (use_pcs_key) + { + GTIFKeySet(gtif, + ProjectedCSTypeGeoKey, + TYPE_SHORT, + 1, + projSysCode); + } + + if (traceDebug()) + { + CLOG << " DEBUG:\n" + << "Geotiff ProjectedCSTypeGeoKey: " << projSysCode + << std::endl; + } + + std::ostringstream os; + os << "UTM Zone " << dec << mapZone << hemisphere.c_str() + << " with " << datumName << " datum"; + + GTIFKeySet(gtif, + PCSCitationGeoKey, + TYPE_ASCII, + 1, + os.str().c_str()); + + } // End of "if (proj_name == "ossimUtmProjection")" + else if(proj_name == "ossimBngProjection") + { + // User-Defined + GTIFKeySet(gtif, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, + PCS_BRITISH_NATIONAL_GRID);//KvUserDefined ); + + // User-Defined + GTIFKeySet(gtif, ProjectionGeoKey, TYPE_SHORT, 1, + KvUserDefined ); + + GTIFKeySet(gtif, + PCSCitationGeoKey, + TYPE_ASCII, + 26, + "PCS_British_National_Grid"); + + GTIFKeySet(gtif, + ProjCoordTransGeoKey, + TYPE_SHORT, + 1, + (uint16)CT_TransverseMercator); + + double clon = ossimString(central_meridian).toDouble(); + + GTIFKeySet(gtif, + ProjNatOriginLongGeoKey, + TYPE_DOUBLE, + 1, + clon); + + double olat = ossimString(origin).toDouble(); + + GTIFKeySet(gtif, + ProjNatOriginLatGeoKey, + TYPE_DOUBLE, + 1, + olat); + + double fe = ossimString(false_easting).toDouble(); + + GTIFKeySet(gtif, + ProjFalseEastingGeoKey, + TYPE_DOUBLE, + 1, + fe); + + double fn = ossimString(false_northing).toDouble(); + + GTIFKeySet(gtif, + ProjFalseNorthingGeoKey, + TYPE_DOUBLE, + 1, + fn); + + double scale = ossimString(scaleFactor).toDouble(); + + GTIFKeySet(gtif, + ProjScaleAtNatOriginGeoKey, + TYPE_DOUBLE, + 1, + scale); + } + else if( (proj_name == "ossimEquDistCylProjection")|| + (proj_name == "ossimLlxyProjection")) + { + double clon = ossimString(central_meridian).toDouble(); + + GTIFKeySet(gtif, + ProjNatOriginLongGeoKey, + TYPE_DOUBLE, + 1, + clon); + + double olat = ossimString(origin).toDouble(); + + GTIFKeySet(gtif, + ProjNatOriginLatGeoKey, + TYPE_DOUBLE, + 1, + olat); + if(proj_name == "ossimLlxyProjection") + { + double fe = ossimString(false_easting).toDouble(); + + GTIFKeySet(gtif, + ProjFalseEastingGeoKey, + TYPE_DOUBLE, + 1, + fe); // False Easting + + double fn = ossimString(false_northing).toDouble(); + + GTIFKeySet(gtif, + ProjFalseNorthingGeoKey, + TYPE_DOUBLE, + 1, + fn); // False Northing + } + } + else if ( (proj_name == "ossimLambertConformalConicProjection") || + (proj_name == "ossimAlbersProjection") ) + { + //*** + // Lambert Conformal Conic: + // tags needed example from the geo tiff spec page: + // ModelTiepointTag = ( 80, 100, 0, 200000, 1500000, 0) + // ModelPixelScaleTag = (1000, 1000, 0) + // GeoKeyDirectoryTag: + // GTModelTypeGeoKey = 1 (ModelTypeProjected) + // GTRasterTypeGeoKey = 1 (RasterPixelIsArea) + // GeographicTypeGeoKey = 4267 (GCS_NAD27) + // ProjectedCSTypeGeoKey = 32767 (user-defined) + // ProjectionGeoKey = 32767 (user-defined) + // ProjLinearUnitsGeoKey = 9001 (Linear_Meter) + // ProjCoordTransGeoKey = 8 (CT_LambertConfConic_2SP) + // ProjStdParallel1GeoKey = 41.333 + // ProjStdParallel2GeoKey = 48.666 + // ProjCenterLongGeoKey =-120.0 + // ProjNatOriginLatGeoKey = 45.0 + // ProjFalseEastingGeoKey, = 200000.0 + // ProjFalseNorthingGeoKey, = 1500000.0 + // + // NOTE: Albers Same as Lambert with the exception of the + // ProjCoordTransGeoKey which is: CT_AlbersEqualArea. + //*** + + //*** + // The easting/northing is the distance from the origin plus the + // false easting/northing. In other words if line 0 is 5,000 + // meters from the origin and the false northing is 5,000 meters, + // then the northing would be 10,000. The same goes for the easting. + //*** + if (proj_name == "ossimLambertConformalConicProjection") + { + GTIFKeySet(gtif, + ProjCoordTransGeoKey, + TYPE_SHORT, + 1, + (uint16)CT_LambertConfConic_2SP ); + } + else // Albers + { + GTIFKeySet(gtif, + ProjCoordTransGeoKey, + TYPE_SHORT, + 1, + (uint16)CT_AlbersEqualArea); + } + + // Only set a pcs code if one is explicitly given in the map projection + if(pcs_code) + { + ossim_uint16 value = ossimString(pcs_code).toULong(); + if(value != 0) + { + GTIFKeySet(gtif, + ProjectedCSTypeGeoKey, + TYPE_SHORT, + 1, + value); + } + } + else + { + // User-Defined + GTIFKeySet(gtif, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, + KvUserDefined ); + } + + // User-Defined + GTIFKeySet(gtif, ProjectionGeoKey, TYPE_SHORT, 1, + KvUserDefined ); + + double phi1 = ossimString(stdParallel1).toDouble(); + + GTIFKeySet(gtif, + ProjStdParallel1GeoKey, + TYPE_DOUBLE, + 1, + phi1); // 1st parallel + + double phi2 = ossimString(stdParallel2).toDouble(); + + GTIFKeySet(gtif, + ProjStdParallel2GeoKey, + TYPE_DOUBLE, + 1, + phi2); // 2nd parallel + + double centerLon = ossimString(central_meridian).toDouble(); + + GTIFKeySet(gtif, + ProjCenterLongGeoKey, + TYPE_DOUBLE, + 1, + centerLon); // Longitude at the origin. + + double org = ossimString(origin).toDouble(); + + GTIFKeySet(gtif, + ProjNatOriginLatGeoKey, + TYPE_DOUBLE, + 1, + org); // Origin + + double fe = ossimString(false_easting).toDouble(); + + GTIFKeySet(gtif, + ProjFalseEastingGeoKey, + TYPE_DOUBLE, + 1, + fe); // False Easting + + double fn = ossimString(false_northing).toDouble(); + + GTIFKeySet(gtif, + ProjFalseNorthingGeoKey, + TYPE_DOUBLE, + 1, + fn); // False Northing + + } // End of Lambert. + else if (proj_name == "ossimTransMercatorProjection") + { + //*** + // Transverse Mercator ( no example in the geo tiff spec. + // Requires: + // - latitude/longitude of the origin + // - easting/northing of some tie point(line/sample 0,0) + // - false easting/northing + // - The scale factor. + //*** + + //*** + // The easting/northing is the distance from the origin plus the + // false easting/northing. In other words if line 0 is 5,000 + // meters from the origin and the false northing is 5,000 meters, + // then the northing would be 10,000. The same goes for the easting. + //*** + GTIFKeySet(gtif, + ProjCoordTransGeoKey, + TYPE_SHORT, + 1, + (uint16)CT_TransverseMercator); + + // Only set a pcs code if one is explicitly given in the map projection + if(pcs_code) + { + ossim_uint16 value = ossimString(pcs_code).toULong(); + if(value != 0) + { + GTIFKeySet(gtif, + ProjectedCSTypeGeoKey, + TYPE_SHORT, + 1, + value); + } + } + else + { + // User-Defined + GTIFKeySet(gtif, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, + KvUserDefined ); + } + + // User-Defined + GTIFKeySet(gtif, ProjectionGeoKey, TYPE_SHORT, 1, + KvUserDefined ); + + double clon = ossimString(central_meridian).toDouble(); + + GTIFKeySet(gtif, + ProjNatOriginLongGeoKey, + TYPE_DOUBLE, + 1, + clon); + + double olat = ossimString(origin).toDouble(); + + GTIFKeySet(gtif, + ProjNatOriginLatGeoKey, + TYPE_DOUBLE, + 1, + olat); + + double fe = ossimString(false_easting).toDouble(); + + GTIFKeySet(gtif, + ProjFalseEastingGeoKey, + TYPE_DOUBLE, + 1, + fe); + + double fn = ossimString(false_northing).toDouble(); + + GTIFKeySet(gtif, + ProjFalseNorthingGeoKey, + TYPE_DOUBLE, + 1, + fn); + + double scale = ossimString(scaleFactor).toDouble(); + + GTIFKeySet(gtif, + ProjScaleAtNatOriginGeoKey, + TYPE_DOUBLE, + 1, + scale); + } // End of TM + + + GTIFWriteKeys(gtif); // Write out geotiff tags. + GTIFFree(gtif); + + return true; +# endif +#endif // #ifdef OSSIM_HAS_GEOTIFF + + return true; +} + +bool ossimTiffWriter::writeFile() + +{ + static const char MODULE[] = "ossimTiffWriter::writeFile"; + + if (traceDebug()) CLOG << "Entered..." << std::endl; + + if(isLutEnabled()) + { + theNBandToIndexFilter = new ossimNBandToIndexFilter; + theNBandToIndexFilter->connectMyInputTo(0, theInputConnection->getInput()); + theNBandToIndexFilter->setLut(theColorLut); + theNBandToIndexFilter->initialize(); + theInputConnection->disconnect(); + theInputConnection->connectMyInputTo(0, theNBandToIndexFilter.get()); + theInputConnection->initialize(); + } + else + { + theNBandToIndexFilter = 0; + } + + if (traceDebug() && theInputConnection) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << "DEBUG:" + << "\nnull: " << theInputConnection->getNullPixelValue() + << "\nmin: " << theInputConnection->getMinPixelValue() + << "\nmax: " << theInputConnection->getMaxPixelValue() + << std::endl; + } + + if (isTiled()) + { + if ( (theInputConnection->getTileWidth() != + static_cast<ossim_uint32>(theOutputTileSize.x)) || + (theInputConnection->getTileHeight() != + static_cast<ossim_uint32>(theOutputTileSize.y)) ) + { + theInputConnection->setTileSize(theOutputTileSize); + } + } + + if(!theInputConnection->isMaster()) + { + theInputConnection->slaveProcessTiles(); + + if(theNBandToIndexFilter.valid()) + { + theInputConnection->connectMyInputTo(0, theNBandToIndexFilter->getInput()); + theNBandToIndexFilter = 0; + } + + return true; + } + + // this might be called from writeFile(projection infoamrtion) method + // we will check to see if the tiff is open. If not then call the open. + // + if(isOpen()) + { + close(); + } + + open(); + + if (!isOpen()) + { + if (traceDebug()) + { + CLOG << " ERROR: Could not open! Returning..." << std::endl; + } + + return false; + } + + if(!theInputConnection) + { + if (traceDebug()) + { + CLOG << " ERROR: No input connection! Returning..." << std::endl; + } + + return false; + } + + // First write the tiff tags. + if (writeTiffTags() == false) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " ERROR:" + << "\nError detected writing tiff tags. Returning..." << std::endl; + return false; + } + } + + // Write the geotiff tags. + if (theOutputGeotiffTagsFlag) + { + if(theViewController) // let this override + { // found in ossimImageWriter base + ossimMapProjection* proj = PTR_CAST(ossimMapProjection, + theViewController->getView()); + if(proj) + { + ossimMapProjectionInfo* projectionInfo + = new ossimMapProjectionInfo(proj, theAreaOfInterest); + + if (writeGeotiffTags(projectionInfo) == false) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " ERROR:" + << "\nError detected writing geotiff tags. Returning..." + << std::endl; + } + delete projectionInfo; + return false; + } + + delete projectionInfo; + } + } + else if(theProjectionInfo) + { + if (writeGeotiffTags(theProjectionInfo) == false) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " ERROR:" + << "\nError detected writing geotiff tags. Returning..." + << std::endl; + } + return false; + } + } + else + { + ossimKeywordlist kwl; + theInputConnection->getImageGeometry(kwl); + + ossimProjection* proj = ossimProjectionFactoryRegistry::instance()-> + createProjection(kwl); + ossimMapProjection* mapProj = PTR_CAST(ossimMapProjection, proj); + if(mapProj) + { + ossimMapProjectionInfo* projectionInfo + = new ossimMapProjectionInfo(mapProj, theAreaOfInterest); + + if (writeGeotiffTags(projectionInfo) == false) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " ERROR:" + << "\nError detected writing geotiff tags. Returning..." + << std::endl; + } + if(proj) + { + delete proj; + } + delete projectionInfo; + return false; + } + + delete projectionInfo; + + } + if(proj) + { + delete proj; + proj = NULL; + } + } + + } // End of "if (theOutputGeotiffTagsFlag)" + + // Write the file with the image data. + bool status = false; + if(theOutputImageType == "tiff_strip") + { + status = writeToStrips(); + } + else if(theOutputImageType == "tiff_strip_band_separate") + { + status = writeToStripsBandSep(); + } + else if((theOutputImageType == "tiff_tiled")|| + (ossimString::downcase(theOutputImageType) == "image/tiff")|| + (ossimString::downcase(theOutputImageType) == "image/tif")|| + (ossimString::downcase(theOutputImageType) == "image/gtif")|| + (ossimString::downcase(theOutputImageType) == "image/gtiff")) + { + status = writeToTiles(); + } + else if(theOutputImageType == "tiff_tiled_band_separate") + { + status = writeToTilesBandSep(); + } + else + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " ERROR:" + << "\nUnsupported output type: " << theOutputImageType + << std::endl; + } + } + + close(); + + if (traceDebug()) CLOG << " Exited..." << std::endl; + + if(theNBandToIndexFilter.valid()) + { + theInputConnection->connectMyInputTo(0, theNBandToIndexFilter->getInput()); + theNBandToIndexFilter = 0; + } + + return status; +} + +void ossimTiffWriter::setLut(const ossimNBandLutDataObject& lut) +{ + theColorLut = lut; +} + +bool ossimTiffWriter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimUnitTypeLut unitLut; + + // Set the pixel type. + ossimString pixelType; + getPixelTypeString(pixelType); + kwl.add(prefix, + ossimKeywordNames::PIXEL_TYPE_KW, + pixelType.c_str(), + true); + + kwl.add(prefix, + "output_geotiff_flag", + (int)theOutputGeotiffTagsFlag, + true); + + kwl.add(ossimString(prefix)+"projection.", + ossimKeywordNames::UNITS_KW, + unitLut.getEntryString(theProjectionUnits), + true); + + kwl.add(prefix, + TIFF_WRITER_OUTPUT_TILE_SIZE_X_KW, + theOutputTileSize.x, + true); + + kwl.add(prefix, + TIFF_WRITER_OUTPUT_TILE_SIZE_Y_KW, + theOutputTileSize.y, + true); + + kwl.add(prefix, + ossimKeywordNames::COMPRESSION_QUALITY_KW, + theJpegQuality, + true); + + kwl.add(prefix, + ossimKeywordNames::COMPRESSION_TYPE_KW, + theCompressionType, + true); + + kwl.add(prefix, + "color_lut_flag", + (ossim_uint32)theColorLutFlag, + true); + + if(theColorLutFlag) + { + if(theLutFilename != "") + { + kwl.add(prefix, + "lut_filename", + theLutFilename.c_str(), + true); + } + else + { + ossimString newPrefix = ossimString(prefix) + "lut."; + theColorLut.saveState(kwl, newPrefix.c_str()); + } + } + + + return ossimImageFileWriter::saveState(kwl, + prefix); +} + +bool ossimTiffWriter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char *value; + ossimUnitTypeLut unitLut; + theProjectionUnits = (ossimUnitType)unitLut.getEntryNumber(kwl, prefix, true); + + value = kwl.find(prefix, ossimKeywordNames::PIXEL_TYPE_KW); + + if(value) + { + if(ossimString(value).downcase().contains("area")) + { + thePixelType = OSSIM_PIXEL_IS_AREA; + } + else + { + thePixelType = OSSIM_PIXEL_IS_POINT; + } + } + + ossimIpt defaultTileSize; + ossimGetDefaultTileSize(defaultTileSize); + + value = kwl.find(prefix, + TIFF_WRITER_OUTPUT_TILE_SIZE_X_KW); + if(value) + { + theOutputTileSize.x = ossimString(value).toLong(); + if(theOutputTileSize.x<1) + { + theOutputTileSize.x = defaultTileSize.x; + } + } + + value = kwl.find(prefix, + TIFF_WRITER_OUTPUT_TILE_SIZE_Y_KW); + if(value) + { + theOutputTileSize.y = ossimString(value).toLong(); + if(theOutputTileSize.y<1) + { + theOutputTileSize.y = defaultTileSize.y; + } + } + + + value = kwl.find(prefix, ossimKeywordNames::COMPRESSION_TYPE_KW); + if(value) + { + theCompressionType = ossimString(value).downcase(); + } + else + { + theCompressionType = "none"; + } + + value = kwl.find(prefix, ossimKeywordNames::COMPRESSION_QUALITY_KW); + if(value) + { + setJpegQuality(ossimString(value).toLong()); + } + + value = kwl.find(prefix, ossimKeywordNames::PHOTOMETRIC_KW); + if(value) + { + thePhotoMetric = ossimString(value).downcase(); + } + + value = kwl.find(prefix, ossimKeywordNames::FILENAME_KW); + if(value) + { + setFilename(ossimFilename(value)); + } + + const char* flag = kwl.find(prefix, "output_geotiff_flag"); + const char* img_nad27_flag = kwl.find(prefix, "imagine_nad27_flag"); + + if(flag) + { + theOutputGeotiffTagsFlag = ossimString(flag).toBool(); + } + + if(img_nad27_flag) + { + theImagineNad27Flag = ossimString(img_nad27_flag).toBool(); + } + + ossimString newPrefix = ossimString(prefix) + "lut."; + + const char* colorLutFlag = kwl.find(prefix, "color_lut_flag"); + if(colorLutFlag) + { + theColorLutFlag = ossimString(colorLutFlag).toBool(); + } + else + { + theColorLutFlag = false; + } + theLutFilename = ossimFilename(kwl.find(prefix, "lut_filename")); + + theLutFilename = ossimFilename(theLutFilename.trim()); + if(theLutFilename != "") + { + theColorLut.open(theLutFilename); + } + else + { + theColorLut.loadState(kwl, newPrefix.c_str()); + } + + if(ossimImageFileWriter::loadState(kwl, + prefix)) + { + if((theOutputImageType!="tiff_tiled") && + (theOutputImageType!="tiff_tiled_band_separate") && + (theOutputImageType!="tiff_strip") && + (theOutputImageType!="tiff_strip_band_separate")&& + (theOutputImageType!="image/tiff")&& + (theOutputImageType!="image/tif")&& + (theOutputImageType!="image/gtif")&& + (theOutputImageType!="image/gtiff")) + { + + theOutputImageType = "tiff_tiled_band_separate";; + } + } + else + { + return false; + } + + return true; +} + +bool ossimTiffWriter::isTiled() const +{ + return ( theOutputImageType == "tiff_tiled" || + theOutputImageType == "image/tiff" || + theOutputImageType == "image/tif" || + theOutputImageType == "image/gtif" || + theOutputImageType == "image/gtiff" || + theOutputImageType == "tiff_tiled_band_separate" ); +} + +bool ossimTiffWriter::writeToTiles() +{ + static const char* const MODULE = "ossimTiffWriter::writeToTiles"; + + if (traceDebug()) CLOG << " Entered." << std::endl; + + // Start the sequence at the first tile. + theInputConnection->setToStartOfSequence(); + + ossimRefPtr<ossimImageData> tempTile = 0; + + if(theColorLutFlag) + { + tempTile = ossimImageDataFactory::instance()->create(this, 1, theInputConnection); + } + else + { + tempTile = ossimImageDataFactory::instance()->create(this, theInputConnection); + } + if(tempTile.valid()) + { + tempTile->initialize(); + } + ossim_uint32 tilesWide = theInputConnection->getNumberOfTilesHorizontal(); + ossim_uint32 tilesHigh = theInputConnection->getNumberOfTilesVertical(); + ossim_uint32 tileWidth = theInputConnection->getTileWidth(); + ossim_uint32 tileHeight = theInputConnection->getTileHeight(); + ossim_uint32 numberOfTiles = theInputConnection->getNumberOfTiles(); + + // Tile loop in the height direction. + ossim_uint32 tileNumber = 0; + vector<ossim_float64> minBands; + vector<ossim_float64> maxBands; + for(ossim_uint32 i = 0; i < tilesHigh; i++) + { + ossimIpt origin(0,0); + origin.y = i * tileHeight; + + // Tile loop in the sample (width) direction. + for(ossim_uint32 j = 0; j < tilesWide; j++) + { + origin.x = j * tileWidth; + + // Grab the tile. + ossimRefPtr<ossimImageData> id = theInputConnection->getNextTile(); + if (!id) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR:" + << "Error returned writing tiff tile: " << tileNumber + << "\nNULL Tile encountered" + << std::endl; + return false; + } + + ossimDataObjectStatus tileStatus = id->getDataObjectStatus(); + ossim_uint32 tileSizeInBytes = id->getSizeInBytes(); + if (tileStatus != OSSIM_FULL) + { + // Clear out the buffer since it won't be filled all the way. + tempTile->setImageRectangle(id->getImageRectangle()); + tempTile->makeBlank(); + } + + if ((tileStatus == OSSIM_PARTIAL || tileStatus == OSSIM_FULL)) + { + // Stuff the tile into the tileBuffer. + id->unloadTile(tempTile->getBuf(), + id->getImageRectangle(), + OSSIM_BIP); + tempTile->setDataObjectStatus(id->getDataObjectStatus()); + if(!theColorLutFlag) + { + id->computeMinMaxPix(minBands, maxBands); + } + } + + //*** + // Write the tile to disk. + //*** + ossim_uint32 bytesWritten = 0; + bytesWritten = TIFFWriteTile(theTif, + tempTile->getBuf(), + origin.x, + origin.y, + 0, // z + 0); // s + + if (bytesWritten != tileSizeInBytes) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " ERROR:" + << "Error returned writing tiff tile: " << i + << "\nExpected bytes written: " << tileSizeInBytes + << "\nBytes written: " << bytesWritten + << std::endl; + } + setErrorStatus(); + return false; + } + + ++tileNumber; + + } // End of tile loop in the sample (width) direction. + + double tile = tileNumber; + double numTiles = numberOfTiles; + setPercentComplete(tile / numTiles * 100); + + } // End of tile loop in the line (height) direction. + + if(!theColorLutFlag) + { + writeMinMaxTags(minBands, maxBands); + } + + if (traceDebug()) CLOG << " Exited." << std::endl; + + return true; +} + +bool ossimTiffWriter::writeToTilesBandSep() +{ + static const char* const MODULE = "ossimTiffWriter::writeToTilesBandSep"; + + if (traceDebug()) CLOG << " Entered." << std::endl; + + // Start the sequence at the first tile. + theInputConnection->setToStartOfSequence(); + + ossim_uint32 bands = theInputConnection->getNumberOfOutputBands(); + ossim_uint32 tilesWide = theInputConnection->getNumberOfTilesHorizontal(); + ossim_uint32 tilesHigh = theInputConnection->getNumberOfTilesVertical(); + ossim_uint32 tileWidth = theInputConnection->getTileWidth(); + ossim_uint32 tileHeight = theInputConnection->getTileHeight(); + ossim_uint32 numberOfTiles = theInputConnection->getNumberOfTiles(); + +#if 0 + if(traceDebug()) + { + ossimIrect boundingRect = theInputConnection->getBoundingRect(); + ossimNotify(ossimNotifyLevel_NOTICE) + << "Bounding rect = " << boundingRect + << "\nBands = " << bands + << "\ntilesWide = " << tilesWide + << "\ntilesHigh = " << tilesHigh + << "\ntileWidth = " << tileWidth + << "\ntileHeight = " << tileHeight << std::endl; + } +#endif + + ossim_uint32 tileNumber = 0; + vector<ossim_float64> minBands; + vector<ossim_float64> maxBands; + for(ossim_uint32 i = 0; ((i < tilesHigh)&&!needsAborting()); ++i) + { + ossimIpt origin; + origin.y = i * tileHeight; + + //*** + // Tile loop in the sample (width) direction. + //*** + for(ossim_uint32 j = 0; ((j < tilesWide)&!needsAborting()); ++j) + { + origin.x = j * tileWidth; + + ossimRefPtr<ossimImageData> id = theInputConnection->getNextTile(); + if(!id) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR:" + << "Error returned writing tiff tile: " << i + << "\nNULL Tile encountered" + << std::endl; + return false; + } + ossim_int32 tileSizeInBytes = id->getSizePerBandInBytes(); + + if(!theColorLutFlag) + { + id->computeMinMaxPix(minBands, maxBands); + } + + //*** + // Band loop. + //*** + for (ossim_uint32 band=0; ((band<bands)&&(!needsAborting())); ++band) + { + // Grab a pointer to the tile for the band. + tdata_t* data = (tdata_t*)id->getBuf(band); + // Write the tile. + tsize_t bytesWritten = 0; + bytesWritten = TIFFWriteTile(theTif, + data, + (ossim_uint32)origin.x, + (ossim_uint32)origin.y, + (ossim_uint32)0, // z + (tsample_t)band); // sample + + if (bytesWritten != tileSizeInBytes) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " ERROR:" + << "Error returned writing tiff tile: " << i + << "\nExpected bytes written: " << tileSizeInBytes + << "\nBytes written: " << bytesWritten + << std::endl; + } + setErrorStatus(); + return false; + } + + } // End of band loop. + + ++tileNumber; + + } // End of tile loop in the sample (width) direction. + + double tile = tileNumber; + double numTiles = numberOfTiles; + setPercentComplete(tile / numTiles * 100); + if(needsAborting()) + { + setPercentComplete(100); + } + + } // End of tile loop in the line (height) direction. + + if(!theColorLutFlag) + { + writeMinMaxTags(minBands, maxBands); + } + + if (traceDebug()) CLOG << " Exited." << std::endl; + + return true; +} + +bool ossimTiffWriter::writeToStrips() +{ + static const char* const MODULE = "ossimTiffWriter::writeToStrips"; + + if (traceDebug()) CLOG << " Entered." << std::endl; + + // Start the sequence at the first tile. + theInputConnection->setToStartOfSequence(); + + ossim_uint32 bands = theInputConnection->getNumberOfOutputBands(); + ossim_uint32 tilesWide = theInputConnection->getNumberOfTilesHorizontal(); + ossim_uint32 tilesHigh = theInputConnection->getNumberOfTilesVertical(); + ossim_uint32 tileHeight = theInputConnection->getTileHeight(); + ossim_uint32 numberOfTiles = theInputConnection->getNumberOfTiles(); + ossim_uint32 width = theAreaOfInterest.width(); + ossim_uint32 bytesInLine = + ossimGetScalarSizeInBytes(theInputConnection->getOutputScalarType()) * + width * bands; + + //*** + // Buffer to hold one line x tileHeight + //*** + ossim_uint32 bufferSizeInBytes = bytesInLine * tileHeight; + unsigned char* buffer = new unsigned char[bufferSizeInBytes]; + + int tileNumber = 0; + vector<ossim_float64> minBands; + vector<ossim_float64> maxBands; + for(ossim_uint32 i = 0; ((i < tilesHigh)&&(!needsAborting())); ++i) + { + // Clear the buffer. + memset(buffer, 0, bufferSizeInBytes); + + // Set the buffer rectangle. + ossimIrect bufferRect(theAreaOfInterest.ul().x, + theAreaOfInterest.ul().y + i * tileHeight, + theAreaOfInterest.ul().x + width - 1, + theAreaOfInterest.ul().y + i * tileHeight + + tileHeight - 1); + + // Tile loop in the sample (width) direction. + for(ossim_uint32 j = 0; ((j < tilesWide)&&(!needsAborting())); ++j) + { + // Get the tile and copy it to the buffer. + ossimRefPtr<ossimImageData> id = theInputConnection->getNextTile(); + if (!id) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR:" + << "Error returned writing tiff tile: " << tileNumber + << "\nNULL Tile encountered" + << std::endl; + delete [] buffer; + return false; + } + id->unloadTile(buffer, bufferRect, OSSIM_BIP); + if(!theColorLutFlag) + { + id->computeMinMaxPix(minBands, maxBands); + } + ++tileNumber; + } + + // Get the number of lines to write from the buffer. + ossim_uint32 linesToWrite = min(tileHeight, static_cast<ossim_uint32>(theAreaOfInterest.lr().y - bufferRect.ul().y + 1)); + + // Write the buffer out to disk. + ossim_uint32 row = static_cast<ossim_uint32>(bufferRect.ul().y - + theAreaOfInterest.ul().y); + ossim_uint8* buf = buffer; + for (ossim_uint32 ii=0; ((ii<linesToWrite)&&(!needsAborting())); ++ii) + { + ossim_int32 status = TIFFWriteScanline(theTif, + buf, + row, + 0); + if (status == -1) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR:" + << "Error returned writing tiff scanline: " << row + << std::endl; + setErrorStatus(); + delete [] buffer; + return false; + } + + ++row; // Increment the line number. + buf += bytesInLine; + + } // End of loop to write lines from buffer to tiff file. + + double tile = tileNumber; + double numTiles = numberOfTiles; + setPercentComplete(tile / numTiles * 100); + if(needsAborting()) + { + setPercentComplete(100); + } + + } // End of loop in the line (height) direction. + + if(!theColorLutFlag) + { + writeMinMaxTags(minBands, maxBands); + } + + // Free the memory. + delete [] buffer; + + if (traceDebug()) CLOG << " Exited." << std::endl; + + return true; +} + +bool ossimTiffWriter::writeToStripsBandSep() +{ + static const char* const MODULE = "ossimTiffWriter::writeToStripsBandSep"; + + if (traceDebug()) CLOG << " Entered." << std::endl; + + // Start the sequence at the first tile. + theInputConnection->setToStartOfSequence(); + + ossim_uint32 bands = theInputConnection->getNumberOfOutputBands(); + ossim_uint32 tilesWide = theInputConnection->getNumberOfTilesHorizontal(); + ossim_uint32 tilesHigh = theInputConnection->getNumberOfTilesVertical(); + ossim_uint32 tileHeight = theInputConnection->getTileHeight(); + ossim_uint32 numberOfTiles = theInputConnection->getNumberOfTiles(); + ossim_uint32 width = theAreaOfInterest.width(); + ossim_uint32 bytesInLine = + ossimGetScalarSizeInBytes(theInputConnection->getOutputScalarType()) * + width; + + //*** + // Buffer to hold one line x tileHeight + //*** + ossim_uint32 bufferSizeInBytes = bytesInLine * tileHeight * bands; + + unsigned char* buffer = new unsigned char[bufferSizeInBytes]; + + // Tile loop in height direction. + ossim_uint32 tileNumber = 0; + vector<ossim_float64> minBands; + vector<ossim_float64> maxBands; + for(ossim_uint32 i = 0; ((i < tilesHigh)&&(!needsAborting())); ++i) + { + // Clear the buffer. + memset(buffer, 0, bufferSizeInBytes); + + // Set the buffer rectangle. + ossimIrect bufferRect(theAreaOfInterest.ul().x, + theAreaOfInterest.ul().y + i * tileHeight, + theAreaOfInterest.ul().x + width - 1, + theAreaOfInterest.ul().y + i * tileHeight + + tileHeight - 1); + + // Tile loop in the sample (width) direction. + for(ossim_uint32 j = 0; ((j < tilesWide)&&(!needsAborting())); ++j) + { + // Get the tile and copy it to the buffer. + ossimRefPtr<ossimImageData> id = theInputConnection->getNextTile(); + if (!id) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR:" + << "Error returned writing tiff tile: " << tileNumber + << "\nNULL Tile encountered" + << std::endl; + delete [] buffer; + return false; + } + id->unloadTile(buffer, bufferRect, OSSIM_BIL); + if(!theColorLutFlag) + { + id->computeMinMaxPix(minBands, maxBands); + } + ++tileNumber; + } + + // Get the number of lines to write from the buffer. + ossim_uint32 linesToWrite = min(tileHeight, static_cast<ossim_uint32>(theAreaOfInterest.lr().y - bufferRect.ul().y + 1)); + + // Write the buffer out to disk. + ossim_uint32 row = static_cast<ossim_uint32>(bufferRect.ul().y - + theAreaOfInterest.ul().y); + ossim_uint8* buf = buffer; + for (ossim_uint32 ii=0; ((ii<linesToWrite)&&(!needsAborting())); ++ii) + { + for (ossim_uint32 band =0; ((band<bands)&&(!needsAborting())); ++band) + { + ossim_int32 status = TIFFWriteScanline(theTif, + buf, + row, + band); + if (status == -1) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR:" + << "Error returned writing tiff scanline: " << row + << std::endl; + delete [] buffer; + return false; + } + buf += bytesInLine; + } + + ++row; // Increment the line number. + + } // End of loop to write lines from buffer to tiff file. + + double tile = tileNumber; + double numTiles = numberOfTiles; + setPercentComplete(tile / numTiles * 100); + if(needsAborting()) + { + setPercentComplete(100); + } + } // End of loop in the line (height) direction. + + if(!theColorLutFlag) + { + writeMinMaxTags(minBands, maxBands); + } + + // Free the memory. + delete [] buffer; + + if (traceDebug()) CLOG << " Exited." << std::endl; + + return true; +} + +void ossimTiffWriter::setTileSize(const ossimIpt& tileSize) +{ + if (tileSize.x % 32 || tileSize.y % 32) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimTiffWriter::changeTileSize ERROR:" + << "\nTile size must be a multiple of 32!" + << "\nSize remains: " << theOutputTileSize + << std::endl; + } + return; + } + + theOutputTileSize = tileSize; +} + +void ossimTiffWriter::writeMinMaxTags(const vector<ossim_float64>& minBand, + const vector<ossim_float64>& maxBand) +{ + if(minBand.size() && maxBand.size()) + { + ossim_float64 minValue = + *std::min_element(minBand.begin(), minBand.end()); + ossim_float64 maxValue = + *std::max_element(maxBand.begin(), maxBand.end()); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimTiffWriter::writeMinMaxTags DEBUG:" + << "\nminValue: " << minValue + << "\nmaxValue: " << maxValue + << std::endl; + } + + switch( theInputConnection->getOutputScalarType() ) + { + case OSSIM_USHORT11: + { + TIFFSetField( theTif, TIFFTAG_MINSAMPLEVALUE, + static_cast<ossim_sint16>(0) ); + TIFFSetField( theTif, TIFFTAG_MAXSAMPLEVALUE, + static_cast<ossim_sint16>(2047) ); + break; + } + case OSSIM_UINT8: + case OSSIM_UINT16: + { + TIFFSetField( theTif, TIFFTAG_MINSAMPLEVALUE, + static_cast<ossim_sint16>(minValue) ); + TIFFSetField( theTif, TIFFTAG_MAXSAMPLEVALUE, + static_cast<ossim_sint16>(maxValue) ); + break; + } + + case OSSIM_SINT16: + case OSSIM_UINT32: + case OSSIM_FLOAT32: + case OSSIM_FLOAT64: + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_NORMALIZED_DOUBLE: + { + TIFFSetField( theTif, TIFFTAG_SMINSAMPLEVALUE, + static_cast<ossim_float32>(minValue) ); + TIFFSetField( theTif, TIFFTAG_SMAXSAMPLEVALUE, + static_cast<ossim_float32>(maxValue) ); + break; + } + default: + { + break; + } + } + } +} + +void ossimTiffWriter::setProperty(ossimRefPtr<ossimProperty> property) +{ + if(!property) + { + return; + } + + if(property->getName() == ossimKeywordNames::COMPRESSION_QUALITY_KW) + { + ossimNumericProperty* numericProperty = PTR_CAST(ossimNumericProperty, + property.get()); + if (numericProperty) + { + setJpegQuality( numericProperty->asInt32() ); + } + } + else if (property->getName() == ossimKeywordNames::COMPRESSION_TYPE_KW) + { + ossimStringProperty* stringProperty = PTR_CAST(ossimStringProperty, + property.get()); + if (stringProperty) + { + ossimString s; + stringProperty->valueToString(s); + setCompressionType(s); + } + } + else if(property->getName() == ossimKeywordNames::PIXEL_TYPE_KW) + { + ossimStringProperty* stringProperty = PTR_CAST(ossimStringProperty, + property.get()); + if (stringProperty) + { + ossimString s; + stringProperty->valueToString(s); + setPixelType(s); + } + } + else if(property->getName() == "lut_file") + { + theLutFilename = ossimFilename(property->valueToString()); + theColorLut.open(theLutFilename); + } + else if(property->getName() == "color_lut_flag") + { + theColorLutFlag = property->valueToString().toBool(); + } + else + { + ossimImageFileWriter::setProperty(property); + } +} + +ossimRefPtr<ossimProperty> ossimTiffWriter::getProperty(const ossimString& name)const +{ + if(name == "Filename") + { + ossimRefPtr<ossimProperty> tempProp = ossimImageFileWriter::getProperty(name); + if(tempProp.valid()) + { + ossimFilenameProperty* filenameProp = PTR_CAST(ossimFilenameProperty, + tempProp.get()); + + if(filenameProp) + { + filenameProp->addFilter("*.tif"); + } + + return tempProp; + } + } + else if (name == ossimKeywordNames::COMPRESSION_QUALITY_KW) + { + ossimNumericProperty* numericProp = + new ossimNumericProperty(name, + ossimString::toString(theJpegQuality), + 1.0, + 100.0); + numericProp-> + setNumericType(ossimNumericProperty::ossimNumericPropertyType_INT); + return numericProp; + } + else if (name == ossimKeywordNames::COMPRESSION_TYPE_KW) + { + ossimStringProperty* stringProp = + new ossimStringProperty(name, + getCompressionType(), + false); // editable flag + stringProp->addConstraint(ossimString("none")); + stringProp->addConstraint(ossimString("jpeg")); + stringProp->addConstraint(ossimString("packbits")); + stringProp->addConstraint(ossimString("deflate")); + stringProp->addConstraint(ossimString("zip")); + return stringProp; + } + else if (name == ossimKeywordNames::PIXEL_TYPE_KW) + { + ossimString value; + getPixelTypeString(value); + ossimStringProperty* stringProp = + new ossimStringProperty(name, + value, + false); // editable flag + stringProp->addConstraint(ossimString("point")); + stringProp->addConstraint(ossimString("area")); + return stringProp; + } + else if (name == "lut_file") + { + ossimFilenameProperty* property = new ossimFilenameProperty(name, theLutFilename); + property->setIoType(ossimFilenameProperty::ossimFilenamePropertyIoType_INPUT); + + return property; + } + else if (name == "color_lut_flag") + { + ossimBooleanProperty* boolProperty = new ossimBooleanProperty(name, + theColorLutFlag); + return boolProperty; + } + return ossimImageFileWriter::getProperty(name); +} + +void ossimTiffWriter::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + propertyNames.push_back(ossimString( + ossimKeywordNames::COMPRESSION_QUALITY_KW)); + propertyNames.push_back(ossimString( + ossimKeywordNames::COMPRESSION_TYPE_KW)); + propertyNames.push_back(ossimString(ossimKeywordNames::PIXEL_TYPE_KW)); + propertyNames.push_back(ossimString("lut_file")); + propertyNames.push_back(ossimString("color_lut_flag")); + + ossimImageFileWriter::getPropertyNames(propertyNames); +} + +bool ossimTiffWriter::isOpen()const +{ + return (theTif!=NULL); +} + +bool ossimTiffWriter::open() +{ + if(theTif) + { + closeTiff(); + } + return openTiff(); +} + +void ossimTiffWriter::close() +{ + closeTiff(); +} + +void ossimTiffWriter::setJpegQuality(ossim_int32 quality) +{ + // Range 1 to 100 with 100 being best. + if (quality > 0 && quality < 101) + { + theJpegQuality = quality; + } + else + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimTiffWriter::setJpegQuality DEBUG:" + << "\nquality out of range: " << quality + << "\nquality has been set to default: " + << DEFAULT_JPEG_QUALITY + << "\nvalid range: 1 to 100 with 100 being best." + << std::endl; + } + + theJpegQuality = DEFAULT_JPEG_QUALITY; + } +} + +ossim_int32 ossimTiffWriter::getJpegQuality()const +{ + + return theJpegQuality; +} + +void ossimTiffWriter::setCompressionType(const ossimString& type) +{ + theCompressionType = type; +} + +ossimString ossimTiffWriter::getCompressionType()const +{ + return theCompressionType; +} + +bool ossimTiffWriter::getGeotiffFlag()const +{ + return theOutputGeotiffTagsFlag; +} + +void ossimTiffWriter::setGeotiffFlag(bool flag) +{ + theOutputGeotiffTagsFlag = flag; +} + +ossimIpt ossimTiffWriter::getOutputTileSize()const +{ + return theOutputTileSize; +} + +ossim_int32 ossimTiffWriter::setProjectionInfo(const ossimMapProjectionInfo& proj) +{ + if(theProjectionInfo) + { + delete theProjectionInfo; + } + theProjectionInfo = new ossimMapProjectionInfo(proj); + + return ossimErrorCodes::OSSIM_OK; +} + +void ossimTiffWriter::setPixelType(ossimPixelType type) +{ + thePixelType = type; +} + +void ossimTiffWriter::setPixelType(const ossimString& type) +{ + ossimString s = type; + s.downcase(); + if (s == "point") + { + setPixelType(OSSIM_PIXEL_IS_POINT); + } + else if (s == "area") + { + setPixelType(OSSIM_PIXEL_IS_AREA); + } +} + +ossimPixelType ossimTiffWriter::getPixelType() const +{ + return thePixelType; +} + +void ossimTiffWriter::getPixelTypeString(ossimString& type) const +{ + if (thePixelType == OSSIM_PIXEL_IS_POINT) + { + type = "point"; + } + else + { + type = "area"; + } +} + +void ossimTiffWriter::getImageTypeList(std::vector<ossimString>& imageTypeList)const +{ + imageTypeList.push_back(ossimString("tiff_strip")); + imageTypeList.push_back(ossimString("tiff_strip_band_separate")); + imageTypeList.push_back(ossimString("tiff_tiled")); + imageTypeList.push_back(ossimString("tiff_tiled_band_separate")); +} + +bool ossimTiffWriter::hasImageType(const ossimString& imageType) const +{ + // check for non image type list types + // We will support mime type + // + if((imageType == "image/tiff")|| + (imageType == "image/gtiff")|| + (imageType == "image/tif")|| + (imageType == "image/gtif")) + { + return true; + } + + return ossimImageFileWriter::hasImageType(imageType); +} + +bool ossimTiffWriter::isLutEnabled()const +{ + return (theColorLutFlag); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimTiffWriter.h b/Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimTiffWriter.h new file mode 100644 index 0000000000..9dc030a1df --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/tiff/ossimTiffWriter.h @@ -0,0 +1,257 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: Frank Warmerdam (warmerda@home.com) +// +// Description: +// +// Contains class declaration for TiffWriter. +// +//******************************************************************* +// $Id: ossimTiffWriter.h,v 1.49 2006/01/06 16:46:46 dburken Exp $ +#ifndef ossimTiffWriter_HEADER +#define ossimTiffWriter_HEADER + +#include <tiffio.h> +#include <imaging/formats/ossimImageFileWriter.h> +#include <base/data_types/ossimKeywordlist.h> +#include <projections/map_projections/ossimMapProjectionInfo.h> +#include <base/common/ossimNBandLutDataObject.h> +#include <imaging/tile_sources/ossimNBandToIndexFilter.h> + +class ossimMapProjectionInfo; + +class OSSIMDLLEXPORT ossimTiffWriter : public ossimImageFileWriter +{ +public: + + ossimTiffWriter(); + + virtual ~ossimTiffWriter(); + + enum UnitType + { + LINEAR_METER = 9001, + LINEAR_FOOT_US_SURVEY = 9003, + ANGULAR_DEGREES = 9102 + }; + + enum + { + USER_DEFINED = 32767 + }; + + /** + * void getImageTypeList(std::vector<ossimString>& imageTypeList)const + * + * Appends this writer image types to list "imageTypeList". + * + * This writer has the following types: + * tiff_strip + * tiff_strip_band_separate + * tiff_tiled + * tiff_tiled_band_separate + * + * @param imageTypeList stl::vector<ossimString> list to append to. + */ + virtual void getImageTypeList(std::vector<ossimString>& imageTypeList)const; + + virtual bool isOpen()const; + virtual bool open(); + virtual void close(); + + /** + * Ranges from 1 to 100 with 100 being the best. This value is only used + * if the compression type is set to jpeg. (default = 75) + * + * @param quality Value to set theJpegQuality to. + * + * @note If quality is out of range it will be set to DEFAULT_JPEG_QUALITY. + */ + virtual void setJpegQuality(ossim_int32 quality); + + /** + * @return theJpegQuality + */ + virtual ossim_int32 getJpegQuality()const; + + /** + * compression type can be JPEG, PACKBITS, or ZIP/DEFLATE + */ + virtual void setCompressionType(const ossimString& type); + + virtual ossimString getCompressionType()const; + + virtual bool getGeotiffFlag()const; + + virtual void setGeotiffFlag(bool flag); + + virtual void setTileSize(const ossimIpt& tileSize); + + virtual ossimIpt getOutputTileSize()const; + + virtual ossim_int32 setProjectionInfo(const ossimMapProjectionInfo& proj); + + void setLut(const ossimNBandLutDataObject& lut); + + /** + * saves the state of the object. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * Will set the property whose name matches the argument + * "property->getName()". + * + * @param property Object containing property to set. + */ + virtual void setProperty(ossimRefPtr<ossimProperty> property); + + /** + * @param name Name of property to return. + * + * @returns A pointer to a property object which matches "name". Returns + * NULL if no match is found. + */ + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + + /** + * Pushes this's names onto the list of property names. + * + * @param propertyNames array to add this's property names to. + */ + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + + /** + * This sets the tiff geotiff key: GTRasterTypeGeoKey + * If "point" the coordinate tie points are relative to the center of the + * pixel. If "area" the coordinate tie points are relative to the upper + * left corner of the pixel. + * + * Default in this writer is: OSSIM_PIXEL_IS_POINT + * + * @param type + * OSSIM_PIXEL_IS_POINT = center of pixel + * OSSIM_PIXEL_IS_AREA = upper left corner of pixel + */ + virtual void setPixelType(ossimPixelType type); + + /** + * This sets the tiff geotiff key: GTRasterTypeGeoKey + * If "point" the coordinate tie points are relative to the center of the + * pixel. If "area" the coordinate tie points are relative to the upper + * left corner of the pixel. + * + * Default in this writer is: OSSIM_PIXEL_IS_POINT + * + * @param type + * "point" = center of pixel + * "area" = upper left corner of pixel + * + * @note If the downcased "type" is not equal to "point" or "area" pixel + * type will remain unchanged. + */ + virtual void setPixelType(const ossimString& type); + + /** + * @return The pixel type as either OSSIM_PIXEL_IS_POINT or + * OSSIM_PIXEL_IS_AREA. + */ + virtual ossimPixelType getPixelType() const; + + /** + * @param type ossimString to initialize which will either be "point" or + * "area". + */ + virtual void getPixelTypeString(ossimString& type) const; + bool hasImageType(const ossimString& imageType) const; + +protected: + + virtual bool writeFile(); + + /** + * @return true on success, false on error. + */ + bool openTiff(); + + /** + * @return true on success, false on error. + */ + bool closeTiff(); + + /** + * Writes image data to a tiled tiff format. + * @return true on success, false on error. + */ + bool writeToTiles(); + + /** + * Writes image data to a tiled tiff band separate format. + * @return true on success, false on error. + */ + bool writeToTilesBandSep(); + + /** + * Writes image data to a strip tiff format. + * @return true on success, false on error. + */ + bool writeToStrips(); + + /** + * Writes image data to a strip tiff band separate format. + * @return true on success, false on error. + */ + bool writeToStripsBandSep(); + + /** + * Writes tiff tags from ossimMapProjectionInfo to tiff file. + * @return true on success, false on error. + */ + bool writeTiffTags(); + + /** + * Writes geotiff tags from ossimMapProjectionInfo to tiff file. + * @return true on success, false on error. + */ + bool writeGeotiffTags(ossimMapProjectionInfo* projectionInfo); + + /** + * @return true if the output type is tiled, false if not. + */ + bool isTiled() const; + + void writeMinMaxTags(const vector<ossim_float64>& minBand, + const vector<ossim_float64>& maxBand); + + bool isLutEnabled()const; + + TIFF* theTif; + ossimPixelType thePixelType; + ossimUnitType theProjectionUnits; + ossimString theCompressionType; + ossimString thePhotoMetric; + long theJpegQuality; + bool theOutputGeotiffTagsFlag; + bool theImagineNad27Flag; + bool theColorLutFlag; + ossimMapProjectionInfo* theProjectionInfo; + ossimIpt theOutputTileSize; + ossimNBandLutDataObject theColorLut; + ossimFilename theLutFilename; + mutable ossimRefPtr<ossimNBandToIndexFilter> theNBandToIndexFilter; +TYPE_DATA +}; + +#endif /* End of "#ifndef ossimTiffWriter_HEADER" */ diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/usgs_dem/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/formats/usgs_dem/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/usgs_dem/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/usgs_dem/ossimUsgsDemTileSource.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/usgs_dem/ossimUsgsDemTileSource.cpp new file mode 100644 index 0000000000..c8915b0e35 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/usgs_dem/ossimUsgsDemTileSource.cpp @@ -0,0 +1,648 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// License: See top level LICENSE.txt. +// +// Author: David Burken +// +// Description: +// +// Contains class declaration for ossimUsgsDemTileSource. +// +//******************************************************************** +// $Id: ossimUsgsDemTileSource.cpp,v 1.26 2006/01/10 16:19:38 dburken Exp $ + +#include <iostream> +#include <fstream> + +#include <imaging/formats/usgs_dem/ossimUsgsDemTileSource.h> +#include <base/common/ossimConstants.h> +#include <base/common/ossimCommon.h> +#include <base/common/ossimKeywordNames.h> +#include <base/common/ossimTrace.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ellipse/ossimEllipsoid.h> +#include <base/data_types/datum/ossimDatum.h> +#include <base/misc/lookup_tables/ossimScalarTypeLut.h> +#include <projections/map_projections/ossimMapProjection.h> +#include <projections/map_projections/ossimEquDistCylProjection.h> +#include <imaging/formats/tiff/ossimTiffTileSource.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <imaging/ossimImageData.h> +#include <imaging/ossimS16ImageData.h> +#include <support_data/usgs_dem/ossimDemHeader.h> +#include <support_data/usgs_dem/ossimDemProfile.h> +#include <support_data/usgs_dem/ossimDemGrid.h> + + +RTTI_DEF1(ossimUsgsDemTileSource, "ossimUsgsDemTileSource", ossimImageHandler) + +// Static trace for debugging +static ossimTrace traceDebug("ossimUsgsDemTileSource:debug"); + +static const char DEM_TYPE_KW[] = "dem_type"; +static const char USGS_DEM_KW[] = "usgs_dem"; + + +ossimUsgsDemTileSource::ossimUsgsDemTileSource() + : + ossimImageHandler(), + theDem(NULL), + theTile(NULL), + theNullValue(0.0), + theMinHeight(0.0), + theMaxHeight(0.0), + theFeetFlag(false), + theIsDemFlag(false), + theScalarType(OSSIM_SINT16) +{ + // Construction not complete. Users should call "open" method. +} + +ossimUsgsDemTileSource::~ossimUsgsDemTileSource() +{ + if (theDem) + { + delete theDem; + theDem = NULL; + } + theTile = NULL; +} + +ossimRefPtr<ossimImageData> ossimUsgsDemTileSource::getTile( + const ossimIrect& tile_rect, ossim_uint32 resLevel) +{ + // This tile source bypassed, or invalid res level, return a blank tile. + if (!isOpen() || !isSourceEnabled() || !isValidRLevel(resLevel)) + { + return ossimRefPtr<ossimImageData>(); + } + + if (theOverview) + { + if (theOverview->hasR0() || resLevel) + { + ossimRefPtr<ossimImageData> temp = theOverview->getTile(tile_rect, + resLevel); + if(temp.valid() && temp->getBuf()) + { + temp->setMinPix(theTile->getMinPix(), theTile->getNumberOfBands()); + temp->setMaxPix(theTile->getMaxPix(), theTile->getNumberOfBands()); + temp->setNullPix(theTile->getNullPix(), theTile->getNumberOfBands()); + } + else + { + return ossimRefPtr<ossimImageData>(); + } + return temp; + } + } + + if (!theTile.valid()) + { + return theTile; + } + + theTile->setImageRectangle(tile_rect); + + ossimIrect image_rect = getImageRectangle(resLevel); + + //*** + // See if any point of the requested tile is in the image. + //*** + if ( tile_rect.intersects(image_rect) ) + { + ossimIrect clip_rect = tile_rect.clipToRect(image_rect); + + if ( !tile_rect.completely_within(clip_rect) ) + { + // Start with a blank tile. + theTile->makeBlank(); + } + + // Load the tile buffer with data from the dem cell. + bool status; + if (theScalarType == OSSIM_FLOAT32) + { + status = fillBuffer(ossim_float32(0.0), tile_rect, clip_rect); + } + else + { + status = fillBuffer(ossim_sint16(0), tile_rect, clip_rect); + + } + if (status == true) + { + theTile->validate(); + return theTile; + } + else + { + return ossimRefPtr<ossimImageData>(); + } + + } // End of if ( tile_rect.intersects(image_rect) ) + + // No part of requested tile within the image rectangle. + return ossimRefPtr<ossimImageData>(); + +} + +//******************************************************************* +// Private Method: +//******************************************************************* +template <class T> +bool ossimUsgsDemTileSource::fillBuffer(T, + const ossimIrect& tile_rect, + const ossimIrect& clip_rect) +{ + const uint32 TILE_WIDTH = theTile->getWidth(); + + T* d = static_cast<T*>(theTile->getBuf()); + + ossim_float32 spatialResZ = theDem->getHeader().getSpatialResZ(); + if (spatialResZ == 0.0) spatialResZ = 1.0; + + // Compute the starting offset. + uint32 offset = (clip_rect.ul().y - tile_rect.ul().y) * TILE_WIDTH + + clip_rect.ul().x - tile_rect.ul().x; + + for (int32 line = clip_rect.ul().y; line <= clip_rect.lr().y; ++line) + { + // Loop in the longitude or sample direction. + int samp_offset = 0; + for (int32 samp = clip_rect.ul().x; samp <= clip_rect.lr().x; ++samp) + { + ossim_float32 p = theDem->getElevation(samp, line); + if (p != theNullValue) + { + p *= spatialResZ; + if (theFeetFlag) p = p * MTRS_PER_FT; + } + d[offset + samp_offset] = static_cast<T>(p); + ++samp_offset; + } + offset += TILE_WIDTH; + } + + return true; +} + +ossimIrect +ossimUsgsDemTileSource::getImageRectangle(ossim_uint32 reduced_res_level) const +{ + return ossimIrect(0, + 0, + getNumberOfSamples(reduced_res_level) - 1, + getNumberOfLines(reduced_res_level) - 1); +} + +bool ossimUsgsDemTileSource::open() +{ + static const char MODULE[] = "ossimUsgsDemTileSource::open"; + + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nAttempting to parse file: " << theImageFile.c_str() + << std::endl; + } + + if (!theImageFile.exists()) // See if file exists. + { + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nFile " << theImageFile.c_str() << " does not exist!" + << std::endl; + } + return false; + } + + //--- + // Open checks: + // 1) Check extension for .dem + // + // 2) Look for file.omd (ossim meta data) file containing keyword + // "dem_type" with value of "usgs_dem". + // + // 3) Look for file.kwl (keyword list) file containing keyword + // "dem_type" with value of "usgs_dem". + // + // NOTE: + // There is a keyword list template stored in the templates directory: + // "ossim/etc/templates/usgs_dem_template.kwl" + //--- + ossimString ext = theImageFile.ext(); + ext.downcase(); + if ( (ext == "kwl") || (ext == "omd") ) + { + // Don't allow keyword list to be fed to open. Only image files. + return false; + } + + if (ext == "dem") + { + theIsDemFlag = true; + } + + // Look for filename.omd + ossimFilename kwl_file = theImageFile; + kwl_file.setExtension("omd"); + if (kwl_file.exists()) // See if file exists. + { + ossimKeywordlist kwl(kwl_file); + if (kwl.getErrorStatus() == ossimErrorCodes::OSSIM_OK) + { + const char* lookup; + + if (!theIsDemFlag) + { + const char* lookup = kwl.find(DEM_TYPE_KW); + if (lookup) + { + ossimString s = lookup; + s.downcase(); + if (s == USGS_DEM_KW) + { + theIsDemFlag = true; + } + } + } + + //--- + // Look for scalar type override. + // + // Note: We only allow float or signed 16 bit. + //--- + lookup = kwl.find(ossimKeywordNames::SCALAR_TYPE_KW); + if (lookup) + { + ossimScalarType st = + static_cast<ossimScalarType>(ossimScalarTypeLut::instance()-> + getEntryNumber(lookup)); + if ( (st == OSSIM_FLOAT32) || (st == OSSIM_SINT16)) + { + theScalarType = st; + } + else + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimUsgsDemTileSource::loadState WARNING:" + << "\nInvalid scalar type: " + << ossimScalarTypeLut::instance()-> + getEntryString(st) + << std::endl; + } + } + } + } + } + + if (!theIsDemFlag) + { + return false; + } + + // Open up the file for reading. + std::ifstream is(theImageFile.c_str(), ios::in | ios::binary); + if (!is) + { + theErrorStatus = ossimErrorCodes::OSSIM_ERROR; + + cerr << MODULE << " ERROR!" + << "\nCould not open file: " << theImageFile.c_str() + << "\nReturning..." << std::endl; + if (traceDebug()) CLOG << "returning with error..." << std::endl; + theIsDemFlag = false; + return false; + } + + //--- + // SPECIAL HACK (drb): + // Check some bytes and make sure there is no binary data. There are + // files out there with .dem extension that are binary rasters. + //--- + ossim_uint8* ubuf = new ossim_uint8[512]; + is.read((char*)ubuf, 512); + if (is) + { + for (int i = 0; i < 512; ++i) + { + if (ubuf[i] > 0x7f) + { + theIsDemFlag = false; + break; + } + } + } + else + { + theIsDemFlag = false; + } + delete [] ubuf; + ubuf = NULL; + if (theIsDemFlag == false) + { + is.close(); + return false; + } + is.seekg(0, ios::beg); + // End of "SPECIAL HACK". + + // Start out with a fresh dem. + if (theDem) delete theDem; + + // Read the dem. + theDem = new ossimDemGrid(); + theDem->read(is); + + is.close(); + + theFeetFlag = (theDem->getHeader().getElevationUnits() == 1) ? + true : false; + + theNullValue = theDem->getMissingDataValue(); + theMinHeight = theFeetFlag ? theDem->getHeader().getMinimumElev() * + MTRS_PER_FT : theDem->getHeader().getMinimumElev(); + theMaxHeight = theFeetFlag ? theDem->getHeader().getMaximumElev() * + MTRS_PER_FT : theDem->getHeader().getMaximumElev(); + + completeOpen(); + + //*** + // Set up the tiles. Note the blank tile will not get initialized to save + // memory. This includes setting the min and max pixel value gathered + // from the statistics. + //*** + theTile = ossimImageDataFactory::instance()->create(this, this); + theTile->initialize(); + + if (traceDebug()) + { + CLOG << setiosflags(ios::fixed) << setprecision(5) << "DEBUG:" + << "\nNull pix: " << (theTile->getNullPix(0)) + << "\nMin pix: " << (theTile->getMinPix(0)) + << "\nMax pix: " << (theTile->getMaxPix(0)) + << "\nlines: " << theDem->getHeight() + << "\nsamples: " << theDem->getWidth() + << std::endl; + } + + return true; +} + +bool ossimUsgsDemTileSource::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + // Save of the dem type keyword. + kwl.add(prefix, DEM_TYPE_KW, USGS_DEM_KW, true); + + // Save the scalar type. + kwl.add(prefix, + ossimKeywordNames::SCALAR_TYPE_KW, + ossimScalarTypeLut::instance()->getEntryString(theScalarType)); + + return ossimImageHandler::saveState(kwl, prefix); +} + +bool ossimUsgsDemTileSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + if (ossimImageHandler::loadState(kwl, prefix)) + { + //*** + // Look for "dem_type: usgs_dem" key value pair. + // Note: If not in the keyword list the "open" will look for it on + // disk. + //*** + const char* lookup = kwl.find(prefix, DEM_TYPE_KW); + if (lookup) + { + ossimString s = lookup; + s.downcase(); + if (s == USGS_DEM_KW) theIsDemFlag = true; + } + + //--- + // Look for scalar type override. + // + // Note: We only allow float or signed 16 bit. + //--- + lookup = kwl.find(prefix, ossimKeywordNames::SCALAR_TYPE_KW); + if (lookup) + { + ossimScalarType st = + static_cast<ossimScalarType>(ossimScalarTypeLut::instance()-> + getEntryNumber(lookup)); + if ( (st == OSSIM_FLOAT32) || (st == OSSIM_SINT16)) + { + theScalarType = st; + } + else + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimUsgsDemTileSource::loadState WARNING:" + << "\nInvalid scalar type: " + << ossimScalarTypeLut::instance()-> + getEntryString(st) + << std::endl; + } + } + } + + if (ossimImageHandler::open(theImageFile)) + { + return true; + } + } + + return false; +} + +bool ossimUsgsDemTileSource::getImageGeometry(ossimKeywordlist& kwl, + const char* prefix) +{ + if (!theDem) + { + return false; + } + + // Previously saved... + if (theGeometryKwl.getSize()) + { + kwl = theGeometryKwl; + return true; + } + + const ossimDemHeader HDR = theDem->getHeader(); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimUsgsDemTileSource::getImageGeometry DEBUG:" + << "\nDEM Header:" + << std::endl; + HDR.print(ossimNotify(ossimNotifyLevel_DEBUG)); + } + + if (HDR.getImageGeometry(kwl, prefix) == false) + { + return false; + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimUsgsDemTileSource::getImageGeometry DEBUG:" + << "keyword list:\n" << kwl + << std::endl; + } + + // Capture for next time. + setImageGeometry(kwl); + + return true; +} + +ossimScalarType +ossimUsgsDemTileSource::getOutputScalarType() const +{ + return theScalarType; +} + +ossim_uint32 ossimUsgsDemTileSource::getTileWidth() const +{ + return ( theTile.valid() ? theTile->getWidth() : 0 ); +} + +ossim_uint32 ossimUsgsDemTileSource::getTileHeight() const +{ + return ( theTile.valid() ? theTile->getHeight() : 0 ); +} + +ossim_uint32 ossimUsgsDemTileSource::getNumberOfLines(ossim_uint32 reduced_res_level) const +{ + if (reduced_res_level == 0) + { + if (theDem) + { + return theDem->getHeight(); + } + else + { + cerr << "ossimUsgsDemTileSource::getNumberOfLines ERROR:" + << "\nNot initialized!" << std::endl; + return 0; + } + } + else if (theOverview) + { + return theOverview->getNumberOfLines(reduced_res_level); + } + + return 0; +} + +ossim_uint32 ossimUsgsDemTileSource::getNumberOfSamples(ossim_uint32 reduced_res_level) const +{ + if (reduced_res_level == 0) + { + if (theDem) + { + return theDem->getWidth(); + } + else + { + cerr << "ossimUsgsDemTileSource::getNumberOfSamples ERROR:" + << "\nNot initialized!" << std::endl; + return 0; + } + } + else if (theOverview) + { + return theOverview->getNumberOfSamples(reduced_res_level); + } + + return 0; +} + +ossim_uint32 ossimUsgsDemTileSource::getImageTileWidth() const +{ + return 0; +} + +ossim_uint32 ossimUsgsDemTileSource::getImageTileHeight() const +{ + return 0; +} + +ossimString ossimUsgsDemTileSource::getShortName() const +{ + return ossimString("usgs dem"); +} + +ossimString ossimUsgsDemTileSource::getLongName() const +{ + return ossimString("usgs dem reader"); +} + +ossimString ossimUsgsDemTileSource::className() const +{ + return ossimString("ossimUsgsDemTileSource"); +} + +ossim_uint32 ossimUsgsDemTileSource::getNumberOfInputBands() const +{ + return 1; +} + +ossim_uint32 ossimUsgsDemTileSource::getNumberOfOutputBands()const +{ + return 1; +} + +double ossimUsgsDemTileSource::getNullPixelValue(ossim_uint32 band)const +{ + if(theMetaData.getNumberOfBands()) + { + return theMetaData.getNullPix(band); + } + return theNullValue; +} + +double ossimUsgsDemTileSource::getMinPixelValue(ossim_uint32 band)const +{ + if(theMetaData.getNumberOfBands()) + { + return theMetaData.getMinPix(band); + } + return theMinHeight; +} + +double ossimUsgsDemTileSource::getMaxPixelValue(ossim_uint32 band)const +{ + if(theMetaData.getNumberOfBands()) + { + return theMetaData.getMaxPix(band); + } + return theMaxHeight; +} + +bool ossimUsgsDemTileSource::isOpen()const +{ + return (theDem ? true : false ); +} + +const ossimUsgsDemTileSource& ossimUsgsDemTileSource::operator=(const ossimUsgsDemTileSource& rhs) +{ + return rhs; +} + +ossimUsgsDemTileSource::ossimUsgsDemTileSource(const ossimUsgsDemTileSource&) +{ +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/usgs_dem/ossimUsgsDemTileSource.h b/Utilities/OSSIM/ossim_core/imaging/formats/usgs_dem/ossimUsgsDemTileSource.h new file mode 100644 index 0000000000..cde4512f09 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/usgs_dem/ossimUsgsDemTileSource.h @@ -0,0 +1,173 @@ +//******************************************************************* +// Copyright (C) 2002 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: David Burken +// +// Description: +// +// Contains class declaration of ossimUsgsDemTileSource. +// The ossimUsgsDemTileSource class is derived from ossimImageHandler and +// is intended to be an image handler for USGS dem files. +// +//******************************************************************** +// $Id: ossimUsgsDemTileSource.h,v 1.17 2006/01/10 16:19:38 dburken Exp $ + +#ifndef ossimUsgsDemTileSource_HEADER +#define ossimUsgsDemTileSource_HEADER + + // #include <fstream> +#include "imaging/formats/ossimImageHandler.h" + +class ossimImageData; +class ossimDemGrid; + +class OSSIM_DLL ossimUsgsDemTileSource : public ossimImageHandler +{ +public: + + ossimUsgsDemTileSource(); + + virtual ~ossimUsgsDemTileSource(); + + virtual ossimString getShortName() const; + virtual ossimString getLongName() const; + virtual ossimString className() const; + + /** + * Returns true if the "theImageFile can be opened. + * + * If the extension is not equal to ".dem" this will attempt to look for + * an ".omd" file with the keyword pair "dem_type: usgs_dem" in it. + * + * Optionally users can change the scalar type from signed 16 bit to + * float with the keyword pair "scalar_type: ossim_float32" + */ + virtual bool open(); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tile_rect, + ossim_uint32 resLevel=0); + + /** + * Returns the number of bands in the image. + * Satisfies pure virtual requirement from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfInputBands() const; + virtual ossim_uint32 getNumberOfOutputBands() const; + + /** + * Returns the number of lines in the image. + * Satisfies pure virtual requirement from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfLines(ossim_uint32 reduced_res_level = 0) const; + + /** + * Returns the number of samples in the image. + * Satisfies pure virtual requirement from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfSamples(ossim_uint32 reduced_res_level = 0) const; + + virtual double getNullPixelValue(ossim_uint32 band=0)const; + virtual double getMinPixelValue(ossim_uint32 band=0)const; + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + + /** + * Returns the zero based image rectangle for the reduced resolution data + * set (rrds) passed in. Note that rrds 0 is the highest resolution rrds. + */ + virtual ossimIrect getImageRectangle(ossim_uint32 reduced_res_level = 0) const; + + /** + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + * + * Keywords picked up by this method: + * dem_type: usgs_dem + * scalar_type: ossim_sint16 (default) + * or + * scalar_type: ossim_float32 + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * Populates the keyword list with image geometry information. This + * method is used to relay projection/model information to users. + * Returns true if geometry info is present, false if not. + */ + virtual bool getImageGeometry(ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * Returns the output pixel type of the tile source. + */ + virtual ossimScalarType getOutputScalarType() const; + + /** + * Returns the width of the output tile. + */ + virtual ossim_uint32 getTileWidth() const; + + /** + * Returns the height of the output tile. + */ + virtual ossim_uint32 getTileHeight() const; + + /** + * Returns the tile width of the image or 0 if the image is not tiled. + * Note: this is not the same as the ossimImageSource::getTileWidth which + * returns the output tile width which can be different than the internal + * image tile width on disk. + */ + virtual ossim_uint32 getImageTileWidth() const; + + /** + * Returns the tile width of the image or 0 if the image is not tiled. + * Note: this is not the same as the ossimImageSource::getTileWidth which + * returns the output tile width which can be different than the internal + * image tile width on disk. + */ + virtual ossim_uint32 getImageTileHeight() const; + + virtual bool isOpen()const; + +private: + // Disallow operator= and copy constrution... + const ossimUsgsDemTileSource& operator=(const ossimUsgsDemTileSource& rhs); + ossimUsgsDemTileSource(const ossimUsgsDemTileSource&); + + /** + * Returns true on success, false on error. + */ + template <class T> bool fillBuffer(T, // dummy template variable + const ossimIrect& tile_rect, + const ossimIrect& clip_rect); + + void gatherStatistics(); + + ossimDemGrid* theDem; + ossimRefPtr<ossimImageData> theTile; + ossim_float64 theNullValue; + ossim_float64 theMinHeight; + ossim_float64 theMaxHeight; + bool theFeetFlag; // elevation units = feet + bool theIsDemFlag; + + /** + * This can be either OSSIM_SINT16 or OSSIM_FLOAT32. Default = OSSIM_SINT16 + * Can be changed via ".omd" file keyword: + */ + ossimScalarType theScalarType; + +TYPE_DATA +}; + +#endif // #ifndef ossimUsgsDemTileSource_HEADER diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/vpf/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/formats/vpf/.cvsignore new file mode 100644 index 0000000000..7df3918588 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/vpf/.cvsignore @@ -0,0 +1,3 @@ +*.d +Makefile + diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationCoverageInfo.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationCoverageInfo.cpp new file mode 100644 index 0000000000..507e16c9d1 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationCoverageInfo.cpp @@ -0,0 +1,217 @@ +//************************************************************************* +// Copyright (C) 2004 Intelligence Data Systems, Inc. All rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************** +// $Id: ossimVpfAnnotationCoverageInfo.cpp,v 1.6 2004/11/22 19:35:59 dburken Exp $ + +#include <vector> +#include <algorithm> +#include <imaging/formats/vpf/ossimVpfAnnotationCoverageInfo.h> +#include <vec/vpf/ossimVpfLibrary.h> +#include <vec/vpf/ossimVpfFeatureClassSchema.h> + +bool ossimVpfAnnotationCoverageInfo::hasRenderableFeature()const +{ + for(ossim_uint32 idx = 0; idx < theFeatureInfoArray.size();++idx) + { + if(theFeatureInfoArray[idx]->getEnabledFlag()) + { + return true; + } + } + + return false; +} + +void ossimVpfAnnotationCoverageInfo::getEnabledFeatures(std::vector<ossimVpfAnnotationFeatureInfo*>& result) +{ + for(ossim_uint32 idx = 0; idx < theFeatureInfoArray.size();++idx) + { + if(theFeatureInfoArray[idx]->getEnabledFlag()) + { + result.push_back(theFeatureInfoArray[idx]); + } + } +} + +void ossimVpfAnnotationCoverageInfo::getAllFeatures(std::vector<ossimVpfAnnotationFeatureInfo*>& result) +{ + for(ossim_uint32 idx = 0; idx < theFeatureInfoArray.size();++idx) + { + result.push_back(theFeatureInfoArray[idx]); + } +} + +ossimIrect ossimVpfAnnotationCoverageInfo::getBoundingProjectedRect()const +{ + ossimIrect result; + result.makeNan(); + + for(ossim_uint32 idx = 0; idx < theFeatureInfoArray.size();++idx) + { + ossimIrect tempRect = theFeatureInfoArray[idx]->getBoundingProjectedRect(); + if(!tempRect.hasNans()) + { + if(result.hasNans()) + { + result = tempRect; + } + else + { + result = result.combine(tempRect); + } + } + } + + return result; +} + + +void ossimVpfAnnotationCoverageInfo::transform(ossimProjection* proj) +{ + for(ossim_uint32 idx = 0; idx < theFeatureInfoArray.size();++idx) + { + theFeatureInfoArray[idx]->transform(proj); + } +} + +void ossimVpfAnnotationCoverageInfo::buildCoverage() +{ + buildCoverage( "" ); +} + +void ossimVpfAnnotationCoverageInfo::buildCoverage(const ossimString& feature) +{ + deleteAllFeatures(); + if(theLibrary) + { + ossimVpfCoverage coverage; + + if(theLibrary->getCoverage(theName, coverage)) + { + ossimVpfFeatureClassSchema schema; + if(coverage.openFeatureClassSchema(schema)) + { + std::vector<ossimString> featureClassArray; + schema.getFeatureClasses(featureClassArray); + schema.closeTable(); + for(ossim_uint32 idx = 0; idx < featureClassArray.size(); ++idx) + { + ossimString s1 = feature; + ossimString s2 = featureClassArray[idx]; + s1.downcase(); + s2.downcase(); + if (! feature.length() || (s1 == s2) ) + { + ossimVpfAnnotationFeatureInfo* featureInfo = + new ossimVpfAnnotationFeatureInfo; + featureInfo->setName(featureClassArray[idx]); + featureInfo->setCoverage(coverage); + theFeatureInfoArray.push_back(featureInfo); + featureInfo->buildFeature(); + } + } + } + } + } +} + +void ossimVpfAnnotationCoverageInfo::drawAnnotations(ossimRgbImage* tile) +{ + for(ossim_uint32 idx = 0; idx < theFeatureInfoArray.size();++idx) + { + if(theFeatureInfoArray[idx]->getEnabledFlag()) + { + theFeatureInfoArray[idx]->drawAnnotations(tile); + } + } +} + +void ossimVpfAnnotationCoverageInfo::deleteAllFeatures() +{ + for(ossim_uint32 idx = 0; idx < theFeatureInfoArray.size();++idx) + { + theFeatureInfoArray[idx]; + } + + theFeatureInfoArray.clear(); +} + + + +bool ossimVpfAnnotationCoverageInfo::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + "name", + theName, + true); + + for(ossim_uint32 idx = 0; idx < theFeatureInfoArray.size(); ++idx) + { + theFeatureInfoArray[idx]->saveState(kwl, + (ossimString(prefix) + "feature" + + ossimString::toString(idx) + ".").c_str()); + } + + return true; +} + +bool ossimVpfAnnotationCoverageInfo::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + deleteAllFeatures(); + + if(!theLibrary) + { + return false; + } + + theName = kwl.find(prefix, "name"); + ossimVpfCoverage coverage; + + if(theLibrary->getCoverage(theName, coverage)) + { + ossimString regExpression = ossimString("^(") + ossimString(prefix) + "feature[0-9]+.)"; + vector<ossimString> keys = + kwl.getSubstringKeyList( regExpression ); + std::vector<int> theNumberList(keys.size()); + int offset = (ossimString(prefix)+"feature").size(); + int idx = 0; + for(idx = 0; idx < (int)theNumberList.size();++idx) + { + ossimString numberStr(keys[idx].begin() + offset, + keys[idx].end()); + theNumberList[idx] = numberStr.toInt(); + } + std::sort(theNumberList.begin(), theNumberList.end()); + + for(idx=0;idx < (int)keys.size();++idx) + { + ossimString newPrefix = ossimString(prefix); + newPrefix += ossimString("feature"); + newPrefix += ossimString::toString(theNumberList[idx]); + newPrefix += ossimString("."); + ossimVpfAnnotationFeatureInfo* featureInfo = new ossimVpfAnnotationFeatureInfo; + featureInfo->setCoverage(coverage); + theFeatureInfoArray.push_back(featureInfo); + if(!featureInfo->loadState(kwl, + newPrefix)) + { + return false; + } + } + } + else + { + return false; + } + + return true; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationCoverageInfo.h b/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationCoverageInfo.h new file mode 100644 index 0000000000..60256d296d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationCoverageInfo.h @@ -0,0 +1,77 @@ +//************************************************************************* +// Copyright (C) 2004 Intelligence Data Systems, Inc. All rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************** +// $Id: ossimVpfAnnotationCoverageInfo.h,v 1.8 2004/12/21 20:12:40 gpotts Exp $ +#ifndef ossimVpfAnnotationCoverageInfo_HEADER +#define ossimVpfAnnotationCoverageInfo_HEADER +#include <imaging/formats/vpf/ossimVpfAnnotationFeatureInfo.h> +#include <vec/vpf/ossimVpfCoverage.h> +class ossimVpfLibrary; + +class ossimRgbImage; + +class ossimVpfAnnotationCoverageInfo +{ +public: + ossimVpfAnnotationCoverageInfo(const ossimString& name="") + :theName(name) + { + + } + virtual ~ossimVpfAnnotationCoverageInfo() + { + deleteAllFeatures(); + } + bool hasRenderableFeature()const; + void getEnabledFeatures(std::vector<ossimVpfAnnotationFeatureInfo*>& result); + void getAllFeatures(std::vector<ossimVpfAnnotationFeatureInfo*>& result); + + void transform(ossimProjection* proj); + ossimIrect getBoundingProjectedRect()const; + void buildCoverage(); + void buildCoverage(const ossimString& feature); + void setName(const ossimString& name) + { + theName = name; + } + ossimString getName()const + { + return theName; + } + void setLibrary(ossimVpfLibrary* library) + { + theLibrary = library; + } + ossimVpfLibrary* getLibrary() + { + return theLibrary; + } + const ossimVpfLibrary* getLibrary()const + { + return theLibrary; + } + void drawAnnotations(ossimRgbImage* tile); + void deleteAllFeatures(); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); +protected: + ossimString theName; + + /*! + * Not owned. + */ + ossimVpfLibrary* theLibrary; + std::vector<ossimVpfAnnotationFeatureInfo*> theFeatureInfoArray; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationFeatureInfo.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationFeatureInfo.cpp new file mode 100644 index 0000000000..7e0ce4dd8f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationFeatureInfo.cpp @@ -0,0 +1,1451 @@ +#include <sstream> + +#include "ossimVpfAnnotationFeatureInfo.h" +#include "vec/vpf/ossimVpfCoverage.h" +#include "vec/vpf/ossimVpfLibrary.h" +#include "vec/vpf/ossimVpfFeatureClassSchema.h" +#include "projections/ossimProjection.h" +#include "base/data_types/ossimPolyLine.h" +#include "base/data_types/ossimGeoPolygon.h" +#include "imaging/annotation/ossimGeoAnnotationSource.h" +#include "imaging/annotation/ossimAnnotationObject.h" +#include "imaging/annotation/ossimGeoAnnotationMultiPolyLineObject.h" +#include "imaging/annotation/ossimGeoAnnotationMultiEllipseObject.h" +#include "imaging/annotation/ossimGeoAnnotationFontObject.h" +#include "imaging/annotation/ossimGeoAnnotationMultiPolyObject.h" +#include "imaging/ossimRgbImage.h" +#include "fonts/ossimFont.h" +#include "fonts/factory/ossimFontFactoryRegistry.h" +#include <base/common/ossimTrace.h> + +static ossimTrace traceDebug("ossimVpfAnnotationFeatureInfo:debug"); + +RTTI_DEF1(ossimVpfAnnotationFeatureInfo, "ossimVpfAnnotationFeatureInfo", ossimObject); + +ossimVpfAnnotationFeatureInfo::ossimVpfAnnotationFeatureInfo(const ossimString& featureName, + const ossimRgbVector& penColor, + const ossimRgbVector& brushColor, + const ossimDpt& pointRadius, + int thickness, + bool enabledFlag) + :theName(featureName), + thePenColor(penColor), + theBrushColor(brushColor), + thePointRadius(pointRadius), + theThickness(thickness), + theFillEnabledFlag(false), + theEnabledFlag(enabledFlag), + theFeatureType(ossimVpfAnnotationFeatureType_UNKNOWN) +{ + ossimFont* font = ossimFontFactoryRegistry::instance()->getDefaultFont(); + + if(font) + { + std::vector<ossimFontInformation> fontInfoArray; + + font->getFontInformation(fontInfoArray); + + if(fontInfoArray.size()) + { + theFontInformation = fontInfoArray[0]; + } + } +} + + +ossimVpfAnnotationFeatureInfo::~ossimVpfAnnotationFeatureInfo() +{ + deleteAllObjects(); +} + +void ossimVpfAnnotationFeatureInfo::transform(ossimProjection* proj) +{ + if(theEnabledFlag) + { + for(int idx = 0; idx < (int)theAnnotationArray.size();++idx) + { + if(theAnnotationArray[idx]) + { + theAnnotationArray[idx]->transform(proj); + theAnnotationArray[idx]->computeBoundingRect(); + } + } + } +} +ossimIrect ossimVpfAnnotationFeatureInfo::getBoundingProjectedRect()const +{ + ossimIrect result; + result.makeNan(); + + if(theEnabledFlag) + { + for(int idx = 0; idx < (int)theAnnotationArray.size();++idx) + { + if(theAnnotationArray[idx]) + { + ossimIrect tempRect = theAnnotationArray[idx]->getBoundingRect(); + if(!tempRect.hasNans()) + { + if(result.hasNans()) + { + result = tempRect; + } + else + { + result = result.combine(tempRect); + } + } + } + } + } + + return result; +} + +void ossimVpfAnnotationFeatureInfo::setEnabledFlag(bool flag) +{ + if(!flag && theEnabledFlag) + { + deleteAllObjects(); + } + else if(flag&&(!theEnabledFlag)) + { + theEnabledFlag = flag; + buildFeature(); + } + theEnabledFlag = flag; +} + +void ossimVpfAnnotationFeatureInfo::buildFeature() +{ + deleteAllObjects(); + + ossimVpfFeatureClassSchemaNode node; + + ossimVpfFeatureClassSchema schema; + theCoverage.openFeatureClassSchema(schema); + if(schema.getFeatureClassNode(theName, + node)) + { + if(node.thePrimitiveTable.contains("edg")) + { + theFeatureType = ossimVpfAnnotationFeatureType_LINE; + if(theEnabledFlag) + { + buildEdgFeature(node.theTable.trim(), + node.theTableKey.trim(), + node.thePrimitiveTable.trim(), + node.thePrimitiveTableKey.trim()); + } + } + else if(node.thePrimitiveTable.contains("txt")) + { + theFeatureType = ossimVpfAnnotationFeatureType_TEXT; + if(theEnabledFlag) + { + buildTxtFeature(node.theTable.trim(), + node.theTableKey.trim(), + node.thePrimitiveTable.trim(), + node.thePrimitiveTableKey.trim()); + } + } + else if(node.thePrimitiveTable.contains("fac")) + { + theFeatureType = ossimVpfAnnotationFeatureType_POLYGON; + if(theEnabledFlag) + { + buildFaceFeature(node.theTable.trim(), + node.theTableKey.trim(), + node.thePrimitiveTable.trim(), + node.thePrimitiveTableKey.trim()); + } + } + else if(node.thePrimitiveTable.contains("cnd")) + { + theFeatureType = ossimVpfAnnotationFeatureType_POINT; + if(theEnabledFlag) + { + buildPointFeature("cnd", + node.theTable.trim(), + node.theTableKey.trim(), + node.thePrimitiveTable.trim(), + node.thePrimitiveTableKey.trim()); + } + } + else if(node.thePrimitiveTable.contains("end")) + { + theFeatureType = ossimVpfAnnotationFeatureType_POINT; + if(theEnabledFlag) + { + buildPointFeature("end", + node.theTable.trim(), + node.theTableKey.trim(), + node.thePrimitiveTable.trim(), + node.thePrimitiveTableKey.trim()); + } + } + else + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "Primitive \""<<node.thePrimitiveTable<<"\" not handled yet" << endl; + } + } + } +} + +void ossimVpfAnnotationFeatureInfo::drawAnnotations(ossimRgbImage* tile) +{ + if(theEnabledFlag) + { + int idx = 0; + for(idx = 0; idx < (int)theAnnotationArray.size(); ++idx) + { + theAnnotationArray[idx]->draw(*tile); + } + } +} + +bool ossimVpfAnnotationFeatureInfo::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + "name", + theName.c_str(), + true); + kwl.add(prefix, + "description", + theDescription.c_str(), + true); + ossimString penColor = (ossimString::toString((int)thePenColor.getR())+ " " + + ossimString::toString((int)thePenColor.getG())+ " " + + ossimString::toString((int)thePenColor.getB())); + ossimString brushColor = (ossimString::toString((int)theBrushColor.getR())+ " " + + ossimString::toString((int)theBrushColor.getG())+ " " + + ossimString::toString((int)theBrushColor.getB())); + kwl.add(prefix, + "pen_color", + penColor, + true); + kwl.add(prefix, + "brush_color", + brushColor, + true); + + if(theFeatureType == ossimVpfAnnotationFeatureType_POINT) + { + kwl.add(prefix, + "point_radius", + ossimString::toString(thePointRadius.x) + " " + + ossimString::toString(thePointRadius.y), + true); + kwl.add(prefix, + "fill_enabled", + theFillEnabledFlag, + true); + } + else if(theFeatureType == ossimVpfAnnotationFeatureType_LINE) + { + kwl.add(prefix, + "thickness", + theThickness, + true); + } + else if(theFeatureType == ossimVpfAnnotationFeatureType_POLYGON) + { + kwl.add(prefix, + "fill_enabled", + theFillEnabledFlag, + true); + kwl.add(prefix, + "thickness", + theThickness, + true); + } + else if(theFeatureType == ossimVpfAnnotationFeatureType_TEXT) + { + theFontInformation.saveState(kwl, + (ossimString(prefix)+"font.").c_str()); + } + kwl.add(prefix, + "enabled", + theEnabledFlag, + true); + kwl.add(prefix, + "feature_type", + getFeatureTypeAsString(), + true); + + return true; +} + +bool ossimVpfAnnotationFeatureInfo::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* name = kwl.find(prefix, "name"); + const char* description = kwl.find(prefix, "description"); + const char* enabled = kwl.find(prefix, "enabled"); + const char* fillEnabled = kwl.find(prefix, "fill_enabled"); + const char* thickness = kwl.find(prefix, "thickness"); + const char* pointRadius = kwl.find(prefix, "point_radius"); + const char* brushColor = kwl.find(prefix, "brush_color"); + const char* penColor = kwl.find(prefix, "pen_color"); + + theFontInformation.loadState(kwl, + (ossimString(prefix)+"font.").c_str()); + + if(name) + { + if(theName != name) + { + deleteAllObjects(); + } + theName = name; + } + if(description) + { + theDescription = description; + } + if(enabled) + { + theEnabledFlag = ossimString(enabled).toBool(); + + if(!theEnabledFlag) + { + deleteAllObjects(); + } + } + + if(fillEnabled) + { + theFillEnabledFlag = ossimString(fillEnabled).toBool(); + } + if(thickness) + { + theThickness = ossimString(thickness).toInt(); + } + if(pointRadius) + { + stringstream ptRadiusStream(pointRadius); + ptRadiusStream >> thePointRadius.x >> thePointRadius.y; + } + if(brushColor) + { + int r, g, b; + stringstream colorStream(brushColor); + colorStream >> r >> g >> b; + + theBrushColor.setR((ossim_uint8)r); + theBrushColor.setG((ossim_uint8)g); + theBrushColor.setB((ossim_uint8)b); + } + if(penColor) + { + int r, g, b; + stringstream colorStream(brushColor); + colorStream >> r >> g >> b; + + thePenColor.setR((ossim_uint8)r); + thePenColor.setG((ossim_uint8)g); + thePenColor.setB((ossim_uint8)b); + } + + if(theEnabledFlag&&(theAnnotationArray.size() < 1)) + { + buildFeature(); + } + else + { + setDrawingFeaturesToAnnotation(); + } + + return true; +} + +ossimString ossimVpfAnnotationFeatureInfo::getFeatureTypeAsString()const +{ + switch(theFeatureType) + { + case ossimVpfAnnotationFeatureType_POINT: + { + return "point"; + } + case ossimVpfAnnotationFeatureType_LINE: + { + return "line"; + } + case ossimVpfAnnotationFeatureType_POLYGON: + { + return "polygon"; + } + case ossimVpfAnnotationFeatureType_TEXT: + { + return "text"; + } + default: + break; + } + + return "unknown"; +} + +ossimVpfAnnotationFeatureInfo::ossimVpfAnnotationFeatureType ossimVpfAnnotationFeatureInfo::getFeatureTypeFromString(const ossimString& featureType)const +{ + ossimString downCased = featureType; + downCased = downCased.downcase(); + + if(downCased.contains("point")) + { + return ossimVpfAnnotationFeatureType_POINT; + } + else if(downCased.contains("line")) + { + return ossimVpfAnnotationFeatureType_LINE; + } + else if(downCased.contains("polygon")) + { + return ossimVpfAnnotationFeatureType_POLYGON; + } + else if(downCased.contains("text")) + { + return ossimVpfAnnotationFeatureType_TEXT; + } + + return ossimVpfAnnotationFeatureType_UNKNOWN; + +} + +void ossimVpfAnnotationFeatureInfo::deleteAllObjects() +{ + for(int idx = 0; idx < (int)theAnnotationArray.size();++idx) + { + delete theAnnotationArray[idx]; + } + + theAnnotationArray.clear(); +} + +void ossimVpfAnnotationFeatureInfo::setDrawingFeaturesToAnnotation() +{ + switch(theFeatureType) + { + case ossimVpfAnnotationFeatureType_POINT: + { + ossimGeoAnnotationMultiEllipseObject* annotation = NULL; + for(int idx = 0; idx < (int)theAnnotationArray.size();++idx) + { + annotation = (ossimGeoAnnotationMultiEllipseObject*)theAnnotationArray[idx]; + + annotation->setColor(thePenColor.getR(), + thePenColor.getG(), + thePenColor.getB()); + annotation->setThickness(theThickness); + annotation->setFillFlag(theFillEnabledFlag); + annotation->setWidthHeight(thePointRadius); + } + + break; + } + case ossimVpfAnnotationFeatureType_TEXT: + { + ossimGeoAnnotationFontObject* annotation = NULL; + ossimFont* font = ossimFontFactoryRegistry::instance()->createFont(theFontInformation); + + for(int idx = 0; idx < (int)theAnnotationArray.size();++idx) + { + annotation = (ossimGeoAnnotationFontObject*)theAnnotationArray[idx]; + annotation->setColor(thePenColor.getR(), + thePenColor.getG(), + thePenColor.getB()); + annotation->setThickness(theThickness); + + if(font) + { + annotation->setFont((ossimFont*)font->dup()); + } + annotation->setPointSize(theFontInformation.thePointSize); + annotation->setScale(theFontInformation.theScale); + annotation->setShear(theFontInformation.theShear); + annotation->setRotation(theFontInformation.theRotation); + } + if(font) + { + delete font; + font = NULL; + } + break; + } + case ossimVpfAnnotationFeatureType_LINE: + { + ossimGeoAnnotationMultiPolyLineObject* annotation = NULL; + for(int idx = 0; idx < (int)theAnnotationArray.size();++idx) + { + annotation = (ossimGeoAnnotationMultiPolyLineObject*)theAnnotationArray[idx]; + annotation->setColor(thePenColor.getR(), + thePenColor.getG(), + thePenColor.getB()); + annotation->setThickness(theThickness); + } + + break; + } + case ossimVpfAnnotationFeatureType_POLYGON: + { + ossimGeoAnnotationMultiPolyObject* annotation = NULL; + for(int idx = 0; idx < (int)theAnnotationArray.size();++idx) + { + annotation = (ossimGeoAnnotationMultiPolyObject*)theAnnotationArray[idx]; + annotation->setColor(thePenColor.getR(), + thePenColor.getG(), + thePenColor.getB()); + annotation->setThickness(theThickness); + annotation->setFillFlag(theFillEnabledFlag); + } + break; + } + default: + { + break; + } + } +} + + +void ossimVpfAnnotationFeatureInfo::buildTxtFeature(const ossimFilename& tableName, + const ossimString& tableKey, + const ossimFilename& primitiveName, + const ossimString& primitiveKey) +{ + ossimFilename tableFileName = theCoverage.getPath().dirCat(tableName); + ossimFilename primitiveTableName; + ossimVpfTable table; + ossimVpfTable primitiveTable; + + if(table.openTable(tableFileName)) + { + table.reset(); + vector<ossimString> columnValues = table.getColumnValues(tableKey.trim()); + + primitiveTableName = theCoverage.getPath().dirCat("txt"); + + vector<ossimString> tileIds; + ossim_int32 stringValuePosition = 0; + ossim_int32 shapeLinePosition = 0; + bool isTiled = false; + if(table.getColumnPosition("tile_id") >= 0) + { + tileIds = table.getColumnValues("tile_id"); + isTiled = true; + } + if(!isTiled) + { + primitiveTableName = theCoverage.getPath().dirCat("txt"); + if(!primitiveTable.openTable(primitiveTableName)) + { + return; + } + stringValuePosition = primitiveTable.getColumnPosition("string"); + shapeLinePosition = primitiveTable.getColumnPosition("shape_line"); + } + ossim_int32 tileId = -1; + for(ossim_uint32 idx = 0; idx < columnValues.size();++idx) + { + if(isTiled) + { + if(tileId != tileIds[idx].toInt()) + { + tileId = tileIds[idx].toInt(); + ossimFilename filename = theCoverage.getLibrary()->getTileName(tileIds[idx].toInt()); + if(theCoverage.getPath().dirCat(filename).dirCat("txt").exists()) + { + primitiveTableName = theCoverage.getPath().dirCat(filename).dirCat("txt"); + } + else if(theCoverage.getPath().dirCat(filename.downcase()).dirCat("txt").exists()) + { + primitiveTableName = theCoverage.getPath().dirCat(filename.downcase()).dirCat("txt"); + } + if(!primitiveTable.openTable(primitiveTableName)) + { + return; + } + stringValuePosition = primitiveTable.getColumnPosition("string"); + shapeLinePosition = primitiveTable.getColumnPosition("shape_line"); + } + } + row_type row = read_row( columnValues[idx].toInt(), + *primitiveTable.getVpfTableData()); + long count = 0; + ossimDpt* ptArray = getXy(*primitiveTable.getVpfTableData(), + row, + shapeLinePosition, + &count); + ossimDpt midPoint; + if(ptArray) + { + midPoint = *ptArray; + + delete [] ptArray; + } + ossimString stringValue = primitiveTable.getColumnValueAsString(row, + stringValuePosition); + free_row(row, *primitiveTable.getVpfTableData()); + + if(!midPoint.hasNans()) + { + ossimGpt centerPoint(midPoint.lat, + midPoint.lon, + OSSIM_DBL_NAN); + ossimFont* font = ossimFontFactoryRegistry::instance()->createFont(theFontInformation); + ossimGeoAnnotationFontObject* annotation = new ossimGeoAnnotationFontObject(centerPoint, + stringValue); + annotation->setColor(thePenColor.getR(), + thePenColor.getG(), + thePenColor.getB()); + annotation->setThickness(theThickness); + + annotation->setFont(font); + annotation->setPointSize(theFontInformation.thePointSize); + annotation->setScale(theFontInformation.theScale); + annotation->setShear(theFontInformation.theShear); + annotation->setRotation(theFontInformation.theRotation); + theAnnotationArray.push_back(annotation); + } + } + } +} + +void ossimVpfAnnotationFeatureInfo::buildEdgFeature(const ossimFilename& tableName, + const ossimString& tableKey, + const ossimFilename& primitiveName, + const ossimString& primitiveKey) +{ + ossimFilename tableFileName = theCoverage.getPath().dirCat(tableName); + ossimFilename primitiveTableName; + ossimVpfTable table; + ossimVpfTable primitiveTable; + + std::vector<ossimPolyLine> polyLineArray; + + if(table.openTable(tableFileName)) + { + + vector<ossimString> columnValues = table.getColumnValues(tableKey.trim()); + vector<ossimString> tileIds; + bool isTiled = false; + if(table.getColumnPosition("tile_id") >= 0) + { + tileIds = table.getColumnValues("tile_id"); + isTiled = true; + } + ossim_int32 coordinateValuePosition = 0; + if(!isTiled) + { + primitiveTableName = theCoverage.getPath().dirCat("edg"); + if(!primitiveTable.openTable(primitiveTableName)) + { + return; + } + coordinateValuePosition = primitiveTable.getColumnPosition("coordinates"); + } + ossim_int32 tileId = -1; + for(ossim_uint32 idx = 0; idx < columnValues.size();++idx) + { + if(isTiled) + { + if(tileId != tileIds[idx].toInt()) + { + tileId = tileIds[idx].toInt(); + ossimFilename filename = theCoverage.getLibrary()->getTileName(tileIds[idx].toInt()); + if(theCoverage.getPath().dirCat(filename).dirCat("edg").exists()) + { + primitiveTableName = theCoverage.getPath().dirCat(filename).dirCat("edg"); + } + else if(theCoverage.getPath().dirCat(filename.downcase()).dirCat("edg").exists()) + { + primitiveTableName = theCoverage.getPath().dirCat(filename.downcase()).dirCat("edg"); + } + if(!primitiveTable.openTable(primitiveTableName)) + { + return; + } + coordinateValuePosition = primitiveTable.getColumnPosition("coordinates"); + } + } + ossimPolyLine polyLine; + + readEdge(polyLine, + columnValues[idx].toInt(), + coordinateValuePosition, + primitiveTable); + + readAttributes(polyLine, table, idx + 1); // third parm is one-based row + + polyLineArray.push_back(polyLine); + } + } + ossimGeoAnnotationMultiPolyLineObject* annotation = new ossimGeoAnnotationMultiPolyLineObject(polyLineArray); + annotation->setColor(thePenColor.getR(), + thePenColor.getG(), + thePenColor.getB()); + annotation->setThickness(theThickness); + theAnnotationArray.push_back(annotation); +} + +void ossimVpfAnnotationFeatureInfo::readAttributes(ossimPolyLine& polyLine, ossimVpfTable& table, int row) { + int numCols = table.getNumberOfColumns(); + + for (int col = 0; col < numCols; col ++) { + polyLine.addAttribute( table.getColumnValueAsString( row, col )); + } +} + +void ossimVpfAnnotationFeatureInfo::buildPointFeature(const ossimString& primitiveName, + const ossimFilename& tableName, + const ossimString& tableKey, + const ossimFilename& primitive, + const ossimString& primitiveKey) +{ + ossimFilename tableFileName = theCoverage.getPath().dirCat(tableName); + ossimFilename primitiveTableName; + ossimVpfTable table; + ossimVpfTable primitiveTable; + + std::vector<ossimGpt> centerPointArray; + + if(table.openTable(tableFileName)) + { + + vector<ossimString> columnValues = table.getColumnValues(tableKey.trim()); + vector<ossimString> tileIds; + bool isTiled = false; + if(table.getColumnPosition("tile_id") >= 0) + { + tileIds = table.getColumnValues("tile_id"); + isTiled = true; + } + ossim_int32 coordinateValuePosition = 0; + if(!isTiled) + { + primitiveTableName = theCoverage.getPath().dirCat(primitiveName); + if(!primitiveTable.openTable(primitiveTableName)) + { + return; + } + coordinateValuePosition = primitiveTable.getColumnPosition("coordinate"); + } + ossim_int32 tileId = -1; + for(ossim_uint32 idx = 0; idx < columnValues.size();++idx) + { + if(isTiled) + { + if(tileId != tileIds[idx].toInt()) + { + tileId = tileIds[idx].toInt(); + ossimFilename filename = theCoverage.getLibrary()->getTileName(tileIds[idx].toInt()); + if(theCoverage.getPath().dirCat(filename).dirCat(primitiveName).exists()) + { + primitiveTableName = theCoverage.getPath().dirCat(filename).dirCat(primitiveName); + } + else if(theCoverage.getPath().dirCat(filename.downcase()).dirCat(primitiveName).exists()) + { + primitiveTableName = theCoverage.getPath().dirCat(filename.downcase()).dirCat(primitiveName); + } + if(!primitiveTable.openTable(primitiveTableName)) + { + return; + } + coordinateValuePosition = primitiveTable.getColumnPosition("coordinate"); + } + } + row_type row = read_row( columnValues[idx].toInt(), + *primitiveTable.getVpfTableData()); + + long count = 0; + ossimDpt* ptArray = getXy(*primitiveTable.getVpfTableData(), + row, + coordinateValuePosition, + &count); + + if(ptArray) + { + for(int i = 0; i < count; ++i) + { + if((fabs(ptArray[i].x) <= 180.0)&& + (fabs(ptArray[i].y) <= 90.0)) + { + centerPointArray.push_back(ossimGpt(ptArray[i].lat, + ptArray[i].lon, + OSSIM_DBL_NAN)); + } + } + delete [] ptArray; + } + free_row(row, *primitiveTable.getVpfTableData()); + } + } + ossimGeoAnnotationMultiEllipseObject* annotation = new ossimGeoAnnotationMultiEllipseObject(centerPointArray, + ossimDpt(2,2)); + annotation->setColor(thePenColor.getR(), + thePenColor.getG(), + thePenColor.getB()); + annotation->setThickness(theThickness); + annotation->setFillFlag(theFillEnabledFlag); + annotation->setWidthHeight(thePointRadius); + theAnnotationArray.push_back(annotation); +} + +int myFaceCount = 0; + +void ossimVpfAnnotationFeatureInfo::buildFaceFeature(const ossimFilename& tableName, + const ossimString& tableKey, // face_id + const ossimFilename& primitive, //face + const ossimString& primitiveKey) // id +{ + ossimFilename tableFileName = theCoverage.getPath().dirCat(tableName); + ossimFilename primitiveTableName; + ossimFilename rngTableName; + ossimFilename edgTableName; + ossimVpfTable table; + ossimVpfTable primitiveTable; + ossimVpfTable rngTable; + ossimVpfTable edgTable; + vector<ossimGeoPolygon> thePolyList; + + if(table.openTable(tableFileName)) + { + vector<ossimString> columnValues = table.getColumnValues(tableKey.trim()); // fac_id + vector<ossimString> tileIds; + bool isTiled = false; + if(table.getColumnPosition("tile_id") >= 0) + { + tileIds = table.getColumnValues("tile_id"); + isTiled = true; + } + ossim_int32 coordinateValuePosition = 0; + ossim_int32 startEdgePosition = 0; + ossim_int32 rngPtrPosition = 0; + if(!isTiled) + { + primitiveTableName = theCoverage.getPath().dirCat("fac"); + rngTableName = theCoverage.getPath().dirCat("rng"); + edgTableName = theCoverage.getPath().dirCat("edg"); + if(!primitiveTable.openTable(primitiveTableName)|| + !rngTable.openTable(rngTableName)|| + !edgTable.openTable(edgTableName)) + { + return; + } + coordinateValuePosition = edgTable.getColumnPosition("coordinates"); + startEdgePosition = rngTable.getColumnPosition("start_edge"); + rngPtrPosition = primitiveTable.getColumnPosition("ring_ptr"); + } // else will get for each face in loop below + + ossim_int32 tileId = -1; + + for(ossim_uint32 idx = 0; idx < columnValues.size();++idx) // for each face feature + { + if(isTiled) // then get table names because we didn't get them above + { + if((tileId != tileIds[idx].toInt())|| + (tileId < 0)) + { + tileId = tileIds[idx].toInt(); + ossimFilename filename = theCoverage.getLibrary()->getTileName(tileIds[idx].toInt()); + if(theCoverage.getPath().dirCat(filename).dirCat("fac").exists()) + { + primitiveTableName = theCoverage.getPath().dirCat(filename).dirCat("fac"); + rngTableName = theCoverage.getPath().dirCat(filename).dirCat("rng"); + edgTableName = theCoverage.getPath().dirCat(filename).dirCat("edg"); + } + else if(theCoverage.getPath().dirCat(filename.downcase()).dirCat("fac").exists()) + { + primitiveTableName = theCoverage.getPath().dirCat(filename.downcase()).dirCat("fac"); + rngTableName = theCoverage.getPath().dirCat(filename.downcase()).dirCat("rng"); + edgTableName = theCoverage.getPath().dirCat(filename.downcase()).dirCat("edg"); + } + if(!primitiveTable.openTable(primitiveTableName)|| + !rngTable.openTable(rngTableName)|| + !edgTable.openTable(edgTableName)) + { + return; + } + coordinateValuePosition = edgTable.getColumnPosition("coordinates"); + startEdgePosition = rngTable.getColumnPosition("start_edge"); + rngPtrPosition = primitiveTable.getColumnPosition("ring_ptr"); + } + } // if(isTiled) + + // get the outer ring id for this face + int thisFaceId = columnValues[idx].toInt(); + int rngId = -1; + + if (thisFaceId <= primitiveTable.getNumberOfRows()) + rngId = readRngId(thisFaceId, + rngPtrPosition, + primitiveTable); // face table + else + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "not getting face " << thisFaceId << " from tile " << tileId << " " << primitiveTableName << + " bacause it has only " << primitiveTable.getNumberOfRows() << " rows" << endl; + } + + if(rngId > 0) + { + int startEdge = readStartEdgeId(rngId, + startEdgePosition, + rngTable); + int outerStartEdge = startEdge; + if(startEdge > 0 ) + { + ossimGeoPolygon polygon; + + myFaceCount ++; + + int ringTableFaceIdColumn = rngTable.getColumnPosition("face_id"); + int ringFaceId = readTableCellAsInt(rngId, ringTableFaceIdColumn, rngTable); + + if (thisFaceId != ringFaceId) { + // as of Mon Dec 20 2004, this has not been observed in vmap0 or vmap1 + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "rejecting face " << thisFaceId << " from " << tableFileName << + " because it's ring (" << rngId << ") has face " << ringFaceId << " and startEdgeId " << startEdge << endl; + } + } else { + readGeoPolygon( polygon, + thisFaceId, + startEdge, + edgTable ); + + // get the inner rings (holes) + int faceIdPosition = rngTable.getColumnPosition("face_id"); + int innerRingOffset = 1; + int rowFaceId = -1; + if (rngId + innerRingOffset <= rngTable.getNumberOfRows()) + rowFaceId = rngTable.getColumnValueAsString( rngId + innerRingOffset, faceIdPosition ).toInt(); + while (rowFaceId == thisFaceId && rngId + innerRingOffset <= rngTable.getNumberOfRows()) { // while there are more inner rings + startEdge = readStartEdgeId(rngId + innerRingOffset, startEdgePosition, rngTable); + + if (startEdge == outerStartEdge) { + // as of Mon Dec 20 2004, this has not been observed in vmap0 or vmap1 + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "rejecting hole in face " + << thisFaceId << " because inner ring " + << rngId + innerRingOffset + << " touches outer ring " << rngId << endl; + } + + innerRingOffset ++; + rowFaceId = rngTable.getColumnValueAsString( rngId + innerRingOffset, faceIdPosition ).toInt(); + continue; + } + + if(startEdge > 0 ) + { + ossimGeoPolygon holePolygon; + + readGeoPolygon( holePolygon, + thisFaceId, + startEdge, + edgTable ); + if(holePolygon.size()) + polygon.addHole( holePolygon ); + } + + innerRingOffset ++; + if (rngId + innerRingOffset <= rngTable.getNumberOfRows()) + rowFaceId = rngTable.getColumnValueAsString( rngId + innerRingOffset, faceIdPosition ).toInt(); + } + + readAttributes(polygon, table, idx + 1); // third parm is one-based row + + thePolyList.push_back(polygon); + } + } + } + } // each fac_id + } + ossimGeoAnnotationMultiPolyObject* annotation = new ossimGeoAnnotationMultiPolyObject(thePolyList); + annotation->setColor(thePenColor.getR(), + thePenColor.getG(), + thePenColor.getB()); + annotation->setThickness(theThickness); + annotation->setFillFlag(theFillEnabledFlag); + + theAnnotationArray.push_back(annotation); +} + +void ossimVpfAnnotationFeatureInfo::readAttributes(ossimGeoPolygon& polygon, ossimVpfTable& table, int row) { + int numCols = table.getNumberOfColumns(); + + for (int col = 0; col < numCols; col ++) { + ossimString s = table.getColumnValueAsString( row, col ); + polygon.addAttribute( s ); + } +} + +/* GET_XY */ +/*****************************************************************************/ +ossimDpt *ossimVpfAnnotationFeatureInfo::getXy(vpf_table_type table, + row_type row, + long pos, + long *count) +{ + long i; + ossimDpt *coord = NULL; + + switch (table.header[pos].type) + { + case 'C': + { + coordinate_type temp, *ptr; + ptr = (coordinate_type*)get_table_element(pos, row, table, &temp, count); + coord = new ossimDpt[*count]; + if ((*count == 1) && (ptr == (coordinate_type*)NULL)) + { + coord->x = (double)temp.x; + coord->y = (double)temp.y; + } + else + { + for (i=0; i<*count; i++) + { + coord[i].x = (double)ptr[i].x; + coord[i].y = (double)ptr[i].y; + } + } + if (ptr) + { + free((char *)ptr); + } + break; + } + case 'Z': + { + tri_coordinate_type temp, *ptr; + ptr = (tri_coordinate_type*)get_table_element (pos, row, table, &temp, count); + coord = new ossimDpt[*count]; + if ((*count == 1) && (ptr == (tri_coordinate_type*)NULL)) + { + coord->x = (double)temp.x; + coord->y = (double)temp.y; + } + else + { + for (i=0; i<*count; i++) + { + coord[i].x = (double)ptr[i].x; + coord[i].y = (double)ptr[i].y; + } + } + if (ptr) + { + free ((char*)ptr); + } + break; + } + case 'B': + { + double_coordinate_type temp, *ptr; + ptr = (double_coordinate_type*)get_table_element (pos, row, table, &temp, count); + coord = new ossimDpt[*count]; + if ((*count == 1) && (ptr == (double_coordinate_type*)NULL)) + { + coord->x = temp.x; + coord->y = temp.y; + } + else + { + for (i=0; i<*count; i++) + { + coord[i].x = ptr[i].x; + coord[i].y = ptr[i].y; + } + } + if (ptr) + { + free ((char*)ptr); + } + break; + } + case 'Y': + { + double_tri_coordinate_type temp, *ptr; + ptr = (double_tri_coordinate_type*)get_table_element (pos, row, table, &temp, count); + coord = new ossimDpt[*count]; + if ((*count == 1) && (ptr == (double_tri_coordinate_type*)NULL)) + { + coord->x = temp.x; + coord->y = temp.y; + } + else + { + for (i=0; i<*count; i++) + { + coord[i].x = ptr[i].x; + coord[i].y = ptr[i].y; + } + } + if (ptr) + { + free((char*)ptr); + } + break; + } + + default: + break; + } /* switch type */ + return (coord); +} + +int ossimVpfAnnotationFeatureInfo::readTableCellAsInt (int rowNumber, + int colNumber, + ossimVpfTable& table) +{ + int result = -1; + row_type row = read_row( rowNumber, *table.getVpfTableData()); + + result = table.getColumnValueAsString(row, colNumber).toInt(); + + free_row(row, *table.getVpfTableData()); + + return result; +} + +int ossimVpfAnnotationFeatureInfo::readRngId(int rowNumber, + int colNumber, + ossimVpfTable& faceTable) +{ + int idResult = -1; + row_type row = read_row( rowNumber, + *faceTable.getVpfTableData()); + + idResult = faceTable.getColumnValueAsString(row, + colNumber).toInt(); + + free_row(row, *faceTable.getVpfTableData()); + + return idResult; +} + +int ossimVpfAnnotationFeatureInfo::readStartEdgeId(int rowNumber, + int colNumber, + ossimVpfTable& rngTable) +{ + int idResult = -1; + + row_type row = read_row( rowNumber, + *rngTable.getVpfTableData()); + + idResult = rngTable.getColumnValueAsString(row, + colNumber).toInt(); + + free_row(row, *rngTable.getVpfTableData()); + + return idResult; + +} + +int ossimVpfAnnotationFeatureInfo::getEdgeKeyId (vpf_table_type& table, row_type& row, int col) { + id_triplet_type key; + long keyCount; + get_table_element( col, + row, + table, + & key, + & keyCount ); + return key.id; +} + +void ossimVpfAnnotationFeatureInfo::readGeoPolygon(ossimGeoPolygon& polygon, + int faceId, + int startEdgeId, + ossimVpfTable& edgTable) { + + ossim_int32 coordinatesCol = edgTable.getColumnPosition( "coordinates" ); + ossim_int32 startNodeCol = edgTable.getColumnPosition( "start_node" ); + ossim_int32 endNodeCol = edgTable.getColumnPosition( "end_node" ); + ossim_int32 rightEdgeCol = edgTable.getColumnPosition( "right_edge" ); + ossim_int32 leftEdgeCol = edgTable.getColumnPosition( "left_edge" ); + ossim_int32 rightFaceCol = edgTable.getColumnPosition( "right_face" ); + ossim_int32 leftFaceCol = edgTable.getColumnPosition( "left_face" ); + + // collect edges + vector < int > edges; + int lastEdge = startEdgeId; + edges.push_back( lastEdge ); + + row_type row = read_row( startEdgeId, *edgTable.getVpfTableData() ); + int startNode = edgTable.getColumnValueAsString( row, startNodeCol ).toInt(); + int endNode = edgTable.getColumnValueAsString( row, endNodeCol ).toInt(); + + if (startNode != endNode) { // there's more than one edge to this ring + int rightFace = getEdgeKeyId( *edgTable.getVpfTableData(), row, rightFaceCol ); + int leftFace = getEdgeKeyId( *edgTable.getVpfTableData(), row, leftFaceCol ); + int rightEdge = getEdgeKeyId( *edgTable.getVpfTableData(), row, rightEdgeCol ); + int leftEdge = getEdgeKeyId( *edgTable.getVpfTableData(), row, leftEdgeCol ); + int nextEdge; + int firstNode, lastNode; + + if (rightFace == leftFace) { + if (rightEdge == leftEdge) { + free_row(row, *edgTable.getVpfTableData()); + // as of Mon Dec 20 2004, this has not been observed in vmap0 or vmap1 + // cout << "rejecting floating line face " << faceId << " line " << __LINE__ << endl; + return; + } + + // this is a dangling start edge; find a non dangling edge to use as the start edge + int dirRight = 1; + int nextEdge = startEdgeId; + int nextLeftFace = leftFace; + int nextRightFace = rightFace; + int mobiusLimit = 1000; + + while (nextLeftFace == nextRightFace) { + if (-- mobiusLimit < 0) { + free_row(row, *edgTable.getVpfTableData()); + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "rejecting mobius face " << faceId << " line " << __LINE__ << endl; + } + return; + } + + int thisEdge = nextEdge; + if (dirRight) { + nextEdge = getEdgeKeyId( *edgTable.getVpfTableData(), row, rightEdgeCol ); + if (nextEdge == thisEdge) + dirRight = 0; + else if (nextEdge == startEdgeId) { + free_row(row, *edgTable.getVpfTableData()); + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "rejecting mobius face " << faceId << " line " << __LINE__ << endl; + } + return; + } + } else { + nextEdge = getEdgeKeyId( *edgTable.getVpfTableData(), row, leftEdgeCol ); + if (nextEdge == thisEdge) { + free_row(row, *edgTable.getVpfTableData()); + // as of Mon Dec 20 2004, this has not been observed in vmap0 or vmap1 + // cout << "rejecting multi floating line face " << faceId << " line " << __LINE__ << endl; + return; + } else if (nextEdge == startEdgeId) { + free_row(row, *edgTable.getVpfTableData()); + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "rejecting mobius face " << faceId << " line " << __LINE__ << endl; + } + return; + } + } + free_row(row, *edgTable.getVpfTableData()); + row = read_row( nextEdge, *edgTable.getVpfTableData() ); + nextRightFace = getEdgeKeyId( *edgTable.getVpfTableData(), row, rightFaceCol ); + nextLeftFace = getEdgeKeyId( *edgTable.getVpfTableData(), row, leftFaceCol ); + } + + startEdgeId = nextEdge; + rightFace = nextRightFace; + leftFace = nextLeftFace; + free_row(row, *edgTable.getVpfTableData()); + row = read_row( startEdgeId, *edgTable.getVpfTableData() ); + startNode = edgTable.getColumnValueAsString( row, startNodeCol ).toInt(); + endNode = edgTable.getColumnValueAsString( row, endNodeCol ).toInt(); + } + + if (rightFace == faceId) { + nextEdge = getEdgeKeyId( *edgTable.getVpfTableData(), row, rightEdgeCol ); + firstNode = startNode; + lastNode = endNode; + } else if (leftFace == faceId) { + nextEdge = getEdgeKeyId( *edgTable.getVpfTableData(), row, leftEdgeCol ); + firstNode = endNode; + lastNode = startNode; + } + else + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "rejecting face " << faceId << " line " << __LINE__ << endl; + } + return; + } + + row_type nextRow; + while (true) { + nextRow = read_row( nextEdge, *edgTable.getVpfTableData() ); + int nextLeftEdge = getEdgeKeyId( *edgTable.getVpfTableData(), nextRow, leftEdgeCol ); + int nextRightEdge = getEdgeKeyId( *edgTable.getVpfTableData(), nextRow, rightEdgeCol ); + int nextLeftFace = getEdgeKeyId( *edgTable.getVpfTableData(), nextRow, leftFaceCol ); + int nextRightFace = getEdgeKeyId( *edgTable.getVpfTableData(), nextRow, rightFaceCol ); + int nextStartNode = edgTable.getColumnValueAsString( nextRow, startNodeCol ).toInt(); + int nextEndNode = edgTable.getColumnValueAsString( nextRow, endNodeCol ).toInt(); + + while (nextLeftFace == nextRightFace) { + int lastEnd; + if (rightFace == faceId) + lastEnd = edgTable.getColumnValueAsString( row, endNodeCol ).toInt(); + else + lastEnd = edgTable.getColumnValueAsString( row, startNodeCol ).toInt(); + + if (lastEnd == nextStartNode) + nextEdge = nextLeftEdge; + else if (lastEnd == nextEndNode) + nextEdge = nextRightEdge; + else { // bad face + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "rejecting face " << faceId << " line " << __LINE__ << endl; + } + return; + } + if (lastEdge == nextEdge) + { // bad face + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "rejecting face " << faceId << " line " << __LINE__ << endl; + } + return; + } + + free_row(nextRow, *edgTable.getVpfTableData()); + nextRow = read_row( nextEdge, *edgTable.getVpfTableData() ); + nextLeftEdge = getEdgeKeyId( *edgTable.getVpfTableData(), nextRow, leftEdgeCol ); + nextRightEdge = getEdgeKeyId( *edgTable.getVpfTableData(), nextRow, rightEdgeCol ); + nextLeftFace = getEdgeKeyId( *edgTable.getVpfTableData(), nextRow, leftFaceCol ); + nextRightFace = getEdgeKeyId( *edgTable.getVpfTableData(), nextRow, rightFaceCol ); + nextStartNode = edgTable.getColumnValueAsString( nextRow, startNodeCol ).toInt(); + nextEndNode = edgTable.getColumnValueAsString( nextRow, endNodeCol ).toInt(); + } + + lastEdge = nextEdge; + edges.push_back( lastEdge ); + + { + int lastEnd; + if (nextRightFace == faceId) { + if (lastNode != nextStartNode) { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "rejecting face " << faceId << " line " << __LINE__ << endl; + } + return; + } + lastEnd = nextEndNode; + } else if (nextLeftFace == faceId) { + if (lastNode != nextEndNode) { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "rejecting face " << faceId << " line " << __LINE__ << endl; + } + return; + } + lastEnd = nextStartNode; + } else { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "rejecting face " << faceId << " line " << __LINE__ << endl; + } + return; + } + + if (lastEnd == firstNode) + break; + } + + free_row(row, *edgTable.getVpfTableData()); + row = nextRow; + startNode = nextStartNode; + endNode = nextEndNode; + rightFace = nextRightFace; + leftFace = nextLeftFace; + + if (rightFace == faceId) { + nextEdge = nextRightEdge; + lastNode = endNode; + } else { + nextEdge = nextLeftEdge; + lastNode = startNode; + } + } + + free_row(nextRow, *edgTable.getVpfTableData()); + nextRow = 0; + } + + for (vector< int >::iterator i = edges.begin(); i != edges.end(); i++) { + long count = 0; + free_row(row, *edgTable.getVpfTableData()); + row = read_row( *i, *edgTable.getVpfTableData() ); + ossimDpt* ptArray = getXy(*edgTable.getVpfTableData(), + row, + coordinatesCol, + &count); + + if(ptArray) + { + int rightFace = getEdgeKeyId( *edgTable.getVpfTableData(), row, rightFaceCol ); + + if (rightFace == faceId) { + for(int p = 0; p < count; ++p) + { + if((fabs(ptArray[p].x) <= 180.0)&& + (fabs(ptArray[p].y) <= 90.0)) + { + polygon.addPoint(ptArray[p].y, ptArray[p].x); + } + } + } else { + for(int p = count - 1; p >= 0; --p) + { + if((fabs(ptArray[p].x) <= 180.0)&& + (fabs(ptArray[p].y) <= 90.0)) + { + polygon.addPoint(ptArray[p].y, ptArray[p].x); + } + } + } + delete [] ptArray; + } + } + free_row(row, *edgTable.getVpfTableData()); +} + +void ossimVpfAnnotationFeatureInfo::readEdge(ossimPolyLine& polyLine, + int rowNumber, + int colPosition, + ossimVpfTable& edgeTable) +{ + polyLine.clear(); + row_type row = read_row( rowNumber, + *edgeTable.getVpfTableData()); + + long count = 0; + ossimDpt* ptArray = getXy(*edgeTable.getVpfTableData(), + row, + colPosition, + &count); + + if(ptArray) + { + for(int i = 0; i < count; ++i) + { + if((fabs(ptArray[i].x) <= 180.0)&& + (fabs(ptArray[i].y) <= 90.0)) + { + polyLine.addPoint(ossimDpt(ptArray[i].x, + ptArray[i].y)); + } + } + delete [] ptArray; + } + free_row(row, *edgeTable.getVpfTableData()); +} + + diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationFeatureInfo.h b/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationFeatureInfo.h new file mode 100644 index 0000000000..700aa574e8 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationFeatureInfo.h @@ -0,0 +1,218 @@ +#ifndef ossimVpfAnnotationFeatureInfo_HEADER +#define ossimVpfAnnotationFeatureInfo_HEADER +#include "base/data_types/color_space/ossimRgbVector.h" +#include "base/data_types/ossimString.h" +#include "base/data_types/ossimGeoPolygon.h" +#include "imaging/annotation/ossimGeoAnnotationObject.h" +#include "vec/vpf/ossimVpfCoverage.h" +#include "base/common/ossimFontInformation.h" + +class ossimGeoAnnotationObject; +class ossimVpfCoverage; +class ossimVpfFeatureClassSchema; +class ossimPolyLine; + +class OSSIMDLLEXPORT ossimVpfAnnotationFeatureInfo : public ossimObject +{ +public: + enum ossimVpfAnnotationFeatureType + { + ossimVpfAnnotationFeatureType_UNKNOWN = 0, + ossimVpfAnnotationFeatureType_POINT = 1, + ossimVpfAnnotationFeatureType_LINE = 2, + ossimVpfAnnotationFeatureType_POLYGON = 3, + ossimVpfAnnotationFeatureType_TEXT = 4, + }; + + ossimVpfAnnotationFeatureInfo(const ossimString& featureName = "", + const ossimRgbVector& penColor = ossimRgbVector(255,255,255), + const ossimRgbVector& brushColor = ossimRgbVector(255,255,255), + const ossimDpt& pointRadius=ossimDpt(1,1), + int thickness=0, + bool enabledFlag = true); + ossimVpfAnnotationFeatureInfo::~ossimVpfAnnotationFeatureInfo(); + + void setCoverage(const ossimVpfCoverage& coverage) + { + theCoverage = coverage; + } + + const ossimVpfCoverage& getCoverage()const + { + return theCoverage; + } + ossimVpfCoverage& getCoverage() + { + return theCoverage; + } + + void setColor(const ossimRgbVector& color) + { + setPenColor(color); + setBrushColor(color); + } + void setPenColor(const ossimRgbVector& penColor) + { + thePenColor = penColor; + } + + ossimRgbVector getPenColor()const + { + return thePenColor; + } + + void setBrushColor(const ossimRgbVector& brushColor) + { + theBrushColor = brushColor; + } + + ossimRgbVector getBrushColor()const + { + return theBrushColor; + } + + void setFillEnabledFlag(bool flag) + { + theFillEnabledFlag = flag; + } + bool getFillEnabledFlag()const + { + return theFillEnabledFlag; + } + void setEnabledFlag(bool flag); + bool getEnabledFlag()const + { + return theEnabledFlag; + } + + void setThickness(int thickness) + { + theThickness = thickness; + } + + int getThickness()const + { + return theThickness; + } + + void setName(const ossimString& name) + { + theName = name; + } + const ossimString& getName()const + { + return theName; + } + + bool isPoint()const + { + return (theFeatureType == ossimVpfAnnotationFeatureType_POINT); + } + bool isLine()const + { + return (theFeatureType == ossimVpfAnnotationFeatureType_LINE); + } + bool isPolygon()const + { + return (theFeatureType == ossimVpfAnnotationFeatureType_POLYGON); + } + bool isText()const + { + return (theFeatureType == ossimVpfAnnotationFeatureType_TEXT); + } + void getFontInformation(ossimFontInformation& fontInfo)const + { + fontInfo = theFontInformation; + } + void setFontInformation(const ossimFontInformation& fontInfo) + { + theFontInformation = fontInfo; + } + + void setPointRadius(const ossimDpt& radius) + { + thePointRadius = radius; + } + ossimDpt getPointRadius()const + { + return thePointRadius; + } + void setDrawingFeaturesToAnnotation(); + ossimIrect getBoundingProjectedRect()const; + void transform(ossimProjection* proj); + void buildFeature(); + void deleteAllObjects(); + void drawAnnotations(ossimRgbImage* tile); + + bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + ossimString getFeatureTypeAsString()const; + ossimVpfAnnotationFeatureType getFeatureTypeFromString(const ossimString& featureType)const; + +private: + void readAttributes(ossimPolyLine& polyLine, ossimVpfTable& table, int row); + void readAttributes(ossimGeoPolygon& polygon, ossimVpfTable& table, int row); + +protected: + ossimString theName; + ossimString theDescription; + ossimRgbVector thePenColor; + ossimRgbVector theBrushColor; + ossimVpfCoverage theCoverage; + ossimDpt thePointRadius; + int theThickness; + bool theFillEnabledFlag; + bool theEnabledFlag; + ossimVpfAnnotationFeatureType theFeatureType; + ossimFontInformation theFontInformation; + + std::vector<ossimGeoAnnotationObject*> theAnnotationArray; + + void buildTxtFeature(const ossimFilename& table, + const ossimString& tableKey, + const ossimFilename& primitive, + const ossimString& primitiveKey); + + void buildEdgFeature(const ossimFilename& table, + const ossimString& tableKey, + const ossimFilename& primitive, + const ossimString& primitiveKey); + + void buildPointFeature(const ossimString& primitiveName, + const ossimFilename& table, + const ossimString& tableKey, + const ossimFilename& primitive, + const ossimString& primitiveKey); + void buildFaceFeature(const ossimFilename& table, + const ossimString& tableKey, + const ossimFilename& primitive, + const ossimString& primitiveKey); + + + void readEdge(ossimPolyLine& polyLine, + int rowNumber, + int colPosition, + ossimVpfTable& edgeTable); + int readTableCellAsInt (int rowNumber, // should replace calls to readRngId, readStartEdgeId with this + int colNumber, + ossimVpfTable& table); + int readRngId(int rowNumber, + int colNumber, + ossimVpfTable& faceTable); + int readStartEdgeId(int rowNumber, + int colNumber, + ossimVpfTable& rngTable); + void readGeoPolygon(ossimGeoPolygon& polygon, + int faceId, + int startEdgeId, + ossimVpfTable& edgTable); + + ossimDpt* getXy(vpf_table_type table, row_type row, long pos, long* count); + int getEdgeKeyId (vpf_table_type& table, row_type& row, int col); + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationLibraryInfo.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationLibraryInfo.cpp new file mode 100644 index 0000000000..8fe71c8129 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationLibraryInfo.cpp @@ -0,0 +1,260 @@ +//************************************************************************* +// Copyright (C) 2004 Intelligence Data Systems, Inc. All rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************** +// $Id: ossimVpfAnnotationLibraryInfo.cpp,v 1.12 2004/12/21 20:12:40 gpotts Exp $ + +#include <algorithm> + +#include <imaging/formats/vpf/ossimVpfAnnotationLibraryInfo.h> +#include <imaging/formats/vpf/ossimVpfAnnotationFeatureInfo.h> +#include <vec/vpf/ossimVpfLibrary.h> +#include <vec/vpf/ossimVpfDatabase.h> +#include <base/common/ossimTrace.h> + +static ossimTrace traceDebug("ossimVpfAnnotationLibraryInfo:debug"); + + +ossimVpfAnnotationLibraryInfo::ossimVpfAnnotationLibraryInfo(const ossimString& libraryName, bool enabledFlag) + : + theName(libraryName), + theEnabledFlag(enabledFlag), + theDatabase(NULL) +{ +} + +ossimVpfAnnotationLibraryInfo::~ossimVpfAnnotationLibraryInfo() +{ + deleteAllCoverage(); +} + +bool ossimVpfAnnotationLibraryInfo::getEnabledFlag()const +{ + return theEnabledFlag; +} + +void ossimVpfAnnotationLibraryInfo::setEnabledFlag(bool flag) +{ + theEnabledFlag = flag; +} + +const ossimString& ossimVpfAnnotationLibraryInfo::getName()const +{ + return theName; +} + +void ossimVpfAnnotationLibraryInfo::setName(const ossimString& libraryName) +{ + theName = libraryName; +} + +void ossimVpfAnnotationLibraryInfo::setDatabase(ossimVpfDatabase* database) +{ + theDatabase = database; +} + +ossimVpfDatabase* ossimVpfAnnotationLibraryInfo::getDatabase() +{ + return theDatabase; +} + +ossimIrect ossimVpfAnnotationLibraryInfo::getBoundingProjectedRect()const +{ + ossimIrect result; + result.makeNan(); + + for(ossim_uint32 idx = 0; idx < theCoverageLayerList.size(); ++idx) + { + ossimIrect tempRect = theCoverageLayerList[idx]->getBoundingProjectedRect(); + if(!tempRect.hasNans()) + { + if(result.hasNans()) + { + result = tempRect; + } + else + { + result = result.combine(tempRect); + } + } + } + + return result; +} + +void ossimVpfAnnotationLibraryInfo::getAllFeatures(std::vector<ossimVpfAnnotationFeatureInfo*>& features) +{ + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimVpfAnnotationLibraryInfo::getAllFeatures DEBUG: entered..." << std::endl; + } + + for(ossim_uint32 idx = 0; idx < theCoverageLayerList.size(); ++idx) + { + theCoverageLayerList[idx]->getAllFeatures(features); + } + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimVpfAnnotationLibraryInfo::getAllFeatures DEBUG: leaving..." << std::endl; + } +} + +void ossimVpfAnnotationLibraryInfo::transform(ossimProjection* proj) +{ + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimVpfAnnotationLibraryInfo::transform DEBUG: entered..." << std::endl; + } + + + for(ossim_uint32 idx = 0; idx < theCoverageLayerList.size(); ++idx) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "transforming coverage = " << theCoverageLayerList[idx]->getName() << std::endl; + } + + theCoverageLayerList[idx]->transform(proj); + } + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimVpfAnnotationLibraryInfo::transform DEBUG: leaving..." << std::endl; + } +} + +void ossimVpfAnnotationLibraryInfo::buildLibrary() +{ + buildLibrary( "", ""); +} + +void ossimVpfAnnotationLibraryInfo::buildLibrary(const ossimString& coverageName, const ossimString& feature) +{ + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimVpfAnnotationLibraryInfo::buildLibrary DEBUG: entered..." << std::endl; + } + deleteAllCoverage(); + if(!theDatabase) + { + return; + } + + ossimVpfLibrary* library = theDatabase->getLibrary(theName); + if(library) + { + std::vector<ossimString> coverageNames; + library->getCoverageNames(coverageNames); + for(ossim_uint32 idx = 0; idx < coverageNames.size(); ++idx) + { + ossimString s1 = coverageName; + ossimString s2 = coverageNames[idx]; + s1.downcase(); + s2.downcase(); + if ( ! coverageName.length() || (s1 == s2) ) + { + ossimVpfAnnotationCoverageInfo* coverageInfo = + new ossimVpfAnnotationCoverageInfo; + coverageInfo->setName(coverageNames[idx]); + coverageInfo->setLibrary(library); + theCoverageLayerList.push_back(coverageInfo); + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "coverage name = " << coverageNames[idx] << std::endl; + } + coverageInfo->buildCoverage(feature); + } + } + } + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimVpfAnnotationLibraryInfo::buildLibrary DEBUG: leaving..." << std::endl; + } +} + + +void ossimVpfAnnotationLibraryInfo::drawAnnotations(ossimRgbImage* tile) +{ + for(ossim_uint32 idx = 0; idx < theCoverageLayerList.size(); ++idx) + { + theCoverageLayerList[idx]->drawAnnotations(tile); + } +} + +void ossimVpfAnnotationLibraryInfo::deleteAllCoverage() +{ + for(ossim_uint32 idx = 0; idx < theCoverageLayerList.size(); ++idx) + { + delete theCoverageLayerList[idx]; + } + + theCoverageLayerList.clear(); +} + +bool ossimVpfAnnotationLibraryInfo::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + ossim_uint32 idx; + + kwl.add(prefix, + "name", + theName, + true); + + for(idx = 0; idx < theCoverageLayerList.size(); ++idx) + { + theCoverageLayerList[idx]->saveState(kwl, + (ossimString(prefix) + "coverage" + ossimString::toString(idx) + ".").c_str()); + } + + return true; +} + +bool ossimVpfAnnotationLibraryInfo::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + deleteAllCoverage(); + theName = kwl.find(prefix, "name"); + + ossimVpfLibrary* library = theDatabase->getLibrary(theName); + + if(!library) + { + return false; + } + ossimString regExpression = ossimString("^(") + ossimString(prefix) + "coverage[0-9]+.)"; + vector<ossimString> keys = + kwl.getSubstringKeyList( regExpression ); + std::vector<int> theNumberList(keys.size()); + int offset = (ossimString(prefix)+"coverage").size(); + int idx = 0; + for(idx = 0; idx < (int)theNumberList.size();++idx) + { + ossimString numberStr(keys[idx].begin() + offset, + keys[idx].end()); + theNumberList[idx] = numberStr.toInt(); + } + std::sort(theNumberList.begin(), theNumberList.end()); + + for(idx = 0; idx < (int)keys.size(); ++idx) + { + ossimString newPrefix = ossimString(prefix); + newPrefix += ossimString("coverage"); + newPrefix += ossimString::toString(theNumberList[idx]); + newPrefix += ossimString("."); + ossimVpfAnnotationCoverageInfo* coverageInfo = new ossimVpfAnnotationCoverageInfo; + coverageInfo->setLibrary(library); + theCoverageLayerList.push_back(coverageInfo); + coverageInfo->loadState(kwl, + newPrefix); + } + + return true; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationLibraryInfo.h b/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationLibraryInfo.h new file mode 100644 index 0000000000..a9bf66a48e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationLibraryInfo.h @@ -0,0 +1,52 @@ +#ifndef ossimVpfAnnotationLibraryInfo_HEADER +#define ossimVpfAnnotationLibraryInfo_HEADER +#include <map> +#include "base/data_types/ossimString.h" +#include "ossimVpfAnnotationCoverageInfo.h" + +class ossimVpfDatabase; +class ossimRgbImage; +class ossimVpfAnnotationFeatureInfo; + +class OSSIMDLLEXPORT ossimVpfAnnotationLibraryInfo +{ +public: + ossimVpfAnnotationLibraryInfo(const ossimString& libraryName = "", + bool enabledFlag=true); + + virtual ~ossimVpfAnnotationLibraryInfo(); + + bool getEnabledFlag()const; + + void setEnabledFlag(bool flag); + + const ossimString& getName()const; + + void setName(const ossimString& libraryName); + + void setDatabase(ossimVpfDatabase* database); + + ossimVpfDatabase* getDatabase(); + + ossimIrect getBoundingProjectedRect()const; + + void transform(ossimProjection* proj); + void buildLibrary(); + void buildLibrary(const ossimString& coverageName, const ossimString& feature); + void deleteAllCoverage(); + void drawAnnotations(ossimRgbImage* tile); + void getAllFeatures(std::vector<ossimVpfAnnotationFeatureInfo*>& features); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +protected: + ossimString theName; + bool theEnabledFlag; + ossimVpfDatabase* theDatabase; + std::vector<ossimVpfAnnotationCoverageInfo*> theCoverageLayerList; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationSource.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationSource.cpp new file mode 100644 index 0000000000..2e3819922d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationSource.cpp @@ -0,0 +1,267 @@ +#include <algorithm> + +#include <imaging/formats/vpf/ossimVpfAnnotationSource.h> +#include <imaging/formats/vpf/ossimVpfAnnotationLibraryInfo.h> +#include <vec/vpf/ossimVpfExtent.h> +#include <projections/map_projections/ossimEquDistCylProjection.h> +#include <imaging/ossimRgbImage.h> +#include <imaging/ossimU8ImageData.h> +#include <base/common/ossimTrace.h> +#include <base/common/ossimKeywordNames.h> + +static ossimTrace traceDebug("ossimVpfAnnotationSource:debug"); + +ossimVpfAnnotationSource::ossimVpfAnnotationSource() + :ossimGeoAnnotationSource() +{ + if(!theProjection) + { + theProjection = new ossimEquDistCylProjection; + theOwnsProjectionFlag = true; + } + ossimMapProjection* mapProj = (ossimMapProjection*) theProjection; + + if(mapProj) + { + mapProj->setMetersPerPixel(ossimDpt(30, 30)); + } +} + +ossimVpfAnnotationSource::~ossimVpfAnnotationSource() +{ + close(); +} + +bool ossimVpfAnnotationSource::open(const ossimFilename& file) +{ + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimVpfAnnotationSource::open DEBUG: entering..." << std::endl; + } + bool result = false; + + if(file.file().downcase() == "dht") + { + if(openDatabase(file)) + { + vector<ossimString> libraryNames = theDatabase.getLibraryNames(); + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "Library names list size = " << libraryNames.size() << std::endl; + } + + for(int idx = 0; idx < (int)libraryNames.size();++idx) + { + ossimVpfAnnotationLibraryInfo* info = new ossimVpfAnnotationLibraryInfo; + info->setName(libraryNames[idx]); + theLibraryInfo.push_back(info); + info->setDatabase(&theDatabase); + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "loading library " << libraryNames[idx] << std::endl; + } + info->buildLibrary(); + info->getAllFeatures(theFeatureList); + } + transformObjects(); + result = true; + } + } + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimVpfAnnotationSource::open DEBUG: leaving..." << std::endl; + } + return result; +} + +void ossimVpfAnnotationSource::close() +{ + theDatabase.closeDatabase(); + for(int idx = 0; idx < (int)theLibraryInfo.size(); ++idx) + { + delete theLibraryInfo[idx]; + } + + theLibraryInfo.clear(); +} + +ossimFilename ossimVpfAnnotationSource::getFilename()const +{ + return theFilename; +} + +void ossimVpfAnnotationSource::transformObjects(ossimProjection* projection) +{ + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimVpfAnnotationSource::transformObjects DEBUG: entered..." << std::endl; + } + ossimProjection* proj = projection; + + if(!proj) + { + proj = theProjection; + } + + if(!proj) return; + for(int idx = 0; idx < (int)theLibraryInfo.size(); ++idx) + { + theLibraryInfo[idx]->transform(proj); + } + computeBoundingRect(); + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimVpfAnnotationSource::transformObjects DEBUG: leaving..." << std::endl; + } +} + +void ossimVpfAnnotationSource::computeBoundingRect() + +{ + ossimIrect result; + result.makeNan(); + for(int i = 0; i < (int)theLibraryInfo.size();++i) + { + ossimIrect tempRect = theLibraryInfo[i]->getBoundingProjectedRect(); + if(!tempRect.hasNans()) + { + if(result.hasNans()) + { + result = tempRect; + } + else + { + result = result.combine(tempRect); + } + } + } + + theRectangle = result; +} + + +void ossimVpfAnnotationSource::deleteAllLibraries() +{ + for(int idx = 0; idx < (int)theLibraryInfo.size();++idx) + { + delete theLibraryInfo[idx]; + } + + theLibraryInfo.clear(); +} + +void ossimVpfAnnotationSource::getAllFeatures(std::vector<ossimVpfAnnotationFeatureInfo*>& features) +{ + features = theFeatureList; +} + +void ossimVpfAnnotationSource::setAllFeatures(const std::vector<ossimVpfAnnotationFeatureInfo*>& features) +{ + theFeatureList = features; + + computeBoundingRect(); + +} + + +void ossimVpfAnnotationSource::drawAnnotations(ossimRefPtr<ossimImageData> tile) +{ + theImage->setCurrentImageData(tile); + if(theImage->getImageData().valid()) + { + for(ossim_uint32 idx = 0; idx < theFeatureList.size();++idx) + { + if(theFeatureList[idx]->getEnabledFlag()) + { + theFeatureList[idx]->drawAnnotations(theImage); + } + } + } +} + +bool ossimVpfAnnotationSource::openDatabase(const ossimFilename& file) +{ + ossimAnnotationSource::deleteAll(); + deleteAllLibraries(); + theFeatureList.clear(); + if(theDatabase.isOpened()) + { + theDatabase.closeDatabase(); + } + + theFilename = file; + return theDatabase.openDatabase(file); +} + + +bool ossimVpfAnnotationSource::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + ossimKeywordNames::FILENAME_KW, + theFilename, + true); + for(ossim_uint32 idx = 0; idx < theLibraryInfo.size(); ++idx) + { + theLibraryInfo[idx]->saveState(kwl, + (ossimString(prefix) + "library" + ossimString::toString(idx) + ".").c_str()); + } + return true; +} + +bool ossimVpfAnnotationSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + bool result = false; + deleteAllLibraries(); + const char* filename = kwl.find(prefix, ossimKeywordNames::FILENAME_KW); + if(filename) + { + if(openDatabase(filename)) + { + int idx = 0; + ossimString regExpression = ossimString("^(") + ossimString(prefix) + "library[0-9]+.)"; + vector<ossimString> keys = + kwl.getSubstringKeyList( regExpression ); + std::vector<int> theNumberList(keys.size()); + int offset = (ossimString(prefix)+"library").size(); + + for(idx = 0; idx < (int)theNumberList.size();++idx) + { + ossimString numberStr(keys[idx].begin() + offset, + keys[idx].end()); + theNumberList[idx] = numberStr.toInt(); + } + std::sort(theNumberList.begin(), theNumberList.end()); + + for(idx=0;idx < (int)keys.size();++idx) + { + ossimString newPrefix = ossimString(prefix); + newPrefix += ossimString("library"); + newPrefix += ossimString::toString(theNumberList[idx]); + newPrefix += ossimString("."); + + ossimVpfAnnotationLibraryInfo* info = new ossimVpfAnnotationLibraryInfo; + theLibraryInfo.push_back(info); + info->setDatabase(&theDatabase); + info->loadState(kwl, + newPrefix); + info->getAllFeatures(theFeatureList); + } + transformObjects(); + result = true; + } + } + + return result; +} + +bool ossimVpfAnnotationSource::open() +{ + return open(theFilename); +} + +bool ossimVpfAnnotationSource::isOpen()const +{ + return (theDatabase.isOpened()); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationSource.h b/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationSource.h new file mode 100644 index 0000000000..b3631e8497 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfAnnotationSource.h @@ -0,0 +1,45 @@ +#ifndef ossimVpfAnnotationSource_HEADER +#define ossimVpfAnnotationSource_HEADER +#include "vec/vpf/ossimVpfDatabase.h" +#include "imaging/formats/ossimImageHandler.h" +#include "base/data_types/ossimIrect.h" +#include "imaging/annotation/ossimGeoAnnotationSource.h" +#include "projections/ossimProjection.h" +#include "ossimVpfAnnotationLibraryInfo.h" +class ossimVpfAnnotationFeatureInfo; +class ossimVpfAnnotationSource : public ossimGeoAnnotationSource +{ +public: + ossimVpfAnnotationSource(); + virtual ~ossimVpfAnnotationSource(); + virtual bool open(); + virtual bool open(const ossimFilename& file); + virtual bool isOpen()const; + + virtual void close(); + virtual ossimFilename getFilename()const; + virtual void computeBoundingRect(); + + virtual void transformObjects(ossimProjection* projection=0); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=NULL)const; + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=NULL); + + virtual void drawAnnotations(ossimRefPtr<ossimImageData> tile); + virtual void getAllFeatures(std::vector<ossimVpfAnnotationFeatureInfo*>& features); + virtual void setAllFeatures(const std::vector<ossimVpfAnnotationFeatureInfo*>& features); + +protected: + ossimVpfDatabase theDatabase; + ossimFilename theFilename; + std::vector<ossimVpfAnnotationLibraryInfo*> theLibraryInfo; + std::vector<ossimVpfAnnotationFeatureInfo*> theFeatureList; + + void deleteAllLibraries(); + bool openDatabase(const ossimFilename& file); +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfTileSource.cpp b/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfTileSource.cpp new file mode 100644 index 0000000000..b4de266425 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfTileSource.cpp @@ -0,0 +1,217 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2004 Garrett Potts, all rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +// $Id: ossimVpfTileSource.cpp,v 1.9 2005/02/11 15:07:32 dburken Exp $ +//---------------------------------------------------------------------------- +#include "ossimVpfTileSource.h" + +RTTI_DEF2(ossimVpfTileSource, "ossimVpfTileSource", ossimImageHandler, ossimViewInterface); + +ossimVpfTileSource::ossimVpfTileSource() + : + ossimViewInterface() +{ + theObject = this; + theAnnotationSource = new ossimVpfAnnotationSource; + theAnnotationSource->setNumberOfBands(3); +} + +ossimVpfTileSource::~ossimVpfTileSource() +{ + if(theAnnotationSource) + { + delete theAnnotationSource; + theAnnotationSource = NULL; + } +} + +bool ossimVpfTileSource::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + return theAnnotationSource->saveState(kwl, prefix); +} + +bool ossimVpfTileSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + return theAnnotationSource->loadState(kwl, prefix); +} + +void ossimVpfTileSource::close() +{ + theAnnotationSource->close(); +} + +bool ossimVpfTileSource::open() +{ + return theAnnotationSource->open(theImageFile); +} + +ossimRefPtr<ossimImageData> ossimVpfTileSource::getTile( + const ossimIrect& tileRect, ossim_uint32 resLevel) +{ + return theAnnotationSource->getTile(tileRect, resLevel); +} + +ossim_uint32 ossimVpfTileSource::getNumberOfInputBands() const +{ + return theAnnotationSource->getNumberOfOutputBands(); +} + +ossim_uint32 ossimVpfTileSource::getNumberOfOutputBands() const +{ + return theAnnotationSource->getNumberOfOutputBands(); +} + +ossim_uint32 ossimVpfTileSource::getNumberOfLines(ossim_uint32 /* reduced_res_level */) const +{ + ossimIrect theBounds = theAnnotationSource->getBoundingRect(); + + if(theBounds.hasNans()) + { + return theBounds.ul().x; + } + + return theBounds.height(); +} + +ossim_uint32 ossimVpfTileSource::getNumberOfSamples(ossim_uint32 /* reduced_res_level */) const +{ + ossimIrect theBounds = theAnnotationSource->getBoundingRect(); + + if(theBounds.hasNans()) + { + return theBounds.ul().x; + } + + return theBounds.height(); +} + +ossim_uint32 ossimVpfTileSource::getNumberOfDecimationLevels() const +{ + return 32; +} + +ossimIrect ossimVpfTileSource::getImageRectangle(ossim_uint32 /* reduced_res_level */) const +{ + return theAnnotationSource->getBoundingRect(); +} + +bool ossimVpfTileSource::getImageGeometry(ossimKeywordlist& kwl, + const char* prefix) +{ + if (theGeometryKwl.getSize()) + { + kwl = theGeometryKwl; + return true; + } + + ossimObject* view = theAnnotationSource->getView(); + if(view) + { + bool result = view->saveState(kwl, prefix); + if (result) + { + // Capture for next time... + setImageGeometry(kwl); + } + return result; + } + + return false; +} + +ossimScalarType ossimVpfTileSource::getOutputScalarType() const +{ + return theAnnotationSource->getOutputScalarType(); +} + +ossim_uint32 ossimVpfTileSource::getTileWidth() const +{ + return theAnnotationSource->getTileWidth(); +} + +ossim_uint32 ossimVpfTileSource::getTileHeight() const +{ + return theAnnotationSource->getTileHeight(); +} + +ossim_uint32 ossimVpfTileSource::getImageTileWidth() const +{ + return 0; +} + +ossim_uint32 ossimVpfTileSource::getImageTileHeight() const +{ + return 0; +} + +bool ossimVpfTileSource::isOpen()const +{ + return theAnnotationSource->isOpen(); +} + +double ossimVpfTileSource::getNullPixelValue(ossim_uint32 band)const +{ + return theAnnotationSource->getNullPixelValue(band); +} + +double ossimVpfTileSource::getMinPixelValue(ossim_uint32 band)const +{ + return theAnnotationSource->getMinPixelValue(band); +} + +double ossimVpfTileSource::getMaxPixelValue(ossim_uint32 band)const +{ + return theAnnotationSource->getMaxPixelValue(band); +} + +ossimObject* ossimVpfTileSource::getView() +{ + return theAnnotationSource->getView(); +} + +const ossimObject* ossimVpfTileSource::getView()const +{ + return theAnnotationSource->getView(); +} + +bool ossimVpfTileSource::setView(ossimObject* baseObject, + bool ownsTheView) +{ + return theAnnotationSource->setView(baseObject, ownsTheView); +} + +void ossimVpfTileSource::getAllFeatures(std::vector<ossimVpfAnnotationFeatureInfo*>& featureList) +{ + if(theAnnotationSource) + { + theAnnotationSource->getAllFeatures(featureList); + } +} + +void ossimVpfTileSource::setAllFeatures(std::vector<ossimVpfAnnotationFeatureInfo*>& featureList) +{ + if(theAnnotationSource) + { + theAnnotationSource->setAllFeatures(featureList); + } +} + +void ossimVpfTileSource::transformObjects() +{ + theAnnotationSource->transformObjects(); +} + +void ossimVpfTileSource::computeBoundingRect() +{ + theAnnotationSource->computeBoundingRect(); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfTileSource.h b/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfTileSource.h new file mode 100644 index 0000000000..73c283f0ac --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/formats/vpf/ossimVpfTileSource.h @@ -0,0 +1,168 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2004 Garrett Potts, all rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// $Id: ossimVpfTileSource.h,v 1.12 2005/02/11 15:07:32 dburken Exp $ +//---------------------------------------------------------------------------- +#ifndef ossimVpfTileSource_HEADER +#define ossimVpfTileSource_HEADER + +#include <imaging/formats/vpf/ossimVpfAnnotationSource.h> +#include <imaging/formats/ossimImageHandler.h> +#include <base/common/ossimViewInterface.h> + + +class OSSIMDLLEXPORT ossimVpfTileSource : public ossimImageHandler, + public ossimViewInterface +{ +public: + + ossimVpfTileSource(); + virtual ~ossimVpfTileSource(); + + virtual void close(); + + /** + * @return Returns true on success, false on error. + * + * @note This method relies on the data member ossimImageData::theImageFile + * being set. Callers should do a "setFilename" prior to calling this + * method or use the ossimImageHandler::open that takes a file name and an + * entry index. + */ + virtual bool open(); + + /*! + * Returns a pointer to a tile given an origin representing the upper + * left corner of the tile to grab from the image. + * Satisfies pure virtual from TileSource class. + */ + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + + /*! + * Returns the number of bands in the image. + * Satisfies pure virtual from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfInputBands() const; + + /*! + * Returns the number of bands in a tile returned from this TileSource. + * Note: we are supporting sources that can have multiple data objects. + * If you want to know the scalar type of an object you can pass in the + */ + virtual ossim_uint32 getNumberOfOutputBands() const; + + /*! + * Returns the number of bands in the image. + * Satisfies pure virtual from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfLines(ossim_uint32 reduced_res_level = 0) const; + + /*! + * Returns the number of bands available from an image. + * Satisfies pure virtual from ImageHandler class. + */ + virtual ossim_uint32 getNumberOfSamples(ossim_uint32 reduced_res_level = 0) const; + + /*! + * Returns the number of reduced resolution data sets (rrds). + * Note: The full res image is counted as a data set so an image with no + * reduced resolution data set will have a count of one. + */ + virtual ossim_uint32 getNumberOfDecimationLevels() const; + + /*! + * Returns the zero based image rectangle for the reduced resolution data + * set (rrds) passed in. Note that rrds 0 is the highest resolution rrds. + */ + virtual ossimIrect getImageRectangle(ossim_uint32 reduced_res_level = 0) const; + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix); + + /*! + * Populates the keyword list with image geometry information. This + * method is used to relay projection/model information to users. + * Returns true if geometry info is present, false if not. + */ + virtual bool getImageGeometry(ossimKeywordlist& kwl, + const char* prefix=0); + + /*! + * Returns the output pixel type of the tile source. + */ + virtual ossimScalarType getOutputScalarType() const; + + /*! + * Returns the width of the output tile. + */ + virtual ossim_uint32 getTileWidth() const; + + /*! + * Returns the height of the output tile. + */ + virtual ossim_uint32 getTileHeight() const; + + /*! + * Returns the tile width of the image or 0 if the image is not tiled. + * Note: this is not the same as the ossimImageSource::getTileWidth which + * returns the output tile width which can be different than the internal + * image tile width on disk. + */ + virtual ossim_uint32 getImageTileWidth() const; + + /*! + * Returns the tile width of the image or 0 if the image is not tiled. + * Note: this is not the same as the ossimImageSource::getTileWidth which + * returns the output tile width which can be different than the internal + * image tile width on disk. + */ + virtual ossim_uint32 getImageTileHeight() const; + + virtual bool isOpen()const; + + virtual double getNullPixelValue(ossim_uint32 band=0)const; + + virtual double getMinPixelValue(ossim_uint32 band=0)const; + + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + + virtual ossimObject* getView(); + + virtual const ossimObject* getView()const; + + virtual bool setView(ossimObject* baseObject, bool ownsTheView = false); + + void getAllFeatures(std::vector<ossimVpfAnnotationFeatureInfo*>& featureList); + + void setAllFeatures(std::vector<ossimVpfAnnotationFeatureInfo*>& featureList); + + void transformObjects(); + + void computeBoundingRect(); + +protected: + ossimVpfAnnotationSource* theAnnotationSource; + + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/histogram/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/histogram/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/histogram/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/imaging/histogram/ossimHistogramWriter.cpp b/Utilities/OSSIM/ossim_core/imaging/histogram/ossimHistogramWriter.cpp new file mode 100644 index 0000000000..91853d24c0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/histogram/ossimHistogramWriter.cpp @@ -0,0 +1,154 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimHistogramWriter.cpp,v 1.25 2005/09/02 18:02:25 gpotts Exp $ +#include <base/common/events/ossimProcessListener.h> +#include <imaging/histogram/ossimHistogramWriter.h> +#include <imaging/ossimImageSource.h> +#include <base/data_types/ossimKeywordlist.h> +#include <imaging/ossimImageSourceSequencer.h> +#include <base/data_types/ossimMultiResLevelHistogram.h> +#include <base/data_types/ossimMultiBandHistogram.h> + +class ossimHistogramWriterProcessListener : public ossimProcessListener +{ +public: + ossimHistogramWriterProcessListener(ossimConnectableObject* passon) + :thePassonTo(passon) + { + } + virtual void processProgressEvent(ossimProcessProgressEvent& event) + { + if(thePassonTo) + { + event.setObject(thePassonTo); + thePassonTo->fireEvent(event); + } + } + + ossimConnectableObject* thePassonTo; + +}; + +RTTI_DEF3(ossimHistogramWriter, + "ossimHistogramWriter", + ossimOutputSource, + ossimProcessInterface, + ossimConnectableObjectListener); + +ossimHistogramWriter::ossimHistogramWriter(ossimImageSource* inputSource, + ossimObject* owner) + : ossimOutputSource(owner, + 1, + 0, + true, + false), + theFileStream(NULL) +{ + theProcessListener = new ossimHistogramWriterProcessListener(this); + + theAreaOfInterest.makeNan(); + connectMyInputTo(0, inputSource); +} + +ossimHistogramWriter::~ossimHistogramWriter() +{ + if(isOpen()) + { + close(); + } + if(theProcessListener) + { + delete theProcessListener; + theProcessListener = 0; + } + +} + +bool ossimHistogramWriter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + bool result = ossimOutputSource::saveState(kwl, prefix); + + + return result; +} + +bool ossimHistogramWriter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + bool result = ossimOutputSource::loadState(kwl, prefix); + + if(result) + { + if(!getNumberOfInputs()) + { + setNumberOfInputs(1); + } + } + + return result; +} + +bool ossimHistogramWriter::execute() +{ + writeHistogram(); + + return true; +} + +void ossimHistogramWriter::writeHistogram() +{ + if(!isOpen()) + { + open(); + if(!isOpen()) + { + cerr << "unable to open file " << theFilename << endl; + return; + } + } + if(!getInput(0)) + { + cerr << "ossimHistogramWriter::writeHistogram is not connected" << endl; + return; + } + ossimHistogramSource* histoSource = PTR_CAST(ossimHistogramSource, getInput(0)); + bool deleteHistoSource = false; + if(!histoSource) + { + histoSource = new ossimImageHistogramSource; + histoSource->connectMyInputTo(0, getInput(0)); + histoSource->enableSource(); + deleteHistoSource = true; + } + + histoSource->addListener( theProcessListener); + + ossimMultiResLevelHistogram* histo = histoSource->getHistogram(); + + if(histo) + { + ossimKeywordlist kwl; + histo->saveState(kwl); + + kwl.writeToStream(*theFileStream); + } + histoSource->removeListener(theProcessListener); + + if(deleteHistoSource) + { + delete histoSource; + histoSource = NULL; + } + + close(); +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/histogram/ossimHistogramWriter.h b/Utilities/OSSIM/ossim_core/imaging/histogram/ossimHistogramWriter.h new file mode 100644 index 0000000000..a92a42b437 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/histogram/ossimHistogramWriter.h @@ -0,0 +1,178 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossimHistogramWriter.h,v 1.28 2005/09/02 18:06:31 dburken Exp $ +#ifndef ossimHistogramWriter_HEADER +#define ossimHistogramWriter_HEADER +#include "base/common/ossimOutputSource.h" +#include "base/data_types/ossimIrect.h" +#include "base/data_types/ossimFilename.h" +#include "base/common/ossimProcessInterface.h" +#include "base/common/events/ossimObjectEvents.h" +#include "base/common/events/ossimProcessProgressEvent.h" +#include "base/common/events/ossimProcessListener.h" +#include "base/common/events/ossimConnectableObjectListener.h" +#include "base/common/events/ossimConnectionEvent.h" +#include "base/common/ossimHistogramSource.h" +#include "imaging/histogram/ossimImageHistogramSource.h" + +#include "imaging/ossimImageSource.h" + +#include <fstream> + +class ossimImageSource; +class ossimHistogramWriterProcessListener; + +class OSSIMDLLEXPORT ossimHistogramWriter : public ossimOutputSource, + public ossimProcessInterface, + public ossimConnectableObjectListener +{ +public: + friend class ossimHistogramWriterProcessListener; + + ossimHistogramWriter(ossimImageSource* inputSource=NULL, + ossimObject* owner=NULL); + + virtual ~ossimHistogramWriter(); + void setAreaOfInterest(const ossimIrect& rect) + { + theAreaOfInterest = rect; + } + + virtual ossimObject* getObject() + { + return this; + } + virtual const ossimObject* getObject()const + { + return this; + } + + virtual bool execute(); + + virtual bool isOpen()const + { + return (theFileStream != NULL); + + } + /*! + * open the histogram file for output. Note if the file was + * previously open then it will close it and re-opens the + * file. + */ + virtual bool open() + { + if(isOpen()) + { + close(); + } + + theFileStream = new std::ofstream(theFilename.c_str()); + + return theFileStream->good(); + } + + virtual bool open(const ossimFilename& filename) + { + return ossimOutputSource::open(filename); + } + virtual void close() + { + delete theFileStream; + theFileStream = NULL; + } + + /*! + * Overrides the base class and maps the outputName to a filename. + */ + virtual void setOutputName(const ossimString& outputName) + { + ossimOutputSource::setOutputName(outputName); + setFilename(outputName); + } + + virtual void setFilename(const ossimFilename& filename) + { + theFilename = filename; + } + + bool canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const + { + return (object&&(inputIndex == 0)&& + (PTR_CAST(ossimHistogramSource, object)|| + PTR_CAST(ossimImageSourceInterface, object))); + } + + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual void processProgressEvent(ossimProcessProgressEvent& event) + { + // we will raise the event if its coming from our + // input. This means that we are connected to a + // ossimHistogramSource. + // + if(event.getObject() != this) + { + ossimProcessInterface::setCurrentMessage(event.getMessage()); + setPercentComplete(event.getPercentComplete()); + } + } + + virtual void connectInputEvent(ossimConnectionEvent& event) + { + if(event.getObject() == this) + { + if(event.getOldObject()) + { + event.getOldObject()->removeListener((ossimProcessListener*)this); + } + if(getInput(0)&& + PTR_CAST(ossimHistogramSource, getInput(0))) + { + getInput(0)->addListener( (ossimProcessListener*)this); + } + } + } + + virtual void disconnectInputEvent(ossimConnectionEvent& event) + { + if(event.getOldObject()&& + PTR_CAST(ossimHistogramSource, getInput(0))) + { + event.getOldObject()->removeListener((ossimProcessListener*)this); + } + } +protected: + virtual void writeHistogram(); + ossimIrect theAreaOfInterest; + ossimFilename theFilename; + std::ofstream* theFileStream; + ossimHistogramWriterProcessListener* theProcessListener; +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/histogram/ossimImageHistogramSource.cpp b/Utilities/OSSIM/ossim_core/imaging/histogram/ossimImageHistogramSource.cpp new file mode 100644 index 0000000000..53be2adf49 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/histogram/ossimImageHistogramSource.cpp @@ -0,0 +1,373 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See LICENSE.txt file in the top level directory. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimImageHistogramSource.cpp,v 1.21 2006/01/10 13:10:29 gpotts Exp $ +#include <imaging/histogram/ossimImageHistogramSource.h> +#include <base/data_types/ossimMultiResLevelHistogram.h> +#include <base/data_types/ossimMultiBandHistogram.h> +#include <imaging/ossimImageSourceSequencer.h> + +RTTI_DEF3(ossimImageHistogramSource, "ossimImageHistogramSource", ossimHistogramSource, ossimConnectableObjectListener, ossimProcessInterface); + +ossimImageHistogramSource::ossimImageHistogramSource(ossimObject* owner) + :ossimHistogramSource(owner, + 1, // one input + 0, // no outputs + true, // input list is fixed + false),// output can still grow though + theHistogramRecomputeFlag(true), + theMaxNumberOfResLevels(1) +{ + theAreaOfInterest.makeNan(); + addListener((ossimConnectableObjectListener*)this); + disableSource(); + + theMinValueOverride = OSSIM_DBL_NAN; + theMaxValueOverride = OSSIM_DBL_NAN; + theNumberOfBinsOverride = -1; +} + +ossimImageHistogramSource::ossimImageHistogramSource(ossimObject* owner, + ossim_uint32 numberOfInputs, + ossim_uint32 numberOfOutputs, + ossim_uint32 inputListFixedFlag, + ossim_uint32 outputListFixedFlag) + :ossimHistogramSource(owner, + numberOfInputs, + numberOfOutputs, + inputListFixedFlag, + outputListFixedFlag), + theHistogramRecomputeFlag(true) +{ + theAreaOfInterest.makeNan(); + addListener((ossimConnectableObjectListener*)this); + disableSource(); +} + +ossimImageHistogramSource::~ossimImageHistogramSource() +{ + removeListener((ossimConnectableObjectListener*)this); +} + +ossimObject* ossimImageHistogramSource::getObject() +{ + return this; +} + +const ossimObject* ossimImageHistogramSource::getObject()const +{ + return this; +} + +void ossimImageHistogramSource::setAreaOfInterest(const ossimIrect& rect) +{ + if(rect != theAreaOfInterest) + { + theHistogramRecomputeFlag = true; + } + theAreaOfInterest = rect; +} + +ossimIrect ossimImageHistogramSource::getAreaOfInterest()const +{ + return theAreaOfInterest; +} + +void ossimImageHistogramSource::getAreaOfInterest(ossimIrect& rect)const +{ + rect = theAreaOfInterest; +} + +ossim_uint32 ossimImageHistogramSource::getMaxNumberOfRLevels()const +{ + return theMaxNumberOfResLevels; +} + +void ossimImageHistogramSource::setMaxNumberOfRLevels(ossim_uint32 number) +{ + if(number != theMaxNumberOfResLevels) + { + theHistogramRecomputeFlag = true; + } + theMaxNumberOfResLevels = number; +} + +ossimMultiResLevelHistogram* ossimImageHistogramSource::getHistogram(const ossimIrect& rect) +{ + if((theAreaOfInterest != rect)|| + (theAreaOfInterest.hasNans())) + { + theAreaOfInterest = rect; + theHistogramRecomputeFlag = true; + } + + return getHistogram(); +} + +bool ossimImageHistogramSource::execute() +{ + if(!isSourceEnabled()) + { + return theHistogram; + } + setProcessStatus(ossimProcessInterface::PROCESS_STATUS_EXECUTING); + if(theHistogramRecomputeFlag) + { + if(theAreaOfInterest.hasNans()) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, getInput(0)); + if(interface) + { + theAreaOfInterest = interface->getBoundingRect(); + } + } + computeHistogram(); + if(getProcessStatus() != ossimProcessInterface::PROCESS_STATUS_ABORTED) + { + theHistogramRecomputeFlag = false; + disableSource(); + } + } + setProcessStatus(ossimProcessInterface::PROCESS_STATUS_NOT_EXECUTING); + + return true; +} + +bool ossimImageHistogramSource::canConnectMyInputTo(ossim_int32 myInputIndex, + const ossimConnectableObject* object)const +{ + return ((myInputIndex==0)&&PTR_CAST(ossimImageSourceInterface, + object)); +} + +void ossimImageHistogramSource::setNumberOfBinsOverride(ossim_int32 numberOfBinsOverride) +{ + theNumberOfBinsOverride = numberOfBinsOverride; +} + +void ossimImageHistogramSource::setMinValueOverride(ossim_float32 minValueOverride) +{ + theMinValueOverride = minValueOverride; +} +void ossimImageHistogramSource::setMaxValueOverride(ossim_float32 maxValueOverride) +{ + theMaxValueOverride = maxValueOverride; +} + +void ossimImageHistogramSource::propertyEvent(ossimPropertyEvent& /* event */) +{ + theHistogramRecomputeFlag = true; +} + +void ossimImageHistogramSource::connectInputEvent(ossimConnectionEvent& /* event */) +{ + theHistogramRecomputeFlag = true; +} + +ossimMultiResLevelHistogram* ossimImageHistogramSource::getHistogram() +{ + execute(); + return theHistogram; +} + +void ossimImageHistogramSource::computeHistogram() +{ + if(theHistogram) + { + delete theHistogram; + theHistogram = NULL; + } + theHistogram = new ossimMultiResLevelHistogram; + + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, getInput(0)); + if(!input) + { + setPercentComplete(100.0); + return; + } + + if(getInput(0)) + { + // sum up all tiles needing processing. We will use the sequncer. +// ossim_uint32 numberOfResLevels = input->getNumberOfDecimationLevels(); + ossim_uint32 index = 0; + double tileCount = 0.0; + double totalTiles = 0.0; + ossim_uint32 numberOfBands = input->getNumberOfOutputBands(); + ossim_uint32 numberOfBins = 0; + float minValue = 0; + float maxValue = 0; + + ossimImageSourceSequencer* sequencer = new ossimImageSourceSequencer; + sequencer->connectMyInputTo(0, getInput(0)); + sequencer->initialize(); + + vector<ossimDpt> decimationFactors; + input->getDecimationFactors(decimationFactors); + + if( decimationFactors.size() < theMaxNumberOfResLevels) + { + cerr << "Number Decimations is smaller than the request number of r-levels" << endl; + return; + } + theHistogram->create(theMaxNumberOfResLevels);//numberOfResLevels); + for(index = 0; index < theMaxNumberOfResLevels; ++index) + { + sequencer->setAreaOfInterest(theAreaOfInterest*decimationFactors[index]); + + totalTiles += sequencer->getNumberOfTiles(); + } + + switch(input->getOutputScalarType()) + { + case OSSIM_UINT8: + { + minValue = 0; + maxValue = OSSIM_DEFAULT_MAX_PIX_UCHAR; + numberOfBins = 256; + + break; + } + case OSSIM_USHORT11: + { + minValue = 0; + maxValue = OSSIM_DEFAULT_MAX_PIX_UINT11; + numberOfBins = OSSIM_DEFAULT_MAX_PIX_UINT11 + 1; + + break; + } + case OSSIM_UINT16: + case OSSIM_UINT32: + { + minValue = 0; + maxValue = OSSIM_DEFAULT_MAX_PIX_UINT16; + numberOfBins = OSSIM_DEFAULT_MAX_PIX_UINT16 + 1; + + break; + } + case OSSIM_SINT16: + case OSSIM_SINT32: + case OSSIM_FLOAT32: + case OSSIM_FLOAT64: + { + minValue = OSSIM_DEFAULT_MIN_PIX_SINT16; + maxValue = OSSIM_DEFAULT_MAX_PIX_SINT16; + numberOfBins = (OSSIM_DEFAULT_MAX_PIX_SINT16-OSSIM_DEFAULT_MIN_PIX_SINT16) + 1; + + break; + } + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_NORMALIZED_DOUBLE: + { + minValue = 0; + maxValue = 1.0; + numberOfBins = OSSIM_DEFAULT_MAX_PIX_UINT16+1; + break; + } + default: + { + cerr << "Unsupported scalar type in ossimImageHistogramSource::computeHistogram()" << endl; + return; + } + } + + if(theMinValueOverride != OSSIM_DBL_NAN) + { + minValue = (float)theMinValueOverride; + } + if(theMaxValueOverride != OSSIM_DBL_NAN) + { + maxValue = (float)theMaxValueOverride; + } + if(theNumberOfBinsOverride > 0) + { + numberOfBins = theNumberOfBinsOverride; + } + ossimProcessInterface::ossimProcessStatus processStatus = getProcessStatus(); + if(numberOfBins > 0) + { + setPercentComplete(0.0); + for(index = 0; + ((index < theMaxNumberOfResLevels)&&//numberOfResLevels)&& + (processStatus != ossimProcessInterface::PROCESS_STATUS_ABORTED)); + ++index) + { + //sequencer->setAreaOfInterest(input->getBoundingRect(index)); + sequencer->setAreaOfInterest(theAreaOfInterest*decimationFactors[index]); + + sequencer->setToStartOfSequence(); + theHistogram->getMultiBandHistogram(index)->create(numberOfBands, + numberOfBins, + minValue, + maxValue); + + processStatus = getProcessStatus(); + if(processStatus!=ossimProcessInterface::PROCESS_STATUS_ABORTED) + { + ossimRefPtr<ossimImageData> data = + sequencer->getNextTile(index); + ++tileCount; + setPercentComplete((100.0*(tileCount/totalTiles))); + processStatus = getProcessStatus(); + long resLevelTotalTiles = sequencer->getNumberOfTiles(); + long resLevelTileCount = 1; + while((resLevelTileCount < resLevelTotalTiles)&& + (processStatus!=ossimProcessInterface::PROCESS_STATUS_ABORTED)) + { + if(data.valid()) + { + data->populateHistogram(theHistogram->getMultiBandHistogram(index)); + } + data = sequencer->getNextTile(index); + processStatus = getProcessStatus(); + ++tileCount; + ++resLevelTileCount; + setPercentComplete((100.0*(tileCount/totalTiles))); + } + } + } + } + delete sequencer; + sequencer = NULL; + } + //setPercentComplete(100); +} + +bool ossimImageHistogramSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimHistogramSource::loadState(kwl, + prefix); + + ossimString newPrefix = ossimString(prefix) + "rect."; + theAreaOfInterest.loadState(kwl, newPrefix); + + if(getNumberOfInputs()!=1) + { + setNumberOfInputs(1); + } + theInputListIsFixedFlag = true; + theOutputListIsFixedFlag = false; + + return true; +} + +bool ossimImageHistogramSource::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + bool result = ossimHistogramSource::saveState(kwl, + prefix); + + if(result) + { + ossimString newPrefix = ossimString(prefix) + "rect."; + theAreaOfInterest.saveState(kwl, newPrefix); + } + + return result; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/histogram/ossimImageHistogramSource.h b/Utilities/OSSIM/ossim_core/imaging/histogram/ossimImageHistogramSource.h new file mode 100644 index 0000000000..4ae355a86b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/histogram/ossimImageHistogramSource.h @@ -0,0 +1,101 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See LICENSE.txt file in the top level directory. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimImageHistogramSource.h,v 1.16 2005/11/27 17:07:12 dburken Exp $ +#ifndef ossimImageHistogramSource_HEADER +#define ossimImageHistogramSource_HEADER +#include <base/common/ossimHistogramSource.h> +#include <imaging/ossimImageSourceInterface.h> +#include <base/common/ossimProcessInterface.h> +#include <base/common/events/ossimConnectableObjectListener.h> +#include <base/common/events/ossimObjectEvents.h> +#include <base/data_types/ossimIrect.h> + +/*! + * This source expects as input an ossimImageSourceInterface. + * it will slice up the requested region into tiles and compute + * the histogram of the passed in rectangle. + */ +class OSSIMDLLEXPORT ossimImageHistogramSource : public ossimHistogramSource, + public ossimConnectableObjectListener, + public ossimProcessInterface +{ +public: + ossimImageHistogramSource(ossimObject* owner = NULL); + ossimImageHistogramSource(ossimObject* owner, + ossim_uint32 numberOfInputs, + ossim_uint32 numberOfOutputs, + ossim_uint32 inputListFixedFlag, + ossim_uint32 outputListFixedFlag); + virtual ~ossimImageHistogramSource(); + + virtual ossimObject* getObject(); + virtual const ossimObject* getObject()const; + + void setAreaOfInterest(const ossimIrect& rect); + + ossimIrect getAreaOfInterest()const; + + void getAreaOfInterest(ossimIrect& rect)const; + + virtual ossim_uint32 getMaxNumberOfRLevels()const; + + virtual void setMaxNumberOfRLevels(ossim_uint32 number); + + /*! + * The first argument is the region of interest that you wish to + * use for the histogram. If the region is different than + * what it has already computed before then the histogram is considered + * dirty and will be re-computed. The returned object is a + * multi-reslevel histogram + */ + virtual ossimMultiResLevelHistogram* getHistogram(const ossimIrect& rect); + + virtual ossimMultiResLevelHistogram* getHistogram(); + virtual bool execute(); + + virtual bool canConnectMyInputTo(ossim_int32 myInputIndex, + const ossimConnectableObject* object)const; + + void setNumberOfBinsOverride(ossim_int32 numberOfBinsOverride); + + void setMinValueOverride(ossim_float32 minValueOverride); + + void setMaxValueOverride(ossim_float32 maxValueOverride); + + virtual void propertyEvent(ossimPropertyEvent& event); + + virtual void connectInputEvent(ossimConnectionEvent& event); + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; +protected: + virtual void computeHistogram(); + + /*! + * Initialized to ossimNAN'S + */ + ossimIrect theAreaOfInterest; + bool theHistogramRecomputeFlag; + + /*! + * Will default to 1. This means it will use up to max + * number of res levels for the histogram. + */ + ossim_uint32 theMaxNumberOfResLevels; + + ossim_float64 theMinValueOverride; + ossim_float64 theMaxValueOverride; + ossim_int32 theNumberOfBinsOverride; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/metadata/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/metadata/.cvsignore new file mode 100644 index 0000000000..7df3918588 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/metadata/.cvsignore @@ -0,0 +1,3 @@ +*.d +Makefile + diff --git a/Utilities/OSSIM/ossim_core/imaging/metadata/ossimEnviHeaderFileWriter.cpp b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimEnviHeaderFileWriter.cpp new file mode 100644 index 0000000000..60cacc25a5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimEnviHeaderFileWriter.cpp @@ -0,0 +1,107 @@ +//---------------------------------------------------------------------------- +// Copyright (c) 2005, David Burken, all rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Class definition for ossimEnviHeaderFileWriter. Meta data class for +// writing an ENVI (The Environment for Visualizing Images) header file. +// +//---------------------------------------------------------------------------- +// $Id: ossimEnviHeaderFileWriter.cpp,v 1.6 2005/08/08 22:00:24 dburken Exp $ + +#include <imaging/metadata/ossimEnviHeaderFileWriter.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimIrect.h> +#include <imaging/ossimImageSourceInterface.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <projections/map_projections/ossimMapProjection.h> +#include <projections/map_projections/ossimMapProjectionInfo.h> + + +RTTI_DEF1(ossimEnviHeaderFileWriter, + "ossimEnviHeaderFileWriter", + ossimMetadataFileWriter) + +ossimEnviHeaderFileWriter::ossimEnviHeaderFileWriter() + : + ossimMetadataFileWriter(), + theHdr() +{ +} + +ossimEnviHeaderFileWriter::~ossimEnviHeaderFileWriter() +{ +} + +bool ossimEnviHeaderFileWriter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + bool result = false; + + if (ossimMetadataFileWriter::loadState(kwl, prefix)) + { + result = theHdr.loadState(kwl, prefix); + } + + return result; +} + +bool writeFile() +{ + bool result = true; + + return result; +} + +bool ossimEnviHeaderFileWriter::writeFile() +{ + theHdr.setLines(theAreaOfInterest.height()); + theHdr.setSamples(theAreaOfInterest.width()); + theHdr.setBands(theInputConnection->getNumberOfOutputBands()); + + // Get the geometry from the input. + ossimKeywordlist kwl; + theInputConnection->getImageGeometry(kwl); + + // Create the projection. + ossimMapProjection* mapProj = NULL; + ossimRefPtr<ossimProjection> proj = + ossimProjectionFactoryRegistry::instance()->createProjection(kwl); + if (proj.valid()) + { + mapProj = PTR_CAST(ossimMapProjection, proj.get()); + + if (mapProj) + { + // Create the projection info. + ossimRefPtr<ossimMapProjectionInfo> projectionInfo + = new ossimMapProjectionInfo(mapProj, theAreaOfInterest); + + // Set the tie points in the keyword list. + projectionInfo->getGeom(kwl); + + // Pass it on to envi header to set the map info string from geometry. + theHdr.setMapInfo(kwl); + } + } + + return theHdr.writeFile(theFilename); +} + +void ossimEnviHeaderFileWriter::getMetadatatypeList( + std::vector<ossimString>& metadatatypeList) const +{ + metadatatypeList.push_back(ossimString("envi_header")); +} + +bool ossimEnviHeaderFileWriter::hasMetadataType( + const ossimString& metadataType)const +{ + return (metadataType == "envi_header"); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/metadata/ossimEnviHeaderFileWriter.h b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimEnviHeaderFileWriter.h new file mode 100644 index 0000000000..fdb66523f7 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimEnviHeaderFileWriter.h @@ -0,0 +1,77 @@ +//---------------------------------------------------------------------------- +// Copyright (c) 2005, David Burken, all rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Class declaration for ossimEnviHeaderFileWriter. Meta data class for +// writing an ENVI (The Environment for Visualizing Images) header file. +// +//---------------------------------------------------------------------------- +// $Id: ossimEnviHeaderFileWriter.h,v 1.4 2005/08/08 22:00:24 dburken Exp $ + +#ifndef ossimEnviHeaderFileWriter_H +#define ossimEnviHeaderFileWriter_H + +#include <fstream> +#include <imaging/metadata/ossimMetadataFileWriter.h> +#include <base/data_types/ossimKeywordlist.h> +#include <support_data/envi/ossimEnviHeader.h> + +/** + * Class for writing a "ENVI" style header. + */ +class OSSIMDLLEXPORT ossimEnviHeaderFileWriter : public ossimMetadataFileWriter +{ +public: + + /** default constructor */ + ossimEnviHeaderFileWriter(); + + /** virtual destructor */ + virtual ~ossimEnviHeaderFileWriter(); + + /** + * Initializes the state of the writer. Users should use this to set + * the envi header fields that are not taken from theInputConnection prior + * to calling execute. + * + * @return true on success, false on failure. + */ + virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix = 0); + + /** + * Satisfies pure virtual from ossimMetadataWriter base. + * + * Appends the writers image types to the "metadatatypeList". + * + * @param metadatatypeList stl::vector<ossimString> list to append to. + * + * @note Appends to the list, does not clear it first. + */ + virtual void getMetadatatypeList( + std::vector<ossimString>& metadatatypeList) const; + + /** + * Satisfies pure virtual from ossimMetadataWriter base. + * + * @param imageType string representing image type. + * + * @return true if "metadataType" is supported by writer. + */ + virtual bool hasMetadataType(const ossimString& metadataType)const; + +private: + + virtual bool writeFile(); + + ossimEnviHeader theHdr; + +TYPE_DATA +}; +#endif /* End of #ifndef ossimEnviHeaderFileWriter_H */ diff --git a/Utilities/OSSIM/ossim_core/imaging/metadata/ossimFgdcFileWriter.cpp b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimFgdcFileWriter.cpp new file mode 100644 index 0000000000..404a15ecd8 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimFgdcFileWriter.cpp @@ -0,0 +1,972 @@ +//---------------------------------------------------------------------------- +// Copyright (c) 2005, David Burken, all rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: Class to write out meta data in a Federal Geographic Data +// Committe (FGDC) format. +// +//---------------------------------------------------------------------------- +// $Id: ossimFgdcFileWriter.cpp,v 1.1 2005/08/09 19:08:32 dburken Exp $ + +#include <fstream> +using namespace std; + +#include <imaging/metadata/ossimFgdcFileWriter.h> +#include <base/common/ossimKeywordNames.h> +#include <base/common/ossimTrace.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimXmlNode.h> +#include <imaging/ossimImageSourceInterface.h> +#include <projections/map_projections/ossimMapProjection.h> +#include <projections/map_projections/ossimMapProjectionInfo.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> + +RTTI_DEF1(ossimFgdcFileWriter, "ossimFgdcFileWriter", ossimMetadataFileWriter) + +static ossimTrace traceDebug("ossimFgdcFileWriter:debug"); + + +ossimFgdcFileWriter::ossimFgdcFileWriter() + : + theIndentionLevel(0), + theTabString("\t"), + theTemplate(), + theSourceImageFilename() +{ +} + +ossimFgdcFileWriter::~ossimFgdcFileWriter() +{ +} + +bool ossimFgdcFileWriter::writeFile() +{ + if(theFilename == ossimFilename::NIL) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimFgdcFileWriter::writeFile no filename set!" << endl; + return false; + } + + if( !theInputConnection ) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimFgdcFileWriter::writeFile no input connection!" << endl; + return false; + } + + ofstream os(theFilename.c_str()); + if (!os) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimFgdcFileWriter::writeFile no input connection!" << endl; + return false; + } + + // Get the geometry from the input. + ossimKeywordlist kwl; + theInputConnection->getImageGeometry(kwl); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimFgdcFileWriter::writeFile debug:\n" + << "Geometry file: " << kwl << endl; + } + + // Create the projection. + ossimRefPtr<ossimProjection> proj = + ossimProjectionFactoryRegistry::instance()->createProjection(kwl); + if (!proj.valid()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimFgdcFileWriter::writeFile Could not create projection." + << endl; + return false; + } + + ossimMapProjection* mapProj = PTR_CAST(ossimMapProjection, proj.get()); + if (!mapProj) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimFgdcFileWriter::writeFile Not map projected." + << endl; + return false; + } + + ossimMapProjectionInfo mpi(mapProj, theInputConnection->getBoundingRect()); + + + + os << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n" + << "<?xml-stylesheet type=\"text/xsl\" href=\"/common/fgdc_classic.xsl\" ?>\n"; + openTag(os, ossimString("metadata"), true); + openTag(os, ossimString("idinfo"), true); + openTag(os, ossimString("citation"), true); + openTag(os, ossimString("citeinfo"), true); + + openTag(os, ossimString("origin"), false); + os << find(ossimString("/metadata/idinfo/citation/citeinfo/origin")); + closeTag(os, ossimString("origin"), false); + + openTag(os, ossimString("pubdate"), false); + os << find(ossimString("/metadata/idinfo/citation/citeinfo/pubdate")); + closeTag(os, ossimString("pubdate"), false); + + openTag(os, ossimString("title"), false); + // os << find(ossimString("/metadata/idinfo/citation/citeinfo/title")); + os << theSourceImageFilename.c_str(); + closeTag(os, ossimString("title"), false); + + openTag(os, ossimString("edition"), false); + os << find(ossimString("/metadata/idinfo/citation/citeinfo/edition")); + closeTag(os, ossimString("edition"), false); + + openTag(os, ossimString("geoform"), false); + os << find(ossimString("/metadata/idinfo/citation/citeinfo/geoform")); + closeTag(os, ossimString("geoform"), false); + + openTag(os, ossimString("serinfo"), true); + openTag(os, ossimString("sername"), false); + os << find(ossimString("/metadata/idinfo/citation/citeinfo/serinfo/sername")); + closeTag(os, ossimString("sername"), false); + + openTag(os, ossimString("issue"), false); + os << theSourceImageFilename.c_str(); + closeTag(os, ossimString("issue"), false); + + closeTag(os, ossimString("serinfo"), true); + + openTag(os, ossimString("pubinfo"), true); + + openTag(os, ossimString("pubplace"), false); + os << find(ossimString("/metadata/idinfo/citation/citeinfo/pubinfo/pubplace")); + closeTag(os, ossimString("pubplace"), false); + + openTag(os, ossimString("publish"), false); + os << find(ossimString("/metadata/idinfo/citation/citeinfo/pubinfo/publish")); + closeTag(os, ossimString("publish"), false); + + closeTag(os, ossimString("pubinfo"), true); + closeTag(os, ossimString("citeinfo"), true); + closeTag(os, ossimString("citation"), true); + + openTag(os, ossimString("descript"), true); + + openTag(os, ossimString("abstract"), false); + os << find(ossimString("/metadata/idinfo/descript/abstract")); + closeTag(os, ossimString("abstract"), false); + + openTag(os, ossimString("purpose"), false); + os << find(ossimString("/metadata/idinfo/descript/purpose")); + closeTag(os, ossimString("purpose"), false); + + openTag(os, ossimString("supplinf"), false); + os << find(ossimString("/metadata/idinfo/descript/supplinf")); + closeTag(os, ossimString("supplinf"), false); + + closeTag(os, ossimString("descript"), true); + + openTag(os, ossimString("timeperd"), true); + openTag(os, ossimString("timeinfo"), true); + openTag(os, ossimString("sngdate"), true); + + openTag(os, ossimString("caldate"), false); + os << find(ossimString("/metadata/idinfo/timeperd/timeinfo/sngdate/caldate")); + closeTag(os, ossimString("caldate"), false); + + closeTag(os, ossimString("sngdate"), true); + closeTag(os, ossimString("timeinfo"), true); + + + openTag(os, ossimString("current"), false); + os << find(ossimString("/metadata/idinfo/timeperd/current")); + closeTag(os, ossimString("current"), false); + + closeTag(os, ossimString("timeperd"), true); + + openTag(os, ossimString("status"), true); + + openTag(os, ossimString("progress"), false); + os << find(ossimString("/metadata/idinfo/status/progress")); + closeTag(os, ossimString("progress"), false); + + openTag(os, ossimString("update"), false); + os << find(ossimString("/metadata/idinfo/status/update")); + closeTag(os, ossimString("update"), false); + + closeTag(os, ossimString("status"), true); + + openTag(os, ossimString("spdom"), true); + openTag(os, ossimString("bounding"), true); + + if (mapProj->isGeographic()) + { + openTag(os, ossimString("westbc"), false); + os << ossimString::toString(mpi.ulGroundPt().lon); + closeTag(os, ossimString("westbc"), false); + + openTag(os, ossimString("eastbc"), false); + os << ossimString::toString(mpi.lrGroundPt().lon); + closeTag(os, ossimString("eastbc"), false); + + openTag(os, ossimString("northbc"), false); + os << ossimString::toString(mpi.ulGroundPt().lat); + closeTag(os, ossimString("northbc"), false); + + openTag(os, ossimString("southbc"), false); + os << ossimString::toString(mpi.lrGroundPt().lat); + closeTag(os, ossimString("southbc"), false); + } + else + { + openTag(os, ossimString("westbc"), false); + os << ossimString::toString(mpi.ulEastingNorthingPt().x); + closeTag(os, ossimString("westbc"), false); + + openTag(os, ossimString("eastbc"), false); + os << ossimString::toString(mpi.lrEastingNorthingPt().x); + closeTag(os, ossimString("eastbc"), false); + + openTag(os, ossimString("northbc"), false); + os << ossimString::toString(mpi.ulEastingNorthingPt().y); + closeTag(os, ossimString("northbc"), false); + + openTag(os, ossimString("southbc"), false); + os << ossimString::toString(mpi.ulEastingNorthingPt().y); + closeTag(os, ossimString("southbc"), false); + } + + closeTag(os, ossimString("bounding"), true); + closeTag(os, ossimString("spdom"), true); + + openTag(os, ossimString("keywords"), true); + + openTag(os, ossimString("theme"), true); + + openTag(os, ossimString("themekt"), false); + os << find(ossimString("/metadata/idinfo/keywords/theme/themekt")); + closeTag(os, ossimString("themekt"), false); + + openTag(os, ossimString("themekey"), false); + os << find(ossimString("/metadata/idinfo/keywords/theme/themekey")); + closeTag(os, ossimString("themekey"), false); + + closeTag(os, ossimString("theme"), true); + + closeTag(os, ossimString("keywords"), true); + + openTag(os, ossimString("accconst"), false); + os << find(ossimString("/metadata/idinfo/accconst")); + closeTag(os, ossimString("accconst"), false); + + openTag(os, ossimString("useconst"), false); + os << find(ossimString("/metadata/idinfo/useconst")); + closeTag(os, ossimString("useconst"), false); + + openTag(os, ossimString("ptcontac"), true); + + openTag(os, ossimString("cntinfo"), true); + + openTag(os, ossimString("cntperp"), true); + openTag(os, ossimString("cntper"), false); + os << find(ossimString("/metadata/idinfo/ptcontac/cntinfo/cntperp/cntper")); + closeTag(os, ossimString("cntper"), false); + closeTag(os, ossimString("cntperp"), true); + + openTag(os, ossimString("cntaddr"), true); + + openTag(os, ossimString("addrtype"), false); + os << find(ossimString("/metadata/idinfo/ptcontac/cntinfo/cntaddr/addrtype")); + closeTag(os, ossimString("addrtype"), false); + + openTag(os, ossimString("address"), false); + os << find(ossimString("/metadata/idinfo/ptcontac/cntinfo/cntaddr/address")); + closeTag(os, ossimString("address"), false); + + openTag(os, ossimString("city"), false); + os << find(ossimString("/metadata/idinfo/ptcontac/cntinfo/cntaddr/city")); + closeTag(os, ossimString("city"), false); + + openTag(os, ossimString("state"), false); + os << find(ossimString("/metadata/idinfo/ptcontac/cntinfo/cntaddr/state")); + closeTag(os, ossimString("state"), false); + + openTag(os, ossimString("postal"), false); + os << find(ossimString("/metadata/idinfo/ptcontac/cntinfo/cntaddr/postal")); + closeTag(os, ossimString("postal"), false); + + openTag(os, ossimString("country"), false); + os << find(ossimString("/metadata/idinfo/ptcontac/cntinfo/cntaddr/country")); + closeTag(os, ossimString("country"), false); + + closeTag(os, ossimString("cntaddr"), true); + + openTag(os, ossimString("cntvoice"), false); + os << find(ossimString("/metadata/idinfo/ptcontac/cntinfo/cntvoice")); + closeTag(os, ossimString("cntvoice"), false); + + openTag(os, ossimString("cntfax"), false); + + os << find(ossimString("/metadata/idinfo/ptcontac/cntinfo/cntfax")); + closeTag(os, ossimString("cntfax"), false); + + openTag(os, ossimString("cntemail"), false); + os << find(ossimString("/metadata/idinfo/ptcontac/cntinfo/cntemail")); + closeTag(os, ossimString("cntemail"), false); + + closeTag(os, ossimString("cntinfo"), true); + closeTag(os, ossimString("ptcontac"), true); + + openTag(os, ossimString("secinfo"), true); + + openTag(os, ossimString("secclass"), false); + os << find(ossimString("/metadata/idinfo/secinfo/secclass")); + closeTag(os, ossimString("secclass"), false); + + openTag(os, ossimString("secsys"), false); + os << find(ossimString("/metadata/idinfo/secinfo/secsys")); + closeTag(os, ossimString("secsys"), false); + + openTag(os, ossimString("sechandl"), false); + os << find(ossimString("/metadata/idinfo/secinfo/sechandl")); + closeTag(os, ossimString("sechandl"), false); + + closeTag(os, ossimString("secinfo"), true); + closeTag(os, ossimString("idinfo"), true); + + openTag(os, ossimString("distinfo"), true); + openTag(os, ossimString("distrib"), true); + openTag(os, ossimString("cntinfo"), true); + openTag(os, ossimString("cntperp"), true); + openTag(os, ossimString("cntper"), false); + os << find(ossimString("/metadata/distinfo/distrib/cntinfo/cntperp/cntper")); + + closeTag(os, ossimString("cntper"), false); + closeTag(os, ossimString("cntperp"), true); + + openTag(os, ossimString("cntaddr"), true); + + openTag(os, ossimString("addrtype"), false); + os << find(ossimString("/metadata/distinfo/distrib/cntinfo/cntaddr/addrtype")); + closeTag(os, ossimString("addrtype"), false); + + openTag(os, ossimString("address"), false); + os << find(ossimString("/metadata/distinfo/distrib/cntinfo/cntaddr/address")); + closeTag(os, ossimString("address"), false); + + openTag(os, ossimString("city"), false); + os << find(ossimString("/metadata/distinfo/distrib/cntinfo/cntaddr/city")); + closeTag(os, ossimString("city"), false); + + openTag(os, ossimString("state"), false); + os << find(ossimString("/metadata/distinfo/distrib/cntinfo/cntaddr/state")); + closeTag(os, ossimString("state"), false); + + openTag(os, ossimString("postal"), false); + os << find(ossimString("/metadata/distinfo/distrib/cntinfo/cntaddr/postal")); + closeTag(os, ossimString("postal"), false); + + openTag(os, ossimString("country"), false); + os << find(ossimString("/metadata/distinfo/distrib/cntinfo/cntaddr/country")); + closeTag(os, ossimString("country"), false); + + closeTag(os, ossimString("cntaddr"), true); + + openTag(os, ossimString("cntvoice"), false); + os << find(ossimString("/metadata/distinfo/distrib/cntinfo/cntvoice")); + closeTag(os, ossimString("cntvoice"), false); + + openTag(os, ossimString("cntfax"), false); + os << find(ossimString("/metadata/distinfo/distrib/cntinfo/cntfax")); + closeTag(os, ossimString("cntfax"), false); + + openTag(os, ossimString("cntemail"), false); + os << find(ossimString("/metadata/distinfo/distrib/cntinfo/cntemail")); + closeTag(os, ossimString("cntemail"), false); + + closeTag(os, ossimString("cntinfo"), true); + closeTag(os, ossimString("distrib"), true); + + openTag(os, ossimString("resdesc"), false); + os << find(ossimString("/metadata/distinfo/resdesc")); + closeTag(os, ossimString("resdesc"), false); + + openTag(os, ossimString("distliab"), false); + os << find(ossimString("/metadata/distinfo/distliab")); + closeTag(os, ossimString("distliab"), false); + + openTag(os, ossimString("stdorder"), true); + openTag(os, ossimString("digform"), true); + openTag(os, ossimString("digtinfo"), true); + + openTag(os, ossimString("formname"), false); + os << find(ossimString("/metadata/distinfo/stdorder/digform/digtinfo/formname")); + closeTag(os, ossimString("formname"), false); + + closeTag(os, ossimString("digtinfo"), true); + + openTag(os, ossimString("digtopt"), true); + openTag(os, ossimString("onlinopt"), true); + openTag(os, ossimString("computer"), true); + openTag(os, ossimString("networka"), true); + + openTag(os, ossimString("networkr"), false); + os << find(ossimString("/metadata/distinfo/stdorder/digform/digtopt/onlinopt/computer/networka/networkr")); + closeTag(os, ossimString("networkr"), false); + + closeTag(os, ossimString("networka"), true); + closeTag(os, ossimString("computer"), true); + closeTag(os, ossimString("onlinopt"), true); + closeTag(os, ossimString("digtopt"), true); + closeTag(os, ossimString("digform"), true); + + openTag(os, ossimString("fees"), false); + os << find(ossimString("/metadata/distinfo/stdorder/fees")); + closeTag(os, ossimString("fees"), false); + + closeTag(os, ossimString("stdorder"), true); + closeTag(os, ossimString("distinfo"), true); + + openTag(os, ossimString("metainfo"), true); + + openTag(os, ossimString("metd"), false); + os << find(ossimString("/metadata/metainfo/metd")); + closeTag(os, ossimString("metd"), false); + + openTag(os, ossimString("metc"), true); + openTag(os, ossimString("cntinfo"), true); + openTag(os, ossimString("cntperp"), true); + + openTag(os, ossimString("cntper"), false); + os << find(ossimString("/metadata/metainfo/metc/cntinfo/cntperp/cntper")); + closeTag(os, ossimString("cntper"), false); + + closeTag(os, ossimString("cntperp"), true); + + openTag(os, ossimString("cntaddr"), true); + + openTag(os, ossimString("addrtype"), false); + os << find(ossimString("/metadata/metainfo/metc/cntinfo/cntaddr/addrtype")); + closeTag(os, ossimString("addrtype"), false); + + openTag(os, ossimString("address"), false); + os << find(ossimString("/metadata/metainfo/metc/cntinfo/cntaddr/address")); + closeTag(os, ossimString("address"), false); + + openTag(os, ossimString("city"), false); + os << find(ossimString("/metadata/metainfo/metc/cntinfo/cntaddr/city")); + closeTag(os, ossimString("city"), false); + + openTag(os, ossimString("state"), false); + os << find(ossimString("/metadata/metainfo/metc/cntinfo/cntaddr/state")); + closeTag(os, ossimString("state"), false); + + openTag(os, ossimString("postal"), false); + os << find(ossimString("/metadata/metainfo/metc/cntinfo/cntaddr/postal")); + closeTag(os, ossimString("postal"), false); + + openTag(os, ossimString("country"), false); + os << find(ossimString("/metadata/metainfo/metc/cntinfo/cntaddr/country")); + closeTag(os, ossimString("country"), false); + + closeTag(os, ossimString("cntaddr"), true); + + openTag(os, ossimString("cntvoice"), false); + os << find(ossimString("/metadata/metainfo/metc/cntinfo/cntvoice")); + closeTag(os, ossimString("cntvoice"), false); + + openTag(os, ossimString("cntfax"), false); + os << find(ossimString("/metadata/metainfo/metc/cntinfo/cntfax")); + closeTag(os, ossimString("cntfax"), false); + + openTag(os, ossimString("cntemail"), false); + os << find(ossimString("/metadata/metainfo/metc/cntinfo/cntemail")); + closeTag(os, ossimString("cntemail"), false); + + closeTag(os, ossimString("cntinfo"), true); + closeTag(os, ossimString("metc"), true); + + openTag(os, ossimString("metstdn"), false); + os << find(ossimString("/metadata/metainfo/metstdn")); + closeTag(os, ossimString("metstdn"), false); + + openTag(os, ossimString("metstdv"), false); + os << find(ossimString("/metadata/metainfo/metstdv")); + closeTag(os, ossimString("metstdv"), false); + + closeTag(os, ossimString("metainfo"), true); + closeTag(os, ossimString("metadata"), true); + + os.close(); + + return true; +} + +bool ossimFgdcFileWriter::writeTemplate(const ossimFilename& file) const +{ + ofstream os(file.c_str()); + if (!os) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimFgdcFileWriter::writeTemplate Could not open: " << file + << endl; + return false; + } + + os << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n" + << "<?xml-stylesheet type=\"text/xsl\" href=\"/common/fgdc_classic.xsl\" ?>\n"; + openTag(os, ossimString("metadata"), true); + openTag(os, ossimString("idinfo"), true); + openTag(os, ossimString("citation"), true); + openTag(os, ossimString("citeinfo"), true); + + openTag(os, ossimString("origin"), false); + closeTag(os, ossimString("origin"), false); + + openTag(os, ossimString("pubdate"), false); + closeTag(os, ossimString("pubdate"), false); + + openTag(os, ossimString("title"), false); + closeTag(os, ossimString("title"), false); + + openTag(os, ossimString("edition"), false); + closeTag(os, ossimString("edition"), false); + + openTag(os, ossimString("geoform"), false); + closeTag(os, ossimString("geoform"), false); + + openTag(os, ossimString("serinfo"), true); + openTag(os, ossimString("sername"), false); + + closeTag(os, ossimString("sername"), false); + + openTag(os, ossimString("issue"), false); + closeTag(os, ossimString("issue"), false); + + closeTag(os, ossimString("serinfo"), true); + + openTag(os, ossimString("pubinfo"), true); + + openTag(os, ossimString("pubplace"), false); + + closeTag(os, ossimString("pubplace"), false); + + openTag(os, ossimString("publish"), false); + closeTag(os, ossimString("publish"), false); + + closeTag(os, ossimString("pubinfo"), true); + closeTag(os, ossimString("citeinfo"), true); + closeTag(os, ossimString("citation"), true); + + openTag(os, ossimString("descript"), true); + + openTag(os, ossimString("abstract"), false); + closeTag(os, ossimString("abstract"), false); + + openTag(os, ossimString("purpose"), false); + closeTag(os, ossimString("purpose"), false); + + openTag(os, ossimString("supplinf"), false); + closeTag(os, ossimString("supplinf"), false); + + closeTag(os, ossimString("descript"), true); + + openTag(os, ossimString("timeperd"), true); + openTag(os, ossimString("timeinfo"), true); + openTag(os, ossimString("sngdate"), true); + + openTag(os, ossimString("caldate"), false); + closeTag(os, ossimString("caldate"), false); + + closeTag(os, ossimString("sngdate"), true); + closeTag(os, ossimString("timeinfo"), true); + + + openTag(os, ossimString("current"), false); + closeTag(os, ossimString("current"), false); + + closeTag(os, ossimString("timeperd"), true); + + openTag(os, ossimString("status"), true); + + openTag(os, ossimString("progress"), false); + closeTag(os, ossimString("progress"), false); + + openTag(os, ossimString("update"), false); + closeTag(os, ossimString("update"), false); + + closeTag(os, ossimString("status"), true); + + openTag(os, ossimString("spdom"), true); + openTag(os, ossimString("bounding"), true); + + openTag(os, ossimString("westbc"), false); + closeTag(os, ossimString("westbc"), false); + openTag(os, ossimString("eastbc"), false); + + closeTag(os, ossimString("eastbc"), false); + openTag(os, ossimString("northbc"), false); + + closeTag(os, ossimString("northbc"), false); + openTag(os, ossimString("southbc"), false); + + closeTag(os, ossimString("southbc"), false); + + closeTag(os, ossimString("bounding"), true); + closeTag(os, ossimString("spdom"), true); + + openTag(os, ossimString("keywords"), true); + + openTag(os, ossimString("theme"), true); + + openTag(os, ossimString("themekt"), false); + closeTag(os, ossimString("themekt"), false); + + openTag(os, ossimString("themekey"), false); + closeTag(os, ossimString("themekey"), false); + + closeTag(os, ossimString("theme"), true); + + closeTag(os, ossimString("keywords"), true); + + openTag(os, ossimString("accconst"), false); + closeTag(os, ossimString("accconst"), false); + + openTag(os, ossimString("useconst"), false); + closeTag(os, ossimString("useconst"), false); + + openTag(os, ossimString("ptcontac"), true); + + openTag(os, ossimString("cntinfo"), true); + + openTag(os, ossimString("cntperp"), true); + openTag(os, ossimString("cntper"), false); + closeTag(os, ossimString("cntper"), false); + closeTag(os, ossimString("cntperp"), true); + + openTag(os, ossimString("cntaddr"), true); + + openTag(os, ossimString("addrtype"), false); + closeTag(os, ossimString("addrtype"), false); + + openTag(os, ossimString("address"), false); + closeTag(os, ossimString("address"), false); + + openTag(os, ossimString("city"), false); + closeTag(os, ossimString("city"), false); + + openTag(os, ossimString("state"), false); + closeTag(os, ossimString("state"), false); + + openTag(os, ossimString("postal"), false); + closeTag(os, ossimString("postal"), false); + + openTag(os, ossimString("country"), false); + closeTag(os, ossimString("country"), false); + + closeTag(os, ossimString("cntaddr"), true); + + openTag(os, ossimString("cntvoice"), false); + closeTag(os, ossimString("cntvoice"), false); + + openTag(os, ossimString("cntfax"), false); + closeTag(os, ossimString("cntfax"), false); + + openTag(os, ossimString("cntemail"), false); + closeTag(os, ossimString("cntemail"), false); + + closeTag(os, ossimString("cntinfo"), true); + + closeTag(os, ossimString("ptcontac"), true); + + openTag(os, ossimString("secinfo"), true); + openTag(os, ossimString("secclass"), false); + closeTag(os, ossimString("secclass"), false); + openTag(os, ossimString("secsys"), false); + closeTag(os, ossimString("secsys"), false); + openTag(os, ossimString("sechandl"), false); + closeTag(os, ossimString("sechandl"), false); + closeTag(os, ossimString("secinfo"), true); + + closeTag(os, ossimString("idinfo"), true); + + openTag(os, ossimString("distinfo"), true); + openTag(os, ossimString("distrib"), true); + openTag(os, ossimString("cntinfo"), true); + openTag(os, ossimString("cntperp"), true); + openTag(os, ossimString("cntper"), false); + closeTag(os, ossimString("cntper"), false); + closeTag(os, ossimString("cntperp"), true); + + openTag(os, ossimString("cntaddr"), true); + + openTag(os, ossimString("addrtype"), false); + closeTag(os, ossimString("addrtype"), false); + + openTag(os, ossimString("address"), false); + closeTag(os, ossimString("address"), false); + + openTag(os, ossimString("city"), false); + closeTag(os, ossimString("city"), false); + + openTag(os, ossimString("state"), false); + closeTag(os, ossimString("state"), false); + + openTag(os, ossimString("postal"), false); + closeTag(os, ossimString("postal"), false); + + openTag(os, ossimString("country"), false); + closeTag(os, ossimString("country"), false); + + closeTag(os, ossimString("cntaddr"), true); + + openTag(os, ossimString("cntvoice"), false); + closeTag(os, ossimString("cntvoice"), false); + + openTag(os, ossimString("cntfax"), false); + closeTag(os, ossimString("cntfax"), false); + + openTag(os, ossimString("cntemail"), false); + closeTag(os, ossimString("cntemail"), false); + + closeTag(os, ossimString("cntinfo"), true); + closeTag(os, ossimString("distrib"), true); + + openTag(os, ossimString("resdesc"), false); + closeTag(os, ossimString("resdesc"), false); + + openTag(os, ossimString("distliab"), false); + closeTag(os, ossimString("distliab"), false); + + openTag(os, ossimString("stdorder"), true); + openTag(os, ossimString("digform"), true); + openTag(os, ossimString("digtinfo"), true); + + openTag(os, ossimString("formname"), false); + closeTag(os, ossimString("formname"), false); + + closeTag(os, ossimString("digtinfo"), true); + + openTag(os, ossimString("digtopt"), true); + openTag(os, ossimString("onlinopt"), true); + openTag(os, ossimString("computer"), true); + openTag(os, ossimString("networka"), true); + + openTag(os, ossimString("networkr"), false); + closeTag(os, ossimString("networkr"), false); + + closeTag(os, ossimString("networka"), true); + closeTag(os, ossimString("computer"), true); + closeTag(os, ossimString("onlinopt"), true); + closeTag(os, ossimString("digtopt"), true); + closeTag(os, ossimString("digform"), true); + + openTag(os, ossimString("fees"), false); + closeTag(os, ossimString("fees"), false); + + closeTag(os, ossimString("stdorder"), true); + closeTag(os, ossimString("distinfo"), true); + + openTag(os, ossimString("metainfo"), true); + + openTag(os, ossimString("metd"), false); + closeTag(os, ossimString("metd"), false); + + openTag(os, ossimString("metc"), true); + openTag(os, ossimString("cntinfo"), true); + openTag(os, ossimString("cntperp"), true); + + openTag(os, ossimString("cntper"), false); + closeTag(os, ossimString("cntper"), false); + + closeTag(os, ossimString("cntperp"), true); + + openTag(os, ossimString("cntaddr"), true); + + openTag(os, ossimString("addrtype"), false); + closeTag(os, ossimString("addrtype"), false); + + openTag(os, ossimString("address"), false); + closeTag(os, ossimString("address"), false); + + openTag(os, ossimString("city"), false); + closeTag(os, ossimString("city"), false); + + openTag(os, ossimString("state"), false); + closeTag(os, ossimString("state"), false); + + openTag(os, ossimString("postal"), false); + closeTag(os, ossimString("postal"), false); + + openTag(os, ossimString("country"), false); + closeTag(os, ossimString("country"), false); + + closeTag(os, ossimString("cntaddr"), true); + + openTag(os, ossimString("cntvoice"), false); + closeTag(os, ossimString("cntvoice"), false); + + openTag(os, ossimString("cntfax"), false); + closeTag(os, ossimString("cntfax"), false); + + openTag(os, ossimString("cntemail"), false); + closeTag(os, ossimString("cntemail"), false); + + closeTag(os, ossimString("cntinfo"), true); + closeTag(os, ossimString("metc"), true); + + openTag(os, ossimString("metstdn"), false); + closeTag(os, ossimString("metstdn"), false); + + openTag(os, ossimString("metstdv"), false); + closeTag(os, ossimString("metstdv"), false); + + closeTag(os, ossimString("metainfo"), true); + closeTag(os, ossimString("metadata"), true); + + os.close(); + + ossimNotify(ossimNotifyLevel_NOTICE) + << "Wrote file: " << file.c_str() << endl; + + return true; +} + +bool ossimFgdcFileWriter::loadState (const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* lookup = kwl.find(prefix, "template"); + if (lookup) + { + setTemplate(ossimFilename(lookup)); + } + lookup = kwl.find(prefix, "source_image_filename"); + if (lookup) + { + theSourceImageFilename = lookup; + } + lookup = kwl.find(prefix, "tab_string"); + if (lookup) + { + theTabString = lookup; + } + lookup = kwl.find(prefix, "fgdc_template_doc"); + if (lookup) + { + setTemplate(ossimFilename(lookup)); + } + + return ossimMetadataFileWriter::loadState(kwl, prefix); +} + +ossim_uint32 ossimFgdcFileWriter::getIndentionLevel() const +{ + return theIndentionLevel; +} + +void ossimFgdcFileWriter::setIndentionLevel(ossim_uint32 level) +{ + theIndentionLevel = level; +} + +ossimString ossimFgdcFileWriter::getTabString() const +{ + return theTabString; +} + +void ossimFgdcFileWriter::setTabString(const ossimString& tabString) +{ + theTabString = tabString; +} + +void ossimFgdcFileWriter::openTag(std::ostream& os, + const ossimString& tag, + bool newLine) const +{ + if ( theIndentionLevel && theTabString.size() ) + { + ossimString tab; + for (ossim_uint32 i = 0; i < theIndentionLevel; ++i) + { + tab += theTabString; + } + + os << tab.c_str(); + } + + os << "<" << tag.c_str() << ">"; + + if (newLine) + { + os << "\n"; + ++theIndentionLevel; + } +} + +void ossimFgdcFileWriter::closeTag(std::ostream& os, + const ossimString& tag, + bool decrementLevel) const +{ + if ( decrementLevel && (theIndentionLevel > 1) && theTabString.size() ) + { + ossimString tab; + for (ossim_uint32 i = 0; i < theIndentionLevel-1; ++i) + { + tab += theTabString; + } + + os << tab.c_str(); + } + + os << "</" << tag.c_str() << ">\n"; + + if (theIndentionLevel && decrementLevel) + { + --theIndentionLevel; + } +} + +void ossimFgdcFileWriter::setTemplate(const ossimFilename& xmlTemplateFile) +{ + theTemplate.openFile(xmlTemplateFile); +} + +ossimString ossimFgdcFileWriter::find(const ossimString& xpath) const +{ + ossimString result; + + if (theTemplate.getErrorStatus()) + { + return result; + } + + vector< ossimRefPtr<ossimXmlNode> > xml_nodes; + theTemplate.findNodes(xpath, xml_nodes); + + if (xml_nodes.size()) + { + if (xml_nodes[0].valid()) + { + result = xml_nodes[0]->getText(); + } + } + return result; +} + +void ossimFgdcFileWriter::getMetadatatypeList( + std::vector<ossimString>& metadatatypeList) const +{ + metadatatypeList.push_back(ossimString("ossim_fgdc")); +} + +bool ossimFgdcFileWriter::hasMetadataType( + const ossimString& metadataType)const +{ + return (metadataType == "ossim_fgdc"); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/metadata/ossimFgdcFileWriter.h b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimFgdcFileWriter.h new file mode 100644 index 0000000000..dae3e8ecae --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimFgdcFileWriter.h @@ -0,0 +1,157 @@ +//---------------------------------------------------------------------------- +// Copyright (c) 2005, David Burken, all rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: Class to write out meta data in a Federal Geographic Data +// Committe (FGDC) format. +// +//---------------------------------------------------------------------------- +// $Id: ossimFgdcFileWriter.h,v 1.2 2005/08/11 18:58:33 gpotts Exp $ +#ifndef ossimFgdcFileWriter_HEADER +#define ossimFgdcFileWriter_HEADER + +#include <imaging/metadata/ossimMetadataFileWriter.h> +#include <base/data_types/ossimXmlNode.h> +#include <base/data_types/ossimXmlDocument.h> + +/** + * Class to write out meta data in a Federal Geographic Data + * Committe (FGDC) format. + */ +class OSSIMDLLEXPORT ossimFgdcFileWriter : public ossimMetadataFileWriter +{ +public: + + /** constructor */ + ossimFgdcFileWriter(); + + /** destructor */ + virtual ~ossimFgdcFileWriter(); + + /** + * Method to load the state from a keyword list. + * + * @param kwl Keyword list to load state from. + * + * @param prefix Prefix to attatch to keyword (like "object1."). + * default=NULL + * + * @return true if ok or false on error. + * + * Keywords picked up by this loadState: + * + * source_image_filename: foo.ntf + * tab_string: "\t" + * fgdc_template_doc: fgdc_template.xml + * + */ + virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0); + + /** + * Satisfies pure virtual from ossimMetadataWriter base. + * + * Appends the writers image types to the "metadatatypeList". + * + * @param metadatatypeList stl::vector<ossimString> list to append to. + * + * @note Appends to the list, does not clear it first. + */ + virtual void getMetadatatypeList( + std::vector<ossimString>& metadatatypeList) const; + + /** + * Satisfies pure virtual from ossimMetadataWriter base. + * + * @param imageType string representing image type. + * + * @return true if "metadataType" is supported by writer. + */ + virtual bool hasMetadataType(const ossimString& metadataType)const; + + + /** @return Returns the current indentation level. */ + ossim_uint32 getIndentionLevel() const; + + /** + * Sets the current indentation level. + * + * @param level Indentation level. "0" equals no indentation. + */ + void setIndentionLevel(ossim_uint32 level); + + /** + * @return The current tab string e.g.: "\t". + */ + ossimString getTabString() const; + + /** + * Sets the tab string. Usually "\t" or spaces " ". + * + * @param tabString String to use for indentation. + */ + void setTabString(const ossimString& tabString); + + /** + * @param title Tile of data usually the image file name. + */ + void setTitle(const ossimString& pubDate); + + void setTemplate(const ossimFilename& xmlTemplateFile); + + ossimString find(const ossimString& xpath) const; + + bool writeTemplate(const ossimFilename& file) const; + +protected: + + /** + * Writes file to disk. + * + * @return true on success, false on failure. + */ + virtual bool writeFile(); + +private: + + /** + * Writes openning tag adding any indentation and brackets. Increments + * indentation level. + * + * @param os otream to write to. + * + * @param tag String representing tag with no brackets, i.e. "metadata". + * + * @param newLine If true a new line "\n" is added. + */ + void openTag(std::ostream& os, + const ossimString& tag, + bool newLine) const; + + /** + * Closes tag decrementing indentation. + * e.g.: <metadata> + * + * @param os otream to write to. + * + * @param tag String representing tag with no brackets. + * + * @param decrementLevel If true indentation level is decremented. + */ + void closeTag(std::ostream& os, + const ossimString& tag, + bool decrementLevel) const; + + mutable ossim_uint32 theIndentionLevel; + ossimString theTabString; + ossimXmlDocument theTemplate; + ossimFilename theSourceImageFilename; + +TYPE_DATA +}; + +#endif /* End of "#ifndef ossimFgdcFileWriter_HEADER" */ diff --git a/Utilities/OSSIM/ossim_core/imaging/metadata/ossimGeomFileWriter.cpp b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimGeomFileWriter.cpp new file mode 100644 index 0000000000..e53cff2eec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimGeomFileWriter.cpp @@ -0,0 +1,96 @@ +//******************************************************************* +// Copyright (C) 2003 Storage Area Networks, Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: Kenneth Melero (kmelero@sanz.com) +// +//******************************************************************* +// $Id: ossimGeomFileWriter.cpp,v 1.9 2006/01/06 16:57:04 dburken Exp $ + +#include <imaging/metadata/ossimGeomFileWriter.h> +#include <base/common/ossimKeywordNames.h> +#include <base/common/ossimTrace.h> +#include <base/data_types/ossimKeywordlist.h> +#include <projections/map_projections/ossimMapProjection.h> +#include <projections/map_projections/ossimMapProjectionInfo.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <imaging/formats/ossimImageHandler.h> +#include <imaging/ossimImageData.h> +#include <imaging/ossimImageSource.h> + +RTTI_DEF1(ossimGeomFileWriter, + "ossimGeomFileWriter", + ossimMetadataFileWriter) + +static const char DEFAULT_FILE_NAME[] = "output.geom"; + +static ossimTrace traceDebug("ossimGeomFileWriter:debug"); + +ossimGeomFileWriter::ossimGeomFileWriter() + : + ossimMetadataFileWriter() +{} + +ossimGeomFileWriter::~ossimGeomFileWriter() +{} + +bool ossimGeomFileWriter::writeFile() +{ + // Get the geometry from the input. + ossimKeywordlist kwl; + theInputConnection->getImageGeometry(kwl); + + // Create the projection. + ossimRefPtr<ossimProjection> proj = + ossimProjectionFactoryRegistry::instance()->createProjection(kwl); + if (!proj.valid()) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimGeomFileWriter::writeFile DEBUG:" + << "\nCreate projection failed!" + << "\nGeometry kwl: " << kwl + << endl; + } + + return false; + } + + ossimMapProjection* mapProj = PTR_CAST(ossimMapProjection, proj.get()); + if (!mapProj) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimGeomFileWriter::writeFile DEBUG:" + << "\nNot a map projection!" + << endl; + } + + return false; + } + + // Create the projection info. + ossimRefPtr<ossimMapProjectionInfo> projectionInfo + = new ossimMapProjectionInfo(mapProj, theAreaOfInterest); + + // Set the tie points. + projectionInfo->getGeom(kwl); + + // Write it to disk. + return kwl.write(theFilename.c_str()); +} + +void ossimGeomFileWriter::getMetadatatypeList( + std::vector<ossimString>& metadatatypeList) const +{ + metadatatypeList.push_back(ossimString("ossim_geometry")); +} + +bool ossimGeomFileWriter::hasMetadataType( + const ossimString& metadataType)const +{ + return (metadataType == "ossim_geometry"); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/metadata/ossimGeomFileWriter.h b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimGeomFileWriter.h new file mode 100644 index 0000000000..24b53f3a46 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimGeomFileWriter.h @@ -0,0 +1,57 @@ +//******************************************************************* +// Copyright (C) 2003 Storage Area Networks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Kenneth Melero (kmelero@sanz.com) +// +//******************************************************************* +// $Id: ossimGeomFileWriter.h,v 1.7 2005/08/08 22:00:24 dburken Exp $ + +#ifndef ossimGeomFileWriter_H +#define ossimGeomFileWriter_H + +#include <imaging/metadata/ossimMetadataFileWriter.h> + +/** ossimGeomFileWriter */ +class OSSIMDLLEXPORT ossimGeomFileWriter : public ossimMetadataFileWriter +{ +public: + /** default constructor */ + ossimGeomFileWriter(); + + /** virtual destructor */ + virtual ~ossimGeomFileWriter(); + + /** + * Satisfies pure virtual from ossimMetadataWriter base. + * + * Appends the writers image types to the "metadatatypeList". + * + * @param metadatatypeList stl::vector<ossimString> list to append to. + * + * @note Appends to the list, does not clear it first. + */ + virtual void getMetadatatypeList( + std::vector<ossimString>& metadatatypeList) const; + + /** + * Satisfies pure virtual from ossimMetadataWriter base. + * + * @param imageType string representing image type. + * + * @return true if "metadataType" is supported by writer. + */ + virtual bool hasMetadataType(const ossimString& metadataType)const; + +private: + + /** Write a geometry file to "theFilename". */ + virtual bool writeFile(); + +TYPE_DATA +}; + +#endif /* End of #ifndef ossimGeomFileWriter_H */ diff --git a/Utilities/OSSIM/ossim_core/imaging/metadata/ossimJpegWorldFileWriter.cpp b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimJpegWorldFileWriter.cpp new file mode 100644 index 0000000000..14d52e775b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimJpegWorldFileWriter.cpp @@ -0,0 +1,119 @@ +//******************************************************************* +// Copyright (C) 2003 Storage Area Networks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Kenneth Melero +// +//******************************************************************* +// $Id: ossimJpegWorldFileWriter.cpp,v 1.7 2005/08/08 22:00:24 dburken Exp $ + +#include <stdio.h> +#include <imaging/metadata/ossimJpegWorldFileWriter.h> +#include <base/common/ossimKeywordNames.h> +#include <base/common/ossimTrace.h> +#include <base/common/ossimRefPtr.h> +#include <base/data_types/ossimKeywordlist.h> +#include <projections/map_projections/ossimMapProjection.h> +#include <projections/map_projections/ossimMapProjectionInfo.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <imaging/formats/ossimImageHandler.h> +#include <imaging/ossimImageData.h> +#include <imaging/ossimImageSource.h> + +RTTI_DEF1(ossimJpegWorldFileWriter, + "ossimJpegWorldFileWriter", + ossimMetadataFileWriter) + +static const char DEFAULT_FILE_NAME[] = "output.jgw"; +static ossimTrace traceDebug("ossimJpegWorldFileWriter:debug"); + +ossimJpegWorldFileWriter::ossimJpegWorldFileWriter() + : + ossimMetadataFileWriter() +{ +} + +ossimJpegWorldFileWriter::~ossimJpegWorldFileWriter() +{ +} + +bool ossimJpegWorldFileWriter::writeFile() +{ + if(!theInputConnection) + { + return false; + } + + std::ofstream out(theFilename.c_str(), ios_base::out); + if (!out) + { + return false; + } + + // Get the geometry. + ossimKeywordlist kwl; + if (!theInputConnection->getImageGeometry(kwl)) + { + return false; + } + + // Make the projection. + ossimRefPtr<ossimProjection> proj = + ossimProjectionFactoryRegistry::instance()->createProjection(kwl); + if (!proj) + { + return false; + } + + // Cast to map projection. + ossimMapProjection* mapProj = PTR_CAST(ossimMapProjection, proj.get()); + if (!mapProj) + { + return false; + } + + // Create the map projection info. + ossimRefPtr<ossimMapProjectionInfo> projectionInfo + = new ossimMapProjectionInfo(mapProj, theAreaOfInterest); + + ossimDpt gsd; + ossimDpt ul; + + if(projectionInfo->getProjection()->isGeographic()) + { + gsd = projectionInfo->getDecimalDegreesPerPixel(); + ul = projectionInfo->ulGroundPt(); + } + else + { + gsd = projectionInfo->getMetersPerPixel(); + ul = projectionInfo->ulEastingNorthingPt(); + } + + out << setiosflags(ios::fixed) << setprecision(15) + << gsd.x << endl + << 0.0 << endl // rotation value X + << 0.0 << endl // rotation value y + << -gsd.y << endl + << ul.u << endl + << ul.v << endl; + + out.close(); + + return true; +} + +void ossimJpegWorldFileWriter::getMetadatatypeList( + std::vector<ossimString>& metadatatypeList) const +{ + metadatatypeList.push_back(ossimString("jpeg_world_file")); +} + +bool ossimJpegWorldFileWriter::hasMetadataType( + const ossimString& metadataType)const +{ + return (metadataType == "jpeg_world_file"); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/metadata/ossimJpegWorldFileWriter.h b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimJpegWorldFileWriter.h new file mode 100644 index 0000000000..313a931d2e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimJpegWorldFileWriter.h @@ -0,0 +1,57 @@ +//******************************************************************* +// Copyright (C) 2003 Storage Area Networks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Kenneth Melero (kmelero@sanz.com) +// +//******************************************************************* +// $Id: ossimJpegWorldFileWriter.h,v 1.4 2005/08/08 22:00:24 dburken Exp $ + +#ifndef ossimJpegWorldFileWriter_H +#define ossimJpegWorldFileWriter_H + +#include <fstream> +#include <imaging/metadata/ossimMetadataFileWriter.h> +#include <base/data_types/ossimKeywordlist.h> + + +/** ossimJpegWorldFileWriter */ +class OSSIMDLLEXPORT ossimJpegWorldFileWriter : public ossimMetadataFileWriter +{ +public: + + ossimJpegWorldFileWriter(); + + virtual ~ossimJpegWorldFileWriter(); + + /** + * Satisfies pure virtual from ossimMetadataWriter base. + * + * Appends the writers image types to the "metadatatypeList". + * + * @param metadatatypeList stl::vector<ossimString> list to append to. + * + * @note Appends to the list, does not clear it first. + */ + virtual void getMetadatatypeList( + std::vector<ossimString>& metadatatypeList) const; + + /** + * Satisfies pure virtual from ossimMetadataWriter base. + * + * @param imageType string representing image type. + * + * @return true if "metadataType" is supported by writer. + */ + virtual bool hasMetadataType(const ossimString& metadataType)const; + +private: + virtual bool writeFile(); + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/metadata/ossimMetadataFileWriter.cpp b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimMetadataFileWriter.cpp new file mode 100644 index 0000000000..9305bce923 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimMetadataFileWriter.cpp @@ -0,0 +1,240 @@ +//******************************************************************* +// Copyright (C) 2003 Stroage Area Networks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Kenneth Melero (kmelero@sanz.com) +// +//******************************************************************* +// $Id: ossimMetadataFileWriter.cpp,v 1.8 2005/06/19 16:07:29 dburken Exp $ + +#include <imaging/metadata/ossimMetadataFileWriter.h> +#include <base/common/ossimTrace.h> +#include <base/common/ossimViewController.h> +#include <base/common/ossimKeywordNames.h> +#include <base/context/ossimErrorContext.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimFilename.h> +#include <imaging/factory/ossimImageHandlerRegistry.h> +#include <imaging/formats/ossimImageHandler.h> + + +RTTI_DEF3(ossimMetadataFileWriter, + "ossimMetadataFileWriter", + ossimConnectableObject, + ossimProcessInterface, + ossimConnectableObjectListener); + +static ossimTrace traceDebug("ossimMetadataFileWriter:degug"); + +ossimMetadataFileWriter::ossimMetadataFileWriter() + : + ossimProcessInterface(), + ossimConnectableObjectListener(), + theInputConnection(NULL), + theFilename(), + thePixelType(OSSIM_PIXEL_IS_POINT), + theAreaOfInterest() +{ + theAreaOfInterest.makeNan(); +} + +ossimMetadataFileWriter::~ossimMetadataFileWriter() +{ +} + +void ossimMetadataFileWriter::initialize() +{ + theInputConnection = PTR_CAST(ossimImageSourceInterface, + getInput()); +} + +bool ossimMetadataFileWriter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + bool result = ossimConnectableObject::loadState(kwl, prefix); + + // Get the filename... + const char* lookup = kwl.find(prefix, ossimKeywordNames::FILENAME_KW); + if(lookup) + { + ossimString filename = lookup; + + setFilename(filename); + } + + // Note: Defaulted to point in constructor. + lookup = kwl.find(prefix, ossimKeywordNames::PIXEL_TYPE_KW); + if (lookup) + { + ossimString s = lookup; + s.downcase(); + if (s.contains("area")) + { + thePixelType = OSSIM_PIXEL_IS_AREA; + } + else if (s.contains("point")) + { + thePixelType = OSSIM_PIXEL_IS_POINT; + } + } + + if(theInputObjectList.size() != 1) + { + theInputObjectList.resize(1); + theInputListIsFixedFlag = true; + } + + theOutputListIsFixedFlag = false; + + return result; +} + +void ossimMetadataFileWriter::disconnectInputEvent(ossimConnectionEvent& event) +{ + initialize(); +} + +void ossimMetadataFileWriter::connectInputEvent(ossimConnectionEvent& event) +{ + theInputConnection = PTR_CAST(ossimImageSourceInterface, getInput()); + initialize(); +} + +void ossimMetadataFileWriter::propertyEvent(ossimPropertyEvent& event) +{ + initialize(); +} + +void ossimMetadataFileWriter::setPixelType(ossimPixelType pixelType) +{ + thePixelType = pixelType; +} + +ossimPixelType ossimMetadataFileWriter::getPixelType()const +{ + return thePixelType; +} + +ossimObject* ossimMetadataFileWriter::getObject() +{ + return this; +} + +const ossimObject* ossimMetadataFileWriter::getObject() const +{ + return this; +} + +bool ossimMetadataFileWriter::execute() +{ + bool result = false; + + if (!theInputConnection) + { + initialize(); + if (!theInputConnection) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimMetadataFileWriter::execute DEBUG:\n" + << "theInputConnection is null!" + << endl; + } + return result; + } + } + + if(theFilename == ossimFilename::NIL) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimMetadataFileWriter::execute DEBUG:\n" + << "theFilename is not set!" + << endl; + } + return result; + } + + //--- + // If theAreaOfInterest hasNans then it was probably not set so use + // the bounding rectangle of the input source. + //--- + if (theAreaOfInterest.hasNans()) + { + theAreaOfInterest = theInputConnection->getBoundingRect(); + if (theAreaOfInterest.hasNans()) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimMetadataFileWriter::execute DEBUG:\n" + << "theAreaOfInterest is not set!" + << endl; + } + return result; + } + } + + setProcessStatus(ossimProcessInterface::PROCESS_STATUS_EXECUTING); + + setPercentComplete(0.0); + + result = writeFile(); + + setProcessStatus(ossimProcessInterface::PROCESS_STATUS_NOT_EXECUTING); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimMetadataFileWriter::execute DEBUG:\n" + << (result?"successful":"unsuccessful") << " write of file: " + << theFilename + << endl; + } + + return result; +} + +void ossimMetadataFileWriter::setPercentComplete(double percentComplete) +{ + ossimProcessInterface::setPercentComplete(percentComplete); + ossimProcessProgressEvent event(this, + percentComplete); + fireEvent(event); +} + +void ossimMetadataFileWriter::setFilename(const ossimFilename& file) +{ + theFilename = file; +} + +const ossimFilename& ossimMetadataFileWriter::getFilename() const +{ + return theFilename; +} + +bool ossimMetadataFileWriter::canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object) const +{ + return (object && + ((PTR_CAST(ossimImageSourceInterface, object) && + inputIndex == 0)|| + (PTR_CAST(ossimViewController, object) && + inputIndex == 1))); +} + +void ossimMetadataFileWriter::setAreaOfInterest( + const ossimIrect& areaOfInterest) +{ + theAreaOfInterest = areaOfInterest; +} + +ossimIrect ossimMetadataFileWriter::getAreaOfInterest() const +{ + return theAreaOfInterest; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/metadata/ossimMetadataFileWriter.h b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimMetadataFileWriter.h new file mode 100644 index 0000000000..e220df010e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimMetadataFileWriter.h @@ -0,0 +1,149 @@ +//******************************************************************* +// Copyright (C) 2003 Storage Area Networks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Kenneth Melero (kmelero@sanz.com) +// +//******************************************************************* +// $Id: ossimMetadataFileWriter.h,v 1.12 2005/08/08 22:00:24 dburken Exp $ + +#ifndef ossimMetadataFileWriter_H +#define ossimMetadataFileWriter_H + +#include <base/common/ossimConstants.h> +#include <base/common/ossimConnectableObject.h> +#include <base/common/ossimProcessInterface.h> +#include <base/common/events/ossimConnectableObjectListener.h> +#include <base/data_types/ossimFilename.h> +#include <base/data_types/ossimIrect.h> +#include <base/common/events/ossimObjectEvents.h> +#include <base/common/events/ossimProcessProgressEvent.h> + +class ossimImageSourceInterface; + +/** + * ossimMetadataFileWriter + * + * Typical usage something like this: + * + * ossimObject* obj = ossimImageMetaDataWriterRegistry::instance()-> + * createObject(ossimString("ossimReadmeFileWriter")); + * if (!obj) + * { + * return; + * } + * ossimMetadataFileWriter* mw = PTR_CAST(ossimMetadataFileWriter, obj); + * if (!mw) + * { + * return; + * } + * + * mw->setFilename(xmlFile); + * mw->loadState(kwl); + * mw->connectMyInputTo(ih.get()); + * mw->execute(); + * delete mw; + */ +class OSSIMDLLEXPORT ossimMetadataFileWriter : + public ossimConnectableObject, + public ossimProcessInterface, + public ossimConnectableObjectListener +{ +public: + ossimMetadataFileWriter(); + + virtual ~ossimMetadataFileWriter(); + + virtual ossimObject* getObject(); + virtual const ossimObject* getObject() const; + + virtual void initialize(); + + virtual bool execute(); + + virtual void setPercentComplete(double percentComplete); + + virtual void setFilename(const ossimFilename& file); + + const ossimFilename& getFilename()const; + + virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix = 0); + + bool canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object) const; + + virtual void disconnectInputEvent(ossimConnectionEvent& event); + virtual void connectInputEvent(ossimConnectionEvent& event); + virtual void propertyEvent(ossimPropertyEvent& event); + + /** + * Ossim uses a concept of "pixel is point" internally. + * + * This means that if you say a tie point is 30.0N -81.0W, the center of + * the pixel at the tie point is 30.0N -81.0W. + * + */ + virtual void setPixelType(ossimPixelType pixelType); + virtual ossimPixelType getPixelType() const; + + /** + * Sets the area of interest to write the meta data for. + * + * @param areaOfInterest Sets theAreaOfInterest. + * + * @note By default the writers will use + * "theInputConnection->getBoundingRect()" if theAreaOfInterest has nans. + */ + virtual void setAreaOfInterest(const ossimIrect& areaOfInterest); + + /** + * @returns theAreaOfInterest. + */ + virtual ossimIrect getAreaOfInterest() const; + + /** + * void getMetadatatypeList(std::vector<ossimString>& metadatatypeList)const + * + * pure virtual + * + * Appends the writers metadata types to the "metadatatypeList". + * + * This is the actual image type name. So for + * example, ossimTiffWorldFileWriter has tiff_world_file type. + * + * @param metadatatypeList stl::vector<ossimString> list to append to. + * + * @note All writers should append to the list, not, clear it and then add + * their types. + */ + virtual void getMetadatatypeList( + std::vector<ossimString>& metadatatypeList)const=0; + + /** + * bool hasMetadataType(const ossimString& metadataType) const + * + * @param imageType string representing image type. + * + * @return true if "metadataType" is supported by writer. + */ + virtual bool hasMetadataType(const ossimString& metadataType)const=0; + +protected: + /** + * Write out the file. + * @return true on success, false on error. + */ + virtual bool writeFile() = 0; + + ossimImageSourceInterface* theInputConnection; + ossimFilename theFilename; + ossimPixelType thePixelType; + ossimIrect theAreaOfInterest; + +TYPE_DATA +}; + +#endif /* End of #ifndef ossimMetadataFileWriter_H */ diff --git a/Utilities/OSSIM/ossim_core/imaging/metadata/ossimReadmeFileWriter.cpp b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimReadmeFileWriter.cpp new file mode 100644 index 0000000000..c7fa067eaa --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimReadmeFileWriter.cpp @@ -0,0 +1,476 @@ +//******************************************************************* +// Copyright (C) 2003 Storage Area Networks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Kenneth Melero (kmelero@sanz.com) +// +//******************************************************************* +// $Id: ossimReadmeFileWriter.cpp,v 1.8 2005/08/08 22:00:24 dburken Exp $ + +#include <iostream> +using namespace std; + +#include <imaging/metadata/ossimReadmeFileWriter.h> +#include <base/common/ossimKeywordNames.h> +#include <base/common/ossimTrace.h> +#include <base/data_types/ossimKeywordlist.h> +#include <projections/map_projections/ossimMapProjection.h> +#include <projections/map_projections/ossimMapProjectionInfo.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <imaging/formats/ossimImageHandler.h> +#include <imaging/ossimImageData.h> +#include <imaging/ossimImageSource.h> + +RTTI_DEF1(ossimReadmeFileWriter, + "ossimReadmeFileWriter", + ossimMetadataFileWriter) + +static const char DEFAULT_FILE_NAME[] = "output_readme.txt"; +static ossimTrace traceDebug("ossimReadmeFileWriter:debug"); + +ossimReadmeFileWriter::ossimReadmeFileWriter() + : + ossimMetadataFileWriter() +{ +} + +ossimReadmeFileWriter::~ossimReadmeFileWriter() +{ +} + +bool ossimReadmeFileWriter::writeFile() +{ + static const char MODULE[] = "ossimReadmeFileWriter::writeFile"; + + if(!theInputConnection) + { + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nNo input connection! Returning..." + << endl; + } + + return false; + } + + std::ofstream out(theFilename.c_str(), ios_base::out); + if (!out) + { + return false; + } + + ossimKeywordlist kwl; + theInputConnection->getImageGeometry(kwl); + + ossimProjection* proj; + proj = ossimProjectionFactoryRegistry::instance()->createProjection(kwl); + if (!proj) + { + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nCould not create projection from geometry!" + << "\nGeometry keyword list dump:\n" + << kwl + << "\nReturning..." + << endl; + } + return false; + } + + ossimMapProjection* mapProj = PTR_CAST(ossimMapProjection, proj); + if (!mapProj) + { + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\nCould not create map projection from geometry!" + << "\nGeometry keyword list dump:\n" + << kwl + << "\nReturning..." + << endl; + } + + delete proj; + return false; + } + + ossimMapProjectionInfo* projectionInfo + = new ossimMapProjectionInfo(mapProj, theAreaOfInterest); + + if(projectionInfo) + { + + out << setiosflags(ios::fixed) + << setiosflags(ios::left) + << setw(16) << "Image: " + << projectionInfo->getImageInfoString(); + + out << setw(17) << "\nLines:" + << projectionInfo->linesPerImage() + << setw(17) << "\nSamples:" + << projectionInfo->pixelsPerLine() + << setw(17) << "\nPixel Size x:" + << setprecision(8) + << projectionInfo->getMetersPerPixel().x + << " meters"; + + out << ", " + << setprecision(8) + << projectionInfo->getUsSurveyFeetPerPixel().x + << " U.S. feet"; + + out << setw(17) << "\nPixel Size y:" + << setprecision(8) + << projectionInfo->getMetersPerPixel().y + << " meters"; + + out << ", " + << setprecision(8) + << projectionInfo->getUsSurveyFeetPerPixel().y + << " U.S. feet"; + + const char* type = kwl.find(ossimKeywordNames::TYPE_KW); + const char* zone = kwl.find(ossimKeywordNames::ZONE_KW); + const char* datum = kwl.find(ossimKeywordNames::DATUM_KW); + const char* ellipsoid = kwl.find(ossimKeywordNames::ELLIPSE_CODE_KW); + + if(type) + out << setw(17) << "\nProjection:" << type; + + if(zone) + out << setw(17) << "\nUTM map zone:" << zone; + + if(datum && ellipsoid) + out << setw(17) << "\nDatum:" << datum + << setw(17) << "\nEllipsoid:" + << ellipsoid; + + out << resetiosflags(ios::left) << endl; + + const ossimString NORTH = "N"; + const ossimString SOUTH = "S"; + const ossimString EAST = "E"; + const ossimString WEST = "W"; + + ossimString tmpString; + double tmpDouble; + + const char* falseEasting + = kwl.find(ossimKeywordNames::FALSE_EASTING_KW); + const char* falseNorthing + = kwl.find(ossimKeywordNames::FALSE_NORTHING_KW); + const char* parallel1 + = kwl.find(ossimKeywordNames::STD_PARALLEL_1_KW); + const char* parallel2 + = kwl.find(ossimKeywordNames::STD_PARALLEL_2_KW); + const char* scaleFactor + = kwl.find(ossimKeywordNames::SCALE_FACTOR_KW); + + ossimString proj_name = mapProj->getClassName(); + + if ( ( proj_name.contains("Lambert") ) || + ( proj_name.contains("Albers") ) || + ( proj_name.contains("TransverseMercator" ) ) ) + { + + double origin_lat = mapProj->origin().latd(); + tmpDouble = fabs(origin_lat); + tmpString = (origin_lat < 0.0) ? SOUTH : NORTH; + out << setiosflags(ios::left) + << "\n" + << setw(18) << "Origin Latitude:" + << resetiosflags(ios::left) + << setw(21) << setprecision(12) << tmpDouble + << tmpString << endl; + + double origin_lon = mapProj->origin().lond(); + tmpDouble = fabs(origin_lon); + tmpString = (origin_lon < 0.0) ? WEST : EAST; + out << setiosflags(ios::left) + << setw(18) << "Origin Longitude:" + << resetiosflags(ios::left) + << setw(21) << tmpDouble << tmpString + << setiosflags(ios::left) + << "\n" + << setw(23) << "False Easting:" + << resetiosflags(ios::left) + << setw(17) << setprecision(4) + << ossimString(falseEasting).toDouble(); + + out << " meters, " << setprecision(4) + << mtrs2usft(ossimString(falseEasting).toDouble()) + << " U.S. feet"; + + out << endl; + + out << setiosflags(ios::left) + << setw(23) << "False Northing:" + << resetiosflags(ios::left) + << setw(17) << setprecision(4) + << ossimString(falseNorthing).toDouble(); + + out << " meters, " << setprecision(4) + << mtrs2usft(ossimString(falseNorthing).toDouble()) + << " U.S. feet"; + + out << endl; + + } // End of if "Alber Lambert or TM. + + if (proj_name.contains("TransverseMercator")) + { + out << setiosflags(ios::left) + << "\n" + << setw(18) << "Scale Factor:" + << resetiosflags(ios::left) + << setw(21) << setprecision(10) + << ossimString(scaleFactor).toDouble() + << "\n" << endl; + } + + if ( (proj_name.contains("Lambert") ) || + (proj_name.contains("Albers") ) ) + { + double stdpar1 = ossimString(parallel1).toDouble(); + tmpDouble = fabs(stdpar1); + tmpString = (stdpar1 < 0.0) ? SOUTH : NORTH; + out << setiosflags(ios::left) + << setw(23) << "Standard Parallel #1:" + << resetiosflags(ios::left) + << setw(16) << setprecision(12) << tmpDouble + << tmpString << endl; + + double stdpar2 = ossimString(parallel2).toDouble(); + tmpDouble = fabs(stdpar2); + tmpString = (stdpar2 < 0.0) ? SOUTH : NORTH; + out << setiosflags(ios::left) + << setw(23) << "Standard Parallel #2:" + << resetiosflags(ios::left) + << setw(16) << setprecision(12) + << tmpDouble << tmpString + << "\n" << endl; + } + + ossimString cornerString[4] = { "Upper Left", + "Upper Right", + "Lower Right", + "Lower Left" }; + + //--- + // Add a note to the readme file stating what the corner coordinates + // are relative to. + //--- + if (projectionInfo->getPixelType() == OSSIM_PIXEL_IS_AREA) + { + out + << "\nCorner coordinates relative to outer edge of pixel.\n\n"; + } + else + { + out + << "\nCorner coordinates relative to center of pixel.\n\n"; + } + + out << "Corner Coordinates:\n\n"; + + //--- + // Upper Left Corner Points + //--- + tmpDouble = fabs(projectionInfo->ulGroundPt().latd()); + tmpString = (projectionInfo->ulGroundPt().latd() < 0.0) ? SOUTH : NORTH; + out << cornerString[0] << endl; + out << setw(14) << "Latitude: " + << setw(16) << setprecision(12) << tmpDouble + << tmpString << endl; + tmpDouble = fabs(projectionInfo->ulGroundPt().lond()); + tmpString = (projectionInfo->ulGroundPt().lond() < 0.0) ? WEST : EAST; + out << setw(14) << "Longitude: " + << setw(16) << tmpDouble << tmpString << endl; + + out << setw(14) << "Easting: " + << setw(17) << setprecision(4) + << projectionInfo->ulEastingNorthingPt().x; + + out << " meters, " << setprecision(4) + << mtrs2usft(projectionInfo->ulEastingNorthingPt().x) + << " U.S. feet"; + + out << endl + << setw(14) << "Northing: " + << setw(17) << projectionInfo->ulEastingNorthingPt().y; + + out << " meters, " << setprecision(4) + << mtrs2usft(projectionInfo->ulEastingNorthingPt().y) + << " U.S. feet"; + + out << endl << endl; + + //--- + // Upper Right Corner Points + //--- + tmpDouble = fabs(projectionInfo->urGroundPt().latd()); + tmpString = (projectionInfo->urGroundPt().latd() < 0.0) ? SOUTH : NORTH; + out << cornerString[1] << endl; + out << setw(14) << "Latitude: " + << setw(16) << setprecision(12) << tmpDouble + << tmpString << endl; + tmpDouble = fabs(projectionInfo->urGroundPt().lond()); + tmpString = (projectionInfo->urGroundPt().lond() < 0.0) ? WEST : EAST; + out << setw(14) << "Longitude: " + << setw(16) << tmpDouble << tmpString << endl; + + out << setw(14) << "Easting: " + << setw(17) << setprecision(4) + << projectionInfo->urEastingNorthingPt().x; + + out << " meters, " << setprecision(4) + << mtrs2usft(projectionInfo->urEastingNorthingPt().x) + << " U.S. feet"; + + out << endl + << setw(14) << "Northing: " + << setw(17) << projectionInfo->urEastingNorthingPt().y; + + out << " meters, " << setprecision(4) + << mtrs2usft(projectionInfo->urEastingNorthingPt().y) + << " U.S. feet"; + + out << endl << endl; + + //--- + // Lower Right Corner Points + //--- + tmpDouble = fabs(projectionInfo->lrGroundPt().latd()); + tmpString = (projectionInfo->lrGroundPt().latd() < 0.0) ? SOUTH : NORTH; + out << cornerString[2] << endl; + out << setw(14) << "Latitude: " + << setw(16) << setprecision(12) << tmpDouble + << tmpString << endl; + tmpDouble = fabs(projectionInfo->lrGroundPt().lond()); + tmpString = (projectionInfo->lrGroundPt().lond() < 0.0) ? WEST : EAST; + out << setw(14) << "Longitude: " + << setw(16) << tmpDouble << tmpString << endl; + + out << setw(14) << "Easting: " + << setw(17) << setprecision(4) + << projectionInfo->lrEastingNorthingPt().x; + + out << " meters, " << setprecision(4) + << mtrs2usft(projectionInfo->lrEastingNorthingPt().x) + << " U.S. feet"; + + out << endl + << setw(14) << "Northing: " + << setw(17) << projectionInfo->lrEastingNorthingPt().y; + + out << " meters, " << setprecision(4) + << mtrs2usft(projectionInfo->lrEastingNorthingPt().y) + << " U.S. feet"; + + out << endl << endl; + + //--- + // Lower Left Corner Points + //--- + tmpDouble = fabs(projectionInfo->llGroundPt().latd()); + tmpString = (projectionInfo->llGroundPt().latd() < 0.0) ? SOUTH : NORTH; + out << cornerString[3] << endl; + out << setw(14) << "Latitude: " + << setw(16) << setprecision(12) << tmpDouble + << tmpString << endl; + tmpDouble = fabs(projectionInfo->llGroundPt().lond()); + tmpString = (projectionInfo->llGroundPt().lond() < 0.0) ? WEST : EAST; + out << setw(14) << "Longitude: " + << setw(16) << tmpDouble << tmpString << endl; + + out << setw(14) << "Easting: " + << setw(17) << setprecision(4) + << projectionInfo->llEastingNorthingPt().x; + + out << " meters, " << setprecision(4) + << mtrs2usft(projectionInfo->llEastingNorthingPt().x) + << " U.S. feet"; + + out << endl + << setw(14) << "Northing: " + << setw(17) << projectionInfo->llEastingNorthingPt().y; + + out << " meters, " << setprecision(4) + << mtrs2usft(projectionInfo->llEastingNorthingPt().y) + << " U.S. feet"; + + out << endl << endl; + + out << "Center Coordinates:\n\n"; + + tmpDouble = fabs(projectionInfo->centerGroundPt().latd()); + + tmpString = (projectionInfo->centerGroundPt().latd() < 0.0) ? SOUTH : NORTH; + + out << setw(14) << "Latitude: " + << setw(16) << setprecision(12) << tmpDouble + << tmpString << endl; + + tmpDouble = fabs(projectionInfo->centerGroundPt().lond()); + + tmpString = (projectionInfo->centerGroundPt().lond() < 0.0) ? WEST : EAST; + + out << setw(14) << "Longitude: " + << setw(16) << tmpDouble << tmpString << endl; + + out << setw(14) << "Easting: " + << setw(17) << setprecision(4) + << projectionInfo->centerEastingNorthingPt().x; + + out << " meters, " << setprecision(4) + << mtrs2usft(projectionInfo->centerEastingNorthingPt().x) + << " U.S. feet"; + + out << endl + << setw(14) << "Northing: " + << setw(17) << projectionInfo->centerEastingNorthingPt().y; + + out << " meters, " << setprecision(4) + << mtrs2usft(projectionInfo->centerEastingNorthingPt().y) + << " U.S. feet"; + + out << endl << endl; + + out + << "\nNOTE: Lat/Lon values are in decimal degrees."; + + out + << "\n Eastings/Northings are in meters."; + + out << endl; + + delete projectionInfo; + } + + if(proj) + { + delete proj; + proj = NULL; + } + + out.close(); + + return true; +} + +void ossimReadmeFileWriter::getMetadatatypeList( + std::vector<ossimString>& metadatatypeList) const +{ + metadatatypeList.push_back(ossimString("ossim_readme")); +} + +bool ossimReadmeFileWriter::hasMetadataType( + const ossimString& metadataType)const +{ + return (metadataType == "ossim_readme"); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/metadata/ossimReadmeFileWriter.h b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimReadmeFileWriter.h new file mode 100644 index 0000000000..2461f66ed0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimReadmeFileWriter.h @@ -0,0 +1,57 @@ +//******************************************************************* +// Copyright (C) 2003 Storage Area Networks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Kenneth Melero (kmelero@sanz.com) +// +//******************************************************************* +// $Id: ossimReadmeFileWriter.h,v 1.5 2005/08/08 22:00:24 dburken Exp $ + +#ifndef ossimReadmeFileWriter_H +#define ossimReadmeFileWriter_H + +#include <fstream> +#include <imaging/metadata/ossimMetadataFileWriter.h> + +/** ossimReadmeFileWriter */ +class OSSIMDLLEXPORT ossimReadmeFileWriter : public ossimMetadataFileWriter +{ +public: + + /** default constructor */ + ossimReadmeFileWriter(); + + /** virtual destructor */ + virtual ~ossimReadmeFileWriter(); + + /** + * Satisfies pure virtual from ossimMetadataWriter base. + * + * Appends the writers image types to the "metadatatypeList". + * + * @param metadatatypeList stl::vector<ossimString> list to append to. + * + * @note Appends to the list, does not clear it first. + */ + virtual void getMetadatatypeList( + std::vector<ossimString>& metadatatypeList) const; + + /** + * Satisfies pure virtual from ossimMetadataWriter base. + * + * @param imageType string representing image type. + * + * @return true if "metadataType" is supported by writer. + */ + virtual bool hasMetadataType(const ossimString& metadataType)const; + +private: + virtual bool writeFile(); + +TYPE_DATA +}; + +#endif /* End of #ifndef ossimReadmeFileWriter_H */ diff --git a/Utilities/OSSIM/ossim_core/imaging/metadata/ossimTiffWorldFileWriter.cpp b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimTiffWorldFileWriter.cpp new file mode 100644 index 0000000000..02a97d28b5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimTiffWorldFileWriter.cpp @@ -0,0 +1,121 @@ +//******************************************************************* +// Copyright (C) 2003 Storage Area Networks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Kenneth Melero (kmelero@sanz.com) +// +//******************************************************************* +// $Id: ossimTiffWorldFileWriter.cpp,v 1.8 2005/08/08 22:00:24 dburken Exp $ + +#include <imaging/metadata/ossimTiffWorldFileWriter.h> +#include <base/common/ossimKeywordNames.h> +#include <base/common/ossimTrace.h> +#include <base/data_types/ossimKeywordlist.h> +#include <projections/map_projections/ossimMapProjection.h> +#include <projections/map_projections/ossimMapProjectionInfo.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <imaging/formats/ossimImageHandler.h> +#include <imaging/ossimImageData.h> +#include <imaging/ossimImageSource.h> + +RTTI_DEF1(ossimTiffWorldFileWriter, + "ossimTiffWorldFileWriter", + ossimMetadataFileWriter) + +static const char DEFAULT_FILE_NAME[] = "output.tfw"; +static ossimTrace traceDebug("ossimTiffWorldFileWriter:debug"); + +ossimTiffWorldFileWriter::ossimTiffWorldFileWriter() + : + ossimMetadataFileWriter() +{ +} + +ossimTiffWorldFileWriter::~ossimTiffWorldFileWriter() +{ +} + +bool ossimTiffWorldFileWriter::writeFile() +{ + bool result = true; + if(!theInputConnection) + { + return false; + } + + std::ofstream out(theFilename.c_str(), ios_base::out); + if (!out) + { + return false; + } + + ossimKeywordlist kwl; + + theInputConnection->getImageGeometry(kwl); + ossimProjection* proj; + proj = ossimProjectionFactoryRegistry::instance()->createProjection(kwl); + ossimMapProjection* mapProj = PTR_CAST(ossimMapProjection, proj); + + if(mapProj) + { + ossimMapProjectionInfo* projectionInfo + = new ossimMapProjectionInfo(mapProj, theAreaOfInterest); + + projectionInfo->setPixelType(thePixelType); + + if(projectionInfo) + { + ossimDpt gsd; + ossimDpt ul; + + if(projectionInfo->getProjection()->isGeographic()) + { + gsd = projectionInfo->getDecimalDegreesPerPixel(); + ul = projectionInfo->ulGroundPt(); + } + else + { + gsd = projectionInfo->getMetersPerPixel(); + ul = projectionInfo->ulEastingNorthingPt(); + } + + out << setiosflags(ios::fixed) << setprecision(15) + << gsd.x << endl + << 0.0 << endl // rotation value X + << 0.0 << endl // rotation value y + << -gsd.y << endl + << ul.x << endl + << ul.y << endl; + + delete projectionInfo; + } + } + else + { + result = false; + } + if(proj) + { + delete proj; + proj = NULL; + } + + out.close(); + + return result; +} + +void ossimTiffWorldFileWriter::getMetadatatypeList( + std::vector<ossimString>& metadatatypeList) const +{ + metadatatypeList.push_back(ossimString("tiff_world_file")); +} + +bool ossimTiffWorldFileWriter::hasMetadataType( + const ossimString& metadataType)const +{ + return (metadataType == "tiff_world_file"); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/metadata/ossimTiffWorldFileWriter.h b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimTiffWorldFileWriter.h new file mode 100644 index 0000000000..58c34e8660 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/metadata/ossimTiffWorldFileWriter.h @@ -0,0 +1,56 @@ +//******************************************************************* +// Copyright (C) 2003 Storage Area Networks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Kenneth Melero (kmelero@sanz.com) +// +//******************************************************************* +// $Id: ossimTiffWorldFileWriter.h,v 1.7 2005/08/08 22:00:24 dburken Exp $ + +#ifndef ossimTiffWorldFileWriter_H +#define ossimTiffWorldFileWriter_H + +#include <imaging/metadata/ossimMetadataFileWriter.h> + +/** ossimTiffWorldFileWriter */ +class OSSIMDLLEXPORT ossimTiffWorldFileWriter : public ossimMetadataFileWriter +{ +public: + + /** default constructor */ + ossimTiffWorldFileWriter(); + + /** default constructor */ + virtual ~ossimTiffWorldFileWriter(); + + /** + * Satisfies pure virtual from ossimMetadataWriter base. + * + * Appends the writers image types to the "metadatatypeList". + * + * @param metadatatypeList stl::vector<ossimString> list to append to. + * + * @note Appends to the list, does not clear it first. + */ + virtual void getMetadatatypeList( + std::vector<ossimString>& metadatatypeList) const; + + /** + * Satisfies pure virtual from ossimMetadataWriter base. + * + * @param imageType string representing image type. + * + * @return true if "metadataType" is supported by writer. + */ + virtual bool hasMetadataType(const ossimString& metadataType)const; + +private: + virtual bool writeFile(); + +TYPE_DATA +}; + +#endif /* End of #ifndef ossimTiffWorldFileWriter_H */ diff --git a/Utilities/OSSIM/ossim_core/imaging/misc/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/misc/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/misc/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/imaging/misc/ossimPixelFlipper.cpp b/Utilities/OSSIM/ossim_core/imaging/misc/ossimPixelFlipper.cpp new file mode 100644 index 0000000000..b2f16ac5e8 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/misc/ossimPixelFlipper.cpp @@ -0,0 +1,1216 @@ +//******************************************************************* +// Copyright (C) 2002 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: David Burken +// +// Description: +// +// Filter to toggle pixel values. +// +//************************************************************************* +// $Id: ossimPixelFlipper.cpp,v 1.23 2006/01/11 15:57:43 dburken Exp $ + +#include <imaging/misc/ossimPixelFlipper.h> +#include <base/common/ossimTrace.h> +#include <base/common/ossimScopedLock.h> +#include <base/context/ossimNotifyContext.h> +#include <base/property/ossimStringProperty.h> +#include <base/property/ossimNumericProperty.h> +#include <base/common/ossimKeywordNames.h> + +RTTI_DEF1(ossimPixelFlipper, "ossimPixelFlipper", ossimImageSourceFilter) + +static ossimTrace traceDebug("ossimPixelFlipper:debug"); + +static const char TARGET_VALUE_KW[] = "target_value"; +static const char REPLACEMENT_VALUE_KW[] = "replacement_value"; +static const char CLAMP_VALUE_KW[] = "clamp_value"; +static const char REPLACEMENT_MODE_KW[] = "replacement_mode"; +static const char CLIP_MODE_KW[] = "clip_mode"; + +#ifdef OSSIM_ID_ENABLED +static const char OSSIM_ID[] = "$Id: ossimPixelFlipper.cpp,v 1.23 2006/01/11 15:57:43 dburken Exp $"; +#endif + +ossimPixelFlipper::ossimPixelFlipper(ossimObject* owner) + : + ossimImageSourceFilter(owner), + theTargetValue(0.0), + theReplacementValue(1.0), + theClampValue(0.0), + theReplacementMode(ossimPixelFlipper::REPLACE_ALL_TARGETS), + theClipMode(ossimPixelFlipper::ossimPixelFlipperClipMode_NONE), + theMutex() + +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimPixelFlipper::ossimPixelFlipper entered...\n"; +#ifdef OSSIM_ID_ENABLED + ossimNotify(ossimNotifyLevel_DEBUG) + << "OSSIM_ID: " << OSSIM_ID << "\n"; +#endif + } + + setDescription(ossimString("Pixel Flipper")); + enableSource(); +} + +ossimPixelFlipper::~ossimPixelFlipper() +{} + +ossimRefPtr<ossimImageData> ossimPixelFlipper::getTile( + const ossimIrect& tile_rect, ossim_uint32 resLevel) +{ + + if(!theInputConnection) + { + return 0; + } + // Fetch tile from pointer from the input source. + ossimRefPtr<ossimImageData> inputTile = + theInputConnection->getTile(tile_rect, resLevel); + + if (!inputTile.valid() || !isSourceEnabled()) return inputTile; + + if (!inputTile->getBuf()) return inputTile; + + // Lock for the length of this method. + ossimScopedLock<ossimMutex> scopeLock(theMutex); + + // Call the appropriate load method. + switch (inputTile->getScalarType()) + { + + case OSSIM_UCHAR: + { + flipPixels(ossim_uint8(0), inputTile.get(), resLevel); + break; + } + + case OSSIM_UINT16: + case OSSIM_USHORT11: + { + flipPixels(ossim_uint16(0), inputTile.get(), resLevel); + break; + } + + case OSSIM_SSHORT16: + { + flipPixels(ossim_sint16(0), inputTile.get(), resLevel); + break; + } + case OSSIM_UINT32: + { + flipPixels(ossim_uint32(0), inputTile.get(), resLevel); + break; + } + case OSSIM_SINT32: + { + flipPixels(ossim_sint32(0), inputTile.get(), resLevel); + break; + } + case OSSIM_FLOAT32: + case OSSIM_NORMALIZED_FLOAT: + { + flipPixels(float(0), inputTile.get(), resLevel); + break; + } + + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_FLOAT64: + { + flipPixels(ossim_float64(0), inputTile.get(), resLevel); + break; + } + + case OSSIM_SCALAR_UNKNOWN: + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimPixelFlipper::getTile Unsupported scalar type!" << endl; + break; + } + } + + return inputTile; +} + +template <class T> +void ossimPixelFlipper::flipPixels(T dummy, + ossimImageData* inputTile, + ossim_uint32 resLevel) +{ + if (!inputTile) return; + + T target = static_cast<T>(theTargetValue); + T replacement = static_cast<T>(theReplacementValue); + T clamp = static_cast<T>(theClampValue); + ossim_uint32 size = inputTile->getSizePerBand(); + ossim_uint32 bands = inputTile->getNumberOfBands(); + ossim_uint32 band; + + bool do_clamp = (clamp > 0) ? true : false; + + // Get pointers to data for each band. + T** buf = new T*[bands]; + + for(band=0; band<bands; ++band) + { + buf[band] = static_cast<T*>(inputTile->getBuf(band)); + } + + ossimIrect rect = inputTile->getImageRectangle(); + ossimIpt ul = rect.ul(); + ossimIpt origin = ul; + ossim_uint32 x=0; + ossim_uint32 y=0; + ossim_uint32 w = rect.width(); + ossim_uint32 h = rect.height(); + ossim_uint32 i = 0; + bool replace = false; + bool needsTesting = false; + switch(theClipMode) + { + case ossimPixelFlipperClipMode_BOUNDING_RECT: + { + if(resLevel < theBoundingRects.size()) + { + if(!rect.intersects(theBoundingRects[resLevel])) + { + return; + } + else + { + needsTesting = !rect.completely_within(theBoundingRects[resLevel]); + } + } + break; + } + case ossimPixelFlipperClipMode_VALID_VERTICES: + { + if(resLevel < theValidVertices.size()) + { + bool ulFlag = theValidVertices[resLevel].isPointWithin(rect.ul()); + bool urFlag = theValidVertices[resLevel].isPointWithin(rect.ur()); + bool lrFlag = theValidVertices[resLevel].isPointWithin(rect.lr()); + bool llFlag = theValidVertices[resLevel].isPointWithin(rect.ll()); + if((!ulFlag)&& + (!urFlag)&& + (!lrFlag)&& + (!llFlag)) + { + return; // none of the tile is inside so return + } + else + { + needsTesting = !(ulFlag&&urFlag&&lrFlag&&llFlag); + } + } + break; + } + default: + { + break; + } + } + + switch (theReplacementMode) + { + case ossimPixelFlipper::REPLACE_PARTIAL_TARGETS: + { + i = 0; + if((theClipMode == ossimPixelFlipperClipMode_NONE)||(!needsTesting)) + { + for (i=0; i<size; ++i) + { + // At least one band must NOT have target for replace to = true; + replace = false; + for (band=0; band<bands; ++band) + { + if (buf[band][i] != target) + { + replace = true; + break; + } + } + if (replace) + { + for (band=0; band<bands; ++band) + { + if (buf[band][i] == target) buf[band][i] = replacement; + } + } + } + } + else + { + bool active; + origin.y = ul.y; + for(y = 0; y < h; ++y) + { + origin.x = ul.x; + for(x =0; x < w; ++x) + { + active = true; + switch(theClipMode) + { + case ossimPixelFlipperClipMode_BOUNDING_RECT: + { + if(resLevel < theBoundingRects.size()) + { + active = theBoundingRects[resLevel].pointWithin(origin); + } + break; + } + case ossimPixelFlipperClipMode_VALID_VERTICES: + { + if(resLevel < theValidVertices.size()) + { + active = theValidVertices[resLevel].isPointWithin(origin); + } + break; + } + default: + { + break; + } + } + replace = false; + if(active) + { + for (band=0; band<bands; ++band) + { + if (buf[band][i] != target) + { + replace = true; + break; + } + } + } + if (replace) + { + for (band=0; band<bands; ++band) + { + if (buf[band][i] == target) buf[band][i] = replacement; + } + } + + ++i; + ++origin.x; + } + ++origin.y; + } + } + break; + } + case ossimPixelFlipper::REPLACE_PARTIAL_TARGETS_ALL_BANDS: + { + i = 0; + if((theClipMode == ossimPixelFlipperClipMode_NONE)||(!needsTesting)) + { + for (i=0; i<size; ++i) + { + // Must be at least one target but not all to replace all bands. + bool has_a_target = false; + replace = false; + for (band=0; band<bands; ++band) + { + if (buf[band][i] == target) + { + has_a_target = true; + break; + } + } + if (has_a_target) + { + for (band=0; band<bands; ++band) + { + if (buf[band][i] != target) + { + replace = true; + break; + } + } + if (replace) + { + for (band=0; band<bands; ++band) + { + buf[band][i] = replacement; + } + } + } + } + } + else + { + bool active = true; + origin.y = ul.y; + for(y = 0; y < h; ++y) + { + origin.x = ul.x; + for(x =0; x < w; ++x) + { + switch(theClipMode) + { + case ossimPixelFlipperClipMode_BOUNDING_RECT: + { + if(resLevel < theBoundingRects.size()) + { + active = theBoundingRects[resLevel].pointWithin(origin); + } + break; + } + case ossimPixelFlipperClipMode_VALID_VERTICES: + { + if(resLevel < theValidVertices.size()) + { + active = theValidVertices[resLevel].isPointWithin(origin); + } + break; + } + default: + { + break; + } + } + bool has_a_target = false; + replace = false; + if(active) + { + for (band=0; band<bands; ++band) + { + if (buf[band][i] == target) + { + has_a_target = true; + break; + } + } + } + if (has_a_target) + { + for (band=0; band<bands; ++band) + { + if (buf[band][i] != target) + { + replace = true; + break; + } + } + if (replace) + { + for (band=0; band<bands; ++band) + { + buf[band][i] = replacement; + } + } + } + + ++i; + ++origin.x; + } + ++origin.y; + } + } + break; + } + case ossimPixelFlipper::REPLACE_FULL_TARGETS: + { + i = 0; + if((theClipMode == ossimPixelFlipperClipMode_NONE)||(!needsTesting)) + { + for (i=0; i<size; ++i) + { + // All bands must have target for replace to = true. + replace = true; + + for (band=0; band<bands; ++band) + { + if (buf[band][i] != target) + { + replace = false; + break; + } + } + if (replace) + { + for (band=0; band<bands; ++band) + { + buf[band][i] = replacement; + } + } + } + } + else + { + origin.y = ul.y; + for(y = 0; y < h; ++y) + { + origin.x = ul.x; + for(x =0; x < w; ++x) + { + replace = true; + switch(theClipMode) + { + case ossimPixelFlipperClipMode_BOUNDING_RECT: + { + if(resLevel < theBoundingRects.size()) + { + replace = theBoundingRects[resLevel].pointWithin(origin); + } + break; + } + case ossimPixelFlipperClipMode_VALID_VERTICES: + { + if(resLevel < theValidVertices.size()) + { + replace = theValidVertices[resLevel].isPointWithin(origin); + } + break; + } + default: + { + break; + } + } + if(replace) + { + for (band=0; band<bands; ++band) + { + if (buf[band][i] != target) + { + replace = false; + break; + } + } + } + + if (replace) + { + for (band=0; band<bands; ++band) + { + buf[band][i] = replacement; + } + } + ++i; + ++origin.x; + } + ++origin.y; + } + } + + break; + } + default: // REPLACE_ALL_TARGETS + { + i = 0; + if((theClipMode == ossimPixelFlipperClipMode_NONE)||(!needsTesting)) + { + for(i = 0; i < size;++i) + { + for (band=0; band<bands; ++band) + { + if (buf[band][i] == target) buf[band][i] = replacement; + } + } + } + else + { + origin.y = ul.y; + for(y = 0; y < h; ++y) + { + origin.x = ul.x; + for(x =0; x < w; ++x) + { + replace = true; + + switch(theClipMode) + { + case ossimPixelFlipperClipMode_BOUNDING_RECT: + { + if(resLevel < theBoundingRects.size()) + { + replace = theBoundingRects[resLevel].pointWithin(origin); + } + break; + } + case ossimPixelFlipperClipMode_VALID_VERTICES: + { + if(resLevel < theValidVertices.size()) + { + replace = theValidVertices[resLevel].isPointWithin(origin); + } + break; + } + default: + { + break; + } + } + if(replace) + { + for (band=0; band<bands; ++band) + { + if (buf[band][i] == target) buf[band][i] = replacement; + } + } + ++i; + ++origin.x; + } + ++origin.y; + } + } + break; + } + + if (do_clamp) + { + for (i=0; i<size; ++i) + { + for (band=0; band<bands; ++band) + { + if (buf[band][i] > clamp) + { + buf[band][i] = clamp; + } + } + } + } + } + + delete [] buf; + inputTile->validate(); +} + +template <class T> void ossimPixelFlipper::clipTile(T dummy, + ossimImageData* inputTile, + ossim_uint32 resLevel) +{ + if(theClipMode == ossimPixelFlipperClipMode_NONE) + { + theClipTileBuffer = 0; + return; + } + if(!inputTile) return; + if(!inputTile->getBuf()|| + (inputTile->getDataObjectStatus() == OSSIM_EMPTY)) + { + return; + } + allocateClipTileBuffer(inputTile); + + + if(theClipTileBuffer.valid()) + { + ossimIrect tileRect = inputTile->getImageRectangle(); + // force to all nulls + theClipTileBuffer->setDataObjectStatus(OSSIM_FULL); + theClipTileBuffer->makeBlank(); + + switch(theClipMode) + { + case ossimPixelFlipperClipMode_NONE: + { + break; + } + case ossimPixelFlipperClipMode_BOUNDING_RECT: + { + if(resLevel < theBoundingRects.size()) + { + if(tileRect.completely_within(theBoundingRects[resLevel])|| + theBoundingRects[resLevel].hasNans()) + { + return; + } + else + { + if(tileRect.intersects(theBoundingRects[resLevel])) + { + ossimIrect clipRect = tileRect.clipToRect(theBoundingRects[resLevel]); + + theClipTileBuffer->setImageRectangle(clipRect); + + theClipTileBuffer->loadTile(inputTile); + inputTile->makeBlank(); + inputTile->loadTile(theClipTileBuffer.get()); + inputTile->validate(); + } + else + { + inputTile->makeBlank(); + } + } + } + break; + } + case ossimPixelFlipperClipMode_VALID_VERTICES: + { + if(resLevel < theValidVertices.size()) + { + const ossimPolygon& p = theValidVertices[resLevel]; + bool ulWithin = p.isPointWithin(tileRect.ul()); + bool urWithin = p.isPointWithin(tileRect.ur()); + bool lrWithin = p.isPointWithin(tileRect.lr()); + bool llWithin = p.isPointWithin(tileRect.ll()); + + if(ulWithin&& + urWithin&& + lrWithin&& + llWithin) + { + return; + } + else if(!(ulWithin|| // if none are in + urWithin|| + lrWithin|| + llWithin)) + { + inputTile->makeBlank(); + return; + } + else + { + ossimIpt ul = tileRect.ul(); + ossimIpt origin; + ossim_uint32 x = 0; + ossim_uint32 y = 0; + ossim_uint32 w = inputTile->getWidth(); + ossim_uint32 h = inputTile->getHeight(); + ossim_uint32 offset = 0; + origin.y = ul.y; + for(y = 0; y < h; ++y) + { + origin.x = ul.x; + for(x = 0; x < w; ++x) + { + + if(!p.isPointWithin(origin)) + { + inputTile->setNull(offset); + } + ++offset; + ++origin.x; + } + ++origin.y; + } + } + } + break; + } + } + } +} + + +void ossimPixelFlipper::allocateClipTileBuffer(ossimRefPtr<ossimImageData> inputImage) +{ + if(inputImage.valid()) + { + bool needDupFlag = false; + if(theClipTileBuffer.valid()) + { + if((theClipTileBuffer->getScalarType() != inputImage->getScalarType())|| + theClipTileBuffer->getNumberOfBands() != theClipTileBuffer->getNumberOfBands()) + { + needDupFlag = true; + } + else + { + theClipTileBuffer->setImageRectangle(inputImage->getImageRectangle()); + } + } + else + { + needDupFlag = true; + } + if(needDupFlag) + { + theClipTileBuffer = (ossimImageData*)inputImage->dup(); + } + } +} + +void ossimPixelFlipper::initialize() +{ + theMutex.lock(); + ossimImageSourceFilter::initialize(); + theValidVertices.clear(); + theBoundingRects.clear(); + + ossim_uint32 rlevels = getNumberOfDecimationLevels(); + ossim_uint32 idx = 0; + + if(rlevels) + { + if(theValidVertices.size() != rlevels) + { + theValidVertices.resize(rlevels); + } + if(theBoundingRects.size() != rlevels) + { + theBoundingRects.resize(rlevels); + } + for(idx = 0; idx < rlevels; ++idx) + { + std::vector<ossimIpt> validVertices; + getValidImageVertices(validVertices, + OSSIM_CLOCKWISE_ORDER, + idx); + theValidVertices[idx] = ossimPolygon(validVertices); + theBoundingRects[idx] = getBoundingRect(idx); + } + } + + theMutex.unlock(); +} + +ossimScalarType ossimPixelFlipper::getOutputScalarType() const +{ + if(theInputConnection) + { + ossimScalarType scalar = theInputConnection->getOutputScalarType(); + { + if (scalar == OSSIM_USHORT16 && theClampValue == 2047.0) + { + //--- + // Special case: + // We have an unsigned 16 bit type but we want to call it + // USHORT11 ( (2^11- 1) = 2047 ). + //--- + return OSSIM_USHORT11; + } + return scalar; + } + } + return OSSIM_SCALAR_UNKNOWN; +} + +ossim_float64 ossimPixelFlipper::getMaxPixelValue (ossim_uint32 band) const +{ + const ossim_float64 MIN = ossimImageSourceFilter::getMinPixelValue(band); + const ossim_float64 MAX = ossimImageSourceFilter::getMaxPixelValue(band); + + if (theClampValue > MIN && theClampValue < MAX) + { + return theClampValue; + } + + return MAX; +} + +bool ossimPixelFlipper::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* lookupReturn; + + lookupReturn = kwl.find(prefix, TARGET_VALUE_KW); + if(lookupReturn) + { + setTargetValue(atof(lookupReturn)); + } + + lookupReturn = kwl.find(prefix, REPLACEMENT_VALUE_KW); + if(lookupReturn) + { + setReplacementValue(atof(lookupReturn)); + } + + lookupReturn = kwl.find(prefix, CLAMP_VALUE_KW); + if(lookupReturn) + { + setClampValue(atof(lookupReturn)); + } + + lookupReturn = kwl.find(prefix, REPLACEMENT_MODE_KW); + if(lookupReturn) + { + ossimString modeString = lookupReturn; + setReplacementMode(modeString); + } + lookupReturn = kwl.find(prefix, CLIP_MODE_KW); + if(lookupReturn) + { + ossimString modeString = lookupReturn; + setClipMode(modeString); + } + + bool status = ossimImageSourceFilter::loadState(kwl, prefix); + + if (traceDebug()) + { + print(ossimNotify(ossimNotifyLevel_DEBUG)); + } + + return status; +} + +bool ossimPixelFlipper::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + // Call the base class saveState. + ossimImageSourceFilter::saveState(kwl, prefix); + + kwl.add(prefix, TARGET_VALUE_KW, theTargetValue); + kwl.add(prefix, REPLACEMENT_VALUE_KW, theReplacementValue); + kwl.add(prefix, CLAMP_VALUE_KW, theClampValue); + kwl.add(prefix, REPLACEMENT_MODE_KW, getReplacementModeString().c_str()); + kwl.add(prefix, CLIP_MODE_KW, getClipModeString().c_str()); + + return true; +} + +void ossimPixelFlipper::setTargetValue(ossim_float64 target_value) +{ + theMutex.lock(); + + if (inRange(target_value)) + { + theTargetValue = target_value; + } + + theMutex.unlock(); +} + +void ossimPixelFlipper::setReplacementValue(ossim_float64 replacement_value) +{ + theMutex.lock(); + + if (inRange(replacement_value)) + { + theReplacementValue = replacement_value; + } + + theMutex.unlock(); +} + +void ossimPixelFlipper::setClampValue(ossim_float64 clamp_value) +{ + theMutex.lock(); + + if (inRange(clamp_value)) + { + theClampValue = clamp_value; + } + + theMutex.unlock(); +} + +void ossimPixelFlipper::setReplacementMode( + ossimPixelFlipper::ReplacementMode mode) +{ + theMutex.lock(); + theReplacementMode = mode; + theMutex.unlock(); +} + +void ossimPixelFlipper::setReplacementMode(const ossimString& modeString) +{ + theMutex.lock(); + + ossimString mode = modeString; + mode.downcase(); + if (mode == "replace_partial_targets") + { + theReplacementMode = ossimPixelFlipper::REPLACE_PARTIAL_TARGETS; + } + else if (mode == "replace_partial_targets_all_bands") + { + theReplacementMode = + ossimPixelFlipper::REPLACE_PARTIAL_TARGETS_ALL_BANDS; + } + else if (mode == "replace_full_targets") + { + theReplacementMode = ossimPixelFlipper::REPLACE_FULL_TARGETS; + } + else if (mode == "replace_all_targets") + { + theReplacementMode = ossimPixelFlipper::REPLACE_ALL_TARGETS; + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimPixelFlipper::setReplacementMode warning:\n" + << "Invalide mode: " << modeString + << endl; + } + + theMutex.unlock(); +} + +void ossimPixelFlipper::setClipMode(ossimPixelFlipper::ClipMode mode) +{ + theMutex.lock(); + theClipMode = mode; + theMutex.unlock(); +} + +void ossimPixelFlipper::setClipMode(const ossimString& modeString) +{ + ossimString mode = modeString; + mode.downcase(); + if (mode == "none") + { + setClipMode(ossimPixelFlipperClipMode_NONE); + } + else if (mode == "bounding_rect") + { + setClipMode(ossimPixelFlipperClipMode_BOUNDING_RECT); + } + else if (mode == "valid_vertices") + { + setClipMode(ossimPixelFlipperClipMode_VALID_VERTICES); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimPixelFlipper::setClipMode warning:\n" + << "Invalide mode: " << modeString + << endl; + } +} + +ossim_float64 ossimPixelFlipper::getClampValue() const +{ + return theClampValue; +} + + +ossim_float64 ossimPixelFlipper::getTargetValue() const +{ + return theTargetValue; +} + +ossim_float64 ossimPixelFlipper::getReplacementValue() const +{ + return theReplacementValue; +} + +ossimPixelFlipper::ReplacementMode ossimPixelFlipper::getReplacementMode() const +{ + return theReplacementMode; +} + +ossimString ossimPixelFlipper::getReplacementModeString() const +{ + switch(theReplacementMode) + { + case REPLACE_ALL_TARGETS: + return ossimString("replace_all_targets"); + case REPLACE_PARTIAL_TARGETS: + return ossimString("replace_partial_targets"); + case REPLACE_PARTIAL_TARGETS_ALL_BANDS: + return ossimString("replace_partial_targets_all_bands"); + case REPLACE_FULL_TARGETS: + return ossimString("replace_full_targets"); + default: + break; + } + + return ossimString("UNKNOWN_MODE"); +} + +ossimString ossimPixelFlipper::getClipModeString() const +{ + switch(theClipMode) + { + case ossimPixelFlipperClipMode_NONE: + { + return ossimString("none"); + } + case ossimPixelFlipperClipMode_BOUNDING_RECT: + { + return ossimString("bounding_rect"); + } + case REPLACE_PARTIAL_TARGETS_ALL_BANDS: + { + return ossimString("valid_vertices"); + } + default: + { + break; + } + } + + return ossimString("none"); +} + +ossimPixelFlipper::ClipMode ossimPixelFlipper::getClipMode() const +{ + return theClipMode; +} + +std::ostream& ossimPixelFlipper::print(std::ostream& out) const +{ + out << "ossimPixelFlipper::print:" + << "\ntarget value: " << theTargetValue + << "\nreplacement value: " << theReplacementValue + << "\nclamp value: " << theClampValue + << "\nreplacement mode: " << getReplacementModeString().c_str() + << "\nclip_mode: " << getClipModeString().c_str() + << endl; + return out; +} + +ossimRefPtr<ossimProperty> ossimPixelFlipper::getProperty( + const ossimString& name)const +{ + // Lock for the length of this method. + ossimScopedLock<ossimMutex> scopeLock(theMutex); + + if (name == TARGET_VALUE_KW) + { + ossimProperty* p = + new ossimNumericProperty(name, + ossimString::toString(theTargetValue)); + p->setCacheRefreshBit(); + return ossimRefPtr<ossimProperty>(p); + } + else if (name == REPLACEMENT_VALUE_KW) + { + ossimProperty* p = + new ossimNumericProperty(name, + ossimString::toString(theReplacementValue)); + p->setCacheRefreshBit(); + return ossimRefPtr<ossimProperty>(p); + } + else if (name == CLAMP_VALUE_KW) + { + ossimProperty* p = + new ossimNumericProperty(name, ossimString::toString(theClampValue)); + p->setCacheRefreshBit(); + return ossimRefPtr<ossimProperty>(p); + } + else if (name == REPLACEMENT_MODE_KW) + { + vector<ossimString> constraintList(4); + constraintList[0] = "replace_all_targets"; + constraintList[1] = "replace_partial_targets"; + constraintList[2] = "replace_partial_targets_all_bands"; + constraintList[3] = "replace_full_targets"; + + ossimStringProperty* p = + new ossimStringProperty(name, + getReplacementModeString(), + false, + constraintList); + p->setCacheRefreshBit(); + return ossimRefPtr<ossimProperty>(p); + } + else if (name == CLIP_MODE_KW) + { + vector<ossimString> constraintList(3); + constraintList[0] = "none"; + constraintList[1] = "bounding_rect"; + constraintList[2] = "valid_vertices"; + + ossimStringProperty* p = + new ossimStringProperty(name, + getClipModeString(), + false, + constraintList); + p->setCacheRefreshBit(); + return ossimRefPtr<ossimProperty>(p); + } + ossimRefPtr<ossimProperty> result = ossimSource::getProperty(name); + + if(result.valid()) + { + if(result->getName() == ossimKeywordNames::ENABLED_KW) + { + result->clearChangeType(); + + // we will at least say its a radiometric change + // + result->setCacheRefreshBit(); + } + } + + return result; +} + +void ossimPixelFlipper::setProperty(ossimRefPtr<ossimProperty> property) +{ + if (!property) return; + + ossimString os = property->valueToString(); + + ossimString name = property->getName(); + if (name == TARGET_VALUE_KW) + { + setTargetValue(os.toDouble()); + } + else if (name == REPLACEMENT_VALUE_KW) + { + setReplacementValue(os.toDouble()); + } + else if (name == CLAMP_VALUE_KW) + { + setClampValue(os.toDouble()); + } + else if (name == REPLACEMENT_MODE_KW) + { + setReplacementMode(os); + } + else if (name == CLIP_MODE_KW) + { + setClipMode(os); + } + else + { + ossimImageSourceFilter::setProperty(property); + } +} + +void ossimPixelFlipper::getPropertyNames( + std::vector<ossimString>& propertyNames)const +{ + propertyNames.push_back(TARGET_VALUE_KW); + propertyNames.push_back(REPLACEMENT_VALUE_KW); + propertyNames.push_back(CLAMP_VALUE_KW); + propertyNames.push_back(REPLACEMENT_MODE_KW); + propertyNames.push_back(CLIP_MODE_KW); + + ossimImageSourceFilter::getPropertyNames(propertyNames); +} + +ossimString ossimPixelFlipper::getShortName()const +{ + return ossimString("Pixel flipper"); +} + +bool ossimPixelFlipper::inRange(ossim_float64 value) const +{ + if (!theInputConnection) + { + //--- + // Not initialized yet... We're going to return true so that things + // like loadState work with the assumption that the caller know's + // the correct range. This check is really intended for an uncheck + // range on the gui side. + //--- + return true; + } + + const ossim_float64 NULL_PIX = ossimImageSourceFilter::getNullPixelValue(); + const ossim_float64 MIN_PIX = ossimImageSourceFilter::getMinPixelValue(); + const ossim_float64 MAX_PIX = ossimImageSourceFilter::getMaxPixelValue(); + + if ( (value == NULL_PIX) || ((value >= MIN_PIX) && (value <= MAX_PIX)) ) + { + return true; + } + + ossimNotify(ossimNotifyLevel_WARN) + << "\nossimPixelFlipper::inRange WARNING:" + << "\nvalue \"" << value + << "\" is out of range!" + << "\nInput source null = " << NULL_PIX + << "\nInput source min = " << MIN_PIX + << "\nInput source max = " << MAX_PIX + << endl; + + return false; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/misc/ossimPixelFlipper.h b/Utilities/OSSIM/ossim_core/imaging/misc/ossimPixelFlipper.h new file mode 100644 index 0000000000..d9b8f42ad7 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/misc/ossimPixelFlipper.h @@ -0,0 +1,246 @@ +//******************************************************************* +// Copyright (C) 2002 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Class to scan pixels and flip target dn pixel value to new dn pixel value. +// This was written to fix partial null pixels. +// +//************************************************************************* +// $Id: ossimPixelFlipper.h,v 1.16 2005/12/09 12:43:39 gpotts Exp $ +#ifndef ossimPixelFlipper_HEADER +#define ossimPixelFlipper_HEADER + +#include <imaging/tile_sources/ossimImageSourceFilter.h> +#include <base/data_types/ossimPolygon.h> +#include <base/common/ossimMutex.h> + +/** + * Class to scan pixels and flip target dn value to a replacement dn + * value. + * + * This was written to fix problems with null pixels, i.e. an image has a + * digital number(dn) of 255 for null and it is desired to use a dn of 0 as + * a null. This can really be used to flip any pixel value to another. + * + * @note This filter currently works on the input tile directly and does + * not copy the data. + * + * @see theReplacementMode data member documentation for more info. + */ +class ossimPixelFlipper : public ossimImageSourceFilter +{ +public: + + enum ReplacementMode + { + /** + * Any pixel with dn of target will be replaced. (default) + */ + REPLACE_ALL_TARGETS = 0, + + /** + * Target will be replaced only at least one subpixel(band) does not have + * the target. + */ + REPLACE_PARTIAL_TARGETS = 1, + + /** + * All bands will be replaced if any band has target but not all. + */ + REPLACE_PARTIAL_TARGETS_ALL_BANDS = 2, + + /** + * Target will be repaced only if all subpixels(bands) have the target. + */ + REPLACE_FULL_TARGETS = 3 + }; + enum ClipMode + { + ossimPixelFlipperClipMode_NONE = 0, + ossimPixelFlipperClipMode_BOUNDING_RECT = 1, + ossimPixelFlipperClipMode_VALID_VERTICES = 2 + }; + /** default constructor */ + ossimPixelFlipper(ossimObject* owner=NULL); + + /** destructor */ + virtual ~ossimPixelFlipper(); + + /** @return "Pixel flipper" as an ossimString. */ + virtual ossimString getShortName()const; + + /** Initializes the state of the object from theInputConnection. */ + virtual void initialize(); + + /** + * @param tile_rect Rectangle to fill tile with. + * + * @param resLevel Reduced resolution level to grab from. + * + * @return ossimRefPtr<ossimImageData> This is tile that was filled with + * tile_rect. + * + * @note Callers should check the ossimRefPtr::valid method. + * The internal pointer of the ossimRefPtr<ossimImageData> can be + * null if the tile_rect did not intersect the input connection's + * bounding rectangle. + */ + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tile_rect, + ossim_uint32 resLevel=0); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual ossimScalarType getOutputScalarType() const; + virtual ossim_float64 getMaxPixelValue (ossim_uint32 band = 0 ) const; + + virtual std::ostream& print(std::ostream& out) const; + + /** @param target_value This is the value to flip. */ + void setTargetValue(ossim_float64 target_value); + + /** @param replacement_value This is the value to flip target to. */ + void setReplacementValue(ossim_float64 replacement_value); + + + /** @see enum ReplacementMode */ + void setReplacementMode(ossimPixelFlipper::ReplacementMode mode); + void setReplacementMode(const ossimString& modeString); + + void setClipMode(const ossimString& modeString); + void setClipMode(ossimPixelFlipper::ClipMode mode); + + /** + * @param clamp_value If set all pixel values above this range will + * be clamped to clamp_value. Must be less than max pixel value of the + * input and cannot be null. + */ + void setClampValue(ossim_float64 clamp_value); + + ossim_float64 getTargetValue() const; + ossim_float64 getReplacementValue() const; + ossim_float64 getClampValue() const; + ossimPixelFlipper::ReplacementMode getReplacementMode() const; + ossimString getReplacementModeString() const; + ossimString getClipModeString() const; + ossimPixelFlipper::ClipMode getClipMode() const; + + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + +protected: + template <class T> void flipPixels(T dummy, + ossimImageData* inpuTile, + ossim_uint32 resLevel); + + template <class T> void clipTile(T dummy, + ossimImageData* inpuTile, + ossim_uint32 resLevel); + + /** + * Verifies pixel is in range. + * @return Returns true if in range else false. + */ + bool inRange(ossim_float64 value) const; + + void allocateClipTileBuffer(ossimRefPtr<ossimImageData> inputImage); + /** The value to replace. */ + ossim_float64 theTargetValue; + + /** The replacement value. */ + ossim_float64 theReplacementValue; + + /** + * If set and not > max pixel values any values higher than theClampValue + * will be clamped to theClampValue. + */ + ossim_float64 theClampValue; + + + /** + * Target Replacement Mode: + * + * If mode is REPLACE_ALL_TARGETS (default): + * Any pixel with dn of target will be replaced. + * + * If mode is REPLACE_PARTIAL_TARGETS: + * Target will be replaced only at least one subpixel(band) does not have + * the target. + * + * If mode is REPLACE_BANDS_PARTIAL_TARGETS_ALL_BANDS: + * All bands will be replaced if any band has target but not all. + * + * If mode is REPLACE_FULL_TARGETS: + * Target will be repaced only if all subpixels(bands) have the target. + * + * Example: + * target = 0 + * replacement = 1 + * Pixel at (0, 0) r=0, g=0, b=0 + * Pixel at (0, 1) r=0, g=30, b=21 + * + * Mode is REPLACE_ALL_TARGETS: + * Pixel at (0, 0) becomes r=1, g=1, b=1 + * Pixel at (0, 1) becomes r=1, g=30, b=21 + * + * Mode is REPLACE_PARTIAL_TARGETS: + * Pixel at (0, 0) remains r=0, g=0, b=0 + * Pixel at (0, 1) becomes r=1, g=30, b=21 + * + * Mode is REPLACE_PARTIAL_TARGETS_ALL_BANDS: + * Pixel at (0, 0) remains r=0, g=0, b=0 + * Pixel at (0, 1) becomes r=1, g=1, b=1 + * + * Mode is REPLACE_FULL_TARGETS: + * Pixel at (0, 0) becomes r=1, g=1, b=1 + * Pixel at (0, 1) remains r=0, g=30, b=21 + * + * Default mode is REPLACE_ALL_TARGETS. + */ + ReplacementMode theReplacementMode; + + /** + * Clip mode + * + * This will flip nulls any pixel value outside the specified mode. + * + * Valid modes are: + * + * none + * bounding_rect + * valid_vertices + * + * if the mode is "none" then nothing is done. + * if the mode is "bounding_rect" then the bounding rect for the requested rlevel + * is used and every pixel outside that + */ + ClipMode theClipMode; + + /** For lock and unlock. */ + mutable ossimMutex theMutex; + + mutable std::vector<ossimPolygon> theValidVertices; + mutable std::vector<ossimIrect> theBoundingRects; + + ossimRefPtr<ossimImageData> theClipTileBuffer; + + TYPE_DATA +}; + + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/misc/ossimVertexExtractor.cpp b/Utilities/OSSIM/ossim_core/imaging/misc/ossimVertexExtractor.cpp new file mode 100644 index 0000000000..e65e027786 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/misc/ossimVertexExtractor.cpp @@ -0,0 +1,1962 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken +// TR # 136 kminear Fix extractVertices method +// +//************************************************************************* +// $Id: ossimVertexExtractor.cpp,v 1.30 2005/02/11 15:07:32 dburken Exp $ + +#include <fstream> +using namespace std; + +#include <imaging/misc/ossimVertexExtractor.h> +#include <imaging/ossimImageSource.h> +#include <imaging/formats/ossimImageHandler.h> +#include <base/common/ossimTrace.h> +#include <base/context/ossimNotifyContext.h> + +static ossimTrace traceDebug("ossimVertexExtractor:degug"); + +RTTI_DEF2(ossimVertexExtractor, "ossimVertexExtractor", + ossimSource, ossimProcessInterface); + +ossimVertexExtractor::ossimVertexExtractor(ossimImageSource* inputSource) + : + ossimOutputSource(NULL, // owner + 1, + 0, + true, + true), + ossimProcessInterface(), + theAreaOfInterest(), + theFilename(ossimFilename::NIL), + theFileStream(), + theVertice(4), + theLeftEdge(NULL), + theRightEdge(NULL) +{ + if (inputSource == NULL) + { + ossimNotify(ossimNotifyLevel_WARN) << "ossimVertexExtractor::ossimVertexExtractor ERROR" + << "\nNULL input image source passed to constructor!" + << std::endl; + } + + connectMyInputTo(0, inputSource); +// theInputObjectList[0] = inputSource; + theAreaOfInterest.makeNan(); +} + +ossimVertexExtractor::~ossimVertexExtractor() +{ + if (theLeftEdge) + { + delete [] theLeftEdge; + theLeftEdge = NULL; + } + if (theRightEdge) + { + delete [] theRightEdge; + theRightEdge = NULL; + } +} + +bool ossimVertexExtractor::execute() +{ + static const char MODULE[] = "ossimVertexExtractor::execute"; + + if (traceDebug()) CLOG << " Entered..." << endl; + + if (theFilename == ossimFilename::NIL) + { + ossimNotify(ossimNotifyLevel_WARN) << "ossimVertexExtractor::execute WARNING:" + << "\nOutput file name is empty. Use setFilename method..." + << std::endl; + return false; + } + + if (theAreaOfInterest.isNan()) + { + ossimNotify(ossimNotifyLevel_NOTICE) << MODULE << " NOTICE ossimVertexExtractor::execute:" + << "\nArea of interest is not set. Use setAreaOfInterest method..." + << "\nDefaulting to bounding rectangle of input source." + << std::endl; + ossimImageSource* src = reinterpret_cast<ossimImageSource*>(getInput(0)); + theAreaOfInterest = src->getBoundingRect(0); + } + + setProcessStatus(ossimProcessInterface::PROCESS_STATUS_EXECUTING); + + if (scanForEdges()) + { + if (extractVertices()) + { + writeVertices(); + } + else + { + return false; + } + } + else + { + return false; + } + + setProcessStatus(ossimProcessInterface::PROCESS_STATUS_NOT_EXECUTING); + + if (traceDebug()) CLOG << " Exited..." << endl; + + return true; +} + +bool ossimVertexExtractor::scanForEdges() +{ + static const char MODULE[] = "ossimVertexExtractor::scanForEdges"; + + if (traceDebug()) CLOG << " Entered..." << endl; + + ossimImageSource* src = reinterpret_cast<ossimImageSource*>(getInput(0)); + if (!src) + { + ossimNotify(ossimNotifyLevel_WARN) + << "WARN ossimVertexExtractor::scanForEdges():" + << "\nInput source is null. Returning..." << std::endl; + return false; + } + + // Allocate the arrays to hold the edges. + if (theLeftEdge) delete [] theLeftEdge; + if (theRightEdge) delete [] theRightEdge; + theLeftEdge = new ossim_int32[theAreaOfInterest.height()]; + theRightEdge = new ossim_int32[theAreaOfInterest.height()]; + for (ossim_int32 i=0; i<(int)theAreaOfInterest.height(); ++i) + { + theLeftEdge[i] = OSSIM_INT_NAN; + theRightEdge[i] = OSSIM_INT_NAN; + } + + // Some constants needed throughout... + const ossim_int32 TILE_HEIGHT = src->getTileHeight(); + const ossim_int32 TILE_WIDTH = src->getTileWidth(); + const ossim_int32 START_LINE = theAreaOfInterest.ul().y; + const ossim_int32 STOP_LINE = theAreaOfInterest.lr().y; + const ossim_int32 START_SAMP = theAreaOfInterest.ul().x; + const ossim_int32 STOP_SAMP = theAreaOfInterest.lr().x; + + // For percent complete status. + double total_tiles_y_dir = theAreaOfInterest.height() / TILE_HEIGHT; + if (theAreaOfInterest.height() % TILE_HEIGHT) total_tiles_y_dir += 1.0; + double tiles_processed = 0.0; + + // Set the status message to be "scanning source for edges..." + ossimNotify(ossimNotifyLevel_INFO) << "Scanning image source for edges..." << std::endl; + + // Start off with a percent complete at 0... + setPercentComplete(0.0); + + // Start of loop to get the left edges. + + // Tile loop in line direction through area of interest. + + for (ossim_int32 line = START_LINE; line < STOP_LINE; line += TILE_HEIGHT) + { + const ossim_int32 START_INDEX = line - START_LINE; + const ossim_int32 STOP_INDEX = ( (line+TILE_HEIGHT-1) < STOP_LINE ) ? + (START_INDEX+TILE_HEIGHT-1) : + (theAreaOfInterest.height()-1); + const ossim_int32 TILE_LINE_STOP = ((line+TILE_HEIGHT-1) < STOP_LINE) ? + (line+TILE_HEIGHT-1) : STOP_LINE; + + // See if all the edges have been found for these tile lines. + bool all_edges_found = true; + for (ossim_int32 i = START_INDEX; i <= STOP_INDEX; ++i) + { + if (theLeftEdge[i] == OSSIM_INT_NAN) + { + all_edges_found = false; + break; + } + } + + // Extract the left edges... + if (all_edges_found == false) + { + //*** + // Tile loop in sample direction through area of interest + // (left edges). + //*** + for (ossim_int32 samp = START_SAMP; samp < STOP_SAMP; samp += TILE_WIDTH) + { + // Get the tile. + ossimRefPtr<ossimImageData> id = + src->getTile(ossimIpt(samp, line)); + + if (!id.valid() || id->getDataObjectStatus() == OSSIM_NULL || + id->getDataObjectStatus() == OSSIM_EMPTY) + { + continue; // Nothing to do... + } + + // Line loop through tile. + const ossim_int32 TILE_SAMP_STOP = ((samp+TILE_WIDTH-1) < STOP_SAMP) ? + (samp+TILE_WIDTH-1) : STOP_SAMP; + + for (ossim_int32 y = line; y <= TILE_LINE_STOP; ++y) + { + ossim_int32 edge_index = y - START_LINE; + if (theLeftEdge[edge_index] == OSSIM_INT_NAN) + { + for (ossim_int32 x = samp; x <= TILE_SAMP_STOP; ++x) + { + if (! (id->isNull(ossimIpt(x,y)))) + { + // Capture the first valid pixel. + theLeftEdge[edge_index] = x - START_SAMP; + break; + } + } + } + } + } // End of tile loop in sample direction through area of interest. + } // End of (all_lines_checked == false) (left edges) + + // See if all the right edges have been found for these tile lines. + all_edges_found = true; + for (ossim_int32 i = START_INDEX; i <= STOP_INDEX; ++i) + { + if (theRightEdge[i] == OSSIM_INT_NAN) + { + all_edges_found = false; + break; + } + } + + // Extract the right edges... + if (all_edges_found == false) + { + //*** + // Tile loop in sample direction through area of interest + // (right edges). + //*** + + // Get the x origin of the last tile in a row. + const ossim_int32 END_TILE_X = START_SAMP + ((theAreaOfInterest.width()/ + TILE_WIDTH)*TILE_WIDTH); + + + for (ossim_int32 samp = END_TILE_X; samp >= START_SAMP; samp -= TILE_WIDTH) + { + // Get the tile. + ossimRefPtr<ossimImageData> id = + src->getTile(ossimIpt(samp, line)); + + if (!id.valid() || id->getDataObjectStatus() == OSSIM_NULL || + id->getDataObjectStatus() == OSSIM_EMPTY) + { + continue; // Nothing to do... + } + + // Line loop through tile. + const ossim_int32 TILE_SAMP_STOP = ((samp+TILE_WIDTH-1) < STOP_SAMP) ? + (samp+TILE_WIDTH-1) : STOP_SAMP; + + for (ossim_int32 y = line; y <= TILE_LINE_STOP; ++y) + { + ossim_int32 edge_index = y - START_LINE; + if (theRightEdge[edge_index] == OSSIM_INT_NAN) + { + for (ossim_int32 x = TILE_SAMP_STOP; x >= samp; --x) + { + if (! (id->isNull(ossimIpt(x,y)))) + { + // Capture the first valid pixel. + theRightEdge[edge_index] = x - START_SAMP; + break; + } + } + } + } + + } // End of tile loop in sample direction through area of interest. + + } // End of (all_lines_checked == false) + + // Set the percent complete. + tiles_processed += 1.0; + setPercentComplete(tiles_processed/total_tiles_y_dir*100.0); + } // End of loop through tiles in line direction. + + setPercentComplete(100.0); + + if (traceDebug()) + { + CLOG << "DEBUG:" << endl; + for (ossim_int32 i=0; i<(int)theAreaOfInterest.height(); ++i) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG: left[" << i << "]: " + << theLeftEdge[i] + << " right[" << i << "]: " + << theRightEdge[i] + << std::endl; + } + } + + + return true; +} + +bool ossimVertexExtractor::extractVertices() +{ + //*** + // This method returns the non-null vertexes of the image corners. + // This can be used to initialize the "ValidImageVertices" for an + // image. + // This method does not handle images that have more than four vertexes. + //*** + static const char MODULE[] = "ossimVertexExtractor::extractVertices"; + + if (traceDebug()) CLOG << " Entered..." << endl; + + if (!theLeftEdge || !theRightEdge) + { + ossimNotify(ossimNotifyLevel_WARN) << "ERROR ossimVertexExtractor::extractVertices():" + << "\nEdges not initialized!" << std::endl; + return false; + } + + // Image must be quadrilateral (i.e. 4 sided polygon) + + ossim_int32 total_lines = theAreaOfInterest.height(); + + ossim_int32 topLine = 0; + ossim_int32 bottomLine = 0; + + ossim_int32 firstLeftSample = 0; + ossim_int32 firstRightSample = 0; + + ossim_int32 lastLeftSample = 0; + ossim_int32 lastRightSample = 0; + + ossim_int32 leftMostSample = 0; + ossim_int32 leftMostSampleLine = 0; + + ossim_int32 rightMostSample = 0; + ossim_int32 rightMostSampleLine = 0; + + ossim_int32 leftCorner_A = 0; + ossim_int32 leftCornerLine_A = 0; + ossim_int32 leftCorner_B = 0; + ossim_int32 leftCornerLine_B = 0; + + ossim_int32 rightCorner_A = 0; + ossim_int32 rightCornerLine_A = 0; + ossim_int32 rightCorner_B = 0; + ossim_int32 rightCornerLine_B = 0; + + + bool found_first_non_null_line = 0; + bool found_last_non_null_line = 0; + + bool rhombus = false; + bool square = false; + bool left = false; + bool right = false; + + ossim_int32 first_non_null_line = 0; + ossim_int32 last_non_null_line = 0; + + ossim_int32 i = 0; + while(found_last_non_null_line == 0) + { + // Look for the first row with a valid DN + // Nulls are negative + + if( (theLeftEdge[i] >= 0) + && (found_first_non_null_line == 0) ) + { + // Found first valid pixel at row i + found_first_non_null_line = 1; + first_non_null_line = i; + + // Finish walking down the rows of the image + while( (found_first_non_null_line == 1) + && (theLeftEdge[i] >= 0) + && (found_last_non_null_line == 0) + && (i <= total_lines) ) + { + i = i+1; + } + found_last_non_null_line = 1; + last_non_null_line = i-1; + } + + i = i+1; + + }//end while "found_last_non_null_line == 0" + + last_non_null_line = last_non_null_line -1; + + topLine = first_non_null_line; + bottomLine = last_non_null_line; + + // Record the slope searching from the right edge + ossim_int32 k = 0; + ossim_int32 start = first_non_null_line; + ossim_int32 end = last_non_null_line; + ossim_int32 sizeDeltaSlope = last_non_null_line - first_non_null_line; + double* rightSlope = new double[sizeDeltaSlope]; + + for(ossim_int32 i = start; i <= (end - 100); i += 100) + { + ossim_int32 run = theRightEdge[i] - theRightEdge[i + 100]; + if(run != 0) + { + rightSlope[k] = 100.0 / run; + } + else + { + rightSlope[k]= OSSIM_INT_NAN; + } + + k = k + 1; + } + if (traceDebug()) + { + CLOG << "DEBUG:" << endl; + for (ossim_int32 i=0; i<= k-1; i++) + { + ossimNotify(ossimNotifyLevel_DEBUG)<< setprecision(15) << "rightSlope[" << i << "]: " + << rightSlope[i] + << std::endl; + } + } + + // Record the slope searching from the left edge + k = 0; + double* leftSlope = new double[sizeDeltaSlope]; + + for(ossim_int32 i = start; i <= (end - 100); i += 100) + { + ossim_int32 run = theLeftEdge[i] - theLeftEdge[i + 100]; + if(run != 0) + { + leftSlope[k] = 100.0 / run; + } + else + { + leftSlope[k] = OSSIM_INT_NAN; + } + + k = k + 1; + } + if (traceDebug()) + { + CLOG << "DEBUG:" << endl; + for (ossim_int32 i=0; i<= k-1; i++) + { + ossimNotify(ossimNotifyLevel_DEBUG) << setprecision(15) << "leftSlope[" << i << "]: " + << leftSlope[i] + << std::endl; + } + } + ossim_int32 sizeOftheSlope = k-1; + ossim_int32 counter = 0; + + + // Find the right most sample + ossim_int32 rightMostEdgeTemp = theRightEdge[topLine]; + ossim_int32 rightMostEdgeTempLine = 0; + + for(ossim_int32 i= (topLine+1); i<bottomLine; i++) + { + if(theRightEdge[i] >= rightMostEdgeTemp) + { + rightMostEdgeTemp = theRightEdge[i]; + rightMostEdgeTempLine = i; + } + } + rightMostSample = rightMostEdgeTemp; + rightMostSampleLine = rightMostEdgeTempLine-1; + lastLeftSample = theLeftEdge[bottomLine]; + + // Find the left most sample + ossim_int32 leftMostEdgeTemp = theLeftEdge[topLine]; + ossim_int32 leftMostEdgeTempLine = 0; + + for(ossim_int32 i= (topLine+1); i<bottomLine; i++) + { + if(theLeftEdge[i] <= leftMostEdgeTemp) + { + leftMostEdgeTemp = theLeftEdge[i]; + leftMostEdgeTempLine = i; + } + } + leftMostSample = leftMostEdgeTemp; + leftMostSampleLine = leftMostEdgeTempLine-1; + firstLeftSample = theLeftEdge[topLine]; + + // Case: Check for square + for(ossim_int32 i=0; i < sizeOftheSlope; ++i) + { + if(leftSlope[i]==rightSlope[i]) + { + counter = counter + 1; + } + } + + if(counter == sizeOftheSlope) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG)<<"\n\n***Case = SQUARE***"<<endl<<endl; + } + + square = 1; + + leftCornerLine_A = topLine; + //leftCorner_A = theLeftEdge[topLine]; //0 + leftCorner_A = leftMostSample; + + rightCornerLine_A = topLine; + //rightCorner_A = theRightEdge[topLine]; //1 + rightCorner_A = rightMostSample; //1 + + rightCornerLine_B = bottomLine; + //rightCorner_B = theRightEdge[bottomLine]; //2 + rightCorner_B = rightMostSample; + + leftCornerLine_B = bottomLine; + //leftCorner_B = theLeftEdge[bottomLine]; //3 + leftCorner_B = leftMostSample; + } + + firstRightSample = theRightEdge[topLine]; + lastRightSample = theRightEdge[bottomLine]; + + + + ossim_int32 halfsamps = (rightMostSample - leftMostSample ) / 2; + + if(square == 0) + { + if( (firstRightSample - firstLeftSample) > halfsamps ) + { + // Case is rhombus (clipped or not clipped) + + rhombus = 1; + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG)<<"\n\n***Case = RHOMBUS***"<<endl; + ossimNotify(ossimNotifyLevel_DEBUG)<<"here"<<endl; + } + + leftCornerLine_A = topLine; + leftCorner_A = firstLeftSample; //0 + + rightCornerLine_A = topLine; + rightCorner_A= firstRightSample; //1 + + rightCornerLine_B = bottomLine; + rightCorner_B = lastRightSample; //2 + + leftCornerLine_B = bottomLine; + leftCorner_B = lastLeftSample; //3 + + } + } + + + if(square == 0 && rhombus == 0) + {//if not square or rhombus + + if(firstLeftSample < lastLeftSample) + {//if tilted right + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG)<<"\n\n***Case = TILTED RIGHT***"<<endl<<endl; + } + + right = true; + + // Regression line 2 is the right side + // Regression line 4 is the left side + // These are handled differently + // These sides may be 'uneven' or 'torn' or 'louvered' + // This code finds the best regression line that 'cuts off' + // this edge fringe + + //Regression Line 1 + + ossim_int32 line1_pt4 = rightMostSampleLine; + ossim_int32 line1_pt0 = topLine; + ossim_int32 line1_pt2 = (line1_pt0 + line1_pt4)/2; + ossim_int32 line1_pt1 = (line1_pt2 + line1_pt0)/2; + ossim_int32 line1_pt3 = (line1_pt2 + line1_pt4)/2; + + double line1RegPtsSamples[] = {theRightEdge[line1_pt1], + theRightEdge[line1_pt2], + theRightEdge[line1_pt3]}; + double line1RegPtsLines[] = {-line1_pt1, + -line1_pt2, + -line1_pt3}; + + double sum_xy_line1 = 0.0; + double sum_x_line1 = 0.0; + double sum_y_line1 = 0.0; + double mean_x_line1 = 0.0; + double mean_y_line1 = 0.0; + double sum_x_squared_line1 = 0.0; + double sum_squared_x_line1 = 0.0; + double b_line1; + double a_line1; + double num_elements_line1 = 3.0; + + for(ossim_int32 i = 0; i < num_elements_line1; ++i) + { + sum_xy_line1 = sum_xy_line1 + + (line1RegPtsSamples[i]*line1RegPtsLines[i]); + + sum_x_line1 = sum_x_line1 + line1RegPtsSamples[i]; + sum_y_line1 = sum_y_line1 + line1RegPtsLines[i]; + + sum_squared_x_line1 = sum_squared_x_line1 + + line1RegPtsSamples[i]*line1RegPtsSamples[i]; + } + + sum_x_squared_line1 = sum_x_line1*sum_x_line1; + mean_y_line1 = sum_y_line1/num_elements_line1; + mean_x_line1 = sum_x_line1/num_elements_line1; + b_line1 = (sum_xy_line1 - (sum_x_line1*sum_y_line1)/num_elements_line1) + / (sum_squared_x_line1 - (sum_x_squared_line1/num_elements_line1)); + a_line1 = mean_y_line1 - b_line1*mean_x_line1; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG)<<" a_line1: "<< a_line1 <<std::endl; + ossimNotify(ossimNotifyLevel_DEBUG)<<" b_line1: "<< b_line1 <<std::endl; + + + for(ossim_int32 i = 0; i < num_elements_line1; ++i) + { + + ossimNotify(ossimNotifyLevel_DEBUG) << setprecision(15) << "line1RegPtsLines[" << i + << "]: " <<line1RegPtsLines[i] + << "\nline1RegPtsSamples[" << i << "]: " + <<line1RegPtsSamples[i] + << std::endl; + + } + } + + //Regression Line 2 + ossim_int32 line2_pt0 = rightMostSampleLine; + ossim_int32 line2_pt4 = bottomLine; + ossim_int32 line2_pt2 = (line2_pt0 + line2_pt4)/2; + ossim_int32 line2_pt1 = (line2_pt2 + line2_pt0)/2; + ossim_int32 line2_pt3 = (line2_pt2 + line2_pt4)/2; + + + ossim_int32 minValuePt1; + ossim_int32 minOffsetPt1; + getMinAndIndex(&theRightEdge[line2_pt1-100], + &theRightEdge[line2_pt1+100], + minValuePt1, minOffsetPt1 ); + line2_pt1 = line2_pt1-100 + minOffsetPt1; + + ossim_int32 minValuePt2; + ossim_int32 minOffsetPt2; + getMinAndIndex(&theRightEdge[line2_pt2-100], + &theRightEdge[line2_pt2+100], + minValuePt2, minOffsetPt2 ); + line2_pt2 = line2_pt2-100 + minOffsetPt2; + + + ossim_int32 minValuePt3; + ossim_int32 minOffsetPt3; + getMinAndIndex(&theRightEdge[line2_pt3-100],&theRightEdge[line2_pt3+100], + minValuePt3, minOffsetPt3 ); + line2_pt3 = line2_pt3-100 + minOffsetPt3; + + //*** + // Find the line within 100 lines of line2_ptx that has the + // minimum sample. This will cut off the 'fringe' + //*** + + double line2RegPtsSamples[] = {theRightEdge[line2_pt1], + theRightEdge[line2_pt2], + theRightEdge[line2_pt3]}; + double line2RegPtsLines[] = {-line2_pt1, + -line2_pt2, + -line2_pt3}; + + double sum_xy_line2 = 0.0; + double sum_x_line2 = 0.0; + double sum_y_line2 = 0.0; + double mean_x_line2 = 0.0; + double mean_y_line2 = 0.0; + double sum_x_squared_line2 = 0.0; + double sum_squared_x_line2 = 0.0; + double b_line2; + double a_line2; + double num_elements_line2 = 3.0; + + for(ossim_int32 i = 0; i < num_elements_line2; ++i) + { + sum_xy_line2 = sum_xy_line2 + + (line2RegPtsSamples[i]*line2RegPtsLines[i]); + + sum_x_line2 = sum_x_line2 + line2RegPtsSamples[i]; + sum_y_line2 = sum_y_line2 + line2RegPtsLines[i]; + + sum_squared_x_line2 = sum_squared_x_line2 + + line2RegPtsSamples[i]*line2RegPtsSamples[i]; + } + + sum_x_squared_line2 = sum_x_line2*sum_x_line2; + mean_y_line2 = sum_y_line2/num_elements_line2; + mean_x_line2 = sum_x_line2/num_elements_line2; + b_line2 = (sum_xy_line2 - (sum_x_line2*sum_y_line2)/num_elements_line2) + / (sum_squared_x_line2 - (sum_x_squared_line2/num_elements_line2)); + a_line2 = mean_y_line2 - b_line2*mean_x_line2; + + if(traceDebug()) + { + for(ossim_int32 i = 0; i < num_elements_line2; ++i) + { + ossimNotify(ossimNotifyLevel_DEBUG) << setprecision(15) << "line2RegPtsLines[" << i << "]: " + <<line2RegPtsLines[i] + << "\nline2RegPtsSamples[" << i << "]: " + <<line2RegPtsSamples[i] + <<std::endl; + } + ossimNotify(ossimNotifyLevel_DEBUG) << "\na_line2: " << a_line2 + << "\nb_line2: " << b_line2 << std::endl; + + } + + //End regression line2 + + //Intersect lines 1 and 2 to get the ur corner vertex + + double ur_x = (a_line1 - a_line2)/(b_line2 - b_line1); + double ur_y = -(a_line1 + b_line1*ur_x); + + //Regression Line 3 + + ossim_int32 line3_pt0 = leftMostSampleLine; + ossim_int32 line3_pt4 = bottomLine; + ossim_int32 line3_pt2 = (line3_pt0 + line3_pt4)/2; + ossim_int32 line3_pt1 = (line3_pt2 + line3_pt0)/2; + ossim_int32 line3_pt3 = (line3_pt2 + line3_pt4)/2; + + double line3RegPtsSamples[] = {theLeftEdge[line3_pt1], + theLeftEdge[line3_pt2], + theLeftEdge[line3_pt3]}; + double line3RegPtsLines[] = {-line3_pt1, + -line3_pt2, + -line3_pt3}; + + double sum_xy_line3 = 0.0; + double sum_x_line3 = 0.0; + double sum_y_line3 = 0.0; + double mean_x_line3 = 0.0; + double mean_y_line3 = 0.0; + double sum_x_squared_line3 = 0.0; + double sum_squared_x_line3 = 0.0; + double b_line3; + double a_line3; + double num_elements_line3 = 3.0; + + for(ossim_int32 i = 0; i < num_elements_line3; ++i) + { + sum_xy_line3 = sum_xy_line3 + + (line3RegPtsSamples[i]*line3RegPtsLines[i]); + + sum_x_line3 = sum_x_line3 + line3RegPtsSamples[i]; + sum_y_line3 = sum_y_line3 + line3RegPtsLines[i]; + + sum_squared_x_line3 = sum_squared_x_line3 + + line3RegPtsSamples[i]*line3RegPtsSamples[i]; + + } + + sum_x_squared_line3 = sum_x_line3*sum_x_line3; + mean_y_line3 = sum_y_line3/num_elements_line3; + mean_x_line3 = sum_x_line3/num_elements_line3; + b_line3 = (sum_xy_line3 - (sum_x_line3*sum_y_line3)/num_elements_line3) + / (sum_squared_x_line3 - (sum_x_squared_line3/num_elements_line3)); + a_line3 = mean_y_line3 - b_line3*mean_x_line3; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "\n\n a_line3: " << a_line3 <<std::endl; + ossimNotify(ossimNotifyLevel_DEBUG) << " b_line3: " << b_line3 <<std::endl; + + + for(ossim_int32 i = 0; i < num_elements_line3; ++i) + { + + ossimNotify(ossimNotifyLevel_DEBUG) << setprecision(15) << "line3RegPtsLines[" << i << "]: " + <<line3RegPtsLines[i] + << "\nline3RegPtsSamples[" << i << "]: " + <<line3RegPtsSamples[i] + << std::endl; + } + } + //End regression line3 + + //Intersect lines 2 and 3 to get the lr corner vertex + + double lr_x = (a_line3 - a_line2)/(b_line2 - b_line3); + double lr_y = -(a_line3 + b_line3*lr_x); + + //End Regression Line3 + + //Regression Line 4 + + ossim_int32 line4_pt0 = leftMostSampleLine; + ossim_int32 line4_pt4 = topLine; + ossim_int32 line4_pt2 = (line4_pt0 + line4_pt4)/2; + ossim_int32 line4_pt1 = (line4_pt2 + line4_pt0)/2; + ossim_int32 line4_pt3 = (line4_pt2 + line4_pt4)/2; + +// //*** +// // Find the line within 100 lines of line2_ptx that has the maximum +// // sample. This will cut off the 'fringe'. +// //*** + + ossim_int32 maxValueLine4Pt1; + ossim_int32 maxOffsetLine4Pt1; + getMaxAndIndex(&theLeftEdge[line4_pt1-100],&theLeftEdge[line4_pt1+100], + maxValueLine4Pt1, maxOffsetLine4Pt1 ); + line4_pt1 = line4_pt1-100 + maxOffsetLine4Pt1; + + + ossim_int32 maxValueLine4Pt2; + ossim_int32 maxOffsetLine4Pt2; + getMaxAndIndex(&theLeftEdge[line4_pt2-100],&theLeftEdge[line4_pt2+100], + maxValueLine4Pt2, maxOffsetLine4Pt2 ); + line4_pt2 = line4_pt2-100 + maxOffsetLine4Pt2; + + + ossim_int32 maxValueLine4Pt3; + ossim_int32 maxOffsetLine4Pt3; + getMaxAndIndex(&theLeftEdge[line4_pt3-100],&theLeftEdge[line4_pt3+100], + maxValueLine4Pt3, maxOffsetLine4Pt3 ); + line4_pt3 = line4_pt3-100 + maxOffsetLine4Pt3; + + + + + double line4RegPtsSamples[] = {theLeftEdge[line4_pt1], + theLeftEdge[line4_pt2], + theLeftEdge[line4_pt3]}; + double line4RegPtsLines[] = {-line4_pt1, + -line4_pt2, + -line4_pt3}; + + double sum_xy_line4 = 0.0; + double sum_x_line4 = 0.0; + double sum_y_line4 = 0.0; + double mean_x_line4 = 0.0; + double mean_y_line4 = 0.0; + double sum_x_squared_line4 = 0.0; + double sum_squared_x_line4 = 0.0; + double b_line4; + double a_line4; + double num_elements_line4 = 3.0; + for(ossim_int32 i = 0; i < num_elements_line4; ++i) + { + sum_xy_line4 = sum_xy_line4 + + (line4RegPtsSamples[i]*line4RegPtsLines[i]); + + sum_x_line4 = sum_x_line4 + line4RegPtsSamples[i]; + sum_y_line4 = sum_y_line4 + line4RegPtsLines[i]; + + sum_squared_x_line4 = sum_squared_x_line4 + + line4RegPtsSamples[i]*line4RegPtsSamples[i]; + + + } + + sum_x_squared_line4 = sum_x_line4*sum_x_line4; + mean_y_line4 = sum_y_line4/num_elements_line4; + mean_x_line4 = sum_x_line4/num_elements_line4; + b_line4 = (sum_xy_line4 - (sum_x_line4*sum_y_line4)/num_elements_line4) + / (sum_squared_x_line4 - (sum_x_squared_line4/num_elements_line4)); + a_line4 = mean_y_line4 - b_line4*mean_x_line4; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG)<<"\na_line4: "<< a_line4 + <<"\nb_line4: "<< b_line4 <<std::endl; + + for(ossim_int32 i = 0; i < num_elements_line4; ++i) + { + + ossimNotify(ossimNotifyLevel_DEBUG) << setprecision(15) << "line4RegPtsLines[" << i << "]: " + <<line4RegPtsLines[i] + << "\nline4RegPtsSamples[" << i << "]: " + <<line4RegPtsSamples[i] + << std::endl; + + } + } + //End regression line4 + + //Intersect lines 3 and 4 to get the ll corner vertex + + double ll_x = (a_line4 - a_line3)/(b_line3 - b_line4); + double ll_y = -(a_line4 + b_line4*ll_x); + + //End Regression Line4 + + //Intersect lines 4 and 1 to get the ul corner vertex + + double ul_x = (a_line4 - a_line1)/(b_line1 - b_line4); + double ul_y = -(a_line4 + b_line4*ul_x); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG)<<"\n\nInitial corners for tilted right: " + <<"\ncorner0: ("<<ul_x<<", "<<ul_y<<")" + <<"\ncorner1: ("<<ur_x<<", "<<ur_y<<")" + <<"\ncorner2: ("<<lr_x<<", "<<lr_y<<")" + <<"\ncorner3: ("<<ll_x<<", "<<ll_y<<")"<<std::endl<<std::endl; + } + + leftCornerLine_A = (ossim_int32)ul_y; + leftCorner_A = (ossim_int32)ul_x; //0 + + rightCornerLine_A = (ossim_int32)ur_y; + rightCorner_A = (ossim_int32)ur_x; //1 + + rightCornerLine_B = (ossim_int32)lr_y; + rightCorner_B =(ossim_int32)lr_x; //2 + + leftCornerLine_B = (ossim_int32)ll_y; + leftCorner_B =(ossim_int32)ll_x; //3 + + + // Check for bad corner points due to irregular shape image + + //for corner 0 (ul), sample should be between left and right most samples + // line can go negative due to jagged edges + + //for corner 1 (ur), sample can go > than num samples + // line should be between top and bottom lines + + //for corner 2 (lr), line should be between top and bottom line + 200 + // sample should be between left and right most sample + + //for corner 3 (ll), line should be between top and bottom line + // sample should can go negative due to jagged edges + + if( (leftCornerLine_A < (topLine - 300)) + || (leftCornerLine_A > total_lines) + || (leftCorner_A > rightMostSample) + || (leftCorner_A < leftMostSample) + + || (rightCornerLine_A < topLine) + || (rightCornerLine_A > bottomLine) + || (rightCorner_A < leftMostSample) + || (rightCorner_A > (rightMostSample + 200)) + + + || (rightCornerLine_B < topLine) + || (rightCornerLine_B > (bottomLine + 200)) + || (rightCorner_B < leftMostSample) + || (rightCorner_B > rightMostSample) + + || (leftCornerLine_B > bottomLine) + || (leftCornerLine_B < topLine) + || (leftCorner_B > rightMostSample) + || (leftCorner_B < (leftMostSample - 200)) ) + + + + { + right = false; + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) <<"\n\n***Case = NOT TILTED RIGHT...***"<<std::endl; + } + } + } + + //tilted left + if(firstRightSample > lastRightSample) + {//begin tilted left + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) <<"\n\n***Case = TILTED LEFT***"<<std::endl; + } + left = true; + + // Regression line 1 is the right side + // Regression line 3 is the left side + // These are handled differently + // These sides may be 'uneven' or 'torn' or 'louvered' + // This code finds the best regression line that 'cuts off' this edge fringe + + + //Regression Line 1 + + ossim_int32 line1_pt4 = rightMostSampleLine; + ossim_int32 line1_pt0 = topLine; + ossim_int32 line1_pt2 = (line1_pt0 + line1_pt4)/2; + ossim_int32 line1_pt1 = (line1_pt2 + line1_pt0)/2; + ossim_int32 line1_pt3 = (line1_pt2 + line1_pt4)/2; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG)<<" line1_pt1: "<<line1_pt0<<std::endl; + ossimNotify(ossimNotifyLevel_DEBUG)<<" line1_pt2: "<<line1_pt1<<std::endl; + ossimNotify(ossimNotifyLevel_DEBUG)<<" line1_pt3: "<<line1_pt2<<std::endl; + ossimNotify(ossimNotifyLevel_DEBUG)<<" line1_pt4: "<<line1_pt3<<std::endl; + } + + ossim_int32 minValueLine1Pt1; + ossim_int32 minOffsetLine1Pt1; + getMinAndIndex(&theLeftEdge[line1_pt1-100],&theLeftEdge[line1_pt1+100], + minValueLine1Pt1, minOffsetLine1Pt1 ); + line1_pt1 = line1_pt1-100 + minOffsetLine1Pt1; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << " line1_pt1: "<< line1_pt1 + <<" minValueLine1Pt1: "<<minValueLine1Pt1<<"\n\n"; + } + + ossim_int32 minValueLine1Pt2; + ossim_int32 minOffsetLine1Pt2; + getMinAndIndex(&theLeftEdge[line1_pt2-100],&theLeftEdge[line1_pt2+100], + minValueLine1Pt2, minOffsetLine1Pt2 ); + line1_pt2 = line1_pt2-100 + minOffsetLine1Pt2; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << " line1_pt2: "<< line1_pt2 + <<" minValueLine1Pt2: "<<minValueLine1Pt2<<"\n\n"; + } + + + ossim_int32 minValueLine1Pt3; + ossim_int32 minOffsetLine1Pt3; + getMinAndIndex(&theLeftEdge[line1_pt3-100],&theLeftEdge[line1_pt3+100], + minValueLine1Pt3, minOffsetLine1Pt3 ); + line1_pt3 = line1_pt3-100 + minOffsetLine1Pt3; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << " line1_pt3: "<< line1_pt3 + <<" minValueLine1Pt3: "<<minValueLine1Pt3<<std::endl<<std::endl; + } + + double line1RegPtsSamples[] = {theRightEdge[line1_pt1], + theRightEdge[line1_pt2], + theRightEdge[line1_pt3]}; + double line1RegPtsLines[] = {-line1_pt1, + -line1_pt2, + -line1_pt3}; + + double sum_xy_line1 = 0.0; + double sum_x_line1 = 0.0; + double sum_y_line1 = 0.0; + double mean_x_line1 = 0.0; + double mean_y_line1 = 0.0; + double sum_x_squared_line1 = 0.0; + double sum_squared_x_line1 = 0.0; + double b_line1; + double a_line1; + double num_elements_line1 = 3.0; + + for(ossim_int32 i = 0; i < num_elements_line1; ++i) + { + sum_xy_line1 = sum_xy_line1 + + (line1RegPtsSamples[i]*line1RegPtsLines[i]); + + sum_x_line1 = sum_x_line1 + line1RegPtsSamples[i]; + sum_y_line1 = sum_y_line1 + line1RegPtsLines[i]; + + sum_squared_x_line1 = sum_squared_x_line1 + + line1RegPtsSamples[i]*line1RegPtsSamples[i]; + + + } + + sum_x_squared_line1 = sum_x_line1*sum_x_line1; + mean_y_line1 = sum_y_line1/num_elements_line1; + mean_x_line1 = sum_x_line1/num_elements_line1; + b_line1 = (sum_xy_line1 - (sum_x_line1*sum_y_line1)/num_elements_line1) + / (sum_squared_x_line1 - (sum_x_squared_line1/num_elements_line1)); + a_line1 = mean_y_line1 - b_line1*mean_x_line1; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG)<<"a_line1: "<< a_line1 + <<"\nb_line1: "<< b_line1 <<std::endl; + + for(ossim_int32 i = 0; i < num_elements_line1; ++i) + { + + ossimNotify(ossimNotifyLevel_DEBUG) << setprecision(15) << "line1RegPtsLines[" << i << "]: " + <<line1RegPtsLines[i] + << "\nline1RegPtsSamples[" << i << "]: " + <<line1RegPtsSamples[i] + << std::endl; + } + } + + + //Regression Line 2 + + ossim_int32 line2_pt0 = rightMostSampleLine; + ossim_int32 line2_pt4 = bottomLine; + ossim_int32 line2_pt2 = (line2_pt0 + line2_pt4)/2; + ossim_int32 line2_pt1 = (line2_pt2 + line2_pt0)/2; + ossim_int32 line2_pt3 = (line2_pt2 + line2_pt4)/2; + + double line2RegPtsSamples[] = {theRightEdge[line2_pt1], + theRightEdge[line2_pt2], + theRightEdge[line2_pt3]}; + double line2RegPtsLines[] = {-line2_pt1, + -line2_pt2, + -line2_pt3}; + + double sum_xy_line2 = 0.0; + double sum_x_line2 = 0.0; + double sum_y_line2 = 0.0; + double mean_x_line2 = 0.0; + double mean_y_line2 = 0.0; + double sum_x_squared_line2 = 0.0; + double sum_squared_x_line2 = 0.0; + double b_line2; + double a_line2; + double num_elements_line2 = 3.0; + for(ossim_int32 i = 0; i < num_elements_line2; ++i) + { + sum_xy_line2 = sum_xy_line2 + + (line2RegPtsSamples[i]*line2RegPtsLines[i]); + + sum_x_line2 = sum_x_line2 + line2RegPtsSamples[i]; + sum_y_line2 = sum_y_line2 + line2RegPtsLines[i]; + + sum_squared_x_line2 = sum_squared_x_line2 + + line2RegPtsSamples[i]*line2RegPtsSamples[i]; + } + + sum_x_squared_line2 = sum_x_line2*sum_x_line2; + mean_y_line2 = sum_y_line2/num_elements_line2; + mean_x_line2 = sum_x_line2/num_elements_line2; + b_line2 = (sum_xy_line2 - (sum_x_line2*sum_y_line2)/num_elements_line2) + / (sum_squared_x_line2 - (sum_x_squared_line2/num_elements_line2)); + a_line2 = mean_y_line2 - b_line2*mean_x_line2; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "a_line2: "<< a_line2 + << "\nb_line2: "<< b_line2 <<std::endl; + + for(ossim_int32 i = 0; i < num_elements_line2; ++i) + { + + ossimNotify(ossimNotifyLevel_DEBUG) << setprecision(15) << "line2RegPtsLines[" << i << "]: " + <<line2RegPtsLines[i] + << "\nline2RegPtsSamples[" << i << "]: " + <<line2RegPtsSamples[i] + << std::endl; + } + } + //End regression line2 + + //Intersect lines 1 and 2 to get the lr corner vertex + + double lr_x = (a_line1 - a_line2)/(b_line2 - b_line1); + double lr_y = -(a_line1 + b_line1*lr_x); + + //Regression Line 3 + + ossim_int32 line3_pt0 = leftMostSampleLine; + ossim_int32 line3_pt4 = bottomLine; + ossim_int32 line3_pt2 = (line3_pt0 + line3_pt4)/2; + ossim_int32 line3_pt1 = (line3_pt2 + line3_pt0)/2; + ossim_int32 line3_pt3 = (line3_pt2 + line3_pt4)/2; + + ossim_int32 maxValueLine3Pt1; + ossim_int32 maxOffsetLine3Pt1; + getMaxAndIndex(&theLeftEdge[line3_pt1-100],&theLeftEdge[line3_pt1+100], + maxValueLine3Pt1, maxOffsetLine3Pt1 ); + line3_pt1 = line3_pt1-100 + maxOffsetLine3Pt1; + + + ossim_int32 maxValueLine3Pt2; + ossim_int32 maxOffsetLine3Pt2; + getMaxAndIndex(&theLeftEdge[line3_pt2-100],&theLeftEdge[line3_pt2+100], + maxValueLine3Pt2, maxOffsetLine3Pt2 ); + line3_pt2 = line3_pt2-100 + maxOffsetLine3Pt2; + + + ossim_int32 maxValueLine3Pt3; + ossim_int32 maxOffsetLine3Pt3; + getMaxAndIndex(&theLeftEdge[line3_pt3-100],&theLeftEdge[line3_pt3+100], + maxValueLine3Pt3, maxOffsetLine3Pt3 ); + line3_pt3 = line3_pt3-100 + maxOffsetLine3Pt3; + + + double line3RegPtsSamples[] = {theLeftEdge[line3_pt1], + theLeftEdge[line3_pt2], + theLeftEdge[line3_pt3]}; + double line3RegPtsLines[] = {-line3_pt1, + -line3_pt2, + -line3_pt3}; + + double sum_xy_line3 = 0.0; + double sum_x_line3 = 0.0; + double sum_y_line3 = 0.0; + double mean_x_line3 = 0.0; + double mean_y_line3 = 0.0; + double sum_x_squared_line3 = 0.0; + double sum_squared_x_line3 = 0.0; + double b_line3; + double a_line3; + double num_elements_line3 = 3.0; + for(ossim_int32 i = 0; i < num_elements_line3; ++i) + { + sum_xy_line3 = sum_xy_line3 + + (line3RegPtsSamples[i]*line3RegPtsLines[i]); + + sum_x_line3 = sum_x_line3 + line3RegPtsSamples[i]; + sum_y_line3 = sum_y_line3 + line3RegPtsLines[i]; + + sum_squared_x_line3 = sum_squared_x_line3 + + line3RegPtsSamples[i]*line3RegPtsSamples[i]; + + + } + + sum_x_squared_line3 = sum_x_line3*sum_x_line3; + mean_y_line3 = sum_y_line3/num_elements_line3; + mean_x_line3 = sum_x_line3/num_elements_line3; + b_line3 = (sum_xy_line3 - (sum_x_line3*sum_y_line3)/num_elements_line3) + / (sum_squared_x_line3 - (sum_x_squared_line3/num_elements_line3)); + a_line3 = mean_y_line3 - b_line3*mean_x_line3; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG)<<"\n\n a_line3: "<< a_line3 <<std::endl + <<" b_line3: "<< b_line3 <<endl; + for(ossim_int32 i = 0; i < num_elements_line3; ++i) + { + + ossimNotify(ossimNotifyLevel_DEBUG) << setprecision(15) << "line3RegPtsLines[" << i << "]: " + << line3RegPtsLines[i] + << "\nline3RegPtsSamples[" << i << "]: " + << line3RegPtsSamples[i] + << std::endl; + } + } + //End regression line3 + + //Intersect lines 2 and 3 to get the ll corner vertex + + double ll_x = (a_line3 - a_line2)/(b_line2 - b_line3); + double ll_y = -(a_line3 + b_line3*ll_x); + + //End Regression Line3 + + //Regression Line 4 + + ossim_int32 line4_pt0 = leftMostSampleLine; + ossim_int32 line4_pt4 = topLine; + ossim_int32 line4_pt2 = (line4_pt0 + line4_pt4)/2; + ossim_int32 line4_pt1 = (line4_pt2 + line4_pt0)/2; + ossim_int32 line4_pt3 = (line4_pt2 + line4_pt4)/2; + + + double line4RegPtsSamples[] = {theLeftEdge[line4_pt1], + theLeftEdge[line4_pt2], + theLeftEdge[line4_pt3]}; + double line4RegPtsLines[] = {-line4_pt1, + -line4_pt2, + -line4_pt3}; + + double sum_xy_line4 = 0.0; + double sum_x_line4 = 0.0; + double sum_y_line4 = 0.0; + double mean_x_line4 = 0.0; + double mean_y_line4 = 0.0; + double sum_x_squared_line4 = 0.0; + double sum_squared_x_line4 = 0.0; + double b_line4; + double a_line4; + double num_elements_line4 = 3.0; + for(ossim_int32 i = 0; i < num_elements_line4; ++i) + { + sum_xy_line4 = sum_xy_line4 + + (line4RegPtsSamples[i]*line4RegPtsLines[i]); + + sum_x_line4 = sum_x_line4 + line4RegPtsSamples[i]; + sum_y_line4 = sum_y_line4 + line4RegPtsLines[i]; + + sum_squared_x_line4 = sum_squared_x_line4 + + line4RegPtsSamples[i]*line4RegPtsSamples[i]; + + + } + + sum_x_squared_line4 = sum_x_line4*sum_x_line4; + mean_y_line4 = sum_y_line4/num_elements_line4; + mean_x_line4 = sum_x_line4/num_elements_line4; + b_line4 = (sum_xy_line4 - (sum_x_line4*sum_y_line4)/num_elements_line4) + / (sum_squared_x_line4 - (sum_x_squared_line4/num_elements_line4)); + a_line4 = mean_y_line4 - b_line4*mean_x_line4; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG)<< "\n\n a_line4: "<< a_line4 <<std::endl; + ossimNotify(ossimNotifyLevel_DEBUG)<< " b_line4: "<< b_line4 <<std::endl; + + for(ossim_int32 i = 0; i < num_elements_line4; ++i) + { + ossimNotify(ossimNotifyLevel_DEBUG) << setprecision(15) << "line4RegPtsLines[" << i << "]: " + <<line4RegPtsLines[i] + << "\nline4RegPtsSamples[" << i << "]: " + <<line4RegPtsSamples[i] + << std::endl; + } + + } + //End regression line 4 + + //Intersect lines 3 and 4 to get the ul corner vertex + + double ul_x = (a_line4 - a_line3)/(b_line3 - b_line4); + double ul_y = -(a_line4 + b_line4*ul_x); + //End Regression Line4 + + //Intersect lines 4 and 1 to get the ur corner vertex + + double ur_x = (a_line4 - a_line1)/(b_line1 - b_line4); + double ur_y = -(a_line4 + b_line4*ur_x); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) <<"Initial corners for tilted left: " + <<"\ncorner0: ("<<ul_x<<", "<<ul_y<<")" + <<"\ncorner1: ("<<ur_x<<", "<<ur_y<<")" + <<"\ncorner2: ("<<lr_x<<", "<<lr_y<<")" + <<"\ncorner3: ("<<ll_x<<", "<<ll_y<<")" <<std::endl; + } + + leftCornerLine_A = (ossim_int32)ul_y; + leftCorner_A = (ossim_int32)ul_x; //0 + + rightCornerLine_A = (ossim_int32)ur_y; + rightCorner_A = (ossim_int32)ur_x; //1 + + rightCornerLine_B = (ossim_int32)lr_y; + rightCorner_B =(ossim_int32)lr_x; //2 + + leftCornerLine_B = (ossim_int32)ll_y; + leftCorner_B =(ossim_int32)ll_x; //3 + + // Check for bad corner points due to irregular shape image + + //for corner 0 (ul), line should be between top and bottom line + // sample should can go negative due to jagged edges + + //for corner 1 (ur), sample should be between left and right most samples + // line can go negative due to jagged edges + + //for corner 2 (lr), line should be between top and bottom lines + // sample can be greater than rightMost samp due to jagged edges + + //for corner 3 (ll), line should be between top and bottom line + 200 + // sample should be between left and right most sample + if( (leftCornerLine_A > bottomLine) + || (leftCornerLine_A < topLine) + || (leftCorner_A > rightMostSample) + || (leftCorner_A < (leftMostSample - 300)) + + || (rightCornerLine_A < (topLine - 300)) + || (rightCornerLine_A > total_lines) + || (rightCorner_A > rightMostSample) + || (rightCorner_A < leftMostSample) + + + || (rightCornerLine_B < topLine) + || (rightCornerLine_B > bottomLine) + || (rightCorner_B < leftMostSample) + || (rightCorner_B > (rightMostSample + 200)) + + || (leftCornerLine_B > (bottomLine + 200)) + || (leftCornerLine_B < topLine) + || (leftCorner_B < leftMostSample) + || (leftCorner_B > rightMostSample) ) + + { + left = false; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) <<"\n\n***Case = NOT TILTED LEFT..***"<<std::endl; + } + } + } + } + + if( (square == 0) && (rhombus == 0) && (right == 0) && (left == 0)) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG)<<"\nDefault case"<<std::endl; + } + + //Suboptimal UL Corner: + leftCornerLine_A = (topLine); + leftCorner_A =(leftMostSample); //0 + + //Look for non-null starting at topLine and going down + //Starting at left most samp and moving right + + bool foundULcornera = false; + bool foundULcornerb = false; + ossimImageHandler* src = reinterpret_cast<ossimImageHandler*>(getInput(0)); + + ossimIrect tileRectUL(leftMostSample, + topLine, + leftMostSample+50, + (topLine + 50) ); + + ossimRefPtr<ossimImageData> dataUL = src->getTile(tileRectUL); + // ossimIrect imageRectangleUL = dataUL->getImageRectangle(); + + ossim_int32 tempSamp_corner0a = 0; + ossim_int32 tempLine_corner0a = 0; + if (dataUL.valid()) + { + for (ossim_int32 line = tileRectUL.ul().y; line <= tileRectUL.lr().y; ++line) + { + for (ossim_int32 samp = tileRectUL.ul().x; samp <=tileRectUL.ur().x; ++samp) + { + // uses band 0 corner points + if(!(dataUL->isNull(ossimIpt(samp,line),0))) + { + + foundULcornera = true; + + //Optimal Corner: + leftCornerLine_A = line;//0 + leftCorner_A = samp; + tempLine_corner0a = line; + tempSamp_corner0a = samp; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + <<"\nFound non null in ul corner pass 1 "<<std::endl + <<"line: "<<line<<std::endl + <<"samp: "<<samp<<std::endl; + } + } + if(foundULcornera == true){break;} + } + if(foundULcornera == true){break;} + } + + // Search in the other direction to handle the case of 'jaggered' edges. + ossim_int32 tempSamp_corner0b = 0; + ossim_int32 tempLine_corner0b = 0; + for (ossim_int32 samp = tileRectUL.ul().x; samp <=tileRectUL.ur().x; ++samp) + { + for (ossim_int32 line = tileRectUL.ul().y; line <= tileRectUL.lr().y; ++line) + { + // uses band 0 corner points + if(!(dataUL->isNull(ossimIpt(samp,line),0))) + { + + foundULcornerb = true; + + //Optimal Corner: + leftCornerLine_A = line;//0 + leftCorner_A = samp; + tempLine_corner0b = line; + tempSamp_corner0b = samp; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + <<"\nFound non null in ul corner pass 2 "<<std::endl + <<"line: "<<line<<std::endl + <<"samp: "<<samp<<std::endl; + } + } + if(foundULcornerb == true){break;} + } + if(foundULcornerb == true){break;} + } + + //Better corner + if(foundULcornerb == true && foundULcornera ==true) + { + leftCornerLine_B = (tempLine_corner0a + tempLine_corner0b)/2; + leftCorner_B = (tempSamp_corner0a + tempSamp_corner0b)/2; + } + + + // Suboptimal UR corner: + rightCornerLine_A = (topLine); + rightCorner_A = (rightMostSample); //1 + + } + //Look for non-null starting at topLine and going down + //Starting at right most samp and moving left + + bool foundURcornera = false; + bool foundURcornerb = false; + + ossimIrect tileRectUR((rightMostSample - 50), + topLine, + rightMostSample, + (topLine + 50) ); + + ossimRefPtr<ossimImageData> dataUR = src->getTile(tileRectUR); + // ossimIrect imageRectangleUR = dataUR->getImageRectangle(); + + ossim_int32 tempSamp_corner1a = 0; + ossim_int32 tempLine_corner1a = 0; + + if (dataUR.valid()) + { + for (ossim_int32 line = tileRectUR.ul().y; line <= tileRectUR.lr().y; ++line) + { + for (ossim_int32 samp = tileRectUR.ur().x; samp > tileRectUR.ul().x; --samp) + { + + if(!(dataUR->isNull(ossimIpt(samp,line),0))) + { + + foundURcornera = true; + rightCornerLine_A = line; + rightCorner_A = samp; + tempLine_corner1a = line; + tempSamp_corner1a = samp; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + <<"\nFound non null in ur corner pass 1 "<<std::endl + <<"line: "<<line<<std::endl + <<"samp: "<<samp<<std::endl; + } + } + if(foundURcornera == true){break;} + } + if(foundURcornera == true){break;} + } + + // Search in the other direction to handle the case of 'jaggered' edges. + ossim_int32 tempSamp_corner1b = 0; + ossim_int32 tempLine_corner1b = 0; + + for (ossim_int32 samp = tileRectUR.ur().x; samp > tileRectUR.ul().x; --samp) + { + for (ossim_int32 line = tileRectUR.ul().y; line <= tileRectUR.lr().y; ++line) + + { + if(!(dataUR->isNull(ossimIpt(samp,line),0))) + { + + foundURcornerb = true; + rightCornerLine_A = line; + rightCorner_A = samp; + tempLine_corner1b = line; + tempSamp_corner1b = samp; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + <<"\nFound non null in ur corner pass 2 "<<std::endl + <<"line: "<<line<<std::endl + <<"samp: "<<samp<<std::endl; + } + } + if(foundURcornerb == true){break;} + } + if(foundURcornerb == true){break;} + } + + //Better corner + if(foundURcornerb == true && foundURcornera ==true) + { + rightCornerLine_B = (tempLine_corner1a + tempLine_corner1b)/2; + rightCorner_B = (tempSamp_corner1a + tempSamp_corner1b)/2; + } + + // Suboptimal LR corner: + rightCornerLine_B = (bottomLine); + rightCorner_B = (rightMostSample); //2 + + } + + //Look for non-null starting at bottomLine and going up + //Starting at right most samp and moving left + + bool foundLRcornera = false; + bool foundLRcornerb = false; + + ossimIrect tileRectLR((rightMostSample - 50), + bottomLine - 50, + rightMostSample, + (bottomLine) ); + + ossimRefPtr<ossimImageData> dataLR = src->getTile(tileRectLR); + // ossimIrect imageRectangleLR = dataLR->getImageRectangle(); + + ossim_int32 tempSamp_corner2a = 0; + ossim_int32 tempLine_corner2a = 0; + + if (dataLR.valid()) + { + for (ossim_int32 line = tileRectLR.lr().y; line >= tileRectLR.ur().y; --line) + { + for (ossim_int32 samp = tileRectLR.lr().x; samp > tileRectLR.ul().x; --samp) + { + + if(!(dataLR->isNull(ossimIpt(samp,line),0))) + { + + foundLRcornera = true; + rightCornerLine_B = line; + rightCorner_B = samp; + tempLine_corner2a = line; + tempSamp_corner2a = samp; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + <<"\nFound non null in lr corner pass 1 "<<std::endl + <<"line: "<<line<<std::endl + <<"samp: "<<samp<<std::endl; + } + } + if(foundLRcornera == true){break;} + } + if(foundLRcornera == true){break;} + } + // Search in the other direction to handle the case of 'jaggered' edges. + + ossim_int32 tempSamp_corner2b = 0; + ossim_int32 tempLine_corner2b = 0; + + for (ossim_int32 samp = tileRectLR.lr().x; samp > tileRectLR.ul().x; --samp) + { + for (ossim_int32 line = tileRectLR.lr().y; line >= tileRectLR.ur().y; --line) + { + if(!(dataLR->isNull(ossimIpt(samp,line),0))) + { + + foundLRcornerb = true; + rightCornerLine_B = line; + rightCorner_B = samp; + tempLine_corner2b = line; + tempSamp_corner2b = samp; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + <<"\nFound non null in lr corner pass 2"<<std::endl + <<"line: "<<line<<std::endl + <<"samp: "<<samp<<std::endl; + } + } + if(foundLRcornerb == true){break;} + } + if(foundLRcornerb == true){break;} + } + //Better corner + if(foundLRcornerb == true && foundLRcornera ==true) + { + rightCornerLine_B = (tempLine_corner2a + tempLine_corner2b)/2; + rightCorner_B = (tempSamp_corner2a + tempSamp_corner2b)/2; + } + // Suboptimal LL corner: + leftCornerLine_B = (bottomLine); + leftCorner_B = (leftMostSample); //3 + + } + + //Look for non-null starting at bottomLine and going up + //Starting at left most samp and moving right + + bool foundLLcornera = false; + bool foundLLcornerb = false; + + ossimIrect tileRectLL((leftMostSample), + (bottomLine - 50), + (leftMostSample +50), + (bottomLine) ); + + ossimRefPtr<ossimImageData> dataLL = src->getTile(tileRectLL); + // ossimIrect imageRectangleLL = dataLL->getImageRectangle(); + + ossim_int32 tempSamp_corner3a = 0; + ossim_int32 tempLine_corner3a = 0; + + if (dataLL.valid()) + { + for (ossim_int32 samp = tileRectLL.ul().x; samp <= tileRectLL.ur().x; ++samp) + { + + for (ossim_int32 line = tileRectLL.lr().y; line >= tileRectLL.ul().y; --line) + + { + + if(!(dataLL->isNull(ossimIpt(samp,line),0))) + { + + foundLLcornera = true; + leftCornerLine_B = line; + leftCorner_B = samp; + tempLine_corner3a = line; + tempSamp_corner3a = samp; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + <<"\nFound non null in ll corner pass 1"<<std::endl + <<"line: "<<line<<std::endl + <<"samp: "<<samp<<std::endl; + } + } + if(foundLLcornera == true){break;} + } + if(foundLLcornera == true){break;} + } + + // Search in the other direction to handle the case of 'jaggered' edges. + + ossim_int32 tempSamp_corner3b = 0; + ossim_int32 tempLine_corner3b = 0; + for (ossim_int32 line = tileRectLL.lr().y; line >= tileRectLL.ul().y; --line) + { + + for (ossim_int32 samp = tileRectLL.ul().x; samp <= tileRectLL.ur().x; ++samp) + + { + + if(!(dataLL->isNull(ossimIpt(samp,line),0))) + { + + foundLLcornerb = true; + leftCornerLine_B = line; + leftCorner_B = samp; + tempLine_corner3b = line; + tempSamp_corner3b = samp; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + <<"\nFound non null in ll corner pass 2 "<<std::endl + <<"line: "<<line<<std::endl + <<"samp: "<<samp<<std::endl; + } + } + if(foundLLcornerb == true){break;} + } + if(foundLLcornerb == true){break;} + } + + //Better corner + if(foundLLcornerb == true && foundLLcornera ==true) + { + leftCornerLine_B = (tempLine_corner3a + tempLine_corner3b)/2; + leftCorner_B = (tempSamp_corner3a + tempSamp_corner3b)/2; + } + } + } + + theVertice[0].x = leftCorner_A; + theVertice[0].y = leftCornerLine_A; + + theVertice[1].x = rightCorner_A; + theVertice[1].y = rightCornerLine_A; + + theVertice[3].x = leftCorner_B; + theVertice[3].y = leftCornerLine_B; + + theVertice[2].x = rightCorner_B; + theVertice[2].y = rightCornerLine_B; + + if (leftSlope) + { + delete [] leftSlope; + leftSlope = NULL; + } + if (rightSlope) + { + delete [] rightSlope; + rightSlope = NULL; + } + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG)<<"\nleftMostSample: " << leftMostSample + <<"\nleftMostSampleLine: " << leftMostSampleLine + <<"\n\nrightMostSample: " << rightMostSample + <<"\nrightMostSampleLine: " << rightMostSampleLine + + <<"\n\nfirstLeftSample: " << firstLeftSample + <<"\nfirstRightSample: " << firstRightSample + + <<"\n\nlastLeftSample: " << lastLeftSample + <<"\nlastRightSample: " << lastRightSample + + <<"\n\ntopLine: " << topLine + <<"\nbottomLine: " << bottomLine + <<"\ntotal_lines: " << total_lines + + << "\n\n\ntheVertice[0]: " << theVertice[0] + << "\ntheVertice[1]: " << theVertice[1] + << "\ntheVertice[2]: " << theVertice[2] + << "\ntheVertice[3]: " << theVertice[3] + << "\n\nreturning..." << std::endl; + } + + return true; +} + +bool ossimVertexExtractor::writeVertices() +{ + static const char MODULE[] = "ossimVertexExtractor::writeVertices"; + + if (traceDebug()) CLOG << " Entered..." << endl; + + if (!isOpen()) + { + // Try to open. + if (!open()) return false; + } + + // Write the points... + theFileStream << "point0.x: " << theVertice[0].x + << "\npoint0.y: " << theVertice[0].y + << "\npoint1.x: " << theVertice[1].x + << "\npoint1.y: " << theVertice[1].y + << "\npoint2.x: " << theVertice[2].x + << "\npoint2.y: " << theVertice[2].y + << "\npoint3.x: " << theVertice[3].x + << "\npoint3.y: " << theVertice[3].y + << endl; + + // Close the file... + close(); + + return true; +} + + +void ossimVertexExtractor::setOutputName(const ossimString& filename) +{ + ossimOutputSource::setOutputName(filename); + + if (isOpen()) close(); + + theFilename = filename; +} + +void ossimVertexExtractor::setAreaOfInterest(const ossimIrect& rect) +{ + theAreaOfInterest = rect; +} + +bool ossimVertexExtractor::isOpen()const +{ + return const_cast<ofstream*>(&theFileStream)->is_open(); +} + +bool ossimVertexExtractor::open() +{ + if(isOpen()) + { + close(); + } + + if (theFilename == ossimFilename::NIL) + { + ossimNotify(ossimNotifyLevel_WARN) << "ossimVertexExtractor::open WARNING:" + << "\nOutput file has not been set. Call setFilename() method..." + << std::endl; + return false; + } + + theFileStream.open(theFilename.c_str()); + + return theFileStream.good(); +} + +void ossimVertexExtractor::close() +{ + if (isOpen()) theFileStream.close(); +} + +template<class T1> +void ossimVertexExtractor::getMinAndIndex(T1* start, T1* end, + T1& minValue, ossim_int32& offsetFromStart) +{ + + offsetFromStart =0; + ossim_int32 currentOffset = 0; + minValue = *start; + while(start < end) + { + if(*start < minValue) + { + + minValue = *start; + offsetFromStart = currentOffset; + } + ++start; + ++currentOffset; + } +} + +template<class T2> +void ossimVertexExtractor::getMaxAndIndex(T2* start, T2* end, + T2& maxValue, ossim_int32& offsetFromStart) +{ + + offsetFromStart =0; + ossim_int32 currentOffset = 0; + maxValue = *start; + while(start < end) + { + if(*start > maxValue) + { + maxValue = *start; + offsetFromStart = currentOffset; + } + ++start; + ++currentOffset; + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/misc/ossimVertexExtractor.h b/Utilities/OSSIM/ossim_core/imaging/misc/ossimVertexExtractor.h new file mode 100644 index 0000000000..352a27405a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/misc/ossimVertexExtractor.h @@ -0,0 +1,173 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// +//************************************************************************* +// $Id: ossimVertexExtractor.h,v 1.15 2004/04/09 19:11:34 gpotts Exp $ + +#ifndef ossimVertexExtractor_HEADER +#define ossimVertexExtractor_HEADER + +#include <fstream> + +#include <base/common/ossimOutputSource.h> +#include <base/common/ossimProcessInterface.h> +#include <base/common/events/ossimProcessProgressEvent.h> +#include <base/data_types/ossimIrect.h> +#include <base/data_types/ossimFilename.h> +#include <imaging/ossimImageSource.h> + +class ossimImageSource; + + +//! Class ossimVertexExtractor + +/*! + * Class designed to scan the area of interest and detect the valid vertices + * of non null image data. + */ +class OSSIMDLLEXPORT ossimVertexExtractor : public ossimOutputSource, + public ossimProcessInterface +{ +public: + ossimVertexExtractor(ossimImageSource* inputSource=NULL); + + virtual ~ossimVertexExtractor(); + + virtual ossimObject* getObject() + { + return this; + } + virtual const ossimObject* getObject()const + { + return this; + } + /*! + * Sets the area of interest in the source to extract the vertices from. + * @param rect ossimIrec representing source area of interest. + */ + void setAreaOfInterest(const ossimIrect& rect); + + /*! + * Sets the name of the output keyword list file which the vertices will + * be dumped to. + * @param filename ossimFilename representing the output file. + * + * Note: + * - If "theFileStream" is open it will be closed. + */ + virtual void setOutputName(const ossimString& filename); + + /*! + * Returns true if "theFileStream" is open, false if not. + */ + virtual bool isOpen() const; + + /*! + * Opens "theFilename" for output. + * Returns true on success, false on error. + * Notes: + * - If the file was previously open then it will close it and re-opens the + * file. + * - Returns false if "theFilename" has not been set. + */ + virtual bool open(); + + /*! + * Closes "theFileStream". + */ + virtual void close(); + + /*! + * Calls protected methods scanForEdges, extractVertices, and + * writeVertices. Will error out if "theFilename" or "theAreaOfInterest + * has not been set or "theFilename" could not be opened. + */ + virtual bool execute(); + + virtual ossimObject* getObjectInterface() { return this; } + + virtual ossimListenerManager* getListenerManagerInterface() + { + return this; + } + + + virtual void setPercentComplete(double percentComplete) + { + ossimProcessInterface::setPercentComplete(percentComplete); + ossimProcessProgressEvent event(this, + percentComplete); + fireEvent(event); + } + + bool canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const + { + + return (object&& PTR_CAST(ossimImageSourceInterface, object)); + } + + vector<ossimIpt> getVertices() { return theVertice; } + +private: + /*! + * Walks each line from left and right side detecting first non null pixel. + * Returns true on success, false on error. + */ + bool scanForEdges(); + + /*! + * Extracts the vertices of the source. Uses "theLeftEdge" and + * "theRightEdge" data members. + * Returns true on success, false on error. + */ + bool extractVertices(); + + template<class T1> + void getMinAndIndex(T1* start, T1* end, + T1& minValue, ossim_int32& offsetFromStart); + template<class T2> + void getMaxAndIndex(T2* start, T2* end, + T2& maxValue, ossim_int32& offsetFromStart); + + /*! + * Writes the result to the output file (theFilename). + * Returns true on success, false on error. + */ + + + bool writeVertices(); + + ossimIrect theAreaOfInterest; + ossimFilename theFilename; + std::ofstream theFileStream; + vector<ossimIpt> theVertice; + ossim_int32* theLeftEdge; + ossim_int32* theRightEdge; + + //! Disallow copy constructor and operator= + ossimVertexExtractor(const ossimVertexExtractor&) {} + const ossimVertexExtractor& operator=(const ossimVertexExtractor& rhs) + {return rhs;} + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimIgenGenerator.cpp b/Utilities/OSSIM/ossim_core/imaging/ossimIgenGenerator.cpp new file mode 100644 index 0000000000..8fb88bec5f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimIgenGenerator.cpp @@ -0,0 +1,703 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimIgenGenerator.cpp,v 1.33 2005/05/09 12:39:38 dburken Exp $ +#include <imaging/ossimIgenGenerator.h> +#include <base/common/ossimKeywordNames.h> +#include <imaging/ossimImageSourceInterface.h> +#include <imaging/ossimImageChain.h> +#include <imaging/tile_sources/ossimGeoPolyCutter.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <base/factory/ossimObjectFactoryRegistry.h> +#include <base/data_types/datum/ossimDatum.h> +#include <base/misc/ossimUsgsQuad.h> + +void ossimIgenGenerator::generateSpecList(bool outputToFileFlag) +{ + if(theTilingFlag&& + (theTileSpacingUnits!=OSSIM_UNIT_UNKNOWN)&& + (!theTileSpacing.hasNans())) + { + generateTiledSpecList(outputToFileFlag); + } + else + { + generateNoTiledSpecList(outputToFileFlag); + } + +} + +void ossimIgenGenerator::getImageFilenamesFromSpecList(std::vector<ossimFilename>& filenameList) +{ + if(!theSpecList.size()) + { + generateSpecList(); + } + if(theSpecList.size()) + { + filenameList.clear(); + for(ossim_uint32 i = 0; i < theSpecList.size(); ++i) + { + const char* filename = theSpecList[i].find("object2.", ossimKeywordNames::FILENAME_KW); + + if(filename) + { + filenameList.push_back(ossimFilename(filename)); + } + else + { + filenameList.clear(); + return; + } + } + } + +} + +ossimGrect ossimIgenGenerator::getBoundingGround()const +{ + return ossimGrect(theOutputGeoPolygon[0], + theOutputGeoPolygon[1], + theOutputGeoPolygon[2], + theOutputGeoPolygon[3]); +} + +void ossimIgenGenerator::executeSpecList() +{ +} + +void ossimIgenGenerator::setInput(ossimConnectableObject* input) +{ + theSpecList.clear(); + generateInputKwl(input); + ossimImageSourceInterface* inputInterface = PTR_CAST(ossimImageSourceInterface, + input); + if(inputInterface) + { + theInputBoundingRect = inputInterface->getBoundingRect(); + } +} + + +void ossimIgenGenerator::generateChainForMultiInput(ossimConnectableObject* connectable) +{ + std::stack<ossimConnectableObject*> aStack; + + generateChainForMultiInputRecurse(aStack, connectable); + + ossim_int32 objectIndex = 1; + while(!aStack.empty()) + { + ossimConnectableObject* current = aStack.top(); + aStack.pop(); + ossimString prefix = ossimString("object") + ossimString::toString(objectIndex) + "."; + + current->saveState(theInputKwl, prefix.c_str()); + + ++objectIndex; + } + theInputKwl.add("type", + "ossimImageChain", + true); + +} + +void ossimIgenGenerator::generateChainForMultiInputRecurse(std::stack<ossimConnectableObject*>& aStack, + ossimConnectableObject* connectable) +{ + + + if(connectable) + { + aStack.push(connectable); + for(ossim_uint32 i = 0; i < connectable->getNumberOfInputs(); ++i) + { + generateChainForMultiInputRecurse(aStack, + connectable->getInput(i)); + } + } +} + + +ossimProjection* ossimIgenGenerator::createProductProjection()const +{ + return ossimProjectionFactoryRegistry::instance()->createProjection(theViewKwl); +} + +ossimObject* ossimIgenGenerator::createOutput()const +{ + return ossimObjectFactoryRegistry::instance()->createObject(theOutputKwl); +} + +ossimObject* ossimIgenGenerator::createInput()const +{ + return ossimObjectFactoryRegistry::instance()->createObject(theInputKwl); +} + +void ossimIgenGenerator::generateInputKwl(ossimConnectableObject* connectable) +{ + theInputKwl.clear(); + if(connectable) + { + // if it has at least one non null input + // then we must build a chain and save it out + if(connectable->getInput()) + { + generateChainForMultiInput(connectable); + } + else // it is a single input + { + connectable->saveState(theInputKwl); + } + } +} + +void ossimIgenGenerator::generateOutputKwl(ossimConnectableObject* connectable) +{ + theOutputKwl.clear(); + if(connectable) + { + connectable->saveState(theOutputKwl); + } +} + +void ossimIgenGenerator::generateViewKwl(ossimObject* view) +{ + theViewKwl.clear(); + if(view) + { + view->saveState(theViewKwl); + } +} + +void ossimIgenGenerator::setDefaultOutput() +{ + +} + +void ossimIgenGenerator::generateTiledSpecList(bool outputToFileFlag) +{ + theSpecList.clear(); + theSpecFileList.clear(); + ossimDpt spacing = theTileSpacing; + + switch(theTileSpacingUnits) + { + case OSSIM_MINUTES: + { + spacing.x /= 60; + spacing.y /= 60; + generateGeoTiledSpecList(spacing, outputToFileFlag); + break; + } + case OSSIM_SECONDS: + { + spacing.x /= 3600; + spacing.y /= 3600; + generateGeoTiledSpecList(spacing, outputToFileFlag); + break; + } + case OSSIM_DEGREES: + { + generateGeoTiledSpecList(spacing, outputToFileFlag); + break; + } + case OSSIM_PIXEL: + { + generatePixelTiledSpecList(outputToFileFlag); + break; + } + default: + break; + } +} + +void ossimIgenGenerator::generatePixelTiledSpecList(bool outputToFileFlag) +{ + ossimProjection* proj = createProductProjection(); + + if((!proj)||(theOutputGeoPolygon.size() != 4)) + { + return; + } + + ossimIrect inputRect = getInputBoundingRect(); + inputRect.stretchToTileBoundary(theTileSpacing); + ossimGeoPolygon tempPoly; + ossimObject* obj = createInput(); + ossimImageChain* chain = PTR_CAST(ossimImageChain, + obj); + ossimGeoPolyCutter* cutter = new ossimGeoPolyCutter; + chain->add(cutter); + + ossimKeywordlist kwl; + ossimFilename outfile = theOutputKwl.find(ossimKeywordNames::FILENAME_KW); + + if(outfile == "") + { + cerr << "Valid filename not given, returning!" << endl; + } + + kwl.add("object2.", theOutputKwl, true); + kwl.add("product.projection.",theViewKwl, true); + addPixelType(kwl, "product."); + ossimDpt p1; + ossimDpt p2; + ossimDpt p3; + ossimDpt p4; + + + proj->worldToLineSample(theOutputGeoPolygon[0], p1); + proj->worldToLineSample(theOutputGeoPolygon[1], p2); + proj->worldToLineSample(theOutputGeoPolygon[2], p3); + proj->worldToLineSample(theOutputGeoPolygon[3], p4); + + ossimIrect bounds(p1, p2, p3, p4); + if(inputRect.completely_within(bounds)) + { + inputRect = bounds; + } + + bounds.stretchToTileBoundary(theTileSpacing); + + ossim_sint32 i = 1; + for(ossim_sint32 ulY = bounds.ul().y; ulY < bounds.lr().y; ulY+=(ossim_sint32)theTileSpacing.y) + { + for(ossim_sint32 ulX = bounds.ul().x; ulX < bounds.lr().x; ulX+=(ossim_sint32)theTileSpacing.x) + { + ossimDrect rect(ulX, + ulY, + ulX + (theTileSpacing.x - 1), + ulY + (theTileSpacing.y - 1)); + ossimGpt gpt1; + ossimGpt gpt2; + ossimGpt gpt3; + ossimGpt gpt4; + + proj->lineSampleToWorld(rect.ul(), gpt1); + proj->lineSampleToWorld(rect.ur(), gpt2); + proj->lineSampleToWorld(rect.lr(), gpt3); + proj->lineSampleToWorld(rect.ll(), gpt4); + + tempPoly.clear(); + tempPoly.addPoint(gpt1); + tempPoly.addPoint(gpt2); + tempPoly.addPoint(gpt3); + tempPoly.addPoint(gpt4); + addPadding(tempPoly, tempPoly); + cutter->setPolygon(tempPoly); + chain->saveState(kwl, "object1."); + + ossimFilename specName(theSpecFileLocation); + specName = specName.dirCat(ossimFilename("igen" + ossimString::toString(i) + ".spec")); + ossimFilename tilename = outfile.path(); + if(theTileNamingConvention == "id") + { + int tileId = getTileId(inputRect, ossimDpt(ulX+theTileSpacing.x/2, ulY+theTileSpacing.y/2), theTileSpacing); + tilename = tilename.dirCat(ossimFilename(outfile.fileNoExtension() + "_" + + ossimString::toString(tileId))); + tilename.setExtension(outfile.ext()); + } + + kwl.add("object2.", + ossimKeywordNames::FILENAME_KW, + tilename, + true); + kwl.add("object2.input_connection1", + kwl.find("object1.id"), + true); + theSpecFileList.push_back(specName); + if(outputToFileFlag) + { + kwl.write(specName.c_str()); + } + else + { + theSpecList.push_back(kwl); + } + i++; + } + } + if(proj) + { + delete proj; + proj = NULL; + } + +} + +void ossimIgenGenerator::generateGeoTiledSpecList(const ossimDpt& spacing, bool outputToFileFlag) +{ + ossimProjection* proj = createProductProjection(); + if((proj)&&(theOutputGeoPolygon.size() == 4)) + { + ossimDrect rect; + + ossimIrect inputRect = getInputBoundingRect(); + ossimGpt gpt1; + ossimGpt gpt2; + ossimGpt gpt3; + ossimGpt gpt4; + proj->lineSampleToWorld(inputRect.ul(), gpt1); + proj->lineSampleToWorld(inputRect.ur(), gpt2); + proj->lineSampleToWorld(inputRect.lr(), gpt3); + proj->lineSampleToWorld(inputRect.ll(), gpt4); + + ossimDrect inputGroundRect(gpt1, + gpt2, + gpt3, + gpt4, + OSSIM_RIGHT_HANDED); + + rect = ossimDrect(theOutputGeoPolygon[0], + theOutputGeoPolygon[1], + theOutputGeoPolygon[2], + theOutputGeoPolygon[3], + OSSIM_RIGHT_HANDED); + + rect.stretchToTileBoundary(spacing); + inputGroundRect.stretchToTileBoundary(spacing); + double ulLat = rect.ul().lat; + double ulLon = rect.ul().lon; + ossimGeoPolygon tempPoly; + ossimObject* obj = createInput(); + ossimImageChain* chain = PTR_CAST(ossimImageChain, + obj); + ossimGeoPolyCutter* cutter = new ossimGeoPolyCutter; + chain->add(cutter); + + ossimKeywordlist kwl; + ossimFilename outfile = theOutputKwl.find(ossimKeywordNames::FILENAME_KW); + + if(outfile == "") + { + cerr << "Valid filename not given, returning!" << endl; + } + + kwl.add("object2.", theOutputKwl, true); + kwl.add("object2.input_connection1", + kwl.find("object1.id"), + true); + kwl.add("product.projection.",theViewKwl, true); + addPixelType(kwl, "product."); + int i = 1; + int row = 0; + int col = 0; + // int tileId = 0; + while(ulLat > rect.ll().lat) + { + ulLon = rect.ul().lon; + col = 0; + while(ulLon < rect.ur().lon) + { + tempPoly.clear(); + tempPoly.addPoint(ulLat, ulLon, OSSIM_DBL_NAN, theOutputGeoPolygon[0].datum()); + tempPoly.addPoint(ulLat, ulLon+spacing.lon, OSSIM_DBL_NAN, theOutputGeoPolygon[0].datum()); + tempPoly.addPoint(ulLat-spacing.lat, ulLon+spacing.lon, OSSIM_DBL_NAN, theOutputGeoPolygon[0].datum()); + tempPoly.addPoint(ulLat-spacing.lat, ulLon, OSSIM_DBL_NAN, theOutputGeoPolygon[0].datum()); + + addPadding(tempPoly, tempPoly); + cutter->setPolygon(tempPoly); + chain->saveState(kwl, "object1."); + + ossimFilename specName(theSpecFileLocation); + specName = specName.dirCat(ossimFilename("igen" + ossimString::toString(i) + ".spec")); + ossimFilename tilename = outfile.path(); + if(theTileNamingConvention == "id") + { + int tileId = getTileId(inputGroundRect, ossimDpt(ulLon, ulLat), spacing); + tilename = tilename.dirCat(ossimFilename(outfile.fileNoExtension() + "_" + + ossimString::toString(tileId))); + tilename.setExtension(outfile.ext()); + } + else + { + ossimUsgsQuad quad(ossimGpt(ulLat - (spacing.x), ulLon+(spacing.x), 0.0)); + if(spacing.x == 7.5/60.0) + { + tilename = tilename.dirCat(ossimFilename(quad.quarterQuadName().downcase().trim())); + } + else + { + tilename = tilename.dirCat(ossimFilename(quad.quarterQuadSegName().downcase().trim())); + } + + tilename.setExtension(outfile.ext()); + } + + kwl.add("object2.", + ossimKeywordNames::FILENAME_KW, + tilename, + true); + kwl.add("object2.input_connection1", + kwl.find("object1.id"), + true); + theSpecFileList.push_back(specName); + if(outputToFileFlag) + { + kwl.write(specName.c_str()); + } + else + { + theSpecList.push_back(kwl); + } + ulLon += spacing.lon; + ++i; + ++col; + } + ++row; + ulLat -= spacing.lat; + } + + if(proj) + { + delete proj; + proj = NULL; + } + } +} + + +void ossimIgenGenerator::generateNoTiledSpecList(bool outputToFileFlag) +{ + theSpecList.clear(); + theSpecFileList.clear(); + + if(theViewKwl.getSize()&& + theInputKwl.getSize()&& + theOutputKwl.getSize()) + { + ossimKeywordlist kwl; + long id = 0; + if(theOutputGeoPolygon.size()) + { + ossimObject* obj = createInput(); + ossimImageChain* chain = PTR_CAST(ossimImageChain, + obj); + if(chain) + { + ossimGeoPolyCutter* cutter = new ossimGeoPolyCutter; + + cutter->setPolygon(theOutputGeoPolygon); + + chain->add(cutter); + chain->saveState(kwl, "object1."); + id = chain->getId().getId(); + } + else + { + kwl.add("object1.",theInputKwl, true); + } + + if(obj) + { + delete obj; + } + } + else + { + kwl.add("object1.",theInputKwl, true); + } + kwl.add("object2.", theOutputKwl, true); + kwl.add("object2.input_connection1", + kwl.find("object1.id"), + true); + kwl.add("product.projection.",theViewKwl, true); + addPixelType(kwl, "product."); + + ossimFilename specName(theSpecFileLocation + + "/"+ + "igen1.spec"); + + theSpecFileList.push_back(specName); + if(outputToFileFlag) + { + kwl.write(specName.c_str()); + } + else + { + theSpecList.push_back(kwl); + } + + kwl.clear(); + } +} + +int ossimIgenGenerator::getTileId(const ossimDrect& rect, + const ossimDpt& currentPt, + const ossimDpt& spacing)const +{ + ossimDpt ul(rect.ul()); + + double relY = fabs(ul.y - currentPt.y); + double relX = fabs(ul.x - currentPt.x); + + + ossim_int32 spacingY = (ossim_int32)(relY/spacing.y); + ossim_int32 spacingX = (ossim_int32)(relX/spacing.x); + ossim_int32 maxHorizontalTiles = (ossim_int32)( (rect.width()-1)/spacing.x); + + return spacingY*maxHorizontalTiles + spacingX; +} + + +ossimIrect ossimIgenGenerator::getInputBoundingRect()const +{ + ossimObject* obj = createInput(); + ossimImageSourceInterface* inter = PTR_CAST(ossimImageSourceInterface, obj); + ossimIrect result; + + result.makeNan(); + if(inter) + { + result = inter->getBoundingRect(); + } + if(obj) + { + delete obj; + } + return result; +} + +void ossimIgenGenerator::addPadding(ossimGeoPolygon& output, + const ossimGeoPolygon& input)const +{ + output = input; + switch(theTilePaddingUnits) + { + case OSSIM_PIXEL: + { + ossimProjection* proj = createProductProjection(); + if(proj) + { + ossimDpt ul; + ossimDpt ur; + ossimDpt lr; + ossimDpt ll; + + if(input.getOrdering() == OSSIM_CLOCKWISE_ORDER) + { + proj->worldToLineSample(input[0], ul); + proj->worldToLineSample(input[1], ur); + proj->worldToLineSample(input[2], lr); + proj->worldToLineSample(input[3], ll); + } + else + { + proj->worldToLineSample(input[0], ul); + proj->worldToLineSample(input[1], ll); + proj->worldToLineSample(input[2], lr); + proj->worldToLineSample(input[3], ur); + + } + + ul -= theTilePadding; + ur += ossimDpt(theTilePadding.x, + -theTilePadding.y); + lr += theTilePadding; + ll += ossimDpt(-theTilePadding.x, + theTilePadding.y); + + proj->lineSampleToWorld(ul, output[0]); + proj->lineSampleToWorld(ur, output[1]); + proj->lineSampleToWorld(lr, output[2]); + proj->lineSampleToWorld(ll, output[3]); + + output.setOrdering(OSSIM_CLOCKWISE_ORDER); + + delete proj; + } + break; + } + case OSSIM_DEGREES: + case OSSIM_MINUTES: + case OSSIM_SECONDS: + { + ossimGpt ul; + ossimGpt ur; + ossimGpt lr; + ossimGpt ll; + ossimDpt spacing = theTilePadding; + + if(theTilePaddingUnits==OSSIM_MINUTES) + { + spacing.x /= 60; + spacing.y /= 60; + } + else if(theTilePaddingUnits==OSSIM_MINUTES) + { + spacing.x /= 3600; + spacing.y /= 3600; + } + + if(input.getOrdering() == OSSIM_CLOCKWISE_ORDER) + { + ul = input[0]; + ur = input[1]; + lr = input[2]; + ll = input[3]; + } + else + { + ul = input[0]; + ll = input[1]; + lr = input[2]; + ur = input[3]; + } + ul.lat += spacing.lat; + ul.lon -= spacing.lon; + ur.lat += spacing.lat; + ur.lon += spacing.lon; + lr.lat -= spacing.lat; + lr.lon += spacing.lon; + ll.lat -= spacing.lat; + ll.lon -= spacing.lon; + + output[0] = ul; + output[1] = ur; + output[2] = lr; + output[3] = ll; + output.setOrdering(OSSIM_CLOCKWISE_ORDER); + + break; + } + case OSSIM_METERS: + { + break; + } + default: + break; + } +} + +void ossimIgenGenerator::addPixelType(ossimKeywordlist& kwl, const char* prefix) +{ + if(thePixelType == OSSIM_PIXEL_IS_POINT) + { + kwl.add(prefix, + ossimKeywordNames::PIXEL_TYPE_KW, + "PIXEL_IS_POINT", + true); + } + else + { + kwl.add(prefix, + ossimKeywordNames::PIXEL_TYPE_KW, + "PIXEL_IS_AREA", + true); + } +} + +void ossimIgenGenerator::setOutput(const ossimKeywordlist& kwl) +{ + theOutputKwl.clear(); + + theOutputKwl = kwl; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimIgenGenerator.h b/Utilities/OSSIM/ossim_core/imaging/ossimIgenGenerator.h new file mode 100644 index 0000000000..182c17dc98 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimIgenGenerator.h @@ -0,0 +1,319 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimIgenGenerator.h,v 1.23 2003/09/17 20:42:57 dburken Exp $ +#ifndef ossimIgenGenerator_HEADER +#define ossimIgenGenerator_HEADER +#include <stack> + +#include "base/common/ossimConstants.h" +#include "base/data_types/ossimKeywordlist.h" +#include "base/data_types/ossimFilename.h" +#include "base/data_types/ossimGrect.h" +#include "base/data_types/ossimGeoPolygon.h" +#include "ossimImageSource.h" +#include "projections/ossimProjection.h" +#include "imaging/formats/ossimImageFileWriter.h" + +class OSSIMDLLEXPORT ossimIgenGenerator +{ +public: + ossimIgenGenerator(ossimConnectableObject* input=NULL, + ossimConnectableObject* output=NULL, + ossimObject* view=NULL) + :thePixelType(OSSIM_PIXEL_IS_POINT), + theTilingFlag(false), + theTileSpacing(7.5, 7.5), + theTileSpacingUnits(OSSIM_MINUTES), + theTilePadding(0,0), + theTilePaddingUnits(OSSIM_PIXEL), + theNamingConvention("DEFAULT"), + theSpecFileLocation(""), + theIgenExecutable("igen"), + theSpecFileIndex(0), + theSpecListIndex(0), + theTileNamingConvention("id") + { + theUpperLeftTileStart.makeNan(); + setInput(input); + setOutput(output); + setView(view); + theInputBoundingRect.makeNan(); + } + + ~ossimIgenGenerator() + { + } + void setOutput(ossimConnectableObject* output) + { + theSpecList.clear(); + generateOutputKwl(output); + } + + void setOutput(const ossimKeywordlist& kwl); + + void setInput(ossimConnectableObject* input); + + void setView(ossimObject* view) + { + generateViewKwl(view); + } + + void generateSpecList(bool outputToFileFlag = false); + void getImageFilenamesFromSpecList(std::vector<ossimFilename>& filenameList); + ossimGrect getBoundingGround()const; + + void executeSpecList(); + + void setIteratorsToStart() + { + theSpecFileIndex = 0; + theSpecListIndex = 0; + } + bool nextSpecFile(ossimFilename& specFile) + { + if(theSpecFileIndex >= theSpecFileList.size()) + { + return false; + } + specFile = theSpecFileList[theSpecFileIndex]; + ++theSpecFileIndex; + return true; + } + void getSpecs(vector<ossimKeywordlist>& specList)const + { + specList = theSpecList; + } + + ossim_uint32 getNumberOfSpecFiles()const + { + return theSpecFileList.size(); + } + + ossimFilename getSpecFilename(ossim_uint32 specFileIndex = 0)const + { + if(specFileIndex < theSpecFileList.size()) + { + return theSpecFileList[specFileIndex]; + } + + return ossimFilename(""); + } + ossimFilename buildExe(ossim_uint32 i = 0)const + { + ossimFilename igenExe = getIgenExecutable(); + ossimFilename specFile = getSpecFilename(i); + + return ossimFilename( igenExe + " " + specFile); + } + + void getSpec(ossimKeywordlist& kwl, + ossim_uint32 specIndex=0) + { + kwl.clear(); + + if(specIndex < theSpecList.size()) + { + kwl = theSpecList[specIndex]; + } + } + void getInput(ossimKeywordlist& kwl, + const char* prefix=NULL)const + { + kwl.add(prefix, + theInputKwl, + true); + } + void getOutput(ossimKeywordlist& kwl, + const char* prefix=NULL)const + { + kwl.add(prefix, + theOutputKwl, + true); + } + + void getView(ossimKeywordlist& kwl, + const char* prefix=NULL)const + { + kwl.add(prefix, + theViewKwl, + true); + } + + void setView(ossimKeywordlist& kwl, + const char* prefix = NULL) + { + theViewKwl.clear(); + theViewKwl.add(prefix, + kwl, + true); + } + void setOutput(ossimKeywordlist& kwl, + const char* prefix = NULL) + { + theOutputKwl.clear(); + theOutputKwl.add(prefix, + kwl, + true); + } + void setSpecFileLocation(const ossimFilename& filename) + { + theSpecFileLocation = filename; + } + const ossimFilename& getSpecFileLocation()const + { + return theSpecFileLocation; + } + void setIgenExecutable(const ossimFilename& igenExecutable) + { + theIgenExecutable = igenExecutable; + } + const ossimFilename& getIgenExecutable()const + { + return theIgenExecutable; + } + void setOutputPolygon(const ossimGeoPolygon& poly) + { + theOutputGeoPolygon = poly; + } + void setPixelType(ossimPixelType pixelType) + { + thePixelType = pixelType; + } + void getOutputGeoPolygon(ossimGeoPolygon& poly)const + { + poly = theOutputGeoPolygon; + } + const ossimGeoPolygon& getOutputGeoPolygon()const + { + return theOutputGeoPolygon; + } + void setTilingFlag(bool flag) + { + theTilingFlag = flag; + } + void setTileSpacing(const ossimDpt& spacing) + { + theTileSpacing = spacing; + } + void setTilePadding(const ossimDpt& padding) + { + theTilePadding = padding; + } + void setTileSpacingUnits(ossimUnitType unitType) + { + theTileSpacingUnits = unitType; + } + void setTilePaddingUnits(ossimUnitType unitType) + { + theTilePaddingUnits = unitType; + } + bool getTilingFlag()const + { + return theTilingFlag; + } + const ossimDpt& getTileSpacing()const + { + return theTileSpacing; + } + const ossimDpt& getTilePadding()const + { + return theTilePadding; + } + ossimUnitType getTileSpacingUnits()const + { + return theTileSpacingUnits; + } + ossimUnitType getTilePaddingUnits()const + { + return theTilePaddingUnits; + } + ossimPixelType getPixelType()const + { + return thePixelType; + } + /*! + * Tile naming convention is a string that can be "id" or "usgs". + * this is used if tiling is enabled. If id is used it will use the filename + * as the prefix and then add to it the id's. If usgs is used it will name + * it based on the USGS name. + */ + void setTileNamingConvention(const ossimString& namingConvention) + { + theTileNamingConvention = namingConvention; + theTileNamingConvention = theTileNamingConvention.downcase(); + + } + const ossimString& getTileNamingConvention()const + { + return theTileNamingConvention; + } + ossimIrect getInputBoundingRect()const; + + ossimProjection* createProductProjection()const; + ossimObject* createOutput()const; + ossimObject* createInput()const; + +protected: + ossimKeywordlist theInputKwl; + ossimKeywordlist theOutputKwl; + ossimKeywordlist theViewKwl; + ossimPixelType thePixelType; + bool theTilingFlag; + ossimDpt theUpperLeftTileStart; + ossimDpt theTileSpacing; + ossimUnitType theTileSpacingUnits; + ossimDpt theTilePadding; + ossimUnitType theTilePaddingUnits; + ossimString theNamingConvention; + ossimFilename theSpecFileLocation; + ossimFilename theIgenExecutable; + ossim_uint32 theSpecFileIndex; + ossim_uint32 theSpecListIndex; + ossimIrect theInputBoundingRect; + ossimGeoPolygon theOutputGeoPolygon; + ossimString theTileNamingConvention; + + vector<ossimKeywordlist> theSpecList; + vector<ossimFilename> theSpecFileList; + + void generateInputKwl(ossimConnectableObject* connectable); + void generateOutputKwl(ossimConnectableObject* connectable); + void generateViewKwl(ossimObject* view); + void setDefaultOutput(); + void generateTiledSpecList(bool outputToFileFlag); + void generateGeoTiledSpecList(const ossimDpt& spacing, bool outputToFileFlag); + void generatePixelTiledSpecList(bool outputToFileFlag); + void generateNoTiledSpecList(bool outputToFileFlag); + + void generateChainForMultiInput(ossimConnectableObject* connectable); + void generateChainForMultiInputRecurse(std::stack<ossimConnectableObject*>& aStack, + ossimConnectableObject* connectable); + + int getTileId(const ossimDrect& rect, + const ossimDpt& currentPt, + const ossimDpt& spacing)const; + void addPadding(ossimGeoPolygon& output, + const ossimGeoPolygon& input)const; + void addPixelType(ossimKeywordlist& kwl, const char* prefix="product."); +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimImageChain.cpp b/Utilities/OSSIM/ossim_core/imaging/ossimImageChain.cpp new file mode 100644 index 0000000000..a87661c8bc --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimImageChain.cpp @@ -0,0 +1,1809 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimImageChain.cpp,v 1.109 2005/11/22 19:46:46 dburken Exp $ +#include <algorithm> +#include <iostream> +#include <iterator> + +#include <imaging/ossimImageChain.h> +#include <base/common/ossimCommon.h> +#include <base/context/ossimNotifyContext.h> +#include <imaging/ossimImageData.h> +#include <base/factory/ossimObjectFactoryRegistry.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/common/ossimTrace.h> +#include <base/common/events/ossimEventIds.h> +#include <base/common/events/ossimObjectEvents.h> +#include <base/common/ossimIdManager.h> + +static ossimTrace traceDebug("ossimImageChain"); + + +RTTI_DEF3(ossimImageChain, "ossimImageChain", ossimImageSource, + ossimConnectableObjectListener, ossimConnectableContainerInterface); + +class ossimImageChainChildListener : public ossimConnectableObjectListener +{ +public: + ossimImageChainChildListener(ossimImageChain* owner) + :theChain(owner) + { + } + virtual void propertyEvent(ossimPropertyEvent& event); + + ossimImageChain* theChain; +}; + +void ossimImageChainChildListener::propertyEvent(ossimPropertyEvent& event) +{ + ossimConnectableObject* obj = PTR_CAST(ossimConnectableObject, + event.getObject()); + + // if it originated from within my chain then propagate up to parent + // only if I have no outputs + // + if(obj) + { + if(!theChain->findObject(PTR_CAST(ossimConnectableObject,event.getObject()))) + { + ossimConnectableObject* interface = theChain->findObject(obj->getId(), false); + + if(interface) + { + ossimConnectableObject* parent = PTR_CAST(ossimConnectableObject, + theChain->getOwner()); + if(parent&& + !theChain->getNumberOfOutputs()) + { + parent->propagateEventToOutputs(event); + } + } + } + else + { + if(!theChain->thePropagateEventFlag) + { + theChain->propagateEventToOutputs(event); + } + } + } +} + +ossimImageChain::ossimImageChain() + :ossimImageSource(), + ossimConnectableContainerInterface((ossimObject*)NULL), + theBlankTile(NULL), + theLoadStateFlag(false) +{ + ossimConnectableContainerInterface::theBaseObject = this; + thePropagateEventFlag = false; + addListener((ossimConnectableObjectListener*)this); + theChildListener = new ossimImageChainChildListener(this); +} + +ossimImageChain::~ossimImageChain() +{ + removeListener((ossimConnectableObjectListener*)this); + deleteList(); + + if(theChildListener) + { + delete theChildListener; + theChildListener = NULL; + } +} + +bool ossimImageChain::addFirst(ossimConnectableObject* obj) +{ + ossimConnectableObject* rightOfThisObj = + (ossimConnectableObject*)getFirstObject(); + + return insertRight(obj, rightOfThisObj); +} + +bool ossimImageChain::addLast(ossimConnectableObject* obj) +{ + if(theImageChainList.size() > 0) + { + ossimConnectableObject* lastSource = theImageChainList[ theImageChainList.size() -1]; + if(PTR_CAST(ossimImageSourceInterface, obj)&&lastSource) + { + obj->disconnect(); + vector<ossimConnectableObject*> tempIn = getInputList(); + lastSource->disconnectAllInputs(); + lastSource->connectMyInputTo(obj); + obj->changeOwner(this); + obj->connectInputList(tempIn); + + tempIn = obj->getInputList(); + theInputListIsFixedFlag = obj->getInputListIsFixedFlag(); + setNumberOfInputs(obj->getNumberOfInputs()); + theImageChainList.push_back(obj); + + obj->addListener((ossimConnectableObjectListener*)this); + return true; + } + } + else + { + return add(obj); + } + + return false;; +} + +ossimImageSourceInterface* ossimImageChain::getFirstSource() +{ + if(theImageChainList.size()>0) + { + return PTR_CAST(ossimImageSourceInterface, + theImageChainList[0]); + } + + return NULL; +} + +ossimObject* ossimImageChain::getFirstObject() +{ + if(theImageChainList.size()>0) + { + return PTR_CAST(ossimObject, + theImageChainList[0]); + } + + return NULL; +} + +ossimImageSourceInterface* ossimImageChain::getLastSource() +{ + if(theImageChainList.size()>0) + { + return PTR_CAST(ossimImageSourceInterface, + *(theImageChainList.end()-1)); + } + + return NULL; +} + +ossimObject* ossimImageChain::getLastObject() +{ + if(theImageChainList.size()>0) + { + return PTR_CAST(ossimObject, + *(theImageChainList.end()-1)); + } + + return NULL; +} + +ossimConnectableObject* ossimImageChain::findObject(const ossimId& id, + bool recurse) +{ + vector<ossimConnectableObject*>::iterator current = theImageChainList.begin(); + + while(current != theImageChainList.end()) + { + if((*current)) + { + if(id == (*current)->getId()) + { + return (*current); + } + } + + ++current; + } + + current = theImageChainList.begin(); + + while(current != theImageChainList.end()) + { + ossimConnectableContainerInterface* child=PTR_CAST(ossimConnectableContainerInterface, + (*current)); + + if(child) + { + ossimConnectableObject* object = child->findObject(id, true); + + if(object) return object; + } + ++current; + } + + return NULL; +} + +ossimConnectableObject* ossimImageChain::findObject(const ossimConnectableObject* obj, + bool recurse) +{ + vector<ossimConnectableObject*>::iterator current = theImageChainList.begin(); + + while(current != theImageChainList.end()) + { + if(*current) + { + if(obj == (*current)) + { + return (*current); + } + } + + ++current; + } + + current = theImageChainList.begin(); + + while(current != theImageChainList.end()) + { + ossimConnectableContainerInterface* child=PTR_CAST(ossimConnectableContainerInterface, (*current)); + + if(child) + { + ossimConnectableObject* object = child->findObject(obj, true); + + if(object) return object; + } + ++current; + } + + return NULL; +} + +// ossimImageSourceInterface* ossimImageChain::findSource(const ossimId& id) +// { +// ossimImageSourceInterface* result = NULL; +// for(unsigned long index = 0; index < theImageChainList.size();++index) +// { +// ossimConnectableObject* obj = PTR_CAST(ossimConnectableObject, theImageChainList[index]); +// if(obj) +// { +// if(id == obj->getId()) +// { +// return PTR_CAST(ossimImageSourceInterface, +// theImageChainList[index]; +// } +// } +// } +// // now lets search children of type ossimImageChain +// for(unsigned long index = 0; index < theImageChainList.size();++index) +// { +// ossimImageChain* child=PTR_CAST(ossimImageChain, theImageChainList[index]->getObject()); +// if(child) +// { +// result = child->findSource(id); +// if(result) +// { +// return result; +// } +// } +// } + +// return result; +// } + +// ossimImageSourceInterface* ossimImageChain::findFirstSourceOfType(const RTTItypeid& typeInfo) +// { +// ossimImageSourceInterface* result = NULL; +// long index = 0; + +// for(index = 0; index < (long)theImageChainList.size();++index) +// { +// if(typeInfo.can_cast(TYPE_INFO(theImageChainList[index]))) +// { +// return PTR_CAST(ossimImageSourceInterface, +// theImageChainList[index]); +// } +// } + +// // if still not found then search children. It will +// // see if one of its children is another container of +// // type ossimImageChain. If so, then it will call +// // its method. +// if(!result) +// { +// for(index = 0; index < (long)theImageChainList.size();++index) +// { +// ossimImageChain* child=PTR_CAST(ossimImageChain, +// theImageChainList[index]); + +// if(child) +// { +// result = child->findFirstSourceOfType(typeInfo); +// if(result) +// { +// return result; +// } +// } +// } +// } + +// return result; +// } + +ossimConnectableObject* ossimImageChain::findFirstObjectOfType(const RTTItypeid& typeInfo, + bool recurse) +{ + vector<ossimConnectableObject*>::iterator current = theImageChainList.begin(); + + while(current != theImageChainList.end()) + { + if((*current)&& + (*current)->canCastTo(typeInfo)) + { + return (*current); + } + ++current; + } + + if(recurse) + { + current = theImageChainList.begin(); + while(current != theImageChainList.end()) + { + ossimConnectableContainerInterface* child=PTR_CAST(ossimConnectableContainerInterface, (*current)); + + if(child) + { + ossimConnectableObject* temp = child->findFirstObjectOfType(typeInfo, recurse); + if(temp) + { + return temp; + } + } + ++current; + } + } + + return (ossimConnectableObject*)NULL; +} + +ossimConnectableObject* ossimImageChain::findFirstObjectOfType(const ossimString& className, + bool recurse) +{ + vector<ossimConnectableObject*>::iterator current = theImageChainList.begin(); + + while(current != theImageChainList.end()) + { + if((*current)&& + (*current)->canCastTo(className) ) + { + return (*current); + } + ++current; + } + + if(recurse) + { + current = theImageChainList.begin(); + while(current != theImageChainList.end()) + { + ossimConnectableContainerInterface* child=PTR_CAST(ossimConnectableContainerInterface, *current); + + if(child) + { + ossimConnectableObject* temp = child->findFirstObjectOfType(className, recurse); + if(temp) + { + return temp; + } + } + ++current; + } + } + + return (ossimConnectableObject*)NULL; +} + +std::vector<ossimConnectableObject*> ossimImageChain::findAllObjectsOfType(const RTTItypeid& typeInfo, + bool recurse) +{ + std::vector<ossimConnectableObject*> result; + vector<ossimConnectableObject*>::iterator current = theImageChainList.begin(); + + while(current != theImageChainList.end()) + { + if((*current)&& + (*current)->canCastTo(typeInfo)) + { + vector<ossimConnectableObject*>::iterator iter = std::find(result.begin(), result.end(), *current); + if(iter == result.end()) + { + result.push_back(*current); + } + } + ++current; + } + + if(recurse) + { + current = theImageChainList.begin(); + while(current != theImageChainList.end()) + { + ossimConnectableContainerInterface* child=PTR_CAST(ossimConnectableContainerInterface, (*current)); + + if(child) + { + vector<ossimConnectableObject*> temp; + temp = child->findAllObjectsOfType(typeInfo, recurse); + for(long index=0; index < (long)temp.size();++index) + { + std::vector<ossimConnectableObject*>::iterator iter = std::find(result.begin(), result.end(), temp[index]); + if(iter == result.end()) + { + result.push_back(temp[index]); + } + } + } + ++current; + } + } + + return result; + +} + +std::vector<ossimConnectableObject*> ossimImageChain::findAllObjectsOfType(const ossimString& className, + bool recurse) +{ + std::vector<ossimConnectableObject*> result; + vector<ossimConnectableObject*>::iterator current = theImageChainList.begin(); + + while(current != theImageChainList.end()) + { + if((*current)&& + (*current)->canCastTo(className)) + { + std::vector<ossimConnectableObject*>::iterator iter = std::find(result.begin(), result.end(), (*current)); + if(iter == result.end()) + { + result.push_back(*current); + } + } + ++current; + } + + if(recurse) + { + current = theImageChainList.begin(); + while(current != theImageChainList.end()) + { + ossimConnectableContainerInterface* child=PTR_CAST(ossimConnectableContainerInterface, *current); + + if(child) + { + vector<ossimConnectableObject*> temp; + temp = child->findAllObjectsOfType(className, recurse); + for(long index=0; index < (long)temp.size();++index) + { + std::vector<ossimConnectableObject*>::iterator iter = std::find(result.begin(), result.end(), temp[index]); + if(iter == result.end()) + { + result.push_back(temp[index]); + } + } + } + ++current; + } + } + + return result; + +} + +// vector<ossimImageSourceInterface*> ossimImageChain::findAllSourcesOfType(const RTTItypeid& typeInfo) +// { +// vector<ossimImageSourceInterface*> result; +// long index = 0; + +// for(index = 0; index < (long)theImageChainList.size();++index) +// { +// if(typeInfo.can_cast(TYPE_INFO(theImageChainList[index]->getObject()))) +// { +// result.push_back( theImageChainList[index]); +// } +// } +// // go through other image chains. +// for(index = 0; index < (long)theImageChainList.size();++index) +// { +// ossimImageChain* child=PTR_CAST(ossimImageChain, theImageChainList[index]->getObject()); + +// if(child) +// { +// vector<ossimImageSourceInterface*> temp; + +// temp = child->findAllSourcesOfType(typeInfo); +// for(long index2=0; index2 < (long)temp.size();index2++) +// { +// result.push_back(temp[index2]); +// } +// } +// } + +// return result; +// } + +void ossimImageChain::makeUniqueIds() +{ + setId(ossimIdManager::instance()->generateId()); + for(long index = 0; index < (long)theImageChainList.size(); ++index) + { + ossimConnectableContainerInterface* container = PTR_CAST(ossimConnectableContainerInterface, + theImageChainList[index]); + if(container) + { + container->makeUniqueIds(); + } + else + { + if(theImageChainList[index]) + { + theImageChainList[index]->setId(ossimIdManager::instance()->generateId()); + } + } + } +} + +ossim_uint32 ossimImageChain::getNumberOfObjects(bool recurse)const +{ + ossim_uint32 result = theImageChainList.size(); + + if(recurse) + { + for(ossim_uint32 i = 0; i < theImageChainList.size(); ++i) + { + ossimConnectableContainerInterface* child=PTR_CAST(ossimConnectableContainerInterface, theImageChainList[i]); + if(child) + { + result += child->getNumberOfObjects(true); + } + } + } + + return result; +} + +ossim_uint32 ossimImageChain::getNumberOfSources() const +{ + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimImageChain::getNumberOfSources is deprecated!" + << "\nUse: ossimImageChain::getNumberOfObjects(false)" + << std::endl; + return getNumberOfObjects(false); +} + +bool ossimImageChain::addChild(ossimConnectableObject* object) +{ + return add(object); +} + +bool ossimImageChain::removeChild(ossimConnectableObject* object) +{ + vector<ossimConnectableObject*>::iterator current = theImageChainList.begin(); + ossim_uint32 i = 0; + while(current != theImageChainList.end()) + { + if(*current) + { + if(object == (*current)) + { + // Send an event to any listeners. + ossimContainerEvent event((ossimObject*)this, + (ossimObject*)object, + OSSIM_EVENT_REMOVE_OBJECT_ID); + fireEvent(event); + object->changeOwner(NULL); + + object->removeListener((ossimConnectableObjectListener*)this); + object->removeListener((ossimConnectableObjectListener*)theChildListener); + + std::vector<ossimConnectableObject*> input = object->getInputList(); + std::vector<ossimConnectableObject*> output = object->getOutputList(); + + // remeber the old size before removing + ossim_uint32 chainSize = theImageChainList.size(); + current = theImageChainList.erase(current); + // fix pointers + // + object->disconnect(); + + if(i == 0) // is it the first in the chain + { + theImageChainList[0]->removeListener(theChildListener); + theImageChainList[0]->addListener(theChildListener); + } + else if(i == (chainSize-1)) // is it the last + { + if(chainSize > 1) + { + ossimConnectableObject* tempObj = theImageChainList[theImageChainList.size()-1]; + if(tempObj) + { + tempObj->connectInputList(input); + } + } + } + else // must be an interior + { + ossim_uint32 inIndex = 0; + + for(inIndex = 0; inIndex < input.size(); ++inIndex) + { + if(input[inIndex]) + { + input[inIndex]->disconnectAllOutputs(); + input[inIndex]->connectOutputList(output); + } + } + } + + return true; + } + } + ++current; + ++i; + } + + current = theImageChainList.begin(); + + while(current != theImageChainList.end()) + { + ossimConnectableContainerInterface* child=PTR_CAST(ossimConnectableContainerInterface, *current); + + if(child) + { + bool result = child->removeChild(object); + if(result) + { + return result; + } + } + ++current; + } + + return false; +} + +ossimConnectableObject* ossimImageChain::removeChild(const ossimId& id) +{ + ossimConnectableObject* obj = findObject(id, true); + + removeChild(obj); + + return obj; +} + +void ossimImageChain::getChildren(vector<ossimConnectableObject*>& children, + bool immediateChildrenOnlyFlag) +{ + ossim_uint32 i = 0; + + vector<ossimConnectableObject*> temp; + for(i = 0; i < theImageChainList.size();++i) + { + temp.push_back(theImageChainList[i]); + } + + for(i = 0; i < temp.size();++i) + { + ossimConnectableContainerInterface* interface = PTR_CAST(ossimConnectableContainerInterface, + temp[i]); + if(immediateChildrenOnlyFlag) + { + children.push_back(temp[i]); + } + else if(!interface) + { + children.push_back(temp[i]); + } + } + + if(!immediateChildrenOnlyFlag) + { + for(i = 0; i < temp.size();++i) + { + ossimConnectableContainerInterface* interface = PTR_CAST(ossimConnectableContainerInterface, + temp[i]); + if(interface) + { + interface->getChildren(children, false); + } + } + } +} + +bool ossimImageChain::add(ossimConnectableObject* source) +{ + bool result = false; + if(PTR_CAST(ossimImageSourceInterface, source)) + { + source->changeOwner(this); + if(theImageChainList.size() > 0) + { + source->disconnectAllOutputs(); + theOutputListIsFixedFlag = source->getOutputListIsFixedFlag(); + theImageChainList[0]->removeListener(theChildListener); + theImageChainList.insert(theImageChainList.begin(), source); + theImageChainList[0]->addListener(theChildListener); + source->addListener((ossimConnectableObjectListener*)this); + theImageChainList[0]->connectMyInputTo(theImageChainList[1]); + result = true; + } + else + { + theInputObjectList = source->getInputList(); + theInputListIsFixedFlag = source->getInputListIsFixedFlag(); + + theOutputObjectList = source->getOutputList(); + theOutputListIsFixedFlag = source->getOutputListIsFixedFlag(); + + theImageChainList.push_back(source); + source->addListener((ossimConnectableObjectListener*)this); + theImageChainList[0]->addListener(theChildListener); + result = true; + } + } + + if (result && source) + { + ossimContainerEvent event(this, source, OSSIM_EVENT_ADD_OBJECT_ID); + fireEvent(event); + } + + return result; +} + +bool ossimImageChain::insertRight(ossimConnectableObject* newObj, + ossimConnectableObject* rightOfThisObj) +{ + if(!theImageChainList.size()) + { + return add(newObj); + } + + if(findObject(rightOfThisObj, false)) + { + vector<ossimConnectableObject*>::iterator iter = theImageChainList.begin(); + while(iter != theImageChainList.end()) + { + if( (*iter) == rightOfThisObj) + { + break; + } + ++iter; + } + if(rightOfThisObj == theImageChainList[0]) + { + return add(newObj); + } + else if(PTR_CAST(ossimImageSourceInterface, newObj)) + { + vector<ossimConnectableObject*> outputList = rightOfThisObj->getOutputList(); + rightOfThisObj->disconnectAllOutputs(); + + // Core dump fix. Connect input prior to outputs. (drb) + newObj->connectMyInputTo(rightOfThisObj); + newObj->connectOutputList(outputList); + newObj->changeOwner(this); + newObj->addListener((ossimConnectableObjectListener*)this); + theImageChainList.insert(iter, newObj); + if (newObj) + { + // Send event to any listeners. + ossimContainerEvent event(this, newObj, OSSIM_EVENT_ADD_OBJECT_ID); + fireEvent(event); + } + return true; + } + } + + return false; +} + +bool ossimImageChain::insertRight(ossimConnectableObject* newObj, + const ossimId& id) +{ + ossimConnectableObject* obj = findObject(id, false); + if(obj) + { + return insertRight(newObj, obj); + } + + return false; +} + +bool ossimImageChain::insertLeft(ossimConnectableObject* newObj, + ossimConnectableObject* leftOfThisObj) +{ + if(!theImageChainList.size()) + { + return add(newObj); + } + + if(findObject(leftOfThisObj, false)) + { + vector<ossimConnectableObject*>::iterator iter = theImageChainList.begin(); + + while(iter != theImageChainList.end()) + { + if( (*iter) == leftOfThisObj) + { + break; + } + ++iter; + } + if(leftOfThisObj==theImageChainList[theImageChainList.size()-1]) + { + return addLast(newObj); + } + else if(PTR_CAST(ossimImageSourceInterface, newObj)) + { + vector<ossimConnectableObject*> inputList = leftOfThisObj->getInputList(); + leftOfThisObj->disconnectAllInputs(); + newObj->connectInputList(inputList); + leftOfThisObj->connectMyInputTo(newObj); + newObj->changeOwner(this); + newObj->addListener((ossimConnectableObjectListener*)this); + theImageChainList.insert(iter+1, newObj); + if (newObj) + { + // Send an event to any listeners. + ossimContainerEvent event(this, newObj, OSSIM_EVENT_ADD_OBJECT_ID); + fireEvent(event); + } + return true; + } + } + + return false; +} + +bool ossimImageChain::insertLeft(ossimConnectableObject* newObj, + const ossimId& id) +{ + ossimConnectableObject* obj = findObject(id, false); + if(obj) + { + return insertLeft(newObj, obj); + } + + return false; +} + +ossimRefPtr<ossimImageData> ossimImageChain::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if((theImageChainList.size() > 0)&&(isSourceEnabled())) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + theImageChainList[0]); + + if(interface) + { + // make sure we initialize in reverse order. + // some source may depend on the initialization of + // its inputs + return interface->getTile(tileRect, resLevel); + } + + } + else + { + if(getInput(0)) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(interface) + { + return interface->getTile(tileRect, + resLevel); + } + } + } + + if(theBlankTile.get()) + { + theBlankTile->setOrigin(tileRect.ul()); + theBlankTile->setWidthHeight(tileRect.width(), + tileRect.height()); + } + + return theBlankTile; +} + +ossim_uint32 ossimImageChain::getNumberOfInputBands() const +{ + if((theImageChainList.size() > 0)&&(isSourceEnabled())) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + theImageChainList[0]); + if(interface) + { + return interface->getNumberOfOutputBands(); + } + } + else + { + if(getInput(0)) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(interface) + { + return interface->getNumberOfOutputBands(); + } + } + } + + return 0; +} + +double ossimImageChain::getNullPixelValue(ossim_uint32 band)const +{ + if((theImageChainList.size() > 0)&&(isSourceEnabled())) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + theImageChainList[0]); + if(interface) + { + return interface->getNullPixelValue(band); + } + } + else + { + if(getInput(0)) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(interface) + { + return interface->getNullPixelValue(band); + } + } + } + + return ossimGetDefaultNull(getOutputScalarType()); +} + +double ossimImageChain::getMinPixelValue(ossim_uint32 band)const +{ + if((theImageChainList.size() > 0)&&(isSourceEnabled())) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + theImageChainList[0]); + if(interface) + { + return interface->getMinPixelValue(band); + } + } + else + { + if(getInput(0)) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(interface) + { + return interface->getMinPixelValue(band); + } + } + } + + return ossimGetDefaultMin(getOutputScalarType()); +} + +double ossimImageChain::getMaxPixelValue(ossim_uint32 band)const +{ + if((theImageChainList.size() > 0)&&(isSourceEnabled())) + { + ossimImageSourceInterface* inter = PTR_CAST(ossimImageSourceInterface, + theImageChainList[0]); + if(inter) + { + return inter->getMaxPixelValue(band); + } + } + else + { + if(getInput(0)) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(interface) + { + return interface->getMaxPixelValue(band); + } + } + } + + return ossimGetDefaultMax(getOutputScalarType()); +} + +void ossimImageChain::getOutputBandList(std::vector<ossim_uint32>& bandList) const +{ + if((theImageChainList.size() > 0)&&(isSourceEnabled())) + { + ossimImageSourceInterface* inter = PTR_CAST(ossimImageSourceInterface, + theImageChainList[0]); + if(inter) + { + return inter->getOutputBandList(bandList); + } + } +} + +ossimScalarType ossimImageChain::getOutputScalarType() const +{ + if((theImageChainList.size() > 0)&&(isSourceEnabled())) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + theImageChainList[0]); + if(interface) + { + return interface->getOutputScalarType(); + } + } + else + { + if(getInput(0)) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(interface) + { + return interface->getOutputScalarType(); + } + } + } + + return OSSIM_SCALAR_UNKNOWN; +} + +ossim_uint32 ossimImageChain::getTileWidth()const +{ + if((theImageChainList.size() > 0)&&(isSourceEnabled())) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + theImageChainList[0]); + if(interface) + { + return interface->getTileWidth();; + } + } + else + { + if(getInput(0)) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(interface) + { + return interface->getTileWidth(); + } + } + } + + return 0; +} + +ossim_uint32 ossimImageChain::getTileHeight()const +{ + if((theImageChainList.size() > 0)&&(isSourceEnabled())) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + theImageChainList[0]); + if(interface) + { + return interface->getTileHeight(); + } + } + else + { + if(getInput(0)) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(interface) + { + return interface->getTileHeight(); + } + } + } + + return 0; +} + +ossimIrect ossimImageChain::getBoundingRect(ossim_uint32 resLevel)const +{ + if((theImageChainList.size() > 0)&&(isSourceEnabled())) + { + + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + theImageChainList[0]); + + if(interface) + { + return interface->getBoundingRect(resLevel); + } + } + else + { + if(getInput(0)) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(interface) + { + return interface->getBoundingRect(); + } + } + } + ossimDrect rect; + rect.makeNan(); + + return rect; + +} + +void ossimImageChain::getValidImageVertices(vector<ossimIpt>& validVertices, + ossimVertexOrdering ordering, + ossim_uint32 resLevel)const +{ + if((theImageChainList.size() > 0)&&(isSourceEnabled())) + { + ossimImageSourceInterface* interface =PTR_CAST(ossimImageSourceInterface, + theImageChainList[0]); + + if(interface) + { + interface->getValidImageVertices(validVertices, + ordering, + resLevel); + } + } + else + { + if(getInput(0)) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(interface) + { + interface->getValidImageVertices(validVertices, + ordering, + resLevel); + } + } + } +} + +bool ossimImageChain::getImageGeometry(ossimKeywordlist& kwl, + const char* prefix) +{ + if((theImageChainList.size() > 0)&&(isSourceEnabled())) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + theImageChainList[0]); + if(interface) + { + return interface->getImageGeometry(kwl, + prefix); + } + } + else + { + if(getInput(0)) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(interface) + { + return interface->getImageGeometry(kwl, + prefix); + } + } + + } + return false; +} + +void ossimImageChain::getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result) const +{ + if((theImageChainList.size() > 0)&&(isSourceEnabled())) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + theImageChainList[0]); + if(interface) + { + interface->getDecimationFactor(resLevel, + result); + return; + } + } + else + { + if(getInput(0)) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(interface) + { + interface->getDecimationFactor(resLevel, result); + return; + } + } + } + + result.makeNan(); +} + +void ossimImageChain::getDecimationFactors(vector<ossimDpt>& decimations) const +{ + if((theImageChainList.size() > 0)&&(isSourceEnabled())) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + theImageChainList[0]); + if(interface) + { + interface->getDecimationFactors(decimations); + } + } + else + { + if(getInput(0)) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(interface) + { + interface->getDecimationFactors(decimations); + return; + } + } + } +} + +ossim_uint32 ossimImageChain::getNumberOfDecimationLevels()const +{ + if((theImageChainList.size() > 0)&&(isSourceEnabled())) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + theImageChainList[0]); + + if(interface) + { + return interface->getNumberOfDecimationLevels(); + } + } + else + { + if(getInput(0)) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(interface) + { + return interface->getNumberOfDecimationLevels(); + } + } + } + + return 1; +} + +bool ossimImageChain::addAllSources(map<ossimId, vector<ossimId> >& idMapping, + const ossimKeywordlist& kwl, + const char* prefix) +{ + static const char* MODULE = "ossimImageChain::addAllSources"; + ossimString copyPrefix = prefix; + bool result = ossimImageSource::loadState(kwl, copyPrefix.c_str()); + + if(!result) + { + return result; + } + long index = 0; + +// ossimSource* source = NULL; + + vector<ossimId> inputConnectionIds; + ossimString regExpression = ossimString("^(") + copyPrefix + "object[0-9]+.)"; + vector<ossimString> keys = + kwl.getSubstringKeyList( regExpression ); + long numberOfSources = keys.size();//kwl.getNumberOfSubstringKeys(regExpression); + + int offset = (copyPrefix+"object").size(); + int idx = 0; + std::vector<int> theNumberList(numberOfSources); + for(idx = 0; idx < (int)theNumberList.size();++idx) + { + ossimString numberStr(keys[idx].begin() + offset, + keys[idx].end()); + theNumberList[idx] = numberStr.toInt(); + } + std::sort(theNumberList.begin(), theNumberList.end()); + for(idx=0;idx < (int)theNumberList.size();++idx) + { + ossimString newPrefix = copyPrefix; + newPrefix += ossimString("object"); + newPrefix += ossimString::toString(theNumberList[idx]); + newPrefix += ossimString("."); + + if(traceDebug()) + { + CLOG << "trying to create source with prefix: " << newPrefix + << std::endl; + } + ossimObject* object = ossimObjectFactoryRegistry::instance()->createObject(kwl, + newPrefix.c_str()); + ossimConnectableObject* source = PTR_CAST(ossimConnectableObject, object); + + if(source) + { + // we did find a source so include it in the count + if(traceDebug()) + { + CLOG << "Created source with prefix: " << newPrefix << std::endl; + } + if(PTR_CAST(ossimImageSourceInterface, source)) + { + ossimId id = source->getId(); + inputConnectionIds.clear(); + + findInputConnectionIds(inputConnectionIds, + kwl, + newPrefix); + if(inputConnectionIds.size() == 0) + { + // we will try to do a default connection + // + + if(theImageChainList.size()) + { + if(traceDebug()) + { + CLOG << "connecting " << source->getClassName() << " to " + << theImageChainList[0]->getClassName() << std::endl; + } + source->connectMyInputTo(0, theImageChainList[0]); + } + } + else + { + // we remember the connection id's so we can connect this later. + // this way we make sure all sources were actually + // allocated. + // + idMapping.insert(std::make_pair(id, inputConnectionIds)); + } + add(source); + } + else + { + delete source; + source = NULL; + } + } + else + { + delete object; + object = NULL; + source = NULL; + } + + ++index; + } + if(theImageChainList.size()) + { + ossimConnectableObject* obj = theImageChainList[(long)theImageChainList.size()-1]; + if(obj) + { + setNumberOfInputs(obj->getNumberOfInputs()); + } + } + + return result; +} + +void ossimImageChain::findInputConnectionIds(vector<ossimId>& result, + const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimString copyPrefix = prefix; + ossim_uint32 idx = 0; + + ossimString regExpression = ossimString("^") + ossimString(prefix) + "input_connection[0-9]+"; + vector<ossimString> keys = + kwl.getSubstringKeyList( regExpression ); + + ossim_int32 offset = (copyPrefix+"input_connection").size(); + ossim_uint32 numberOfKeys = keys.size(); + std::vector<int> theNumberList(numberOfKeys); + for(idx = 0; idx < theNumberList.size();++idx) + { + ossimString numberStr(keys[idx].begin() + offset, + keys[idx].end()); + theNumberList[idx] = numberStr.toInt(); + } + std::sort(theNumberList.begin(), theNumberList.end()); + copyPrefix += ossimString("input_connection"); + for(idx=0;idx < theNumberList.size();++idx) + { + const char* lookup = kwl.find(copyPrefix,ossimString::toString(theNumberList[idx])); + if(lookup) + { + long id = ossimString(lookup).toLong(); + result.push_back(ossimId(id)); + } + } +} + +bool ossimImageChain::connectAllSources(const map<ossimId, vector<ossimId> >& idMapping) +{ + if(idMapping.size()) + { + map<ossimId, vector<ossimId> >::const_iterator iter = idMapping.begin(); + + while(iter != idMapping.end()) + { + ossimConnectableObject* currentSource = findObject((*iter).first); + + if(currentSource) + { + long upperBound = (*iter).second.size(); + for(long index = 0; index < upperBound; ++index) + { + if((*iter).second[index].getId() > -1) + { + ossimConnectableObject* inputSource = PTR_CAST(ossimConnectableObject, findObject((*iter).second[index])); + currentSource->connectMyInputTo(index, inputSource); + + } + else + { + currentSource->disconnectMyInput((ossim_int32)index); + } + } + } + else + { + cerr << "Could not find " << (*iter).first << " for source: "; + return false; + } + ++iter; + } + } + + return true; +} + +bool ossimImageChain::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + bool result = true; + + result = ossimImageSource::saveState(kwl, prefix); + + if(!result) + { + return result; + } + long upper = theImageChainList.size(); + long counter = 1; + + // start with the tail and go to the head fo the list. + for(long index = upper - 1; ((index >= 0)&&result); --index, ++counter) + { + ossimString newPrefix = prefix; + + newPrefix += (ossimString("object") + + ossimString::toString(counter) + + ossimString(".")); + result = theImageChainList[index]->saveState(kwl, newPrefix.c_str()); + } + + return result; +} + +bool ossimImageChain::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + static const char* MODULE = "ossimImageChain::loadState(kwl, prefix)"; + deleteList(); + + ossimImageSource::loadState(kwl, prefix); + + + theLoadStateFlag = true; + bool result = true; + + map<ossimId, vector<ossimId> > idMapping; + result = addAllSources(idMapping, kwl, prefix); + if(!result) + { + CLOG << "problems adding sources" << std::endl; + } + result = connectAllSources(idMapping); + if(!result) + { + CLOG << "problems connecting sources" << std::endl; + } + + theLoadStateFlag = false; + return result; +} + + +void ossimImageChain::initialize() +{ + static const char* MODULE = "ossimImageChain::initialize()"; + if (traceDebug()) CLOG << " Entered..." << std::endl; + + long upper = theImageChainList.size(); + + for(long index = upper - 1; index >= 0; --index) + { + if(traceDebug()) + { + CLOG << "initilizing source: " + << theImageChainList[index]->getClassName() + << std::endl; + } + if(theImageChainList[index]) + { + ossimImageSourceInterface* interface = + PTR_CAST(ossimImageSourceInterface, theImageChainList[index]); + + if(interface) + { + // make sure we initialize in reverse order. + // some source may depend on the initialization of + // its inputs + interface->initialize(); + } + } + } + if (traceDebug()) CLOG << " Exited..." << std::endl; +} + +void ossimImageChain::enableSource() +{ + long upper = theImageChainList.size(); + + for(long index = upper - 1; index >= 0; --index) + { + // make sure we initialize in reverse order. + // some source may depend on the initialization of + // its inputs + ossimSource* source = PTR_CAST(ossimSource, theImageChainList[index]); + if(source) + { + source->enableSource(); + } + } + + theEnableFlag = true; +} + +void ossimImageChain::disableSource() +{ + long upper = theImageChainList.size(); + + for(long index = upper - 1; index >= 0; --index) + { + // make sure we initialize in reverse order. + // some source may depend on the initialization of + // its inputs + ossimSource* source = PTR_CAST(ossimSource, theImageChainList[index]); + if(source) + { + source->disableSource(); + } + } + + theEnableFlag = false; +} + + +vector<ossimConnectableObject*>& ossimImageChain::getChildren() +{ + return theImageChainList; +} + +bool ossimImageChain::deleteFirst() +{ + if (theImageChainList.size() == 0) return false; + + // Clear any listeners, memory. + ossim_uint32 index = 0; + theImageChainList[index]-> + removeListener((ossimConnectableObjectListener*)this); + theImageChainList[index]->removeListener(theChildListener); + theImageChainList[index]->changeOwner(NULL); + delete theImageChainList[index]; + + // Remove from the vector. + vector<ossimConnectableObject*>::iterator i = theImageChainList.begin(); + theImageChainList.erase(i); + return true; +} + +bool ossimImageChain::deleteLast() +{ + if (theImageChainList.size() == 0) return false; + + // Clear any listeners, memory. + ossim_uint32 index = theImageChainList.size() - 1; + theImageChainList[index]-> + removeListener((ossimConnectableObjectListener*)this); + theImageChainList[index]->removeListener(theChildListener); + theImageChainList[index]->changeOwner(NULL); + delete theImageChainList[index]; + + // Remove from the vector. + theImageChainList.pop_back(); + return true; +} + +void ossimImageChain::deleteList() +{ + long upper = theImageChainList.size(); + + + for(long index = 0; index < upper; ++index) + { + theImageChainList[index]->removeListener((ossimConnectableObjectListener*)this); + theImageChainList[index]->removeListener(theChildListener); + theImageChainList[index]->changeOwner(NULL); + delete theImageChainList[index]; + } + + theImageChainList.clear(); +} + +void ossimImageChain::disconnectInputEvent(ossimConnectionEvent& event) +{ + if(theImageChainList.size()) + { + if(event.getObject()==this) + { + if(theImageChainList[theImageChainList.size()-1]) + { + for(ossim_uint32 i = 0; i < event.getNumberOfOldObjects(); ++i) + { + theImageChainList[theImageChainList.size()-1]->disconnectMyInput(event.getOldObject(i)); + } + } + } + } +} + +void ossimImageChain::disconnectOutputEvent(ossimConnectionEvent& event) +{ +} + +void ossimImageChain::connectInputEvent(ossimConnectionEvent& event) +{ + if(theImageChainList.size()) + { + if(event.getObject()==this) + { + if(theImageChainList[theImageChainList.size()-1]) + { + for(ossim_uint32 i = 0; i < event.getNumberOfNewObjects(); ++i) + { + ossimConnectableObject* obj = event.getNewObject(i); + theImageChainList[theImageChainList.size()-1]->connectMyInputTo(findInputIndex(obj), + obj, + false); + } + } + } + else if(event.getObject() == theImageChainList[0]) + { + if(!theLoadStateFlag) + { +// theInputObjectList = theImageChainList[0]->getInputList(); + } + } + initialize(); + } +} + +void ossimImageChain::connectOutputEvent(ossimConnectionEvent& event) +{ +} + +// void ossimImageChain::propertyEvent(ossimPropertyEvent& event) +// { +// if(theImageChainList.size()) +// { +// ossimConnectableObject* obj = PTR_CAST(ossimConnectableObject, +// event.getObject()); + +// if(obj) +// { +// ossimImageSourceInterface* interface = findSource(obj->getId()); + +// if(interface) +// { +// ossimConnectableObject* obj = PTR_CAST(ossimConnectableObject, +// interface.getObject()); +// if(obj) +// { + +// } +// } +// } +// } +// } + +void ossimImageChain::objectDestructingEvent(ossimObjectDestructingEvent& event) +{ + if(!event.getObject()) return; + + if(theImageChainList.size()&&(event.getObject()!=this)) + { + removeChild(PTR_CAST(ossimConnectableObject, + event.getObject())); + } +} + +void ossimImageChain::propagateEventToOutputs(ossimEvent& event) +{ + if(thePropagateEventFlag) return; + + thePropagateEventFlag = true; + if(theImageChainList.size()) + { + if(theImageChainList[theImageChainList.size()-1]) + { + theImageChainList[theImageChainList.size()-1]->fireEvent(event); + theImageChainList[theImageChainList.size()-1]->propagateEventToOutputs(event); + } + } + ossimConnectableObject::propagateEventToOutputs(event); + thePropagateEventFlag = false; +} + +void ossimImageChain::propagateEventToInputs(ossimEvent& event) +{ + if(thePropagateEventFlag) return; + + thePropagateEventFlag = true; + if(theImageChainList.size()) + { + if(theImageChainList[0]) + { + theImageChainList[0]->fireEvent(event); + theImageChainList[0]->propagateEventToOutputs(event); + } + } + thePropagateEventFlag = false; +} + +ossimConnectableObject* ossimImageChain::operator[](ossim_uint32 index) +{ + return getConnectableObject(index); +} + +ossimConnectableObject* ossimImageChain::getConnectableObject( + ossim_uint32 index) +{ + if(theImageChainList.size() && (index < theImageChainList.size())) + { + return theImageChainList[index]; + } + + return (ossimConnectableObject*)NULL; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimImageChain.h b/Utilities/OSSIM/ossim_core/imaging/ossimImageChain.h new file mode 100644 index 0000000000..4d3859cc8f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimImageChain.h @@ -0,0 +1,358 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimImageChain.h,v 1.52 2005/11/22 19:45:06 dburken Exp $ +#ifndef ossimImageChain_HEADER +#define ossimImageChain_HEADER +#include <vector> +#include <map> +using namespace std; + +#include <imaging/ossimImageSource.h> +#include <base/common/events/ossimConnectableObjectListener.h> +#include <base/common/ossimId.h> +#include <base/common/ossimConnectableContainerInterface.h> + +class ossimImageChainChildListener; + +class OSSIMDLLEXPORT ossimImageChain : public ossimImageSource, + public ossimConnectableObjectListener, + public ossimConnectableContainerInterface +{ +public: + ossimImageChain(); + virtual ~ossimImageChain(); + + /** + * @param index Index of object to get. + * + * @see getNumberOfObjects(false) to get the number of objects inside + * the container. + * + * @return Container's object at that index or NULL if out of range. + */ + ossimConnectableObject* operator[](ossim_uint32 index); + + /** + * Same as operator[](ossim_uint32 i) + * + * @param index Index of object to get. + * + * @see getNumberOfObjects(false) to get the number of objects inside + * the container. + * + * @return Container's object at that index or NULL if out of range. + * + * @note This does not recurse into other containers. + */ + virtual ossimConnectableObject* getConnectableObject(ossim_uint32 index); + + /** + * Return the first source which is the one that first receives the + * getTile request + */ + virtual ossimImageSourceInterface* getFirstSource(); + virtual ossimObject* getFirstObject(); + + /** + * Return the last source which is the one that last receives the + * getTile request. + */ + virtual ossimImageSourceInterface* getLastSource(); + virtual ossimObject* getLastObject(); + + + /** + * Adds it to the start of the chain. This is the first one to receive + * the getTile request. This basically inserts it to the right of the + * right most filter. + * Returns true on success, false on error. + */ + bool addFirst(ossimConnectableObject* obj); + + /** + * Adds it to the end. this is the last one to receive the getTile + * request. This basically inserts it to the left of the left most filter. + * Returns true on success, false on error. + */ + bool addLast(ossimConnectableObject* obj); + + /** + * Deletes the first object. + * Note this is really most right of the chain. + * Returns true if deletion occurred, false if the chain is empty. + */ + bool deleteFirst(); + + /** + * Deletes the last object. + * Note this is really most left of the chain. + * Returns true if deletion occurred, false if the chain is empty. + */ + bool deleteLast(); + + /** + * + */ + bool insertRight(ossimConnectableObject* newObj, + ossimConnectableObject* rightOfThisObj); + + /** + * + */ + bool insertRight(ossimConnectableObject* newObj, + const ossimId& id); + + /** + * + */ + bool insertLeft(ossimConnectableObject* newObj, + const ossimId& id); + /** + * + */ + bool insertLeft(ossimConnectableObject* newObj, + ossimConnectableObject* leftOfThisObj); + + + /** + * Will return true or false if an image source was + * added to the chain. It will add and do a connection + * to the previous source automatically. This is a + * chain and the order of insertion matters. It adds it to the beginning + * of the list. The last one added is the first one to receive + * the getTile. Basically inserts to the right of the rightmost filter + * + */ + virtual bool add(ossimConnectableObject* source); + + /** + * Within the image chain will pass the head of the + * list. + */ + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + + /** + * this call is passed to the head of the list. + */ + virtual ossim_uint32 getNumberOfInputBands() const; + + /** + * This call is passed to the head of the list. + */ + virtual ossimScalarType getOutputScalarType() const; + + virtual double getNullPixelValue(ossim_uint32 band=0)const; + virtual double getMinPixelValue(ossim_uint32 band=0)const; + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + + virtual void getOutputBandList(std::vector<ossim_uint32>& bandList) const; + + /** + * This call is passed to the head of the list. + */ + virtual ossim_uint32 getTileWidth()const; + + /** + * This call is passed to the head of the list. + */ + virtual ossim_uint32 getTileHeight()const; + + /** + * Will pass this call to the head of the list. + */ + virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0)const; + virtual void getValidImageVertices(vector<ossimIpt>& validVertices, + ossimVertexOrdering ordering=OSSIM_CLOCKWISE_ORDER, + ossim_uint32 resLevel=0)const; + + virtual bool getImageGeometry(ossimKeywordlist& kwl, + const char* prefix=NULL); + + virtual void getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result) const; + virtual void getDecimationFactors(vector<ossimDpt>& decimations) const; + virtual ossim_uint32 getNumberOfDecimationLevels()const; + + /** + * Will save the state of the chain. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=NULL)const; + + /** + * Will load the state. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=NULL); + + virtual void initialize(); + virtual void enableSource(); + virtual void disableSource(); + vector<ossimConnectableObject*>& getChildren(); + + bool canConnectMyInputTo(ossim_int32 myInputIndex, + const ossimConnectableObject* object)const + { + if(theImageChainList.size()&& + theImageChainList[theImageChainList.size()-1]) + { + ossimConnectableObject* obj = PTR_CAST(ossimConnectableObject, theImageChainList[theImageChainList.size()-1]); + if(obj) + { + return obj->canConnectMyInputTo(myInputIndex, + object); + } + } + + return false; + } + +// bool canConnectMyOutputTo(int32 myOutputIndex, +// const ossimConnectableObject* object)const +// { +// if(theImageChainList.size()&&theImageChainList[0]) +// { +// ossimConnectableObject* obj = PTR_CAST(ossimConnectableObject, theImageChainList[0]); +// if(obj) +// { +// return obj->canConnectMyOutputTo(myOutputIndex, +// object); +// } +// } + +// return false; +// } + + // ________________________CONNECTABLE CONTAINER DEFINTIONS_________________ + // + + /** + * Will find all objects of the past in type. Use the RTTI type info. An optional + * recurse flag will say if there is another container then recurse it to + * find the type you are looking for else it just looks within its immediate + * children + * + * Example: passing STATIC_TYPE_INFO(ossimImageRenderer) as an argument will + * look for all ossimImageRenderer's and return the list. + */ + virtual std::vector<ossimConnectableObject*> findAllObjectsOfType(const RTTItypeid& typeInfo, + bool recurse=true); + virtual std::vector<ossimConnectableObject*> findAllObjectsOfType(const ossimString& className, + bool recurse=true); + + /** + * Will find the firt object of the past in type. Use the RTTI type info.An optional + * recurse flag will say if there is another container then recurse it to + * find the type you are looking for else it just looks within its immediate + * children + * + * Example: passing STATIC_TYPE_INFO(ossimImageRenderer) as an argument will + * look for the first ossimImageRenderer and return that object. + */ + virtual ossimConnectableObject* findFirstObjectOfType(const RTTItypeid& typeInfo, + bool recurse=true); + virtual ossimConnectableObject* findFirstObjectOfType(const ossimString& className, + bool recurse=true); + + /** + * will search for the object given an id. If recurse is true it will + * recurse to other containers. + */ + virtual ossimConnectableObject* findObject(const ossimId& id, + bool recurse=true); + + virtual ossimConnectableObject* findObject(const ossimConnectableObject* obj, + bool recurse=true); + + /** + * Will cycle through all sources setting their ids. the idLast wlil + * be updated + * so we can recurse into other containers. + */ + virtual void makeUniqueIds(); + + /** + * Returns the number of objects within this container and all child + * containers. + * + * @param recurse If true and object is a contains containers; all objects + * will be conter. If false only the objects of this container will be + * counted (theImageChainList.size()). + */ + virtual ossim_uint32 getNumberOfObjects(bool recurse=true)const; + + /** + * Deprecated! Please use getNumberOfObjects(false). + * + * @return The number of objects in this container or + * (theImageChainList.size()). + */ + virtual ossim_uint32 getNumberOfSources() const; + + /** + * Will add an object to the container and then set the added objects owner + * to this. + */ + virtual bool addChild(ossimConnectableObject* attachableObject); + + /** + * Will remove the child from the container. Changes the owner of the + * child to be NULL; + */ + virtual bool removeChild(ossimConnectableObject* object); + virtual ossimConnectableObject* removeChild(const ossimId& id); + + virtual void getChildren(vector<ossimConnectableObject*>& children, + bool immediateChildrenOnlyFlag); + //______________END CONNECTABLE CONTAINER INTERFACE____________ + + virtual void disconnectInputEvent(ossimConnectionEvent& event); + virtual void disconnectOutputEvent(ossimConnectionEvent& event); + virtual void connectInputEvent(ossimConnectionEvent& event); + virtual void connectOutputEvent(ossimConnectionEvent& event); + virtual void objectDestructingEvent(ossimObjectDestructingEvent& event); + + virtual void propagateEventToOutputs(ossimEvent& event); + virtual void propagateEventToInputs(ossimEvent& event); + +protected: + friend class ossimImageChainChildListener; + /** + * This will hold a sequence of image sources. + * theFirst one in the list will be the head of the + * list and the last one is the tail. + */ + vector<ossimConnectableObject*> theImageChainList; + + ossimRefPtr<ossimImageData> theBlankTile; + ossimImageChainChildListener* theChildListener; + mutable bool thePropagateEventFlag; + mutable bool theLoadStateFlag; + /** + * For dynamic loading to take place we must allocate all objects first and + * then assign id's later. We must remember the id's so we can do this. + * we will create a map that takes the id of the source as a key and a + * vector of input id's to connect it's inputs to. + */ + bool addAllSources(map<ossimId, vector<ossimId> >& idMapping, + const ossimKeywordlist& kwl, + const char* prefix = NULL); + void findInputConnectionIds(vector<ossimId>& result, + const ossimKeywordlist& kwl, + const char* prefix=NULL); + bool connectAllSources(const map<ossimId, vector<ossimId> >& idMapping); + + void deleteList(); + +TYPE_DATA +}; +#endif /* #ifndef ossimImageChain_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimImageData.cpp b/Utilities/OSSIM/ossim_core/imaging/ossimImageData.cpp new file mode 100644 index 0000000000..b2a093dc0a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimImageData.cpp @@ -0,0 +1,5662 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimImageData.cpp,v 1.149 2006/01/04 22:31:15 dburken Exp $ + +#include <iterator> + +#include <imaging/ossimImageData.h> +#include <base/common/ossimSource.h> +#include <base/context/ossimErrorContext.h> +#include <base/data_types/ossimIrect.h> +#include <base/data_types/ossimMultiBandHistogram.h> +#include <base/data_types/ossimHistogram.h> +#include <base/misc/lookup_tables/ossimScalarTypeLut.h> + +RTTI_DEF1(ossimImageData, "ossimImageData", ossimRectilinearDataObject) + +ossimImageData::ossimImageData() + : ossimRectilinearDataObject(2, // 2d + NULL, // owner + 1, // bands + OSSIM_UINT8), // scalar + theNullPixelValue(NULL), + theMinPixelValue(NULL), + theMaxPixelValue(NULL), + theOrigin(0, 0) +{ + ossimIpt defaultTileSize; + ossimGetDefaultTileSize(defaultTileSize); + theSpatialExtents[0] = defaultTileSize.x; + theSpatialExtents[1] = defaultTileSize.y; +} + +ossimImageData::ossimImageData(ossimSource* owner, + ossimScalarType scalar, + ossim_uint32 bands) + : ossimRectilinearDataObject(2, + owner, + bands, + scalar), + theNullPixelValue(NULL), + theMinPixelValue(NULL), + theMaxPixelValue(NULL), + theOrigin(0, 0) +{ + ossimIpt defaultTileSize; + ossimGetDefaultTileSize(defaultTileSize); + theSpatialExtents[0] = defaultTileSize.x; + theSpatialExtents[1] = defaultTileSize.y; + initializeDefaults(); +} + +ossimImageData::ossimImageData(ossimSource* owner, + ossimScalarType scalar, + ossim_uint32 bands, + ossim_uint32 width, + ossim_uint32 height) + :ossimRectilinearDataObject(owner, + bands, + width, // 2-D array + height, + scalar), + theNullPixelValue(NULL), + theMinPixelValue(NULL), + theMaxPixelValue(NULL), + theOrigin(0, 0) +{ + theSpatialExtents[0] = width; + theSpatialExtents[1] = height; + initializeDefaults(); +} + +ossimImageData::ossimImageData(const ossimImageData &rhs) + :ossimRectilinearDataObject(rhs), + theNullPixelValue(NULL), + theMinPixelValue(NULL), + theMaxPixelValue(NULL), + theOrigin(rhs.theOrigin) +{ + if(rhs.theNullPixelValue) + { + theNullPixelValue = new ossim_float64[getNumberOfBands()]; + + memcpy((void*)theNullPixelValue, + (const void*)rhs.theNullPixelValue, + (sizeof(ossim_float64)*(int)getNumberOfBands())); + } + if(rhs.theMinPixelValue) + { + theMinPixelValue = new ossim_float64[getNumberOfBands()]; + + memcpy((void*)theMinPixelValue, + (const void*)rhs.theMinPixelValue, + (sizeof(ossim_float64)*(int)getNumberOfBands())); + } + if(rhs.theMaxPixelValue) + { + theMaxPixelValue = new ossim_float64[getNumberOfBands()]; + + memcpy((void*)theMaxPixelValue, + (const void*)rhs.theMaxPixelValue, + (sizeof(ossim_float64)*(int)getNumberOfBands())); + } +} + +ossimImageData::~ossimImageData() +{ + if(theMinPixelValue) + { + delete [] theMinPixelValue; + theMinPixelValue = NULL; + } + if(theMaxPixelValue) + { + delete [] theMaxPixelValue; + theMaxPixelValue = NULL; + } + if(theNullPixelValue) + { + delete [] theNullPixelValue; + theNullPixelValue = NULL; + } +} + +bool ossimImageData::isValidBand(ossim_uint32 band) const +{ + return (band<getNumberOfDataComponents()); +} + +ossim_uint32 ossimImageData::getSize() const +{ + return (getSizePerBand() * getNumberOfDataComponents()); +} + +ossim_uint32 ossimImageData::getSizePerBand() const +{ + return (getHeight() * getWidth()); +} + +ossim_uint32 ossimImageData::getSizeInBytes() const +{ + return (getSizePerBandInBytes() * getNumberOfDataComponents()); +} + +ossim_uint32 ossimImageData::getSizePerBandInBytes() const +{ + return (getHeight() * getWidth() * getScalarSizeInBytes()); +} + +const void* ossimImageData::getBuf() const +{ + return static_cast<const void*>(theDataBuffer); +} + +void* ossimImageData::getBuf() +{ + return static_cast<void*>(theDataBuffer); +} + +const void* ossimImageData::getBuf(ossim_uint32 band) const +{ + const ossim_uint8* b = theDataBuffer; + + if (isValidBand(band) && b != NULL) + { + b += (band * getSizePerBandInBytes()); + return static_cast<const void*>(b); + } + return NULL; +} + +void* ossimImageData::getBuf(ossim_uint32 band) +{ + ossim_uint8* b = theDataBuffer; + + if (isValidBand(band) && b != NULL) + { + b += (band * getSizePerBandInBytes()); + return static_cast<void*>(b); + } + return NULL; +} + +const ossim_uint8* ossimImageData::getUcharBuf() const +{ + if (theScalarType == OSSIM_UINT8) + { + return static_cast<const ossim_uint8*>(theDataBuffer); + } + return NULL; +} + +const ossim_uint16* ossimImageData::getUshortBuf() const +{ + if (theScalarType == OSSIM_UINT16 || + theScalarType == OSSIM_USHORT11) + { + return static_cast<const ossim_uint16*>(getBuf()); + } + return NULL; +} + +const ossim_sint16* ossimImageData::getSshortBuf() const +{ + if (theScalarType == OSSIM_SINT16) + { + return static_cast<const ossim_sint16*>(getBuf()); + } + return NULL; +} + +const ossim_float32* ossimImageData::getFloatBuf() const +{ + if (theScalarType == OSSIM_FLOAT32 || + theScalarType == OSSIM_NORMALIZED_FLOAT) + { + return static_cast<const ossim_float32*>(getBuf()); + } + return NULL; +} + +const ossim_float64* ossimImageData::getDoubleBuf() const +{ + if (theScalarType == OSSIM_FLOAT64 || + theScalarType == OSSIM_NORMALIZED_DOUBLE) + { + return static_cast<const ossim_float64*>(getBuf()); + } + return NULL; +} + +ossim_uint8* ossimImageData::getUcharBuf() +{ + if (theScalarType == OSSIM_UINT8) + { + return theDataBuffer; + } + return NULL; +} + +ossim_uint16* ossimImageData::getUshortBuf() +{ + if (theScalarType == OSSIM_UINT16 || + theScalarType == OSSIM_USHORT11) + { + return static_cast<ossim_uint16*>(getBuf()); + } + return NULL; +} + +ossim_sint16* ossimImageData::getSshortBuf() +{ + if (theScalarType == OSSIM_SINT16) + { + return static_cast<ossim_sint16*>(getBuf()); + } + return NULL; +} + +ossim_float32* ossimImageData::getFloatBuf() +{ + if (theScalarType == OSSIM_FLOAT32 || + theScalarType == OSSIM_NORMALIZED_FLOAT) + { + return static_cast<ossim_float32*>(getBuf()); + } + return NULL; +} + +ossim_float64* ossimImageData::getDoubleBuf() +{ + if (theScalarType == OSSIM_FLOAT64 || + theScalarType == OSSIM_NORMALIZED_DOUBLE) + { + return static_cast<ossim_float64*>(getBuf()); + } + return NULL; +} + +const ossim_uint8* ossimImageData::getUcharBuf(ossim_uint32 band) const +{ + if (theScalarType == OSSIM_UINT8) + { + return static_cast<const ossim_uint8*>(getBuf(band)); + } + return NULL; +} + +const ossim_uint16* ossimImageData::getUshortBuf(ossim_uint32 band) const +{ + if (theScalarType == OSSIM_UINT16 || + theScalarType == OSSIM_USHORT11) + { + return static_cast<const ossim_uint16*>(getBuf(band)); + } + return NULL; +} + +const ossim_sint16* ossimImageData::getSshortBuf(ossim_uint32 band) const +{ + if (theScalarType == OSSIM_SINT16) + { + return static_cast<const ossim_sint16*>(getBuf(band)); + } + return NULL; +} + +const ossim_float32* ossimImageData::getFloatBuf(ossim_uint32 band) const +{ + if (theScalarType == OSSIM_FLOAT32 || + theScalarType == OSSIM_NORMALIZED_FLOAT) + { + return static_cast<const ossim_float32*>(getBuf(band)); + } + return NULL; +} + +const ossim_float64* ossimImageData::getDoubleBuf(ossim_uint32 band) const +{ + if (theScalarType == OSSIM_FLOAT64 || + theScalarType == OSSIM_NORMALIZED_DOUBLE) + { + return static_cast<const ossim_float64*>(getBuf(band)); + } + return NULL; +} + +ossim_uint8* ossimImageData::getUcharBuf(ossim_uint32 band) +{ + if (theScalarType == OSSIM_UINT8) + { + return static_cast<ossim_uint8*>(getBuf(band)); + } + return NULL; +} + +ossim_uint16* ossimImageData::getUshortBuf(ossim_uint32 band) +{ + if (theScalarType == OSSIM_UINT16 || + theScalarType == OSSIM_USHORT11) + { + return static_cast<ossim_uint16*>(getBuf(band)); + } + return NULL; +} + +ossim_sint16* ossimImageData::getSshortBuf(ossim_uint32 band) +{ + if (theScalarType == OSSIM_SINT16) + { + return static_cast<ossim_sint16*>(getBuf(band)); + } + return NULL; +} + +ossim_float32* ossimImageData::getFloatBuf(ossim_uint32 band) +{ + if (theScalarType == OSSIM_FLOAT32 || + theScalarType == OSSIM_NORMALIZED_FLOAT) + { + return static_cast<ossim_float32*>(getBuf(band)); + } + return NULL; +} + +ossim_float64* ossimImageData::getDoubleBuf(ossim_uint32 band) +{ + if (theScalarType == OSSIM_FLOAT64 || + theScalarType == OSSIM_NORMALIZED_DOUBLE) + { + return static_cast<ossim_float64*>(getBuf(band)); + } + return NULL; +} + +void ossimImageData::getNormalizedFloat(ossim_uint32 offset, + ossim_uint32 bandNumber, + ossim_float32& result)const +{ + if(!result) + { + return; + } + + // Make sure that the types and width and height are good. + if( (getDataObjectStatus() == OSSIM_NULL) && + (bandNumber < getNumberOfDataComponents()) ) + { + return; + } + + ossim_float32 delta = theMaxPixelValue[bandNumber] - theMinPixelValue[bandNumber]; + switch (getScalarType()) + { + case OSSIM_UINT8: + { + const unsigned char* sourceBuf = getUcharBuf(bandNumber); + result = (sourceBuf[offset] - theMinPixelValue[bandNumber])/delta; + break; + } + case OSSIM_SINT8: + { + const ossim_sint8* sourceBuf = static_cast<const ossim_sint8*>(getBuf(bandNumber)); + result = (sourceBuf[offset] - theMinPixelValue[bandNumber])/delta; + break; + } + case OSSIM_USHORT11: + case OSSIM_UINT16: + { + const ossim_uint16* sourceBuf = getUshortBuf(bandNumber); + result = (sourceBuf[offset] - theMinPixelValue[bandNumber])/delta; + break; + } + case OSSIM_SINT16: + { + const ossim_sint16* sourceBuf = getSshortBuf(bandNumber); + result = (sourceBuf[offset] - theMinPixelValue[bandNumber])/delta; + break; + } + case OSSIM_UINT32: + { + const ossim_uint32* sourceBuf = + static_cast<const ossim_uint32*>(getBuf(bandNumber)); + result = (sourceBuf[offset] - theMinPixelValue[bandNumber])/delta; + break; + } + case OSSIM_SINT32: + { + const ossim_sint32* sourceBuf = static_cast<const ossim_sint32*>(getBuf(bandNumber)); + result = (sourceBuf[offset] - theMinPixelValue[bandNumber])/delta; + break; + } + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT32: + { + const ossim_float32* sourceBuf = getFloatBuf(bandNumber); + result = (sourceBuf[offset] - theMinPixelValue[bandNumber])/delta; + break; + } + case OSSIM_FLOAT64: + case OSSIM_NORMALIZED_DOUBLE: + { + const ossim_float64* sourceBuf = getDoubleBuf(bandNumber); + result = (sourceBuf[offset] - theMinPixelValue[bandNumber])/delta; + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + // Shouldn't hit this. + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::setNormalizedFloat Unsupported scalar type!" + << std::endl; + + result = 0; + } + } +} + +void ossimImageData::setNormalizedFloat(ossim_uint32 offset, + ossim_uint32 bandNumber, + ossim_float32 inputValue) +{ + // Make sure that the types and width and height are good. + if( (getDataObjectStatus() == OSSIM_NULL)&& + (bandNumber < getNumberOfDataComponents()) ) + { + return; + } + + ossim_float32 delta = theMaxPixelValue[bandNumber] - theMinPixelValue[bandNumber]; + switch (getScalarType()) + { + case OSSIM_UINT8: + { + unsigned char* sourceBuf = getUcharBuf(bandNumber); + sourceBuf[offset] = + static_cast<ossim_uint8>(theMinPixelValue[bandNumber] + + delta*inputValue); + + break; + } + case OSSIM_SINT8: + { + ossim_sint8* sourceBuf = static_cast<ossim_sint8*>(getBuf(bandNumber)); + sourceBuf[offset] = + static_cast<ossim_sint8>(theMinPixelValue[bandNumber] + + delta*inputValue); + break; + } + case OSSIM_USHORT11: + case OSSIM_UINT16: + { + ossim_uint16* sourceBuf = getUshortBuf(bandNumber); + sourceBuf[offset] = + static_cast<ossim_uint16>(theMinPixelValue[bandNumber] + + delta*inputValue); + break; + } + case OSSIM_SINT16: + { + ossim_sint16* sourceBuf = getSshortBuf(bandNumber); + sourceBuf[offset] = + static_cast<ossim_sint16>(theMinPixelValue[bandNumber] + + delta*inputValue); + break; + } + case OSSIM_UINT32: + { + ossim_uint32* sourceBuf = + static_cast<ossim_uint32*>(getBuf(bandNumber)); + sourceBuf[offset] = + static_cast<ossim_uint32>(theMinPixelValue[bandNumber] + + delta*inputValue); + break; + } + case OSSIM_SINT32: + { + ossim_sint32* sourceBuf = static_cast<ossim_sint32*>(getBuf(bandNumber)); + sourceBuf[offset] = + static_cast<ossim_sint32>(theMinPixelValue[bandNumber] + + delta*inputValue); + break; + } + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT32: + { + ossim_float32* sourceBuf = getFloatBuf(bandNumber); + sourceBuf[offset] = + static_cast<ossim_float32>(theMinPixelValue[bandNumber] + + delta*inputValue); + break; + } + case OSSIM_FLOAT64: + case OSSIM_NORMALIZED_DOUBLE: + { + ossim_float64* sourceBuf = getDoubleBuf(bandNumber); + sourceBuf[offset] = + static_cast<ossim_float64>(theMinPixelValue[bandNumber] + + delta*inputValue); + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + // Shouldn't hit this. + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::setNormalizedFloat Unsupported scalar type!" + << std::endl; + } +} + +void ossimImageData::convertToNormalizedFloat(ossimImageData* result)const +{ + if(!result) + { + return; + } + // make sure that the types and width and height are + // good. + if( (result->getScalarType() != OSSIM_NORMALIZED_FLOAT) || + (result->getNumberOfBands() != this->getNumberOfBands())|| + (result->getWidth() != this->getWidth()) || + (result->getHeight() != this->getHeight())|| + (result->getDataObjectStatus() == OSSIM_NULL) || + (getDataObjectStatus() == OSSIM_NULL)) + { + return; + } + + copyTileToNormalizedBuffer((ossim_float32*)result->getBuf()); + result->setDataObjectStatus(getDataObjectStatus()); +} + +ossimRefPtr<ossimImageData> ossimImageData::newNormalizedFloat()const +{ + ossimRefPtr<ossimImageData> result = + new ossimImageData(NULL, + OSSIM_NORMALIZED_FLOAT, + this->getNumberOfBands(), + this->getWidth(), + this->getHeight()); + + result->initialize(); + + convertToNormalizedFloat(result.get()); + + return result; +} + +void ossimImageData::convertToNormalizedDouble(ossimImageData* result)const +{ + if(!result) + { + return; + } + // make sure that the types and width and height are + // good. + if( (result->getScalarType() != OSSIM_NORMALIZED_DOUBLE) || + (result->getNumberOfBands() != this->getNumberOfBands())|| + (result->getWidth() != this->getWidth()) || + (result->getHeight() != this->getHeight())|| + (result->getDataObjectStatus() == OSSIM_NULL) || + (getDataObjectStatus() == OSSIM_NULL)) + { + return; + } + + copyTileToNormalizedBuffer((ossim_float64*)result->getBuf()); + result->setDataObjectStatus(getDataObjectStatus()); +} + +ossimImageData* ossimImageData::newNormalizedDouble()const +{ + ossimImageData* result = new ossimImageData(NULL, + OSSIM_NORMALIZED_DOUBLE, + this->getNumberOfBands(), + this->getWidth(), + this->getHeight()); + result->initialize(); + + convertToNormalizedDouble(result); + + return result; +} + + +void ossimImageData::unnormalizeInput(ossimImageData* normalizedInput) +{ + if((normalizedInput->getScalarType() != OSSIM_NORMALIZED_FLOAT) && + (normalizedInput->getScalarType() != OSSIM_NORMALIZED_DOUBLE) ) + { + //ERROR + return; + } + + if(normalizedInput->getScalarType() == OSSIM_NORMALIZED_DOUBLE) + { + copyNormalizedBufferToTile((ossim_float64*)normalizedInput->getBuf()); + } + else + { + copyNormalizedBufferToTile((ossim_float32*)normalizedInput->getBuf()); + } +} + +ossim_float64 ossimImageData::computeMeanSquaredError( + ossim_float64 meanValue, + ossim_uint32 bandNumber) const +{ + ossim_float64 result = -1; // invalid MSE + + switch (getScalarType()) + { + case OSSIM_UINT8: + { + result = computeMeanSquaredError(ossim_uint8(0), + meanValue, + bandNumber); + break; + } + case OSSIM_SINT8: + { + result = computeMeanSquaredError(ossim_sint8(0), + meanValue, + bandNumber); + break; + } + case OSSIM_UINT16: + case OSSIM_USHORT11: + { + result = computeMeanSquaredError(ossim_uint16(0), + meanValue, + bandNumber); + break; + } + case OSSIM_SINT16: + { + result = computeMeanSquaredError(ossim_sint16(0), + meanValue, + bandNumber); + break; + } + case OSSIM_UINT32: + { + result = computeMeanSquaredError(ossim_uint32(0), + meanValue, + bandNumber); + break; + } + case OSSIM_SINT32: + { + result = computeMeanSquaredError(ossim_sint32(0), + meanValue, + bandNumber); + break; + } + case OSSIM_FLOAT32: + case OSSIM_NORMALIZED_FLOAT: + { + result = computeMeanSquaredError(ossim_float32(0.0), + meanValue, + bandNumber); + break; + } + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_FLOAT64: + { + result = computeMeanSquaredError(ossim_float64(0.0), + meanValue, + bandNumber); + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + setDataObjectStatus(OSSIM_STATUS_UNKNOWN); + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimImageData::computeMeanSquaredError File %s line %d\n\ +Invalid scalar type: %d", + __FILE__, + __LINE__, + getScalarType()); + break; + } + } + + return result; +} + +template <class T> ossim_float64 ossimImageData::computeMeanSquaredError( + T, /* dummyTemplate */ + ossim_float64 meanValue, + ossim_uint32 bandNumber) const +{ + ossim_float64 result = -1.0; // invalid MSE + + if ( (getDataObjectStatus() == OSSIM_NULL) || + (getDataObjectStatus() == OSSIM_EMPTY) ) + { + return result; + } + + ossim_uint32 index = 0; + ossim_float64 delta = 0.0; + ossim_uint32 validPixelCount = 0; + + const T* BUFFER = static_cast<const T*>(getBuf(bandNumber)); + if(BUFFER) + { + const ossim_uint32 BOUNDS = getSizePerBand(); + for(index = 0; index < BOUNDS; ++index) + { + if(!isNull(index)) + { + delta = BUFFER[index] - meanValue; + result += (delta*delta); + ++validPixelCount; + } + } + if(validPixelCount > 0) + { + result /= validPixelCount; + } + } + + return result; +} + + +//****************************************************************** +// +// NOTE: I was checking for null and not adding it to the histogram. +// this was messing up the equalization algorithms since the +// accumulation histogram did not represent the area of the +// image. For now I will leave out the check for "is null" and +// add this to the count so that the total accumulation is the +// area of the image. +// +//****************************************************************** +void ossimImageData::populateHistogram(ossimMultiBandHistogram* histo) +{ + ossim_uint32 numberOfBands = getNumberOfBands(); + + if( (getDataObjectStatus() == OSSIM_NULL) || + (getDataObjectStatus() == OSSIM_EMPTY)|| + (!histo)) + { + return; + } + switch(getScalarType()) + { + case OSSIM_UINT8: + { + for(ossim_uint32 band = 0; band < numberOfBands; ++band) + { + ossimHistogram* currentHisto = histo->getHistogram(band); + ossim_uint8* buffer = (ossim_uint8*)getBuf(band); + + if(currentHisto) + { + ossimHistogram* currentHisto = histo->getHistogram(band); + + if(currentHisto) + { + ossim_uint32 upperBound = getWidth()*getHeight(); + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + currentHisto->UpCount((float)buffer[offset]); + } + } + } + } + break; + } + case OSSIM_UINT16: + case OSSIM_USHORT11: + { + for(ossim_uint32 band = 0; band < numberOfBands; ++band) + { + ossimHistogram* currentHisto = histo->getHistogram(band); + + ossim_uint16* buffer = (ossim_uint16*)getBuf(band); + if(currentHisto) + { + ossim_uint32 upperBound = getWidth()*getHeight(); + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + currentHisto->UpCount((float)buffer[offset]); + } + } + } + break; + } + case OSSIM_SINT16: + { + for(ossim_uint32 band = 0; band < numberOfBands; ++band) + { + ossimHistogram* currentHisto = histo->getHistogram(band); + ossim_sint16* buffer = (ossim_sint16*)getBuf(band); + + if(currentHisto) + { + ossim_uint32 upperBound = getWidth()*getHeight(); + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + currentHisto->UpCount((float)buffer[offset]); + } + } + } + break; + } + case OSSIM_SINT32: + { + for(ossim_uint32 band = 0; band < numberOfBands; ++band) + { + ossimHistogram* currentHisto = histo->getHistogram(band); + ossim_sint32* buffer = (ossim_sint32*)getBuf(band); + + if(currentHisto) + { + ossim_uint32 upperBound = getWidth()*getHeight(); + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + currentHisto->UpCount((float)buffer[offset]); + } + } + } + break; + } + case OSSIM_UINT32: + { + for(ossim_uint32 band = 0; band < numberOfBands; ++band) + { + ossimHistogram* currentHisto = histo->getHistogram(band); + ossim_uint32* buffer = (ossim_uint32*)getBuf(band); + + if(currentHisto) + { + ossim_uint32 upperBound = getWidth()*getHeight(); + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + currentHisto->UpCount((float)buffer[offset]); + } + } + } + break; + } + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_FLOAT64: + { + for(ossim_uint32 band = 0; band < numberOfBands; ++band) + { + ossimHistogram* currentHisto = histo->getHistogram(band); + ossim_float64* buffer = (ossim_float64*)getBuf(band); + + if(currentHisto) + { + ossim_uint32 upperBound = getWidth()*getHeight(); + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + currentHisto->UpCount((float)buffer[offset]); + } + } + } + break; + } + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT32: + { + for(ossim_uint32 band = 0; band < numberOfBands; ++band) + { + ossimHistogram* currentHisto = histo->getHistogram(band); + ossim_float32* buffer = (ossim_float32*)getBuf(band); + + if(currentHisto) + { + ossim_uint32 upperBound = getWidth()*getHeight(); + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + currentHisto->UpCount((float)buffer[offset]); + } + } + } + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + //ERROR + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::populateHistogram\n" + << "Unknown scalar type." << std::endl; + } + } // end of switch +} + +ossim_float64 ossimImageData::computeAverageBandValue(ossim_uint32 bandNumber) const +{ + ossim_float64 result = 0.0; + + switch (getScalarType()) + { + case OSSIM_UINT8: + { + result = computeAverageBandValue(ossim_uint8(0), + bandNumber); + break; + } + case OSSIM_SINT8: + { + result = computeAverageBandValue(ossim_sint8(0), + bandNumber); + break; + } + case OSSIM_UINT16: + case OSSIM_USHORT11: + { + result = computeAverageBandValue(ossim_uint16(0), + bandNumber); + break; + } + case OSSIM_SINT16: + { + result = computeAverageBandValue(ossim_sint16(0), + bandNumber); + break; + } + case OSSIM_UINT32: + { + result = computeAverageBandValue(ossim_uint32(0), + bandNumber); + break; + } + case OSSIM_SINT32: + { + result = computeAverageBandValue(ossim_sint32(0), + bandNumber); + break; + } + case OSSIM_FLOAT32: + case OSSIM_NORMALIZED_FLOAT: + { + result = computeAverageBandValue(ossim_float32(0.0), + bandNumber); + break; + } + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_FLOAT64: + { + result = computeAverageBandValue(ossim_float64(0.0), + bandNumber); + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + setDataObjectStatus(OSSIM_STATUS_UNKNOWN); + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimImageData::computeAverageBandValue File %s line %d\n\ +Invalid scalar type: %d", + __FILE__, + __LINE__, + getScalarType()); + break; + } + } + + return result; +} + +template <class T> ossim_float64 ossimImageData::computeAverageBandValue( + T, /* dummy */ + ossim_uint32 bandNumber) const +{ + ossim_float64 result = 0.0; + + if ( (getDataObjectStatus() == OSSIM_NULL) || + (getDataObjectStatus() == OSSIM_EMPTY) ) + { + return result; + } + + ossim_uint32 index = 0; + ossim_uint32 validPixelCount = 0; + + const T* BUFFER = static_cast<const T*>(getBuf(bandNumber)); + if(BUFFER) + { + const ossim_uint32 BOUNDS = getSizePerBand(); + for(index = 0; index < BOUNDS; ++index) + { + if(!isNull(index)) + { + result += BUFFER[index]; + ++validPixelCount; + } + } + if(validPixelCount > 0) + { + result /= validPixelCount; + } + } + + return result; +} + +ossimDataObjectStatus ossimImageData::validate() const +{ + switch (getScalarType()) + { + case OSSIM_UINT8: + { + return validate(ossim_uint8(0)); + } + case OSSIM_SINT8: + { + return validate(ossim_sint8(0)); + } + + case OSSIM_UINT16: + case OSSIM_USHORT11: + { + return validate(ossim_uint16(0)); + } + case OSSIM_SINT16: + { + return validate(ossim_sint16(0)); + } + + case OSSIM_UINT32: + { + return validate(ossim_uint32(0)); + } + case OSSIM_SINT32: + { + return validate(ossim_sint32(0)); + } + case OSSIM_FLOAT32: + case OSSIM_NORMALIZED_FLOAT: + { + return validate(ossim_float32(0.0)); + } + + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_FLOAT64: + { + return validate(ossim_float64(0.0)); + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + setDataObjectStatus(OSSIM_STATUS_UNKNOWN); + break; + } + } + + return OSSIM_STATUS_UNKNOWN; +} + +template <class T> +ossimDataObjectStatus ossimImageData::validate(T /* dummyTemplate */ ) const +{ + if (theDataBuffer == NULL) + { + setDataObjectStatus(OSSIM_NULL); + return OSSIM_NULL; + } + + ossim_uint32 count = 0; + const ossim_uint32 SIZE = getSize(); + const ossim_uint32 BOUNDS = getSizePerBand(); + const ossim_uint32 NUMBER_OF_BANDS = getNumberOfBands(); + + for(ossim_uint32 band = 0; band < NUMBER_OF_BANDS; ++band) + { + const T NP = static_cast<T>(theNullPixelValue[band]); + const T* p = static_cast<const T*>(getBuf(band)); + + for (ossim_uint32 i = 0; i < BOUNDS; ++i) + { + // check if the band is null + if (p[i] != NP) ++count; + } + } + + if (!count) + setDataObjectStatus(OSSIM_EMPTY); + else if (count == SIZE) + setDataObjectStatus(OSSIM_FULL); + else + setDataObjectStatus(OSSIM_PARTIAL); + + return getDataObjectStatus(); +} + +void ossimImageData::makeBlank() +{ + if ( (theDataBuffer == NULL) || (getDataObjectStatus() == OSSIM_EMPTY) ) + { + return; // nothing to do... + } + + switch (getScalarType()) + { + case OSSIM_UINT8: + { + makeBlank(ossim_uint8(0)); + return; + } + case OSSIM_SINT8: + { + makeBlank(ossim_sint8(0)); + return; + } + case OSSIM_UINT16: + case OSSIM_USHORT11: + { + makeBlank(ossim_uint16(0)); + return; + } + case OSSIM_SINT16: + { + makeBlank(ossim_sint16(0)); + return; + } + case OSSIM_UINT32: + { + makeBlank(ossim_uint32(0)); + return; + } + case OSSIM_SINT32: + { + makeBlank(ossim_sint32(0)); + return; + } + case OSSIM_FLOAT32: + case OSSIM_NORMALIZED_FLOAT: + { + makeBlank(ossim_float32(0.0)); + return; + } + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_FLOAT64: + { + makeBlank(ossim_float64(0.0)); + return; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + setDataObjectStatus(OSSIM_STATUS_UNKNOWN); + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimImageData::makeBlank File %s line %d\n\ +Invalid scalar type: %d", + __FILE__, + __LINE__, + getScalarType()); + break; + } + } +} + +template <class T> void ossimImageData::makeBlank(T /* dummyTemplate */ ) +{ + if ( (theDataBuffer == NULL) || (getDataObjectStatus() == OSSIM_EMPTY) ) + { + return; // nothing to do... + } + + const ossim_uint32 BANDS = getNumberOfBands(); + const ossim_uint32 SPB = getSizePerBand(); + + for(ossim_uint32 band = 0; band < BANDS; ++band) + { + const T NP = static_cast<T>(theNullPixelValue[band]); + T* p = static_cast<T*>(getBuf(band)); + for (ossim_uint32 i = 0; i < SPB; ++i) + { + p[i] = NP; + } + } + + setDataObjectStatus(OSSIM_EMPTY); +} + +void ossimImageData::initialize() +{ + // let the base class allocate a buffer + ossimRectilinearDataObject::initialize(); + + if(!theMinPixelValue) + { + initializeDefaults(); + } + + if (theDataBuffer) + { + makeBlank(); // Make blank will set the status. + } +} + +bool ossimImageData::isWithin(ossim_int32 x, ossim_int32 y) +{ + return ((x >= theOrigin.x) && + (x < theOrigin.x + static_cast<ossim_int32>(theSpatialExtents[0])) && + (y >= theOrigin.y) && + (y < theOrigin.y + static_cast<ossim_int32>(theSpatialExtents[1]))); + +} + +void ossimImageData::setValue(ossim_int32 x, ossim_int32 y, ossim_float64 color) +{ + if(theDataBuffer&&isWithin(x, y)) + { + ossim_uint32 band=0; + + //*** + // Compute the offset into the buffer for (x,y). This should always + // come out positive. + //*** + ossim_uint32 ux = static_cast<ossim_uint32>(x - theOrigin.x); + ossim_uint32 uy = static_cast<ossim_uint32>(y - theOrigin.y); + + ossim_uint32 offset = uy * theSpatialExtents[0] + ux; + + switch (getScalarType()) + { + case OSSIM_UINT8: + { + for(band = 0; band < theNumberOfDataComponents; band++) + { + unsigned char* buf = static_cast<unsigned char*>(getBuf(band))+ + offset; + *buf = (unsigned char)color; + } + break; + } + case OSSIM_SINT8: + { + for(band = 0; band < theNumberOfDataComponents; band++) + { + ossim_sint8* buf = static_cast<ossim_sint8*>(getBuf(band))+ + offset; + *buf = (ossim_sint8)color; + } + break; + } + case OSSIM_UINT16: + case OSSIM_USHORT11: + { + for(band = 0; band < theNumberOfDataComponents; band++) + { + ossim_uint16* buf = static_cast<ossim_uint16*>(getBuf(band))+ + offset; + *buf = (ossim_uint16)color; + } + break; + } + case OSSIM_SINT16: + { + for(band = 0; band < theNumberOfDataComponents; band++) + { + signed short* buf = static_cast<signed short*>(getBuf(band))+ + offset; + *buf = (signed short)color; + } + break; + } + case OSSIM_UINT32: + { + for(band = 0; band < theNumberOfDataComponents; band++) + { + ossim_uint32* buf = static_cast<ossim_uint32*>(getBuf(band))+ + offset; + *buf = (ossim_uint32)color; + } + break; + } + case OSSIM_SINT32: + { + for(band = 0; band < theNumberOfDataComponents; band++) + { + ossim_sint32* buf = static_cast<ossim_sint32*>(getBuf(band))+ + offset; + *buf = (ossim_sint32)color; + } + break; + } + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT32: + { + for(band = 0; band < theNumberOfDataComponents; band++) + { + ossim_float32* buf = static_cast<ossim_float32*>(getBuf(band))+offset; + *buf = (ossim_float32)color; + } + break; + } + case OSSIM_FLOAT64: + case OSSIM_NORMALIZED_DOUBLE: + { + for(band = 0; band < theNumberOfDataComponents; band++) + { + ossim_float64* buf = static_cast<ossim_float64*>(getBuf(band))+offset; + *buf = color; + } + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + //ERROR + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::setValue Unsupported scalar type!" + << std::endl; + + } + + } // End of: switch (getScalarType()) + } +} + +void ossimImageData::initializeDefaults() +{ + ossim_uint32 numberOfBands = getNumberOfBands(); + if(numberOfBands < 1) + { + return; + } + if(theMinPixelValue) + { + delete [] theMinPixelValue; + theMinPixelValue = NULL; + } + if(theMaxPixelValue) + { + delete [] theMaxPixelValue; + theMaxPixelValue = NULL; + } + if(theNullPixelValue) + { + delete [] theNullPixelValue; + theNullPixelValue = NULL; + } + theMinPixelValue = new ossim_float64[numberOfBands]; + theMaxPixelValue = new ossim_float64[numberOfBands]; + theNullPixelValue = new ossim_float64[numberOfBands]; + ossim_uint32 band; + switch (getScalarType()) + { + case OSSIM_UINT8: + { + for(band = 0; band < numberOfBands; ++band) + { + theNullPixelValue[band] = 0.0; + theMinPixelValue[band] = OSSIM_DEFAULT_MIN_PIX_UCHAR; + theMaxPixelValue[band] = OSSIM_DEFAULT_MAX_PIX_UCHAR; + } + break; + } + case OSSIM_SINT8: + { + for(band = 0; band < numberOfBands; ++band) + { + theNullPixelValue[band] = OSSIM_DEFAULT_MIN_PIX_SINT8-1; + theMinPixelValue[band] = OSSIM_DEFAULT_MIN_PIX_SINT8; + theMaxPixelValue[band] = OSSIM_DEFAULT_MAX_PIX_SINT8; + } + break; + } + case OSSIM_UINT16: + { + for(band = 0; band < numberOfBands; ++band) + { + theNullPixelValue[band] = OSSIM_USHORT_NAN; + theMinPixelValue[band] = OSSIM_DEFAULT_MIN_PIX_UINT16; + theMaxPixelValue[band] = OSSIM_DEFAULT_MAX_PIX_UINT16; + } + break; + } + case OSSIM_USHORT11: + { + for(band = 0; band < numberOfBands; ++band) + { + theNullPixelValue[band] = OSSIM_USHORT_NAN; + theMinPixelValue[band] = OSSIM_DEFAULT_MIN_PIX_UINT11; + theMaxPixelValue[band] = OSSIM_DEFAULT_MAX_PIX_UINT11; + } + break; + } + case OSSIM_SINT16: + { + for(band = 0; band < numberOfBands; ++band) + { + theNullPixelValue[band] = OSSIM_SSHORT_NAN; + theMinPixelValue[band] = OSSIM_DEFAULT_MIN_PIX_SINT16; + theMaxPixelValue[band] = OSSIM_DEFAULT_MAX_PIX_SINT16; + } + break; + } + case OSSIM_UINT32: + { + for(band = 0; band < numberOfBands; ++band) + { + theNullPixelValue[band] = OSSIM_UINT_NAN; + theMinPixelValue[band] = OSSIM_DEFAULT_MIN_PIX_UINT32; + theMaxPixelValue[band] = OSSIM_DEFAULT_MAX_PIX_UINT32; + } + break; + } + case OSSIM_SINT32: + { + for(band = 0; band < numberOfBands; ++band) + { + theNullPixelValue[band] = OSSIM_DEFAULT_MIN_PIX_SINT32-1; + theMinPixelValue[band] = OSSIM_DEFAULT_MIN_PIX_SINT32; + theMaxPixelValue[band] = OSSIM_DEFAULT_MAX_PIX_SINT32; + } + break; + } + case OSSIM_NORMALIZED_FLOAT: + { + for(band = 0; band < numberOfBands; ++band) + { + theNullPixelValue[band] = 0.0; + theMinPixelValue[band] = OSSIM_DEFAULT_MIN_PIX_NORM_FLOAT; + theMaxPixelValue[band] = OSSIM_DEFAULT_MAX_PIX_NORM_FLOAT; + } + break; + } + case OSSIM_FLOAT32: + { + for(band = 0; band < numberOfBands; ++band) + { + theNullPixelValue[band] = OSSIM_FLT_NAN; + theMinPixelValue[band] = OSSIM_DEFAULT_MIN_PIX_FLOAT; + theMaxPixelValue[band] = OSSIM_DEFAULT_MAX_PIX_FLOAT; + } + break; + } + case OSSIM_FLOAT64: + { + for(band = 0; band < numberOfBands; ++band) + { + theNullPixelValue[band] = OSSIM_DBL_NAN; + theMinPixelValue[band] = OSSIM_DEFAULT_MIN_PIX_DOUBLE; + theMaxPixelValue[band] = OSSIM_DEFAULT_MAX_PIX_DOUBLE; + } + break; + } + case OSSIM_NORMALIZED_DOUBLE: + { + for(band = 0; band < numberOfBands; ++band) + { + theNullPixelValue[band] = 0.0; + theMinPixelValue[band] = OSSIM_DEFAULT_MIN_PIX_NORM_DOUBLE; + theMaxPixelValue[band] = OSSIM_DEFAULT_MAX_PIX_NORM_DOUBLE; + } + break; + } + default: + { + for(band = 0; band < numberOfBands; ++band) + { + theNullPixelValue[band] = 0.0; + theMinPixelValue[band] = OSSIM_DEFAULT_MIN_PIX_UCHAR; + theMaxPixelValue[band] = OSSIM_DEFAULT_MAX_PIX_UCHAR; + } + break; + } + } +} + +bool ossimImageData::isEqualTo(const ossimDataObject& rhs, + bool deepTest)const +{ + ossimImageData* rhsPtr = PTR_CAST(ossimImageData, &rhs); + if(!(&rhs)||(!rhsPtr)) return false; + bool result = ( (theScalarType == rhsPtr->theScalarType)&& + (theNumberOfDataComponents == rhsPtr->theNumberOfDataComponents)&& + (theOrigin == rhsPtr->theOrigin)&& + (getWidth() == rhsPtr->getWidth())&& + (getHeight() == rhsPtr->getHeight())); + + if(result) + { + bool test=true; + for(ossim_uint32 index = 0; index < theNumberOfDataComponents; ++index) + { + if(theMinPixelValue[index] != rhsPtr->theMinPixelValue[index]) + { + test = false; + break; + } + if(theMaxPixelValue[index] != rhsPtr->theMaxPixelValue[index]) + { + test = false; + break; + } + if(theNullPixelValue[index] != rhsPtr->theNullPixelValue[index]) + { + test = false; + break; + } + } + result = test; + } + if(deepTest&&result) + { + if(theDataBuffer && rhsPtr->theDataBuffer) + { + if(memcmp(theDataBuffer, rhsPtr->theDataBuffer, getSizeInBytes()) != 0) + { + result = false; + } + } + else if(!theDataBuffer&&!rhsPtr->theDataBuffer) + { + // nothing both are null so don't change the result. + } + else // one is null so not equal. + { + result = false; + } + } + + return result; +} + +ossimString ossimImageData::getScalarTypeAsString() const +{ + return ossimScalarTypeLut::instance()->getEntryString(getScalarType()); +} + +ossim_uint32 ossimImageData::getNumberOfBands() const +{ + return getNumberOfDataComponents(); +} + +ossim_float64 ossimImageData::getPix(const ossimIpt& position, + ossim_uint32 band) const +{ + ossimIpt relative( position.x - theOrigin.x, + position.y - theOrigin.y); + return getPix((theSpatialExtents[0])*relative.y + relative.x, band); +} + +ossim_float64 ossimImageData::getPix(ossim_uint32 offset, ossim_uint32 band) const +{ + switch(theScalarType) + { + case OSSIM_UINT8: + { + const ossim_uint8* buf = getUcharBuf(band); + if(buf) + { + return (ossim_float64)buf[offset]; + } + } + case OSSIM_SINT8: + { + const ossim_sint8* buf = static_cast<const ossim_sint8*>(getBuf(band)); + if(buf) + { + return (ossim_float64)buf[offset]; + } + } + case OSSIM_USHORT11: + case OSSIM_UINT16: + { + const ossim_uint16* buf = getUshortBuf(band); + if(buf) + { + return (ossim_float64)buf[offset]; + } + break; + } + case OSSIM_SINT16: + { + const ossim_sint16* buf = getSshortBuf(band); + if(buf) + { + return (ossim_float64)buf[offset]; + } + break; + } + case OSSIM_SINT32: + { + const ossim_sint32* buf = static_cast<const ossim_sint32*>(getBuf(band)); + if(buf) + { + return (ossim_float64)buf[offset]; + } + break; + } + case OSSIM_UINT32: + { + const ossim_uint32* buf = static_cast<const ossim_uint32*>(getBuf(band)); + if(buf) + { + return (ossim_float64)buf[offset]; + } + break; + } + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_FLOAT64: + { + const ossim_float64* buf = getDoubleBuf(band); + if(buf) + { + return (ossim_float64)buf[offset]; + } + break; + } + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT32: + { + const ossim_float32* buf = getFloatBuf(band); + if(buf) + { + return (ossim_float64)buf[offset]; + } + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + // Shouldn't hit this. + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::fill Unsupported scalar type!" + << std::endl; + } + + return 0.0; +} + +void ossimImageData::fill(ossim_uint32 band, ossim_float64 value) +{ + void* s = getBuf(band); + + if (s == NULL) return; // nothing to do... + + ossim_uint32 size_in_pixels = getWidth()*getHeight(); + + switch (getScalarType()) + { + case OSSIM_UINT8: + { + ossim_uint8* p = getUcharBuf(band); + ossim_uint8 np = static_cast<ossim_uint8>(value); + for (ossim_uint32 i=0; i<size_in_pixels; i++) p[i] = np; + + break; + } + case OSSIM_SINT8: + { + ossim_sint8* p = static_cast<ossim_sint8*>(getBuf(band)); + ossim_sint8 np = static_cast<ossim_sint8>(value); + for (ossim_uint32 i=0; i<size_in_pixels; i++) p[i] = np; + + break; + } + case OSSIM_UINT16: + case OSSIM_USHORT11: + { + ossim_uint16* p = getUshortBuf(band); + ossim_uint16 np = static_cast<ossim_uint16>(value); + for (ossim_uint32 i=0; i<size_in_pixels; i++) p[i] = np; + + break; + } + case OSSIM_SINT16: + { + ossim_sint16* p = getSshortBuf(band); + ossim_sint16 np = static_cast<ossim_sint16>(value); + for (ossim_uint32 i=0; i<size_in_pixels; i++) p[i] = np; + + break; + } + case OSSIM_UINT32: + { + ossim_uint32* p = static_cast<ossim_uint32*>(getBuf(band)); + ossim_uint32 np = static_cast<ossim_uint32>(value); + for (ossim_uint32 i=0; i<size_in_pixels; i++) p[i] = np; + + break; + } + case OSSIM_SINT32: + { + ossim_sint32* p = static_cast<ossim_sint32*>(getBuf(band)); + ossim_sint32 np = static_cast<ossim_sint32>(value); + for (ossim_uint32 i=0; i<size_in_pixels; i++) p[i] = np; + + break; + } + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT32: + { + ossim_float32* p = getFloatBuf(band); + ossim_float32 np = static_cast<ossim_float32>(value); + for (ossim_uint32 i=0; i<size_in_pixels; i++) p[i] = np; + + break; + } + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_FLOAT64: + { + ossim_float64* p = getDoubleBuf(band); + ossim_float64 np = static_cast<ossim_float64>(value); + for (ossim_uint32 i=0; i<size_in_pixels; i++) p[i] = np; + + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimImageData::makeBlank File %s line %d\n\ +Invalid scalar type: %d", + __FILE__, + __LINE__, + getScalarType()); + return; + } + + setDataObjectStatus(OSSIM_EMPTY); + +} + +void ossimImageData::fill(ossim_float64 value) +{ + ossim_uint32 valueNullCount= 0; + for(ossim_uint32 band=0; band < getNumberOfBands(); ++band) + { + if (value == theNullPixelValue[band]) + { + ++valueNullCount; + } + + fill(band, value); + } + + if (valueNullCount==0) + { + setDataObjectStatus(OSSIM_FULL); + } + else if(valueNullCount==getNumberOfBands()) + { + setDataObjectStatus(OSSIM_EMPTY); + } + else + { + setDataObjectStatus(OSSIM_PARTIAL); + } +} + +bool ossimImageData::isNull(ossim_uint32 offset)const +{ + ossim_uint32 numberOfBands = getNumberOfBands(); + ossim_uint32 band=0; + if(!getBuf()) + { + return true; + } + + switch(getScalarType()) + { + case OSSIM_UINT8: + { + for(band = 0; band < numberOfBands; ++band) + { + const ossim_uint8* buf = static_cast<const ossim_uint8*>(getBuf(band))+offset; + if((*buf) != (ossim_uint8)getNullPix(band)) + { + return false; + } + } + break; + } + case OSSIM_SINT8: + { + for(band = 0; band < numberOfBands; ++band) + { + const ossim_sint8* buf = static_cast<const ossim_sint8*>(getBuf(band))+offset; + if((*buf) != (ossim_uint8)getNullPix(band)) + { + return false; + } + } + break; + } + case OSSIM_UINT16: + case OSSIM_USHORT11: + { + for(band = 0; band < numberOfBands; band++) + { + const ossim_uint16* buf = static_cast<const ossim_uint16*>(getBuf(band))+offset; + if((*buf) != (ossim_uint16)getNullPix(band)) + { + return false; + } + } + break; + } + case OSSIM_SINT16: + { + for(band = 0; band < numberOfBands; band++) + { + const ossim_sint16* buf = static_cast<const ossim_sint16*>(getBuf(band))+offset; + if((*buf) != (ossim_sint16)getNullPix(band)) + { + return false; + } + } + break; + } + case OSSIM_UINT32: + { + for(band = 0; band < numberOfBands; band++) + { + const ossim_uint32* buf = static_cast<const ossim_uint32*>(getBuf(band))+offset; + if((*buf) != (ossim_uint32)getNullPix(band)) + { + return false; + } + } + break; + } + case OSSIM_SINT32: + { + for(band = 0; band < numberOfBands; band++) + { + const ossim_sint32* buf = static_cast<const ossim_sint32*>(getBuf(band))+offset; + if((*buf) != (ossim_sint32)getNullPix(band)) + { + return false; + } + } + break; + } + case OSSIM_NORMALIZED_FLOAT: + { + for(band = 0; band < numberOfBands; band++) + { + const ossim_float32* buf = static_cast<const ossim_float32*>(getBuf(band))+offset; + if((*buf) != 0.0) + { + return false; + } + } + break; + } + case OSSIM_FLOAT32: + { + for(band = 0; band < numberOfBands; band++) + { + const ossim_float32* buf = static_cast<const ossim_float32*>(getBuf(band))+offset; + if((*buf) != (ossim_float32)getNullPix(band)) + { + return false; + } + } + break; + } + case OSSIM_NORMALIZED_DOUBLE: + { + for(band = 0; band < numberOfBands; band++) + { + const ossim_float64* buf = static_cast<const ossim_float64*>(getBuf(band))+offset; + if((*buf) != 0.0) + { + return false; + } + } + break; + } + case OSSIM_FLOAT64: + { + for(band = 0; band < numberOfBands; band++) + { + const ossim_float64* buf = static_cast<const ossim_float64*>(getBuf(band))+offset; + if((*buf) != getNullPix(band)) + { + return false; + } + } + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + //ERROR + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::isNull Unsupported scalar type!" + << std::endl; + } + } + return true; +} + +bool ossimImageData::isNull(ossim_uint32 offset, ossim_uint32 band)const +{ + switch(getScalarType()) + { + case OSSIM_UINT8: + { + const ossim_uint8* buf = + static_cast<const ossim_uint8*>(getBuf(band))+offset; + + if((*buf) != (ossim_uint8)getNullPix(band)) + { + return false; + } + break; + } + case OSSIM_SINT8: + { + const ossim_sint8* buf = + static_cast<const ossim_sint8*>(getBuf(band))+offset; + + if((*buf) != (ossim_sint8)getNullPix(band)) + { + return false; + } + break; + } + case OSSIM_UINT16: + case OSSIM_USHORT11: + { + const ossim_uint16* buf = + static_cast<const ossim_uint16*>(getBuf(band))+offset; + if((*buf) != (ossim_uint16)getNullPix(band)) + { + return false; + } + break; + } + case OSSIM_SINT16: + { + const ossim_sint16* buf = + static_cast<const ossim_sint16*>(getBuf(band))+offset; + if((*buf) != (ossim_sint16)getNullPix(band)) + { + return false; + } + break; + } + case OSSIM_UINT32: + { + const ossim_uint32* buf = + static_cast<const ossim_uint32*>(getBuf(band))+offset; + if((*buf) != (ossim_uint32)getNullPix(band)) + { + return false; + } + break; + } + case OSSIM_SINT32: + { + const ossim_sint32* buf = + static_cast<const ossim_sint32*>(getBuf(band))+offset; + if((*buf) != (ossim_sint32)getNullPix(band)) + { + return false; + } + break; + } + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT32: + { + const ossim_float32* buf = static_cast<const ossim_float32*>(getBuf(band))+offset; + if((*buf) != (ossim_float32)getNullPix(band)) + { + return false; + } + break; + } + case OSSIM_FLOAT64: + case OSSIM_NORMALIZED_DOUBLE: + { + const ossim_float64* buf = static_cast<const ossim_float64*>(getBuf(band))+offset; + if((*buf) != getNullPix(band)) + { + return false; + } + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + //ERROR + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::isNull Unsupported scalar type!" + << std::endl; + } + } + return true; +} + +bool ossimImageData::isNull(const ossimIpt& pt)const +{ + ossim_int32 xNew = (pt.x - theOrigin.x); + ossim_int32 yNew = (pt.y - theOrigin.y); + if(xNew < 0 || xNew >= (int)theSpatialExtents[0] || + yNew < 0 || yNew >= (int)theSpatialExtents[1]) + { + return true; + } + ossim_uint32 offset = getWidth()*yNew + xNew; + + return isNull(offset); +} + +bool ossimImageData::isNull(const ossimIpt& pt, ossim_uint32 band)const +{ + ossim_int32 xNew = (pt.x - theOrigin.x); + ossim_int32 yNew = (pt.y - theOrigin.y); + if(xNew < 0 || xNew >= (int)theSpatialExtents[0] || + yNew < 0 || yNew >= (int)theSpatialExtents[1]) + { + return true; + } + ossim_uint32 offset = getWidth()*yNew + xNew; + + return isNull(offset, band); +} + +void ossimImageData::setNull(ossim_uint32 offset) +{ + ossim_uint32 numberOfBands = getNumberOfBands(); + ossim_uint32 band=0; + switch(getScalarType()) + { + case OSSIM_UINT8: + { + for(band = 0; band < numberOfBands; ++band) + { + ossim_uint8* buf = static_cast<ossim_uint8*>(getBuf(band))+offset; + *buf = (ossim_uint8)getNullPix(band); + } + break; + } + case OSSIM_SINT8: + { + for(band = 0; band < numberOfBands; ++band) + { + ossim_sint8* buf = static_cast<ossim_sint8*>(getBuf(band))+offset; + *buf = (ossim_sint8)getNullPix(band); + } + break; + } + case OSSIM_UINT16: + case OSSIM_USHORT11: + { + for(band = 0; band < numberOfBands; band++) + { + ossim_uint16* buf = static_cast<ossim_uint16*>(getBuf(band))+ + offset; + *buf = (ossim_uint16)getNullPix(band); + } + break; + } + case OSSIM_SINT16: + { + for(band = 0; band < numberOfBands; band++) + { + ossim_sint16* buf = static_cast<ossim_sint16*>(getBuf(band))+ + offset; + *buf = (ossim_sint16)getNullPix(band); + } + break; + } + case OSSIM_UINT32: + { + for(band = 0; band < numberOfBands; band++) + { + ossim_uint32* buf = static_cast<ossim_uint32*>(getBuf(band))+ + offset; + *buf = (ossim_uint32)getNullPix(band); + } + break; + } + case OSSIM_SINT32: + { + for(band = 0; band < numberOfBands; band++) + { + ossim_sint32* buf = static_cast<ossim_sint32*>(getBuf(band))+ + offset; + *buf = (ossim_sint32)getNullPix(band); + } + break; + } + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT32: + { + for(band = 0; band < numberOfBands; band++) + { + ossim_float32* buf = static_cast<ossim_float32*>(getBuf(band))+offset; + *buf = (ossim_float32)getNullPix(band); + } + break; + } + case OSSIM_FLOAT64: + case OSSIM_NORMALIZED_DOUBLE: + { + for(band = 0; band < numberOfBands; band++) + { + ossim_float64* buf = static_cast<ossim_float64*>(getBuf(band))+offset; + *buf = getNullPix(band); + } + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + //ERROR + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::isNull Unsupported scalar type!" + << std::endl; + } + } +} + +void ossimImageData::setNull(ossim_uint32 offset, ossim_uint32 band) +{ + switch(getScalarType()) + { + case OSSIM_UINT8: + { + ossim_uint8* buf = static_cast<ossim_uint8*>(getBuf(band))+offset; + *buf = (ossim_uint8)getNullPix(band); + break; + } + case OSSIM_SINT8: + { + ossim_sint8* buf = static_cast<ossim_sint8*>(getBuf(band))+offset; + *buf = (ossim_sint8)getNullPix(band); + break; + } + case OSSIM_UINT16: + case OSSIM_USHORT11: + { + ossim_uint16* buf = static_cast<ossim_uint16*>(getBuf(band))+offset; + *buf = (ossim_uint16)getNullPix(band); + break; + } + case OSSIM_SINT16: + { + ossim_sint16* buf = static_cast<ossim_sint16*>(getBuf(band))+offset; + *buf = (ossim_sint16)getNullPix(band); + break; + } + case OSSIM_UINT32: + { + ossim_uint32* buf = static_cast<ossim_uint32*>(getBuf(band))+offset; + *buf = (ossim_uint32)getNullPix(band); + break; + } + case OSSIM_SINT32: + { + ossim_sint32* buf = static_cast<ossim_sint32*>(getBuf(band))+offset; + *buf = (ossim_sint32)getNullPix(band); + break; + } + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT32: + { + ossim_float32* buf = static_cast<ossim_float32*>(getBuf(band))+offset; + *buf = (ossim_float32)getNullPix(band); + break; + } + case OSSIM_FLOAT64: + case OSSIM_NORMALIZED_DOUBLE: + { + ossim_float64* buf = static_cast<ossim_float64*>(getBuf(band))+offset; + *buf = getNullPix(band); + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + //ERROR + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::isNull Unsupported scalar type!" + << std::endl; + } + } +} + +void ossimImageData::setNull(const ossimIpt& pt) +{ + ossim_int32 xNew = (pt.x - theOrigin.x); + ossim_int32 yNew = (pt.y - theOrigin.y); + + if(xNew < 0 || xNew >= (int)theSpatialExtents[0] || + yNew < 0 || yNew >= (int)theSpatialExtents[1]) + { + return; + } + ossim_uint32 offset = ((int)getWidth())*yNew + xNew; + + setNull(offset); +} + +void ossimImageData::setNull(const ossimIpt& pt, ossim_uint32 band) +{ + ossim_int32 xNew = (pt.x - theOrigin.x); + ossim_int32 yNew = (pt.y - theOrigin.y); + + if(xNew < 0 || xNew >= (int)theSpatialExtents[0] || + yNew < 0 || yNew >= (int)theSpatialExtents[1]) + { + return; + } + ossim_uint32 offset = ((int)getWidth())*yNew + xNew; + + setNull(offset, band); +} + +void ossimImageData::setNullPix(ossim_float64 null_pix) +{ + if(!theNullPixelValue) initializeDefaults(); + if(!theNullPixelValue) return; + ossim_uint32 num = getNumberOfBands(); + for(ossim_uint32 band = 0; band < num; ++band) + { + theNullPixelValue[band] = null_pix; + } +} + +void ossimImageData::setNullPix(ossim_float64 null_pix, ossim_uint32 band) +{ + if(!theNullPixelValue) initializeDefaults(); + if(!theNullPixelValue) return; + theNullPixelValue[band] = null_pix; +} + +void ossimImageData::setNullPix(const ossim_float64* nullPixArray, ossim_uint32 numberOfValues) +{ + if(!nullPixArray) return; + if(!theNullPixelValue) initializeDefaults(); + if(!theNullPixelValue) return; + for(ossim_uint32 band = 0; + (band < numberOfValues)&&(band < theNumberOfDataComponents); ++band) + { + theNullPixelValue[band] = nullPixArray[band]; + } +} + +void ossimImageData::setMinPix(ossim_float64 min_pix, ossim_uint32 band) +{ + if(!theMinPixelValue) initializeDefaults(); + if(!theMinPixelValue) return; + theMinPixelValue[band] = min_pix; +} + +void ossimImageData::setMinPix(const ossim_float64* minPixArray, ossim_uint32 numberOfValues) +{ + if(!minPixArray) return; + if(!theMinPixelValue) initializeDefaults(); + if(!theMinPixelValue) return; + for(ossim_uint32 band = 0; (band < numberOfValues)&&(band < theNumberOfDataComponents); ++band) + { + theMinPixelValue[band] = minPixArray[band]; + } +} + +void ossimImageData::setMinPix(ossim_float64 min_pix) +{ + if(!theMinPixelValue) initializeDefaults(); + if(!theMinPixelValue) return; + ossim_uint32 num = getNumberOfBands(); + for(ossim_uint32 band = 0; band < num; ++band) + { + theMinPixelValue[band] = min_pix; + } +} + +void ossimImageData::setMaxPix(ossim_float64 max_pix) +{ + if(!theMaxPixelValue) initializeDefaults(); + if(!theMaxPixelValue) return; + ossim_uint32 num = getNumberOfBands(); + for(ossim_uint32 band = 0; band < num; ++band) + { + theMaxPixelValue[band] = max_pix; + } +} + +void ossimImageData::setMaxPix(ossim_float64 max_pix, ossim_uint32 band) +{ + if(!theMaxPixelValue) initializeDefaults(); + if(!theMaxPixelValue) return; + theMaxPixelValue[band] = max_pix; +} + +void ossimImageData::setMaxPix(const ossim_float64* maxPixArray, ossim_uint32 numberOfValues) +{ + if(!maxPixArray) return; + if(!theMaxPixelValue) initializeDefaults(); + if(!theMaxPixelValue) return; + for(ossim_uint32 band = 0; (band < numberOfValues)&&(band < theNumberOfDataComponents); ++band) + { + theMaxPixelValue[band] = maxPixArray[band]; + } +} + +void ossimImageData::setNumberOfBands(ossim_uint32 bands, + bool reallocate) +{ + ossim_uint32 b = getNumberOfBands(); + if((b != bands)&& + bands&& + theNullPixelValue&& + theMinPixelValue&& + theMaxPixelValue) + { + setNumberOfDataComponents(bands); + if(reallocate) + { + ossimRectilinearDataObject::initialize(); + } + + ossim_uint32 minBands = ossimMin(b, bands); + ossim_float64 *newNull = new ossim_float64[bands]; + ossim_float64 *newMin = new ossim_float64[bands]; + ossim_float64 *newMax = new ossim_float64[bands]; + + std::copy(theNullPixelValue, + theNullPixelValue + minBands, + newNull); + std::copy(theMinPixelValue, + theMinPixelValue + minBands, + newMin); + std::copy(theMaxPixelValue, + theMaxPixelValue + minBands, + newMax); + + if(bands > minBands) + { + std::fill(newNull+minBands, + newNull+bands, + theNullPixelValue[b - 1]); + std::fill(newMin+minBands, + newMin+bands, + theMinPixelValue[b - 1]); + std::fill(newMax+minBands, + newMax+bands, + theMaxPixelValue[b - 1]); + } + + delete [] theNullPixelValue; + delete [] theMinPixelValue; + delete [] theMaxPixelValue; + + theNullPixelValue = newNull; + theMinPixelValue = newMin; + theMaxPixelValue = newMax; + + } +} + +void ossimImageData::setImageRectangleAndBands(const ossimIrect& rect, + ossim_uint32 numberOfBands) +{ + if(rect.hasNans()) + { + return; + } + + ossim_uint32 bands = getNumberOfBands(); + ossim_uint32 w = getWidth(); + ossim_uint32 h = getHeight(); + ossim_uint32 nw = rect.width(); + ossim_uint32 nh = rect.height(); + + setOrigin(rect.ul()); + setWidthHeight(nw, nh); + setNumberOfBands(numberOfBands, false); + + // we will try to be non destructive on the resize of the number of bands + if( ( (w*h != nw*nh) || ( bands != numberOfBands) ) && + (theDataObjectStatus != OSSIM_NULL) ) + { + initialize(); + } +} + +void ossimImageData::setImageRectangle(const ossimIrect& rect) +{ + if(rect.hasNans()) + { + return; + } + + ossim_uint32 w = getWidth(); + ossim_uint32 h = getHeight(); + ossim_uint32 nw = rect.width(); + ossim_uint32 nh = rect.height(); + + setOrigin(rect.ul()); + setWidthHeight(nw, nh); + + // we will try to be non destructive on the resize of the number of bands + if ( (w*h != nw*nh) && (theDataObjectStatus != OSSIM_NULL) ) + { + initialize(); + } +} + +void ossimImageData::assign(const ossimDataObject* data) +{ + if(!data) return; + ossimImageData* d = PTR_CAST(ossimImageData, data); + if(d) + { + assign(d); + } +} + +void ossimImageData::assign(const ossimImageData* data) +{ + ossimSource* tmp_owner = getOwner(); + + ossimRectilinearDataObject::assign(data); + + //*** + // The data member "theSource" will be overwritten so capture it and then + // set it back. + //*** + setOwner(tmp_owner); + + if(this != data) + { + if(theMinPixelValue) + { + delete [] theMinPixelValue; + theMinPixelValue = NULL; + } + if(theMaxPixelValue) + { + delete [] theMaxPixelValue; + theMaxPixelValue = NULL; + } + if(theNullPixelValue) + { + delete [] theNullPixelValue; + theNullPixelValue = NULL; + } + ossim_uint32 numberOfBands = getNumberOfBands(); + if(!numberOfBands) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::assign\n" + << "Number of components is 0, can't assign" << std::endl; + return; + } + theOrigin = data->theOrigin; + theMinPixelValue = new ossim_float64[numberOfBands]; + theMaxPixelValue = new ossim_float64[numberOfBands]; + theNullPixelValue = new ossim_float64[numberOfBands]; + if(data->theMinPixelValue&& + data->theMaxPixelValue&& + data->theNullPixelValue) + { + for(ossim_uint32 band = 0; band < numberOfBands; ++band) + { + theMinPixelValue[band] = data->theMinPixelValue[band]; + theMaxPixelValue[band] = data->theMaxPixelValue[band]; + theNullPixelValue[band] = data->theNullPixelValue[band]; + } + } + else + { + initializeDefaults(); + } + } +} + +void ossimImageData::assignBand(const ossimImageData* data, + ossim_uint32 source_band, + ossim_uint32 output_band) +{ + //*** + // This method requires this image data to be initialized to the same + // size as the source data being copied. + //*** + + // Some basic error checking... + if ( !data->isValidBand(source_band) ) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::assignBand ERROR:" + << "\nInvalid source band!" << std::endl; + return; + } + if ( !isValidBand(output_band) ) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::assignBand ERROR:" + << "\nInvalid output band!" << std::endl; + return; + } + if (data->getDataObjectStatus() == OSSIM_NULL) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::assignBand ERROR:" + << "\nSource data status is null!" << std::endl; + return; + } + if (getDataObjectStatus() == OSSIM_NULL) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::assignBand ERROR:" + << "\nThis status is null!" << std::endl; + return; + } + + //*** + // Make sure this buffer is the same size; if not, return. + //*** + ossim_uint32 source_size = data->getSizePerBandInBytes(); + + if ( source_size != getSizePerBandInBytes() ) + { + return; + } + + // Get the pointers to the bands. + const void* s = data->getBuf(source_band); + void* d = getBuf(output_band); + + // One last check. + if (s == NULL || d == NULL) + { + return; + } + + // Ok copy the image data... + memcpy(d, s, source_size); +} + +void ossimImageData::loadBand(const void* src, + const ossimIrect& src_rect, + ossim_uint32 band) +{ + // Call the appropriate load method. + switch (getScalarType()) + { + case OSSIM_UINT8: + loadBand(ossim_uint8(0), src, src_rect, band); + return; + + case OSSIM_SINT8: + loadBand(ossim_sint8(0), src, src_rect, band); + return; + + case OSSIM_UINT16: + case OSSIM_USHORT11: + loadBand(ossim_uint16(0), src, src_rect, band); + return; + + case OSSIM_SINT16: + loadBand(ossim_sint16(0), src, src_rect, band); + return; + + case OSSIM_UINT32: + loadBand(ossim_uint32(0), src, src_rect, band); + return; + + case OSSIM_SINT32: + loadBand(ossim_sint32(0), src, src_rect, band); + return; + + case OSSIM_FLOAT32: + case OSSIM_NORMALIZED_FLOAT: + loadBand(ossim_float32(0), src, src_rect, band); + return; + + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_FLOAT64: + loadBand(ossim_float64(0), src, src_rect, band); + return; + + case OSSIM_SCALAR_UNKNOWN: + default: + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimImageData::loadBand\n\ +File %s line %d\nUnknown scalar type!", + __FILE__, + __LINE__); + return; + } +} + +void ossimImageData::loadBand(const void* src, + const ossimIrect& src_rect, + const ossimIrect& clip_rect, + ossim_uint32 band) +{ + // Call the appropriate load method. + switch (getScalarType()) + { + case OSSIM_UINT8: + loadBand(ossim_uint8(0), src, src_rect, clip_rect, band); + return; + + case OSSIM_SINT8: + loadBand(ossim_sint8(0), src, src_rect, clip_rect, band); + return; + + case OSSIM_UINT16: + case OSSIM_USHORT11: + loadBand(ossim_uint16(0), src, src_rect, clip_rect, band); + return; + + case OSSIM_SINT16: + loadBand(ossim_sint16(0), src, src_rect, clip_rect, band); + return; + + case OSSIM_UINT32: + loadBand(ossim_uint32(0), src, src_rect, clip_rect, band); + return; + + case OSSIM_SINT32: + loadBand(ossim_sint32(0), src, src_rect, clip_rect, band); + return; + + case OSSIM_FLOAT32: + case OSSIM_NORMALIZED_FLOAT: + loadBand(ossim_float32(0), src, src_rect, clip_rect, band); + return; + + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_FLOAT64: + loadBand(ossim_float64(0), src, src_rect, clip_rect, band); + return; + + case OSSIM_SCALAR_UNKNOWN: + default: + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimImageData::loadBand\n\ +File %s line %d\nUnknown scalar type!", + __FILE__, + __LINE__); + return; + } +} + +template <class T> void ossimImageData::loadBand(T, // dummy template variable + const void* src, + const ossimIrect& src_rect, + ossim_uint32 band) +{ + const ossimIrect img_rect = getImageRectangle(); + + // Get the clip rect. + const ossimIrect clip_rect = img_rect.clipToRect(src_rect); + + + loadBand(T(0), src, src_rect, clip_rect, band); +} + +template <class T> void ossimImageData::loadBand(T, // dummy template variable + const void* src, + const ossimIrect& src_rect, + const ossimIrect& clip_rect, + ossim_uint32 band) +{ + static const char MODULE[] = "ossimImageData::loadBand"; + + // Check the pointer. + if (!src) + { + // Set the error... + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "%s File %s line %d\nNULL pointer passed to method!", + MODULE, + __FILE__, + __LINE__); + return; + } + + // Check the band. + if (!isValidBand(band)) + { + // Set the error... + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "%s File %s line %d\nInvalid band: %d", + MODULE, + __FILE__, + __LINE__, + band); + return; + } + + const ossimIrect img_rect = getImageRectangle(); + + // Check for intersect. + if ( ! img_rect.intersects(src_rect) ) + { +// cerr <<"Doing nothing" << std::endl; + return; // Nothing to do here. + } + + // Check the clip rect. + if (!clip_rect.completely_within(img_rect)) + { +// cerr << MODULE +// << " ERROR: clip rect does not fall within tile rect!" +// << std::endl; + return; + } + + // Check the status and allocate memory if needed. + if (getDataObjectStatus() == OSSIM_NULL) initialize(); + + // Get the width of the buffers. + ossim_uint32 s_width = src_rect.width(); + ossim_uint32 d_width = getWidth(); + + const T* s = static_cast<const T*>(src); + T* d = static_cast<T*>(getBuf(band)); + + // Move the pointers to the first valid pixel. + s += (clip_rect.ul().y - src_rect.ul().y) * s_width + + clip_rect.ul().x - src_rect.ul().x; + + d += (clip_rect.ul().y - img_rect.ul().y) * d_width + + clip_rect.ul().x - img_rect.ul().x; + + // Copy the data. + ossim_uint32 clipHeight = clip_rect.height(); + ossim_uint32 clipWidth = clip_rect.width(); + + for (ossim_uint32 line = 0; line < clipHeight; ++line) + { + for (ossim_uint32 sample = 0; sample < clipWidth; ++sample) + { + d[sample] = s[sample]; + } + + s += s_width; + d += d_width; + } +} + +void ossimImageData::loadTile(const ossimImageData* src) +{ + if (!src) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::loadTile ERROR:" + << "Null tile passed to method!" << std::endl; + return; + } + + if (!src->getBuf()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::loadTile ERROR:" + << "Source tile buff is null!" << std::endl; + return; + } + + if (!this->getBuf()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::loadTile ERROR:" + << "This tile not initialized!" << std::endl; + return; + } + + if (src->getNumberOfBands() != this->getNumberOfBands()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::loadTile ERROR:" + << "Tiles do not have same number of bands!" << std::endl; + return; + } + + //*** + // Set the status of this tile to the status of the source tile. + // Do this in place of validate. + //*** + setDataObjectStatus(src->getDataObjectStatus()); + + if(getScalarType() == src->getScalarType()) + { + loadTile((void*)(src->getBuf()), + src->getImageRectangle(), + OSSIM_BSQ); + setNullPix(src->getNullPix(), src->getNumberOfBands()); + } + else // do a slow generic normalize to unnormalize copy + { + // Check the pointer. + ossimIrect src_rect = src->getImageRectangle(); + const ossimIrect img_rect = getImageRectangle(); + + // Check for intersect. + if ( !img_rect.intersects(src_rect) ) + { + return; // Nothing to do here. + } + + // Get the clip rect. + const ossimIrect clip_rect = img_rect.clipToRect(src_rect); + + // Check the status and allocate memory if needed. + if (getDataObjectStatus() == OSSIM_NULL) initialize(); + + // Get the width of the buffers. + ossim_uint32 num_bands = getNumberOfBands(); + ossim_uint32 s_width = src_rect.width(); + ossim_uint32 d_width = getWidth(); + + ossim_uint32 band; + + ossim_uint32 sourceOffset = (clip_rect.ul().y - src_rect.ul().y) * + s_width + (clip_rect.ul().x - src_rect.ul().x); + + ossim_uint32 destinationOffset = (clip_rect.ul().y - img_rect.ul().y) * + d_width + (clip_rect.ul().x - img_rect.ul().x); + + ossim_uint32 clipHeight = clip_rect.height(); + ossim_uint32 clipWidth = clip_rect.width(); + + // Copy the data. + for (band=0; band<num_bands; ++band) + { + ossim_uint32 sourceIndex = sourceOffset; + ossim_uint32 destinationIndex = destinationOffset; + ossim_float32 tempResult = 0.0; + + for (ossim_uint32 line = 0; line < clipHeight; ++line) + { + for (ossim_uint32 sample = 0; sample < clipWidth; ++sample) + { + src->getNormalizedFloat(sourceIndex + sample, + band, + tempResult); + + this->setNormalizedFloat(destinationIndex + sample, + band, + tempResult); + } + sourceIndex += s_width; + destinationIndex += d_width; + } + } + } +} + +void ossimImageData::loadTile(const void* src, + const ossimIrect& src_rect, + ossimInterleaveType il_type) +{ + switch (il_type) + { + case OSSIM_BIP: + loadTileFromBip(src, src_rect); + return; + case OSSIM_BIL: + loadTileFromBil(src, src_rect); + return; + case OSSIM_BSQ: + loadTileFromBsq(src, src_rect); + return; + default: + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::loadTile ERROR: unsupported interleave type!" + << std::endl; + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimImageData::loadTile\n\ +File %s line %d\nUnknown interleave type!", + __FILE__, + __LINE__); + return; + } // End of "switch (type)" +} + +void ossimImageData::loadTile(const void* src, + const ossimIrect& src_rect, + const ossimIrect& clip_rect, + ossimInterleaveType il_type) +{ + switch (il_type) + { + case OSSIM_BIP: + loadTileFromBip(src, src_rect, clip_rect); + return; + case OSSIM_BIL: + loadTileFromBil(src, src_rect, clip_rect); + return; + case OSSIM_BSQ: + loadTileFromBsq(src, src_rect, clip_rect); + return; + default: + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::loadTile ERROR: unsupported interleave type!" + << std::endl; + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimImageData::loadTile\n\ +File %s line %d\nUnknown interleave type!", + __FILE__, + __LINE__); + return; + } // End of "switch (type)" +} + +void ossimImageData::loadTileFromBip(const void* src, + const ossimIrect& src_rect) +{ + switch (getScalarType()) + { + case OSSIM_UINT8: + loadTileFromBip(ossim_uint8(0), src, src_rect); + return; + + case OSSIM_SINT8: + loadTileFromBip(ossim_sint8(0), src, src_rect); + return; + + case OSSIM_UINT16: + case OSSIM_USHORT11: + loadTileFromBip(ossim_uint16(0), src, src_rect); + return; + + case OSSIM_SINT16: + loadTileFromBip(ossim_sint16(0), src, src_rect); + return; + + case OSSIM_UINT32: + loadTileFromBip(ossim_uint32(0), src, src_rect); + return; + + case OSSIM_SINT32: + loadTileFromBip(ossim_sint32(0), src, src_rect); + return; + + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT32: + loadTileFromBip(ossim_float32(0), src, src_rect); + return; + + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_FLOAT64: + loadTileFromBip(ossim_float64(0), src, src_rect); + return; + + case OSSIM_SCALAR_UNKNOWN: + default: + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimImageData::loadTileFromBip\n\ +File %s line %d\nUnsupported scalar type for method!", + __FILE__, + __LINE__); + return; + } +} + +void ossimImageData::loadTileFromBip(const void* src, + const ossimIrect& src_rect, + const ossimIrect& clip_rect) +{ + switch (getScalarType()) + { + case OSSIM_UINT8: + loadTileFromBip(ossim_uint8(0), src, src_rect, clip_rect); + return; + + case OSSIM_SINT8: + loadTileFromBip(ossim_sint8(0), src, src_rect, clip_rect); + return; + + case OSSIM_UINT16: + case OSSIM_USHORT11: + loadTileFromBip(ossim_uint16(0), src, src_rect, clip_rect); + return; + + case OSSIM_SINT16: + loadTileFromBip(ossim_sint16(0), src, src_rect, clip_rect); + return; + + case OSSIM_UINT32: + loadTileFromBip(ossim_uint32(0), src, src_rect, clip_rect); + return; + + case OSSIM_SINT32: + loadTileFromBip(ossim_sint32(0), src, src_rect, clip_rect); + return; + + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT32: + loadTileFromBip(ossim_float32(0), src, src_rect, clip_rect); + return; + + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_FLOAT64: + loadTileFromBip(ossim_float64(0), src, src_rect, clip_rect); + return; + + case OSSIM_SCALAR_UNKNOWN: + default: + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimImageData::loadTileFromBip\n\ +File %s line %d\nUnsupported scalar type for method!", + __FILE__, + __LINE__); + return; + } +} + +void ossimImageData::loadTileFromBil(const void* src, + const ossimIrect& src_rect) +{ + switch (getScalarType()) + { + case OSSIM_UINT8: + loadTileFromBil(ossim_uint8(0), src, src_rect); + return; + + case OSSIM_SINT8: + loadTileFromBil(ossim_sint8(0), src, src_rect); + return; + + case OSSIM_UINT16: + case OSSIM_USHORT11: + loadTileFromBil(ossim_uint16(0), src, src_rect); + return; + + case OSSIM_SINT16: + loadTileFromBil(ossim_sint16(0), src, src_rect); + return; + + case OSSIM_UINT32: + loadTileFromBil(ossim_uint32(0), src, src_rect); + return; + + case OSSIM_SINT32: + loadTileFromBil(ossim_sint32(0), src, src_rect); + return; + + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT32: + loadTileFromBil(ossim_float32(0), src, src_rect); + return; + + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_FLOAT64: + loadTileFromBil(ossim_float64(0), src, src_rect); + return; + + case OSSIM_SCALAR_UNKNOWN: + default: + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimImageData::loadTileFromBil\n\ +File %s line %d\nUnsupported scalar type for method!", + __FILE__, + __LINE__); + return; + } +} + +void ossimImageData::loadTileFromBil(const void* src, + const ossimIrect& src_rect, + const ossimIrect& clip_rect) +{ + switch (getScalarType()) + { + case OSSIM_UINT8: + loadTileFromBil(ossim_uint8(0), src, src_rect, clip_rect); + return; + + case OSSIM_SINT8: + loadTileFromBil(ossim_sint8(0), src, src_rect, clip_rect); + return; + + case OSSIM_UINT16: + case OSSIM_USHORT11: + loadTileFromBil(ossim_uint16(0), src, src_rect, clip_rect); + return; + + case OSSIM_SINT16: + loadTileFromBil(ossim_sint16(0), src, src_rect, clip_rect); + return; + + case OSSIM_UINT32: + loadTileFromBil(ossim_uint32(0), src, src_rect, clip_rect); + return; + + case OSSIM_SINT32: + loadTileFromBil(ossim_sint32(0), src, src_rect, clip_rect); + return; + + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT32: + loadTileFromBil(ossim_float32(0), src, src_rect, clip_rect); + return; + + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_FLOAT64: + loadTileFromBil(ossim_float64(0), src, src_rect, clip_rect); + return; + + case OSSIM_SCALAR_UNKNOWN: + default: + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimImageData::loadTileFromBil\n\ +File %s line %d\nUnsupported scalar type for method!", + __FILE__, + __LINE__); + return; + } +} + +void ossimImageData::loadTileFromBsq(const void* src, + const ossimIrect& src_rect) +{ + switch (getScalarType()) + { + case OSSIM_UINT8: + loadTileFromBsq(ossim_uint8(0), src, src_rect); + return; + + case OSSIM_SINT8: + loadTileFromBsq(ossim_sint8(0), src, src_rect); + return; + + case OSSIM_UINT16: + case OSSIM_USHORT11: + loadTileFromBsq(ossim_uint16(0), src, src_rect); + return; + + case OSSIM_SINT16: + loadTileFromBsq(ossim_sint16(0), src, src_rect); + return; + + case OSSIM_UINT32: + loadTileFromBsq(ossim_uint32(0), src, src_rect); + return; + + case OSSIM_SINT32: + loadTileFromBsq(ossim_sint32(0), src, src_rect); + return; + + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT32: + loadTileFromBsq(ossim_float32(0), src, src_rect); + return; + + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_FLOAT64: + loadTileFromBsq(ossim_float64(0), src, src_rect); + return; + + case OSSIM_SCALAR_UNKNOWN: + default: + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimImageData::loadTileFromBsq\n\ +File %s line %d\nUnsupported scalar type for method!", + __FILE__, + __LINE__); + return; + } +} + +void ossimImageData::loadTileFromBsq(const void* src, + const ossimIrect& src_rect, + const ossimIrect& clip_rect) +{ + switch (getScalarType()) + { + case OSSIM_UINT8: + loadTileFromBsq(ossim_uint8(0), src, src_rect, clip_rect); + return; + + case OSSIM_SINT8: + loadTileFromBsq(ossim_sint8(0), src, src_rect, clip_rect); + return; + + case OSSIM_UINT16: + case OSSIM_USHORT11: + loadTileFromBsq(ossim_uint16(0), src, src_rect, clip_rect); + return; + + case OSSIM_SINT16: + loadTileFromBsq(ossim_sint16(0), src, src_rect, clip_rect); + return; + + case OSSIM_UINT32: + loadTileFromBsq(ossim_uint32(0), src, src_rect, clip_rect); + return; + + case OSSIM_SINT32: + loadTileFromBsq(ossim_sint32(0), src, src_rect, clip_rect); + return; + + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT32: + loadTileFromBsq(ossim_float32(0), src, src_rect, clip_rect); + return; + + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_FLOAT64: + loadTileFromBsq(ossim_float64(0), src, src_rect, clip_rect); + return; + + case OSSIM_SCALAR_UNKNOWN: + default: + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimImageData::loadTileFromBsq\n\ +File %s line %d\nUnsupported scalar type for method!", + __FILE__, + __LINE__); + return; + } +} + + +void ossimImageData::computeMinMaxPix(vector<ossim_float64>& minBands, + vector<ossim_float64>& maxBands) +{ + if ( (getDataObjectStatus() == OSSIM_NULL) || + (getDataObjectStatus() == OSSIM_EMPTY) ) + { + return; + } + + switch(theScalarType) + { + case OSSIM_UINT8: + { + computeMinMaxPix((ossim_uint8)0, + minBands, + maxBands); + break; + } + case OSSIM_SINT8: + { + computeMinMaxPix((ossim_sint8)0, + minBands, + maxBands); + break; + + } + case OSSIM_USHORT11: + case OSSIM_UINT16: + { + computeMinMaxPix((ossim_uint16)0, + minBands, + maxBands); + break; + } + case OSSIM_SINT16: + { + computeMinMaxPix((ossim_sint16)0, + minBands, + maxBands); + break; + } + case OSSIM_UINT32: + { + computeMinMaxPix((ossim_uint32)0, + minBands, + maxBands); + break; + } + case OSSIM_SINT32: + { + computeMinMaxPix((ossim_sint32)0, + minBands, + maxBands); + break; + } + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT32: + { + computeMinMaxPix((ossim_float32)0.0, + minBands, + maxBands); + break; + } + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_FLOAT64: + { + computeMinMaxPix((ossim_float64)0.0, + minBands, + maxBands); + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + // Shouldn't hit this. + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::computeMinPix Unsupported scalar type!" + << std::endl; + break; + } + } +} + +template <class T> +void ossimImageData::computeMinMaxPix(T dummyValue, + vector<ossim_float64>& minBands, + vector<ossim_float64>& maxBands) +{ + const ossim_uint32 BANDS = getNumberOfBands(); + const ossim_uint32 SPB = getSizePerBand(); + + if( minBands.size() != BANDS || + maxBands.size() != BANDS ) + { + minBands.resize(BANDS); + maxBands.resize(BANDS); + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + // Set min to max and max to min for starters. + minBands[band] = getMaxPix(band); + maxBands[band] = getMinPix(band); + } + } + + for(ossim_uint32 band = 0; band < BANDS; ++band) + { + const T* bandBuffer = (const T*)getBuf(band); + if(bandBuffer) + { + const T NP = static_cast<T>(getNullPix(band)); + ossim_float64 currentMin = minBands[band]; + ossim_float64 currentMax = maxBands[band]; + for(ossim_uint32 offset = 0; offset < SPB; ++offset) + { + T p = bandBuffer[offset]; + if(p != NP) + { + if(p < currentMin) + { + currentMin = p; + } + else if(p > currentMax) + { + currentMax = p; + } + } + } + minBands[band] = currentMin; + maxBands[band] = currentMax; + } + } +} + +template <class T> +void ossimImageData::loadTileFromBip(T, // dummy template variable + const void* src, + const ossimIrect& src_rect) +{ + const ossimIrect img_rect = getImageRectangle(); + + // Get the clip rect. + const ossimIrect clip_rect = img_rect.clipToRect(src_rect); + + loadTileFromBip(T(0), src, src_rect, clip_rect); +} + +template <class T> +void ossimImageData::loadTileFromBip(T, // dummy template variable + const void* src, + const ossimIrect& src_rect, + const ossimIrect& clip_rect) +{ + static const char MODULE[] = "ossimImageData::loadTileFromBip"; + + // Check the pointer. + if (!src) + { + // Set the error... + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "%s File %s line %d\nNULL pointer passed to method!", + MODULE, + __FILE__, + __LINE__); + return; + } + + const ossimIrect img_rect = getImageRectangle(); + + // Check for intersect. + if ( ! img_rect.intersects(src_rect) ) + { + return; // Nothing to do here. + } + + // Check the clip rect. + if (!clip_rect.completely_within(img_rect)) + { +// cerr << MODULE +// << " ERROR: clip rect does not fall within tile rect!" +// << std::endl; + return; + } + + // Check the status and allocate memory if needed. + if (getDataObjectStatus() == OSSIM_NULL) initialize(); + + // Get the width of the buffers. + ossim_uint32 num_bands = getNumberOfBands(); + ossim_uint32 s_width = (src_rect.width()) * num_bands; + ossim_uint32 d_width = getWidth(); + ossim_uint32 band = 0; + const T* s = static_cast<const T*>(src); + T** d = new T*[num_bands]; + + // Make destination pointers to each one. + for (band=0; band<num_bands; band++) + { + d[band] = static_cast<T*>(getBuf(band)); + + // Move the pointers to the first valid pixel. + d[band] += (clip_rect.ul().y - img_rect.ul().y) * d_width + + clip_rect.ul().x - img_rect.ul().x; + } + + // Move the source pointer to the first valid pixel. + s += (clip_rect.ul().y - src_rect.ul().y) * s_width + + (clip_rect.ul().x - src_rect.ul().x) * num_bands; + + // Copy the data. + ossim_uint32 clipHeight = clip_rect.height(); + ossim_uint32 clipWidth = clip_rect.width(); + + for (ossim_uint32 line = 0; line < clipHeight; ++line) + { + ossim_uint32 j = 0; + for (ossim_uint32 sample = 0; sample < clipWidth; ++sample) + { + for (band=0; band<num_bands; band++) + { + d[band][sample] = s[j+band]; + } + j += num_bands; + } + + s += s_width; + for (band=0; band<num_bands; band++) + { + d[band] += d_width; + } + } + + delete [] d; +} + +template <class T> +void ossimImageData::loadTileFromBil(T, // dummy template variable + const void* src, + const ossimIrect& src_rect) +{ + const ossimIrect img_rect = getImageRectangle(); + + // Get the clip rect. + const ossimIrect clip_rect = img_rect.clipToRect(src_rect); + + loadTileFromBil(T(0), src, src_rect, clip_rect); +} + +template <class T> +void ossimImageData::loadTileFromBil(T, // dummy template variable + const void* src, + const ossimIrect& src_rect, + const ossimIrect& clip_rect) +{ + static const char MODULE[] = "ossimImageData::loadTileFromBil"; + + // Check the pointer. + if (!src) + { + // Set the error... + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "%s File %s line %d\nNULL pointer passed to method!", + MODULE, + __FILE__, + __LINE__); + return; + } + + const ossimIrect img_rect = getImageRectangle(); + + // Check for intersect. + if ( ! img_rect.intersects(src_rect) ) + { + return; // Nothing to do here. + } + + // Check the clip rect. + if (!clip_rect.completely_within(img_rect)) + { +// cerr << MODULE +// << " ERROR: clip rect does not fall within tile rect!" +// << std::endl; + return; + } + + // Check the status and allocate memory if needed. + if (getDataObjectStatus() == OSSIM_NULL) initialize(); + + // Get the width of the buffers. + ossim_uint32 num_bands = getNumberOfBands(); + ossim_uint32 s_width = (src_rect.lr().x - src_rect.ul().x + 1); + ossim_uint32 d_width = getWidth(); + ossim_uint32 band = 0; + ossim_uint32 d_offset = (clip_rect.ul().y - img_rect.ul().y) * d_width + + clip_rect.ul().x - img_rect.ul().x; + + const T* s = static_cast<const T*>(src); + + // Get the number of bands and make destination pointers to each one. + T** d = new T*[num_bands]; + + for (band=0; band<num_bands; band++) + { + d[band] = static_cast<T*>(getBuf(band)); + + // Move the pointers to the first valid pixel. + d[band] += d_offset; + } + + // Move the source pointer to the first valid pixel. + s += (clip_rect.ul().y - src_rect.ul().y) * s_width * num_bands + + clip_rect.ul().x - src_rect.ul().x; + + // Copy the data. + ossim_uint32 clipHeight = clip_rect.height(); + ossim_uint32 clipWidth = clip_rect.width(); + + for (ossim_uint32 line = 0; line < clipHeight; ++line) + { + for (band = 0; band < num_bands; ++band) + { + for (ossim_uint32 sample = 0; sample < clipWidth; ++sample) + { + d[band][sample] = s[sample]; + } + s += s_width; + d[band] += d_width; + } + } + + delete [] d; +} + +template <class T> +void ossimImageData::loadTileFromBsq(T, // dummy template variable + const void* src, + const ossimIrect& src_rect) +{ + const ossimIrect img_rect = getImageRectangle(); + + // Get the clip rect. + const ossimIrect clip_rect = img_rect.clipToRect(src_rect); + + loadTileFromBsq(T(0), src, src_rect, clip_rect); +} + +template <class T> +void ossimImageData::loadTileFromBsq(T, // dummy template variable + const void* src, + const ossimIrect& src_rect, + const ossimIrect& clip_rect) +{ + static const char MODULE[] = "ossimImageData::loadTileFromBsq"; + + // Check the pointer. + if (!src) + { + // Set the error... + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "%s File %s line %d\nNULL pointer passed to method!", + MODULE, + __FILE__, + __LINE__); + return; + } + + const ossimIrect img_rect = getImageRectangle(); + + // Check for intersect. + if ( ! img_rect.intersects(src_rect) ) + { + return; // Nothing to do here. + } + + // Check the clip rect. + if (!clip_rect.completely_within(img_rect)) + { +// cerr << MODULE +// << " ERROR: clip rect does not fall within tile rect!" +// << std::endl; + return; + } + + // Check the status and allocate memory if needed. + if (getDataObjectStatus() == OSSIM_NULL) initialize(); + + // Get the width of the buffers. + ossim_uint32 num_bands = getNumberOfBands(); + ossim_uint32 s_width = src_rect.width(); + ossim_uint32 d_width = getWidth(); + ossim_uint32 s_band_offset = s_width * src_rect.height(); + + const T* s = static_cast<const T*>(src); + + ossim_uint32 band; + ossim_uint32 destinationOffset = (clip_rect.ul().y - img_rect.ul().y) * d_width + + (clip_rect.ul().x - img_rect.ul().x); + ossim_uint32 destinationIndex = destinationOffset; + ossim_uint32 sourceOffset = (clip_rect.ul().y - src_rect.ul().y) * s_width + + (clip_rect.ul().x - src_rect.ul().x); + ossim_uint32 sourceIndex = sourceOffset; + ossim_uint32 clipHeight = clip_rect.height(); + ossim_uint32 clipWidth = clip_rect.width(); + + // Copy the data. + for (band=0; band<num_bands; band++) + { + T* destinationBand = static_cast<T*>(getBuf(band)); + destinationIndex = destinationOffset; + sourceIndex = sourceOffset + s_band_offset*band; + + for (ossim_uint32 line = 0; line < clipHeight; ++line) + { + for (ossim_uint32 sample = 0; sample < clipWidth; ++sample) + { + destinationBand[destinationIndex + sample] + = s[sourceIndex+sample]; + } + sourceIndex += s_width; + destinationIndex += d_width; + } + } +} + +void ossimImageData::loadTileFrom1Band(const void* src, + const ossimIrect& src_rect) +{ + ossim_uint32 bands = getNumberOfBands(); + for(ossim_uint32 band = 0; band < bands; ++band) + { + loadBand(src, src_rect, band); + } +} + +void ossimImageData::loadTileFrom1Band(const ossimImageData* src) +{ + if(!src) return; + loadTileFrom1Band((const void*)src->getBuf(), + src->getImageRectangle()); +} + +void ossimImageData::loadShortBand(const void* src, + const ossimIrect& src_rect, + ossim_uint32 band, + bool swap_bytes) +{ + static const char MODULE[] = "ossimImageData::loadShortBand"; + + // Check the pointer. + if (!src) + { + // Set the error... + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "%s File %s line %d\nNULL pointer passed to method!", + MODULE, + __FILE__, + __LINE__); + return; + } + + // Check the band. + if (!isValidBand(band)) + { + // Set the error... + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "%s File %s line %d\nInvalid band: %d", + MODULE, + __FILE__, + __LINE__, + band); + return; + } + + const ossimIrect img_rect = getImageRectangle(); + + // Check for intersect. + if ( ! img_rect.intersects(src_rect) ) + { + return; // Nothing to do here. + } + + // Get the clip rect. + const ossimIrect clip_rect = img_rect.clipToRect(src_rect); + + // Check the status and allocate memory if needed. + if (getDataObjectStatus() == OSSIM_NULL) initialize(); + + // Get the width of the buffers. + ossim_uint32 s_width = src_rect.width(); + ossim_uint32 d_width = getWidth(); + + const ossim_uint16* s = static_cast<const ossim_uint16*>(src); + ossim_uint16* d = getUshortBuf(band); + + // Move the pointers to the first valid pixel. + s += (clip_rect.ul().y - src_rect.ul().y) * s_width + + clip_rect.ul().x - src_rect.ul().x; + + d += (clip_rect.ul().y - img_rect.ul().y) * d_width + + clip_rect.ul().x - img_rect.ul().x; + + // Copy the data. + for (ossim_int32 line=clip_rect.ul().y; line<=clip_rect.lr().y; line++) + { + ossim_uint32 i = 0; + for (ossim_int32 sample=clip_rect.ul().x; sample<=clip_rect.lr().x; sample++) + { + d[i] = (swap_bytes ? ( (s[i] << 8) | (s[i] >> 8) ) : + s[i]); + ++i; + } + + s += s_width; + d += d_width; + } + + validate(); +} + +bool ossimImageData::isPointWithin(const ossimIpt& point)const +{ + return ((point.x >= theOrigin.x)&& + (point.y >= theOrigin.y)&& + ((point.x - theOrigin.x)<static_cast<long>(theSpatialExtents[0]))&& + ((point.y - theOrigin.y)<static_cast<long>(theSpatialExtents[1]))); +} + +bool ossimImageData::isPointWithin(ossim_int32 x, ossim_int32 y)const +{ + return ((x >= theOrigin.x)&& + (y >= theOrigin.y)&& + ((x - theOrigin.x) < static_cast<long>(theSpatialExtents[0]))&& + ((y - theOrigin.y) < static_cast<long>(theSpatialExtents[1]))); +} + +void ossimImageData::unloadTile(void* dest, + const ossimIrect& dest_rect, + ossimInterleaveType type) const +{ + unloadTile(dest, dest_rect, getImageRectangle(), type); +} + +void ossimImageData::unloadTile(void* dest, + const ossimIrect& dest_rect, + const ossimIrect& clip_rect, + ossimInterleaveType type) const +{ + switch (type) + { + case OSSIM_BIP: + unloadTileToBip(dest, dest_rect, clip_rect); + return; + case OSSIM_BIL: + unloadTileToBil(dest, dest_rect, clip_rect); + return; + case OSSIM_BSQ: + unloadTileToBsq(dest, dest_rect, clip_rect); + return; + default: + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimImageData::unloadTile\n\ +File %s line %d\nUnknown scalar type!", + __FILE__, + __LINE__); + return; + } // End of "switch (getScalarType())" +} + +void ossimImageData::unloadTileToBip(void* dest, + const ossimIrect& dest_rect, + const ossimIrect& clip_rect) const +{ + switch (getScalarType()) + { + case OSSIM_UINT8: + unloadTileToBip(ossim_uint8(0), dest, dest_rect, clip_rect); + return; + + case OSSIM_SINT8: + unloadTileToBip(ossim_sint8(0), dest, dest_rect, clip_rect); + return; + + case OSSIM_UINT16: + case OSSIM_USHORT11: + unloadTileToBip(ossim_uint16(0), dest, dest_rect, clip_rect); + return; + + case OSSIM_SINT16: + unloadTileToBip(ossim_sint16(0), dest, dest_rect, clip_rect); + return; + + case OSSIM_UINT32: + unloadTileToBip(ossim_uint32(0), dest, dest_rect, clip_rect); + return; + + case OSSIM_SINT32: + unloadTileToBip(ossim_sint32(0), dest, dest_rect, clip_rect); + return; + + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT32: + unloadTileToBip(ossim_float32(0), dest, dest_rect, clip_rect); + return; + + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_FLOAT64: + unloadTileToBip(ossim_float64(0), dest, dest_rect, clip_rect); + return; + + case OSSIM_SCALAR_UNKNOWN: + default: + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimImageData::unloadTileToBip\n\ +File %s line %d\nUnsupported scalar type for method!", + __FILE__, + __LINE__); + return; + } +} + +void ossimImageData::unloadTileToBil(void* dest, + const ossimIrect& dest_rect, + const ossimIrect& clip_rect) const +{ + switch (getScalarType()) + { + case OSSIM_UINT8: + unloadTileToBil(ossim_uint8(0), dest, dest_rect, clip_rect); + return; + + case OSSIM_SINT8: + unloadTileToBil(ossim_sint8(0), dest, dest_rect, clip_rect); + return; + + case OSSIM_UINT16: + case OSSIM_USHORT11: + unloadTileToBil(ossim_uint16(0), dest, dest_rect, clip_rect); + return; + + case OSSIM_SINT16: + unloadTileToBil(ossim_sint16(0), dest, dest_rect, clip_rect); + return; + + case OSSIM_UINT32: + unloadTileToBil(ossim_uint32(0), dest, dest_rect, clip_rect); + return; + + case OSSIM_SINT32: + unloadTileToBil(ossim_sint32(0), dest, dest_rect, clip_rect); + return; + + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT32: + unloadTileToBil(ossim_float32(0), dest, dest_rect, clip_rect); + return; + + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_FLOAT64: + unloadTileToBil(ossim_float64(0), dest, dest_rect, clip_rect); + return; + + case OSSIM_SCALAR_UNKNOWN: + default: + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimImageData::unloadTileToBil\n\ +File %s line %d\nUnsupported scalar type for method!", + __FILE__, + __LINE__); + return; + } +} + +void ossimImageData::unloadTileToBsq(void* dest, + const ossimIrect& dest_rect, + const ossimIrect& clip_rect) const +{ + switch (getScalarType()) + { + case OSSIM_UINT8: + unloadTileToBsq(ossim_uint8(0), dest, dest_rect, clip_rect); + return; + + case OSSIM_SINT8: + unloadTileToBsq(ossim_sint8(0), dest, dest_rect, clip_rect); + return; + + case OSSIM_UINT16: + case OSSIM_USHORT11: + unloadTileToBsq(ossim_uint16(0), dest, dest_rect, clip_rect); + return; + + case OSSIM_SINT16: + unloadTileToBsq(ossim_sint16(0), dest, dest_rect, clip_rect); + return; + + case OSSIM_UINT32: + unloadTileToBsq(ossim_uint32(0), dest, dest_rect, clip_rect); + return; + + case OSSIM_SINT32: + unloadTileToBsq(ossim_sint32(0), dest, dest_rect, clip_rect); + return; + + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT32: + unloadTileToBsq(ossim_float32(0), dest, dest_rect, clip_rect); + return; + + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_FLOAT64: + unloadTileToBsq(ossim_float64(0), dest, dest_rect, clip_rect); + return; + + case OSSIM_SCALAR_UNKNOWN: + default: + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimImageData::unloadTileToBsq\n\ +File %s line %d\nUnsupported scalar type for method!", + __FILE__, + __LINE__); + return; + } +} + +void ossimImageData::unloadBand(void* dest, + const ossimIrect& dest_rect, + ossim_uint32 band) const +{ + unloadBand(dest, dest_rect, getImageRectangle(), band); +} + +void ossimImageData::unloadBand(void* dest, + const ossimIrect& dest_rect, + const ossimIrect& clip_rect, + ossim_uint32 band) const +{ + // Call the appropriate load method. + switch (getScalarType()) + { + case OSSIM_UINT8: + unloadBand(ossim_uint8(0), dest, dest_rect, clip_rect, band); + return; + + case OSSIM_SINT8: + unloadBand(ossim_sint8(0), dest, dest_rect, clip_rect, band); + return; + + case OSSIM_UINT16: + case OSSIM_USHORT11: + unloadBand(ossim_uint16(0), dest, dest_rect, clip_rect, band); + return; + + case OSSIM_SINT16: + unloadBand(ossim_sint16(0), dest, dest_rect, clip_rect, band); + return; + + case OSSIM_UINT32: + unloadBand(ossim_uint32(0), dest, dest_rect, clip_rect, band); + return; + + case OSSIM_SINT32: + unloadBand(ossim_sint32(0), dest, dest_rect, clip_rect, band); + return; + + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT32: + unloadBand(ossim_float32(0), dest, dest_rect, clip_rect, band); + return; + + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_FLOAT64: + unloadBand(ossim_float64(0), dest, dest_rect, clip_rect, band); + return; + + case OSSIM_SCALAR_UNKNOWN: + default: + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimImageData::unloadBand\n\ +File %s line %d\nUnsupported scalar type for method!", + __FILE__, + __LINE__); + return; + } +} + +template <class T> +void ossimImageData::unloadBand(T, // dummy tmeplate variable + void* dest, + const ossimIrect& dest_rect, + const ossimIrect& clip_rect, + ossim_uint32 band) const +{ + static const char MODULE[] = "ossimImageData::unloadBand"; + + // Check the pointers. + if (!dest) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR:" + << "\nNULL pointer passed to method! Returning..." << std::endl; + return; + } + + if (getDataObjectStatus() == OSSIM_NULL) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR:" + << "\nThis object is null! Returning..." << std::endl; + return; + } + + ossimIrect img_rect = getImageRectangle(); + + // Clip the clip_rect to the tile rect. + ossimIrect output_clip_rect = clip_rect.clipToRect(img_rect); + + // Clip it again to the destination rect. + output_clip_rect = dest_rect.clipToRect(output_clip_rect); + + // Check the output clip rect for intersection. + if (!output_clip_rect.intersects(img_rect)) + { + return; + } + if ( !(output_clip_rect.intersects(dest_rect)) ) + { + return; + } + + // Check for valid band. + if (!isValidBand(band)) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " NOTICE:" + << "\nInvalid band: " << band << " Returning..." + << std::endl; + return; + } + + ossim_uint32 num_bands = getNumberOfBands(); + + ossim_uint32 buf_width = dest_rect.lr().x - dest_rect.ul().x + 1; + + // Get a pointer to the source band buffer. + const T* s = reinterpret_cast<const T*>(getBuf(band)); + + // Get the offset for each source band. + ossim_uint32 src_offset = (output_clip_rect.ul().y - img_rect.ul().y) * + getWidth() + output_clip_rect.ul().x - img_rect.ul().x; + + // Move the pointers to the start. + T* d = reinterpret_cast<T*>(dest); + + d += (output_clip_rect.ul().y - dest_rect.ul().y) * buf_width * num_bands + + output_clip_rect.ul().x - dest_rect.ul().x; + + s += src_offset; + + for (ossim_int32 line=output_clip_rect.ul().y; + line<=output_clip_rect.lr().y; ++line) + { + ossim_uint32 i=0; + for (ossim_int32 samp=clip_rect.ul().x; + samp<=output_clip_rect.lr().x; ++samp) + { + d[i] = s[i]; + ++i; + } + d += buf_width; + s += getWidth(); + } +} + +template <class T> void +ossimImageData::unloadTileToBip(T, // dummy template variable + void* dest, + const ossimIrect& dest_rect, + const ossimIrect& clip_rect) const +{ + static const char MODULE[] = "ossimImageData::unloadTileToBip"; + + // Check the pointer. + if (!dest) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR:" + << "\nNULL pointer passed to method! Returning..." << std::endl; + return; + } + + bool dataIsNull = false; + if (getDataObjectStatus() == OSSIM_NULL) + { + dataIsNull = true; + } + + ossimIrect img_rect = getImageRectangle(); + + // Clip the clip_rect to the tile rect. + ossimIrect output_clip_rect = clip_rect.clipToRect(img_rect); + + // Clip it again to the destination rect. + output_clip_rect = dest_rect.clipToRect(output_clip_rect); + + // Check the output clip rect for intersection. + if (output_clip_rect.hasNans()) + { + return; + } + if ( !(output_clip_rect.intersects(dest_rect)) ) + { + return; + } + + ossim_int32 num_bands = getNumberOfBands(); + + ossim_int32 buf_width = dest_rect.width() * num_bands; + + if(!dataIsNull) + { + // Get the number of bands and grab a pointers to each one. + const T** s = new const T*[num_bands]; + + ossim_int32 band; + ossim_int32 s_width = getWidth(); + + for (band=0; band<num_bands; band++) + { + s[band] = reinterpret_cast<const T*>(getBuf(band)); + } + + // Move the pointers to the start. + T* d = reinterpret_cast<T*>(dest); + + d += (output_clip_rect.ul().y - dest_rect.ul().y) * buf_width + + (output_clip_rect.ul().x - dest_rect.ul().x) * num_bands; + + // Get the offset for each source band. + ossim_int32 src_offset = (output_clip_rect.ul().y - img_rect.ul().y) * + s_width + (output_clip_rect.ul().x - img_rect.ul().x); + + ossim_int32 output_clip_width = output_clip_rect.width(); + ossim_int32 output_clip_height = output_clip_rect.height(); + + for (band=0; band<(ossim_int32)getNumberOfBands(); band++) + { + s[band] += src_offset; + } + + ossim_int32 j; + for (ossim_int32 line=0; line<output_clip_height; ++line) + { + j = 0; + for (ossim_int32 samp=0; samp<output_clip_width; ++samp, j+=num_bands) + { + for (band=0; band<num_bands; ++band) + { + d[j+band] = s[band][samp]; + } + } + + // increment to next line... + d += buf_width; + for (band=0; band<num_bands; ++band) + { + s[band] += s_width; + } + + } + delete [] s; + } + else + { + ossim_int32 band = 0; + T* nulls = new T[num_bands]; + for(band = 0; band < num_bands; ++band) + { + nulls[band] = static_cast<T>(theNullPixelValue[band]); + } + // Move the pointers to the start. + T* d = reinterpret_cast<T*>(dest); + + d += (output_clip_rect.ul().y - dest_rect.ul().y) * buf_width + + (output_clip_rect.ul().x - dest_rect.ul().x) * num_bands; + + for (ossim_int32 line=output_clip_rect.ul().y; + line<=output_clip_rect.lr().y; ++line) + { + ossim_int32 i=0; + ossim_int32 j=0; + for (ossim_int32 samp=output_clip_rect.ul().x; + samp<=output_clip_rect.lr().x; ++samp) + { + for (band=0; band<num_bands; ++band) + { + d[j+band] = nulls[band]; + } + ++i; // increment to next pixel... + j+= num_bands; + } + + // increment to next line... + d += buf_width; + } + delete [] nulls; + nulls = NULL;; + } +} + +template <class T> void +ossimImageData::unloadTileToBil(T, // dummy template arg... + void* dest, + const ossimIrect& dest_rect, + const ossimIrect& clip_rect) const +{ + static const char MODULE[] = "ossimImageData::unloadTileToBil"; + + // Check the pointers. + if (!dest) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR:" + << "\nNULL pointer passed to method! Returning..." << std::endl; + return; + } + bool dataIsNull = false; + if (getDataObjectStatus() == OSSIM_NULL) + { + dataIsNull = true; + } + + ossimIrect img_rect = getImageRectangle(); + + // Clip the clip_rect to the tile rect. + ossimIrect output_clip_rect = clip_rect.clipToRect(img_rect); + + // Clip it again to the destination rect. + output_clip_rect = dest_rect.clipToRect(output_clip_rect); + + // Check the output clip rect for intersection. + if (output_clip_rect.hasNans()) + { + return; + } + if ( !(output_clip_rect.intersects(dest_rect)) ) + { + return; + } + + ossim_uint32 num_bands = getNumberOfBands(); + + ossim_uint32 buf_width = dest_rect.width(); + + if(!dataIsNull) + { + // Get the number of bands and grab a pointers to each one. + const T** s = new const T*[num_bands]; + + ossim_uint32 band; + + for (band=0; band<num_bands; band++) + { + s[band] = reinterpret_cast<const T*>(getBuf(band)); + } + + // Get the offset for each source band. + ossim_uint32 src_offset = (output_clip_rect.ul().y - img_rect.ul().y) * + getWidth() + (output_clip_rect.ul().x - img_rect.ul().x); + + // Move the pointers to the start. + T* d = reinterpret_cast<T*>(dest); + + d += (output_clip_rect.ul().y - dest_rect.ul().y) * + buf_width * num_bands + + (output_clip_rect.ul().x-dest_rect.ul().x); + + for (band=0; band<num_bands; ++band) + { + s[band] += src_offset; + } + + for (ossim_int32 line=output_clip_rect.ul().y; + line<=output_clip_rect.lr().y; ++line) + { + for (band=0; band<num_bands; ++band) + { + ossim_uint32 i=0; + for (ossim_int32 samp=output_clip_rect.ul().x; + samp<=output_clip_rect.lr().x; ++samp) + { + d[i] = s[band][i]; + ++i; + } + d += buf_width; + s[band] += getWidth(); + } + } + // Free up memory allocated for pointers. + delete [] s; + } + else + { + ossim_uint32 band = 0; + T* nulls = new T[num_bands]; + for(band = 0; band < num_bands; ++band) + { + nulls[band] = static_cast<T>(theNullPixelValue[band]); + } + + // Move the pointers to the start. + T* d = reinterpret_cast<T*>(dest); + + d += (output_clip_rect.ul().y - dest_rect.ul().y) * + buf_width * num_bands + (output_clip_rect.ul().x - dest_rect.ul().x); + + for (ossim_int32 line=output_clip_rect.ul().y; + line<=output_clip_rect.lr().y; ++line) + { + for (band=0; band<num_bands; ++band) + { + ossim_uint32 i=0; + for (ossim_int32 samp=output_clip_rect.ul().x; + samp<=output_clip_rect.lr().x; ++samp) + { + d[i] = nulls[band]; + ++i; + } + d += buf_width; + } + } + } +} + +template <class T> void +ossimImageData::unloadTileToBsq(T, // dummy template arg... + void* dest, + const ossimIrect& dest_rect, + const ossimIrect& clip_rect) const +{ + static const char MODULE[] = "ossimImageData::unloadTileToBsq"; + + // Check the pointers. + if (!dest) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR:" + << "\nNULL pointer passed to method! Returning..." << std::endl; + return; + } + + bool dataIsNull = false; + if (getDataObjectStatus() == OSSIM_NULL) + { + dataIsNull = true; + } + + ossimIrect img_rect = getImageRectangle(); + + // Clip the clip_rect to the tile rect. + ossimIrect output_clip_rect = clip_rect.clipToRect(img_rect); + + // Clip it again to the destination rect. + output_clip_rect = dest_rect.clipToRect(output_clip_rect); + + // Check the output clip rect for intersection. + if (output_clip_rect.hasNans()) + { + return; + } + if ( !(output_clip_rect.intersects(dest_rect)) ) + { + return; + } + + ossim_uint32 num_bands = getNumberOfBands(); + ossim_uint32 band = 0; + if(!dataIsNull) + { + ossim_uint32 num_bands = getNumberOfBands(); + ossim_uint32 d_width = dest_rect.lr().x - dest_rect.ul().x + 1; + ossim_uint32 d_band_offset = d_width * (dest_rect.lr().y-dest_rect.ul().y+1); + ossim_uint32 s_width = getWidth(); + ossim_uint32 s_offset = (output_clip_rect.ul().y - img_rect.ul().y) * + s_width + (output_clip_rect.ul().x - img_rect.ul().x); + + T* d = static_cast<T*>(dest); + const T** s = new const T*[num_bands]; + + // Grab a pointers to each one. + for (band=0; band<num_bands; ++band) + { + s[band] = reinterpret_cast<const T*>(getBuf(band)); + + // Move to first valid pixel. + s[band] += s_offset; + } + + // Move to first valid pixel. + d += (output_clip_rect.ul().y - dest_rect.ul().y) * d_width + + (output_clip_rect.ul().x - dest_rect.ul().x); + + for (band=0; band<num_bands; ++band) + { + ossim_uint32 d_buf_offset = 0; + + for (ossim_int32 line=output_clip_rect.ul().y; + line<=output_clip_rect.lr().y; ++line) + { + ossim_int32 i=0; + for (ossim_int32 samp=output_clip_rect.ul().x; + samp<=output_clip_rect.lr().x; ++samp) + { + d[d_buf_offset+i] = s[band][i]; + ++i; + } + + d_buf_offset += d_width; + s[band] += s_width; + } + d += d_band_offset; + } + + // Free up memory allocated for pointers. + delete [] s; + } + else + { + ossim_uint32 d_width = dest_rect.lr().x - dest_rect.ul().x + 1; + ossim_uint32 d_band_offset = d_width * (dest_rect.lr().y-dest_rect.ul().y+1); + + ossim_uint8* d = static_cast<ossim_uint8*>(dest); + + // Move to first valid pixel. + d += (output_clip_rect.ul().y - dest_rect.ul().y) * d_width + + (output_clip_rect.ul().x - dest_rect.ul().x); + + for (band=0; band<num_bands; ++band) + { + ossim_uint8 np = static_cast<ossim_uint8>(theNullPixelValue[band]); + ossim_uint32 d_buf_offset = 0; + + for (ossim_int32 line=output_clip_rect.ul().y; + line<=output_clip_rect.lr().y; ++line) + { + ossim_int32 i=0; + for (ossim_int32 samp=output_clip_rect.ul().x; + samp<=output_clip_rect.lr().x; ++samp) + { + d[d_buf_offset+i] = np; + ++i; + } + + d_buf_offset += d_width; + } + d += d_band_offset; + } + } +} + +ossimObject* ossimImageData::dup() const +{ + return new ossimImageData(*this); +} + +void ossimImageData::copyTileToNormalizedBuffer(ossim_float64* buf)const +{ + if (!buf) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::copyTileToNormalizedBuffer ERROR:" + << "\nNull buffer passed to method! Returning..." << std::endl; + return; + } + + if (getDataObjectStatus() == OSSIM_NULL) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::copyTileToNormalizedBuffer ERROR:" + << "\nThis object is null! Returning..." << std::endl; + return; + } + + switch(getScalarType()) + { + case OSSIM_NORMALIZED_DOUBLE: + { + memmove(buf, getBuf(), getDataSizeInBytes()); + break; + } + case OSSIM_NORMALIZED_FLOAT: + { + ossim_uint32 upperBound = getWidth()*getHeight()*getNumberOfBands(); + const ossim_float32* inputBuf = static_cast<const ossim_float32*>(getBuf()); + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + buf[offset] = inputBuf[offset]; + } + break; + } + case OSSIM_FLOAT32: + { + copyTileToNormalizedBuffer((ossim_float32)0, buf); + break; + } + case OSSIM_FLOAT64: + { + copyTileToNormalizedBuffer((ossim_float64)0, buf); + break; + } + case OSSIM_UINT8: + { + copyTileToNormalizedBuffer((ossim_uint8)0, buf); + break; + + } + case OSSIM_SINT8: + { + copyTileToNormalizedBuffer((ossim_sint8)0, buf); + break; + + } + case OSSIM_USHORT11: + case OSSIM_UINT16: + { + copyTileToNormalizedBuffer((ossim_uint16)0, buf); + break; + } + case OSSIM_SINT16: + { + copyTileToNormalizedBuffer((ossim_sint16)0, buf); + break; + } + case OSSIM_UINT32: + { + copyTileToNormalizedBuffer((ossim_uint32)0, buf); + break; + } + case OSSIM_SINT32: + { + copyTileToNormalizedBuffer((ossim_sint32)0, buf); + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "NOTICE: copyTileToNormalizedBuffer not implemented yet" + << std::endl; + } + + } // End of "switch(getScalarType())" +} + +template <class T> +void ossimImageData::copyTileToNormalizedBuffer(T dummyTemplate, + ossim_float64* buf) const +{ + const ossim_uint32 SIZE = getSizePerBand(); + const ossim_uint32 BANDS = getNumberOfBands(); + + for(ossim_uint32 band = 0; band < BANDS; ++band) + { + const ossim_float64 MIN_PIX = getMinPix(band); + const ossim_float64 MAX_PIX = getMaxPix(band); + const ossim_float64 RANGE = (MAX_PIX-MIN_PIX); + const ossim_float64 NP = getNullPix(band); + + const T* s = (T*)getBuf(band); // source + ossim_float64* d = (ossim_float64*)(buf + (band*SIZE)); // destination + + for(ossim_uint32 offset = 0; offset < SIZE; ++offset) + { + ossim_float64 p = s[offset]; + if(p != NP) + { + if( p == MIN_PIX) + { + d[offset] = OSSIM_DEFAULT_MIN_PIX_NORM_DOUBLE; + } + else + { + d[offset] = (p-MIN_PIX)/RANGE; + } + } + else + { + d[offset] = 0.0; + } + } + } +} + +template <class T> +void ossimImageData::copyTileToNormalizedBuffer(T dummyTemplate, + ossim_float32* buf) const +{ + const ossim_uint32 SIZE = getSizePerBand(); + const ossim_uint32 BANDS = getNumberOfBands(); + + for(ossim_uint32 band = 0; band < BANDS; ++band) + { + const ossim_float64 MIN_PIX = getMinPix(band); + const ossim_float64 MAX_PIX = getMaxPix(band); + const ossim_float64 RANGE = (MAX_PIX-MIN_PIX); + const ossim_float64 NP = getNullPix(band); + + const T* s = (T*)getBuf(band); // source + ossim_float32* d = (ossim_float32*)(buf + (band*SIZE)); // destination + + for(ossim_uint32 offset = 0; offset < SIZE; ++offset) + { + ossim_float64 p = s[offset]; + if(p != NP) + { + if( p == MIN_PIX) + { + d[offset] = OSSIM_DEFAULT_MIN_PIX_NORM_FLOAT; + } + else + { + d[offset] = (p-MIN_PIX)/RANGE; + } + } + else + { + d[offset] = 0.0; + } + } + } +} + +template <class T> +void ossimImageData::copyTileToNormalizedBuffer(T dummyTemplate, + ossim_uint32 band, + ossim_float64* buf) const +{ + const ossim_uint32 SIZE = getSizePerBand(); + const ossim_float64 MIN_PIX = getMinPix(band); + const ossim_float64 MAX_PIX = getMaxPix(band); + const ossim_float64 RANGE = (MAX_PIX-MIN_PIX); + const ossim_float64 NP = getNullPix(band); + + const T* s = (T*)getBuf(band); // source + ossim_float64* d = (ossim_float64*)(buf); // destination + + for(ossim_uint32 offset = 0; offset < SIZE; ++offset) + { + ossim_float64 p = s[offset]; + if(p != NP) + { + if( p == MIN_PIX) + { + d[offset] = OSSIM_DEFAULT_MIN_PIX_NORM_DOUBLE; + } + else + { + d[offset] = (p-MIN_PIX)/RANGE; + } + } + else + { + d[offset] = 0.0; + } + } +} + +template <class T> +void ossimImageData::copyTileToNormalizedBuffer(T dummyTemplate, + ossim_uint32 band, + ossim_float32* buf) const +{ + const ossim_uint32 SIZE = getSizePerBand(); + const ossim_float64 MIN_PIX = getMinPix(band); + const ossim_float64 MAX_PIX = getMaxPix(band); + const ossim_float64 RANGE = (MAX_PIX-MIN_PIX); + const ossim_float64 NP = getNullPix(band); + + const T* s = (T*)getBuf(band); // source + ossim_float32* d = (ossim_float32*)(buf); // destination + + for(ossim_uint32 offset = 0; offset < SIZE; ++offset) + { + ossim_float64 p = s[offset]; + if(p != NP) + { + if( p == MIN_PIX) + { + d[offset] = OSSIM_DEFAULT_MIN_PIX_NORM_FLOAT; + } + else + { + d[offset] = (p-MIN_PIX)/RANGE; + } + } + else + { + d[offset] = 0.0; + } + } +} + +template <class T> +void ossimImageData::copyNormalizedBufferToTile(T dummyTemplate, + ossim_float64* buf) +{ + const ossim_uint32 SIZE = getSizePerBand(); + const ossim_uint32 BANDS = getNumberOfBands(); + + for(ossim_uint32 band = 0; band < BANDS; ++band) + { + const ossim_float64 MIN_PIX = getMinPix(band); + const ossim_float64 MAX_PIX = getMaxPix(band); + const ossim_float64 RANGE = (MAX_PIX-MIN_PIX); + const T NP = (T)getNullPix(band); + + ossim_float64* s = buf + (band*SIZE); // source + T* d = (T*)getBuf(band); // destination + + for(ossim_uint32 offset = 0; offset < SIZE; ++offset) + { + const ossim_float64 P = s[offset]; + if(P != 0.0) + { + d[offset] = (T)(MIN_PIX + RANGE*P); + } + else + { + d[offset] = NP; + } + } + } +} + +template <class T> +void ossimImageData::copyNormalizedBufferToTile(T dummyTemplate, + ossim_float32* buf) +{ + const ossim_uint32 SIZE = getSizePerBand(); + const ossim_uint32 BANDS = getNumberOfBands(); + + for(ossim_uint32 band = 0; band < BANDS; ++band) + { + const ossim_float64 MIN_PIX = getMinPix(band); + const ossim_float64 MAX_PIX = getMaxPix(band); + const ossim_float64 RANGE = (MAX_PIX-MIN_PIX); + const T NP = (T)getNullPix(band); + + ossim_float32* s = buf + (band*SIZE); // source + T* d = (T*)getBuf(band); // destination + + for(ossim_uint32 offset = 0; offset < SIZE; ++offset) + { + const ossim_float64 P = s[offset]; + if(P != 0.0) + { + ossim_float64 test = MIN_PIX + RANGE*P; + if(test > MAX_PIX) test = MAX_PIX; + d[offset] = (T)test; + } + else + { + d[offset] = NP; + } + } + } +} + +template <class T> +void ossimImageData::copyNormalizedBufferToTile(T dummyTemplate, + ossim_uint32 band, + ossim_float64* buf) +{ + const ossim_uint32 SIZE = getSizePerBand(); + const ossim_float64 MIN_PIX = getMinPix(band); + const ossim_float64 MAX_PIX = getMaxPix(band); + const ossim_float64 RANGE = (MAX_PIX-MIN_PIX); + const T NP = (T)getNullPix(band); + + ossim_float64* s = buf; // source + T* d = (T*)getBuf(band); // destination + + for(ossim_uint32 offset = 0; offset < SIZE; ++offset) + { + const ossim_float64 P = s[offset]; + if(P != 0.0) + { + ossim_float64 test = MIN_PIX + RANGE*P; + if(test > MAX_PIX) test = MAX_PIX; + d[offset] = (T)test; + } + else + { + d[offset] = NP; + } + } +} + +template <class T> +void ossimImageData::copyNormalizedBufferToTile(T dummyTemplate, + ossim_uint32 band, + ossim_float32* buf) +{ + const ossim_uint32 SIZE = getSizePerBand(); + const ossim_float64 MIN_PIX = getMinPix(band); + const ossim_float64 MAX_PIX = getMaxPix(band); + const ossim_float64 RANGE = (MAX_PIX-MIN_PIX); + const T NP = (T)getNullPix(band); + + ossim_float32* s = buf; // source + T* d = (T*)getBuf(band); // destination + + for(ossim_uint32 offset = 0; offset < SIZE; ++offset) + { + const ossim_float64 P = s[offset]; + if(P != 0.0) + { + ossim_float64 test = MIN_PIX + RANGE*P; + if(test > MAX_PIX) test = MAX_PIX; + d[offset] = (T)test; + } + else + { + d[offset] = NP; + } + } +} + +void ossimImageData::copyTileBandToNormalizedBuffer(ossim_uint32 band, + ossim_float64* buf) const +{ + if (!buf) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::copyTileBandToNormalizedBuffer ERROR:" + << "\nNull buffer passed to method! Returning..." << std::endl; + return; + } + + if (getDataObjectStatus() == OSSIM_NULL) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::copyTileBandToNormalizedBuffer ERROR:" + << "\nThis object is null! Returning..." << std::endl; + return; + } + + if(!getBuf(band)) return; + + switch(getScalarType()) + { + case OSSIM_NORMALIZED_DOUBLE: + { + memmove(buf, getBuf(band), getDataSizeInBytes()); + break; + } + case OSSIM_NORMALIZED_FLOAT: + { + ossim_uint32 upperBound = getWidth()*getHeight(); + const ossim_float32* inputBuf = static_cast<const ossim_float32*>(getBuf(band)); + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + buf[offset] = inputBuf[offset]; + } + break; + } + case OSSIM_FLOAT32: + { + copyTileToNormalizedBuffer((ossim_float32)0, band, buf); + break; + } + case OSSIM_FLOAT64: + { + copyTileToNormalizedBuffer((ossim_float64)0, band, buf); + break; + } + case OSSIM_UINT8: + { + copyTileToNormalizedBuffer((ossim_uint8)0, band, buf); + break; + + } + case OSSIM_SINT8: + { + copyTileToNormalizedBuffer((ossim_sint8)0, band, buf); + break; + + } + case OSSIM_USHORT11: + case OSSIM_UINT16: + { + copyTileToNormalizedBuffer((ossim_uint16)0, band, buf); + break; + } + case OSSIM_SINT16: + { + copyTileToNormalizedBuffer((ossim_sint16)0, band, buf); + break; + } + case OSSIM_UINT32: + { + copyTileToNormalizedBuffer((ossim_uint32)0, band, buf); + break; + } + case OSSIM_SINT32: + { + copyTileToNormalizedBuffer((ossim_sint32)0, band, buf); + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::copyTileBandToNormalizedBuffer ERROR:" + << " Unknown scalar type!" + << std::endl; + } + + } // End of "switch(getScalarType())" + +} + +void ossimImageData::copyTileToNormalizedBuffer(ossim_float32* buf)const +{ + + if (!buf) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::copyTileToNormalizedBuffer ERROR:" + << "\nNull buffer passed to method! Returning..." << std::endl; + return; + } + + if (getDataObjectStatus() == OSSIM_NULL) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::copyTileToNormalizedBuffer ERROR:" + << "\nThis object is null! Returning..." << std::endl; + return; + } + + switch(getScalarType()) + { + case OSSIM_NORMALIZED_DOUBLE: + { + ossim_uint32 upperBound = getWidth()*getHeight()*getNumberOfBands(); + const ossim_float32* inputBuf = static_cast<const ossim_float32*>(getBuf()); + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + buf[offset] = inputBuf[offset]; + } + break; + } + case OSSIM_NORMALIZED_FLOAT: + { + memmove(buf, getBuf(), getDataSizeInBytes()); + break; + } + case OSSIM_FLOAT32: + { + copyTileToNormalizedBuffer((ossim_float32)0, buf); + break; + } + case OSSIM_FLOAT64: + { + copyTileToNormalizedBuffer((ossim_float64)0, buf); + break; + } + case OSSIM_UINT8: + { + copyTileToNormalizedBuffer((ossim_uint8)0, buf); + break; + + } + case OSSIM_SINT8: + { + copyTileToNormalizedBuffer((ossim_sint8)0, buf); + break; + + } + case OSSIM_USHORT11: + case OSSIM_UINT16: + { + copyTileToNormalizedBuffer((ossim_uint16)0, buf); + break; + } + case OSSIM_SINT16: + { + copyTileToNormalizedBuffer((ossim_sint16)0, buf); + break; + } + case OSSIM_UINT32: + { + copyTileToNormalizedBuffer((ossim_uint32)0, buf); + break; + } + case OSSIM_SINT32: + { + copyTileToNormalizedBuffer((ossim_sint32)0, buf); + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "NOTICE: copyTileToNormalizedBuffer not implemented yet" + << std::endl; + } + + } // End of "switch(getScalarType())" +} + +void ossimImageData::copyTileBandToNormalizedBuffer(ossim_uint32 band, + ossim_float32* buf)const +{ + if (!buf) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::copyTileBandToNormalizedBuffer ERROR:" + << "\nNull buffer passed to method! Returning..." << std::endl; + return; + } + + if (getDataObjectStatus() == OSSIM_NULL) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::copyTileBandToNormalizedBuffer ERROR:" + << "\nThis object is null! Returning..." << std::endl; + return; + } + + switch(getScalarType()) + { + case OSSIM_NORMALIZED_DOUBLE: + { + ossim_uint32 upperBound = getWidth()*getHeight(); + const ossim_float32* inputBuf = static_cast<const ossim_float32*>(getBuf(band)); + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + buf[offset] = inputBuf[offset]; + } + break; + } + case OSSIM_NORMALIZED_FLOAT: + { + memmove(buf, getBuf(band), getSizePerBandInBytes()); + break; + } + case OSSIM_FLOAT32: + { + copyTileToNormalizedBuffer((ossim_float32)0, band, buf); + break; + } + case OSSIM_FLOAT64: + { + copyTileToNormalizedBuffer((ossim_float64)0, band, buf); + break; + } + case OSSIM_UINT8: + { + copyTileToNormalizedBuffer((ossim_uint8)0, band, buf); + break; + + } + case OSSIM_SINT8: + { + copyTileToNormalizedBuffer((ossim_sint8)0, band, buf); + break; + + } + case OSSIM_USHORT11: + case OSSIM_UINT16: + { + copyTileToNormalizedBuffer((ossim_uint16)0, band, buf); + break; + } + case OSSIM_SINT16: + { + copyTileToNormalizedBuffer((ossim_sint16)0, band, buf); + break; + } + case OSSIM_UINT32: + { + copyTileToNormalizedBuffer((ossim_uint32)0, band, buf); + break; + } + case OSSIM_SINT32: + { + copyTileToNormalizedBuffer((ossim_sint32)0, band, buf); + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::copyTileBandToNormalizedBuffer ERROR:" + << " Unknown scalar type" + << std::endl; + } + + } // End of "switch(getScalarType())" +} + + +void ossimImageData::copyNormalizedBufferToTile(ossim_float64* buf) +{ + if (!buf) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::copyNormalizedBufferToTile ERROR:" + << "\nNull buffer passed to method! Returning..." << std::endl; + return; + } + + if (getDataObjectStatus() == OSSIM_NULL) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::copyNormalizedBufferToTile ERROR:" + << "\nThis object is null! Returning..." << std::endl; + return; + } + + switch(getScalarType()) + { + case OSSIM_NORMALIZED_DOUBLE: + { + memmove(getBuf(), buf, getDataSizeInBytes()); + break; + } + case OSSIM_NORMALIZED_FLOAT: + { + ossim_uint32 upperBound = getWidth()*getHeight()*getNumberOfBands(); + ossim_float32* inputBuf = static_cast<ossim_float32*>(getBuf()); + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + inputBuf[offset] = static_cast<ossim_float32>(buf[offset]); + } + break; + } + case OSSIM_FLOAT32: + { + copyNormalizedBufferToTile((ossim_float32)0, buf); + break; + } + case OSSIM_FLOAT64: + { + copyNormalizedBufferToTile((ossim_float64)0, buf); + break; + } + case OSSIM_UINT8: + { + copyNormalizedBufferToTile((ossim_uint8)0, buf); + break; + + } + case OSSIM_SINT8: + { + copyNormalizedBufferToTile((ossim_sint8)0, buf); + break; + + } + case OSSIM_USHORT11: + case OSSIM_UINT16: + { + copyNormalizedBufferToTile((ossim_uint16)0, buf); + break; + } + case OSSIM_SINT16: + { + copyNormalizedBufferToTile((ossim_sint16)0, buf); + break; + } + case OSSIM_UINT32: + { + copyNormalizedBufferToTile((ossim_uint32)0, buf); + break; + } + case OSSIM_SINT32: + { + copyNormalizedBufferToTile((ossim_sint32)0, buf); + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::copyNormalizedBufferToTile\n" + << "Unknown scalar type!" << std::endl; + } + + } // End of "switch(getScalarType())". +} + +void ossimImageData::copyNormalizedBufferToTile(ossim_uint32 band, + ossim_float64* buf) +{ + if (!buf) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::copyNormalizedBufferToTile ERROR:" + << "\nNull buffer passed to method! Returning..." << std::endl; + return; + } + + if (getDataObjectStatus() == OSSIM_NULL) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::copyNormalizedBufferToTile ERROR:" + << "\nThis object is null! Returning..." << std::endl; + return; + } + + if(band < getNumberOfBands()) + { + switch(getScalarType()) + { + case OSSIM_NORMALIZED_DOUBLE: + { + memmove(getBuf(band), buf, getSizePerBandInBytes()); + break; + } + case OSSIM_NORMALIZED_FLOAT: + { + ossim_uint32 upperBound = getWidth()*getHeight(); + ossim_float32* inputBuf = static_cast<ossim_float32*>(getBuf(band)); + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + inputBuf[offset] = static_cast<ossim_float32>(buf[offset]); + } + break; + } + case OSSIM_FLOAT32: + { + copyNormalizedBufferToTile((ossim_float32)0, band, buf); + break; + } + case OSSIM_FLOAT64: + { + copyNormalizedBufferToTile((ossim_float64)0, band, buf); + break; + } + case OSSIM_UINT8: + { + copyNormalizedBufferToTile((ossim_uint8)0, band, buf); + break; + + } + case OSSIM_SINT8: + { + copyNormalizedBufferToTile((ossim_sint8)0, band, buf); + break; + + } + case OSSIM_USHORT11: + case OSSIM_UINT16: + { + copyNormalizedBufferToTile((ossim_uint16)0, band, buf); + break; + } + case OSSIM_SINT16: + { + copyNormalizedBufferToTile((ossim_sint16)0, band, buf); + break; + } + case OSSIM_UINT32: + { + copyNormalizedBufferToTile((ossim_uint32)0, band, buf); + break; + } + case OSSIM_SINT32: + { + copyNormalizedBufferToTile((ossim_sint32)0, band, buf); + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::copyNormalizedBufferToTile\n" + << "Unknown scalar type." << std::endl; + } + + } // End of "switch(getScalarType())". + } +} + +void ossimImageData::copyNormalizedBufferToTile(ossim_float32* buf) +{ + if (!buf) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::copyNormalizedBufferToTile ERROR:" + << "\nNull buffer passed to method! Returning..." << std::endl; + return; + } + + if (getDataObjectStatus() == OSSIM_NULL) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::copyNormalizedBufferToTile ERROR:" + << "\nThis object is null! Returning..." << std::endl; + return; + } + + switch(getScalarType()) + { + case OSSIM_NORMALIZED_DOUBLE: + { + ossim_uint32 upperBound = getWidth()*getHeight()*getNumberOfBands(); + ossim_float64* inputBuf = static_cast<ossim_float64*>(getBuf()); + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + inputBuf[offset] = buf[offset]; + } + break; + } + case OSSIM_NORMALIZED_FLOAT: + { + memmove(getBuf(), buf, getDataSizeInBytes()); + break; + } + case OSSIM_FLOAT32: + { + copyNormalizedBufferToTile((ossim_float32)0, buf); + break; + } + case OSSIM_FLOAT64: + { + copyNormalizedBufferToTile((ossim_float64)0, buf); + break; + } + case OSSIM_UINT8: + { + copyNormalizedBufferToTile((ossim_uint8)0, buf); + break; + + } + case OSSIM_SINT8: + { + copyNormalizedBufferToTile((ossim_sint8)0, buf); + break; + + } + case OSSIM_USHORT11: + case OSSIM_UINT16: + { + copyNormalizedBufferToTile((ossim_uint16)0, buf); + break; + } + case OSSIM_SINT16: + { + copyNormalizedBufferToTile((ossim_sint16)0, buf); + break; + } + case OSSIM_UINT32: + { + copyNormalizedBufferToTile((ossim_uint32)0, buf); + break; + } + case OSSIM_SINT32: + { + copyNormalizedBufferToTile((ossim_sint32)0, buf); + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageDatacopyNormalizedBufferToTile\n" + << "Unknown scalar type!" << std::endl; + } + + } // End of "switch(getScalarType())". +} + +void ossimImageData::copyNormalizedBufferToTile(ossim_uint32 band, + ossim_float32* buf) +{ + if (!buf) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::copyNormalizedBufferToTile ERROR:" + << "\nNull buffer passed to method! Returning..." << std::endl; + return; + } + + if (getDataObjectStatus() == OSSIM_NULL) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::copyNormalizedBufferToTile ERROR:" + << "\nThis object is null! Returning..." << std::endl; + return; + } + + switch(getScalarType()) + { + case OSSIM_NORMALIZED_DOUBLE: + { + ossim_uint32 upperBound = getWidth()*getHeight(); + ossim_float64* inputBuf = static_cast<ossim_float64*>(getBuf(band)); + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + inputBuf[offset] = buf[offset]; + } + break; + } + case OSSIM_NORMALIZED_FLOAT: + { + memmove(getBuf(band), buf, getSizePerBandInBytes()); + break; + } + case OSSIM_FLOAT32: + { + copyNormalizedBufferToTile((ossim_float32)0, band, buf); + break; + } + case OSSIM_FLOAT64: + { + copyNormalizedBufferToTile((ossim_float64)0, band, buf); + break; + } + case OSSIM_UINT8: + { + copyNormalizedBufferToTile((ossim_uint8)0, band, buf); + break; + + } + case OSSIM_SINT8: + { + copyNormalizedBufferToTile((ossim_sint8)0, band, buf); + break; + + } + case OSSIM_USHORT11: + case OSSIM_UINT16: + { + copyNormalizedBufferToTile((ossim_uint16)0, band, buf); + break; + } + case OSSIM_SINT16: + { + copyNormalizedBufferToTile((ossim_sint16)0, band, buf); + break; + } + case OSSIM_UINT32: + { + copyNormalizedBufferToTile((ossim_uint32)0, band, buf); + break; + } + case OSSIM_SINT32: + { + copyNormalizedBufferToTile((ossim_sint32)0, band, buf); + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageData::copyNormalizedBufferToTile\n" + << "Unknown scalar type!" << std::endl; + } + + } // End of "switch(getScalarType())". +} + +ossim_float64 ossimImageData::getMinNormalizedPix() const +{ + if (theScalarType == OSSIM_NORMALIZED_DOUBLE || + theScalarType == OSSIM_NORMALIZED_FLOAT) + { + return theMinPixelValue[0]; // Already normalized. + } + return (1.0 / (theMaxPixelValue[0] - theMinPixelValue[0] + 1.0)); +} + +std::ostream& ossimImageData::print(std::ostream& out) const +{ + out << "ossimImageData::print:" + << "\ntheOrigin: " << theOrigin << std::endl; + if(theNullPixelValue) + { + out << "Null values: "; + + copy(theNullPixelValue, + theNullPixelValue + getNumberOfBands(), + std::ostream_iterator<ossim_float64>(out, " ")); + out << "\n"; + } + if(theMinPixelValue) + { + out << "Min values: "; + + copy(theMinPixelValue, + theMinPixelValue + getNumberOfBands(), + std::ostream_iterator<ossim_float64>(out, " ")); + out << "\n"; + } + if(theMaxPixelValue) + { + out << "Max values: "; + + copy(theMaxPixelValue, + theMaxPixelValue + getNumberOfBands(), + std::ostream_iterator<ossim_float64>(out, " ")); + out << "\n"; + } + out << "width: " << getWidth() + << "\nheight: " << getHeight() + << "\nimage rectangle: " << getImageRectangle() + << std::endl; + + return ossimRectilinearDataObject::print(out); +} + +ossim_uint32 ossimImageData::getWidth()const +{ + if(theSpatialExtents) return theSpatialExtents[0]; + return 0; +} + +ossim_uint32 ossimImageData::getHeight()const +{ + if(theSpatialExtents) return theSpatialExtents[1]; + return 0; +} + +void ossimImageData::getWidthHeight(ossim_uint32& w, ossim_uint32& h) +{ + if(theSpatialExtents) + { + w = theSpatialExtents[0]; + h = theSpatialExtents[1]; + } +} + +void ossimImageData::setWidth(ossim_uint32 width) +{ + if(theSpatialExtents) + { + theSpatialExtents[0] = width; + } +} + +void ossimImageData::setHeight(ossim_uint32 height) +{ + if(theSpatialExtents) + { + theSpatialExtents[1] = height; + } +} + +void ossimImageData::setWidthHeight(ossim_uint32 w, ossim_uint32 h) +{ + if(theSpatialExtents) + { + theSpatialExtents[0] = w; + theSpatialExtents[1] = h; + } +} + +void ossimImageData::setOrigin(const ossimIpt& origin) +{ + theOrigin = origin; +} + +ossim_uint32 ossimImageData::getDataSizeInBytes()const +{ + return getSizeInBytes(); +} + +const ossimImageData& ossimImageData::operator=(const ossimImageData& /* rhs */) +{ + return *this; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimImageData.h b/Utilities/OSSIM/ossim_core/imaging/ossimImageData.h new file mode 100644 index 0000000000..0d89bc4f4e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimImageData.h @@ -0,0 +1,930 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: A brief description of the contents of the file. +// +//******************************************************************* +// $Id: ossimImageData.h,v 1.72 2005/11/14 21:38:01 dburken Exp $ +#ifndef ossimImageData_HEADER +#define ossimImageData_HEADER + +#include <vector> +using namespace std; + +#include <base/common/ossimRectilinearDataObject.h> +#include <base/data_types/ossimIrect.h> +#include <base/data_types/ossimIpt.h> +#include <base/common/ossimRefPtr.h> + +class ossimMultiBandHistogram; + +class OSSIMDLLEXPORT ossimImageData : public ossimRectilinearDataObject +{ +public: + ossimImageData(const ossimImageData &rhs); + + ossimImageData(ossimSource* source, + ossimScalarType scalar, + ossim_uint32 bands = 1); + + ossimImageData(ossimSource* source, + ossimScalarType scalar, + ossim_uint32 bands, + ossim_uint32 width, + ossim_uint32 height); + + virtual ~ossimImageData(); + + /** + * @return The width of the data object. + */ + virtual ossim_uint32 getWidth()const; + + /** + * @return The height of the data object. + */ + virtual ossim_uint32 getHeight()const; + + /** + * @return The image rectangle relative to origin, height and width. + */ + virtual ossimIrect getImageRectangle() const; + virtual void getWidthHeight(ossim_uint32& w, ossim_uint32& h); + virtual void setWidth(ossim_uint32 width); + virtual void setHeight(ossim_uint32 height); + virtual void setWidthHeight(ossim_uint32 w, ossim_uint32 h); + virtual void setImageRectangleAndBands(const ossimIrect& rect, + ossim_uint32 numberOfBands); + virtual void setImageRectangle(const ossimIrect& rect); + virtual void setOrigin(const ossimIpt& origin); + + virtual void assign(const ossimDataObject* data); + virtual void assign(const ossimImageData* data); + virtual void assignBand(const ossimImageData* data, + ossim_uint32 source_band, + ossim_uint32 output_band); + + virtual ossimObject* dup() const; + + /** + * Uses prime numbers as coefficients for this summation. + * Take the the fours bytes of each origin and multiply + * by the prime numbers and sum together. This has + * been proven by others to give nicely distributed + * id number. + */ + virtual ossim_uint32 getHashId()const; + + virtual void setNullPix(ossim_float64 null_pix); + virtual void setNullPix(ossim_float64 null_pix, ossim_uint32 band); + virtual void setNullPix(const ossim_float64* nullPixArray, + ossim_uint32 numberOfValues); + virtual void setMinPix(ossim_float64 min_pix); + virtual void setMinPix(ossim_float64 min_pix, ossim_uint32 band); + virtual void setMinPix(const ossim_float64* minPixArray, + ossim_uint32 numberOfValues); + virtual void setMaxPix(ossim_float64 max_pix); + virtual void setMaxPix(ossim_float64 max_pix, ossim_uint32 band); + virtual void setMaxPix(const ossim_float64* maxPixArray, + ossim_uint32 numberOfValues); + + virtual const ossimIpt& getOrigin()const{return theOrigin;} + + /** + * If the minBands and maxBands are empty or not equal to the imageData's + * current number of bands it will erase the contents, resize, and then + * replace the values in the passed in array with this objects min max + * values. If the arrays are the same size as this objects number of + * bands it will just update the values and use the current values in the + * arrays as initial min max values. + * + * If the status of this object(getDataObjectStatus()) is OSSIM_NULL or + * OSSIM_EMPTY no action is performed. + */ + virtual void computeMinMaxPix(vector<ossim_float64>& minBands, + vector<ossim_float64>& maxBands); + + virtual const ossim_float64* getNullPix()const; + virtual const ossim_float64* getMinPix()const; + virtual const ossim_float64* getMaxPix()const; + virtual ossim_float64 getNullPix(ossim_uint32 band) const; + virtual ossim_float64 getMinPix(ossim_uint32 band) const; + virtual ossim_float64 getMaxPix(ossim_uint32 band) const; + + /** + * returns normalized minimum pixel value of band zero. + */ + virtual ossim_float64 getMinNormalizedPix() const; + virtual ossimString getScalarTypeAsString()const; + virtual ossim_uint32 getNumberOfBands() const; + virtual void setNumberOfBands(ossim_uint32 bands, + bool reallocate=false); + + /** + * Will return the pixel at location position. Note it will first get + * the passed in position relative to the origin or upper left + * corner of this tile and then return the result. + */ + virtual ossim_float64 getPix(const ossimIpt& position, + ossim_uint32 band=0) const; + + /** + * Will return the pixel at offset and band number. + */ + virtual ossim_float64 getPix(ossim_uint32 offset, + ossim_uint32 band = 0) const; + + /** + * will fill the entire band with + * the value. + */ + void fill(ossim_uint32 band, ossim_float64 value); + + /** + * will fill all bands with the passed in + * value. + */ + void fill(ossim_float64 value); + bool isNull(ossim_uint32 offset)const; + bool isNull(ossim_uint32 offset, ossim_uint32 band)const; + void setNull(ossim_uint32 offset); + void setNull(ossim_uint32 offset, ossim_uint32 band); + + bool isNull(const ossimIpt& pt)const; + void setNull(const ossimIpt& pt); + bool isNull(const ossimIpt& pt, ossim_uint32 band)const; + void setNull(const ossimIpt& pt, ossim_uint32 band); + + virtual bool isValidBand(ossim_uint32 band) const; + virtual ossimDataObjectStatus validate() const; + + /** + * Will take this tile and normalize it to a newly + * allocated floating point tile. + */ + virtual ossimRefPtr<ossimImageData> newNormalizedFloat()const; + + /** + * will go to the band and offset and compute the + * normalized float and return it back to the + * caller through the result argument. + */ + virtual void getNormalizedFloat(ossim_uint32 offset, + ossim_uint32 bandNumber, + ossim_float32& result)const; + + /** + * This will assign to this object a normalized + * value by unnormalizing to its native type. + */ + virtual void setNormalizedFloat(ossim_uint32 offset, + ossim_uint32 bandNumber, + ossim_float32 input); + + /** + * Will use the memory that you pass in to normalize + * this data object. + */ + virtual void convertToNormalizedFloat(ossimImageData* result)const; + + /** + * Will take this tile and normalize it to a newly + * allocated double point tile. + */ + virtual ossimImageData* newNormalizedDouble()const; + + /** + * Will use the memory that you pass in to normalize + * this data object. + */ + virtual void convertToNormalizedDouble(ossimImageData* result)const; + + /** + * Will take the normalized input and convert it + * to this tile's data type. Example: if this + * tile is of type UCHAR and its input is of type + * NORALIZED_FLOAT it will unnormalize the data by + * doing: + * + * minPix + normalizedInput*(maxPix-minPix) + * + * on a per band basis. + */ + virtual void unnormalizeInput(ossimImageData* normalizedInput); + + /** + * This will compute the average value for the band. + */ + virtual ossim_float64 computeAverageBandValue( + ossim_uint32 bandNumber = 0) const; + + /** + * This will call the compute average band value and then + * use that in the calculation of: + + * It will then do a SUM[(Mean - Actual)^2]/width*height. + * + * This is the average variance from the passed in + * mean. + */ + virtual ossim_float64 computeMeanSquaredError( + ossim_float64 meanValue, + ossim_uint32 bandNumber = 0) const; + + virtual void populateHistogram(ossimMultiBandHistogram* histo); + + /** + * @return const void* to theDataBuffer + */ + virtual const void* getBuf() const; + + /** + * @return const ossim_uint8* to theDataBuffer if scalar is of type + * OSSIM_UCHAR; else, NULL. + */ + virtual const ossim_uint8* getUcharBuf() const; + + /** + * @return const ossim_uint16* to theDataBuffer if scalar is of type + * OSSIM_USHORT16 or USHORT11; else, NULL. + */ + virtual const ossim_uint16* getUshortBuf() const; + + /** + * @return const ossim_sint16* to theDataBuffer if scalar is of type + * OSSIM_SSHORT16; else, NULL. + */ + virtual const ossim_sint16* getSshortBuf() const; + + /** + * @return const ossim_float32* to theDataBuffer if scalar is of type + * OSSIM_FLOAT or OSSIM_NORMALIZED_FLOAT; else, NULL. + */ + virtual const ossim_float32* getFloatBuf() const; + + /** + * @return const ossim_float64* to theDataBuffer if scalar is of type + * OSSIM_DOUBLE or OSSIM_NORMALIZED_DOUBLE; else, NULL. + */ + virtual const ossim_float64* getDoubleBuf() const; + + /** + * @return void* to theDataBuffer + */ + virtual void* getBuf(); + + /** + * @return ossim_uint8* to theDataBuffer if scalar is of type + * OSSIM_UCHAR; else, NULL. + */ + virtual ossim_uint8* getUcharBuf(); + + /** + * @return ossim_uint16* to theDataBuffer if scalar is of type + * OSSIM_USHORT16 or OSSIM_USHORT11; else, NULL. + */ + virtual ossim_uint16* getUshortBuf(); + + /** + * @return ossim_sint16* to theDataBuffer if scalar is of type + * OSSIM_SSHORT16; else, NULL. + */ + virtual ossim_sint16* getSshortBuf(); + + /** + * @return ossim_float32* to theDataBuffer if scalar is of type + * OSSIM_FLOAT or OSSIM_NORMALIZED_FLOAT; else, NULL. + */ + virtual ossim_float32* getFloatBuf(); + + /** + * @return float64* to theDataBuffer if scalar is of type OSSIM_DOUBLE or + * OSSIM_NORMALIZED_DOUBLE; else, NULL. + */ + virtual ossim_float64* getDoubleBuf(); + + /** + * @param band (zero based) + * @return void* to theDataBuffer positioned at band. + */ + virtual const void* getBuf(ossim_uint32 band) const; + + /** + * @param band (zero based) + * @return ossim_uint8* to theDataBuffer positioned at band if scalar is + * of type OSSIM_UCHAR; else, NULL. + */ + virtual const ossim_uint8* getUcharBuf(ossim_uint32 band) const; + + /** + * @param band (zero based) + * @return ossim_uint16* to theDataBuffer positioned at band if scalar is + * of type OSSIM_USHORT16 or OSSIM_USHORT11; else, NULL. + */ + virtual const ossim_uint16* getUshortBuf(ossim_uint32 band) const; + + /** + * @param band (zero based) + * @return ossim_sint16* to theDataBuffer positioned at band if scalar is + * of type OSSIM_SSHORT16; else, NULL. + */ + virtual const ossim_sint16* getSshortBuf(ossim_uint32 band) const; + + /** + * @param band (zero based) + * @return ossim_float32* to theDataBuffer positioned at band if scalar is + * of type OSSIM_FLOAT or OSSIM_NORMALIZED_FLOAT; else, NULL. + */ + virtual const ossim_float32* getFloatBuf(ossim_uint32 band) const; + + /** + * @param band (zero based) + * @return ossim_float64* to theDataBuffer positioned at band if scalar is + * of type OSSIM_DOUBLE or OSSIM_NORMALIZED_DOUBLE; else, NULL. + */ + virtual const ossim_float64* getDoubleBuf(ossim_uint32 band) const; + + /** + * @param band (zero based) + * @return void* to theDataBuffer positioned at band. + */ + virtual void* getBuf(ossim_uint32 band); + + /** + * @param band (zero based) + * @return ossim_uint8* to theDataBuffer positioned at band if scalar is + * of type OSSIM_UCHAR; else, NULL. + */ + virtual ossim_uint8* getUcharBuf(ossim_uint32 band); + + /** + * @param band (zero based) + * @return ossim_uint16* to theDataBuffer positioned at band if scalar is + * of type OSSIM_USHORT16 or OSSIM_USHORT11; else, NULL. + */ + virtual ossim_uint16* getUshortBuf(ossim_uint32 band); + + /** + * @param band (zero based) + * @return ossim_sint16* to theDataBuffer positioned at band if scalar is + * of type OSSIM_SSHORT16; else, NULL. + */ + virtual ossim_sint16* getSshortBuf(ossim_uint32 band); + + /** + * @param band (zero based) + * @return ossim_float32* to theDataBuffer positioned at band if scalar is + * of type OSSIM_FLOAT or OSSIM_NORMALIZED_FLOAT; else, NULL. + */ + virtual ossim_float32* getFloatBuf(ossim_uint32 band); + + /** + * @param band (zero based) + * @return ossim_float64* to theDataBuffer positioned at band if scalar is + * of type OSSIM_DOUBLE or OSSIM_NORMALIZED_DOUBLE; else, NULL. + */ + virtual ossim_float64* getDoubleBuf(ossim_uint32 band); + + /** + * Returns the total number of pixels in a tile for all bands. + * Note: This is not in bytes but in pixels. + */ + virtual ossim_uint32 getSize() const; + + /** + * Returns the number of pixels in a single band in a tile. + * Note: This is not in bytes but in pixels. + */ + virtual ossim_uint32 getSizePerBand()const; + + /** + * Returns the number of bytes in single band of the tile. + */ + virtual ossim_uint32 getSizePerBandInBytes() const; + + virtual ossim_uint32 getDataSizeInBytes()const; + + /** + * Returns the total number of bytes for all bands. + */ + virtual ossim_uint32 getSizeInBytes() const; + + /** + * Initializes data to null pixel values. + */ + virtual void makeBlank(); + + /** + * Initialize the data buffer. + */ + virtual void initialize(); + + /** + * Copies entire tile to buf passed in. Data put in buf is normalized. + * The "buf" passed to method is assumed to be at least as big as: + * "getSize() * sizeof(double)" + */ + virtual void copyTileToNormalizedBuffer(ossim_float64* buf) const; + virtual void copyTileToNormalizedBuffer(ossim_float32* buf)const; + + /** + * Will copy this tiles specified band number to the normalized buffer. + * if the band is out of range then nothing is done and returns. + * + * @param band Zero based band to copy. + * + * @param buf Buffer to copy to. + */ + virtual void copyTileBandToNormalizedBuffer(ossim_uint32 band, + ossim_float64* buf) const; + + /** + * Will copy this tiles specified band number to the normalized buffer. + * if the band is out of range then nothing is done and returns. + * + * @param band Zero based band to copy. + * + * @param buf Buffer to copy to. + */ + virtual void copyTileBandToNormalizedBuffer(ossim_uint32 band, + ossim_float32* buf)const; + + /** + * Copies buf passed in to tile. Data is unnormalized to the tile's + * scalar type. + * The "buf" passed to method is assumed to be at least as big as the tiles: + * "getSize() * sizeof(double)" + */ + virtual void copyNormalizedBufferToTile(ossim_float64* buf); + virtual void copyNormalizedBufferToTile(ossim_float32* buf); + + /** + * Will copy the normalized buffer to this tiles + * specified band. If band is out of range then nothing + * + * is done and returns. + */ + virtual void copyNormalizedBufferToTile(ossim_uint32 band, + ossim_float64* buf); + virtual void copyNormalizedBufferToTile(ossim_uint32 band, + ossim_float32* buf); + + virtual bool isWithin(ossim_int32 x, ossim_int32 y); + virtual void setValue(ossim_int32 x, ossim_int32 y, ossim_float64 color); + + virtual void loadBand(const void* src, + const ossimIrect& src_rect, + ossim_uint32 band); + + virtual void loadBand(const void* src, + const ossimIrect& src_rect, + const ossimIrect& clip_rect, + ossim_uint32 band); + + virtual void loadTile(const void* src, + const ossimIrect& src_rect, + ossimInterleaveType il_type); + + virtual void loadTile(const void* src, + const ossimIrect& src_rect, + const ossimIrect& clip_rect, + ossimInterleaveType il_type); + + /** + * Will load a tile of different types. If they + * are the same then it will call loadTile(void*...) + * method. Note if they are of different types we + * will have to go through a much slower assign + * process by normalizing the right side and then + * unnormalizing to the destination type. For this + * method to work they both must have the same + * number of bands. + */ + virtual void loadTile(const ossimImageData* src); + + virtual void loadTileFrom1Band(const ossimImageData* data); + + virtual void loadTileFrom1Band(const void* src, + const ossimIrect& src_rect); + /** + * Specialized to load a tile from a short (16 bit scalar type) buffer. + * Performs byte swapping if swap_bytes is set to true. + */ + virtual void loadShortBand(const void* src, + const ossimIrect& src_rect, + ossim_uint32 band, + bool swap_bytes=false); + + virtual void unloadTile(void* dest, + const ossimIrect& dest_rect, + ossimInterleaveType il_type) const; + + virtual void unloadTile(void* dest, + const ossimIrect& dest_rect, + const ossimIrect& clip_rect, + ossimInterleaveType il_type) const; + + virtual void unloadBand(void* dest, + const ossimIrect& dest_rect, + ossim_uint32 band) const; + + virtual void unloadBand(void* dest, + const ossimIrect& dest_rect, + const ossimIrect& clip_rect, + ossim_uint32 band) const; + + + virtual bool isPointWithin(const ossimIpt& point)const; + virtual bool isPointWithin(ossim_int32 x, + ossim_int32 y)const; + + virtual std::ostream& print(std::ostream& out) const; + +protected: + ossimImageData(); + + /** + * Templated valide method. + * + * @return The status of the ossimImageDataMethod. + * + * @note See ossimConstants.h for ossimDataObjectStatus enumerations. + */ + template <class T> ossimDataObjectStatus validate(T dummyTemplate) const; + + /** + * Templated makeBlank method. + */ + template <class T> void makeBlank(T dummyTemplate); + + /** + * Templated computeMeanSquaredError method. + */ + template <class T> + ossim_float64 computeMeanSquaredError(T dummyTemplate, + ossim_float64 meanValue, + ossim_uint32 bandNumber) const; + + /** + * Templated computeAverageBandValue method. + */ + template <class T> + ossim_float64 computeAverageBandValue(T dummyTemplate, + ossim_uint32 bandNumber) const; + + /** + * + * Takes normPix, unnormalizes and initializes pixel. + * "band" is used as index to get the min/max/null values. + */ + void getPixFromNorm(ossim_int32& pixel, + ossim_float32 normPix, + ossim_uint32 band) const; + + + /** + * Takes normPix, unnormalizes and initializes pixel. + * "band" is used as index to get the min/max/null values. + */ + void getPixFromNorm(ossim_int32& pixel, + ossim_float64 normPix, + ossim_uint32 band) const; + + /** + * Take pixel, normalizes and initializes normPix. + * "band" is used as index to get the min/max/null values. + */ + void getNormFromPix (ossim_int32 pixel, + ossim_float32& normPix, + ossim_uint32 band) const; + + /** + * Take pixel, normalizes and initializes normPix. + * "band" is used as index to get the min/max/null values. + */ + void getNormFromPix (ossim_int32 pixel, + ossim_float64& normPix, + ossim_uint32 band) const; + + void loadTileFromBip(const void* src, const ossimIrect& src_rect); + void loadTileFromBil(const void* src, const ossimIrect& src_rect); + void loadTileFromBsq(const void* src, const ossimIrect& src_rect); + + void loadTileFromBip(const void* src, + const ossimIrect& src_rect, + const ossimIrect& clip_rect); + void loadTileFromBil(const void* src, + const ossimIrect& src_rect, + const ossimIrect& clip_rect); + void loadTileFromBsq(const void* src, + const ossimIrect& src_rect, + const ossimIrect& clip_rect); + + void unloadTileToBip(void* dest, + const ossimIrect& dest_rect, + const ossimIrect& clip_rect) const; + void unloadTileToBil(void* dest, + const ossimIrect& dest_rect, + const ossimIrect& clip_rect) const; + void unloadTileToBsq(void* dest, + const ossimIrect& dest_rect, + const ossimIrect& clip_rect) const; + + /** + * Copies entire tile to buf passed in. Data put in buf is normalized. + * The "buf" passed to method is assumed to be at least as big as: + * "getSize() * sizeof(double)" + */ + template <class T> + void copyTileToNormalizedBuffer(T dummyTemplate, + ossim_float64* buf) const; + template <class T> + void copyTileToNormalizedBuffer(T dummyTemplate, + ossim_float32* buf)const; + + /** + * Will copy this tiles specified band number to the normalized buffer. + * if the band is out of range then nothing is done and returns. + */ + template <class T> + void copyTileToNormalizedBuffer(T dummyTemplate, + ossim_uint32 band, ossim_float64* buf) const; + template <class T> + void copyTileToNormalizedBuffer(T dummyTemplate, + ossim_uint32 band, ossim_float32* buf)const; + + /** + * Copies buf passed in to tile. Data is unnormalized to the tile's + * scalar type. + * The "buf" passed to method is assumed to be at least as big as the tiles: + * "getSize() * sizeof(double)" + */ + template <class T> + void copyNormalizedBufferToTile(T dummyTemplate, + ossim_float64* buf); + template <class T> + void copyNormalizedBufferToTile(T dummyTemplate, + ossim_float32* buf); + template <class T> + void copyNormalizedBufferToTile(T dummyTemplate, + ossim_uint32 band, + ossim_float64* buf); + template <class T> + void copyNormalizedBufferToTile(T dummyTemplate, + ossim_uint32 band, + ossim_float32* buf); + + + template <class T> void computeMinMaxPix(T dummyValue, + vector<ossim_float64>& minBands, + vector<ossim_float64>& maxBands); + + template <class T> void loadBand(T, // dummy template variable + const void* src, + const ossimIrect& src_rect, + ossim_uint32 band); + + template <class T> void loadBand(T, // dummy template variable + const void* src, + const ossimIrect& src_rect, + const ossimIrect& clip_rect, + ossim_uint32 band); + + template <class T> void loadTileFromBip(T, // dummy template variable + const void* src, + const ossimIrect& src_rect); + + template <class T> void loadTileFromBip(T, // dummy template variable + const void* src, + const ossimIrect& src_rect, + const ossimIrect& clip_rect); + + template <class T> void loadTileFromBil(T, // dummy template variable + const void* src, + const ossimIrect& src_rect); + + template <class T> void loadTileFromBil(T, // dummy template variable + const void* src, + const ossimIrect& src_rect, + const ossimIrect& clip_rect); + + template <class T> void loadTileFromBsq(T, // dummy template variable + const void* src, + const ossimIrect& src_rect); + + template <class T> void loadTileFromBsq(T, // dummy template variable + const void* src, + const ossimIrect& src_rect, + const ossimIrect& clip_rect); + + template <class T> void unloadTileToBip(T, // dummy tmeplate variable + void* dest, + const ossimIrect& dest_rect, + const ossimIrect& clip_rect) const; + + template <class T> void unloadTileToBil(T, // dummy tmeplate variable + void* dest, + const ossimIrect& dest_rect, + const ossimIrect& clip_rect) const; + + template <class T> void unloadTileToBsq(T, // dummy tmeplate variable + void* dest, + const ossimIrect& dest_rect, + const ossimIrect& clip_rect) const; + + template <class T> void unloadBand(T, // dummy tmeplate variable + void* dest, + const ossimIrect& dest_rect, + const ossimIrect& clip_rect, + ossim_uint32 band) const; + + virtual void initializeDefaults(); + + virtual bool isEqualTo(const ossimDataObject& rhs, + bool deepTest=false)const; + + bool hasSameDimensionsAs(ossimImageData* data)const + { + if(!data) return false; + return ((theNumberOfSpatialComponents == + data->theNumberOfSpatialComponents)& + (theSpatialExtents[0] == data->theSpatialExtents[0])&& + (theSpatialExtents[1] == data->theSpatialExtents[1])&& + (theScalarType == data->theScalarType)); + } + + /** + * Have a null pixel value per band. + */ + ossim_float64* theNullPixelValue; + + /** + * Have a min pixel value per band. + */ + ossim_float64* theMinPixelValue; + + /** + * Have a max pixel value per band. + */ + ossim_float64* theMaxPixelValue; + + ossimIpt theOrigin; + +private: + /** + * @note disallow + */ + const ossimImageData& operator=(const ossimImageData &rhs); + +TYPE_DATA +}; + +inline void ossimImageData::getPixFromNorm(ossim_int32& pixel, + ossim_float32 normPix, + ossim_uint32 band) const +{ + // If norm pix is 0.0 or negative make if null. + ossim_float32 p = theNullPixelValue[band]; + + if (normPix > 0.0) + { + // un-normalize... + p = normPix * (theMaxPixelValue[band]-theMinPixelValue[band]+1.0); + + // handle negative min values. + p = p + theMinPixelValue[band] - 1.0; + + // Clamp to max. + if (p > theMaxPixelValue[band]) p = theMaxPixelValue[band]; + + //*** + // If p is less than min, make it min as it wasn't a null before. + // Add or subtract 0.5 to p otherwise as it will be cast to an + // int for proper rounding. + //*** + p = p > theMinPixelValue[band] ? + ( p<0.0 ? p-0.5 : p+0.5 ) : + theMinPixelValue[band]; + } + + // Cast back to an int. + pixel = static_cast<ossim_int32>(p); +} + +inline void ossimImageData::getPixFromNorm(ossim_int32& pixel, + ossim_float64 normPix, + ossim_uint32 band) const +{ + // If norm pix is 0.0 or negative make if null. + ossim_float64 p = theNullPixelValue[band]; + + if (normPix > 0.0) + { + // un-normalize... + p = normPix * (theMaxPixelValue[band]-theMinPixelValue[band]+1.0); + + // handle negative min values. + p = p + theMinPixelValue[band] - 1.0; + + // Clamp to max. + if (p > theMaxPixelValue[band]) p = theMaxPixelValue[band]; + + //*** + // If p is less than min, make it min as it wasn't a null before. + // Add or subtract 0.5 to p otherwise as it will be cast to an + // int for proper rounding. + //*** + p = p > theMinPixelValue[band] ? + ( p<0.0 ? p-0.5 : p+0.5 ) : + theMinPixelValue[band]; + } + + // Cast back to an int. + pixel = static_cast<ossim_int32>(p); +} + +inline void ossimImageData::getNormFromPix(ossim_int32 pixel, + ossim_float32& normPix, + ossim_uint32 band) const +{ + if (pixel == theNullPixelValue[band]) normPix = 0.0; + else if (pixel >= theMaxPixelValue[band]) normPix = 1.0; + + //*** + // Normalize... + // Note that this will shift any negatives to positive prior to dividing. + //*** + else normPix = ( (pixel-theMinPixelValue[band]+1) / + (theMaxPixelValue[band] - theMinPixelValue[band] + 1.0) ); +} + +inline void ossimImageData::getNormFromPix(ossim_int32 pixel, + ossim_float64& normPix, + ossim_uint32 band) const +{ + if (pixel == theNullPixelValue[band]) normPix = 0.0; + else if (pixel >= theMaxPixelValue[band]) normPix = 1.0; + + //*** + // Normalize... + // Note that this will shift any negatives to positive prior to dividing. + //*** + else normPix = ( (pixel-theMinPixelValue[band]+1) / + (theMaxPixelValue[band] - theMinPixelValue[band] + 1.0) ); +} + +inline ossimIrect ossimImageData::getImageRectangle() const +{ + ossimIpt lr(theOrigin.x + getWidth() - 1, + theOrigin.y + getHeight() - 1); + + return ossimIrect(theOrigin, lr); +} + +inline const ossim_float64* ossimImageData::getNullPix()const +{ + return theNullPixelValue; +} + +inline const ossim_float64* ossimImageData::getMinPix()const +{ + return theMinPixelValue; +} + +inline const ossim_float64* ossimImageData::getMaxPix()const +{ + return theMaxPixelValue; +} + +inline ossim_float64 ossimImageData::getNullPix(ossim_uint32 band) const +{ + return theNullPixelValue[band]; +} + +inline ossim_float64 ossimImageData::getMinPix(ossim_uint32 band) const +{ + return theMinPixelValue[band]; +} + +inline ossim_float64 ossimImageData::getMaxPix(ossim_uint32 band) const +{ + return theMaxPixelValue[band]; +} + +inline ossim_uint32 ossimImageData::getHashId()const +{ + const unsigned char *bufx = (unsigned char*)(&theOrigin.x); + const unsigned char *bufy = (unsigned char*)(&theOrigin.y); + return (ossim_uint32)(bufx[0]*101 + bufx[1]*103 + + bufx[2]*107 + bufx[3]*109 + + bufy[0]*139 + bufy[1]*149 + + bufy[2]*151 + bufy[3]*157); +} + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimImageDataHelper.cpp b/Utilities/OSSIM/ossim_core/imaging/ossimImageDataHelper.cpp new file mode 100644 index 0000000000..32803b4921 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimImageDataHelper.cpp @@ -0,0 +1,604 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimImageDataHelper.cpp,v 1.6 2005/05/09 12:39:38 dburken Exp $ +#include "ossimImageDataHelper.h" +#include "base/data_types/ossimPolyArea2d.h" +#include "base/data_types/ossimLine.h" +#include <vector> +#include <algorithm> + +ossimImageDataHelper::ossimImageDataHelper(ossimImageData* imageData) +{ + setImageData(imageData); +} + + +void ossimImageDataHelper::setImageData(ossimImageData* imageData) +{ + theImageData = imageData; + if(theImageData) + { + theImageRectangle = theImageData->getImageRectangle(); + thePolyImageRectangle = ossimPolyArea2d(theImageRectangle.ul(), + theImageRectangle.ur(), + theImageRectangle.lr(), + theImageRectangle.ll()); + theOrigin = theImageRectangle.ul(); + } +} + +void ossimImageDataHelper::copyInputToThis(const void* input, + const ossimPolygon& region, + bool clipPoly) +{ + switch(theImageData->getScalarType()) + { + case OSSIM_UCHAR: + { + copyInputToThis(reinterpret_cast<const ossim_uint8*>(input), + region, + clipPoly); + break; + } + case OSSIM_USHORT16: + case OSSIM_USHORT11: + { + copyInputToThis(reinterpret_cast<const ossim_uint16*>(input), + region, + clipPoly); + break; + } + case OSSIM_SSHORT16: + { + copyInputToThis(reinterpret_cast<const ossim_sint16*>(input), + region, + clipPoly); + break; + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + copyInputToThis(reinterpret_cast<const float*>(input), + region, + clipPoly); + break; + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + copyInputToThis(reinterpret_cast<const double*>(input), + region, + clipPoly); + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + break; + } + } +} + +void ossimImageDataHelper::fill(const ossimRgbVector& color, + std::vector<ossimPolygon>& regionList, + bool clipPoly) +{ + int i = 0; + + for(i = 0; i < (int)regionList.size();++i) + { + fill(color, + regionList[i], + clipPoly); + } +} + + +void ossimImageDataHelper::fill(const double* values, + std::vector<ossimPolygon>& regionList, + bool clipPoly) +{ + int i = 0; + + for(i = 0; i < (int)regionList.size();++i) + { + fill(values, + regionList[i], + clipPoly); + } +} + +void ossimImageDataHelper::fill(const ossimRgbVector& color, + const ossimPolygon& region, + bool clipPoly) +{ + double colorArray[3]; + + colorArray[0] = color.getR(); + colorArray[1] = color.getG(); + colorArray[2] = color.getB(); + switch(theImageData->getScalarType()) + { + case OSSIM_UCHAR: + { + if(theImageData->getNumberOfBands() <= 3) + { + fill(static_cast<ossim_uint8>(0), + (const double*)colorArray, + region, + clipPoly); + + } + break; + } + case OSSIM_SCALAR_UNKNOWN: + case OSSIM_USHORT16: + case OSSIM_USHORT11: + case OSSIM_SSHORT16: + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + default: + { + break; + } + } +} + +void ossimImageDataHelper::fill(const ossimRgbVector& color, + const ossimIrect& region, + bool clipPoly) +{ + double colorArray[3]; + + colorArray[0] = color.getR(); + colorArray[1] = color.getG(); + colorArray[2] = color.getB(); + + switch(theImageData->getScalarType()) + { + case OSSIM_UCHAR: + { + if(theImageData->getNumberOfBands() <= 3) + { + fill(static_cast<ossim_uint8>(0), + colorArray, + region, + clipPoly); + + } + break; + } + case OSSIM_SCALAR_UNKNOWN: + case OSSIM_USHORT16: + case OSSIM_USHORT11: + case OSSIM_SSHORT16: + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + break; + } + default: + break; + } +} + +void ossimImageDataHelper::fill(const double* values, + const ossimPolygon& region, + bool clipPoly) +{ + switch(theImageData->getScalarType()) + { + case OSSIM_UCHAR: + { + fill(static_cast<ossim_uint8>(0), + values, + region, + clipPoly); + break; + } + case OSSIM_USHORT16: + case OSSIM_USHORT11: + { + fill(static_cast<ossim_uint16>(0), + values, + region, + clipPoly); + break; + } + case OSSIM_SSHORT16: + { + fill(static_cast<ossim_sint16>(0), + values, + region, + clipPoly); + break; + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + fill(static_cast<float>(0), + values, + region, + clipPoly); + break; + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + fill(static_cast<double>(0), + values, + region, + clipPoly); + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + break; + } + } +} + +void ossimImageDataHelper::fill(const double* values, + const ossimIrect& region, + bool clipPoly) +{ + switch(theImageData->getScalarType()) + { + case OSSIM_UCHAR: + { + fill(static_cast<ossim_uint8>(0), + values, + region, + clipPoly); + break; + } + case OSSIM_USHORT16: + case OSSIM_USHORT11: + { + fill(static_cast<ossim_uint16>(0), + values, + region, + clipPoly); + break; + } + case OSSIM_SSHORT16: + { + fill(static_cast<ossim_sint16>(0), + values, + region, + clipPoly); + break; + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + fill(static_cast<float>(0), + values, + region, + clipPoly); + break; + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + fill(static_cast<double>(0), + values, + region, + clipPoly); + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + break; + } + } +} + + + +template <class T> +void ossimImageDataHelper::copyInputToThis(const T* inputBuf, + const ossimPolygon& region, + bool clipPoly) +{ + if(clipPoly) + { + ossimPolyArea2d polyArea(region); + ossimPolyArea2d clipArea = polyArea&thePolyImageRectangle; + + vector<ossimPolygon> clipList; + clipArea.getAllVisiblePolygons(clipList); + int i = 0; + + for(i = 0; i < (int)clipList.size();++i) + { + copyInputToThis(inputBuf, + clipList[i]); + } + } + else + { + copyInputToThis(inputBuf, + region); + } +} + +template <class T> +void ossimImageDataHelper::copyInputToThis(const T* inputBuf, + const ossimPolygon& region) +{ + int n; + int i; + int y; + ossim_int32 miny, maxy, minx, maxx; + int x1, y1; + int x2, y2; + int ind1, ind2; + int ints; + vector<int> polyInts; + T* buf = reinterpret_cast<T*>(theImageData->getBuf()); + + ossim_int32 blockLength=theImageData->getWidth()*theImageData->getHeight(); + ossim_int32 bandOffset = 0; + + region.getIntegerBounds(minx, miny, maxx, maxy); + ossim_int32 rowOffset = (miny-theOrigin.y)*theImageData->getWidth(); + n = region.getVertexCount(); + /* Fix in 1.3: count a vertex only once */ + for (y = miny; (y <= maxy); y++) + { + polyInts.clear(); + ints = 0; + for (i = 0; (i < n); i++) + { + if (!i) + { + ind1 = n - 1; + ind2 = 0; + } + else + { + ind1 = i - 1; + ind2 = i; + } + y1 = irint(region[ind1].y); + y2 = irint(region[ind2].y); + if (y1 < y2) + { + x1 = irint(region[ind1].x); + x2 = irint(region[ind2].x); + } + else if (y1 > y2) + { + y2 = irint(region[ind1].y); + y1 = irint(region[ind2].y); + x2 = irint(region[ind1].x); + x1 = irint(region[ind2].x); + } + else + { + continue; + } + if ((y >= y1) && (y < y2)) + { + polyInts.push_back((y - y1) * (x2 - x1) / (y2 - y1) + x1); + } + else if ((y == maxy) && (y > y1) && (y <= y2)) + { + polyInts.push_back((y - y1) * (x2 - x1) / (y2 - y1) + x1); + } + } + std::sort(polyInts.begin(), polyInts.end()); + + for (i = 0; (i < (int)polyInts.size()); i += 2) + { + ossim_int32 startX = polyInts[i]-theOrigin.x; + ossim_int32 endX = polyInts[i+1]-theOrigin.x; + while(startX <= endX) + { + bandOffset = 0; + int band; + for(band = 0; band < (ossim_int32)theImageData->getNumberOfBands();++band) + { + buf[rowOffset+bandOffset+startX] = (inputBuf[rowOffset+bandOffset+startX]); + bandOffset += blockLength; + } + ++startX; + } + } + rowOffset += theImageData->getWidth(); + } +} + +template <class T> +void ossimImageDataHelper::fill(T dummyVariable, + const double* values, + const ossimPolygon& region, + bool clipPoly) +{ + if(clipPoly) + { + ossimPolyArea2d polyArea(region); + ossimPolyArea2d clipArea = polyArea&thePolyImageRectangle; + + vector<ossimPolygon> clipList; + clipArea.getAllVisiblePolygons(clipList); + + int i = 0; + for(i = 0; i < (int)clipList.size();++i) + { + fill(dummyVariable, + values, + clipList[i]); + } + } + else + { + fill(dummyVariable, + values, + region); + } +} + +template <class T> +void ossimImageDataHelper::fill(T dummyVariable, + const double* values, + const ossimIrect& region, + bool clipPoly) +{ + if(clipPoly) + { + fill(dummyVariable, + values, + region.clipToRect(theImageData->getImageRectangle())); + } + else + { + fill(dummyVariable, + values, + region); + } +} + +template <class T> +void ossimImageDataHelper::fill(T dummyVariable, + const double* values, + const ossimPolygon& region) +{ + int n; + int i; + int y; + ossim_int32 miny, maxy, minx, maxx; + int x1, y1; + int x2, y2; + int ind1, ind2; + int ints; + vector<int> polyInts; + T* buf = reinterpret_cast<T*>(theImageData->getBuf()); + + ossim_int32 blockLength=theImageData->getWidth()*theImageData->getHeight(); + ossim_int32 bandOffset = 0; + + region.getIntegerBounds(minx, miny, maxx, maxy); + ossim_int32 rowOffset = (miny-theOrigin.y)*theImageData->getWidth(); + n = region.getVertexCount(); + /* Fix in 1.3: count a vertex only once */ + for (y = miny; (y <= maxy); y++) + { + polyInts.clear(); + ints = 0; + for (i = 0; (i < n); i++) + { + if (!i) + { + ind1 = n - 1; + ind2 = 0; + } + else + { + ind1 = i - 1; + ind2 = i; + } + y1 = irint(region[ind1].y); + y2 = irint(region[ind2].y); + if (y1 < y2) + { + x1 = irint(region[ind1].x); + x2 = irint(region[ind2].x); + } + else if (y1 > y2) + { + y2 = irint(region[ind1].y); + y1 = irint(region[ind2].y); + x2 = irint(region[ind1].x); + x1 = irint(region[ind2].x); + } + else + { + continue; + } + if ((y >= y1) && (y < y2)) + { + polyInts.push_back((y - y1) * (x2 - x1) / (y2 - y1) + x1); + } + else if ((y == maxy) && (y > y1) && (y <= y2)) + { + polyInts.push_back((y - y1) * (x2 - x1) / (y2 - y1) + x1); + } + } + std::sort(polyInts.begin(), polyInts.end()); + + for (i = 0; (i < (int)polyInts.size()); i += 2) + { + ossim_int32 startX = ossimAbs(polyInts[i]-theOrigin.x); + ossim_int32 endX = ossimAbs(polyInts[i+1]-theOrigin.x); + while(startX <= endX) + { + bandOffset = 0; + int band; + for(band = 0; band < (int)theImageData->getNumberOfBands();++band) + { + buf[rowOffset+bandOffset+startX] = (T)(values[band]); + bandOffset += blockLength; + } + ++startX; + } + } + rowOffset += theImageData->getWidth(); + } +} + +template <class T> +void ossimImageDataHelper::fill(T dummyVariable, + const double* values, + const ossimIrect& region) +{ + T* buf = reinterpret_cast<T*>(theImageData->getBuf()); + + ossim_int32 blockLength=theImageData->getWidth()*theImageData->getHeight(); + ossim_int32 bandOffset = 0; + ossim_int32 miny,maxy; + ossim_int32 minx, maxx; + ossim_int32 y = 0; + miny = region.ul().y-theOrigin.y; + maxy = region.lr().y-theOrigin.y; + minx = region.ul().x-theOrigin.x; + maxx = region.lr().x-theOrigin.x; + + ossim_int32 rowOffset = (miny)*theImageData->getWidth(); + ossim_int32 startX = minx; + ossim_int32 endX = maxx; + ossim_int32 bands = (ossim_int32)theImageData->getNumberOfBands(); + + for (y = miny; (y <= maxy); ++y) + { + startX=minx; + while(startX <= endX) + { + bandOffset = 0; + int band = 0; + for(band = 0; band < bands;++band) + { + buf[rowOffset+bandOffset+startX] = (T)(values[band]); + bandOffset += blockLength; + } + ++startX; + } + rowOffset += theImageData->getWidth(); + } +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimImageDataHelper.h b/Utilities/OSSIM/ossim_core/imaging/ossimImageDataHelper.h new file mode 100644 index 0000000000..defe2e39bf --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimImageDataHelper.h @@ -0,0 +1,115 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossimImageDataHelper.h,v 1.2 2002/05/03 16:41:25 gpotts Exp $ +#ifndef ossimImageDataHelper_HEADER +#define ossimImageDataHelper_HEADER + +#include "ossimImageData.h" +#include "base/data_types/ossimPolyArea2d.h" +#include "base/data_types/color_space/ossimRgbVector.h" + +class ossimImageDataHelper +{ +public: + /*! + * This must be a valid image data object + */ + ossimImageDataHelper(ossimImageData* imageData); + + void setImageData(ossimImageData* imageData); + + void fill(const double* values, + const ossimIrect& rect, + bool clipPoly=true); + + void fill(const double* values, + std::vector<ossimPolygon>& regionList, + bool clipPoly=true); + + void fill(const ossimRgbVector& color, + std::vector<ossimPolygon>& regionList, + bool clipPoly=true); + + void fill(const ossimRgbVector& color, + const ossimIrect& rect, + bool clipPoly=true); + /*! + * Values must be of the same type as the image data that + * we are writing to. + */ + void fill(const double* values, + const ossimPolygon& region, + bool clipPoly=true); + + void fill(const ossimRgbVector& color, + const ossimPolygon& region, + bool clipPoly=true); + /*! + * The input is assumed to have the same origin, size and scalar + * as this object. This will implement a selection + */ + void copyInputToThis(const void* input, + const ossimPolygon& region, + bool clipPoly=true); + + ossimImageData* theImageData; + + +protected: + ossimIpt theOrigin; + ossimIrect theImageRectangle; + ossimPolyArea2d thePolyImageRectangle; + + template <class T> + void fill(T dummyVariable, + const double* values, + const ossimPolygon& region, + bool clipPoly); + + template <class T> + void fill(T dummyVariable, + const double* values, + const ossimIrect& region, + bool clipPoly); + + template <class T> + void copyInputToThis(const T* inputBuf, + const ossimPolygon& region, + bool clipPoly); + + template <class T> + void fill(T dummyVariable, + const double* values, + const ossimPolygon& region); + template <class T> + void fill(T dummyVariable, + const double* values, + const ossimIrect& region); + + template <class T> + void copyInputToThis(const T* inputBuf, + const ossimPolygon& region); + + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimImageDisplayWriter.cpp b/Utilities/OSSIM/ossim_core/imaging/ossimImageDisplayWriter.cpp new file mode 100644 index 0000000000..80c87cb5a8 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimImageDisplayWriter.cpp @@ -0,0 +1,52 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Frank Warmerdam (warmerdam@pobox.com) +// +// Description: +// +// Contains class declaration for ossimImageWriter +//******************************************************************* +// $Id: ossimImageDisplayWriter.cpp,v 1.3 2003/05/13 11:31:03 dburken Exp $ +#include "ossimImageDisplayWriter.h" + +RTTI_DEF3(ossimImageDisplayWriter, "ossimImageDisplayWriter", ossimImageWriter, ossimDisplayInterface, ossimConnectableObjectListener); + +ossimImageDisplayWriter::ossimImageDisplayWriter(ossimObject* owner) + :ossimImageWriter(owner, + 1, + 0, + true, + true), + ossimConnectableObjectListener() +{ +} + +ossimImageDisplayWriter::ossimImageDisplayWriter(ossimObject* owner, + ossim_uint32 numberOfInputs, + ossim_uint32 numberOfOutputs, + bool inputListIsFixed, + bool outputListIsFixed) + : ossimImageWriter(owner, + numberOfInputs, + numberOfOutputs, + inputListIsFixed, + outputListIsFixed), + ossimConnectableObjectListener() +{ +} diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimImageDisplayWriter.h b/Utilities/OSSIM/ossim_core/imaging/ossimImageDisplayWriter.h new file mode 100644 index 0000000000..4e969fc789 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimImageDisplayWriter.h @@ -0,0 +1,90 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Frank Warmerdam (warmerdam@pobox.com) +// +// Description: +// +// Contains class declaration for ossimImageWriter +//******************************************************************* +// $Id: ossimImageDisplayWriter.h,v 1.13 2003/05/13 11:31:03 dburken Exp $ +#ifndef ossimImageDisplayWriter_HEADER +#define ossimImageDisplayWriter_HEADER + +#include "imaging/ossimImageWriter.h" +#include "base/data_types/ossimFilename.h" +#include "base/common/events/ossimConnectableObjectListener.h" +#include "base/common/ossimDisplayInterface.h" +#include "base/common/events/ossimObjectEvents.h" +#include "base/common/events/ossimProcessProgressEvent.h" + +class ossimImageDisplayWriter : public ossimImageWriter, + public ossimDisplayInterface, + public ossimConnectableObjectListener + +{ +public: + virtual ~ossimImageDisplayWriter(){} + + + bool canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const + { + + return (object&& PTR_CAST(ossimImageSourceInterface, object)); + } + virtual void setOutputName(const ossimString& out) + { + setTitle(out); + } + + /*! + * Sets the title of a display. + */ + virtual void setTitle( const ossimString& title )=0; + + /*! + * will return true if its minimized + */ + virtual bool isMinimized()const=0; + + virtual bool isMaximized()const=0; + /*! + * Will repaint the display + */ + virtual void refreshDisplay()=0; + + + virtual void minimize()=0; + + virtual void maximize()=0; + /*! + * Will show a display + */ + virtual void show()=0; + +protected: + ossimImageDisplayWriter(ossimObject* owner=NULL); + ossimImageDisplayWriter(ossimObject* owner, + ossim_uint32 numberOfInputs, + ossim_uint32 numberOfOutputs, + bool inputListIsFixed, + bool outputListIsFixed); +TYPE_DATA +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimImageMetaData.cpp b/Utilities/OSSIM/ossim_core/imaging/ossimImageMetaData.cpp new file mode 100644 index 0000000000..34b5c3e4ba --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimImageMetaData.cpp @@ -0,0 +1,476 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +// Contains class definition for ossimImageMetaData. +// +//******************************************************************* +// $Id: ossimImageMetaData.cpp,v 1.14 2005/10/16 21:18:58 dburken Exp $ +#include <vector> +#include <algorithm> +#include <imaging/ossimImageMetaData.h> +#include <base/common/ossimKeywordNames.h> +#include <base/data_types/ossimString.h> +#include <base/misc/lookup_tables/ossimScalarTypeLut.h> +#include <base/common/ossimTrace.h> + +static ossimTrace traceDebug("ossimImageMetaData:debug"); + +ossimImageMetaData::ossimImageMetaData() + :theNullPixelArray(NULL), + theMinPixelArray(NULL), + theMaxPixelArray(NULL), + theScalarType(OSSIM_SCALAR_UNKNOWN), + theNumberOfBands(0) +{ +} + +ossimImageMetaData::ossimImageMetaData(ossimScalarType aType, + ossim_uint32 numberOfBands) + :theNullPixelArray(NULL), + theMinPixelArray(NULL), + theMaxPixelArray(NULL), + theScalarType(aType), + theNumberOfBands(numberOfBands) +{ + if(theNumberOfBands) + { + theNullPixelArray = new double[theNumberOfBands]; + theMinPixelArray = new double[theNumberOfBands]; + theMaxPixelArray = new double[theNumberOfBands]; + + setDefaultsForArrays(); + } +} + +ossimImageMetaData::ossimImageMetaData(const ossimImageMetaData& rhs) +{ + assign(rhs); +} + +ossimImageMetaData::~ossimImageMetaData() +{ + clear(); +} + +void ossimImageMetaData::clear() +{ + if(theNullPixelArray) + { + delete [] theNullPixelArray; + theNullPixelArray = NULL; + } + if(theMinPixelArray) + { + delete [] theMinPixelArray; + theMinPixelArray = NULL; + } + if(theMaxPixelArray) + { + delete [] theMaxPixelArray; + theMaxPixelArray = NULL; + } + theScalarType = OSSIM_SCALAR_UNKNOWN; + theNumberOfBands = 0; +} + +void ossimImageMetaData::clearBandInfo() +{ + if(theNullPixelArray) + { + delete [] theNullPixelArray; + theNullPixelArray = NULL; + } + if(theMinPixelArray) + { + delete [] theMinPixelArray; + theMinPixelArray = NULL; + } + if(theMaxPixelArray) + { + delete [] theMaxPixelArray; + theMaxPixelArray = NULL; + } + theScalarType = OSSIM_SCALAR_UNKNOWN; + theNumberOfBands = 0; +} + +void ossimImageMetaData::setDefaultsForArrays() +{ + ossim_uint32 i=0; + + for(i = 0; i < theNumberOfBands; ++i) + { + theNullPixelArray[i] = ossimGetDefaultNull(theScalarType); + theMinPixelArray[i] = ossimGetDefaultMin(theScalarType); + theMaxPixelArray[i] = ossimGetDefaultMax(theScalarType); + } +} + +void ossimImageMetaData::setNumberOfBands(ossim_uint32 numberOfBands) +{ + if(theNullPixelArray) + { + delete [] theNullPixelArray; + theNullPixelArray = NULL; + } + if(theMinPixelArray) + { + delete [] theMinPixelArray; + theMinPixelArray = NULL; + } + if(theMaxPixelArray) + { + delete [] theMaxPixelArray; + theMaxPixelArray = NULL; + } + + theNumberOfBands = numberOfBands; + + if(theNumberOfBands) + { + theNullPixelArray = new double[theNumberOfBands]; + theMinPixelArray = new double[theNumberOfBands]; + theMaxPixelArray = new double[theNumberOfBands]; + + setDefaultsForArrays(); + } +} + +void ossimImageMetaData::assign(const ossimImageMetaData& rhs) +{ + if(this != &rhs) + { + clear(); + theNumberOfBands = rhs.getNumberOfBands(); + theScalarType = rhs.getScalarType(); + + if(theNumberOfBands) + { + theNullPixelArray = new double[theNumberOfBands]; + theMinPixelArray = new double[theNumberOfBands]; + theMaxPixelArray = new double[theNumberOfBands]; + + std::copy(rhs.getNullPixelArray(), + rhs.getNullPixelArray()+theNumberOfBands, + theNullPixelArray); + std::copy(rhs.getMinPixelArray(), + rhs.getMinPixelArray()+theNumberOfBands, + theMinPixelArray); + std::copy(rhs.getMaxPixelArray(), + rhs.getMaxPixelArray()+theNumberOfBands, + theMaxPixelArray); + } + } +} + +bool ossimImageMetaData::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + static const char MODULE[] = "ossimImageMetaData::loadState"; + + if (traceDebug()) + { + CLOG << " Entered..." + << "\nkwl:\n" << kwl + << "\nprefix: " << (prefix?prefix:"") << endl; + } + + bool result = true; + clear(); + + ossim_int32 scalar = + ossimScalarTypeLut::instance()->getEntryNumber(kwl, prefix); + if (scalar == ossimLookUpTable::NOT_FOUND) + { + theScalarType = OSSIM_SCALAR_UNKNOWN; + } + else + { + theScalarType = static_cast<ossimScalarType>(scalar); + } + + if (traceDebug()) + { + CLOG << "DEBUG:" + << "\ntheScalarType: " << theScalarType << endl; + } + + const char* kwlLookup = kwl.find(prefix, ossimKeywordNames::NUMBER_BANDS_KW); + if (kwlLookup) + { + theNumberOfBands = ossimString(kwlLookup).toInt(); + setNumberOfBands(theNumberOfBands); + } + + loadBandInfo(kwl, prefix); + + if(!theNumberOfBands) + { + result = false; + } + return result; +} + +void ossimImageMetaData::loadBandInfo(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimString copyPrefix = prefix; + ossimString regExpression = ossimString("^(") + copyPrefix + "band[0-9]+.)"; + vector<ossimString> keys = + kwl.getSubstringKeyList( regExpression ); + + ossim_uint32 numberOfBands = keys.size(); + theMinValuesValidFlag = true; + theMaxValuesValidFlag = true; + theNullValuesValidFlag = true; + + if(!numberOfBands) + { + theMinValuesValidFlag = false; + theMaxValuesValidFlag = false; + theNullValuesValidFlag = false; + return; + } + if((!theNumberOfBands)|| + (theNumberOfBands != numberOfBands)) + { + setNumberOfBands(numberOfBands); + } + + int offset = (copyPrefix+"band").size(); + int idx = 0; + std::vector<int> theNumberList(numberOfBands); + for(idx = 0; idx < (int)theNumberList.size();++idx) + { + ossimString numberStr(keys[idx].begin() + offset, + keys[idx].end()); + theNumberList[idx] = numberStr.toInt(); + } + std::sort(theNumberList.begin(), theNumberList.end()); + for(idx=0;idx < (int)theNumberList.size();++idx) + { + ossimString newPrefix = copyPrefix; + newPrefix += ossimString("band"); + newPrefix += ossimString::toString(theNumberList[idx]); + newPrefix += ossimString("."); + + const char* minValue = kwl.find(newPrefix.c_str(), + ossimKeywordNames::MIN_VALUE_KW); + const char* maxValue = kwl.find(newPrefix.c_str(), + ossimKeywordNames::MAX_VALUE_KW); + const char* nullValue = kwl.find(newPrefix.c_str(), + ossimKeywordNames::NULL_VALUE_KW); + + if(minValue) + { + theMinPixelArray[idx] = ossimString(minValue).toDouble(); + } + else + { + theMinValuesValidFlag = false; + theMinPixelArray[idx] = ossimGetDefaultMin(theScalarType); + } + if(maxValue) + { + theMaxPixelArray[idx] = ossimString(maxValue).toDouble(); + } + else + { + theMaxValuesValidFlag = false; + theMaxPixelArray[idx] = ossimGetDefaultMax(theScalarType); + } + if(nullValue) + { + theNullPixelArray[idx] = ossimString(nullValue).toDouble(); + } + else + { + theNullValuesValidFlag = false; + theNullPixelArray[idx] = ossimGetDefaultNull(theScalarType); + } + } +} + +bool ossimImageMetaData::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + if(theNullPixelArray&&theMinPixelArray&&theMaxPixelArray) + { + ossim_int32 band = 0; + + for (band=0; band<(ossim_int32)theNumberOfBands; ++band) + { + ossimString kwMin = (ossimKeywordNames::BAND_KW + + ossimString::toString(band+1) + "." + + ossimKeywordNames::MIN_VALUE_KW); + ossimString kwMax = (ossimKeywordNames::BAND_KW + + ossimString::toString(band+1) + "." + + ossimKeywordNames::MAX_VALUE_KW); + ossimString kwNull = (ossimKeywordNames::BAND_KW + + ossimString::toString(band+1) + "." + + ossimKeywordNames::NULL_VALUE_KW); + + kwl.add(prefix, + kwMin.c_str(), + theMinPixelArray[band], + true); + kwl.add(prefix, + kwMax.c_str(), + theMaxPixelArray[band], + true); + kwl.add(prefix, + kwNull.c_str(), + theNullPixelArray[band], + true); + } + kwl.add(prefix, + ossimKeywordNames::NUMBER_BANDS_KW, + (ossim_int32)theNumberOfBands, + true); + kwl.add(prefix, + ossimKeywordNames::SCALAR_TYPE_KW, + (ossimScalarTypeLut::instance()->getEntryString(theScalarType)), + true); + } + + return true; +} + +ossim_uint32 ossimImageMetaData::getNumberOfBands()const +{ + return theNumberOfBands; +} + +void ossimImageMetaData::setScalarType(ossimScalarType aType) +{ + theScalarType = aType; +} + +ossimScalarType ossimImageMetaData::getScalarType()const +{ + return theScalarType; +} + +double ossimImageMetaData::getMinPix(ossim_uint32 band)const +{ + if(theNumberOfBands&&theMinPixelArray) + { + ossim_uint32 i = ossimMin(band, (ossim_uint32)(theNumberOfBands-1)); + + return theMinPixelArray[i]; + } + return ossimGetDefaultMin(theScalarType); +} + +void ossimImageMetaData::setMinPix(ossim_uint32 band, double pix) +{ + if((band < theNumberOfBands)&&(theMinPixelArray)) + { + theMinPixelArray[band] = pix; + } +} + +void ossimImageMetaData::setMaxPix(ossim_uint32 band, double pix) +{ + if((band < theNumberOfBands)&& + (theMaxPixelArray)) + { + theMaxPixelArray[band] = pix; + } +} + +void ossimImageMetaData::setNullPix(ossim_uint32 band, double pix) +{ + if((band < theNumberOfBands)&&(theNullPixelArray)) + { + theNullPixelArray[band] = pix; + } +} + +double ossimImageMetaData::getMaxPix(ossim_uint32 band)const +{ + if(theNumberOfBands&&theMaxPixelArray) + { + ossim_uint32 i = ossimMin(band, (ossim_uint32)(theNumberOfBands-1)); + + return theMaxPixelArray[i]; + } + return ossimGetDefaultMax(theScalarType); +} + +double ossimImageMetaData::getNullPix(ossim_uint32 band)const +{ + if(theNumberOfBands&&theNullPixelArray) + { + ossim_uint32 i = ossimMin(band, (ossim_uint32)(theNumberOfBands-1)); + + return theNullPixelArray[i]; + } + return ossimGetDefaultNull(theScalarType); +} + +const double* ossimImageMetaData::getMinPixelArray()const +{ + return theMinPixelArray; +} +const double* ossimImageMetaData::getMaxPixelArray()const +{ + return theMaxPixelArray; +} + +const double* ossimImageMetaData::getNullPixelArray()const +{ + return theNullPixelArray; +} + +void ossimImageMetaData::setMinValuesValid(bool flag) +{ + theMinValuesValidFlag = flag; +} + +void ossimImageMetaData::setMaxValuesValid(bool flag) +{ + theMaxValuesValidFlag = flag; +} + +void ossimImageMetaData::setNullValuesValid(bool flag) +{ + theNullValuesValidFlag = flag; +} + +bool ossimImageMetaData::getMinValuesValidFlag()const +{ + return theMinValuesValidFlag; +} + +bool ossimImageMetaData::getMaxValuesValidFlag()const +{ + return theMaxValuesValidFlag; +} + +bool ossimImageMetaData::getNullValuesValidFlag()const +{ + return theNullValuesValidFlag; +} + +const ossimImageMetaData& ossimImageMetaData::operator=( + const ossimImageMetaData& rhs) +{ + assign(rhs); + + return *this; +} + +bool ossimImageMetaData::isValid()const +{ + return ((theNumberOfBands>0)&& + (theScalarType != OSSIM_SCALAR_UNKNOWN)); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimImageMetaData.h b/Utilities/OSSIM/ossim_core/imaging/ossimImageMetaData.h new file mode 100644 index 0000000000..3d987f95b5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimImageMetaData.h @@ -0,0 +1,102 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +// Contains class declaration for ossimImageMetaData. +// +//******************************************************************* +// $Id: ossimImageMetaData.h,v 1.11 2005/08/11 13:41:12 gpotts Exp $ +#ifndef ossimImageMetaData_HEADER +#define ossimImageMetaData_HEADER +#include <base/common/ossimConstants.h> +#include <base/common/ossimCommon.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimFilename.h> + +class OSSIM_DLL ossimImageMetaData +{ +public: + ossimImageMetaData(); + ossimImageMetaData(ossimScalarType aType, + ossim_uint32 numberOfBands); + ossimImageMetaData(const ossimImageMetaData& rhs); + + virtual ~ossimImageMetaData(); + + void clear(); + void clearBandInfo(); + void setDefaultsForArrays(); + + void setNumberOfBands(ossim_uint32 numberOfBands); + + ossim_uint32 getNumberOfBands()const; + + void setScalarType(ossimScalarType aType); + + ossimScalarType getScalarType()const; + + double getMinPix(ossim_uint32 band)const; + + void setMinPix(ossim_uint32 band, double pix); + + void setMaxPix(ossim_uint32 band, double pix); + + void setNullPix(ossim_uint32 band, double pix); + + double getMaxPix(ossim_uint32 band)const; + + double getNullPix(ossim_uint32 band)const; + + const double* getMinPixelArray()const; + + const double* getMaxPixelArray()const; + + const double* getNullPixelArray()const; + + void setMinValuesValid(bool flag); + + void setMaxValuesValid(bool flag); + + void setNullValuesValid(bool flag); + + bool getMinValuesValidFlag()const; + + bool getMaxValuesValidFlag()const; + + bool getNullValuesValidFlag()const; + + const ossimImageMetaData& operator=(const ossimImageMetaData& rhs); + + bool isValid()const; + + void assign(const ossimImageMetaData& rhs); + + bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + +protected: + double* theNullPixelArray; + double* theMinPixelArray; + double* theMaxPixelArray; + + bool theMinValuesValidFlag; + bool theMaxValuesValidFlag; + bool theNullValuesValidFlag; + + ossimScalarType theScalarType; + ossim_uint32 theNumberOfBands; + + + void loadBandInfo(const ossimKeywordlist& kwl, const char* prefix = 0); +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimImageShapeFileIndex.cpp b/Utilities/OSSIM/ossim_core/imaging/ossimImageShapeFileIndex.cpp new file mode 100644 index 0000000000..f280765c7c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimImageShapeFileIndex.cpp @@ -0,0 +1,197 @@ +#include "ossimImageShapeFileIndex.h" +#include <imaging/factory/ossimImageHandlerRegistry.h> +#include <imaging/formats/ossimImageHandler.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <projections/ossimProjection.h> +#include <base/common/ossimTrace.h> + +#include <vec/shape/shapefil.h> + +static ossimTrace traceDebug("ossimImageShapeFileIndex:debug"); + +ossimImageShapeFileIndex::ossimImageShapeFileIndex(const ossimFilename& shapeFilename) + :theGlobalMinx(OSSIM_INFINITY), + theGlobalMiny(OSSIM_INFINITY), + theGlobalMaxx(-OSSIM_INFINITY), + theGlobalMaxy(-OSSIM_INFINITY) +{ + setFilename(shapeFilename); +} + +void ossimImageShapeFileIndex::setFilename(const ossimFilename& shapeFilename) +{ + theFilename = shapeFilename; + theFilename = theFilename.setExtension(""); +} + +void ossimImageShapeFileIndex::add(const ossimFilename& filename, + const ossim_int32 entry, // default to all entries + const ossimString& groupName) +{ + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimImageShapeFileIndex::add: Entered ...." << std::endl; + } + ossimRefPtr<ossimImageHandler> h = ossimImageHandlerRegistry::instance()->open(filename); + ossimRefPtr<ossimProjection> proj; + + if(h.valid()) + { + std::vector<ossim_uint32> entryList; + if(entry < 0) + { + h->getEntryList(entryList); + } + else + { + entryList.push_back(static_cast<ossim_uint32>(entry)); + } + + ossim_uint32 idx = 0; + for(idx = 0; idx < entryList.size(); ++idx) + { + ossimKeywordlist kwl; + if(h->setCurrentEntry(entryList[idx])) + { + ossimIrect bounds = h->getBoundingRect(); + + h->getImageGeometry(kwl); + proj = ossimProjectionFactoryRegistry::instance()->createProjection(kwl); + + if(proj.valid()) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "Adding file: " << filename << std::endl + << " entry: " << entryList[idx] << std::endl; + } + std::vector<ossimDpt> points; + ossim_float64 minx; + ossim_float64 miny; + ossim_float64 maxx; + ossim_float64 maxy; + ossimGpt ulgpt; + ossimGpt urgpt; + ossimGpt lrgpt; + ossimGpt llgpt; + const ossimDatum* datum = ossimDatumFactory::instance()->wgs84(); + proj->lineSampleToWorld(bounds.ul(), ulgpt); + proj->lineSampleToWorld(bounds.ur(), urgpt); + proj->lineSampleToWorld(bounds.lr(), lrgpt); + proj->lineSampleToWorld(bounds.ll(), llgpt); + + ulgpt.changeDatum(datum); + urgpt.changeDatum(datum); + lrgpt.changeDatum(datum); + llgpt.changeDatum(datum); + + points.push_back(ossimDpt(ulgpt)); + points.push_back(ossimDpt(urgpt)); + points.push_back(ossimDpt(lrgpt)); + points.push_back(ossimDpt(llgpt)); + + ossimDrect rect(points, OSSIM_RIGHT_HANDED); + + minx = rect.ll().x; + miny = rect.ll().y; + maxx = rect.ur().x; + maxy = rect.ur().y; + + if(minx < theGlobalMinx) theGlobalMinx = minx; + if(maxx > theGlobalMaxx) theGlobalMaxx = maxx; + if(miny < theGlobalMiny) theGlobalMiny = miny; + if(maxy > theGlobalMaxy) theGlobalMaxy = maxy; + + theRecords.push_back(new ossimImageShapeFileIndexRecord(filename, + entryList[idx], + groupName, + minx, + miny, + maxx, + maxy)); + } + } + } + } + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimImageShapeFileIndex::add: Leaving ...." << std::endl; + } +} + +void ossimImageShapeFileIndex::build(ossim_uint32 maxDepth)const +{ + if(theRecords.size()) + { + SHPHandle hSHP = SHPCreate( theFilename.c_str(), SHPT_POLYGON); + DBFHandle hDBF = DBFCreate( theFilename.c_str()); + + DBFAddField(hDBF, "GROUP", FTString, 256, 0); + DBFAddField(hDBF, "FILENAME", FTString, 256, 0); + DBFAddField(hDBF, "ENTRY", FTInteger, 10, 0); + DBFAddField(hDBF, "DATUM", FTString, 16, 0); + + double* x = new double[4]; + double* y = new double[4]; + int nVertices = 4; + ossim_uint32 idx = 0; + int iRecord = 0; + for(idx = 0; idx < theRecords.size(); ++idx) + { + x[0] = theRecords[idx]->theMinx; + x[1] = theRecords[idx]->theMaxx; + x[2] = theRecords[idx]->theMaxx; + x[3] = theRecords[idx]->theMinx; + + y[0] = theRecords[idx]->theMaxy; + y[1] = theRecords[idx]->theMaxy; + y[2] = theRecords[idx]->theMiny; + y[3] = theRecords[idx]->theMiny; + + SHPObject* obj = SHPCreateSimpleObject(SHPT_POLYGON, + nVertices, + x, + y, + 0); + SHPWriteObject( hSHP, -1, obj ); + iRecord = DBFGetRecordCount( hDBF ); + DBFWriteStringAttribute(hDBF, iRecord, 0, theRecords[idx]->theGroupName.c_str()); + DBFWriteStringAttribute(hDBF, iRecord, 1, theRecords[idx]->theFilename.c_str()); + DBFWriteIntegerAttribute(hDBF, iRecord, 2, (int)(theRecords[idx]->theEntry)); + DBFWriteStringAttribute(hDBF, iRecord, 3, "WGE"); + SHPDestroyObject(obj); + } + + DBFClose(hDBF); + SHPTree * shpTree = 0; + double minV[4] = {0.0,0.0,0.0,0.0}; + double maxV[4] = {0.0,0.0,0.0,0.0}; + + minV[0] = theGlobalMinx; + minV[1] = theGlobalMiny; + + maxV[0] = theGlobalMaxx; + maxV[1] = theGlobalMaxy; + if(maxDepth>1) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "building quadtree with " << maxDepth << " levels." << std::endl + << "minx = " << theGlobalMinx << std::endl + << "miny = " << theGlobalMiny << std::endl + << "maxx = " << theGlobalMaxx << std::endl + << "maxy = " << theGlobalMaxy << std::endl; + } + shpTree = SHPCreateTree(hSHP, 2, maxDepth, minV, maxV); + } + + if(shpTree) + { + SHPWriteTree(shpTree, (theFilename+".qtree").c_str()); + SHPDestroyTree(shpTree); + } + SHPClose(hSHP); + } + +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimImageShapeFileIndex.h b/Utilities/OSSIM/ossim_core/imaging/ossimImageShapeFileIndex.h new file mode 100644 index 0000000000..29ef7e090e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimImageShapeFileIndex.h @@ -0,0 +1,61 @@ +#ifndef ossimImageShapeFileIndex_HEADER +#define ossimImageShapeFileIndex_HEADER +#include <base/common/ossimObject.h> +#include <base/common/ossimReferenced.h> +#include <base/common/ossimRefPtr.h> +#include <base/data_types/ossimFilename.h> + +class OSSIM_DLL ossimImageShapeFileIndex : public ossimObject +{ +public: + ossimImageShapeFileIndex(const ossimFilename& shapeFilename = ""); + void setFilename(const ossimFilename& shapeFilename); + + void add(const ossimFilename& filename, + const ossim_int32 entry=-1, // default to all entries + const ossimString& groupName="RASTER"); + /** + * + */ + void build(ossim_uint32 maxDepth=1)const; + +protected: + class ossimImageShapeFileIndexRecord : public ossimReferenced + { + public: + ossimImageShapeFileIndexRecord(const ossimFilename& filename="", + ossim_uint32 entry=0, + const ossimString& groupName="", + ossim_float64 minx=0.0, + ossim_float64 miny=0.0, + ossim_float64 maxx=0.0, + ossim_float64 maxy=0.0) + :theFilename(filename), + theEntry(entry), + theGroupName(groupName), + theMinx(minx), + theMiny(miny), + theMaxx(maxx), + theMaxy(maxy) + { + } + + ossimFilename theFilename; + ossim_uint32 theEntry; + ossimString theGroupName; + ossim_float64 theMinx; + ossim_float64 theMiny; + ossim_float64 theMaxx; + ossim_float64 theMaxy; + }; + + std::vector<ossimRefPtr<ossimImageShapeFileIndexRecord> > theRecords; + + ossimFilename theFilename; + ossim_float64 theGlobalMinx; + ossim_float64 theGlobalMiny; + ossim_float64 theGlobalMaxx; + ossim_float64 theGlobalMaxy; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimImageSource.cpp b/Utilities/OSSIM/ossim_core/imaging/ossimImageSource.cpp new file mode 100644 index 0000000000..e6d8a00f86 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimImageSource.cpp @@ -0,0 +1,336 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimImageSource.cpp,v 1.48 2005/12/09 12:19:04 gpotts Exp $ + +#include <imaging/ossimImageSource.h> +#include <imaging/ossimImageData.h> +#include <base/property/ossimProperty.h> +#include <base/common/ossimKeywordNames.h> + +RTTI_DEF2(ossimImageSource, + "ossimImageSource" , + ossimSource, + ossimImageSourceInterface) + +ossimImageSource::ossimImageSource(ossimObject* owner) + :ossimSource(owner, 0,0,false,false) +{ +} + +ossimImageSource::ossimImageSource(ossimObject* owner, + ossim_uint32 inputListSize, + ossim_uint32 outputListSize, + bool inputListIsFixedFlag, + bool outputListIsFixedFlag) + : + ossimSource(owner, inputListSize, outputListSize, + inputListIsFixedFlag, outputListIsFixedFlag) +{ +} + +ossimImageSource::~ossimImageSource() +{ +} + +ossimRefPtr<ossimImageData> ossimImageSource::getTile(const ossimIpt& origin, + ossim_uint32 resLevel) +{ + ossimIrect tile_rect(origin.x, + origin.y, + origin.x + getTileWidth() - 1, + origin.y + getTileHeight() - 1); + + return getTile(tile_rect, resLevel); +} + +ossimRefPtr<ossimImageData> ossimImageSource::getTile(const ossimIrect& rect, + ossim_uint32 resLevel) +{ + ossimImageSourceInterface* inter = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(inter) + { + return inter->getTile(rect, resLevel); + } + return NULL; +} + +void ossimImageSource::getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result)const +{ + ossimImageSourceInterface* inter = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(inter) + { + inter->getDecimationFactor(resLevel, result); + } +} + +void ossimImageSource::getDecimationFactors(vector<ossimDpt>& decimations)const +{ + ossimImageSourceInterface* inter = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(inter) + { + inter->getDecimationFactors(decimations); + } +} + +ossim_uint32 ossimImageSource::getNumberOfDecimationLevels() const +{ + ossimImageSourceInterface* inter = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(inter) + { + return inter->getNumberOfDecimationLevels(); + } + return 0; +} + +ossimScalarType ossimImageSource::getOutputScalarType() const +{ + ossimImageSourceInterface* inter = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(inter) + { + return inter->getOutputScalarType(); + } + + return OSSIM_SCALAR_UNKNOWN; +} + +ossim_uint32 ossimImageSource::getTileWidth() const +{ + ossimImageSourceInterface* inter = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(inter) + { + return inter->getTileWidth(); + } + ossimIpt defaultTileSize; + ossimGetDefaultTileSize(defaultTileSize); + + return defaultTileSize.x; +} + +ossim_uint32 ossimImageSource::getTileHeight() const +{ + ossimImageSourceInterface* inter = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(inter) + { + return inter->getTileHeight(); + } + + ossimIpt defaultTileSize; + ossimGetDefaultTileSize(defaultTileSize); + + return defaultTileSize.y; +} + +ossimIrect ossimImageSource::getBoundingRect(ossim_uint32 resLevel)const +{ + ossimImageSourceInterface* inter = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(inter) + { + return inter->getBoundingRect(resLevel); + } + ossimIrect rect; + rect.makeNan(); + return rect; +} + +bool ossimImageSource::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + return ossimSource::saveState(kwl, prefix); +} + +bool ossimImageSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + return ossimSource::loadState(kwl, prefix); +} + +//***************************************************************************** +// METHOD: ossimImageSource::getValidImageVertices() +//***************************************************************************** +void ossimImageSource::getValidImageVertices(vector<ossimIpt>& validVertices, + ossimVertexOrdering ordering, + ossim_uint32 resLevel)const +{ + ossimImageSourceInterface* inter = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(inter) + { + return inter->getValidImageVertices(validVertices, + ordering, + resLevel); + } + ossimIrect boundingRect = getBoundingRect(resLevel); + validVertices.clear(); + + if(ordering == OSSIM_CLOCKWISE_ORDER) + { + validVertices.push_back(boundingRect.ul()); + validVertices.push_back(boundingRect.ur()); + validVertices.push_back(boundingRect.lr()); + validVertices.push_back(boundingRect.ll()); + } + else + { + validVertices.push_back(boundingRect.ul()); + validVertices.push_back(boundingRect.ll()); + validVertices.push_back(boundingRect.lr()); + validVertices.push_back(boundingRect.ur()); + } +} + +double ossimImageSource::getNullPixelValue(ossim_uint32 band)const +{ + ossimImageSourceInterface* inter = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(inter) + { + return inter->getNullPixelValue(band); + } + + return ossimGetDefaultNull(getOutputScalarType()); +} + +double ossimImageSource::getMinPixelValue(ossim_uint32 band)const +{ + ossimImageSourceInterface* inter = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(inter) + { + return inter->getMinPixelValue(band); + } + return ossimGetDefaultMin(getOutputScalarType()); +} + +double ossimImageSource::getMaxPixelValue(ossim_uint32 band)const +{ + ossimImageSourceInterface* inter = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(inter) + { + return inter->getMaxPixelValue(band); + } + + return ossimGetDefaultMax(getOutputScalarType()); +} + + +bool ossimImageSource::getImageGeometry(ossimKeywordlist& kwl, + const char* prefix) +{ + int i = 0; + for(i = 0; i < (int)getNumberOfInputs(); ++i) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + getInput(i)); + if(interface) + { + return interface->getImageGeometry(kwl, prefix); + } + } + + return false; +} + +void ossimImageSource::setImageGeometry(const ossimKeywordlist& kwl) +{ + ossimImageSourceInterface* inter = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if (inter) + { + setImageGeometry(kwl); + } +} + +void ossimImageSource::saveImageGeometry() const +{ + ossimImageSourceInterface* inter = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if (inter) + { + saveImageGeometry(); + } +} + +void ossimImageSource::saveImageGeometry(const ossimFilename& geometry_file) const +{ + ossimImageSourceInterface* inter = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if (inter) + { + saveImageGeometry(geometry_file); + } +} + +void ossimImageSource::getOutputBandList(std::vector<ossim_uint32>& bandList) const +{ + bandList.clear(); + const ossim_uint32 BANDS = getNumberOfOutputBands(); + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + bandList.push_back(band); + } +} + +ossim_uint32 ossimImageSource::getNumberOfOutputBands() const +{ + return getNumberOfInputBands(); +} + +ossimRefPtr<ossimProperty> ossimImageSource::getProperty(const ossimString& name)const +{ + ossimRefPtr<ossimProperty> result = ossimSource::getProperty(name); + + ossimString tempName = name; + if(result.valid()) + { + if(tempName.downcase() == ossimKeywordNames::ENABLED_KW) + { + result->clearChangeType(); + + // we will at least say its a radiometric change + // + result->setFullRefreshBit(); + } + } + + return result; +} + +void ossimImageSource::setProperty(ossimRefPtr<ossimProperty> property) +{ + ossimSource::setProperty(property); +} + +void ossimImageSource::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + ossimSource::getPropertyNames(propertyNames); +} + +// Protected to hide from use... +ossimImageSource::ossimImageSource (const ossimImageSource& rhs) + :ossimSource(), + ossimImageSourceInterface(rhs) +{} + +// Protected to hide from use... +const ossimImageSource& ossimImageSource::operator=(const ossimImageSource&) +{ + return *this; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimImageSource.h b/Utilities/OSSIM/ossim_core/imaging/ossimImageSource.h new file mode 100644 index 0000000000..0dbdd81c8e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimImageSource.h @@ -0,0 +1,202 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimImageSource.h,v 1.48 2005/09/15 12:28:44 gpotts Exp $ +#ifndef ossimImageSource_HEADER +#define ossimImageSource_HEADER + +#include <base/common/ossimSource.h> +#include <base/context/ossimErrorContext.h> +#include <base/common/ossimConstants.h> +#include <base/data_types/ossimDrect.h> +#include <imaging/ossimImageData.h> +#include <imaging/ossimImageSourceInterface.h> + +class ossimDpt; + +class OSSIMDLLEXPORT ossimImageSource : public ossimSource, + public ossimImageSourceInterface +{ +public: + ossimImageSource(ossimObject* owner = 0); + ossimImageSource(ossimObject* owner, + ossim_uint32 inputListSize, + ossim_uint32 outputListSize, + bool inputListIsFixedFlag=true, + bool outputListIsFixedFlag=true); + + virtual ~ossimImageSource(); + + /** + * @return from origin out to tile_width-1, and tile_height-1. + */ + virtual ossimRefPtr<ossimImageData> getTile(const ossimIpt& origin, + ossim_uint32 resLevel=0); + + /** + * @return the requested region of interest + */ + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect, + ossim_uint32 resLevel=0); + + /** + * For RTTI support. overrides ossimImageSourceInterface + * get object to return the correct casted base pointer + * for RTTI casting + */ + virtual ossimObject* getObject() { return this; } + + /** + * For RTTI support. overrides ossimImageSourceInterface + * get object to return the correct casted base pointer + * for RTTI casting + */ + virtual const ossimObject* getObject() const { return this; } + + + /** + * Will return the decimation factor for the given resolution + * level. the decimation is the scale from Resolution 0 or full + * res. Usually this is a power of 2 decimation where + * the decimation result is 1.0/2^resoltion. + */ + virtual void getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result)const; + + /** + * Will return an array of all decimations for each resolution level. + */ + virtual void getDecimationFactors(vector<ossimDpt>& decimations) const; + + /** + * Will return the number of resolution levels. Note: resolution + * level 0 is included in the return count. + */ + virtual ossim_uint32 getNumberOfDecimationLevels() const; + + /** + * Returns the number of bands in a tile returned from this TileSource. + */ + virtual ossim_uint32 getNumberOfOutputBands() const; + + /** + * Initializes bandList to the zero based order of output bands. + */ + virtual void getOutputBandList(std::vector<ossim_uint32>& bandList) const; + + /** + * This will be used to query the output pixel type of the tile source. + * Please ignore the argument. It will soon be removed. + */ + virtual ossimScalarType getOutputScalarType() const; + + /** + * Returns the default processing tile width + */ + virtual ossim_uint32 getTileWidth() const; + + /** + * Returns the default processing tile height + */ + virtual ossim_uint32 getTileHeight() const; + + /** + * Each band has a null pixel associated with it. The null pixel + * represents an invalid value. + */ + virtual double getNullPixelValue(ossim_uint32 band=0)const; + + + /** + * Returns the min pixel of the band. + */ + virtual double getMinPixelValue(ossim_uint32 band=0)const; + + /** + * Returns the max pixel of the band. + */ + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + + /** + * This will return the bounding rect of the source. We can have several + * sources which are in a chain to modify the bounding image rect. + * lets say you are next to an image handler then it will return the + * bounding rect for that image. If you are at the right side of a + * resampler then you will get a bounding rect along the image view plane. + * This is going to be a very import method for both image writers, + * mosaics or anything that needs to operate only within the bounds of an + * image. + */ + virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0) const; + + /** + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * ordering specifies how the vertices should be arranged. + * valid image vertices is basically the tightly fit convex hull + * of the image. Usually an image has NULL values and are + * internally not upright rectangular. This can cause + * problems some spatial filters. + * + * The default implementation is to return the bounding rect. + */ + virtual void getValidImageVertices(vector<ossimIpt>& validVertices, + ossimVertexOrdering ordering=OSSIM_CLOCKWISE_ORDER, + ossim_uint32 resLevel=0)const; + + /** + * the default is to find the first input source that is of + * type ossimImageSourceInterface and return its input geometry. + */ + virtual bool getImageGeometry(ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * Default method to call input's setImageGeometry. + */ + virtual void setImageGeometry(const ossimKeywordlist& kwl); + + /** + * Default method to call input's saveImageGeometry. + */ + virtual void saveImageGeometry() const; + + /** + * Default method to call input's saveImageGeometry. + */ + virtual void saveImageGeometry(const ossimFilename& geometry_file) const; + + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + + +protected: + ossimImageSource (const ossimImageSource& rhs); + const ossimImageSource& operator= (const ossimImageSource&); + +private: + +TYPE_DATA +}; + +#endif /* #ifndef ossimImageSource_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimImageSourceInterface.cpp b/Utilities/OSSIM/ossim_core/imaging/ossimImageSourceInterface.cpp new file mode 100644 index 0000000000..676d70c4a1 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimImageSourceInterface.cpp @@ -0,0 +1,18 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimImageSourceInterface.cpp,v 1.3 2005/07/15 19:49:48 dburken Exp $ +#include <imaging/ossimImageSourceInterface.h> + +RTTI_DEF(ossimImageSourceInterface, "ossimImageSourceInterface"); + +ossimImageSourceInterface::~ossimImageSourceInterface() +{ +} diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimImageSourceInterface.h b/Utilities/OSSIM/ossim_core/imaging/ossimImageSourceInterface.h new file mode 100644 index 0000000000..749eb30adf --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimImageSourceInterface.h @@ -0,0 +1,109 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimImageSourceInterface.h,v 1.21 2005/09/15 12:28:44 gpotts Exp $ +#ifndef ossimImageSourceInterface_HEADER +#define ossimImageSourceInterface_HEADER + +#include <base/context/ossimErrorContext.h> +#include <base/common/ossimConstants.h> +#include <base/common/ossimRefPtr.h> +#include <base/data_types/ossimIrect.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimFilename.h> + +class ossimImageData; +class ossimObject; + +class OSSIMDLLEXPORT ossimImageSourceInterface +{ +public: + virtual ~ossimImageSourceInterface(); + + virtual ossimObject* getObject()=0; + virtual const ossimObject* getObject()const=0; + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIpt& origin, + ossim_uint32 resLevel=0) = 0; + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect, + ossim_uint32 resLevel=0) = 0; + + virtual void getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result)const=0; + virtual void getDecimationFactors(vector<ossimDpt>& decimations)const=0; + virtual ossim_uint32 getNumberOfDecimationLevels()const=0; + + /*! + * Returns the number of bands available from the input. + */ + virtual ossim_uint32 getNumberOfInputBands() const = 0; + + /*! + * Returns the number of bands in output. + */ + virtual ossim_uint32 getNumberOfOutputBands() const = 0; + + /*! + * Initializes bandList to the zero based order of output bands. + */ + virtual void getOutputBandList(std::vector<ossim_uint32>& bandList) const=0; + + virtual ossimScalarType getOutputScalarType() const = 0; + + virtual ossim_uint32 getTileWidth() const = 0; + virtual ossim_uint32 getTileHeight() const = 0; + + virtual double getNullPixelValue(ossim_uint32 band=0)const=0; + virtual double getMinPixelValue(ossim_uint32 band=0)const=0; + virtual double getMaxPixelValue(ossim_uint32 band=0)const=0; + + virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0)const=0; + + virtual void getValidImageVertices(vector<ossimIpt>& validVertices, + ossimVertexOrdering ordering=OSSIM_CLOCKWISE_ORDER, + ossim_uint32 resLevel=0)const=0; + + virtual bool getImageGeometry(ossimKeywordlist& kwl, + const char* prefix=0)=0; + + /** + * Sets the image geometry keyword list. + * + * @note Callers should note that this will override any existing + * geometry. + * + * @note This does not write the geometry to disk, to do so call + * one of the saveImageGeometry methods. + */ + virtual void setImageGeometry(const ossimKeywordlist& kwl)=0; + + /** + * Saves the image geometry to a file that will be made based on the image + * file name. + */ + virtual void saveImageGeometry()const=0; + + /** + * Saves the image geomety to geom_file. + */ + virtual void saveImageGeometry(const ossimFilename& geometry_file)const=0; + + virtual void initialize()=0; + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0)=0; + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const=0; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimImageSourceSequencer.cpp b/Utilities/OSSIM/ossim_core/imaging/ossimImageSourceSequencer.cpp new file mode 100644 index 0000000000..98e03e0118 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimImageSourceSequencer.cpp @@ -0,0 +1,424 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +//******************************************************************* +// $Id: ossimImageSourceSequencer.cpp,v 1.34 2005/11/17 12:40:30 gpotts Exp $ +#include <imaging/ossimImageSourceSequencer.h> +#include <imaging/ossimImageData.h> +#include <base/data_types/ossimIrect.h> +#include <imaging/ossimImageWriter.h> +#include <base/common/ossimTrace.h> +#include <imaging/factory/ossimImageDataFactory.h> + +RTTI_DEF2(ossimImageSourceSequencer, "ossimImageSourceSequencer", + ossimImageSource, ossimConnectableObjectListener); + +static ossimTrace traceDebug("ossimImageSourceSequencer:debug"); + +ossimImageSourceSequencer::ossimImageSourceSequencer(ossimImageSource* inputSource, + ossimObject* owner) + :ossimImageSource(owner, + 1, + 1, + true, + true), + theBlankTile(NULL), + theAreaOfInterest(0,0,0,0), + theTileSize(OSSIM_DEFAULT_TILE_WIDTH, OSSIM_DEFAULT_TILE_HEIGHT), + theNumberOfTilesHorizontal(0), + theNumberOfTilesVertical(0), + theCurrentTileNumber(0) +{ + ossimGetDefaultTileSize(theTileSize); + theAreaOfInterest.makeNan(); + theInputConnection = inputSource; + if(inputSource) + { + connectMyInputTo(0, inputSource); + initialize(); + } + addListener( (ossimConnectableObjectListener*)this); +} + +ossimImageSourceSequencer::~ossimImageSourceSequencer() +{ + removeListener((ossimConnectableObjectListener*)this); +} + +ossim_uint32 ossimImageSourceSequencer::getNumberOfTiles()const +{ + return (theNumberOfTilesHorizontal*theNumberOfTilesVertical); +} + + +ossim_uint32 ossimImageSourceSequencer::getNumberOfTilesHorizontal()const +{ + return theNumberOfTilesHorizontal; +} + +ossim_uint32 ossimImageSourceSequencer::getNumberOfTilesVertical()const +{ + return theNumberOfTilesVertical; +} + +ossimScalarType ossimImageSourceSequencer::getOutputScalarType() const +{ + if(theInputConnection) + { + return theInputConnection->getOutputScalarType(); + } + + return OSSIM_SCALAR_UNKNOWN; +} + +ossimIpt ossimImageSourceSequencer::getTileSize()const +{ + return theTileSize; +} + +void ossimImageSourceSequencer::setTileSize(const ossimIpt& tileSize) +{ + theTileSize = tileSize; + updateTileDimensions(); +// initialize(); +} + +void ossimImageSourceSequencer::setTileSize(int width, int height) +{ + setTileSize(ossimIpt(width, height)); +} + +void ossimImageSourceSequencer::updateTileDimensions() +{ + if(theAreaOfInterest.hasNans() || + theTileSize.hasNans()) + { + theNumberOfTilesHorizontal = 0; + theNumberOfTilesVertical = 0; + } + else + { + ossim_int32 width = theAreaOfInterest.width(); + ossim_int32 height = theAreaOfInterest.height(); + + theNumberOfTilesHorizontal = static_cast<ossim_uint32>(ceil((double)width/(double)theTileSize.x)); + theNumberOfTilesVertical = static_cast<ossim_uint32>(ceil((double)height/(double)theTileSize.y)); + } +} + +void ossimImageSourceSequencer::initialize() +{ + theInputConnection = PTR_CAST(ossimImageSourceInterface, getInput(0)); + + if(theInputConnection) + { + if(theTileSize.hasNans()) + { + theTileSize.x = theInputConnection->getTileWidth(); + theTileSize.y = theInputConnection->getTileHeight(); + } + + ossimDrect rect = theInputConnection->getBoundingRect(); + if(rect.hasNans()) + { + theAreaOfInterest.makeNan(); + } + else + { + rect.stretchOut(); + setAreaOfInterest(rect); + } + updateTileDimensions(); + + theBlankTile = ossimImageDataFactory::instance()->create(this, + this); + if(theBlankTile.valid()) + { + theBlankTile->initialize(); + } + } +} + +bool ossimImageSourceSequencer::canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const +{ + return (object&& PTR_CAST(ossimImageSourceInterface, object)); +} + +void ossimImageSourceSequencer::connectInputEvent(ossimConnectionEvent& event) +{ + theInputConnection = PTR_CAST(ossimImageSourceInterface, getInput(0)); + initialize(); +} + +void ossimImageSourceSequencer::disconnectInputEvent(ossimConnectionEvent& event) +{ + theInputConnection = PTR_CAST(ossimImageSourceInterface, getInput(0)); +} + +ossimIrect ossimImageSourceSequencer::getBoundingRect(ossim_uint32 resLevel)const +{ + ossimDrect temp; + temp.makeNan(); + + if(!theInputConnection) return temp; + + if(theAreaOfInterest.hasNans()) + { + return theInputConnection->getBoundingRect(resLevel); + } + + return theAreaOfInterest; +} + +void ossimImageSourceSequencer::getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result) const +{ + if(theInputConnection) + { + theInputConnection->getDecimationFactor(resLevel, + result); + } + result.makeNan(); +} + +void ossimImageSourceSequencer::getDecimationFactors(vector<ossimDpt>& decimations) const +{ + if(theInputConnection) + { + theInputConnection->getDecimationFactors(decimations); + } +} + +ossim_uint32 ossimImageSourceSequencer::getNumberOfDecimationLevels()const +{ + if(theInputConnection) + { + return theInputConnection->getNumberOfDecimationLevels(); + } + + return 0; +} + +void ossimImageSourceSequencer::setAreaOfInterest(const ossimIrect& areaOfInterest) +{ + if(areaOfInterest.hasNans()) + { + theAreaOfInterest.makeNan(); + theNumberOfTilesHorizontal = 0; + theNumberOfTilesVertical = 0; + } + + // let's round it to the nearest pixel value before setting it. + theAreaOfInterest = areaOfInterest; + updateTileDimensions(); +} + +const ossimIrect& ossimImageSourceSequencer::getAreaOfInterest()const +{ + return theAreaOfInterest; +} + +void ossimImageSourceSequencer::setToStartOfSequence() +{ + theCurrentTileNumber = 0; +} + +ossimRefPtr<ossimImageData> ossimImageSourceSequencer::getTile( + const ossimIrect& rect, ossim_uint32 resLevel) +{ + if(theInputConnection) + { + ossimRefPtr<ossimImageData> tile = + theInputConnection->getTile(rect, resLevel); + if (tile.valid()) + { + return tile; + } + else + { + // We should return a valid tile for the writers. + theBlankTile->setImageRectangle(rect); + return theBlankTile; + } + } + + return NULL; +} + +ossimRefPtr<ossimImageData> ossimImageSourceSequencer::getNextTile( + ossim_uint32 resLevel) +{ + if(!theInputConnection) + { + return NULL; + } + ossimIpt origin; + if(getTileOrigin(theCurrentTileNumber, origin)) + { + ++theCurrentTileNumber; + ossimIrect tileRect(origin.x, + origin.y, + origin.x + (theTileSize.x - 1), + origin.y + (theTileSize.y - 1)); + ossimRefPtr<ossimImageData> data = theInputConnection->getTile(tileRect, + resLevel); + if(!data.valid() || !data->getBuf()) + { + theBlankTile->setImageRectangle(tileRect); + return theBlankTile; + } + + return data; + } + + + return ossimRefPtr<ossimImageData>(); +} + +ossimRefPtr<ossimImageData> ossimImageSourceSequencer::getTile( + ossim_int32 id, ossim_uint32 resLevel) +{ + static const char* MODULE= "ossimImageSourceSequencer::getTile(id, resLevel)"; + if(traceDebug()) + { + CLOG << "entering.."<<endl; + } + if(!theInputConnection) + { + if(traceDebug()) + { + CLOG << "No input connection so returing NULL" << endl; + } + return NULL; + } + // if we have no tiles try to initialize. + if(getNumberOfTiles() == 0) + { + initialize(); + } + ossimIpt origin; + + if(getTileOrigin(id, origin)) + { + if(traceDebug()) + { + CLOG << "returning tile" << endl; + } + ossimIrect tRect(origin.x, + origin.y, + origin.x + theTileSize.x - 1, + origin.y + theTileSize.y - 1); + + ossimRefPtr<ossimImageData> temp = theInputConnection->getTile(tRect, + resLevel); + + + theBlankTile->setImageRectangle(tRect); + + if(temp.valid()) + { + if(!temp->getBuf()) + { + return theBlankTile; + } + } + else + { + return theBlankTile; + } + return temp; + } + else + { + if(traceDebug()) + { + CLOG << "was not able to get an origin for id = " << id << endl; + } + } + if(traceDebug()) + { + CLOG << "leaving.."<<endl; + } + return NULL; +} + + +bool ossimImageSourceSequencer::getTileOrigin(ossim_int32 id, + ossimIpt& origin)const +{ + if(id < 0) + { + return false; + } + if((theNumberOfTilesHorizontal > 0)&& + (theCurrentTileNumber < getNumberOfTiles())) + { + ossim_int32 y = id/static_cast<ossim_int32>(theNumberOfTilesHorizontal); + ossim_int32 x = id%static_cast<ossim_int32>(theNumberOfTilesHorizontal); + if((x < static_cast<ossim_int32>(theNumberOfTilesHorizontal)) && + (y < static_cast<ossim_int32>(theNumberOfTilesVertical))) + { + origin.x = theAreaOfInterest.ul().x + x*theTileSize.x; + origin.y = theAreaOfInterest.ul().y + y*theTileSize.y; + } + else + { + return false; + } + } + else + { + return false; + } + + return true; +} + +double ossimImageSourceSequencer::getNullPixelValue(ossim_uint32 band)const +{ + if (theInputConnection) + { + return theInputConnection->getNullPixelValue(band); + } + + return ossimImageSource::getNullPixelValue(band); +} + +double ossimImageSourceSequencer::getMinPixelValue(ossim_uint32 band)const +{ + if (theInputConnection) + { + return theInputConnection->getMinPixelValue(band); + } + + return ossimImageSource::getMinPixelValue(band); +} + +double ossimImageSourceSequencer::getMaxPixelValue(ossim_uint32 band)const +{ + if (theInputConnection) + { + return theInputConnection->getMaxPixelValue(band); + } + + return ossimImageSource::getMaxPixelValue(band); +} + +ossim_uint32 ossimImageSourceSequencer::getNumberOfInputBands()const +{ + if(theInputConnection) + { + return theInputConnection->getNumberOfOutputBands(); + } + + return 0; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimImageSourceSequencer.h b/Utilities/OSSIM/ossim_core/imaging/ossimImageSourceSequencer.h new file mode 100644 index 0000000000..b04d9c9ec6 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimImageSourceSequencer.h @@ -0,0 +1,160 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimImageSourceSequencer.h,v 1.30 2005/11/17 12:43:52 gpotts Exp $ +#ifndef ossimImageSourceSequencer_HEADER +#define ossimImageSourceSequencer_HEADER +#include "ossimImageSource.h" +#include "base/data_types/ossimIpt.h" +#include "base/common/events/ossimConnectableObjectListener.h" + + +class OSSIMDLLEXPORT ossimImageSourceSequencer + : + public ossimImageSource, + public ossimConnectableObjectListener +{ +public: + ossimImageSourceSequencer(ossimImageSource* inputSource=NULL, + ossimObject* owner=NULL); + + virtual ~ossimImageSourceSequencer(); + /*! + * This will return the number of tiles within the + * area of interest. + */ + ossim_uint32 getNumberOfTiles()const; + + /*! + * Will return the number of tiles along the + * x or horizontal direction. + */ + ossim_uint32 getNumberOfTilesHorizontal()const; + + /*! + * Will return the number of tiles along the + * y or vertical direction. + */ + ossim_uint32 getNumberOfTilesVertical()const; + + /*! + * This must be called. We can only initialize this + * object completely if we know all connections + * are valid. Some other object drives this and so the + * connection's initialize will be called after. The job + * of this connection is to set up the sequence. It will + * default to the bounding rect. The area of interest can be + * set to some other rectagle (use setAreaOfInterest). + */ + virtual void initialize(); + + /*! + * Will set the current area of interest. + */ + virtual void setAreaOfInterest(const ossimIrect& areaOfInterest); + + /*! + * Just returns the current area of interest. + */ + const ossimIrect& getAreaOfInterest()const; + + /*! + * Will set the internal pointers to the upperleft + * tile number. To go to the next tile in the sequence + * just call getNextTile. + */ + virtual void setToStartOfSequence(); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect, + ossim_uint32 resLevel=0); + + /*! + * Will allow you to get the next tile in the sequence. + * Note the last tile returned will be an invalid + * ossimRefPtr<ossimImageData>. Callers should be able to do: + * + * ossimRefPtr<ossimImageData> id = sequencer->getNextTile(); + * while (id.valid()) + * { + * doSomething; + * id = sequencer->getNextTile(); + * } + * + */ + virtual ossimRefPtr<ossimImageData> getNextTile(ossim_uint32 resLevel=0); + + virtual bool getTileOrigin(ossim_int32 id, + ossimIpt& origin)const; + virtual ossimRefPtr<ossimImageData> getTile(ossim_int32 id, + ossim_uint32 resLevel=0); + + virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0)const; + virtual void getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result) const; + virtual void getDecimationFactors(vector<ossimDpt>& decimations) const; + virtual ossim_uint32 getNumberOfDecimationLevels()const; + + /*! + * Returns the number of bands available from the input. + */ + virtual ossim_uint32 getNumberOfInputBands()const; + + virtual ossimScalarType getOutputScalarType() const; + + virtual ossim_uint32 getTileWidth()const { return theTileSize.x; } + virtual ossim_uint32 getTileHeight()const { return theTileSize.y; } + + virtual void slaveProcessTiles() + { + return; + } + virtual bool isMaster()const + { + return true; + } + + virtual ossimIpt getTileSize()const; + virtual void setTileSize(const ossimIpt& tileSize); + virtual void setTileSize(int width, int height); + + virtual void connectInputEvent(ossimConnectionEvent& event); + virtual void disconnectInputEvent(ossimConnectionEvent& event); + + virtual bool canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const; + + virtual double getNullPixelValue(ossim_uint32 band=0)const; + virtual double getMinPixelValue(ossim_uint32 band=0)const; + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + +protected: + ossimImageSourceInterface* theInputConnection; + ossimRefPtr<ossimImageData> theBlankTile; + /*! + * Is the area of interest. The default will + * + */ + ossimIrect theAreaOfInterest; + + /*! + * Called during initialize. + */ + ossimIpt theTileSize; + + ossim_uint32 theNumberOfTilesHorizontal; + ossim_uint32 theNumberOfTilesVertical; + ossim_uint32 theCurrentTileNumber; + + void updateTileDimensions(); + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimImageStatisticsSource.cpp b/Utilities/OSSIM/ossim_core/imaging/ossimImageStatisticsSource.cpp new file mode 100644 index 0000000000..f50dc104fa --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimImageStatisticsSource.cpp @@ -0,0 +1,180 @@ +//******************************************************************* +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +#include <imaging/ossimImageStatisticsSource.h> +#include <imaging/ossimImageSourceInterface.h> +#include <imaging/ossimImageSourceSequencer.h> + + +ossimImageStatisticsSource::ossimImageStatisticsSource() + :ossimSource(0, + 1, + 0, + true, + false) +{ +} + +ossimImageStatisticsSource::~ossimImageStatisticsSource() +{ + +} + +void ossimImageStatisticsSource::computeStatistics() +{ + ossimImageSourceInterface* anInterface = PTR_CAST(ossimImageSourceInterface, + getInput()); + + if(anInterface&&isSourceEnabled()) + { + clearStatistics(); + ossimScalarType outputScalarType = anInterface->getOutputScalarType(); + + switch(outputScalarType) + { + case OSSIM_UCHAR: + { + computeStatisticsTemplate((ossim_uint8)0); + break; + } + case OSSIM_USHORT16: + case OSSIM_USHORT11: + { + computeStatisticsTemplate((ossim_uint16)0); + break; + } + case OSSIM_SSHORT16: + { + computeStatisticsTemplate((ossim_sint16)0); + break; + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + computeStatisticsTemplate((ossim_float64)0); + break; + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + computeStatisticsTemplate((ossim_float32)0); + break; + } + default : + { + break; + } + } + } +} + +bool ossimImageStatisticsSource::canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const +{ + return (PTR_CAST(ossimImageSourceInterface, object)&&(inputIndex < 1)); +} + +template <class T> +void ossimImageStatisticsSource::computeStatisticsTemplate(T dummyVariable) +{ + ossimImageSourceSequencer* sequencer = new ossimImageSourceSequencer; + + sequencer->connectMyInputTo(getInput()); + sequencer->setToStartOfSequence(); + ossim_uint32 bands = sequencer->getNumberOfOutputBands(); + + if(bands) + { + setStatsSize(bands); + ossimRefPtr<ossimImageData> dataObject; + + while( (dataObject=sequencer->getNextTile()).valid() ) + { + ossim_uint32 bandIdx = 0; + bands = dataObject->getNumberOfBands(); + ossimDataObjectStatus status = dataObject->getDataObjectStatus(); + if((status != OSSIM_EMPTY)&& + (dataObject->getBuf())) + { + ossim_uint32 offsetMax = dataObject->getWidth()*dataObject->getHeight(); + for(bandIdx = 0; bandIdx < bands; ++bandIdx) + { + ossim_float64 pixelCount = 0.0; + ossim_uint32 offset = 0; + T* dataPtr = static_cast<T*>(dataObject->getBuf(bandIdx)); + T nullPixel = static_cast<T>(dataObject->getNullPix(bandIdx)); + for(offset = 0; offset < offsetMax; ++offset) + { + if((*dataPtr) != nullPixel) + { + theMean[bandIdx] += *dataPtr; + if((*dataPtr) < theMin[bandIdx]) + { + theMin[bandIdx] = (*dataPtr); + } + if((*dataPtr) > theMax[bandIdx]) + { + theMax[bandIdx] = (*dataPtr); + } + ++pixelCount; + } + ++dataPtr; + } + if(pixelCount > 0) + { + theMean[bandIdx] /= pixelCount; + } + } + } + } + } + + sequencer->disconnect(); + delete sequencer; + sequencer = 0; +} + +const std::vector<ossim_float64>& ossimImageStatisticsSource::getMean()const +{ + return theMean; +} + +const std::vector<ossim_float64>& ossimImageStatisticsSource::getMin()const +{ + return theMin; +} + +const std::vector<ossim_float64>& ossimImageStatisticsSource::getMax()const +{ + return theMax; +} + +void ossimImageStatisticsSource::clearStatistics() +{ + theMean.clear(); + theMin.clear(); + theMax.clear(); +} + +void ossimImageStatisticsSource::setStatsSize(ossim_uint32 size) +{ + theMean.resize(size); + theMin.resize(size); + theMax.resize(size); + + std::fill(theMean.begin(), + theMean.end(), + (ossim_float64)0.0); + std::fill(theMin.begin(), + theMin.end(), + OSSIM_DEFAULT_MAX_PIX_DOUBLE); + std::fill(theMax.begin(), + theMax.end(), + (ossim_float64)OSSIM_DEFAULT_MIN_PIX_DOUBLE); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimImageStatisticsSource.h b/Utilities/OSSIM/ossim_core/imaging/ossimImageStatisticsSource.h new file mode 100644 index 0000000000..1c78bac8af --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimImageStatisticsSource.h @@ -0,0 +1,32 @@ +#ifndef ossimImageStatistics_HEADER +#define ossimImageStatistics_HEADER +#include <base/common/ossimSource.h> + +class OSSIMDLLEXPORT ossimImageStatisticsSource : public ossimSource +{ +public: + ossimImageStatisticsSource(); + virtual ~ossimImageStatisticsSource(); + + + virtual void computeStatistics(); + + virtual bool canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const; + + const std::vector<ossim_float64>& getMean()const; + const std::vector<ossim_float64>& getMin()const; + const std::vector<ossim_float64>& getMax()const; + +protected: + void clearStatistics(); + template <class T> + void computeStatisticsTemplate(T dummyVariable); + void setStatsSize(ossim_uint32 size); + + std::vector<ossim_float64> theMean; + std::vector<ossim_float64> theMin; + std::vector<ossim_float64> theMax; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimImageWriter.cpp b/Utilities/OSSIM/ossim_core/imaging/ossimImageWriter.cpp new file mode 100644 index 0000000000..84d7046c99 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimImageWriter.cpp @@ -0,0 +1,81 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: Frank Warmerdam (warmerdam@pobox.com) +// +// Description: +// +// Contains class declaration for ossimImageWriter. +//******************************************************************* +// $Id: ossimImageWriter.cpp,v 1.14 2006/01/03 13:24:18 dburken Exp $ + +#include <imaging/ossimImageWriter.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimFilename.h> +#include <base/common/ossimKeywordNames.h> +#include <base/context/ossimErrorContext.h> +#include <imaging/formats/tiff/ossimTiffOverviewBuilder.h> +#include <imaging/factory/ossimImageHandlerRegistry.h> +#include <imaging/formats/ossimImageHandler.h> + +RTTI_DEF1(ossimImageWriter, "ossimImageWriter", ossimOutputSource); + +ossimImageWriter::ossimImageWriter(ossimObject* owner) + : ossimOutputSource(owner, + 1, + 0, + true, + true) +{ + theAreaOfInterest.makeNan(); +} + +ossimImageWriter::ossimImageWriter(ossimObject* owner, + ossim_uint32 numberOfInputs, + ossim_uint32 numberOfOutputs, + bool inputListIsFixed, + bool outputListIsFixed) + :ossimOutputSource(owner, + numberOfInputs, + numberOfOutputs, + inputListIsFixed, + outputListIsFixed) +{ + theAreaOfInterest.makeNan(); +} + +ossimImageWriter::~ossimImageWriter() +{ +} + +bool ossimImageWriter::setViewingRect(const ossimIrect &aRect) +{ + setAreaOfInterest(aRect); + + return true; +} + +ossimIrect ossimImageWriter::getAreaOfInterest() const +{ + return theAreaOfInterest; +} + +void ossimImageWriter::setAreaOfInterest(const ossimIrect& inputAreaOfInterest) +{ + theAreaOfInterest = inputAreaOfInterest; +} + +bool ossimImageWriter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + return ossimOutputSource::saveState(kwl, prefix); +} + +bool ossimImageWriter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + return ossimOutputSource::loadState(kwl, prefix); +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimImageWriter.h b/Utilities/OSSIM/ossim_core/imaging/ossimImageWriter.h new file mode 100644 index 0000000000..834fd791f4 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimImageWriter.h @@ -0,0 +1,71 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: Frank Warmerdam (warmerdam@pobox.com) +// +// Description: +// +// Contains class declaration for ossimImageWriter +//******************************************************************* +// $Id: ossimImageWriter.h,v 1.19 2006/01/03 15:43:40 gpotts Exp $ + +#ifndef ossimImageWriter_HEADER +#define ossimImageWriter_HEADER + +#include <base/common/ossimConstants.h> +#include <base/common/ossimOutputSource.h> +#include <base/common/ossimCommon.h> +#include <base/data_types/ossimIrect.h> + +class ossimImage; +class ossimImageSource; +class ossimImageWriter; +class ossimImageWriterFactory; +class ossimKeywordlist; +class ossimFilename; + +#include <imaging/ossimImageSourceSequencer.h> + + +class OSSIM_DLL ossimImageWriter : public ossimOutputSource +{ +public: + ossimImageWriter(ossimObject* owner=NULL); + + ossimImageWriter(ossimObject* owner, + ossim_uint32 numberOfInputs, + ossim_uint32 numberOfOutputs, + bool inputListIsFixed, + bool outputListIsFixed); + + virtual ~ossimImageWriter(); + + /** + * @param aRect the rectangle to write. + * + * @return true on success, false if the rectangle is invalid. + */ + virtual bool setViewingRect(const ossimIrect &aRect); + + /** + * @return Returns theAreaOfInterest. + */ + virtual ossimIrect getAreaOfInterest() const; + + virtual void setAreaOfInterest(const ossimIrect& inputAreaOfInterest); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +protected: + + ossimIrect theAreaOfInterest; +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimRgbImage.cpp b/Utilities/OSSIM/ossim_core/imaging/ossimRgbImage.cpp new file mode 100644 index 0000000000..b794510275 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimRgbImage.cpp @@ -0,0 +1,1910 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// Description: +// +// +// Credits: +// Much of the implementation within this file was taken from gd +// We can use it but we need to give credit to the people who wrote +// the algorithms. +// +// COPYRIGHT STATEMENT FOLLOWS THIS LINE + +// Portions copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +// by Cold Spring Harbor Laboratory. Funded under Grant P41-RR02188 by +// the National Institutes of Health. + +// Portions copyright 1996, 1997, 1998, 1999, 2000, 2001 by +// Boutell.Com, Inc. + +// Portions relating to GD2 format copyright 1999, 2000 Philip Warner. + +// Portions relating to PNG copyright 1999, 2000 Greg Roelofs. + +// Portions relating to libttf copyright 1999, 2000 John Ellson +// (ellson@lucent.com). + +// Portions relating to JPEG and to color quantization copyright 2000, +// Doug Becker and copyright (C) 1994-1998, Thomas G. Lane. This +// software is based in part on the work of the Independent JPEG +// Group. See the file README-JPEG.TXT for more information. + +// Portions relating to WBMP copyright 2000 Maurice Szmurlo and Johan +// Van den Brande. + +// _Permission has been granted to copy, distribute and modify gd in +// any context without fee, including a commercial application, +// provided that this notice is present in user-accessible supporting +// documentation._ + +// This does not affect your ownership of the derived work itself, and +// the intent is to assure proper credit for the authors of gd, not to +// interfere with your productive use of gd. If you have questions, +// ask. "Derived works" includes all programs that utilize the +// library. Credit must be given in user-accessible documentation. + +// _This software is provided "AS IS."_ The copyright holders disclaim +// all warranties, either express or implied, including but not +// limited to implied warranties of merchantability and fitness for a +// particular purpose, with respect to this code and accompanying +// documentation. + +// Although their code does not appear in gd 2.0.1, the authors wish +// to thank David Koblas, David Rowley, and Hutchison Avenue Software +// Corporation for their prior contributions. + +// END OF COPYRIGHT STATEMENT +//************************************************************************* +// $Id: ossimRgbImage.cpp,v 1.18 2005/07/18 11:20:06 gpotts Exp $ +#include <iostream> +using namespace std; +#include <stdlib.h> +#include <imaging/ossimRgbImage.h> +#include <stddef.h> +#include <math.h> +#include <base/data_types/ossimDrect.h> +#include <base/common/ossimCommon.h> + +// this should be in another file. This is from gd's gdtable.c file and has +// precomputations for sine and cosine. It looks like they multiply the cos and +// sign by 1024 and store the rounded int. +static const int gdCosT[] = +{ + 1024, + 1023, + 1023, + 1022, + 1021, + 1020, + 1018, + 1016, + 1014, + 1011, + 1008, + 1005, + 1001, + 997, + 993, + 989, + 984, + 979, + 973, + 968, + 962, + 955, + 949, + 942, + 935, + 928, + 920, + 912, + 904, + 895, + 886, + 877, + 868, + 858, + 848, + 838, + 828, + 817, + 806, + 795, + 784, + 772, + 760, + 748, + 736, + 724, + 711, + 698, + 685, + 671, + 658, + 644, + 630, + 616, + 601, + 587, + 572, + 557, + 542, + 527, + 512, + 496, + 480, + 464, + 448, + 432, + 416, + 400, + 383, + 366, + 350, + 333, + 316, + 299, + 282, + 265, + 247, + 230, + 212, + 195, + 177, + 160, + 142, + 124, + 107, + 89, + 71, + 53, + 35, + 17, + 0, + -17, + -35, + -53, + -71, + -89, + -107, + -124, + -142, + -160, + -177, + -195, + -212, + -230, + -247, + -265, + -282, + -299, + -316, + -333, + -350, + -366, + -383, + -400, + -416, + -432, + -448, + -464, + -480, + -496, + -512, + -527, + -542, + -557, + -572, + -587, + -601, + -616, + -630, + -644, + -658, + -671, + -685, + -698, + -711, + -724, + -736, + -748, + -760, + -772, + -784, + -795, + -806, + -817, + -828, + -838, + -848, + -858, + -868, + -877, + -886, + -895, + -904, + -912, + -920, + -928, + -935, + -942, + -949, + -955, + -962, + -968, + -973, + -979, + -984, + -989, + -993, + -997, + -1001, + -1005, + -1008, + -1011, + -1014, + -1016, + -1018, + -1020, + -1021, + -1022, + -1023, + -1023, + -1024, + -1023, + -1023, + -1022, + -1021, + -1020, + -1018, + -1016, + -1014, + -1011, + -1008, + -1005, + -1001, + -997, + -993, + -989, + -984, + -979, + -973, + -968, + -962, + -955, + -949, + -942, + -935, + -928, + -920, + -912, + -904, + -895, + -886, + -877, + -868, + -858, + -848, + -838, + -828, + -817, + -806, + -795, + -784, + -772, + -760, + -748, + -736, + -724, + -711, + -698, + -685, + -671, + -658, + -644, + -630, + -616, + -601, + -587, + -572, + -557, + -542, + -527, + -512, + -496, + -480, + -464, + -448, + -432, + -416, + -400, + -383, + -366, + -350, + -333, + -316, + -299, + -282, + -265, + -247, + -230, + -212, + -195, + -177, + -160, + -142, + -124, + -107, + -89, + -71, + -53, + -35, + -17, + 0, + 17, + 35, + 53, + 71, + 89, + 107, + 124, + 142, + 160, + 177, + 195, + 212, + 230, + 247, + 265, + 282, + 299, + 316, + 333, + 350, + 366, + 383, + 400, + 416, + 432, + 448, + 464, + 480, + 496, + 512, + 527, + 542, + 557, + 572, + 587, + 601, + 616, + 630, + 644, + 658, + 671, + 685, + 698, + 711, + 724, + 736, + 748, + 760, + 772, + 784, + 795, + 806, + 817, + 828, + 838, + 848, + 858, + 868, + 877, + 886, + 895, + 904, + 912, + 920, + 928, + 935, + 942, + 949, + 955, + 962, + 968, + 973, + 979, + 984, + 989, + 993, + 997, + 1001, + 1005, + 1008, + 1011, + 1014, + 1016, + 1018, + 1020, + 1021, + 1022, + 1023, + 1023 +}; + +static const int gdSinT[] = +{ + 0, + 17, + 35, + 53, + 71, + 89, + 107, + 124, + 142, + 160, + 177, + 195, + 212, + 230, + 247, + 265, + 282, + 299, + 316, + 333, + 350, + 366, + 383, + 400, + 416, + 432, + 448, + 464, + 480, + 496, + 512, + 527, + 542, + 557, + 572, + 587, + 601, + 616, + 630, + 644, + 658, + 671, + 685, + 698, + 711, + 724, + 736, + 748, + 760, + 772, + 784, + 795, + 806, + 817, + 828, + 838, + 848, + 858, + 868, + 877, + 886, + 895, + 904, + 912, + 920, + 928, + 935, + 942, + 949, + 955, + 962, + 968, + 973, + 979, + 984, + 989, + 993, + 997, + 1001, + 1005, + 1008, + 1011, + 1014, + 1016, + 1018, + 1020, + 1021, + 1022, + 1023, + 1023, + 1024, + 1023, + 1023, + 1022, + 1021, + 1020, + 1018, + 1016, + 1014, + 1011, + 1008, + 1005, + 1001, + 997, + 993, + 989, + 984, + 979, + 973, + 968, + 962, + 955, + 949, + 942, + 935, + 928, + 920, + 912, + 904, + 895, + 886, + 877, + 868, + 858, + 848, + 838, + 828, + 817, + 806, + 795, + 784, + 772, + 760, + 748, + 736, + 724, + 711, + 698, + 685, + 671, + 658, + 644, + 630, + 616, + 601, + 587, + 572, + 557, + 542, + 527, + 512, + 496, + 480, + 464, + 448, + 432, + 416, + 400, + 383, + 366, + 350, + 333, + 316, + 299, + 282, + 265, + 247, + 230, + 212, + 195, + 177, + 160, + 142, + 124, + 107, + 89, + 71, + 53, + 35, + 17, + 0, + -17, + -35, + -53, + -71, + -89, + -107, + -124, + -142, + -160, + -177, + -195, + -212, + -230, + -247, + -265, + -282, + -299, + -316, + -333, + -350, + -366, + -383, + -400, + -416, + -432, + -448, + -464, + -480, + -496, + -512, + -527, + -542, + -557, + -572, + -587, + -601, + -616, + -630, + -644, + -658, + -671, + -685, + -698, + -711, + -724, + -736, + -748, + -760, + -772, + -784, + -795, + -806, + -817, + -828, + -838, + -848, + -858, + -868, + -877, + -886, + -895, + -904, + -912, + -920, + -928, + -935, + -942, + -949, + -955, + -962, + -968, + -973, + -979, + -984, + -989, + -993, + -997, + -1001, + -1005, + -1008, + -1011, + -1014, + -1016, + -1018, + -1020, + -1021, + -1022, + -1023, + -1023, + -1024, + -1023, + -1023, + -1022, + -1021, + -1020, + -1018, + -1016, + -1014, + -1011, + -1008, + -1005, + -1001, + -997, + -993, + -989, + -984, + -979, + -973, + -968, + -962, + -955, + -949, + -942, + -935, + -928, + -920, + -912, + -904, + -895, + -886, + -877, + -868, + -858, + -848, + -838, + -828, + -817, + -806, + -795, + -784, + -772, + -760, + -748, + -736, + -724, + -711, + -698, + -685, + -671, + -658, + -644, + -630, + -616, + -601, + -587, + -572, + -557, + -542, + -527, + -512, + -496, + -480, + -464, + -448, + -432, + -416, + -400, + -383, + -366, + -350, + -333, + -316, + -299, + -282, + -265, + -247, + -230, + -212, + -195, + -177, + -160, + -142, + -124, + -107, + -89, + -71, + -53, + -35, + -17 +}; + +ossimRgbImage::ossimRgbImage() + : theImageData(NULL), + theOffsets(NULL), + theThickness(1), + theRed(255), + theGreen(255), + theBlue(255) +{ +} + +ossimRgbImage::ossimRgbImage(ossimRefPtr<ossimImageData>& currentImageData) + : theImageData(NULL), + theOffsets(NULL), + theThickness(1), + theRed(255), + theGreen(255), + theBlue(255) +{ + setCurrentImageData(currentImageData); +} + + +ossimRgbImage::~ossimRgbImage() +{ + if(theOffsets) + { + delete [] theOffsets; + theOffsets = NULL; + } +} + +const ossimRefPtr<ossimImageData> ossimRgbImage::getImageData()const +{ + return theImageData; +} + +void ossimRgbImage::createNewGrey(long width, long height) +{ + theImageData = new ossimImageData(NULL, + OSSIM_UCHAR, + 1, + width, + height); + theImageData->initialize(); + + setCurrentImageData(theImageData); + +} + +void ossimRgbImage::createNewTrueColor(long width, long height) +{ + theImageData = new ossimImageData(NULL, + OSSIM_UCHAR, + 3, + width, + height); + theImageData->initialize(); +} + +void ossimRgbImage::initialize() +{ + if(!theImageData) + { + return; + } + if(theOffsets) + { + delete [] theOffsets; + theOffsets = NULL; + } + theWidth = theImageData->getWidth(); + theHeight = theImageData->getHeight(); + + theOffsets = new long[theHeight]; + for(long row = 0; row < theHeight; ++row) + { + theOffsets[row] = row*theWidth; + } + + // make it work for 1, 2, or 3 band data. + // we assume the fourth band is for the alpha channel + if(theImageData->getNumberOfBands() == 3) + { // point each band to r, g, b. + theBands[0] = static_cast<unsigned char*>(theImageData->getBuf(0)); + theBands[1] = static_cast<unsigned char*>(theImageData->getBuf(1)); + theBands[2] = static_cast<unsigned char*>(theImageData->getBuf(2)); + } + else if(theImageData->getNumberOfBands() == 2) + {//point r and g to the same place + theBands[0] = static_cast<unsigned char*>(theImageData->getBuf(0)); + theBands[1] = static_cast<unsigned char*>(theImageData->getBuf(0)); + theBands[2] = static_cast<unsigned char*>(theImageData->getBuf(1)); + } + else if(theImageData->getNumberOfBands() == 1) + {// point all band s to the first band + theBands[0] = static_cast<unsigned char*>(theImageData->getBuf(0)); + theBands[1] = static_cast<unsigned char*>(theImageData->getBuf(0)); + theBands[2] = static_cast<unsigned char*>(theImageData->getBuf(0)); + } +} + +void ossimRgbImage::setCurrentImageData(ossimRefPtr<ossimImageData>& imageData) +{ + if(imageData.valid()) + { + if((imageData->getScalarType() == OSSIM_UCHAR)&& + (imageData->getDataObjectStatus()!=OSSIM_NULL)) + { + theImageData = imageData; + initialize(); + } + } +} + +ossimRefPtr<ossimImageData> ossimRgbImage::getImageData() +{ + return theImageData; +} + + +void ossimRgbImage::drawPolygon(ossimIpt *p, + int n) +{ + if(!theImageData) + { + return; + } + int i; + int lx, ly; + + if (!n) + { + return; + } + lx = p->x; + ly = p->y; + drawLine (lx, ly, p[n - 1].x, p[n - 1].y); + + for (i = 1; (i < n); i++) + { + p++; + drawLine (lx, ly, p->x, p->y); + lx = p->x; + ly = p->y; + } +} + +void ossimRgbImage::drawPolygon(ossimDpt *p, + int n) +{ + if(!theImageData) + { + return; + } + int i; + double lx, ly; + + if (!n) + { + return; + } + lx = p->x; + ly = p->y; + drawLine (lx, ly, p[n - 1].x, p[n - 1].y); + + for (i = 1; (i < n); i++) + { + p++; + drawLine (lx, ly, p->x, p->y); + lx = p->x; + ly = p->y; + } +} + +void ossimRgbImage::drawPolygon(const vector<ossimIpt> &p) +{ + if(!theImageData) + { + return; + } + int n = p.size(); + + int i; + int lx, ly; + + if (!n) + { + return; + } + lx = p[0].x; + ly = p[0].y; + drawLine (lx, ly, p[n - 1].x, p[n - 1].y); + + for (i = 1; (i < n); i++) + { + drawLine (lx, ly, p[i].x, p[i].y); + lx = p[i].x; + ly = p[i].y; + } +} + +void ossimRgbImage::drawPolygon(const vector<ossimDpt> &p) +{ + if(!theImageData) + { + return; + } + int n = p.size(); + + int i; + double lx, ly; + + if (!n) + { + return; + } + lx = p[0].x; + ly = p[0].y; + drawLine (lx, ly, p[n - 1].x, p[n - 1].y); + + for (i = 1; (i < n); i++) + { + drawLine (lx, ly, p[i].x, p[i].y); + lx = p[i].x; + ly = p[i].y; + } +} + +inline int gdCompareInt (const void *a, const void *b) +{ + return (*(const int *) a) - (*(const int *) b); +} + +void ossimRgbImage::drawFilledArc (double cx, + double cy, + double w, + double h, + double s, + double e) +{ +// drawFilledArc((int)irint(cx), // center x +// (int)irint(cy), // center y +// (int)irint(w), // width +// (int)irint(h), // height +// (int)irint(s), // start angle +// (int)irint(e)); // end angle + drawFilledArc((int)(cx), // center x + (int)(cy), // center y + (int)(w), // width + (int)(h), // height + (int)(s), // start angle + (int)(e)); // end angle +} + +void ossimRgbImage::drawFilledArc (int cx, + int cy, + int w, + int h, + int s, + int e) +{ + if(!theImageData) + { + return; + } + ossimIpt pts[3]; + int i; + int lx = 0, ly = 0; + int fx, fy; + int w2, h2; + w2 = w / 2; + h2 = h / 2; + while (e < s) + { + e += 360; + } + for (i = s; (i <= e); i++) + { + int x, y; + x = ((long) gdCosT[i % 360] * (long) w2 / 1024) + cx; + y = ((long) gdSinT[i % 360] * (long) h2 / 1024) + cy; + if (i != s) + { + /* This is expensive! */ + pts[0].x = lx; + pts[0].y = ly; + pts[1].x = x; + pts[1].y = y; + pts[2].x = cx; + pts[2].y = cy; + drawFilledPolygon (pts, 3); + } + else + { + fx = x; + fy = y; + } + lx = x; + ly = y; + } +} + +void ossimRgbImage::drawArc (int cx, + int cy, + int w, + int h, + int s, + int e) +{ + if(!theImageData) + { + return; + } + int i; + int lx = 0, ly = 0; + int fx, fy; + int w2, h2; + w2 = w / 2; + h2 = h / 2; + while (e < s) + { + e += 360; + } + for (i = s; (i <= e); i++) + { + int x, y; + x = ((long) gdCosT[i % 360] * (long) w2 / 1024) + cx; + y = ((long) gdSinT[i % 360] * (long) h2 / 1024) + cy; + if (i != s) + { + drawLine (lx, ly, x, y); + } + else + { + fx = x; + fy = y; + } + lx = x; + ly = y; + } +} + +void ossimRgbImage::drawFilledPolygon(ossimIpt *p, + int n) +{ + if(!theImageData) + { + return; + } + int i; + int y; + int miny, maxy; + int minx, maxx; + int x1, y1; + int x2, y2; + int ind1, ind2; + int ints; + int *polyInts = NULL; + + if(!n) + { + return; + } + polyInts = new int[n]; + + miny = p[0].y; + maxy = p[0].y; + minx = p[0].x; + maxx = p[0].x; + for (i = 1; (i < n); i++) + { + miny = std::min((int)p[i].y, miny); + minx = std::min((int)p[i].x, minx); + maxy = std::max((int)p[i].y, maxy); + maxx = std::max((int)p[i].x, maxx); + } + /* Fix in 1.3: count a vertex only once */ + for (y = miny; (y <= maxy); y++) + { + ints = 0; + for (i = 0; (i < n); i++) + { + if (!i) + { + ind1 = n - 1; + ind2 = 0; + } + else + { + ind1 = i - 1; + ind2 = i; + } + y1 = p[ind1].y; + y2 = p[ind2].y; + if (y1 < y2) + { + x1 = p[ind1].x; + x2 = p[ind2].x; + } + else if (y1 > y2) + { + y2 = p[ind1].y; + y1 = p[ind2].y; + x2 = p[ind1].x; + x1 = p[ind2].x; + } + else + { + continue; + } + if ((y >= y1) && (y < y2)) + { + polyInts[ints++] = (y - y1) * (x2 - x1) / (y2 - y1) + x1; + } + else if ((y == maxy) && (y > y1) && (y <= y2)) + { + polyInts[ints++] = (y - y1) * (x2 - x1) / (y2 - y1) + x1; + } + } + qsort (polyInts, ints, sizeof (int), gdCompareInt); + + if(ints) + { + for (i = 0; (i < (ints)); i += 2) + { + drawLine (polyInts[i], y, + polyInts[i + 1], y); + } + } + else + { + if((miny == maxy) && (minx==maxx)) + { + drawLine((int)p[0].x, (int)p[0].y, (int)p[0].x, (int)p[0].y); + } + } + } + + if (polyInts) delete [] polyInts; +} + +void ossimRgbImage::drawFilledPolygon(ossimDpt *p, + int n) +{ + if(!theImageData) + { + return; + } + int i; + int y; + int miny, maxy; + int x1, y1; + int x2, y2; + int ind1, ind2; + int ints; + int *polyInts = NULL; + + if(!n) + { + return; + } + polyInts = new int[n]; + +// miny = irint(p[0].y); +// maxy = irint(p[0].y); + miny = (int)(p[0].y); + maxy = (int)(p[0].y); + for (i = 1; (i < n); i++) + { +// int testPy = irint(p[i].y); + int testPy = (int)(p[i].y); + if (testPy < miny) + { + miny = testPy; + } + if (testPy > maxy) + { + maxy = testPy; + } + } + /* Fix in 1.3: count a vertex only once */ + for (y = miny; (y <= maxy); y++) + { + ints = 0; + for (i = 0; (i < n); i++) + { + if (!i) + { + ind1 = n - 1; + ind2 = 0; + } + else + { + ind1 = i - 1; + ind2 = i; + } +// y1 = irint(p[ind1].y); +// y2 = irint(p[ind2].y); + y1 = (int)(p[ind1].y); + y2 = (int)(p[ind2].y); + if (y1 < y2) + { + x1 = irint(p[ind1].x); + x2 = irint(p[ind2].x); + } + else if (y1 > y2) + { +// y2 = irint(p[ind1].y); +// y1 = irint(p[ind2].y); +// x2 = irint(p[ind1].x); +// x1 = irint(p[ind2].x); + y2 = (int)(p[ind1].y); + y1 = (int)(p[ind2].y); + x2 = (int)(p[ind1].x); + x1 = (int)(p[ind2].x); + } + else + { + continue; + } + if ((y >= y1) && (y < y2)) + { + polyInts[ints++] = (y - y1) * (x2 - x1) / (y2 - y1) + x1; + } + else if ((y == maxy) && (y > y1) && (y <= y2)) + { + polyInts[ints++] = (y - y1) * (x2 - x1) / (y2 - y1) + x1; + } + } + qsort (polyInts, ints, sizeof (int), gdCompareInt); + + for (i = 0; (i < (ints)); i += 2) + { + drawLine (polyInts[i], y, + polyInts[i + 1], y); + } + } + + if (polyInts) delete [] polyInts; +} + +void ossimRgbImage::drawFilledPolygon(const vector<ossimIpt> &p) +{ + if(!theImageData) + { + return; + } + int n = p.size(); + int i; + int y; + int miny, maxy; + int x1, y1; + int x2, y2; + int ind1, ind2; + int ints; + int *polyInts = NULL; + + if(!n) + { + return; + } + polyInts = new int[n]; + + miny = p[0].y; + maxy = p[0].y; + for (i = 1; (i < n); i++) + { + if (p[i].y < miny) + { + miny = p[i].y; + } + if (p[i].y > maxy) + { + maxy = p[i].y; + } + } + /* Fix in 1.3: count a vertex only once */ + for (y = miny; (y <= maxy); y++) + { + ints = 0; + for (i = 0; (i < n); i++) + { + if (!i) + { + ind1 = n - 1; + ind2 = 0; + } + else + { + ind1 = i - 1; + ind2 = i; + } + y1 = p[ind1].y; + y2 = p[ind2].y; + if (y1 < y2) + { + x1 = p[ind1].x; + x2 = p[ind2].x; + } + else if (y1 > y2) + { + y2 = p[ind1].y; + y1 = p[ind2].y; + x2 = p[ind1].x; + x1 = p[ind2].x; + } + else + { + continue; + } + if ((y >= y1) && (y < y2)) + { + polyInts[ints++] = (y - y1) * (x2 - x1) / (y2 - y1) + x1; + } + else if ((y == maxy) && (y > y1) && (y <= y2)) + { + polyInts[ints++] = (y - y1) * (x2 - x1) / (y2 - y1) + x1; + } + } + qsort (polyInts, ints, sizeof (int), gdCompareInt); + + for (i = 0; (i < (ints)); i += 2) + { + drawLine (polyInts[i], y, + polyInts[i + 1], y); + } + } + + if (polyInts) delete [] polyInts; +} + +void ossimRgbImage::drawFilledPolygon(const vector<ossimDpt> &p) +{ + if(!theImageData) + { + return; + } + int n = p.size(); + int i; + int y; + int miny, maxy; + int x1, y1; + int x2, y2; + int ind1, ind2; + int ints; + int *polyInts = NULL; + + if(!n) + { + return; + } + polyInts = new int[n]; + + miny = (int)p[0].y;//irint(p[0].y); + maxy = (int)p[0].y;//irint(p[0].y); + for (i = 1; (i < n); i++) + { + int testPy = (int)p[i].y;//irint(p[i].y); + if (testPy < miny) + { + miny = testPy; + } + if (testPy > maxy) + { + maxy = testPy; + } + } + /* Fix in 1.3: count a vertex only once */ + for (y = miny; (y <= maxy); y++) + { + ints = 0; + for (i = 0; (i < n); i++) + { + if (!i) + { + ind1 = n - 1; + ind2 = 0; + } + else + { + ind1 = i - 1; + ind2 = i; + } +// y1 = irint(p[ind1].y); +// y2 = irint(p[ind2].y); + y1 = (int)(p[ind1].y); + y2 = (int)(p[ind2].y); + if (y1 < y2) + { +// x1 = irint(p[ind1].x); +// x2 = irint(p[ind2].x); + x1 = (int)(p[ind1].x); + x2 = (int)(p[ind2].x); + } + else if (y1 > y2) + { +// y2 = irint(p[ind1].y); +// y1 = irint(p[ind2].y); +// x2 = irint(p[ind1].x); +// x1 = irint(p[ind2].x); + y2 = (int)(p[ind1].y); + y1 = (int)(p[ind2].y); + x2 = (int)(p[ind1].x); + x1 = (int)(p[ind2].x); + } + else + { + continue; + } + if ((y >= y1) && (y < y2)) + { + polyInts[ints++] = (y - y1) * (x2 - x1) / (y2 - y1) + x1; + } + else if ((y == maxy) && (y > y1) && (y <= y2)) + { + polyInts[ints++] = (y - y1) * (x2 - x1) / (y2 - y1) + x1; + } + } + qsort (polyInts, ints, sizeof (int), gdCompareInt); + + for (i = 0; (i < (ints)); i += 2) + { + drawLine (polyInts[i], y, + polyInts[i + 1], y); + } + } + + if (polyInts) delete [] polyInts; +} + +void ossimRgbImage::drawLine(const ossimIpt& start, + const ossimIpt& end) +{ + drawLine((int)start.x, + (int)start.y, + (int)end.x, + (int)end.y); + +} + +void ossimRgbImage::drawLine(const ossimDpt& start, + const ossimDpt& end) +{ +// drawLine((int)irint(start.x), +// (int)irint(start.y), +// (int)irint(end.x), +// (int)irint(end.y)); + + drawLine((int)(start.x), + (int)(start.y), + (int)(end.x), + (int)(end.y)); + +} + +void ossimRgbImage::drawLine(double x1, + double y1, + double x2, + double y2) +{ +// drawLine((int)irint(x1), +// (int)irint(y1), +// (int)irint(x2), +// (int)irint(y2)); + drawLine((int)(x1), + (int)(y1), + (int)(x2), + (int)(y2)); + +} +void ossimRgbImage::drawLine(int x1, + int y1, + int x2, + int y2) +{ + if(!theImageData) + { + return; + } + + // we need to shift x and y relative to the image data + // origin. That way we are doing the algorithm relative to + // the 0,0 + // + ossimIpt origin = ossimDpt(theImageData->getOrigin()); + x1 += (-origin.x); + y1 += (-origin.y); + x2 += (-origin.x); + y2 += (-origin.y); + +// ossimDpt start(x1, y1); +// ossimDpt end(x2,y2); +// ossimDrect bounds(0,0,theWidth-1, theHeight-1); + +// if(bounds.clip(start, end)) return; + +// x1 = (int)start.x; +// y1 = (int)start.y; +// x2 = (int)end.x; +// y2 = (int)end.y; + + int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag; + int wid; + int w, wstart; + int thick = theThickness; + + dx = abs (x2 - x1); + dy = abs (y2 - y1); + if (dy <= dx) + { + /* More-or-less horizontal. use wid for vertical stroke */ + /* Doug Claar: watch out for NaN in atan2 (2.0.5) */ + if ((dx == 0) && (dy == 0)) + { + wid = 1; + } + else + { + /* 2.0.12: Michael Schwartz: divide rather than multiply; + TBB: but watch out for /0! */ + double ac = cos (atan2 ((double)dy, (double)dx)); + if (ac != 0) + { + wid = irint(thick / ac); + } + else + { + wid = 1; + } + if (wid == 0) + { + wid = 1; + } + } + d = 2 * dy - dx; + incr1 = 2 * dy; + incr2 = 2 * (dy - dx); + if (x1 > x2) + { + x = x2; + y = y2; + ydirflag = (-1); + xend = x1; + } + else + { + x = x1; + y = y1; + ydirflag = 1; + xend = x2; + } + + /* Set up line thickness */ + wstart = y - wid / 2; + for (w = wstart; w < wstart + wid; w++) + slowPlotPixel(x, w, theRed, theGreen, theBlue); + + if (((y2 - y1) * ydirflag) > 0) + { + while (x < xend) + { + x++; + if (d < 0) + { + d += incr1; + } + else + { + y++; + d += incr2; + } + wstart = y - wid / 2; + for (w = wstart; w < wstart + wid; w++) + slowPlotPixel(x, w, theRed, theGreen, theBlue); + } + } + else + { + while (x < xend) + { + x++; + if (d < 0) + { + d += incr1; + } + else + { + y--; + d += incr2; + } + wstart = y - wid / 2; + for (w = wstart; w < wstart + wid; w++) + slowPlotPixel(x, w, theRed, theGreen, theBlue); + } + } + } + else + { + /* More-or-less vertical. use wid for horizontal stroke */ + /* 2.0.12: Michael Schwartz: divide rather than multiply; + TBB: but watch out for /0! */ + double as = sin (atan2 ((double)dy, (double)dx)); + if (as != 0) + { + wid = irint(thick / as); + } + else + { + wid = 1; + } + if (wid == 0) + wid = 1; + + d = 2 * dx - dy; + incr1 = 2 * dx; + incr2 = 2 * (dx - dy); + if (y1 > y2) + { + y = y2; + x = x2; + yend = y1; + xdirflag = (-1); + } + else + { + y = y1; + x = x1; + yend = y2; + xdirflag = 1; + } + + /* Set up line thickness */ + wstart = x - wid / 2; + for (w = wstart; w < wstart + wid; w++) + slowPlotPixel(w, y, theRed, theGreen, theBlue); + + if (((x2 - x1) * xdirflag) > 0) + { + while (y < yend) + { + y++; + if (d < 0) + { + d += incr1; + } + else + { + x++; + d += incr2; + } + wstart = x - wid / 2; + for (w = wstart; w < wstart + wid; w++) + slowPlotPixel(w, y, theRed, theGreen, theBlue); + } + } + else + { + while (y < yend) + { + y++; + if (d < 0) + { + d += incr1; + } + else + { + x--; + d += incr2; + } + wstart = x - wid / 2; + for (w = wstart; w < wstart + wid; w++) + slowPlotPixel(w, y, theRed, theGreen, theBlue); + } + } + } +} +void ossimRgbImage::drawRectangle(double x1, + double y1, + double x2, + double y2) +{ +// drawRectangle(irint(x1), +// irint(y1), +// irint(x2), +// irint(y2)); + drawRectangle((int)(x1), + (int)(y1), + (int)(x2), + (int)(y2)); +} + +void ossimRgbImage::drawRectangle(int x1, + int y1, + int x2, + int y2) +{ + if(x1 > x2) + { + swap(x1, x2); + } + if(y1 > y2) + { + swap(y1, y2); + } + int x1h = x1, + x1v = x1, + y1h = y1, + y1v = y1, + x2h = x2, + x2v = x2, + y2h = y2, + y2v = y2; + + int thick = theThickness; + + + if (thick > 1) + { + int half = thick / 2; + int half1 = thick - half; + + if (y1 < y2) + { + y1v = y1h - half; + y2v = y2h + half1 - 1; + } + else + { + y1v = y1h + half1 - 1; + y2v = y2h - half; + } + } + + drawLine (x1h, y1h, x2h, y1h); + drawLine (x1h, y2h, x2h, y2h); + drawLine (x1v, y1v, x1v, y2v); + drawLine (x2v, y1v, x2v, y2v); +} + + +void ossimRgbImage::drawFilledRectangle(double x1, + double y1, + double x2, + double y2) +{ +// drawFilledRectangle((int)irint(x1), +// (int)irint(y1), +// (int)irint(x2), +// (int)irint(y2)); + drawFilledRectangle((int)(x1), + (int)(y1), + (int)(x2), + (int)(y2)); +} + +void ossimRgbImage::drawFilledRectangle(int x1, + int y1, + int x2, + int y2) +{ + int x, y; + + if(x1 > x2) + { + swap(x1, x2); + } + if(y1 > y2) + { + swap(y1, y2); + } + for (y = y1; (y <= y2); y++) + { + for (x = x1; (x <= x2); x++) + { + slowPlotPixel (x, y, theRed, theGreen, theBlue); + } + } +} + +void ossimRgbImage::fill() +{ + if(!theImageData) + { + return; + } + long width = theWidth; + long height = theHeight; + + for(long row = 0; row < height; ++row) + { + for(long col = 0; col < width; ++col) + { + fastPlotPixel(col, row, + theRed, theGreen, theBlue); + } + } +} + +void ossimRgbImage::setDrawColor(unsigned char r, + unsigned char g, + unsigned char b) +{ + theRed = r; + theGreen = g; + theBlue = b; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimRgbImage.h b/Utilities/OSSIM/ossim_core/imaging/ossimRgbImage.h new file mode 100644 index 0000000000..da9af0bb98 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimRgbImage.h @@ -0,0 +1,370 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimRgbImage.h,v 1.14 2005/05/20 20:22:41 dburken Exp $ +#ifndef ossimRgbImage_HEADER +#define ossimRgbImage_HEADER +#include <base/data_types/ossimIpt.h> +#include <imaging/ossimImageData.h> + +#include <vector> +using namespace std; + +class OSSIM_DLL ossimRgbImage +{ +public: + ossimRgbImage(); + ossimRgbImage(ossimRefPtr<ossimImageData>& currentImageData); + + virtual ~ossimRgbImage(); + + /** + * Will construct a new single band image data object. + */ + virtual void createNewGrey(long width, long height); + + /** + * Will construct a new 3 band rgb data object. + */ + virtual void createNewTrueColor(long width, long height); + + /** + * Will initilize any pre-computations that are needed. + * Example: setting up the origin for adjustments and + * setting up the offsets. + */ + virtual void initialize(); + + /** + * This will plot a pixel and will do inside outside compares. + * This assumes the pixel has already been put into a relative + * 0,0 to the upper left corner of the image data. + * + * example: if the upperleft corner or origin of the image was + * 34, 55 then it assumes that the points passed in are + * already relative to that corner not absolute. + */ + inline void slowPlotPixel(long x, + long y, + unsigned char r, + unsigned char g, + unsigned char b); + + /** + * same thing as slowPlotPixel but without the inside outside compare + */ + inline void fastPlotPixel(long x, + long y, + unsigned char r, + unsigned char g, + unsigned char b); + + /** + * All the drawing algorithms have thickness. So you can draw a line + * that has thickness of 3 pixels if you want. Note: the thickness is in + * pixels + */ + void setThickness(long thickness){theThickness = thickness;} + + + /** + * Allows you to change the image data that this RgbImage object + * operates on. You can specify if the image owns the data or not. + * if it doesn't own the data then it will not destroy it when the + * data is changed to a different data object or if this object + * is deleted. + */ + void setCurrentImageData(ossimRefPtr<ossimImageData>& imageData); + /** + * Will return the image data. + */ + ossimRefPtr<ossimImageData> getImageData(); + + /** + * We will cut and paste the code from + * drawFilledPolygon(ossimIpt *p, int n). + */ + void drawFilledPolygon(const vector<ossimDpt>& p); + /** + * We will cut and paste the code from + * drawFilledPolygon(ossimIpt *p, int n). + */ + void drawFilledPolygon(const vector<ossimIpt>& p); + + + /** + * This will draw a polygon and fill it with the specified color. + */ + void drawFilledPolygon(ossimDpt *p, + int n); + /** + * This will draw a polygon and fill it with the specified color. + */ + void drawFilledPolygon(ossimIpt *p, + int n); + + /** + * will draw an arc. The cx and cy specifies the center point in image + * space. The parameters w, h are the width and height of the arc. + * The s and e are the starting and ending angles. So if I want to + * draw a complete circle at point 45, 45 with width 10 and height 23 then + * we set the angles s =0 and e = 360: + * drawArc(45, 45, 10, 23, 0, 360). + * + */ + void drawArc(double cx, + double cy, + double w, + double h, + double s, + double e); + + /** + * will draw an arc. The cx and cy specifies the center point in image + * space. The parameters w, h are the width and height of the arc. + * The s and e are the starting and ending angles. So if I want to + * draw a complete circle at point 45, 45 with width 10 and height 23 then + * we set the angles s =0 and e = 360: + * drawArc(45, 45, 10, 23, 0, 360). + * + */ + void drawArc(int cx, + int cy, + int w, + int h, + int s, + int e); + + /** + * This will draw a filled arc. See drawArc for documentation of + * parameters. + */ + void drawFilledArc(double cx, + double cy, + double w, + double h, + double s, + double e); + + /** + * This will draw a filled arc. See drawArc for documentation of + * parameters. + */ + void drawFilledArc(int cx, + int cy, + int w, + int h, + int s, + int e); + + void drawPolygon(const vector<ossimDpt>& p); + void drawPolygon(const vector<ossimIpt>& p); + + /** + * Draws a polygon. The first argument is an array of points. The second + * argument is the number of points and the rest are the rgb color values. + * theColor used is set by the setDrawColor. + */ + void drawPolygon(ossimDpt *p, + int n); + + /** + * Draws a polygon. The first argument is an array of points. The second + * argument is the number of points and the rest are the rgb color values. + * theColor used is set by the setDrawColor. + */ + void drawPolygon(ossimIpt *p, + int n); + + /** + * About all the draw routines will call draw line. it takes a start and + * an end point and a color value. + * theColor used is set by the setDrawColor. + */ + void drawLine(double x1, + double y1, + double x2, + double y2); + + /** + * About all the draw routines will call draw line. it takes a start and + * an end point and a color value. + * theColor used is set by the setDrawColor. + */ + void drawLine(int x1, + int y1, + int x2, + int y2); + + /** + * About all the draw routines will call draw line. it takes a start and + * an end point and a color value. + * theColor used is set by the setDrawColor. + */ + void drawLine(const ossimIpt& start, + const ossimIpt& end); + /** + * About all the draw routines will call draw line. it takes a start and + * an end point and a color value. + * theColor used is set by the setDrawColor. + */ + void drawLine(const ossimDpt& start, + const ossimDpt& end); + + + /** + * Will draw a rectangle. The color used is set by setDrawColor. + */ + void drawRectangle(double x1, + double y1, + double x2, + double y2); + + /** + * Will draw a rectangle. The color used is set by setDrawColor. + */ + void drawRectangle(int x1, + int y1, + int x2, + int y2); + + /** + * Will draw a filled rectangle with the current draw color. + * Use setDrawColor to set it. + */ + void drawFilledRectangle(double x1, + double y1, + double x2, + double y2); + + /** + * Will draw a filled rectangle with the current draw color. + * Use setDrawColor to set it. + */ + void drawFilledRectangle(int x1, + int y1, + int x2, + int y2); + + /** + * Will fill the entire data object with the specified color set in + * setDrawColor. + */ + void fill(); + + void setDrawColor(unsigned char r = 255, + unsigned char g = 255, + unsigned char b = 255); + /** + * Will take the point passed in and translate + * to a 0,0. + * Example: + * Let's say that we have origin 45,34 for the + * image's upper left corner. then a call to this + * method will translate the point passed in + * x-45, y-34 + */ +// inline void translateToOrigin(long& x, long& y); + + /** + * Will take the point passed in and translate + * to a 0,0. + * Example: + * Let's say that we have origin 45,34 for the + * image's upper left corner. then a call to this + * method will translate the point passed in + * x-45, y-34 + */ +// inline void translateToOrigin(ossimDpt& pt); + const ossimRefPtr<ossimImageData> getImageData()const; + +protected: + + /** + * This object operates on the ossimImageData. Note the + * ossimImageData is a band separate so the bands follow sequentially: + * all the reds followed by all the blues followed by all greens + */ + ossimRefPtr<ossimImageData> theImageData; + + /** + * This will hold precomputed offsets to the + * start of each row. This will get rid of a multiplication + * per access. Since we will be accessing on a per pixel basis + * this will be needed. + */ + long *theOffsets; + + /** + * This is a fast access to the start of each band. + */ + unsigned char* theBands[3]; + + /** + * This is here so we don't have to call theWidth and theHeight + * of the ossimImageData. + */ + long theWidth; + + /** + * This is here so we don't have to call theWidth and theHeight + * of the ossimImageData. + */ + long theHeight; + + /** + * Holds the draw thickness. + */ + long theThickness; + + + /** + * The red component of the color used in drawing the shapes + */ + unsigned char theRed; + + /** + * The green component of the color used in drawing the shapes + */ + unsigned char theGreen; + + /** + * The blue component of the color used in drawing the shapes + */ + unsigned char theBlue; +}; + +inline void ossimRgbImage::slowPlotPixel(long x, + long y, + unsigned char r, + unsigned char g, + unsigned char b) +{ + if((x > -1) && (x < theWidth) && + (y > -1) && (y < theHeight)) + { + theBands[0][theOffsets[y]+x] = r; + theBands[1][theOffsets[y]+x] = g; + theBands[2][theOffsets[y]+x] = b; + } +} + +inline void ossimRgbImage::fastPlotPixel(long x, + long y, + unsigned char r, + unsigned char g, + unsigned char b) +{ + theBands[0][theOffsets[y]+x] = r; + theBands[1][theOffsets[y]+x] = g; + theBands[2][theOffsets[y]+x] = b; +} + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimS16ImageData.cpp b/Utilities/OSSIM/ossim_core/imaging/ossimS16ImageData.cpp new file mode 100644 index 0000000000..4921c3a5be --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimS16ImageData.cpp @@ -0,0 +1,716 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Class definition of ossimU16ImageData. Specialized image data object for +// signed short data. +// +//************************************************************************* +// $Id: ossimS16ImageData.cpp,v 1.19 2004/09/02 13:59:03 dburken Exp $ + +#include <imaging/ossimS16ImageData.h> +#include <base/common/ossimErrorCodes.h> +#include <base/context/ossimErrorContext.h> +#include <base/data_types/ossimIrect.h> +#include <base/data_types/ossimMultiBandHistogram.h> +#include <base/data_types/ossimHistogram.h> + +RTTI_DEF1(ossimS16ImageData, "ossimS16ImageData", ossimImageData) + +ossimS16ImageData::ossimS16ImageData() + : + ossimImageData() +{ +} + +ossimS16ImageData::ossimS16ImageData(ossimSource* source, + ossim_uint32 bands) + : + ossimImageData(source, + OSSIM_SSHORT16, + bands) +{ +} + +ossimS16ImageData::ossimS16ImageData(ossimSource* source, + ossim_uint32 bands, + ossim_uint32 width, + ossim_uint32 height) + : + ossimImageData(source, + OSSIM_SSHORT16, + bands, + width, + height) +{ +} + +ossimS16ImageData::ossimS16ImageData(const ossimS16ImageData &rhs) + : + ossimImageData(rhs) +{ +} + +ossimS16ImageData::~ossimS16ImageData() +{ +} + +ossimObject* ossimS16ImageData::dup()const +{ + return new ossimS16ImageData(*this); +} + +ossimDataObjectStatus ossimS16ImageData::validate() const +{ + if (theDataBuffer == NULL) + { + setDataObjectStatus(OSSIM_NULL); + return OSSIM_NULL; + } + + ossim_uint32 count = 0; + const ossim_uint32 SIZE = getSize(); + const ossim_uint32 BOUNDS = getSizePerBand(); + const ossim_uint32 NUMBER_OF_BANDS = getNumberOfBands(); + + for(ossim_uint32 band = 0; band < NUMBER_OF_BANDS; ++band) + { + ossim_sint16 np = (ossim_sint16)theNullPixelValue[band]; + const ossim_sint16* p = getSshortBuf(band); + for (ossim_uint32 i=0; i<BOUNDS; i++) + { + // check if the band is null + if (p[i] != np) count++; + } + } + + if (!count) + setDataObjectStatus(OSSIM_EMPTY); + else if (count == SIZE) + setDataObjectStatus(OSSIM_FULL); + else + setDataObjectStatus(OSSIM_PARTIAL); + + return getDataObjectStatus(); +} + +void ossimS16ImageData::getNormalizedFloat(ossim_uint32 offset, + ossim_uint32 bandNumber, + float& result)const +{ + if(!result) + { + return; + } + + // make sure that the types and width and height are good. + if( (getDataObjectStatus() == OSSIM_NULL) && isValidBand(bandNumber) ) + { + return; + } + + ossim_int32 p = getSshortBuf(bandNumber)[offset]; + + getNormFromPix(p, result, bandNumber); +} + +void ossimS16ImageData::setNormalizedFloat(ossim_uint32 offset, + ossim_uint32 bandNumber, + float inputValue) +{ + // make sure that the types and width and height are + // good. + if((getDataObjectStatus() == OSSIM_NULL)&& + (bandNumber < getNumberOfBands())) + { + return; + } + + ossim_int32 p; + + getPixFromNorm(p, inputValue, bandNumber); + + getSshortBuf(bandNumber)[offset] = static_cast<ossim_sint16>(p); +} + +void +ossimS16ImageData::convertToNormalizedFloat(ossimImageData* result)const +{ + if(!result) + { + return; + } + // make sure that the types and width and height are + // good. + if( (result->getScalarType() != OSSIM_NORMALIZED_FLOAT) || + (result->getNumberOfBands() != this->getNumberOfBands())|| + (result->getWidth() != this->getWidth()) || + (result->getHeight() != this->getHeight())|| + (result->getDataObjectStatus() == OSSIM_NULL) || + (getDataObjectStatus() == OSSIM_NULL)) + { + return; + } + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + for(ossim_uint32 bandCount = 0; bandCount < theNumberOfDataComponents; + ++bandCount) + { + const ossim_sint16* sourceBuf = getSshortBuf(bandCount); + ossim_float32* resultBuf = static_cast<ossim_float32*>(result->getBuf(bandCount)); + for(ossim_uint32 counter = 0; counter < size; ++counter) + { + getNormFromPix(sourceBuf[counter], resultBuf[counter], bandCount); + } + } + } +} + +void ossimS16ImageData::convertToNormalizedDouble(ossimImageData* result)const +{ + if(!result) + { + return; + } + + // make sure that the types and width and height are + // good. + if( (result->getScalarType() != OSSIM_NORMALIZED_FLOAT) || + (result->getNumberOfBands() != this->getNumberOfBands())|| + (result->getWidth() != this->getWidth()) || + (result->getHeight() != this->getHeight())|| + (result->getDataObjectStatus() == OSSIM_NULL) || + (getDataObjectStatus() == OSSIM_NULL)) + { + return; + } + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + for(ossim_uint32 bandCount = 0; bandCount < theNumberOfDataComponents; + ++bandCount) + { + const ossim_sint16* sourceBuf = getSshortBuf(bandCount); + ossim_float64* resultBuf = static_cast<ossim_float64*>(result->getBuf(bandCount)); + for(ossim_uint32 counter = 0; counter < size; ++counter) + { + getNormFromPix(sourceBuf[counter], + resultBuf[counter], + bandCount); + } + } + } + +} + +void ossimS16ImageData::unnormalizeInput(ossimImageData* normalizedInput) +{ + if((normalizedInput->getScalarType() != OSSIM_NORMALIZED_FLOAT) && + (normalizedInput->getScalarType() != OSSIM_NORMALIZED_DOUBLE) ) + { + //ERROR + return; + } + + ossim_uint32 counter = 0; + ossim_uint32 bandCount = 0; + ossim_uint32 size = getSizePerBand(); + ossimScalarType scalarType = normalizedInput->getScalarType(); + + if(size > 0) + { + if(scalarType == OSSIM_NORMALIZED_FLOAT) + { + for(bandCount = 0; bandCount < theNumberOfDataComponents; ++bandCount) + { + ossim_float32* sourceBuf = + static_cast<ossim_float32*>(normalizedInput->getBuf(bandCount)); + ossim_sint16* resultBuf = getSshortBuf(bandCount); + for(counter = 0; counter < size; ++counter) + { + ossim_float32 f = sourceBuf[counter]; + ossim_int32 p; + getPixFromNorm(p, f, bandCount); + resultBuf[counter] = static_cast<ossim_sint16>(p); + } + } + } + else // Double + { + for(bandCount = 0; bandCount < theNumberOfDataComponents; ++bandCount) + { + ossim_float64* sourceBuf = + static_cast<ossim_float64*>(normalizedInput->getBuf(bandCount)); + ossim_sint16* resultBuf = getSshortBuf(bandCount); + for(counter = 0; counter < size; ++counter) + { + ossim_int32 p; + getPixFromNorm(p, sourceBuf[counter], bandCount); + resultBuf[counter] = static_cast<ossim_sint16>(p); + } + } + } + } +} + +double ossimS16ImageData::computeMeanSquaredError(double meanValue, + ossim_uint32 bandNumber) +{ + double result = -1; // invalid MSE + ossim_uint32 index = 0; + double delta = 0; + ossim_uint32 validPixelCount=0; + + ossim_sint16* buffer = getSshortBuf(bandNumber); + if(buffer) + { + ossim_uint32 bounds = getWidth()*getHeight(); + for(index = 0; index < bounds; ++index) + { + if(!isNull(index)) + { + delta = *buffer - meanValue; + result += (delta*delta); + ++validPixelCount; + } + ++buffer; + } + if(validPixelCount > 0) + { + result /= validPixelCount; + } + } + + return result; +} + +//****************************************************************** +// +// NOTE: I was checking for null and not adding it to the histogram. +// this was messing up the equalization algorithms since the +// accumulation histogram did not represent the area of the +// image. For now I will leave out the check for "is null" and +// add this to the count so that the total accumulation is the +// area of the image. +// +//****************************************************************** +void ossimS16ImageData::populateHistogram(ossimMultiBandHistogram* histo) +{ + ossim_uint32 numberOfBands = getNumberOfBands(); + + if( (getDataObjectStatus() == OSSIM_NULL) || + (getDataObjectStatus() == OSSIM_EMPTY)) + { + return; + } + + for(ossim_uint32 band = 0; band < numberOfBands; ++band) + { + ossimHistogram* currentHisto = histo->getHistogram(band); + ossim_sint16* buffer = getSshortBuf(band); + + if(currentHisto) + { + float *counts = currentHisto->GetCounts(); + ossim_uint32 upperBound = getWidth()*getHeight(); + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + counts[buffer[offset]]++; + } + } + } +} + +double ossimS16ImageData::computeAverageBandValue(ossim_uint32 bandNumber) +{ + double result = 0.0; + ossim_uint32 index = 0; + ossim_uint32 validPixelCount=0; + + ossim_sint16* buffer = getSshortBuf(bandNumber); + if(buffer) + { + ossim_uint32 bounds = getSizePerBand(); + for(index = 0; index < bounds; ++index) + { + if(!isNull(index)) + { + result += *buffer; + ++validPixelCount; + } + ++buffer; + } + if(validPixelCount > 0) + { + result /= validPixelCount; + } + } + + return result; +} + +void ossimS16ImageData::makeBlank() +{ + void* s = getBuf(); + + if (s == NULL) return; // nothing to do... + + ossim_uint32 size_in_pixels = getSizePerBand(); + + for(ossim_uint32 band =0; band < getNumberOfBands(); ++band) + { + ossim_sint16 np = (ossim_sint16)theNullPixelValue[band]; + ossim_sint16* p = getSshortBuf(band); + for (ossim_uint32 i=0; i<size_in_pixels; i++) p[i] = np; + } + + setDataObjectStatus(OSSIM_EMPTY); +} + +void ossimS16ImageData::setValue(ossim_int32 x, ossim_int32 y, double color) +{ + if(theDataBuffer&&isWithin(x, y)) + { + //*** + // Compute the offset into the buffer for (x,y). This should always + // come out positive. + //*** + ossim_uint32 ux = static_cast<ossim_uint32>(x - theOrigin.x); + ossim_uint32 uy = static_cast<ossim_uint32>(y - theOrigin.y); + + ossim_uint32 offset = uy * theSpatialExtents[0] + ux; + + for(ossim_uint32 band = 0; band < theNumberOfDataComponents; band++) + { + ossim_sint16* buf = getSshortBuf(band)+offset; + *buf = (ossim_sint16)color; + } + } +} + +void ossimS16ImageData::fill(ossim_uint32 band, double value) +{ + void* s = getBuf(band); + + if (s == NULL) return; // nothing to do... + + ossim_uint32 size_in_pixels = getSizePerBand(); + ossim_sint16* p = getSshortBuf(band); + + for (ossim_uint32 i=0; i<size_in_pixels; i++) p[i] = (ossim_sint16)value; + + // Set the status to unknown since we don't know about the other bands. + setDataObjectStatus(OSSIM_STATUS_UNKNOWN); +} + + +bool ossimS16ImageData::isNull(ossim_uint32 offset)const +{ + for(ossim_uint32 band = 0; band < getNumberOfBands(); ++band) + { + const ossim_sint16* buf = getSshortBuf(band)+offset; + + if((*buf) != theNullPixelValue[band]) + { + return false; + } + } + + return true; +} + +void ossimS16ImageData::setNull(ossim_uint32 offset) +{ + for(ossim_uint32 band = 0; band < getNumberOfBands(); ++band) + { + ossim_sint16* buf = getSshortBuf(band)+offset; + *buf = static_cast<ossim_sint16>(theNullPixelValue[band]); + } +} + +void ossimS16ImageData::loadBand(const void* src, + const ossimIrect& src_rect, + ossim_uint32 band) +{ + ossimImageData::loadBand(ossim_sint16(0), src, src_rect, band); +} + +void ossimS16ImageData::loadTile(void* src, + const ossimIrect& src_rect, + ossimInterleaveType il_type) +{ + // Load the tile from the buffer. + switch (il_type) + { + case OSSIM_BIP: + ossimImageData::loadTileFromBip(ossim_sint16(0), src, src_rect); + break; + case OSSIM_BIL: + ossimImageData::loadTileFromBil(ossim_sint16(0), src, src_rect); + break; + case OSSIM_BSQ: + ossimImageData::loadTileFromBsq(ossim_sint16(0), src, src_rect); + break; + default: + ossimNotify(ossimNotifyLevel_WARN) + << "ossimS16ImageData::loadTile" + << "\nUnknown interleave type passed to method. Returning..." + << endl; + break; + } +} + +void ossimS16ImageData::unloadBand(void* dest, + const ossimIrect& dest_rect, + ossim_uint32 band) const +{ + ossimImageData::unloadBand(ossim_sint16(0), dest, dest_rect, + getImageRectangle(), band); +} + +void ossimS16ImageData::copyTileToNormalizedBuffer(double* buf) const +{ + if (!buf) + { + ossimNotify(ossimNotifyLevel_WARN) << "ossimS16ImageData::copyTileToNormalizedBuffer ERROR:" + << "\nBuffer passed to method is NULL!" + << endl; + return; + } + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + for(ossim_uint32 band = 0; band < getNumberOfBands(); band++) + { + const ossim_sint16* s = getSshortBuf(band); // source + ossim_float64* d = buf + (band*size); // destination + + for(ossim_uint32 index = 0; index < size; index++) + { + getNormFromPix(s[index], d[index], band); + } + } + } +} + +void ossimS16ImageData::copyTileToNormalizedBuffer(ossim_uint32 band, + double* buf) const +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU11ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + if(!getBuf(band)) return; + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + const ossim_sint16* s = getSshortBuf(band); // source + double* d = buf; // destination + + for(ossim_uint32 index = 0; index < size; index++) + { + getNormFromPix(*s, *d, band); + } + } +} + +void ossimS16ImageData::copyNormalizedBufferToTile(double* buf) +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimS16ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + for(ossim_uint32 band = 0; band < getNumberOfBands(); band++) + { + ossim_float64* s = buf + (band*size); // source + ossim_sint16* d = getSshortBuf(band); // destination + + for(ossim_uint32 index = 0; index < size; index++) + { + ossim_int32 p; + getPixFromNorm(p, s[index], band); + d[index] = static_cast<ossim_sint16>(p); + } + } + } +} + +void ossimS16ImageData::copyNormalizedBufferToTile(ossim_uint32 band, + double* buf) +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU11ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + + ossim_uint32 size = getSizePerBand(); + + if((size > 0)&&getBuf(band)) + { + double* s = buf; // source + ossim_sint16* d = getSshortBuf(band); // destination + + for(ossim_uint32 index = 0; index < size; index++) + { + ossim_int32 p; + getPixFromNorm(p, *s, band); + *d = static_cast<ossim_sint16>(p); + ++d; + ++s; + } + } +} + +void ossimS16ImageData::copyTileToNormalizedBuffer(float* buf) const +{ + if (!buf) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimS16ImageData::copyTileToNormalizedBuffer ERROR:" + << "\nBuffer passed to method is NULL!" << endl; + return; + } + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + for(ossim_uint32 band = 0; band < getNumberOfBands(); band++) + { + const ossim_sint16* s = getSshortBuf(band); // source + float* d = buf + (band*size); // destination + + for(ossim_uint32 index = 0; index < size; index++) + { + getNormFromPix(s[index], d[index], band); + } + } + } +} + +void ossimS16ImageData::copyTileToNormalizedBuffer(ossim_uint32 band, + float* buf) const +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU11ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + if(!getBuf(band)) return; + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + const ossim_sint16* s = getSshortBuf(band); // source + float* d = buf; // destination + + for(ossim_uint32 index = 0; index < size; index++) + { + getNormFromPix(*s, *d, band); + } + } +} + +void ossimS16ImageData::copyNormalizedBufferToTile(float* buf) +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimS16ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + for(ossim_uint32 band = 0; band < getNumberOfBands(); band++) + { + float* s = buf + (band*size); // source + ossim_sint16* d = getSshortBuf(band); // destination + + for(ossim_uint32 index = 0; index < size; index++) + { + ossim_int32 p; + getPixFromNorm(p, s[index], band); + d[index] = static_cast<ossim_sint16>(p); + } + } + } +} + +void ossimS16ImageData::copyNormalizedBufferToTile(ossim_uint32 band, + float* buf) +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU11ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + + ossim_uint32 size = getSizePerBand(); + + if((size > 0)&&getBuf(band)) + { + float* s = buf; // source + ossim_sint16* d = getSshortBuf(band); // destination + + for(ossim_uint32 index = 0; index < size; index++) + { + ossim_int32 p; + getPixFromNorm(p, *s, band); + *d = static_cast<ossim_sint16>(p); + ++d; + ++s; + } + } +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimS16ImageData.h b/Utilities/OSSIM/ossim_core/imaging/ossimS16ImageData.h new file mode 100644 index 0000000000..3dc5b3ad13 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimS16ImageData.h @@ -0,0 +1,195 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Class declaration of ossimS16ImageData. Specialized image data object for +// signed short data. +// +//************************************************************************* +// $Id: ossimS16ImageData.h,v 1.15 2004/09/02 13:59:03 dburken Exp $ + +#ifndef ossimS16ImageData_HEADER +#define ossimS16ImageData_HEADER + +#include "ossimImageData.h" + +class OSSIMDLLEXPORT ossimS16ImageData : public ossimImageData +{ +public: + ossimS16ImageData(ossimSource* source, + ossim_uint32 bands = 1); + + ossimS16ImageData(ossimSource* source, + ossim_uint32 bands, + ossim_uint32 width, + ossim_uint32 height); + + ossimS16ImageData(const ossimS16ImageData &rhs); + + virtual ~ossimS16ImageData(); + + /*! + * Perform object duplication. + */ + virtual ossimObject* dup()const; + + /*! + * will fill the entire band with + * the value. + */ + void fill(ossim_uint32 band, double value); + + + bool isNull(ossim_uint32 offset)const; + void setNull(ossim_uint32 offset); + + virtual ossimDataObjectStatus validate() const; + + /*! + * will go to the band and offset and compute the + * normalized float and return it back to the + * caller through the result argument. + */ + virtual void getNormalizedFloat(ossim_uint32 offset, + ossim_uint32 bandNumber, + float& result)const; + + /*! + * This will assign to this object a normalized + * value by unnormalizing to its native type. + */ + virtual void setNormalizedFloat(ossim_uint32 offset, + ossim_uint32 bandNumber, + float input); + + /*! + * Will use the memory that you pass in to normalize + * this data object. + */ + virtual void convertToNormalizedFloat(ossimImageData* result)const; + + /*! + * Will use the memory that you pass in to normalize + * this data object. + */ + virtual void convertToNormalizedDouble(ossimImageData* result)const; + + /*! + * Will take the normalized input and convert it + * to this tile's data type. Example: if this + * tile is of type UCHAR and its input is of type + * NORALIZED_FLOAT it will unnormalize the data by + * doing: + * + * minPix + normalizedInput*(maxPix-minPix) + * + * on a per band basis. + */ + virtual void unnormalizeInput(ossimImageData* normalizedInput); + + /*! + * This will compute the average value for the band. + */ + virtual double computeAverageBandValue(ossim_uint32 bandNumber = 0); + + /*! + * This will call the compute average band value and then + * use that in the calculation of: + + * It will then do a SUM[(Mean - Actual)^2]/width*height. + * + * This is the average variance from the passed in + * mean. Basically think of the mean as a completely + * grey image and we would like to see how this + * image varies from the passed in mean. + */ + virtual double computeMeanSquaredError(double meanValue, + ossim_uint32 bandNumber = 0); + + virtual void populateHistogram(ossimMultiBandHistogram* histo); + + /*! + * Initializes data to null pixel values. + */ + virtual void makeBlank(); + + virtual void setValue(ossim_int32 x, ossim_int32 y, double color); + + virtual void loadBand(const void* src, + const ossimIrect& src_rect, + ossim_uint32 band); + + virtual void loadTile(void* src, + const ossimIrect& src_rect, + ossimInterleaveType il_type); + + virtual void unloadBand(void* dest, + const ossimIrect& dest_rect, + ossim_uint32 band) const; + + /*! + * Copies entire tile to buf passed in. Data put in buf is normalized. + * The "buf" passed to method is assumed to be at least as big as: + * "getSize() * sizeof(double)" + */ + virtual void copyTileToNormalizedBuffer(double* buf) const; + + /*! + * Copies buf passed in to tile. Data is unnormalized to the tile's + * scalar type. + * The "buf" passed to method is assumed to be at least as big as the tiles: + * "getSize() * sizeof(double)" + */ + virtual void copyNormalizedBufferToTile(double* buf); + + /*! + * Will copy this tiles specified band number to the normalized buffer. + * if the band is out of range then nothing is done and returns. + */ + virtual void copyTileToNormalizedBuffer(ossim_uint32 band, double* buf) const; + virtual void copyTileToNormalizedBuffer(ossim_uint32 band, float* buf)const; + + /*! + * Copies entire tile to buf passed in. Data put in buf is normalized. + * The "buf" passed to method is assumed to be at least as big as: + * "getSize() * sizeof(double)" + */ + virtual void copyTileToNormalizedBuffer(float* buf) const; + + /*! + * Copies buf passed in to tile. Data is unnormalized to the tile's + * scalar type. + * The "buf" passed to method is assumed to be at least as big as the tiles: + * "getSize() * sizeof(double)" + */ + virtual void copyNormalizedBufferToTile(float* buf); + + /*! + * Will copy the normalized buffer to this tiles + * specified band. If band is out of range then nothing + * is done and returns. + */ + virtual void copyNormalizedBufferToTile(ossim_uint32 band, + double* buf); + virtual void copyNormalizedBufferToTile(ossim_uint32 band, + float* buf); +protected: + ossimS16ImageData(); + +private: + + // Disallow from use... + const ossimS16ImageData& operator =(const ossimS16ImageData &rhs) + {return *this;} + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimTiling.cpp b/Utilities/OSSIM/ossim_core/imaging/ossimTiling.cpp new file mode 100644 index 0000000000..3303d712cf --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimTiling.cpp @@ -0,0 +1,854 @@ +//******************************************************************* +// Copyright (C) 2004 Garrett Potts +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: implementation for image generator +// +//************************************************************************* +// $Id: ossimTiling.cpp,v 1.10 2005/08/18 19:43:28 gpotts Exp $ + +#include <sstream> +#include <iomanip> +#include <imaging/ossimTiling.h> +#include <base/misc/lookup_tables/ossimUnitTypeLut.h> +#include <base/misc/ossimUnitConversionTool.h> +#include <base/context/ossimNotifyContext.h> +#include <base/common/ossimTrace.h> + +static ossimTrace traceDebug("ossimTiling:debug"); + +RTTI_DEF1(ossimTiling, "ossimTiling", ossimObject); + +ossimTiling::ossimTiling() + :theTilingDistance(0,0), + theTilingDistanceUnitType(OSSIM_UNIT_UNKNOWN), + theDelta(0,0), + theDeltaType(ossimTilingDeltaType_TOTAL_PIXELS), + thePaddingSizeInPixels(0.0, 0.0), + theMapProjection(), + theImageRect(), + theTilingRect(), + theTileId(-1), + theTotalHorizontalTiles(0), + theTotalVerticalTiles(0), + theTotalTiles(0), + theTileNameMask() +{ +} + +bool ossimTiling::initialize(const ossimMapProjection& proj, + const ossimIrect& boundingRect) +{ + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimTiling::initialize DEBUG: Entered..." + << "\nBounding rect === " << boundingRect + << std::endl; + } + + bool result = true; + theMapProjection = (ossimMapProjection*)proj.dup(); + theImageRect = boundingRect; + + result = validate(); + + ossimDpt convertedTilingDistance = theTilingDistance; + + if(result) + { + // Let's setup the bounding tile rect. + if(theTilingDistanceUnitType != OSSIM_PIXEL) + { + getConvertedTilingDistance(convertedTilingDistance); + + if(theMapProjection->isGeographic()) + { + ossimGpt ul; + ossimGpt ur; + ossimGpt lr; + ossimGpt ll; + + theMapProjection->lineSampleToWorld(theImageRect.ul(), + ul); + theMapProjection->lineSampleToWorld(theImageRect.ur(), + ur); + theMapProjection->lineSampleToWorld(theImageRect.lr(), + lr); + theMapProjection->lineSampleToWorld(theImageRect.ll(), + ll); + + theTilingRect = ossimDrect(ossimDpt(ul), + ossimDpt(ur), + ossimDpt(lr), + ossimDpt(ll), + OSSIM_RIGHT_HANDED); + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG: Geographic input bounds = " + << theTilingRect + << std::endl; + } + + theTilingRect.stretchToTileBoundary(convertedTilingDistance); + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG: Geographic input bounds stretched = " + << theTilingRect << std::endl; + } + + clampGeographic(theTilingRect); + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG: Geographic input bounds clamped = " + << theTilingRect << std::endl; + } + + } // End "if(theMapProjection->isGeographic())" + + else // meters + { + ossimDpt ul; + ossimDpt ur; + ossimDpt lr; + ossimDpt ll; + + theMapProjection->lineSampleToEastingNorthing(theImageRect.ul(), + ul); + theMapProjection->lineSampleToEastingNorthing(theImageRect.ur(), + ur); + theMapProjection->lineSampleToEastingNorthing(theImageRect.lr(), + lr); + theMapProjection->lineSampleToEastingNorthing(theImageRect.ll(), + ll); + theTilingRect = ossimDrect(ul, + ur, + lr, + ll, + OSSIM_RIGHT_HANDED); + + theTilingRect.stretchToTileBoundary(convertedTilingDistance); + } + } + else + { + ossim_int32 remainderX = (ossim_int32)((theImageRect.width()%((ossim_int32)theDelta.x)) != 0); + ossim_int32 remainderY = (ossim_int32)((theImageRect.height()%((ossim_int32)theDelta.y)) != 0); + + ossim_int32 w = (ossim_int32)((theImageRect.width()/(ossim_int32)theDelta.x)*theDelta.x + + (remainderX*theDelta.x)); + ossim_int32 h = (ossim_int32)((theImageRect.height()/(ossim_int32)theDelta.y)*theDelta.y + + (remainderY*theDelta.y)); + theTilingRect = ossimDrect(theImageRect.ul().x, + theImageRect.ul().y, + theImageRect.ul().x + (w-1), + theImageRect.ul().y + (h-1)); + + // since we are pixel space we force delta to be 1 pixel unit + // + theDelta.x = 1.0; + theDelta.y = 1.0; + theDeltaType = ossimTilingDeltaType_PER_PIXEL; + } + } + + theTotalHorizontalTiles = irint(fabs(theTilingRect.ur().x - theTilingRect.ul().x)/convertedTilingDistance.x); + theTotalVerticalTiles = irint(fabs(theTilingRect.ur().y - theTilingRect.lr().y)/convertedTilingDistance.y); + theTotalTiles = theTotalHorizontalTiles*theTotalVerticalTiles; + + // reset the tile id to the beginning + // + reset(); + + if(traceDebug()) + { + print(ossimNotify(ossimNotifyLevel_DEBUG)); + + ossimNotify(ossimNotifyLevel_DEBUG) + << "\nossimTiling::initialize DEBUG: Leaving..." << std::endl; + } + return result; +} + +bool ossimTiling::next(ossimRefPtr<ossimMapProjection>& resultProjection, + ossimIrect& resultingBounds, + ossimString& resultingName)const +{ + bool result = true; + + if(theTileId < theTotalTiles) + { + ossimDpt origin; + ossim_int64 row; + ossim_int64 col; + + getRowCol(row, col, theTileId); + + getTileName(resultingName, + row, col, theTileId); + + getOrigin(origin, row, col); + + if(theTilingDistanceUnitType == OSSIM_PIXEL) + { + ossimIpt ul = origin; + + resultingBounds = + ossimIrect(ul.x - (ossim_int32)thePaddingSizeInPixels.x, + ul.y - (ossim_int32)thePaddingSizeInPixels.y, + ul.x + ((ossim_int32)theTilingDistance.x-1) + + (ossim_int32)thePaddingSizeInPixels.x, + ul.y + ((ossim_int32)theTilingDistance.y-1) + + (ossim_int32)thePaddingSizeInPixels.y); + } + else + { + + ossimDpt deltaPerPixel = getDeltaPerPixel(); + ossimIpt pixels; + + if(theDeltaType == ossimTilingDeltaType_TOTAL_PIXELS) + { + pixels = theDelta; + } + else + { + pixels = ossimDpt(theTilingDistance.x/theDelta.x, + theTilingDistance.y/theDelta.y); + } + + if(theMapProjection->isGeographic()) + { + theMapProjection->setUlGpt(ossimGpt(origin.lat, + origin.lon, + 0.0, + theMapProjection->origin().datum())); + theMapProjection->setDecimalDegreesPerPixel(deltaPerPixel); + } + else + { + theMapProjection->setUlEastingNorthing(ossimDpt(origin.x, + origin.y)); + theMapProjection->setMetersPerPixel(deltaPerPixel); + } + resultingBounds = ossimIrect(-(ossim_int32)thePaddingSizeInPixels.x, + -(ossim_int32)thePaddingSizeInPixels.y, + (pixels.x-1) + (ossim_int32)thePaddingSizeInPixels.x, + (pixels.y-1) + (ossim_int32)thePaddingSizeInPixels.y); + } + resultProjection = theMapProjection; + + ++theTileId; + if(traceDebug()&&resultProjection.valid()) + { + ossimKeywordlist projKwl; + + resultProjection->saveState(projKwl); + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimTiling::next DEBUG: rect = " << resultingBounds + << "\nproj = " << projKwl + << "\ntileName = " << resultingName + << "\norigin = " << origin << std::endl; + } + } + else + { + result = false; + } + + + return result; +} + + +void ossimTiling::reset() +{ + theTileId = 0; +} + +void ossimTiling::setTilingDistance(const ossimDpt& tilingDistance, + ossimUnitType unitType) +{ + theTilingDistance = tilingDistance; + theTilingDistanceUnitType = unitType; +} + +void ossimTiling::setDelta(const ossimDpt& delta, + ossimTilingDeltaType deltaType) +{ + theDelta = delta; + theDeltaType = deltaType; +} + +bool ossimTiling::validate()const +{ + bool result = true; + + if(theMapProjection.valid()) + { + if(theMapProjection->isGeographic()) + { + switch(theTilingDistanceUnitType) + { + case OSSIM_DEGREES: + case OSSIM_RADIANS: + case OSSIM_SECONDS: + case OSSIM_MINUTES: + case OSSIM_PIXEL: + { + break; + } + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimTiling::validate()\n" + << "Map projeciton requires tiling in angular units but the" + << "\nspacing is in non angular" << std::endl; + result = false; + } + } + } + else + { + switch(theTilingDistanceUnitType) + { + case OSSIM_METERS: + case OSSIM_FEET: + case OSSIM_US_SURVEY_FEET: + case OSSIM_NAUTICAL_MILES: + case OSSIM_PIXEL: + case OSSIM_MILES: + case OSSIM_MILLIMETERS: + { + break; + } + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimTiling::validate()" + << "\nMap projeciton requires tiling using linear spacing" + << " but the spacing is in non linear" << std::endl; + result = false; + } + } + } + } + else + { + result = false; + ossimNotify(ossimNotifyLevel_WARN) + << "ossimTiling::validate()" + << "\nthe image projection is null and so not valid" + << std::endl; + } + if((theDelta.x <= FLT_EPSILON) || + (theDelta.y <= FLT_EPSILON)) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimTiling::validate() the delta is too small or is negative" + << "value = " << theDelta << std::endl; + result = false; + } + if((theTilingDistance.x <= FLT_EPSILON)|| + (theTilingDistance.y <= FLT_EPSILON)) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimTiling::validate()" + << "\nthe tiling distance is too small or is negative" + << "Value = " << theTilingDistance << std::endl; + } + + if(theImageRect.hasNans()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimTiling::validate() the image rect has nans" + << std::endl; + result = false; + } + + return result; +} + +bool ossimTiling::isAngularUnit(ossimUnitType unitType)const +{ + bool result = false; + + switch(unitType) + { + case OSSIM_DEGREES: + case OSSIM_RADIANS: + case OSSIM_SECONDS: + case OSSIM_MINUTES: + { + result = true; + break; + } + default: + { + break; + } + } + return result; +} + +bool ossimTiling::isLinearUnit(ossimUnitType unitType)const +{ + bool result = false; + + switch(unitType) + { + case OSSIM_METERS: + case OSSIM_FEET: + case OSSIM_US_SURVEY_FEET: + case OSSIM_NAUTICAL_MILES: + case OSSIM_MILES: + case OSSIM_MILLIMETERS: + { + result = true; + break; + } + default: + { + break; + } + } + return result; + +} + +void ossimTiling::setTileNameMask(const ossimString& mask) +{ + if(theTileNameMask == "") + { + theTileNameMask = "tile%i%"; + } + if(mask.contains("%i%")|| + mask.contains("%oc%")|| + mask.contains("%or%")|| + mask.contains("%r%")|| + mask.contains("%c%")|| + mask.contains("%SRTM%")) + { + theTileNameMask = mask; + } + else + { + theTileNameMask += "%i%"; + } +} + +ossimString ossimTiling::getTileNameMask()const +{ + return theTileNameMask; +} + +bool ossimTiling::getRowCol(ossim_int64& row, + ossim_int64& col, + ossim_int64 tileId)const +{ + bool result = true; + + if((theTotalHorizontalTiles > 0)&& + (tileId < theTotalTiles)) + { + row = tileId/static_cast<ossim_int64>(theTotalHorizontalTiles); + col = tileId%static_cast<ossim_int64>(theTotalHorizontalTiles); + if((col >= static_cast<ossim_int32>(theTotalHorizontalTiles)) && + (row >= static_cast<ossim_int32>(theTotalVerticalTiles))) + { + result = false; + } + } + return result; +} + +bool ossimTiling::getOrigin(ossimDpt& origin, + ossim_int64 tileId)const +{ + ossim_int64 row; + ossim_int64 col; + + bool result = getRowCol(row, col, tileId); + if(result) + { + result = getOrigin(origin, row, col); + } + + return result; +} + +bool ossimTiling::getOrigin(ossimDpt& origin, + ossim_int64 row, + ossim_int64 col)const +{ + bool result = false; + + if((col < static_cast<ossim_int64>(theTotalHorizontalTiles)) && + (row < static_cast<ossim_int64>(theTotalVerticalTiles))) + { + ossimDpt convertedTilingDistance; + getConvertedTilingDistance(convertedTilingDistance); + + result = true; + if(theTilingRect.orientMode() == OSSIM_RIGHT_HANDED) + { + origin.x = theTilingRect.ul().x + col*convertedTilingDistance.x; + origin.y = theTilingRect.ul().y - row*convertedTilingDistance.y; + } + else + { + origin.x = theTilingRect.ul().x + col*convertedTilingDistance.x; + origin.y = theTilingRect.ul().y + row*convertedTilingDistance.y; + } + } + + return result; +} + +ossimDpt ossimTiling::getDeltaPerPixel()const +{ + + ossimDpt result = theDelta; + + if (!theMapProjection) + { + return result; + } + + if(theDeltaType == ossimTilingDeltaType_TOTAL_PIXELS) + { + result = ossimDpt(theTilingDistance.x/theDelta.x, + theTilingDistance.y/theDelta.y); + } + + ossimUnitConversionTool unitConverter(theMapProjection->origin(), + 1.0, + theTilingDistanceUnitType); + if(theMapProjection->isGeographic()) + { + unitConverter.setValue(result.x, theTilingDistanceUnitType); + result.x = unitConverter.getValue(OSSIM_DEGREES); + + unitConverter.setValue(result.y, + theTilingDistanceUnitType); + result.y = unitConverter.getValue(OSSIM_DEGREES); + } + else + { + unitConverter.setValue(result.x, + theTilingDistanceUnitType); + result.x = unitConverter.getValue(OSSIM_METERS); + + unitConverter.setValue(result.y, + theTilingDistanceUnitType); + result.y = unitConverter.getValue(OSSIM_METERS); + } + + return result; +} + +void ossimTiling::getTileName(ossimString& resultingName, + ossim_int64 row, + ossim_int64 col, + ossim_int64 id)const +{ + if(theTileNameMask == "") + { + ostringstream idString; + idString << id; + resultingName = ossimString("tile") + idString.str().c_str(); + } + else if(theTileNameMask.contains("%SRTM%")) + { + // must be a 1x1 degree tiling distance + // + if((theTilingDistanceUnitType == OSSIM_DEGREES)&& + (theTilingDistance.x == 1.0)&& + (theTilingDistance.x == 1.0)) + { + ostringstream latString; + ostringstream lonString; + + resultingName = ""; + ossimDpt origin; + getOrigin(origin, row, col); + // the name is lower left and not upper left + // subtract one degree + // + origin.lat -=1; + latString << setfill('0') << setw(2) << fabs(origin.lat); + lonString << setfill('0') << setw(3) << fabs(origin.lon); + + if(origin.lat < 0.0) + { + resultingName += "S"; + } + else + { + resultingName += "N"; + } + resultingName += latString.str().c_str(); + if(origin.lon < 0.0) + { + resultingName += "W"; + } + else + { + resultingName += "E"; + } + resultingName += lonString.str().c_str(); + resultingName += ".hgt"; + } + } + else + { + ostringstream rowString; + ostringstream colString; + ostringstream idString; + ostringstream oRowString; + ostringstream oColString; + ossimDpt origin; + getOrigin(origin, row, col); + + rowString << row; + colString << col; + idString << id; + oRowString << row; + oColString << col; + + resultingName = theTileNameMask; + resultingName = resultingName.substitute("%r%", + rowString.str().c_str()); + resultingName = resultingName.substitute("%c%", + colString.str().c_str()); + resultingName = resultingName.substitute("%i%", + idString.str().c_str()); + resultingName = resultingName.substitute("%oc", + oColString.str().c_str()); + resultingName = resultingName.substitute("%or", + oRowString.str().c_str()); + } +} + +void ossimTiling::clampGeographic(ossimDrect& rect)const +{ + ossimDpt ul = rect.ul(); + ossimDpt lr = rect.lr(); + + if(ul.lat > 90) ul.lat = 90.0; + if(lr.lat < -90.0) lr.lat = -90.0; + + if(ul.lon < -180) ul.lon = -180; + if(lr.lon > 180) lr.lon = 180; + + rect = ossimDrect(ul, lr, rect.orientMode()); +} + +bool ossimTiling::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + std::stringstream tilingDistance; + ossimUnitTypeLut unitLut; + + tilingDistance << theTilingDistance.x << " " << theTilingDistance.y << std::endl; + + kwl.add(prefix, + "tiling_distance", + tilingDistance.str().c_str(), + true); + + + kwl.add(prefix, + "tiling_distance_type", + unitLut.getTableIndexString(theTilingDistanceUnitType), + true); + std::ostringstream delta; + delta << theDelta.x << " " << theDelta.y; + kwl.add(prefix, + "delta", + delta.str().c_str(), + true); + + if(theDeltaType == ossimTilingDeltaType_TOTAL_PIXELS) + { + kwl.add(prefix, + "delta_type", + "total_pixels", + true); + } + else + { + kwl.add(prefix, + "delta_type", + "delta_per_pixels", + true); + } + std::ostringstream padding; + + padding << thePaddingSizeInPixels.x << " " << thePaddingSizeInPixels.y; + kwl.add(prefix, + "padding_size_in_pixels", + padding.str().c_str(), + true); + + kwl.add(prefix, + "tile_name_mask", + theTileNameMask.c_str(), + true); + + return true; +} + +bool ossimTiling::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimUnitTypeLut unitLut; + const char* tilingDistance = kwl.find(prefix, + "tiling_distance"); + const char* tilingDistanceType = kwl.find(prefix, + "tiling_distance_type"); + const char* delta = kwl.find(prefix, + "delta"); + + const char* deltaType = kwl.find(prefix, + "delta_type"); + const char* paddingSizeInPixels = kwl.find(prefix, + "padding_size_in_pixels"); + theTileNameMask = kwl.find(prefix, + "tile_name_mask"); + + setTileNameMask(theTileNameMask); + + bool result = tilingDistance&&tilingDistanceType&&delta&&deltaType&&paddingSizeInPixels; + + std::istringstream distance(ossimString(tilingDistance).c_str()); + distance >> theTilingDistance.x >> theTilingDistance.y; + + if(theTilingDistance.x <= 0.0) + { + theTilingDistance.x = 1.0; + } + if(theTilingDistance.y<=0.0) + { + theTilingDistance.y = theTilingDistance.x; + } + + unitLut.getTableIndexString(theTilingDistanceUnitType), + theTilingDistanceUnitType = (ossimUnitType) unitLut.getEntryNumber(ossimString(tilingDistanceType).c_str()); + + + theDelta = ossimDpt(0,0); + + std::istringstream deltaValues(ossimString(delta).c_str()); + deltaValues >> theDelta.x >> theDelta.y; + + if(theDelta.x <= 0.0) + { + theDelta.x = 1.0; + } + + if(theDelta.y <= 0.0) + { + theDelta.y = theDelta.x; + } + + if(ossimString(deltaType).downcase().contains("total")) + { + theDeltaType = ossimTilingDeltaType_TOTAL_PIXELS; + } + else + { + theDeltaType = ossimTilingDeltaType_PER_PIXEL; + } + + std::istringstream padding(ossimString(paddingSizeInPixels).c_str()); + padding >> thePaddingSizeInPixels.x >> thePaddingSizeInPixels.y; + + if (traceDebug()) + { + print(ossimNotify(ossimNotifyLevel_DEBUG)); + } + + return result; +} + +std::ostream& ossimTiling::print(std::ostream& out) const +{ + out << "theTilingDistance: " << theTilingDistance + << "\ntheTilingDistanceUnitType: " << theTilingDistanceUnitType + << "\ntheDelta: " << theDelta + << "\ntheDeltaType: " << theDeltaType + << "\nthePaddingSizeInPixels: " << thePaddingSizeInPixels + << "\ntheImageRect: " << theImageRect + << "\ntheTilingRect: " << theTilingRect + << "\ntheTileId: " << theTileId + << "\ntheTotalHorizontalTiles: " << theTotalHorizontalTiles + << "\ntheTotalVerticalTiles: " << theTotalVerticalTiles + << "\ntheTotalTiles: " << theTotalTiles + << "\ntheTileNameMask: " << theTileNameMask; + + if (theMapProjection.valid()) + { + out << "\ntheMapProjection:\n" << theMapProjection->print(out); + } + else + { + out << "theMapProjection is not set."; + } + out << endl; + + return out; +} + +void ossimTiling::getConvertedTilingDistance(ossimDpt& pt) const +{ + if(theTilingDistanceUnitType == OSSIM_PIXEL) + { + pt = theTilingDistance; + return; + } + if (!theMapProjection) + { + // This should not happen... + ossimNotify(ossimNotifyLevel_WARN) + << "ossimTiling::getConvertedTilingDistance WARNING" + << " projection not set!" << endl; + pt = theTilingDistance; + return; + } + ossimUnitConversionTool unitConverter(theMapProjection->origin(), + 1.0, + theTilingDistanceUnitType); + + if(theMapProjection->isGeographic()) + { + unitConverter.setValue(theTilingDistance.x, + theTilingDistanceUnitType); + pt.x = unitConverter.getValue(OSSIM_DEGREES); + + unitConverter.setValue(theTilingDistance.y, + theTilingDistanceUnitType); + pt.y = unitConverter.getValue(OSSIM_DEGREES); + } + else + { + unitConverter.setValue(theTilingDistance.x, + theTilingDistanceUnitType); + pt.x = unitConverter.getValue(OSSIM_METERS); + + unitConverter.setValue(theTilingDistance.y, + theTilingDistanceUnitType); + pt.y = unitConverter.getValue(OSSIM_METERS); + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimTiling.h b/Utilities/OSSIM/ossim_core/imaging/ossimTiling.h new file mode 100644 index 0000000000..d220bff3ff --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimTiling.h @@ -0,0 +1,161 @@ +//******************************************************************* +// Copyright (C) 2004 Garrett Potts +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: implementation for image generator +// +//************************************************************************* +// $Id: ossimTiling.h,v 1.5 2005/08/02 19:43:27 dburken Exp $ +#ifndef ossimTiling_HEADER +#define ossimTiling_HEADER +#include <base/common/ossimObject.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimDrect.h> +#include <base/data_types/ossimIrect.h> +#include <base/data_types/ossimKeywordlist.h> +#include <projections/map_projections/ossimMapProjection.h> +#include <base/common/ossimRefPtr.h> + +class OSSIM_DLL ossimTiling : public ossimObject +{ +public: + typedef enum ossimTilingDeltaType + { + ossimTilingDeltaType_TOTAL_PIXELS, + ossimTilingDeltaType_PER_PIXEL + }; + ossimTiling(); + + + + bool initialize(const ossimMapProjection& proj, + const ossimIrect& boundingRect); + + bool next(ossimRefPtr<ossimMapProjection>& resultProjection, + ossimIrect& resultingBounds, + ossimString& resultingName)const; + + void reset(); + + /** + * + * @param tilingDistance Distance in the specified units. + * @param unitType Currently only angular unit degrees, + * and linear unit meters are supported. + * If unitType is pixel unit then the + * delta per unit will be set to 1. + * + */ + void setTilingDistance(const ossimDpt& tilingDistance, + ossimUnitType unitType); + + /** + * This sets the pixel delta. The delta can either be TOTAL_PIXELS or + * UNIT_PER_PIXEL. + * + * If the delta type is TOTAL_PIXELS then the unit per pixel is calculated + * from the theTilingDistance. This is very useful when wanting to be on + * even geographic boundaries and would like to have a fixed width and + * height for + * the pixels. Flight simulators use this tiling scheme for power of 2 + * outputs. + * + * if the delta type is unit per pixel then the total pixels is computed + * form the + * theTilingDistance. This is useful when you might want whole number + * GSD's and whole numbered tile boundaries. + */ + void setDelta(const ossimDpt& delta, + ossimTilingDeltaType deltaType); + + /** + * This sets the tilename mask. The key tokens that are supported are. + * + * %r% Replaces with the row number of the current tile + * %c% Replaces with the column number of the current tile + * %i% Replaces with the current tile id. + * %or% Replaces with the origin of the row + * %oc% Replaces with the origin of the col + * %SRTM% Replaces all filenames with the SRTM file name convention + * + * + * Examples: + * tile%r%_%c% assume r = 0 and c = 100 then + * this is replaced with tile0_100 + * + */ + void setTileNameMask(const ossimString& mask); + ossimString getTileNameMask()const; + + bool getRowCol(ossim_int64& row, + ossim_int64& col, + ossim_int64 tileId)const; + bool getOrigin(ossimDpt& origin, + ossim_int64 tileId)const; + bool getOrigin(ossimDpt& origin, + ossim_int64 row, + ossim_int64 col)const; + + void setPaddingSizeInPixels(const ossimIpt& pizelOverlap); + ossimDpt getDeltaPerPixel()const; + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual std::ostream& print(std::ostream& out) const; + +protected: + + /** + * @return The tiling distance converted to either degrees or meters. + */ + void getConvertedTilingDistance(ossimDpt& pt) const; + + /** The size of a tile in theTilingDistanceUnitType. */ + ossimDpt theTilingDistance; + + /** The unit type for "theDelta", and "theTilingDistance". */ + ossimUnitType theTilingDistanceUnitType; + + /** + * If (theDeltaType == ossimTilingDeltaType_TOTAL_PIXELS) then + * this is the size of the tile in pixels like 1024 x 1024. + * + * If (theDeltaType == ossimTilingDeltaType_PER_PIXEL) then + * this is the size of a single pixel like 1.0 meter. + */ + ossimDpt theDelta; + + /** @see theDelta */ + ossimTilingDeltaType theDeltaType; + + ossimDpt thePaddingSizeInPixels; + mutable ossimRefPtr<ossimMapProjection> theMapProjection; + ossimIrect theImageRect; + ossimDrect theTilingRect; + mutable ossim_int64 theTileId; + ossim_int64 theTotalHorizontalTiles; + ossim_int64 theTotalVerticalTiles; + ossim_int64 theTotalTiles; + ossimString theTileNameMask; + + bool validate()const; + bool isAngularUnit(ossimUnitType unitType)const; + bool isLinearUnit(ossimUnitType unitType)const; + void getTileName(ossimString& resultingName, + ossim_int64 row, + ossim_int64 col, + ossim_int64 id)const; + void clampGeographic(ossimDrect& rect)const; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimU11ImageData.cpp b/Utilities/OSSIM/ossim_core/imaging/ossimU11ImageData.cpp new file mode 100644 index 0000000000..ab16abb802 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimU11ImageData.cpp @@ -0,0 +1,724 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Class definition of ossimU11ImageData. Specialized image data object for +// unsigned short data with an 11 bit depth. +// +// NOTE: This object is optimized for unsigned short data and assumes the +// following: null pixel value = 0.0 +// min pixel value = 1.0 +// max pixel value = 2047.0 (2^11 - 1) +// +// If you want anything else use the less efficient ossimImageData. +// +//************************************************************************* +// $Id: ossimU11ImageData.cpp,v 1.18 2006/01/10 13:10:29 gpotts Exp $ + +#include <cstring> // for memset function +using namespace std; + +#include <imaging/ossimU11ImageData.h> +#include <base/common/ossimSource.h> +#include <base/context/ossimErrorContext.h> +#include <base/data_types/ossimIrect.h> +#include <base/data_types/ossimMultiBandHistogram.h> +#include <base/data_types/ossimHistogram.h> + +RTTI_DEF1(ossimU11ImageData, "ossimU11ImageData", ossimImageData) + +const ossimNormalizedU11RemapTable ossimU11ImageData::theRemapTable; + +ossimU11ImageData::ossimU11ImageData() + : + ossimImageData() +{ +} + +ossimU11ImageData::ossimU11ImageData(ossimSource* source, + ossim_uint32 bands) + : + ossimImageData(source, + OSSIM_USHORT11, + bands) +{ +} + +ossimU11ImageData::ossimU11ImageData(ossimSource* source, + ossim_uint32 bands, + ossim_uint32 width, + ossim_uint32 height) + : + ossimImageData(source, + OSSIM_USHORT11, + bands, + width, + height) +{ +} + +ossimU11ImageData::ossimU11ImageData(const ossimU11ImageData &rhs) + : + ossimImageData(rhs) +{} + +ossimU11ImageData::~ossimU11ImageData() +{ +} + +ossimObject* ossimU11ImageData::dup()const +{ + return new ossimU11ImageData(*this); +} + +ossimDataObjectStatus ossimU11ImageData::validate() const +{ + if (theDataBuffer == NULL) + { + setDataObjectStatus(OSSIM_NULL); + return OSSIM_NULL; + } + + ossim_uint32 count = 0; + const ossim_uint32 SIZE = getSize(); + const ossim_uint32 BOUNDS = getSizePerBand(); + const ossim_uint32 NUMBER_OF_BANDS = getNumberOfBands(); + + for(ossim_uint32 band = 0; band < NUMBER_OF_BANDS; ++band) + { + const ossim_uint16* p = getUshortBuf(band); + for (ossim_uint32 i=0; i<BOUNDS; i++) + { + // check if the band is null + if (p[i] != 0) count++; + } + } + + if (!count) + setDataObjectStatus(OSSIM_EMPTY); + else if (count == SIZE) + setDataObjectStatus(OSSIM_FULL); + else + setDataObjectStatus(OSSIM_PARTIAL); + + return getDataObjectStatus(); +} + +void ossimU11ImageData::getNormalizedFloat(ossim_uint32 offset, + ossim_uint32 bandNumber, + float& result)const +{ + if(!result) + { + return; + } + + // make sure that the types and width and height are good. + if( (getDataObjectStatus() == OSSIM_NULL) && isValidBand(bandNumber) ) + { + return; + } + + const ossim_uint16* sourceBuf = getUshortBuf(bandNumber); + result = static_cast<float>(theRemapTable.normFromPix(sourceBuf[offset])); +} + +void ossimU11ImageData::setNormalizedFloat(ossim_uint32 offset, + ossim_uint32 bandNumber, + float inputValue) +{ + // make sure that the types and width and height are + // good. + if((getDataObjectStatus() == OSSIM_NULL)&& + (bandNumber < getNumberOfBands())) + { + return; + } + + ossim_uint16* sourceBuf = getUshortBuf(bandNumber); + sourceBuf[offset] + = static_cast<ossim_uint16>(theRemapTable.pixFromNorm(inputValue)); +} + +void +ossimU11ImageData::convertToNormalizedFloat(ossimImageData* result)const +{ + if(!result) + { + return; + } + // make sure that the types and width and height are + // good. + if( (result->getScalarType() != OSSIM_NORMALIZED_FLOAT) || + (result->getNumberOfBands() != this->getNumberOfBands())|| + (result->getWidth() != this->getWidth()) || + (result->getHeight() != this->getHeight())|| + (result->getDataObjectStatus() == OSSIM_NULL) || + (getDataObjectStatus() == OSSIM_NULL)) + { + return; + } + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + for(ossim_uint32 bandCount = 0; bandCount < theNumberOfDataComponents; ++bandCount) + { + const ossim_uint16* sourceBuf = getUshortBuf(bandCount); + float* resultBuf = static_cast<float*>(result->getBuf(bandCount)); + for(ossim_uint32 counter = 0; counter < size; ++counter) + { + resultBuf[counter] + = static_cast<float>(theRemapTable. + normFromPix(sourceBuf[counter])); + } + } + } +} + +void ossimU11ImageData::convertToNormalizedDouble(ossimImageData* result)const +{ + if(!result) + { + return; + } + + // make sure that the types and width and height are + // good. + if( (result->getScalarType() != OSSIM_NORMALIZED_FLOAT) || + (result->getNumberOfBands() != this->getNumberOfBands())|| + (result->getWidth() != this->getWidth()) || + (result->getHeight() != this->getHeight())|| + (result->getDataObjectStatus() == OSSIM_NULL) || + (getDataObjectStatus() == OSSIM_NULL)) + { + return; + } + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + for(ossim_uint32 bandCount = 0; bandCount < theNumberOfDataComponents; ++bandCount) + { + const ossim_uint16* sourceBuf = getUshortBuf(bandCount); + double* resultBuf = static_cast<double*>(result->getBuf(bandCount)); + for(ossim_uint32 counter = 0; counter < size; ++counter) + { + resultBuf[counter] = theRemapTable.normFromPix(sourceBuf[counter]); + } + } + } + +} + +void ossimU11ImageData::unnormalizeInput(ossimImageData* normalizedInput) +{ + if((normalizedInput->getScalarType() != OSSIM_NORMALIZED_FLOAT) && + (normalizedInput->getScalarType() != OSSIM_NORMALIZED_DOUBLE) ) + { + //ERROR + return; + } + + ossim_uint32 counter = 0; + ossim_uint32 bandCount = 0; + ossim_uint32 size = getSizePerBand(); + ossimScalarType scalarType = normalizedInput->getScalarType(); + + if(size > 0) + { + if(scalarType == OSSIM_NORMALIZED_FLOAT) + { + for(bandCount = 0; bandCount < theNumberOfDataComponents; ++bandCount) + { + float* sourceBuf = + static_cast<float*>(normalizedInput->getBuf(bandCount)); + ossim_uint16* resultBuf = getUshortBuf(bandCount); + for(counter = 0; counter < size; ++counter) + { + resultBuf[counter] + = static_cast<ossim_uint16>(theRemapTable. + pixFromNorm(sourceBuf[counter])); + } + } + } + else // Double + { + for(bandCount = 0; bandCount < theNumberOfDataComponents; ++bandCount) + { + double* sourceBuf = + static_cast<double*>(normalizedInput->getBuf(bandCount)); + ossim_uint16* resultBuf = getUshortBuf(bandCount); + for(counter = 0; counter < size; ++counter) + { + resultBuf[counter] + = static_cast<ossim_uint16>(theRemapTable. + pixFromNorm(sourceBuf[counter])); + } + } + } + } +} + +double ossimU11ImageData::computeMeanSquaredError(double meanValue, + ossim_uint32 bandNumber) +{ + double result = -1; // invalid MSE + ossim_uint32 index = 0; + double delta = 0; + ossim_uint32 validPixelCount=0; + + ossim_uint16* buffer = getUshortBuf(bandNumber); + if(buffer) + { + ossim_uint32 bounds = getWidth()*getHeight(); + for(index = 0; index < bounds; ++index) + { + if(!isNull(index)) + { + delta = *buffer - meanValue; + result += (delta*delta); + ++validPixelCount; + } + ++buffer; + } + if(validPixelCount > 0) + { + result /= validPixelCount; + } + } + + return result; +} + +//****************************************************************** +// +// NOTE: I was checking for null and not adding it to the histogram. +// this was messing up the equalization algorithms since the +// accumulation histogram did not represent the area of the +// image. For now I will leave out the check for "is null" and +// add this to the count so that the total accumulation is the +// area of the image. +// +//****************************************************************** +void ossimU11ImageData::populateHistogram(ossimMultiBandHistogram* histo) +{ + ossim_uint32 numberOfBands = getNumberOfBands(); + + if( (getDataObjectStatus() == OSSIM_NULL) || + (getDataObjectStatus() == OSSIM_EMPTY)) + { + return; + } + + for(ossim_uint32 band = 0; band < numberOfBands; ++band) + { + ossimHistogram* currentHisto = histo->getHistogram(band); + ossim_uint16* buffer = getUshortBuf(band); + + if(currentHisto) + { + //float *counts = currentHisto->GetCounts(); + ossim_uint32 upperBound = getWidth()*getHeight(); + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + currentHisto->UpCount((float)buffer[offset]); + } + } + } +} + +double ossimU11ImageData::computeAverageBandValue(ossim_uint32 bandNumber) +{ + double result = 0.0; + ossim_uint32 index = 0; + ossim_uint32 validPixelCount=0; + + ossim_uint16* buffer = getUshortBuf(bandNumber); + if(buffer) + { + ossim_uint32 bounds = getSizePerBand(); + for(index = 0; index < bounds; ++index) + { + if(!isNull(index)) + { + result += *buffer; + ++validPixelCount; + } + ++buffer; + } + if(validPixelCount > 0) + { + result /= validPixelCount; + } + } + + return result; +} + +void ossimU11ImageData::makeBlank() +{ + void* s = getBuf(); + + if (s == NULL) return; // nothing to do... + + ossim_uint32 size_in_pixels = getSizePerBand(); + + for(ossim_uint32 band =0; band < getNumberOfBands(); ++band) + { + ossim_uint16* p = getUshortBuf(band); + for (ossim_uint32 i=0; i<size_in_pixels; i++) p[i] = 0; + } + + setDataObjectStatus(OSSIM_EMPTY); +} + +void ossimU11ImageData::setValue(long x, long y, double color) +{ + if(theDataBuffer&&isWithin(x, y)) + { + //*** + // Compute the offset into the buffer for (x,y). This should always + // come out positive. + //*** + ossim_uint32 ux = static_cast<ossim_uint32>(x - theOrigin.x); + ossim_uint32 uy = static_cast<ossim_uint32>(y - theOrigin.y); + + ossim_uint32 offset = uy * theSpatialExtents[0] + ux; + + for(ossim_uint32 band = 0; band < theNumberOfDataComponents; band++) + { + ossim_uint16* buf = getUshortBuf(band)+offset; + *buf = (ossim_uint16)color; + } + } +} + +void ossimU11ImageData::fill(ossim_uint32 band, double value) +{ + void* s = getBuf(band); + + if (s == NULL) return; // nothing to do... + + ossim_uint32 size_in_pixels = getSizePerBand(); + ossim_uint16* p = getUshortBuf(band); + ossim_uint16 np = static_cast<ossim_uint16>(value); + + for (ossim_uint32 i=0; i<size_in_pixels; i++) p[i] = np; + + // Set the status to unknown since we don't know about the other bands. + setDataObjectStatus(OSSIM_STATUS_UNKNOWN); +} + + +bool ossimU11ImageData::isNull(ossim_uint32 offset)const +{ + for(ossim_uint32 band = 0; band < getNumberOfBands(); ++band) + { + const ossim_uint16* buf = getUshortBuf(band)+offset; + + if((*buf) != theNullPixelValue[band]) + { + return false; + } + } + + return true; +} + +void ossimU11ImageData::setNull(ossim_uint32 offset) +{ + ossim_uint32 bands = getNumberOfBands(); + for(ossim_uint32 band = 0; band < bands; ++band) + { + ossim_uint16* buf = getUshortBuf(band)+offset; + *buf = (ossim_uint16)theNullPixelValue[band]; + } +} + +void ossimU11ImageData::loadBand(const void* src, + const ossimIrect& src_rect, + ossim_uint32 band) +{ + ossimImageData::loadBand(ossim_uint16(0), src, src_rect, band); +} + +void ossimU11ImageData::loadTile(void* src, + const ossimIrect& src_rect, + ossimInterleaveType il_type) +{ + // Load the tile from the buffer. + switch (il_type) + { + case OSSIM_BIP: + ossimImageData::loadTileFromBip(ossim_uint16(0), src, src_rect); + break; + case OSSIM_BIL: + ossimImageData::loadTileFromBil(ossim_uint16(0), src, src_rect); + break; + case OSSIM_BSQ: + ossimImageData::loadTileFromBsq(ossim_uint16(0), src, src_rect); + break; + default: + ossimNotify(ossimNotifyLevel_WARN) + << "ossimU11ImageData::loadTile" + << "\nUnknown interleave type passed to method. Returning..." + << endl; + break; + } +} + +void ossimU11ImageData::unloadBand(void* dest, + const ossimIrect& dest_rect, + ossim_uint32 band) const +{ + ossimImageData::unloadBand(ossim_uint16(0), dest, dest_rect, + getImageRectangle(), band); +} + +void ossimU11ImageData::copyTileToNormalizedBuffer(double* buf) const +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU11ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + for(ossim_uint32 band = 0; band < getNumberOfBands(); band++) + { + const ossim_uint16* s = getUshortBuf(band); // source + double* d = buf + (band*size); // destination + + for(ossim_uint32 index = 0; index < size; index++) + { + d[index] = theRemapTable. + normFromPix(static_cast<ossim_int32>(s[index])); + } + } + } +} + +void ossimU11ImageData::copyTileToNormalizedBuffer(ossim_uint32 band, + double* buf) const +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU11ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + if(!getBuf(band)) return; + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + const ossim_uint16* s = getUshortBuf(band); // source + double* d = buf; // destination + + for(ossim_uint32 index = 0; index < size; index++) + { + *d = theRemapTable. + normFromPix(static_cast<ossim_int32>(*s)); + } + } +} + + +void ossimU11ImageData::copyNormalizedBufferToTile(double* buf) +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU11ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + for(ossim_uint32 band = 0; band < getNumberOfBands(); band++) + { + double* s = buf + (band*size); // source + ossim_uint16* d = getUshortBuf(band); // destination + + for(ossim_uint32 index = 0; index < size; index++) + { + d[index] = theRemapTable.pixFromNorm(s[index]); + } + } + } +} + +void ossimU11ImageData::copyNormalizedBufferToTile(ossim_uint32 band, + double* buf) +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU11ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + + ossim_uint32 size = getSizePerBand(); + + if((size > 0)&&getBuf(band)) + { + double* s = buf; // source + ossim_uint16* d = getUshortBuf(band); // destination + + for(ossim_uint32 index = 0; index < size; ++index) + { + *d = theRemapTable.pixFromNorm(*s); + ++d; + ++s; + } + } +} + + +void ossimU11ImageData::copyTileToNormalizedBuffer(float* buf) const +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU11ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + for(ossim_uint32 band = 0; band < getNumberOfBands(); band++) + { + const ossim_uint16* s = getUshortBuf(band); // source + float* d = buf + (band*size); // destination + + for(ossim_uint32 index = 0; index < size; index++) + { + d[index] = theRemapTable. + normFromPix(static_cast<ossim_int32>(s[index])); + } + } + } +} + +void ossimU11ImageData::copyTileToNormalizedBuffer(ossim_uint32 band, + float* buf) const +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU11ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + if(!getBuf(band)) return; + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + const ossim_uint16* s = getUshortBuf(band); // source + float* d = buf; // destination + + for(ossim_uint32 index = 0; index < size; index++) + { + *d = theRemapTable. + normFromPix(static_cast<ossim_int32>(*s)); + } + } +} + +void ossimU11ImageData::copyNormalizedBufferToTile(float* buf) +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU11ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + for(ossim_uint32 band = 0; band < getNumberOfBands(); band++) + { + float* s = buf + (band*size); // source + ossim_uint16* d = getUshortBuf(band); // destination + + for(ossim_uint32 index = 0; index < size; index++) + { + d[index] = theRemapTable.pixFromNorm(s[index]); + } + } + } +} + + +void ossimU11ImageData::copyNormalizedBufferToTile(ossim_uint32 band, + float* buf) +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU11ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + + ossim_uint32 size = getSizePerBand(); + + if((size > 0)&&getBuf(band)) + { + float* s = buf; // source + ossim_uint16* d = getUshortBuf(band); // destination + + for(ossim_uint32 index = 0; index < size; ++index) + { + *d = theRemapTable.pixFromNorm(*s); + ++d; + ++s; + } + } +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimU11ImageData.h b/Utilities/OSSIM/ossim_core/imaging/ossimU11ImageData.h new file mode 100644 index 0000000000..f6cd7943b0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimU11ImageData.h @@ -0,0 +1,204 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Class declaration of ossimU16ImageData. Specialized image data object for +// unsigned short data with an 11 bit depth. +// +// NOTE: This object is optimized for unsigned short data and assumes the +// following: null pixel value = 0.0 +// min pixel value = 1.0 +// max pixel value = 2047.0 (2^11 - 1) +// +// If you want anything else use the less efficient ossimImageData. +// +//************************************************************************* +// $Id: ossimU11ImageData.h,v 1.16 2004/09/02 13:59:03 dburken Exp $ + +#ifndef ossimU11ImageData_HEADER +#define ossimU11ImageData_HEADER + +#include "ossimImageData.h" +#include "imaging/remap_tables/ossimNormalizedU11RemapTable.h" + +class OSSIMDLLEXPORT ossimU11ImageData : public ossimImageData +{ +public: + ossimU11ImageData(ossimSource* source, + ossim_uint32 bands = 1); + + ossimU11ImageData(ossimSource* source, + ossim_uint32 bands, + ossim_uint32 width, + ossim_uint32 height); + + ossimU11ImageData(const ossimU11ImageData &rhs); + + virtual ~ossimU11ImageData(); + + virtual ossimObject* dup()const; + + /*! + * will fill the entire band with + * the value. + */ + void fill(ossim_uint32 band, double value); + + bool isNull(ossim_uint32 offset)const; + void setNull(ossim_uint32 offset); + + virtual ossimDataObjectStatus validate() const; + + /*! + * will go to the band and offset and compute the + * normalized float and return it back to the + * caller through the result argument. + */ + virtual void getNormalizedFloat(ossim_uint32 offset, + ossim_uint32 bandNumber, + float& result)const; + + /*! + * This will assign to this object a normalized + * value by unnormalizing to its native type. + */ + virtual void setNormalizedFloat(ossim_uint32 offset, + ossim_uint32 bandNumber, + float input); + + /*! + * Will use the memory that you pass in to normalize + * this data object. + */ + virtual void convertToNormalizedFloat(ossimImageData* result)const; + + /*! + * Will use the memory that you pass in to normalize + * this data object. + */ + virtual void convertToNormalizedDouble(ossimImageData* result)const; + + /*! + * Will take the normalized input and convert it + * to this tile's data type. Example: if this + * tile is of type UCHAR and its input is of type + * NORALIZED_FLOAT it will unnormalize the data by + * doing: + * + * minPix + normalizedInput*(maxPix-minPix) + * + * on a per band basis. + */ + virtual void unnormalizeInput(ossimImageData* normalizedInput); + + /*! + * This will compute the average value for the band. + */ + virtual double computeAverageBandValue(ossim_uint32 bandNumber = 0); + + /*! + * This will call the compute average band value and then + * use that in the calculation of: + + * It will then do a SUM[(Mean - Actual)^2]/width*height. + * + * This is the average variance from the passed in + * mean. Basically think of the mean as a completely + * grey image and we would like to see how this + * image varies from the passed in mean. + */ + virtual double computeMeanSquaredError(double meanValue, + ossim_uint32 bandNumber = 0); + + virtual void populateHistogram(ossimMultiBandHistogram* histo); + + /*! + * Initializes data to null pixel values. + */ + virtual void makeBlank(); + + virtual void setValue(long x, long y, double color); + + virtual void loadBand(const void* src, + const ossimIrect& src_rect, + ossim_uint32 band); + + virtual void loadTile(void* src, + const ossimIrect& src_rect, + ossimInterleaveType il_type); + + virtual void unloadBand(void* dest, + const ossimIrect& dest_rect, + ossim_uint32 band) const; + + /*! + * Copies entire tile to buf passed in. Data put in buf is normalized. + * The "buf" passed to method is assumed to be at least as big as: + * "getSize() * sizeof(double)" + */ + virtual void copyTileToNormalizedBuffer(double* buf) const; + + /*! + * Copies buf passed in to tile. Data is unnormalized to the tile's + * scalar type. + * The "buf" passed to method is assumed to be at least as big as the tiles: + * "getSize() * sizeof(double)" + */ + virtual void copyNormalizedBufferToTile(double* buf); + + /*! + * Will copy this tiles specified band number to the normalized buffer. + * if the band is out of range then nothing is done and returns. + */ + virtual void copyTileToNormalizedBuffer(ossim_uint32 band, + double* buf) const; + virtual void copyTileToNormalizedBuffer(ossim_uint32 band, + float* buf)const; + + /*! + * Copies entire tile to buf passed in. Data put in buf is normalized. + * The "buf" passed to method is assumed to be at least as big as: + * "getSize() * sizeof(double)" + */ + virtual void copyTileToNormalizedBuffer(float* buf) const; + + /*! + * Copies buf passed in to tile. Data is unnormalized to the tile's + * scalar type. + * The "buf" passed to method is assumed to be at least as big as the tiles: + * "getSize() * sizeof(double)" + */ + virtual void copyNormalizedBufferToTile(float* buf); + + /*! + * Will copy the normalized buffer to this tiles + * specified band. If band is out of range then nothing + * is done and returns. + */ + virtual void copyNormalizedBufferToTile(ossim_uint32 band, + double* buf); + virtual void copyNormalizedBufferToTile(ossim_uint32 band, + float* buf); + +protected: + ossimU11ImageData(); + +private: + + // Disallow from use... + const ossimU11ImageData& operator =(const ossimU11ImageData &rhs) + {return *this;} + + static const ossimNormalizedU11RemapTable theRemapTable; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimU16ImageData.cpp b/Utilities/OSSIM/ossim_core/imaging/ossimU16ImageData.cpp new file mode 100644 index 0000000000..1d5943479b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimU16ImageData.cpp @@ -0,0 +1,695 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Class definition of ossimU16ImageData. Specialized image data object for +// unsigned short data. +// +// NOTE: This object is optimized for unsigned short data and assumes the +// following: null pixel value = 0.0 +// min pixel value = 1.0 +// max pixel value = 65535.0 (2^16 - 1) +// +// If you want anything else use the less efficient ossimImageData. +// +//************************************************************************* +// $Id: ossimU16ImageData.cpp,v 1.17 2004/09/02 13:59:03 dburken Exp $ + +#include <string.h> // for memset function + +#include "ossimU16ImageData.h" +#include "base/common/ossimSource.h" +#include "base/context/ossimErrorContext.h" +#include "base/data_types/ossimIrect.h" +#include "base/data_types/ossimMultiBandHistogram.h" +#include "base/data_types/ossimHistogram.h" + +RTTI_DEF1(ossimU16ImageData, "ossimU16ImageData", ossimImageData) + +const ossimNormalizedU16RemapTable ossimU16ImageData::theRemapTable; + +ossimU16ImageData::ossimU16ImageData() + : + ossimImageData() +{ +} + +ossimU16ImageData::ossimU16ImageData(ossimSource* source, + ossim_uint32 bands) + : + ossimImageData(source, + OSSIM_USHORT16, + bands) +{ +} + +ossimU16ImageData::ossimU16ImageData(ossimSource* source, + ossim_uint32 bands, + ossim_uint32 width, + ossim_uint32 height) + : + ossimImageData(source, + OSSIM_USHORT16, + bands, + width, + height) +{ +} + +ossimU16ImageData::ossimU16ImageData(const ossimU16ImageData &rhs) + : + ossimImageData(rhs) +{ +} + +ossimU16ImageData::~ossimU16ImageData() +{ +} + +ossimObject* ossimU16ImageData::dup()const +{ + return new ossimU16ImageData(*this); +} + +ossimDataObjectStatus ossimU16ImageData::validate() const +{ + if (theDataBuffer == NULL) + { + setDataObjectStatus(OSSIM_NULL); + return OSSIM_NULL; + } + + ossim_uint32 count = 0; + const ossim_uint32 SIZE = getSize(); + const ossim_uint32 BOUNDS = getSizePerBand(); + const ossim_uint32 NUMBER_OF_BANDS = getNumberOfBands(); + + for(ossim_uint32 band = 0; band < NUMBER_OF_BANDS; ++band) + { + const ossim_uint16* p = getUshortBuf(band); + for (ossim_uint32 i=0; i<BOUNDS; i++) + { + // check if the band is null + if (p[i] != 0) count++; + } + } + + if (!count) + setDataObjectStatus(OSSIM_EMPTY); + else if (count == SIZE) + setDataObjectStatus(OSSIM_FULL); + else + setDataObjectStatus(OSSIM_PARTIAL); + + return getDataObjectStatus(); +} + +void ossimU16ImageData::getNormalizedFloat(ossim_uint32 offset, + ossim_uint32 bandNumber, + float& result)const +{ + if(!result) + { + return; + } + + // make sure that the types and width and height are good. + if( (getDataObjectStatus() == OSSIM_NULL) && isValidBand(bandNumber) ) + { + return; + } + + const ossim_uint16* sourceBuf = getUshortBuf(bandNumber); + result = static_cast<float>(theRemapTable.normFromPix(sourceBuf[offset])); +} + +void ossimU16ImageData::setNormalizedFloat(ossim_uint32 offset, + ossim_uint32 bandNumber, + float inputValue) +{ + // make sure that the types and width and height are + // good. + if((getDataObjectStatus() == OSSIM_NULL)&& + (bandNumber < getNumberOfBands())) + { + return; + } + + ossim_uint16* sourceBuf = getUshortBuf(bandNumber); + sourceBuf[offset] + = static_cast<ossim_uint16>(theRemapTable.pixFromNorm(inputValue)); +} + +void +ossimU16ImageData::convertToNormalizedFloat(ossimImageData* result)const +{ + if(!result) + { + return; + } + // make sure that the types and width and height are + // good. + if( (result->getScalarType() != OSSIM_NORMALIZED_FLOAT) || + (result->getNumberOfBands() != this->getNumberOfBands())|| + (result->getWidth() != this->getWidth()) || + (result->getHeight() != this->getHeight())|| + (result->getDataObjectStatus() == OSSIM_NULL) || + (getDataObjectStatus() == OSSIM_NULL)) + { + return; + } + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + for(ossim_uint32 bandCount = 0; bandCount < theNumberOfDataComponents; ++bandCount) + { + const ossim_uint16* sourceBuf = getUshortBuf(bandCount); + float* resultBuf = static_cast<float*>(result->getBuf(bandCount)); + for(ossim_uint32 counter = 0; counter < size; ++counter) + { + resultBuf[counter] + = static_cast<float>(theRemapTable. + normFromPix(sourceBuf[counter])); + } + } + } +} + +void ossimU16ImageData::convertToNormalizedDouble(ossimImageData* result)const +{ + if(!result) + { + return; + } + + // make sure that the types and width and height are + // good. + if( (result->getScalarType() != OSSIM_NORMALIZED_FLOAT) || + (result->getNumberOfBands() != this->getNumberOfBands())|| + (result->getWidth() != this->getWidth()) || + (result->getHeight() != this->getHeight())|| + (result->getDataObjectStatus() == OSSIM_NULL) || + (getDataObjectStatus() == OSSIM_NULL)) + { + return; + } + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + for(ossim_uint32 bandCount = 0; bandCount < theNumberOfDataComponents; ++bandCount) + { + const ossim_uint16* sourceBuf = getUshortBuf(bandCount); + double* resultBuf = static_cast<double*>(result->getBuf(bandCount)); + for(ossim_uint32 counter = 0; counter < size; ++counter) + { + resultBuf[counter] = theRemapTable.normFromPix(sourceBuf[counter]); + } + } + } + +} + +void ossimU16ImageData::unnormalizeInput(ossimImageData* normalizedInput) +{ + if((normalizedInput->getScalarType() != OSSIM_NORMALIZED_FLOAT) && + (normalizedInput->getScalarType() != OSSIM_NORMALIZED_DOUBLE) ) + { + //ERROR + return; + } + + ossim_uint32 counter = 0; + ossim_uint32 bandCount = 0; + ossim_uint32 size = getSizePerBand(); + ossimScalarType scalarType = normalizedInput->getScalarType(); + + if(size > 0) + { + if(scalarType == OSSIM_NORMALIZED_FLOAT) + { + for(bandCount = 0; bandCount < theNumberOfDataComponents; ++bandCount) + { + float* sourceBuf = + static_cast<float*>(normalizedInput->getBuf(bandCount)); + ossim_uint16* resultBuf = getUshortBuf(bandCount); + for(counter = 0; counter < size; ++counter) + { + resultBuf[counter] + = static_cast<ossim_uint16>(theRemapTable. + pixFromNorm(sourceBuf[counter])); + } + } + } + else // Double + { + for(bandCount = 0; bandCount < theNumberOfDataComponents; ++bandCount) + { + double* sourceBuf = + static_cast<double*>(normalizedInput->getBuf(bandCount)); + ossim_uint16* resultBuf = getUshortBuf(bandCount); + for(counter = 0; counter < size; ++counter) + { + resultBuf[counter] + = static_cast<ossim_uint16>(theRemapTable. + pixFromNorm(sourceBuf[counter])); + } + } + } + } +} + +double ossimU16ImageData::computeMeanSquaredError(double meanValue, + ossim_uint32 bandNumber) +{ + double result = -1; // invalid MSE + ossim_uint32 index = 0; + double delta = 0; + ossim_uint32 validPixelCount=0; + + ossim_uint16* buffer = getUshortBuf(bandNumber); + if(buffer) + { + ossim_uint32 bounds = getWidth()*getHeight(); + for(index = 0; index < bounds; ++index) + { + if(!isNull(index)) + { + delta = *buffer - meanValue; + result += (delta*delta); + ++validPixelCount; + } + ++buffer; + } + if(validPixelCount > 0) + { + result /= validPixelCount; + } + } + + return result; +} + +//****************************************************************** +// +// NOTE: I was checking for null and not adding it to the histogram. +// this was messing up the equalization algorithms since the +// accumulation histogram did not represent the area of the +// image. For now I will leave out the check for "is null" and +// add this to the count so that the total accumulation is the +// area of the image. +// +//****************************************************************** +void ossimU16ImageData::populateHistogram(ossimMultiBandHistogram* histo) +{ + ossim_uint32 numberOfBands = getNumberOfBands(); + + if( (getDataObjectStatus() == OSSIM_NULL) || + (getDataObjectStatus() == OSSIM_EMPTY)) + { + return; + } + + for(ossim_uint32 band = 0; band < numberOfBands; ++band) + { + ossimHistogram* currentHisto = histo->getHistogram(band); + ossim_uint16* buffer = getUshortBuf(band); + + if(currentHisto) + { + float *counts = currentHisto->GetCounts(); + ossim_uint32 upperBound = getWidth()*getHeight(); + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + counts[buffer[offset]]++; + } + } + } +} + +double ossimU16ImageData::computeAverageBandValue(ossim_uint32 bandNumber) +{ + double result = 0.0; + ossim_uint32 index = 0; + ossim_uint32 validPixelCount=0; + + ossim_uint16* buffer = getUshortBuf(bandNumber); + if(buffer) + { + ossim_uint32 bounds = getSizePerBand(); + for(index = 0; index < bounds; ++index) + { + if(!isNull(index)) + { + result += *buffer; + ++validPixelCount; + } + ++buffer; + } + if(validPixelCount > 0) + { + result /= validPixelCount; + } + } + + return result; +} + +void ossimU16ImageData::makeBlank() +{ + void* s = getBuf(); + + if (s == NULL) return; // nothing to do... + + ossim_uint32 size_in_pixels = getSizePerBand(); + + for(ossim_uint32 band =0; band < getNumberOfBands(); ++band) + { + ossim_uint16* p = getUshortBuf(band); + for (ossim_uint32 i=0; i<size_in_pixels; i++) p[i] = 0; + } + + setDataObjectStatus(OSSIM_EMPTY); +} + +void ossimU16ImageData::setValue(long x, long y, double color) +{ + if(theDataBuffer&&isWithin(x, y)) + { + //*** + // Compute the offset into the buffer for (x,y). This should always + // come out positive. + //*** + ossim_uint32 ux = static_cast<ossim_uint32>(x - theOrigin.x); + ossim_uint32 uy = static_cast<ossim_uint32>(y - theOrigin.y); + + ossim_uint32 offset = uy * theSpatialExtents[0] + ux; + + for(ossim_uint32 band = 0; band < theNumberOfDataComponents; band++) + { + ossim_uint16* buf = getUshortBuf(band)+offset; + *buf = (ossim_uint16)color; + } + } +} + +void ossimU16ImageData::fill(ossim_uint32 band, double value) +{ + void* s = getBuf(band); + + if (s == NULL) return; // nothing to do... + + ossim_uint32 size_in_pixels = getSizePerBand(); + ossim_uint16* p = getUshortBuf(band); + ossim_uint16 np = static_cast<ossim_uint16>(value); + + for (ossim_uint32 i=0; i<size_in_pixels; i++) p[i] = np; + + // Set the status to unknown since we don't know about the other bands. + setDataObjectStatus(OSSIM_STATUS_UNKNOWN); +} + + +void ossimU16ImageData::loadBand(const void* src, + const ossimIrect& src_rect, + ossim_uint32 band) +{ + ossimImageData::loadBand(ossim_uint16(0), src, src_rect, band); +} + +void ossimU16ImageData::loadTile(void* src, + const ossimIrect& src_rect, + ossimInterleaveType il_type) +{ + // Load the tile from the buffer. + switch (il_type) + { + case OSSIM_BIP: + ossimImageData::loadTileFromBip(ossim_uint16(0), src, src_rect); + break; + case OSSIM_BIL: + ossimImageData::loadTileFromBil(ossim_uint16(0), src, src_rect); + break; + case OSSIM_BSQ: + ossimImageData::loadTileFromBsq(ossim_uint16(0), src, src_rect); + break; + default: + cout << " NOTICE:" + << "\nUnknown interleave type passed to method. Returning..." + << endl; + break; + } +} + +void ossimU16ImageData::unloadBand(void* dest, + const ossimIrect& dest_rect, + ossim_uint32 band) const +{ + ossimImageData::unloadBand(ossim_uint16(0), dest, dest_rect, + getImageRectangle(), band); +} + +void ossimU16ImageData::copyTileToNormalizedBuffer(double* buf) const +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU16ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + for(ossim_uint32 band = 0; band < getNumberOfBands(); band++) + { + const ossim_uint16* s = getUshortBuf(band); // source + double* d = buf + (band*size); // destination + + for(ossim_uint32 index = 0; index < size; index++) + { + d[index] = theRemapTable. + normFromPix(static_cast<ossim_int32>(s[index])); + } + } + } +} + +void ossimU16ImageData::copyTileToNormalizedBuffer(ossim_uint32 band, + double* buf) const +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU11ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + if(!getBuf(band)) return; + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + const ossim_uint16* s = getUshortBuf(band); // source + double* d = buf; // destination + + for(ossim_uint32 index = 0; index < size; index++) + { + *d = theRemapTable. + normFromPix(static_cast<ossim_int32>(*s)); + } + } +} + +void ossimU16ImageData::copyNormalizedBufferToTile(double* buf) +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU16ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + for(ossim_uint32 band = 0; band < getNumberOfBands(); band++) + { + double* s = buf + (band*size); // source + ossim_uint16* d = getUshortBuf(band); // destination + + for(ossim_uint32 index = 0; index < size; index++) + { + d[index] = theRemapTable.pixFromNorm(s[index]); + } + } + } +} + +void ossimU16ImageData::copyNormalizedBufferToTile(ossim_uint32 band, + double* buf) +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU11ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + + ossim_uint32 size = getSizePerBand(); + + if((size > 0)&&getBuf(band)) + { + double* s = buf; // source + ossim_uint16* d = getUshortBuf(band); // destination + + for(ossim_uint32 index = 0; index < size; index++) + { + *d = theRemapTable.pixFromNorm(*s); + ++d; + ++s; + } + } +} + +void ossimU16ImageData::copyTileToNormalizedBuffer(float* buf) const +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU16ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + for(ossim_uint32 band = 0; band < getNumberOfBands(); band++) + { + const ossim_uint16* s = getUshortBuf(band); // source + float* d = buf + (band*size); // destination + + for(ossim_uint32 index = 0; index < size; index++) + { + d[index] = theRemapTable. + normFromPix(static_cast<ossim_int32>(s[index])); + } + } + } +} + +void ossimU16ImageData::copyTileToNormalizedBuffer(ossim_uint32 band, + float* buf) const +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU11ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + if(!getBuf(band)) return; + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + const ossim_uint16* s = getUshortBuf(band); // source + float* d = buf; // destination + + for(ossim_uint32 index = 0; index < size; index++) + { + *d = theRemapTable. + normFromPix(static_cast<ossim_int32>(*s)); + } + } +} + +void ossimU16ImageData::copyNormalizedBufferToTile(float* buf) +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU16ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + for(ossim_uint32 band = 0; band < getNumberOfBands(); band++) + { + float* s = buf + (band*size); // source + ossim_uint16* d = getUshortBuf(band); // destination + + for(ossim_uint32 index = 0; index < size; index++) + { + d[index] = theRemapTable.pixFromNorm(s[index]); + } + } + } +} + +void ossimU16ImageData::copyNormalizedBufferToTile(ossim_uint32 band, + float* buf) +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU11ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + + ossim_uint32 size = getSizePerBand(); + + if((size > 0)&&getBuf(band)) + { + float* s = buf; // source + ossim_uint16* d = getUshortBuf(band); // destination + + for(ossim_uint32 index = 0; index < size; index++) + { + *d = theRemapTable.pixFromNorm(*s); + ++d; + ++s; + } + } +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimU16ImageData.h b/Utilities/OSSIM/ossim_core/imaging/ossimU16ImageData.h new file mode 100644 index 0000000000..582a2ab47a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimU16ImageData.h @@ -0,0 +1,208 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Class declaration of ossimU16ImageData. Specialized image data object for +// unsigned short data. +// +// NOTE: This object is optimized for unsigned short data and assumes the +// following: null pixel value = 0.0 +// min pixel value = 1.0 +// max pixel value = 65536.0 (2^16 - 1) +// +// If you want anything else use the less efficient ossimImageData. +// +//************************************************************************* +// $Id: ossimU16ImageData.h,v 1.16 2004/09/02 13:59:03 dburken Exp $ + +#ifndef ossimU16ImageData_HEADER +#define ossimU16ImageData_HEADER + +#include "ossimImageData.h" +#include "imaging/remap_tables/ossimNormalizedU16RemapTable.h" + +class OSSIMDLLEXPORT ossimU16ImageData : public ossimImageData +{ +public: + ossimU16ImageData(ossimSource* source, + ossim_uint32 bands = 1); + + ossimU16ImageData(ossimSource* source, + ossim_uint32 bands, + ossim_uint32 width, + ossim_uint32 height); + + ossimU16ImageData(const ossimU16ImageData &rhs); + + virtual ~ossimU16ImageData(); + + /*! + * Perform object duplication. + */ + virtual ossimObject* dup()const; + + /*! + * will fill the entire band with + * the value. + */ + void fill(ossim_uint32 band, double value); + + /*! + * will fill all bands with the passed in + * value. + */ + void fill(double value); + + virtual ossimDataObjectStatus validate() const; + + /*! + * will go to the band and offset and compute the + * normalized float and return it back to the + * caller through the result argument. + */ + virtual void getNormalizedFloat(ossim_uint32 offset, + ossim_uint32 bandNumber, + float& result)const; + + /*! + * This will assign to this object a normalized + * value by unnormalizing to its native type. + */ + virtual void setNormalizedFloat(ossim_uint32 offset, + ossim_uint32 bandNumber, + float input); + + /*! + * Will use the memory that you pass in to normalize + * this data object. + */ + virtual void convertToNormalizedFloat(ossimImageData* result)const; + + /*! + * Will use the memory that you pass in to normalize + * this data object. + */ + virtual void convertToNormalizedDouble(ossimImageData* result)const; + + /*! + * Will take the normalized input and convert it + * to this tile's data type. Example: if this + * tile is of type UCHAR and its input is of type + * NORALIZED_FLOAT it will unnormalize the data by + * doing: + * + * minPix + normalizedInput*(maxPix-minPix) + * + * on a per band basis. + */ + virtual void unnormalizeInput(ossimImageData* normalizedInput); + + /*! + * This will compute the average value for the band. + */ + virtual double computeAverageBandValue(ossim_uint32 bandNumber = 0); + + /*! + * This will call the compute average band value and then + * use that in the calculation of: + + * It will then do a SUM[(Mean - Actual)^2]/width*height. + * + * This is the average variance from the passed in + * mean. Basically think of the mean as a completely + * grey image and we would like to see how this + * image varies from the passed in mean. + */ + virtual double computeMeanSquaredError(double meanValue, + ossim_uint32 bandNumber = 0); + + virtual void populateHistogram(ossimMultiBandHistogram* histo); + + /*! + * Initializes data to null pixel values. + */ + virtual void makeBlank(); + + virtual void setValue(long x, long y, double color); + + virtual void loadBand(const void* src, + const ossimIrect& src_rect, + ossim_uint32 band); + + virtual void loadTile(void* src, + const ossimIrect& src_rect, + ossimInterleaveType il_type); + + virtual void unloadBand(void* dest, + const ossimIrect& dest_rect, + ossim_uint32 band) const; + + /*! + * Copies entire tile to buf passed in. Data put in buf is normalized. + * The "buf" passed to method is assumed to be at least as big as: + * "getSize() * sizeof(double)" + */ + virtual void copyTileToNormalizedBuffer(double* buf) const; + + /*! + * Copies buf passed in to tile. Data is unnormalized to the tile's + * scalar type. + * The "buf" passed to method is assumed to be at least as big as the tiles: + * "getSize() * sizeof(double)" + */ + virtual void copyNormalizedBufferToTile(double* buf); + + /*! + * Will copy this tiles specified band number to the normalized buffer. + * if the band is out of range then nothing is done and returns. + */ + virtual void copyTileToNormalizedBuffer(ossim_uint32 band, double* buf) const; + virtual void copyTileToNormalizedBuffer(ossim_uint32 band, float* buf)const; + + /*! + * Copies entire tile to buf passed in. Data put in buf is normalized. + * The "buf" passed to method is assumed to be at least as big as: + * "getSize() * sizeof(double)" + */ + virtual void copyTileToNormalizedBuffer(float* buf) const; + + /*! + * Copies buf passed in to tile. Data is unnormalized to the tile's + * scalar type. + * The "buf" passed to method is assumed to be at least as big as the tiles: + * "getSize() * sizeof(double)" + */ + virtual void copyNormalizedBufferToTile(float* buf); + + /*! + * Will copy the normalized buffer to this tiles + * specified band. If band is out of range then nothing + * is done and returns. + */ + virtual void copyNormalizedBufferToTile(ossim_uint32 band, + double* buf); + virtual void copyNormalizedBufferToTile(ossim_uint32 band, + float* buf); +protected: + ossimU16ImageData(); + + +private: + + // Disallow from use... + const ossimU16ImageData& operator =(const ossimU16ImageData &rhs) + {return *this;} + + static const ossimNormalizedU16RemapTable theRemapTable; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimU8ImageData.cpp b/Utilities/OSSIM/ossim_core/imaging/ossimU8ImageData.cpp new file mode 100644 index 0000000000..b10a547c6d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimU8ImageData.cpp @@ -0,0 +1,738 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Class definition of ossimU8ImageData. Specialized image data object for +// unsigned char data. +// +// NOTE: This object is optimized for unsigned char data and assumes the +// following: null pixel value = 0.0 +// min pixel value = 1.0 +// max pixel value = 255.0 +// +// If you want anything else use the less efficient ossimImageData. +// +//************************************************************************* +// $Id: ossimU8ImageData.cpp,v 1.26 2005/08/11 14:31:25 dburken Exp $ + +#include <cstring> // for memset function +using namespace std; + +#include <imaging/ossimU8ImageData.h> +#include <base/common/ossimSource.h> +#include <base/context/ossimErrorContext.h> +#include <base/data_types/ossimIrect.h> +#include <base/data_types/ossimMultiBandHistogram.h> +#include <base/data_types/ossimHistogram.h> + +RTTI_DEF1(ossimU8ImageData, "ossimU8ImageData", ossimImageData) + +const ossimNormalizedU8RemapTable ossimU8ImageData::theRemapTable; + +ossimU8ImageData::ossimU8ImageData(ossimSource* source, + ossim_uint32 bands) + : + ossimImageData(source, + OSSIM_UCHAR, + bands) +{ +} + +ossimU8ImageData::ossimU8ImageData(ossimSource* source, + ossim_uint32 bands, + ossim_uint32 width, + ossim_uint32 height) + : + ossimImageData(source, + OSSIM_UCHAR, + bands, + width, + height) +{ +} + +ossimU8ImageData::~ossimU8ImageData() +{ +} + +ossimObject* ossimU8ImageData::dup()const +{ + return new ossimU8ImageData(*this); +} + +void ossimU8ImageData::fill(double value) +{ + ossimImageData::fill(value); +} + +ossimDataObjectStatus ossimU8ImageData::validate() const +{ + if (theDataBuffer == NULL) + { + setDataObjectStatus(OSSIM_NULL); + return OSSIM_NULL; + } + + ossim_uint32 count = 0; + const ossim_uint32 SIZE = getSize(); + const ossim_uint32 BOUNDS = getSizePerBand(); + const ossim_uint32 NUMBER_OF_BANDS = getNumberOfBands(); + + for(ossim_uint32 band = 0; band < NUMBER_OF_BANDS; ++band) + { + const ossim_uint8* p = getUcharBuf(band); + ossim_uint8 np = (ossim_uint8)getNullPix(band); + for (ossim_uint32 i=0; i<BOUNDS; ++i) + { + // check if the band is null + if (p[i] != np) ++count; + } + } + + if (!count) + setDataObjectStatus(OSSIM_EMPTY); + else if (count == SIZE) + setDataObjectStatus(OSSIM_FULL); + else + setDataObjectStatus(OSSIM_PARTIAL); + + return getDataObjectStatus(); +} + +void ossimU8ImageData::getNormalizedFloat(ossim_uint32 offset, + ossim_uint32 bandNumber, + float& result)const +{ + if(!result) + { + return; + } + + // make sure that the types and width and height are good. + if( (getDataObjectStatus() == OSSIM_NULL) && isValidBand(bandNumber) ) + { + return; + } + + const ossim_uint8* sourceBuf = getUcharBuf(bandNumber); + result = static_cast<float>(theRemapTable.normFromPix(sourceBuf[offset])); +} + +void ossimU8ImageData::setNormalizedFloat(ossim_uint32 offset, + ossim_uint32 bandNumber, + float inputValue) +{ + // make sure that the types and width and height are + // good. + if((getDataObjectStatus() == OSSIM_NULL)&& + (bandNumber < getNumberOfBands())) + { + return; + } + + ossim_uint8* sourceBuf = getUcharBuf(bandNumber); + sourceBuf[offset] + = static_cast<ossim_uint8>(theRemapTable.pixFromNorm(inputValue)); +} + +void ossimU8ImageData::convertToNormalizedFloat(ossimImageData* result)const +{ + if(!result) + { + return; + } + // make sure that the types and width and height are + // good. + if( (result->getScalarType() != OSSIM_NORMALIZED_FLOAT) || + (result->getNumberOfBands() != this->getNumberOfBands())|| + (result->getWidth() != this->getWidth()) || + (result->getHeight() != this->getHeight())|| + (result->getDataObjectStatus() == OSSIM_NULL) || + (getDataObjectStatus() == OSSIM_NULL)) + { + return; + } + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + for(ossim_uint32 bandCount = 0; bandCount < theNumberOfDataComponents; ++bandCount) + { + const ossim_uint8* sourceBuf = getUcharBuf(bandCount); + float* resultBuf = static_cast<float*>(result->getBuf(bandCount)); + for(ossim_uint32 counter = 0; counter < size; ++counter) + { + resultBuf[counter] + = static_cast<float>(theRemapTable. + normFromPix(sourceBuf[counter])); + } + } + } +} + +void ossimU8ImageData::convertToNormalizedDouble(ossimImageData* result)const +{ + if(!result) + { + return; + } + + // make sure that the types and width and height are + // good. + if( (result->getScalarType() != OSSIM_NORMALIZED_FLOAT) || + (result->getNumberOfBands() != this->getNumberOfBands())|| + (result->getWidth() != this->getWidth()) || + (result->getHeight() != this->getHeight())|| + (result->getDataObjectStatus() == OSSIM_NULL) || + (getDataObjectStatus() == OSSIM_NULL)) + { + return; + } + + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + for(ossim_uint32 bandCount = 0; bandCount < theNumberOfDataComponents; ++bandCount) + { + const ossim_uint8* sourceBuf = getUcharBuf(bandCount); + double* resultBuf = static_cast<double*>(result->getBuf(bandCount)); + for(ossim_uint32 counter = 0; counter < size; ++counter) + { + resultBuf[counter] = theRemapTable.normFromPix(sourceBuf[counter]); + } + } + } +} + +void ossimU8ImageData::unnormalizeInput(ossimImageData* normalizedInput) +{ + if((normalizedInput->getScalarType() != OSSIM_NORMALIZED_FLOAT) && + (normalizedInput->getScalarType() != OSSIM_NORMALIZED_DOUBLE) ) + { + //ERROR + return; + } + + ossim_uint32 counter = 0; + ossim_uint32 bandCount = 0; + ossim_uint32 size = getSizePerBand(); + ossimScalarType scalarType = normalizedInput->getScalarType(); + + if(size > 0) + { + if(scalarType == OSSIM_NORMALIZED_FLOAT) + { + for(bandCount = 0; bandCount < theNumberOfDataComponents; ++bandCount) + { + float* sourceBuf = + static_cast<float*>(normalizedInput->getBuf(bandCount)); + ossim_uint8* resultBuf = getUcharBuf(bandCount); + for(counter = 0; counter < size; ++counter) + { + resultBuf[counter] + = static_cast<ossim_uint8>(theRemapTable. + pixFromNorm(sourceBuf[counter])); + } + } + } + else // Double + { + for(bandCount = 0; bandCount < theNumberOfDataComponents; ++bandCount) + { + double* sourceBuf = + static_cast<double*>(normalizedInput->getBuf(bandCount)); + ossim_uint8* resultBuf = getUcharBuf(bandCount); + for(counter = 0; counter < size; ++counter) + { + resultBuf[counter] + = static_cast<ossim_uint8>(theRemapTable. + pixFromNorm(sourceBuf[counter])); + } + } + } + } +} + +double ossimU8ImageData::computeMeanSquaredError(double meanValue, + ossim_uint32 bandNumber) +{ + double result = -1; // invalid MSE + ossim_uint32 index = 0; + double delta = 0; + ossim_uint32 validPixelCount=0; + + ossim_uint8* buffer = getUcharBuf(bandNumber); + if(buffer) + { + ossim_uint32 bounds = getWidth()*getHeight(); + for(index = 0; index < bounds; ++index) + { + if(!isNull(index)) + { + delta = *buffer - meanValue; + result += (delta*delta); + ++validPixelCount; + } + ++buffer; + } + if(validPixelCount > 0) + { + result /= validPixelCount; + } + } + + return result; +} + +//****************************************************************** +// +// NOTE: I was checking for null and not adding it to the histogram. +// this was messing up the equalization algorithms since the +// accumulation histogram did not represent the area of the +// image. For now I will leave out the check for "is null" and +// add this to the count so that the total accumulation is the +// area of the image. +// +//****************************************************************** +void ossimU8ImageData::populateHistogram(ossimMultiBandHistogram* histo) +{ + ossim_uint32 numberOfBands = getNumberOfBands(); + + if( (getDataObjectStatus() == OSSIM_NULL) || + (getDataObjectStatus() == OSSIM_EMPTY)) + { + return; + } + + for(ossim_uint32 band = 0; band < numberOfBands; ++band) + { + ossimHistogram* currentHisto = histo->getHistogram(band); + ossim_uint8* buffer = getUcharBuf(band); + + if(currentHisto) + { + float *counts = currentHisto->GetCounts(); + ossim_uint32 upperBound = getWidth()*getHeight(); + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + counts[buffer[offset]]++; + } + } + } +} + +double ossimU8ImageData::computeAverageBandValue(ossim_uint32 bandNumber) +{ + double result = 0.0; + ossim_uint32 index = 0; + ossim_uint32 validPixelCount=0; + + ossim_uint8* buffer = getUcharBuf(bandNumber); + if(buffer) + { + ossim_uint32 bounds = getWidth()*getHeight(); + for(index = 0; index < bounds; ++index) + { + if(!isNull(index)) + { + result += *buffer; + ++validPixelCount; + } + ++buffer; + } + if(validPixelCount > 0) + { + result /= validPixelCount; + } + } + + return result; +} + +void ossimU8ImageData::makeBlank() +{ + if ( (theDataBuffer == NULL) || (getDataObjectStatus() == OSSIM_EMPTY) ) + { + return; // nothing to do... + } + + const ossim_uint32 BANDS = getNumberOfBands(); + int n = static_cast<int>(getSizePerBand()); + for(ossim_uint32 band = 0; band < BANDS; ++band) + { + int c = static_cast<int>(theNullPixelValue[band]); + void* p = getBuf(band); + memset(p, c, n); + } + + setDataObjectStatus(OSSIM_EMPTY); +} + +void ossimU8ImageData::setValue(ossim_int32 x, ossim_int32 y, double color) +{ + if(theDataBuffer&&isWithin(x, y)) + { + //*** + // Compute the offset into the buffer for (x,y). This should always + // come out positive. + //*** + ossim_uint32 ux = static_cast<ossim_uint32>(x - theOrigin.x); + ossim_uint32 uy = static_cast<ossim_uint32>(y - theOrigin.y); + + ossim_uint32 offset = uy * theSpatialExtents[0] + ux; + + for(ossim_uint32 band = 0; band < theNumberOfDataComponents; ++band) + { + ossim_uint8* buf = getUcharBuf(band)+offset; + *buf = (ossim_uint8)color; + } + } +} + +void ossimU8ImageData::fill(ossim_uint32 band, double value) +{ + void* s = getBuf(band); + + if (s == NULL) return; // nothing to do... + + ossim_uint32 size_in_pixels = getSizePerBand(); + ossim_uint8* p = getUcharBuf(band); + ossim_uint8 np = static_cast<ossim_uint8>(value); + + for (ossim_uint32 i=0; i<size_in_pixels; ++i) p[i] = np; + + // Set the status to unknown since we don't know about the other bands. + setDataObjectStatus(OSSIM_STATUS_UNKNOWN); +} + + +bool ossimU8ImageData::isNull(ossim_uint32 offset)const +{ + for(ossim_uint32 band = 0; band < getNumberOfBands(); ++band) + { + const ossim_uint8* buf = getUcharBuf(band)+offset; + + if((*buf) != theNullPixelValue[band]) + { + return false; + } + } + + return true; +} + +void ossimU8ImageData::setNull(ossim_uint32 offset) +{ + for(ossim_uint32 band = 0; band < getNumberOfBands(); ++band) + { + ossim_uint8* buf = (getUcharBuf(band))+offset; + *buf = (ossim_uint8)theNullPixelValue[band]; + } +} + +void ossimU8ImageData::loadBand(const void* src, + const ossimIrect& src_rect, + ossim_uint32 band) +{ + ossimImageData::loadBand(ossim_uint8(0), src, src_rect, band); +} + +void ossimU8ImageData::loadTile(void* src, + const ossimIrect& src_rect, + ossimInterleaveType il_type) +{ + // Load the tile from the buffer. + switch (il_type) + { + case OSSIM_BIP: + ossimImageData::loadTileFromBip(ossim_uint8(0), src, src_rect); + break; + case OSSIM_BIL: + ossimImageData::loadTileFromBil(ossim_uint8(0), src, src_rect); + break; + case OSSIM_BSQ: + ossimImageData::loadTileFromBsq(ossim_uint8(0), src, src_rect); + break; + default: + ossimNotify(ossimNotifyLevel_WARN) + << "ossimU8ImageData::loadTile" + << "\nUnknown interleave type passed to method. Returning..." + << endl; + break; + } +} + +void ossimU8ImageData::unloadBand(void* dest, + const ossimIrect& dest_rect, + ossim_uint32 band) const +{ + ossimImageData::unloadBand(ossim_uint8(0), dest, dest_rect, + getImageRectangle(), band); +} + +void ossimU8ImageData::copyTileToNormalizedBuffer(double* buf) const +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU8ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + ossim_uint32 size = getSizePerBand(); + if(!getBuf()) + { + memset(buf, '\0', size); + return; + } + + if(size > 0) + { + for(ossim_uint32 band = 0; band < getNumberOfBands(); ++band) + { + const ossim_uint8* s = getUcharBuf(band); // source + double* d = buf + (band*size); // destination + if(s&&d) + { + for(ossim_uint32 index = 0; index < size; ++index) + { + d[index] = theRemapTable. + normFromPix(static_cast<ossim_int32>(s[index])); + } + } + } + } +} + +void ossimU8ImageData::copyTileToNormalizedBuffer(float* buf) const +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU8ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + ossim_uint32 size = getSizePerBand(); + if(!getBuf()) + { + memset(buf, '\0', size); + return; + } + + if(size > 0) + { + for(ossim_uint32 band = 0; band < getNumberOfBands(); ++band) + { + const ossim_uint8* s = getUcharBuf(band); // source + float* d = buf + (band*size); // destination + if(s&&d) + { + for(ossim_uint32 index = 0; index < size; ++index) + { + d[index] = theRemapTable. + normFromPix(static_cast<ossim_int32>(s[index])); + } + } + } + } +} + +void ossimU8ImageData::copyTileToNormalizedBuffer(ossim_uint32 band, + double* buf) const +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU8ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + ossim_uint32 size = getSizePerBand(); + if(!getBuf(band)) + { + memset(buf, '\0', size); + return; + } + + if(size > 0) + { + const ossim_uint8* s = getUcharBuf(band); // source + double* d = buf; // destination + for(ossim_uint32 index = 0; index < size; ++index) + { + *d = theRemapTable. + normFromPix(static_cast<ossim_int32>(*s)); + ++d; + ++s; + } + } +} + +void ossimU8ImageData::copyTileToNormalizedBuffer(ossim_uint32 band, + float* buf) const +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU8ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + ossim_uint32 size = getSizePerBand(); + if(!getBuf(band)) + { + memset(buf, '\0', size); + return; + } + + if(size > 0) + { + const ossim_uint8* s = getUcharBuf(band); // source + float* d = buf; // destination + for(ossim_uint32 index = 0; index < size; ++index) + { + *d = theRemapTable. + normFromPix(static_cast<ossim_int32>(*s)); + ++d; + ++s; + } + } +} + +void ossimU8ImageData::copyNormalizedBufferToTile(double* buf) +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU8ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + if(!getBuf()) return; + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + for(ossim_uint32 band = 0; band < getNumberOfBands(); ++band) + { + double* s = buf + (band*size); // source + ossim_uint8* d = getUcharBuf(band); // destination + + for(ossim_uint32 index = 0; index < size; ++index) + { + d[index] = theRemapTable.pixFromNorm(s[index]); + } + } + } +} + +void ossimU8ImageData::copyNormalizedBufferToTile(float* buf) +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU8ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + if(!getBuf()) return; + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + for(ossim_uint32 band = 0; band < getNumberOfBands(); ++band) + { + float* s = buf + (band*size); // source + ossim_uint8* d = getUcharBuf(band); // destination + + for(ossim_uint32 index = 0; index < size; ++index) + { + d[index] = theRemapTable.pixFromNorm(s[index]); + } + } + } +} + +void ossimU8ImageData::copyNormalizedBufferToTile(ossim_uint32 band, + double* buf) +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU8ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + if(!getBuf(band)) return; + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + double* s = buf; // source + ossim_uint8* d = getUcharBuf(band); // destination + + for(ossim_uint32 index = 0; index < size; ++index) + { + d[index] = theRemapTable.pixFromNorm(s[index]); + } + } +} + +void ossimU8ImageData::copyNormalizedBufferToTile(ossim_uint32 band, + float* buf) +{ + if (!buf) + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "ossimU8ImageData::copyTileToNormalizedBuffer File %s line %d\nNull pointer passed to method!", + __FILE__, + __LINE__); + return; + } + if(!getBuf(band)) return; + ossim_uint32 size = getSizePerBand(); + + if(size > 0) + { + float* s = buf; // source + ossim_uint8* d = getUcharBuf(band); // destination + + for(ossim_uint32 index = 0; index < size; ++index) + { + d[index] = theRemapTable.pixFromNorm(s[index]); + } + } +} + + +const ossimU8ImageData& ossimU8ImageData::operator=( + const ossimU8ImageData& /* rhs */) +{ + return *this; +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/ossimU8ImageData.h b/Utilities/OSSIM/ossim_core/imaging/ossimU8ImageData.h new file mode 100644 index 0000000000..ad772cc4e0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/ossimU8ImageData.h @@ -0,0 +1,189 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Class declaration of ossimU8ImageData. Specialized image data object for +// unsigned char data. +// +// NOTE: This object is optimized for unsigned char data and assumes the +// following: null pixel value = 0.0 +// min pixel value = 1.0 +// max pixel value = 255.0 +// +// If you want anything else use the less efficient ossimImageData. +// +//************************************************************************* +// $Id: ossimU8ImageData.h,v 1.19 2005/07/23 15:54:50 dburken Exp $ + +#ifndef ossimU8ImageData_HEADER +#define ossimU8ImageData_HEADER + +#include "ossimImageData.h" +#include "imaging/remap_tables/ossimNormalizedU8RemapTable.h" + +class OSSIMDLLEXPORT ossimU8ImageData : public ossimImageData +{ +public: + ossimU8ImageData(ossimSource* source=NULL, + ossim_uint32 bands = 1); + + ossimU8ImageData(ossimSource* source, + ossim_uint32 bands, + ossim_uint32 width, + ossim_uint32 height); + + ossimU8ImageData(const ossimU8ImageData& rhs) + :ossimImageData(rhs) + {} + + virtual ~ossimU8ImageData(); + + virtual ossimObject* dup()const; + + /*! + * will fill the entire band with + * the value. + */ + void fill(ossim_uint32 band, double value); + void fill(double value); + + bool isNull(ossim_uint32 offset)const; + void setNull(ossim_uint32 offset); + + virtual ossimDataObjectStatus validate() const; + + /*! + * will go to the band and offset and compute the + * normalized float and return it back to the + * caller through the result argument. + */ + virtual void getNormalizedFloat(ossim_uint32 offset, + ossim_uint32 bandNumber, + float& result)const; + + /*! + * This will assign to this object a normalized + * value by unnormalizing to its native type. + */ + virtual void setNormalizedFloat(ossim_uint32 offset, + ossim_uint32 bandNumber, + float input); + + /*! + * Will use the memory that you pass in to normalize + * this data object. + */ + virtual void convertToNormalizedFloat(ossimImageData* result)const; + + /*! + * Will use the memory that you pass in to normalize + * this data object. + */ + virtual void convertToNormalizedDouble(ossimImageData* result)const; + + /*! + * Will take the normalized input and convert it + * to this tile's data type. Example: if this + * tile is of type UCHAR and its input is of type + * NORALIZED_FLOAT it will unnormalize the data by + * doing: + * + * minPix + normalizedInput*(maxPix-minPix) + * + * on a per band basis. + */ + virtual void unnormalizeInput(ossimImageData* normalizedInput); + + /*! + * This will compute the average value for the band. + */ + virtual double computeAverageBandValue(ossim_uint32 bandNumber = 0); + + /*! + * This will call the compute average band value and then + * use that in the calculation of: + + * It will then do a SUM[(Mean - Actual)^2]/width*height. + * + * This is the average variance from the passed in + * mean. Basically think of the mean as a completely + * grey image and we would like to see how this + * image varies from the passed in mean. + */ + virtual double computeMeanSquaredError(double meanValue, + ossim_uint32 bandNumber = 0); + + virtual void populateHistogram(ossimMultiBandHistogram* histo); + + /*! + * Initializes data to null pixel values. + */ + virtual void makeBlank(); + + virtual void setValue(ossim_int32 x, ossim_int32 y, double color); + + virtual void loadBand(const void* src, + const ossimIrect& src_rect, + ossim_uint32 band); + + virtual void loadTile(void* src, + const ossimIrect& src_rect, + ossimInterleaveType il_type); + + virtual void unloadBand(void* dest, + const ossimIrect& dest_rect, + ossim_uint32 band) const; + + /*! + * Copies entire tile to buf passed in. Data put in buf is normalized. + * The "buf" passed to method is assumed to be at least as big as: + * "getSize() * sizeof(double)" + */ + virtual void copyTileToNormalizedBuffer(double* buf) const; + virtual void copyTileToNormalizedBuffer(float* buf) const; + + /*! + * Will copy this tiles specified band number to the normalized buffer. + * if the band is out of range then nothing is done and returns. + */ + virtual void copyTileToNormalizedBuffer(ossim_uint32 band, double* buf) const; + virtual void copyTileToNormalizedBuffer(ossim_uint32 band, float* buf)const; + + /*! + * Copies buf passed in to tile. Data is unnormalized to the tile's + * scalar type. + * The "buf" passed to method is assumed to be at least as big as the tiles: + * "getSize() * sizeof(double)" + */ + virtual void copyNormalizedBufferToTile(double* buf); + virtual void copyNormalizedBufferToTile(float* buf); + + /*! + * Will copy the normalized buffer to this tiles + * specified band. If band is out of range then nothing + * is done and returns. + */ + virtual void copyNormalizedBufferToTile(ossim_uint32 band, + double* buf); + virtual void copyNormalizedBufferToTile(ossim_uint32 band, + float* buf); + + virtual ossim_float64 getMinNormalizedPix() const { return theRemapTable[1]; } + +private: + + const ossimU8ImageData& operator =(const ossimU8ImageData &rhs); + + static const ossimNormalizedU8RemapTable theRemapTable; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/patch/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/patch/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/patch/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/imaging/patch/ossimTilePatch.cpp b/Utilities/OSSIM/ossim_core/imaging/patch/ossimTilePatch.cpp new file mode 100644 index 0000000000..a78765b3e6 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/patch/ossimTilePatch.cpp @@ -0,0 +1,518 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimTilePatch.cpp,v 1.36 2005/02/11 15:07:32 dburken Exp $ + +#include <vector> +using namespace std; + +#include <imaging/patch/ossimTilePatch.h> +#include <imaging/ossimImageData.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <imaging/ossimImageSource.h> +#include <base/common/ossimErrorCodes.h> +ossimDiscreteNearestNeighbor ossimTilePatch::nearestNeighborKernel; + +ossimTilePatch::ossimTilePatch(ossimImageSourceInterface* input) +{ + thePatchData = ossimImageDataFactory::instance()->create(NULL, input); + thePatchData->initialize(); +} + +ossimTilePatch::ossimTilePatch(ossimScalarType scalarType, + long numberOfComponents, + long width, + long height) + :thePatchData(NULL) +{ + thePatchData = ossimImageDataFactory::instance()->create(NULL, + scalarType, + numberOfComponents, + width, + height); + + thePatchData->initialize(); +} + +ossimTilePatch::~ossimTilePatch() +{ +} + +ossimIrect ossimTilePatch::getRect()const +{ + return thePatchData->getImageRectangle(); +} + +ossimDrect ossimTilePatch::findBoundingRect(const ossimDpt &p1, + const ossimDpt &p2, + const ossimDpt &p3, + const ossimDpt &p4) +{ + vector<ossimDpt> points(4); + + points[0] = p1; + points[1] = p2; + points[2] = p3; + points[3] = p4; + + return ossimDrect(points); +} + +void ossimTilePatch::fillPatch(ossimImageSourceInterface* tileSource, + long resLevel) +{ + // long w = tileSource->getTileWidth(); + // long h = tileSource->getTileHeight(); + + if(thePatchData.valid()) + { + ossimIrect rect = thePatchData->getImageRectangle(); + thePatchData->makeBlank(); + // ossimIpt origin(rect.ul()); + ossimRefPtr<ossimImageData> aTile = tileSource->getTile(rect, resLevel); + thePatchData->loadTile(aTile.get()); + } +} + +void ossimTilePatch::setData(ossimRefPtr<ossimImageData>& patchData) +{ + thePatchData = patchData; +} + +void ossimTilePatch::convolve(ossimDiscreteConvolutionKernel* kernel) +{ + if(!kernel) return; + + long w = thePatchData->getWidth(); + long h = thePatchData->getHeight(); + + long kW = kernel->getWidth(); + long kH = kernel->getHeight(); + ossimIpt origin = thePatchData->getOrigin(); + + if( (w < kW) || (h < kH)) + { + cerr << " Error ossimTilePatch::convolve(kernel): patch is smaller than kernel size" << endl; + return; + } + ossimRefPtr<ossimImageData> kernelBuffer =(ossimImageData*) thePatchData->dup(); + + // now let's make the buffer just fit the convolution filter + // + kernelBuffer->setWidth(w - kW); + kernelBuffer->setHeight(h - kH); + kernelBuffer->setOrigin(ossimDpt(origin.x + kW/2.0, + origin.y + kH/2.0)); + kernelBuffer->initialize(); + + fillTile(kernelBuffer, kernel); + + kernelBuffer->validate(); + // now copy the data back to the buffer + // + thePatchData->loadTile(kernelBuffer.get()); + + // now make sure we validate the buffer. + thePatchData->validate(); +} + +void ossimTilePatch::fillTile(ossimRefPtr<ossimImageData>& aTile)const +{ + if(aTile.valid() && + (aTile->getNumberOfBands()==thePatchData->getNumberOfBands())&& + (aTile->getBuf())&& + (thePatchData->getBuf())&& + (thePatchData->getScalarType()==aTile->getScalarType())) + { + aTile->loadTile(thePatchData.get()); + } +} + +void ossimTilePatch::fillTile(ossimRefPtr<ossimImageData>& result, + ossimDiscreteConvolutionKernel* kernel)const +{ + if(!kernel) + { + cerr << "Error: Kernel is NULL in ossimTilePatch::fillTile(tile, kernel)!!" << endl; + } + if(thePatchData->getScalarType() != result->getScalarType()) + { + //ERROR + return; + } + else + { + switch(thePatchData->getScalarType()) + { + case OSSIM_UCHAR: + { + fillTileTemplate(static_cast<ossim_uint8>(0), + result, + kernel); + break; + } + case OSSIM_USHORT16: + case OSSIM_USHORT11: + { + fillTileTemplate(static_cast<ossim_uint16>(0), + result, + kernel); + break; + } + case OSSIM_SSHORT16: + { + fillTileTemplate(static_cast<ossim_sint16>(0), + result, + kernel); + break; + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + fillTileTemplate(static_cast<float>(0), + result, + kernel); + break; + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + fillTileTemplate(static_cast<double>(0), + result, + kernel); + break; + } + default: + { + ossimSetError("ossimTilePatch", + ossimErrorCodes::OSSIM_ERROR, + "unhandled scalar type %d", + (int)thePatchData->getScalarType()); + break; + } + } + } +} + + + +void ossimTilePatch::fillTile(ossimRefPtr<ossimImageData>& result, + const ossimDpt &ul, + const ossimDpt &ur, + const ossimDpt &deltaUl, + const ossimDpt &deltaUr, + const ossimDpt &length)const +{ + result->setNullPix(thePatchData->getNullPix(), thePatchData->getNumberOfBands()); + result->setMinPix(thePatchData->getMinPix(), thePatchData->getNumberOfBands()); + result->setMaxPix(thePatchData->getMaxPix(), thePatchData->getNumberOfBands()); + result->makeBlank(); + if(thePatchData->getScalarType() != result->getScalarType()) + { + //ERROR + return; + } + else + { + switch(thePatchData->getScalarType()) + { + case OSSIM_UCHAR: + { + fillTileTemplate(static_cast<ossim_uint8>(0), + result, + ul, + ur, + deltaUl, + deltaUr, + length); + break; + } + case OSSIM_USHORT16: + case OSSIM_USHORT11: + { + fillTileTemplate(static_cast<ossim_uint16>(0), + result, + ul, + ur, + deltaUl, + deltaUr, + length); + break; + } + case OSSIM_SSHORT16: + { + fillTileTemplate(static_cast<ossim_sint16>(0), + result, + ul, + ur, + deltaUl, + deltaUr, + length); + break; + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + fillTileTemplate(static_cast<float>(0), + result, + ul, + ur, + deltaUl, + deltaUr, + length); + break; + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + fillTileTemplate(static_cast<double>(0), + result, + ul, + ur, + deltaUl, + deltaUr, + length); + break; + } + default: + { + ossimSetError("ossimTilePatch", + ossimErrorCodes::OSSIM_ERROR, + "unhandled scalar type %d", + (int)thePatchData->getScalarType()); + break; + } + } + } + +} + + +template<class T> +void ossimTilePatch::fillTileTemplate(T dummyVariable, + ossimRefPtr<ossimImageData>& result, + ossimDiscreteConvolutionKernel* kernel)const +{ + // get the origin. The convolution could be + // an offset into the patch. + // + ossimIpt startOrigin = result->getOrigin(); + + // Make sure that the patch is not empty or NULL + // + ossimDataObjectStatus status = thePatchData->getDataObjectStatus(); + if((status==OSSIM_EMPTY)|| + (status == OSSIM_NULL)) + { + return; + } + ossimDpt startDelta(fabs((double)startOrigin.x - thePatchData->getOrigin().x), + fabs((double)startOrigin.y - thePatchData->getOrigin().y)); + + // let's setup some variables that we will need to do the + // convolution algorithm. + // + ossimIrect patchRect = thePatchData->getImageRectangle(); + long tileHeight = result->getHeight(); + long tileWidth = result->getWidth(); + long outputBands = result->getNumberOfBands(); + long convolutionWidth = kernel->getWidth(); + long convolutionHeight = kernel->getHeight(); + long convolutionOffsetX= convolutionWidth/2; + long convolutionOffsetY= convolutionHeight/2; + long patchWidth = patchRect.width(); + long patchCenterOffset = (long)(patchWidth*startDelta.y + startDelta.x); + long patchConvolutionOffsetDelta = patchWidth*convolutionOffsetY + convolutionOffsetX; + long patchLineStartOffset = patchCenterOffset - patchConvolutionOffsetDelta; + long outputOffset = 0; + double min = 1.0; + double max = 255.0; + if(status == OSSIM_PARTIAL) // must check for NULLS + { + for(long y = 0; y <tileHeight; y++) + { + patchCenterOffset = patchLineStartOffset; + + for(long x =0; x < tileWidth; x++) + { + if(!thePatchData->isNull(patchCenterOffset)) + { + double convolveResult = 0; + for(long b = 0; b < outputBands; ++b) + { + min=result->getMinPix(b); + max=result->getMaxPix(b); + T* buf = (T*)(thePatchData->getBuf(b)) + patchCenterOffset; + T* outBuf = (T*)(result->getBuf(b)); + + kernel->convolveSubImage(buf, + patchWidth, + convolveResult); + convolveResult = convolveResult < min?min:convolveResult; + convolveResult = convolveResult > max?max:convolveResult; + outBuf[outputOffset] = (ossim_uint8)convolveResult; + } + } + else + { + result->setNull(outputOffset); + } + ++outputOffset; + ++patchCenterOffset; + } + patchLineStartOffset += patchWidth; + } + } + else + { + for(long b = 0; b < outputBands; ++b) + { + double convolveResult = 0; + const T* buf = (const T*)thePatchData->getBuf(b); + T* outBuf = (T*)(result->getBuf(b)); + outputOffset = 0; + patchCenterOffset = (long)(patchWidth*startDelta.y + startDelta.x); + patchLineStartOffset = patchCenterOffset - patchConvolutionOffsetDelta; + min=result->getMinPix(b); + max=result->getMaxPix(b); + + for(long y = 0; y <tileHeight; y++) + { + patchCenterOffset = patchLineStartOffset; + + for(long x =0; x < tileWidth; x++) + { + kernel->convolveSubImage(&buf[patchCenterOffset], + patchWidth, + convolveResult); + convolveResult = convolveResult < min? min:convolveResult; + convolveResult = convolveResult > max?max:convolveResult; + outBuf[outputOffset] = (T)convolveResult; + ++outputOffset; + ++patchCenterOffset; + } + patchLineStartOffset += patchWidth; + } + } + } +} + + +template <class T> +void ossimTilePatch::fillTileTemplate(T dummyVariable, + ossimRefPtr<ossimImageData>& result, + const ossimDpt &ul, + const ossimDpt &ur, + const ossimDpt &deltaUl, + const ossimDpt &deltaUr, + const ossimDpt &length)const +{ + double stepSizeWidth = 1.0/length.x; + double stepSizeHeight = 1.0/length.y; + long patchWidth = thePatchData->getWidth(); + long patchHeight = thePatchData->getHeight(); + + + ossimIrect rect = thePatchData->getImageRectangle(); + + ossimDpt startSave(ul.x - rect.ul().x, + ul.y - rect.ul().y ); + ossimDpt endSave(ur.x - rect.ul().x, + ur.y - rect.ul().y); + for(ossim_uint32 band = 0; band < thePatchData->getNumberOfBands(); ++band) + { + T *resultBuf = (T*)result->getBuf(band); + const T *sourceBuf = (T*)thePatchData->getBuf(band); + ossimDpt start = startSave; + ossimDpt end = endSave; + T nullPix = static_cast<T>(result->getNullPix(band)); + for(long y = 0; y < length.y; y++) + { + double deltaX = (end.x - start.x)*stepSizeWidth; + double deltaY = (end.y - start.y)*stepSizeHeight; + ossimDpt pointXY = start; + for(long x = 0; x < length.x; x++) + { + int xPixel = pointXY.x<0?(int)floor(pointXY.x):(int)pointXY.x; + int yPixel = pointXY.y<0?(int)floor(pointXY.y):(int)pointXY.y; + if( (xPixel >=0) && (xPixel < patchWidth) && + (yPixel >=0) && (yPixel < patchHeight)) + { + *resultBuf = sourceBuf[yPixel*patchWidth + xPixel]; + } + else + { + *resultBuf = nullPix; + } + + resultBuf++; + pointXY.y += deltaY; + pointXY.x += deltaX; + } + + start.x += deltaUl.x; + start.y += deltaUl.y; + end.x += deltaUr.x; + end.y += deltaUr.y; + } + } +} + + +void ossimTilePatch::setRect(const ossimDpt &p1, + const ossimDpt &p2, + const ossimDpt &p3, + const ossimDpt &p4, + const ossimDpt &tile_size, + const ossimDpt &padding) +{ + setRect(findBoundingRect(p1, p2, p3, p4), + tile_size, + padding); +} + +void ossimTilePatch::setRect(const ossimDpt ¢er, + const ossimDpt &rect_size, + const ossimDpt &tile_size, + const ossimDpt &padding) +{ + ossimDpt ul (center - rect_size/2.0); + ossimDpt lr (center + rect_size/2.0); + ossimDrect rect (ul, lr); + setRect(rect, tile_size, padding); +} + +void ossimTilePatch::setRect(const ossimDrect &aRect, + const ossimDpt &tile_size, + const ossimDpt &padding) +{ + ossimDpt ul(aRect.ul().x - padding.x, + aRect.ul().y - padding.y); + ossimDpt lr(aRect.lr().x + padding.x, + aRect.lr().y + padding.y); + + ossimDrect rect(ul, lr); + rect.stretchOut(); + +// rect = alignRectToBoundary(rect, tile_size); + + if(thePatchData.valid()) + { + if( ((long)thePatchData->getWidth() != (long)rect.width()) || + ((long)thePatchData->getHeight() != (long)rect.height())) + { + thePatchData->setWidth((long)rect.width()); + thePatchData->setHeight((long)rect.height()); + } + thePatchData->setOrigin(rect.ul()); + thePatchData->initialize(); + } +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/patch/ossimTilePatch.h b/Utilities/OSSIM/ossim_core/imaging/patch/ossimTilePatch.h new file mode 100644 index 0000000000..ce0beafaf5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/patch/ossimTilePatch.h @@ -0,0 +1,135 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimTilePatch.h,v 1.24 2005/02/18 15:59:25 dburken Exp $ + +#ifndef ossimTilePatch_HEADER +#define ossimTilePatch_HEADER +#include <base/common/ossimObject.h> +#include <base/common/ossimRefPtr.h> +#include <base/data_types/ossimIrect.h> +#include <base/data_types/ossimDrect.h> +#include <imaging/filters/ossimDiscreteNearestNeighbor.h> +#include <imaging/ossimImageData.h> + +class ossimImageSourceInterface; + +class ossimTilePatch : public ossimObject +{ +public: + ossimTilePatch(ossimImageSourceInterface* input); + /*! + * The rect is assumed up right and all we need + * to do is compute the even tile boundary rect + */ + ossimTilePatch(ossimScalarType scalarType = OSSIM_UCHAR, + long numberOfComponents = 1, + long width=128, + long height=128); + virtual ~ossimTilePatch(); + + /*! + * return the tile boundary aligned rectangle for this + * patch. + */ + virtual ossimIrect getRect()const; + + /*! + * The padding is for any convolution that must take + * place. + */ + virtual void setRect(const ossimDpt &p1, + const ossimDpt &p2, + const ossimDpt &p3, + const ossimDpt &p4, + const ossimDpt &tile_size, + const ossimDpt &padding=ossimDpt(0,0)); + + virtual void setRect(const ossimDrect &aRect, + const ossimDpt &tile_size, + const ossimDpt &padding=ossimDpt(0,0)); + + virtual void setRect(const ossimDpt ¢er_of_rect, + const ossimDpt &rect_size, + const ossimDpt &tile_size, + const ossimDpt &padding=ossimDpt(0,0)); + + /*! + * This will fill the tile from the tile patch. + */ + virtual void fillTile(ossimRefPtr<ossimImageData>& aTile)const; + + /*! + * This will fill the tile from the tile patch and apply the convolution + * kernel. This is optimized for upright rectangles. Use the bilinear + * fill tile bellow for arbitrary 4-sided polygons. + */ + virtual void fillTile(ossimRefPtr<ossimImageData>& result, + ossimDiscreteConvolutionKernel* kernel)const; + + /*! + * We will assume that the patch is already + * big enough to satisfy the kernel size. + */ + virtual void fillTile(ossimRefPtr<ossimImageData>& result, + const ossimDpt &ul, + const ossimDpt &ur, + const ossimDpt &deltaUl, + const ossimDpt &deltaUr, + const ossimDpt &length)const; + + + virtual void fillPatch(ossimImageSourceInterface *imageSource, + long resLevel = 0); + + + +// static ossimIrect alignRectToBoundary(const ossimDrect &aRect, +// const ossimDpt &tile_size); + static ossimDrect findBoundingRect(const ossimDpt &p1, + const ossimDpt &p2, + const ossimDpt &p3, + const ossimDpt &p4); + /*! + * Do not delete this data. We give raw access to the buffer + * if there are special things you wish to have done. + */ + ossimRefPtr<ossimImageData> getData(){return thePatchData;} + + void setData(ossimRefPtr<ossimImageData>& patchData); + /*! + * This will implement an in place convolution. It will + * allocate a buffer pass it to the convolution algorithm + * and then replace the internal buffer. + */ + void convolve(ossimDiscreteConvolutionKernel* kernel); + +protected: + ossimRefPtr<ossimImageData> thePatchData; + static ossimDiscreteNearestNeighbor nearestNeighborKernel; + + + + template<class T> + void fillTileTemplate(T dummyVariable, + ossimRefPtr<ossimImageData>& result, + const ossimDpt &ul, + const ossimDpt &ur, + const ossimDpt &deltaUl, + const ossimDpt &deltaUr, + const ossimDpt &length)const; + + template<class T> + void fillTileTemplate(T dummyVariable, + ossimRefPtr<ossimImageData>& result, + ossimDiscreteConvolutionKernel* kernel)const; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/reconstruction/ossimMeanMedianFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/reconstruction/ossimMeanMedianFilter.cpp new file mode 100644 index 0000000000..e50a11ee83 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/reconstruction/ossimMeanMedianFilter.cpp @@ -0,0 +1,929 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimMeanMedianFilter.cpp,v 1.11 2005/05/22 13:33:12 dburken Exp $ + +#include <vector> +#include <algorithm> +#include <numeric> +using namespace std; + +#include <imaging/reconstruction/ossimMeanMedianFilter.h> +#include <base/property/ossimNumericProperty.h> +#include <base/property/ossimBooleanProperty.h> +#include <base/property/ossimStringProperty.h> + +RTTI_DEF1(ossimMeanMedianFilter, + "ossimMeanMedianFilter", + ossimImageSourceFilter); + +// Keywords used throughout. +static const ossimString WINDOW_SIZE_KW = "window_size"; +static const ossimString FILTER_TYPE_KW = "filter_type"; +static const ossimString AUTO_GROW_KW = "auto_grow_rectangle_flag"; + +ossimMeanMedianFilter::ossimMeanMedianFilter(ossimObject* owner) + :ossimImageSourceFilter(owner), + theTile(0), + theFilterType(OSSIM_MEDIAN), + theWindowSize(3), + theEnableFillNullFlag(false), + theAutoGrowRectFlag(false) +{ + setDescription(ossimString("Mean Median Filter")); +} + +ossimMeanMedianFilter::~ossimMeanMedianFilter() +{ +} + +ossimRefPtr<ossimImageData> ossimMeanMedianFilter::getTile( + const ossimIrect& rect, ossim_uint32 resLevel) +{ + if(!isSourceEnabled()) + { + return ossimImageSourceFilter::getTile(rect, resLevel); + } + + ossim_uint32 halfSize = getWindowSize()>>1; + + ossimIrect requestRect(rect.ul().x - halfSize, + rect.ul().y - halfSize, + rect.lr().x + halfSize, + rect.lr().y + halfSize); + + ossimRefPtr<ossimImageData> inputData = + ossimImageSourceFilter::getTile(requestRect, resLevel); + if(!inputData.valid() || !inputData->getBuf()) + { + return inputData; + } + + if(!theTile.valid()) + { + theTile = (ossimImageData*)inputData->dup(); + theTile->setImageRectangle(rect); + } + else + { + theTile->setImageRectangleAndBands(rect, inputData->getNumberOfBands()); + } + + applyFilter(inputData); + + theTile->setDataObjectStatus(inputData->getDataObjectStatus()); + if(theEnableFillNullFlag) + { + theTile->validate(); + } + + return theTile; +} + +void ossimMeanMedianFilter::setWindowSize(ossim_uint32 windowSize) +{ + theWindowSize = windowSize; +} + +ossim_uint32 ossimMeanMedianFilter::getWindowSize()const +{ + return theWindowSize; +} + +void ossimMeanMedianFilter::initialize() +{ + ossimImageSourceFilter::initialize(); + + theTile = NULL; +} + +void ossimMeanMedianFilter::applyFilter(ossimRefPtr<ossimImageData>& input) +{ + switch(input->getScalarType()) + { + case OSSIM_UINT8: + { + switch (theFilterType) + { + case OSSIM_MEDIAN: + case OSSIM_MEDIAN_FILL_NULLS: + applyMedian(ossim_uint8(0), input); + break; + + case OSSIM_MEDIAN_NULL_CENTER_ONLY: + applyMedianNullCenterOnly(ossim_uint8(0), input); + break; + + case OSSIM_MEAN: + case OSSIM_MEAN_FILL_NULLS: + applyMean(ossim_uint8(0), input); + break; + + case OSSIM_MEAN_NULL_CENTER_ONLY: + applyMeanNullCenterOnly(ossim_uint8(0), input); + + default: + break; + } + break; + } + case OSSIM_USHORT11: + case OSSIM_UINT16: + { + switch (theFilterType) + { + case OSSIM_MEDIAN: + case OSSIM_MEDIAN_FILL_NULLS: + applyMedian(ossim_uint16(0), input); + break; + + case OSSIM_MEDIAN_NULL_CENTER_ONLY: + applyMedianNullCenterOnly(ossim_uint16(0), input); + break; + + case OSSIM_MEAN: + case OSSIM_MEAN_FILL_NULLS: + applyMean(ossim_uint16(0), input); + break; + + case OSSIM_MEAN_NULL_CENTER_ONLY: + applyMeanNullCenterOnly(ossim_uint16(0), input); + break; + + default: + break; + } + break; + } + case OSSIM_SINT16: + { + switch (theFilterType) + { + case OSSIM_MEDIAN: + case OSSIM_MEDIAN_FILL_NULLS: + applyMedian(ossim_sint16(0), input); + break; + + case OSSIM_MEDIAN_NULL_CENTER_ONLY: + applyMedianNullCenterOnly(ossim_sint16(0), input); + break; + + case OSSIM_MEAN: + case OSSIM_MEAN_FILL_NULLS: + applyMean(ossim_sint16(0), input); + break; + + case OSSIM_MEAN_NULL_CENTER_ONLY: + applyMeanNullCenterOnly(ossim_sint16(0), input); + break; + + default: + break; + } + break; + } + case OSSIM_UINT32: + { + switch (theFilterType) + { + case OSSIM_MEDIAN: + case OSSIM_MEDIAN_FILL_NULLS: + applyMedian(ossim_uint32(0), input); + break; + + case OSSIM_MEDIAN_NULL_CENTER_ONLY: + applyMedianNullCenterOnly(ossim_uint32(0), input); + break; + + case OSSIM_MEAN: + case OSSIM_MEAN_FILL_NULLS: + applyMean(ossim_uint32(0), input); + break; + + case OSSIM_MEAN_NULL_CENTER_ONLY: + applyMeanNullCenterOnly(ossim_uint32(0), input); + break; + + default: + break; + } + } + case OSSIM_FLOAT32: + case OSSIM_NORMALIZED_FLOAT: + { + switch (theFilterType) + { + case OSSIM_MEDIAN: + case OSSIM_MEDIAN_FILL_NULLS: + applyMedian(ossim_float32(0.0), input); + break; + + case OSSIM_MEDIAN_NULL_CENTER_ONLY: + applyMedianNullCenterOnly(ossim_float32(0.0), input); + break; + + case OSSIM_MEAN: + case OSSIM_MEAN_FILL_NULLS: + applyMean(ossim_float32(0.0), input); + break; + + case OSSIM_MEAN_NULL_CENTER_ONLY: + applyMeanNullCenterOnly(ossim_float32(0.0), input); + break; + + default: + break; + } + break; + } + case OSSIM_FLOAT64: + case OSSIM_NORMALIZED_DOUBLE: + { + switch (theFilterType) + { + case OSSIM_MEDIAN: + case OSSIM_MEDIAN_FILL_NULLS: + applyMedian(ossim_float64(0.0), input); + break; + + case OSSIM_MEDIAN_NULL_CENTER_ONLY: + applyMedianNullCenterOnly(ossim_float64(0.0), input); + break; + + case OSSIM_MEAN: + case OSSIM_MEAN_FILL_NULLS: + applyMean(ossim_float64(0.0), input); + break; + + case OSSIM_MEAN_NULL_CENTER_ONLY: + applyMeanNullCenterOnly(ossim_float64(0.0), input); + break; + + default: + break; + } + break; + } + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimMeanMedianFilter::applyFilter WARNING:\n" + << "Unhandled scalar type!" << endl; + } + } +} + +template <class T> +void ossimMeanMedianFilter::applyMean(T dummyVariable, + ossimRefPtr<ossimImageData>& inputData) +{ + ossim_uint32 halfWindow = (theWindowSize >> 1); + ossim_uint32 bandIdx = 0; + ossim_uint32 x = 0; + ossim_uint32 y = 0; + ossim_uint32 kernelX = 0; + ossim_uint32 kernelY = 0; + ossim_uint32 kernelIdx = 0; + ossim_uint32 iw = inputData->getWidth(); + ossim_uint32 ow = theTile->getWidth(); + ossim_uint32 oh = theTile->getHeight(); + ossim_uint32 numberOfBands = ossimMin(theTile->getNumberOfBands(), + inputData->getNumberOfBands()); + ossimDataObjectStatus status = inputData->getDataObjectStatus(); + std::vector<double> values(theWindowSize*theWindowSize); + + if(status == OSSIM_FULL) + { + for(bandIdx = 0; bandIdx < numberOfBands; ++bandIdx) + { + T* inputBuf = (T*)inputData->getBuf(bandIdx); + T* outputBuf = (T*)theTile->getBuf(bandIdx); + + if(inputBuf&&outputBuf) + { + for(y = 0; y < oh; ++y) + { + for(x = 0; x < ow; ++x) + { + kernelIdx = 0; + for(kernelY = 0; kernelY < theWindowSize; ++kernelY) + { + for(kernelX = 0; kernelX < theWindowSize;++kernelX) + { + values[kernelIdx] = *(inputBuf+kernelX + kernelY*iw); + ++kernelIdx; + } + } + + + if(values.size() > 0) + { + double sum = std::accumulate(values.begin(), + values.end(), + 0.0); + double average = sum/(double)values.size(); + (*outputBuf) = (T)average; + } + ++inputBuf; + ++outputBuf; + } + + inputBuf+=(halfWindow<<1); + } + } + } + } + else + { + for(bandIdx = 0; bandIdx < numberOfBands; ++bandIdx) + { + T* inputBuf = (T*)inputData->getBuf(bandIdx); + T* outputBuf = (T*)theTile->getBuf(bandIdx); + T np = (T)inputData->getNullPix(bandIdx); + if(inputBuf&&outputBuf) + { + for(y = 0; y < oh; ++y) + { + for(x = 0; x < ow; ++x) + { + values.clear(); + for(kernelY = 0; kernelY < theWindowSize; ++kernelY) + { + for(kernelX = 0; kernelX < theWindowSize;++kernelX) + { + T tempValue = *(inputBuf+kernelX + kernelY*iw); + + if(tempValue != np) + { + values.push_back((double)tempValue); + } + } + } + + + if(values.size() > 0) + { + double accumulate = std::accumulate(values.begin(), + values.end(), + 0.0); + double average = accumulate/(double)values.size(); + if(*(inputBuf+halfWindow + halfWindow*iw) == np) + { + if(theEnableFillNullFlag) + { + (*outputBuf) = (T)average; + } + else + { + (*outputBuf) = np; + } + } + else + { + (*outputBuf) = (T)average; + } + } + else + { + *outputBuf = np; + } + ++inputBuf; + ++outputBuf; + } + + inputBuf+=(halfWindow<<1); + } + } + } + } +} + +template <class T> void ossimMeanMedianFilter::applyMeanNullCenterOnly( + T dummyVariable, + ossimRefPtr<ossimImageData>& inputData) +{ + ossim_uint32 halfWindow = (theWindowSize >> 1); + ossim_uint32 bandIdx = 0; + ossim_uint32 x = 0; + ossim_uint32 y = 0; + ossim_uint32 kernelX = 0; + ossim_uint32 kernelY = 0; + ossim_uint32 iw = inputData->getWidth(); + ossim_uint32 ow = theTile->getWidth(); + ossim_uint32 oh = theTile->getHeight(); + ossim_uint32 numberOfBands = ossimMin(theTile->getNumberOfBands(), + inputData->getNumberOfBands()); + ossimDataObjectStatus status = inputData->getDataObjectStatus(); + std::vector<double> values; + + if(status == OSSIM_FULL) + { + // Nothing to do just copy the tile. + theTile->loadTile(inputData.get()); + } + else + { + // Partial tile with nulls in it. + for(bandIdx = 0; bandIdx < numberOfBands; ++bandIdx) + { + T* inputBuf = (T*)inputData->getBuf(bandIdx); + T* outputBuf = (T*)theTile->getBuf(bandIdx); + if (!inputBuf || !outputBuf) + { + return; // Shouldn't happen... + } + + const T NP = (T)inputData->getNullPix(bandIdx); + + for(y = 0; y < oh; ++y) + { + for(x = 0; x < ow; ++x) + { + // Get the center input pixel. + const T CP = *(inputBuf+halfWindow + halfWindow*iw); + if (CP == NP) + { + values.clear(); + for(kernelY = 0; kernelY < theWindowSize; ++kernelY) + { + for(kernelX = 0; kernelX < theWindowSize;++kernelX) + { + T tempValue = *(inputBuf+kernelX + kernelY*iw); + + if(tempValue != NP) + { + values.push_back((double)tempValue); + } + } + } + + if(values.size() > 0) + { + double accumulate = std::accumulate(values.begin(), + values.end(), + 0.0); + double average = accumulate/(double)values.size(); + (*outputBuf) = (T)average; + } + else + { + (*outputBuf) = NP; + } + + } + else // Center pixel (CP) not null. + { + (*outputBuf) = CP; + } + + // Move over... + ++inputBuf; + ++outputBuf; + + } // End of loop in x direction. + + // Move down... + inputBuf+=(halfWindow<<1); + + } // End of loop in y direction. + + } // End of band loop. + + } // End of else "partial tile" block. +} + +template <class T> +void ossimMeanMedianFilter::applyMedian(T dummyVariable, + ossimRefPtr<ossimImageData>& inputData) +{ + ossim_uint32 halfWindow = (theWindowSize >> 1); + ossim_uint32 bandIdx = 0; + ossim_uint32 x = 0; + ossim_uint32 y = 0; + ossim_uint32 kernelX = 0; + ossim_uint32 kernelY = 0; + ossim_uint32 kernelIdx = 0; + ossim_uint32 iw = inputData->getWidth(); + ossim_uint32 ow = theTile->getWidth(); + ossim_uint32 oh = theTile->getHeight(); + ossim_uint32 numberOfBands = ossimMin(theTile->getNumberOfBands(), + inputData->getNumberOfBands()); + ossimDataObjectStatus status = inputData->getDataObjectStatus(); + std::vector<T> values(theWindowSize*theWindowSize); + + if(status == OSSIM_FULL) + { + for(bandIdx = 0; bandIdx < numberOfBands; ++bandIdx) + { + T* inputBuf = (T*)inputData->getBuf(bandIdx); + T* outputBuf = (T*)theTile->getBuf(bandIdx); + + if(inputBuf&&outputBuf) + { + for(y = 0; y < oh; ++y) + { + for(x = 0; x < ow; ++x) + { + kernelIdx = 0; + for(kernelY = 0; kernelY < theWindowSize; ++kernelY) + { + for(kernelX = 0; kernelX < theWindowSize;++kernelX) + { + values[kernelIdx] = *(inputBuf+kernelX + kernelY*iw); + ++kernelIdx; + } + } + + std::sort(values.begin(), + values.end()); + + if(values.size() > 0) + { + (*outputBuf) = values[values.size()>>1]; + } + ++inputBuf; + ++outputBuf; + } + + inputBuf+=(halfWindow<<1); + } + } + } + } + else + { + for(bandIdx = 0; bandIdx < numberOfBands; ++bandIdx) + { + T* inputBuf = (T*)inputData->getBuf(bandIdx); + T* outputBuf = (T*)theTile->getBuf(bandIdx); + T np = (T)inputData->getNullPix(bandIdx); + if(inputBuf&&outputBuf) + { + for(y = 0; y < oh; ++y) + { + for(x = 0; x < ow; ++x) + { + values.clear(); + for(kernelY = 0; kernelY < theWindowSize; ++kernelY) + { + for(kernelX = 0; kernelX < theWindowSize;++kernelX) + { + T tempValue = *(inputBuf+kernelX + kernelY*iw); + + if(tempValue != np) + { + values.push_back(tempValue); + } + } + } + + std::sort(values.begin(), + values.end()); + + if(values.size() > 0) + { + if(*(inputBuf+halfWindow + halfWindow*iw) == np) + { + if(theEnableFillNullFlag) + { + (*outputBuf) = values[values.size()>>1]; + } + else + { + (*outputBuf) = np; + } + } + else + { + (*outputBuf) = values[values.size()>>1]; + } + } + else + { + *outputBuf = np; + } + ++inputBuf; + ++outputBuf; + } + + inputBuf+=(halfWindow<<1); + } + } + } + } +} + +template <class T> void ossimMeanMedianFilter::applyMedianNullCenterOnly ( + T dummyVariable, + ossimRefPtr<ossimImageData>& inputData) +{ + ossim_uint32 halfWindow = (theWindowSize >> 1); + ossim_uint32 bandIdx = 0; + ossim_uint32 x = 0; + ossim_uint32 y = 0; + ossim_uint32 kernelX = 0; + ossim_uint32 kernelY = 0; + ossim_uint32 iw = inputData->getWidth(); + ossim_uint32 ow = theTile->getWidth(); + ossim_uint32 oh = theTile->getHeight(); + ossim_uint32 numberOfBands = ossimMin(theTile->getNumberOfBands(), + inputData->getNumberOfBands()); + ossimDataObjectStatus status = inputData->getDataObjectStatus(); + std::vector<T> values; + + if(status == OSSIM_FULL) + { + // Nothing to do just copy the tile. + theTile->loadTile(inputData.get()); + } + else + { + // Partial tile with nulls in it. + for(bandIdx = 0; bandIdx < numberOfBands; ++bandIdx) + { + T* inputBuf = (T*)inputData->getBuf(bandIdx); + T* outputBuf = (T*)theTile->getBuf(bandIdx); + if (!inputBuf || !outputBuf) + { + return; // Shouldn't happen... + } + + const T NP = (T)inputData->getNullPix(bandIdx); + + for(y = 0; y < oh; ++y) + { + for(x = 0; x < ow; ++x) + { + // Get the center input pixel. + const T CP = *(inputBuf+halfWindow + halfWindow*iw); + if (CP == NP) + { + values.clear(); + for(kernelY = 0; kernelY < theWindowSize; ++kernelY) + { + for(kernelX = 0; kernelX < theWindowSize;++kernelX) + { + T tempValue = *(inputBuf+kernelX + kernelY*iw); + + if(tempValue != NP) + { + values.push_back(tempValue); + } + } + } + + std::sort(values.begin(), + values.end()); + + if(values.size() > 0) + { + (*outputBuf) = values[values.size()>>1]; + } + else + { + (*outputBuf) = NP; + } + } + else // Center pixel (CP) not null. + { + (*outputBuf) = CP; + } + + // Move over... + ++inputBuf; + ++outputBuf; + + } // End of loop in x direction. + + // Move down... + inputBuf+=(halfWindow<<1); + + } // End of loop in y direction. + + } // End of band loop. + + } // End of else "partial tile" block. +} + +void ossimMeanMedianFilter::setProperty(ossimRefPtr<ossimProperty> property) +{ + if(!property.valid()) + { + return; + } + + ossimString name = property->getName(); + + if (name == WINDOW_SIZE_KW) + { + theWindowSize = property->valueToString().toUInt32(); + } + else if (name == FILTER_TYPE_KW) + { + ossimString value = property->valueToString(); + setFilterType(value); + } + else if (name == AUTO_GROW_KW) + { + ossimString value; + property->valueToString(value); + setAutoGrowRectFlag(value.toBool()); + } + else + { + ossimImageSourceFilter::setProperty(property); + } +} + +ossimRefPtr<ossimProperty> ossimMeanMedianFilter::getProperty(const ossimString& name)const +{ + if (name == WINDOW_SIZE_KW) + { + ossimProperty* prop = + new ossimNumericProperty(WINDOW_SIZE_KW, + ossimString::toString(theWindowSize), + 3, + 25); + prop->setCacheRefreshBit(); + + return prop; + } + else if (name == FILTER_TYPE_KW) + { + std::vector<ossimString> constraintList; + getFilterTypeList(constraintList); + ossimString value = getFilterTypeString(); + ossimProperty* prop = new ossimStringProperty(FILTER_TYPE_KW, + value, + false, + constraintList); + prop->setCacheRefreshBit(); + + return prop; + } + else if (name == AUTO_GROW_KW) + { + ossimRefPtr<ossimProperty> p = new ossimBooleanProperty( + AUTO_GROW_KW, getAutoGrowRectFlag()); + p->setFullRefreshBit(); + return p; + } + return ossimImageSourceFilter::getProperty(name); +} + +void ossimMeanMedianFilter::getPropertyNames( + std::vector<ossimString>& propertyNames)const +{ + propertyNames.push_back(WINDOW_SIZE_KW); + propertyNames.push_back(FILTER_TYPE_KW); + propertyNames.push_back(AUTO_GROW_KW); + + ossimImageSourceFilter::getPropertyNames(propertyNames); +} + +bool ossimMeanMedianFilter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + WINDOW_SIZE_KW.c_str(), + theWindowSize, + true); + kwl.add(prefix, + FILTER_TYPE_KW.c_str(), + getFilterTypeString(), + true); + kwl.add(prefix, + AUTO_GROW_KW.c_str(), + (theAutoGrowRectFlag?"true":"false"), + true); + + return ossimImageSourceFilter::saveState(kwl, prefix); +} + +bool ossimMeanMedianFilter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* lookup = NULL; + + lookup = kwl.find(prefix, WINDOW_SIZE_KW.c_str()); + if(lookup) + { + theWindowSize = ossimString(lookup).toUInt32(); + } + + lookup = kwl.find(prefix, FILTER_TYPE_KW.c_str()); + if(lookup) + { + ossimString type = lookup; + setFilterType(type); + } + + lookup = kwl.find(prefix, AUTO_GROW_KW.c_str()); + if(lookup) + { + ossimString flag = lookup; + setAutoGrowRectFlag(flag.toBool()); + } + + return ossimImageSourceFilter::loadState(kwl, prefix); +} +void ossimMeanMedianFilter::setFilterType(ossimMeanMedianFilterType type) +{ + theFilterType = type; +} + +void ossimMeanMedianFilter::setFilterType(const ossimString& type) +{ + ossimString s = type; + s.downcase(); + + std::vector<ossimString> list; + getFilterTypeList(list); + + for (ossim_uint32 i = 0; i < list.size(); ++i) + { + if (s == list[i]) + { + theFilterType = static_cast<ossimMeanMedianFilterType>(i); + } + } + + if ( (theFilterType == OSSIM_MEDIAN_FILL_NULLS) || + (theFilterType == OSSIM_MEAN_FILL_NULLS) ) + { + theEnableFillNullFlag = true; + } + else + { + theEnableFillNullFlag = false; + } +} + +void ossimMeanMedianFilter::setAutoGrowRectFlag(bool flag) +{ + theAutoGrowRectFlag = flag; +} + +bool ossimMeanMedianFilter::getAutoGrowRectFlag() const +{ + return theAutoGrowRectFlag; +} + +ossimString ossimMeanMedianFilter::getFilterTypeString() const +{ + std::vector<ossimString> list; + getFilterTypeList(list); + return list[theFilterType]; +} + +void ossimMeanMedianFilter::getFilterTypeList( + std::vector<ossimString>& list) const +{ + list.resize(OSSIM_MEAN_NULL_CENTER_ONLY+1); + + list[0] = ossimString("median"); + list[1] = ossimString("median_fill_nulls"); + list[2] = ossimString("median_null_center_only"); + list[3] = ossimString("mean"); + list[4] = ossimString("mean_fill_nulls"); + list[5] = ossimString("mean_null_center_only"); +} + +ossimIrect ossimMeanMedianFilter::getBoundingRect(ossim_uint32 resLevel)const +{ + // Get the input rectangle. + ossimIrect rect = ossimImageSourceFilter::getBoundingRect(resLevel); + if (!theAutoGrowRectFlag || rect.hasNans()) + { + return rect; // Not in autogrow mode or no input connection yet... + } + + if ( (theFilterType == OSSIM_MEDIAN_FILL_NULLS) || + (theFilterType == OSSIM_MEDIAN_NULL_CENTER_ONLY) || + (theFilterType == OSSIM_MEAN_FILL_NULLS) || + (theFilterType == OSSIM_MEAN_NULL_CENTER_ONLY) ) + { + ossimIpt pt = rect.ul(); + const ossim_int32 HW = (theWindowSize >> 1); // half window size. + + // Adjust the upper left. + pt.x = pt.x-HW; + pt.y = pt.y-HW; + rect.set_ul(pt); + + // Adjust the lower right. + pt = rect.lr(); + pt.x = pt.x+HW; + pt.y = pt.y+HW; + rect.set_lr(pt); + } + + return rect; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/reconstruction/ossimMeanMedianFilter.h b/Utilities/OSSIM/ossim_core/imaging/reconstruction/ossimMeanMedianFilter.h new file mode 100644 index 0000000000..cdf007f467 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/reconstruction/ossimMeanMedianFilter.h @@ -0,0 +1,129 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimMeanMedianFilter.h,v 1.7 2005/04/26 19:37:08 dburken Exp $ +#ifndef ossimMeanMedianFilter_HEADER +#define ossimMeanMedianFilter_HEADER + +#include "imaging/tile_sources/ossimImageSourceFilter.h" + +/*! + * class ossimMeanMedianFilter + * + * Allows you to change between a median or mean filter. You can + * also specify a window size which the median or mean is computed and + * the center pixel is replaced. + * + */ +class ossimMeanMedianFilter : public ossimImageSourceFilter +{ +public: + + enum ossimMeanMedianFilterType + { + /** Applies filter to any non-null center pixel. */ + OSSIM_MEDIAN = 0, + + /** Applies filter to all pixels including null center pixels. */ + OSSIM_MEDIAN_FILL_NULLS = 1, + + /** Applies filter to only null center pixels. */ + OSSIM_MEDIAN_NULL_CENTER_ONLY = 2, + + /** Applies filter to any non-null center pixel. */ + OSSIM_MEAN = 3, + + /* Applies filter to all pixels including null center pixels. */ + OSSIM_MEAN_FILL_NULLS = 4, + + /** Applies filter to only null center pixels. */ + OSSIM_MEAN_NULL_CENTER_ONLY = 5 + }; + + ossimMeanMedianFilter(ossimObject* owner=NULL); + virtual ~ossimMeanMedianFilter(); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect, + ossim_uint32 resLevel=0); + virtual void initialize(); + + void setWindowSize(ossim_uint32 windowSize); + ossim_uint32 getWindowSize()const; + + /** + * @param flag Set "theAutoGrowRectFlag". This only affects filter types + * that set nulls. Will have a growing affect on the edges. + */ + void setAutoGrowRectFlag(bool flag); + bool getAutoGrowRectFlag() const; + + void setFilterType(ossimMeanMedianFilterType type); + void setFilterType(const ossimString& type); + ossimString getFilterTypeString() const; + void getFilterTypeList(std::vector<ossimString>& list) const; + + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + + /** + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * @return Returns the bounding rectangle which is the input bounding + * rectangle with any expansion (from autogrow) added in. + */ + virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0)const; + +protected: + + ossimRefPtr<ossimImageData> theTile; + ossimMeanMedianFilterType theFilterType; + ossim_uint32 theWindowSize; + + /** Used by applyMean and applyMedian for "fill null" modes. */ + bool theEnableFillNullFlag; + + /** + * If true rectangle is expanded by half filter in each direction if the + * theFilterType fills nulls. + */ + bool theAutoGrowRectFlag; + + void applyFilter(ossimRefPtr<ossimImageData>& input); + + template <class T> + void applyMean(T dummyVariable, + ossimRefPtr<ossimImageData>& inputData); + template <class T> + void applyMeanNullCenterOnly(T dummyVariable, + ossimRefPtr<ossimImageData>& inputData); + + template <class T> + void applyMedian(T dummyVariable, + ossimRefPtr<ossimImageData>& inputData); + template <class T> + void applyMedianNullCenterOnly(T dummyVariable, + ossimRefPtr<ossimImageData>& inputData); +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/remap_tables/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/remap_tables/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/remap_tables/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedRemapTable.cpp b/Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedRemapTable.cpp new file mode 100644 index 0000000000..6a83789e09 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedRemapTable.cpp @@ -0,0 +1,29 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// Description: +// +// Contains class definition for NormalizedRemapTable. +//******************************************************************* +// $Id: ossimNormalizedRemapTable.cpp,v 1.2 2001/10/11 15:39:42 dburken Exp $ + +#include "ossimNormalizedRemapTable.h" + +ossimNormalizedRemapTable::ossimNormalizedRemapTable() +{} diff --git a/Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedRemapTable.h b/Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedRemapTable.h new file mode 100644 index 0000000000..9cb76452dd --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedRemapTable.h @@ -0,0 +1,68 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// +// Description: +// +// Contains class declaration for NormalizedRemapTable. Table for +// normalizing unsigned 8 bit data. +//******************************************************************* +// $Id: ossimNormalizedRemapTable.h,v 1.3 2003/05/13 11:31:06 dburken Exp $ + + +#ifndef ossimNormalizedRemapTable_HEADER +#define ossimNormalizedRemapTable_HEADER + +#include "base/common/ossimConstants.h" + +//******************************************************************* +// CLASS: ossimNormalizedRemapTable +//******************************************************************* +class ossimNormalizedRemapTable +{ +public: + ossimNormalizedRemapTable(); + + virtual ~ossimNormalizedRemapTable(){} + + /*! + * Returns a normalized value (between '0.0' and '1.0') from + * a pixel value. + */ + virtual ossim_float64 normFromPix(ossim_int32 pix) const = 0; + + /*! + * Returns an pixel value as an int from a normalized value. + */ + virtual ossim_int32 pixFromNorm(ossim_float64 normPix) const = 0; + + /*! + * Returns a normalized value (between '0.0' and '1.0') from a + * pixel value. + */ + virtual ossim_float64 operator[](ossim_int32 pix) const = 0; + +private: + // Forbid copy constructor and asignment operator. + ossimNormalizedRemapTable(const ossimNormalizedRemapTable& source); + ossimNormalizedRemapTable& operator=(const ossimNormalizedRemapTable&); + + }; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedU11RemapTable.cpp b/Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedU11RemapTable.cpp new file mode 100644 index 0000000000..2aabe883bc --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedU11RemapTable.cpp @@ -0,0 +1,45 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// Description: +// +// Contains class definition for ossimNormalizedU11RemapTable. +//******************************************************************* +// $Id: ossimNormalizedU11RemapTable.cpp,v 1.3 2003/05/13 11:31:06 dburken Exp $ + +#include "ossimNormalizedU11RemapTable.h" + +double ossimNormalizedU11RemapTable::theTable[TABLE_ENTRIES]; +bool ossimNormalizedU11RemapTable::theTableIsInitialized = false; + +ossimNormalizedU11RemapTable::ossimNormalizedU11RemapTable() +{ + if (!theTableIsInitialized) + { + //*** + // Initialize the remap table. + //*** + for (ossim_int32 i = 0; i < TABLE_ENTRIES; i++) + { + ossim_float64 tmp = i; + theTable[i] = tmp / 2047.0; + } + theTableIsInitialized = true; + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedU11RemapTable.h b/Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedU11RemapTable.h new file mode 100644 index 0000000000..0aacd3ae17 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedU11RemapTable.h @@ -0,0 +1,102 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// +// Description: +// +// Contains class declaration for ossimNormalizedU11RemapTable. Table for +// normalizing unsigned 11 bit data. +// +//******************************************************************* +// $Id: ossimNormalizedU11RemapTable.h,v 1.3 2003/05/13 11:31:06 dburken Exp $ + +#ifndef ossimNormalizedU11RemapTable_HEADER +#define ossimNormalizedU11RemapTable_HEADER + +#include "ossimNormalizedRemapTable.h" + +class ossimNormalizedU11RemapTable : public ossimNormalizedRemapTable +{ +public: + ossimNormalizedU11RemapTable(); + + virtual ~ossimNormalizedU11RemapTable(){} + + enum + { + TABLE_ENTRIES = 2048 + }; + + virtual ossim_float64 normFromPix(ossim_int32 pix) const; + //> Returns a normalized value (between '0.0' and '1.0') from an eight + // bit unsigned char. + //< + + virtual ossim_int32 pixFromNorm(ossim_float64 normPix) const; + //> Returns a pixel value from a normalized value. + // Notes: + // - Valid returns range from '0' to '255' so given a + // value greater than '1.0' method returns '255' and given a + // value less than '0.0' method returns '0.0'. + //< + + virtual ossim_float64 operator[](ossim_int32 pix) const; + //> Returns a normalized value (between '0.0' and '1.0') from an eight + // bit unsigned char. + //< + +private: + // Forbid copy constructor and asignment operator. + ossimNormalizedU11RemapTable(const ossimNormalizedU11RemapTable& source){} + ossimNormalizedU11RemapTable& + operator=(const ossimNormalizedU11RemapTable&); + + static ossim_float64 theTable[TABLE_ENTRIES]; + static bool theTableIsInitialized; +}; + +inline ossim_float64 ossimNormalizedU11RemapTable::operator[](ossim_int32 pix) const +{ + return (pix < TABLE_ENTRIES ? (pix > 0 ? theTable[pix] : 0.0) : 1.0); +} + +inline ossim_float64 ossimNormalizedU11RemapTable::normFromPix(ossim_int32 pix) const +{ + return (pix < TABLE_ENTRIES ? (pix > 0 ? theTable[pix] : 0.0) : 1.0); +} + +inline ossim_int32 ossimNormalizedU11RemapTable::pixFromNorm(ossim_float64 normPix) const +{ + // un-normalize... + ossim_float64 p = normPix * 2047.0; + + // Ensure pixel is between 0 and 2047. + p = p < 2047.0 ? (p > 0.0 ? p : 0.0) : 2047.0; + + //*** + // If p is between greater than zero and less than one, make it one as it + // wasn't a null before. + // Add 0.5 to p otherwise as it will be cast to an int for proper rounding. + //*** + p = p > 1.0 ? (p+0.5) : ( !p ? 0.0 : 1.0); + + return static_cast<ossim_int32>(p); +} + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedU16RemapTable.cpp b/Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedU16RemapTable.cpp new file mode 100644 index 0000000000..4c05d55e41 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedU16RemapTable.cpp @@ -0,0 +1,45 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// Description: +// +// Contains class definition for ossimNormalizedU16RemapTable. +//******************************************************************* +// $Id: ossimNormalizedU16RemapTable.cpp,v 1.3 2003/05/13 11:31:06 dburken Exp $ + +#include "ossimNormalizedU16RemapTable.h" + +double ossimNormalizedU16RemapTable::theTable[TABLE_ENTRIES]; +bool ossimNormalizedU16RemapTable::theTableIsInitialized = false; + +ossimNormalizedU16RemapTable::ossimNormalizedU16RemapTable() +{ + if (!theTableIsInitialized) + { + //*** + // Initialize the remap table. + //*** + for (ossim_int32 i = 0; i < TABLE_ENTRIES; i++) + { + ossim_float64 tmp = i; + theTable[i] = tmp / 65535.0; + } + theTableIsInitialized = true; + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedU16RemapTable.h b/Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedU16RemapTable.h new file mode 100644 index 0000000000..b165b1e9b5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedU16RemapTable.h @@ -0,0 +1,101 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// +// Description: +// +// Contains class declaration for ossimNormalizedU16RemapTable. Table for +// normalizing unsigned 16 bit data. +//******************************************************************* +// $Id: ossimNormalizedU16RemapTable.h,v 1.3 2003/05/13 11:31:06 dburken Exp $ + +#ifndef ossimNormalizedU16RemapTable_HEADER +#define ossimNormalizedU16RemapTable_HEADER + +#include "ossimNormalizedRemapTable.h" + +class ossimNormalizedU16RemapTable : public ossimNormalizedRemapTable +{ +public: + ossimNormalizedU16RemapTable(); + + virtual ~ossimNormalizedU16RemapTable(){} + + enum + { + TABLE_ENTRIES = 65536 + }; + + virtual ossim_float64 normFromPix(ossim_int32 pix) const; + //> Returns a normalized value (between '0.0' and '1.0') from an eight + // bit unsigned char. + //< + + virtual ossim_int32 pixFromNorm(ossim_float64 normPix) const; + //> Returns a pixel value from a normalized value. + // Notes: + // - Valid returns range from '0' to '255' so given a + // value greater than '1.0' method returns '255' and given a + // value less than '0.0' method returns '0.0'. + //< + + virtual ossim_float64 operator[](ossim_int32 pix) const; + //> Returns a normalized value (between '0.0' and '1.0') from an eight + // bit unsigned char. + //< + +private: + // Forbid copy constructor and asignment operator. + ossimNormalizedU16RemapTable(const ossimNormalizedU16RemapTable& source){} + ossimNormalizedU16RemapTable& + operator=(const ossimNormalizedU16RemapTable&); + + static ossim_float64 theTable[TABLE_ENTRIES]; + static bool theTableIsInitialized; +}; + +inline ossim_float64 ossimNormalizedU16RemapTable::operator[](ossim_int32 pix) const +{ + return (pix < TABLE_ENTRIES ? (pix > 0 ? theTable[pix] : 0.0) : 1.0); +} + +inline ossim_float64 ossimNormalizedU16RemapTable::normFromPix(ossim_int32 pix) const +{ + return (pix < TABLE_ENTRIES ? (pix > 0 ? theTable[pix] : 0.0) : 1.0); +} + +inline ossim_int32 ossimNormalizedU16RemapTable::pixFromNorm(ossim_float64 normPix) const +{ + // un-normalize... + ossim_float64 p = normPix * 65535.0; + + // Ensure pixel is between 0 and 65535. + p = p < 65535.0 ? (p > 0.0 ? p : 0.0) : 65535.0; + + //*** + // If p is between greater than zero and less than one, make it one as it + // wasn't a null before. + // Add 0.5 to p otherwise as it will be cast to an int for proper rounding. + //*** + p = p > 1.0 ? (p+0.5) : ( !p ? 0.0 : 1.0); + + return static_cast<ossim_int32>(p); +} + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedU8RemapTable.cpp b/Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedU8RemapTable.cpp new file mode 100644 index 0000000000..3f05bb8318 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedU8RemapTable.cpp @@ -0,0 +1,45 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// Description: +// +// Contains class definition for ossimNormalizedU8RemapTable. +//******************************************************************* +// $Id: ossimNormalizedU8RemapTable.cpp,v 1.3 2003/05/13 11:31:06 dburken Exp $ + +#include "ossimNormalizedU8RemapTable.h" + +double ossimNormalizedU8RemapTable::theTable[TABLE_ENTRIES]; +bool ossimNormalizedU8RemapTable::theTableIsInitialized = false; + +ossimNormalizedU8RemapTable::ossimNormalizedU8RemapTable() +{ + if (!theTableIsInitialized) + { + //*** + // Initialize the remap table. + //*** + for (ossim_int32 i = 0; i < TABLE_ENTRIES; i++) + { + ossim_float64 tmp = i; + theTable[i] = tmp / 255.0; + } + theTableIsInitialized = true; + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedU8RemapTable.h b/Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedU8RemapTable.h new file mode 100644 index 0000000000..982e4d8359 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/remap_tables/ossimNormalizedU8RemapTable.h @@ -0,0 +1,104 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// +// Description: +// +// Contains class declaration for ossimNormalizedU8RemapTable. Table for +// normalizing unsigned 8 bit data. +//******************************************************************* +// $Id: ossimNormalizedU8RemapTable.h,v 1.3 2003/05/13 11:31:06 dburken Exp $ + +#ifndef ossimNormalizedU8RemapTable_HEADER +#define ossimNormalizedU8RemapTable_HEADER + +#include "ossimNormalizedRemapTable.h" + +//******************************************************************* +// CLASS: ossimNormalizedU8RemapTable +//******************************************************************* +class ossimNormalizedU8RemapTable : public ossimNormalizedRemapTable +{ +public: + ossimNormalizedU8RemapTable(); + + virtual ~ossimNormalizedU8RemapTable(){} + + enum + { + TABLE_ENTRIES = 256, + MAX_TABLE_INDEX = 255 + }; + + virtual ossim_float64 normFromPix(ossim_int32 pix) const; + //> Returns a normalized value (between '0.0' and '1.0') from an eight + // bit unsigned char. + //< + + virtual ossim_int32 pixFromNorm(ossim_float64 normPix) const; + //> Returns a pixel value from a normalized value. + // Notes: + // - Valid returns range from '0' to '255' so given a + // value greater than '1.0' method returns '255' and given a + // value less than '0.0' method returns '0.0'. + //< + + virtual ossim_float64 operator[](ossim_int32 pix) const; + //> Returns a normalized value (between '0.0' and '1.0') from an eight + // bit unsigned char. + //< + +private: + // Forbid copy constructor and asignment operator. + ossimNormalizedU8RemapTable(const ossimNormalizedU8RemapTable& source); + ossimNormalizedU8RemapTable& operator=(const ossimNormalizedU8RemapTable&); + + static ossim_float64 theTable[TABLE_ENTRIES]; + static bool theTableIsInitialized; +}; + +inline ossim_float64 ossimNormalizedU8RemapTable::operator[](ossim_int32 pix) const +{ + return (pix < TABLE_ENTRIES ? (pix > 0 ? theTable[pix] : 0.0) : 1.0); +} + +inline ossim_float64 ossimNormalizedU8RemapTable::normFromPix(ossim_int32 pix) const +{ + return (pix < TABLE_ENTRIES ? (pix > 0 ? theTable[pix] : 0.0) : 1.0); +} + +inline ossim_int32 ossimNormalizedU8RemapTable::pixFromNorm(ossim_float64 normPix) const +{ + // un-normalize... + ossim_float64 p = normPix * 255.0; + + // Ensure pixel is between 0 and 255. + p = p < 255.0 ? (p > 0.0 ? p : 0.0) : 255.0; + + //*** + // If p is between greater than zero and less than one, make it one as it + // wasn't a null before. + // Add 0.5 to p otherwise as it will be cast to an int for proper rounding. + //*** + p = p > 1.0 ? (p+0.5) : ( !p ? 0.0 : 1.0); + + return static_cast<ossim_int32>(p); +} + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/resample/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/resample/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/resample/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/imaging/resample/ossimFilterResampler.cpp b/Utilities/OSSIM/ossim_core/imaging/resample/ossimFilterResampler.cpp new file mode 100644 index 0000000000..7c62e37b64 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/resample/ossimFilterResampler.cpp @@ -0,0 +1,921 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts + +// Contributor: +// David A. Horner (DAH) http://dave.thehorners.com +// +//************************************************************************* +// $Id: ossimFilterResampler.cpp,v 1.43 2006/01/11 13:37:26 gpotts Exp $ + +#include <imaging/resample/ossimFilterResampler.h> +#include <base/common/ossimCommon.h> +#include <base/common/ossimPreferences.h> +#include <base/common/ossimKeywordNames.h> +#include <base/data_types/ossimKeywordlist.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimDrect.h> +#include <imaging/filters/ossimFilterTable.h> +ossimFilterResampler::ossimFilterResampler() + :theMinifyFilter(new ossimNearestNeighborFilter()), + theMagnifyFilter(new ossimNearestNeighborFilter()), + theMinifyFilterType(ossimFilterResampler_NEAREST_NEIGHBOR), + theMagnifyFilterType(ossimFilterResampler_NEAREST_NEIGHBOR), + theScaleFactor(1.0, 1.0), + theInverseScaleFactor(1.0, 1.0), + theBlurFactor(1.0) +{ + setScaleFactor(ossimDpt(1.0, 1.0)); + loadState(ossimPreferences::instance()->preferencesKWL(),"resampler."); + +} + +ossimFilterResampler::~ossimFilterResampler() +{ + if(theMinifyFilter) + { + delete theMinifyFilter; + theMinifyFilter = NULL; + } + if(theMagnifyFilter) + { + delete theMagnifyFilter; + theMagnifyFilter = NULL; + } +} + + +void ossimFilterResampler::resample(const ossimRefPtr<ossimImageData>& input, + ossimRefPtr<ossimImageData>& output, + const ossimDpt& ul, + const ossimDpt& ur, + const ossimDpt& deltaUl, + const ossimDpt& deltaUr, + const ossimDpt& length) +{ + resample(input, + output, + output->getImageRectangle(), + ul, + ur, + deltaUl, + deltaUr, + length); +} + +void ossimFilterResampler::resample(const ossimRefPtr<ossimImageData>& input, + ossimRefPtr<ossimImageData>& output, + const ossimIrect& outputSubRect, + const ossimDpt& ul, + const ossimDpt& ur, + const ossimDpt& deltaUl, + const ossimDpt& deltaUr, + const ossimDpt& length) +{ + if(!input.valid() || + !output.valid() || + !input->getBuf() || + !output->getBuf()) + { + return; + } + + ossimScalarType scalarType = input->getScalarType(); + switch(scalarType) + { + case OSSIM_UINT8: + { + resampleBilinearTile(ossim_uint8(0), // dummy template variable + input, + output, + outputSubRect, + ul, + ur, + deltaUl, + deltaUr, + length); + break; + } + case OSSIM_SINT8: + { + resampleBilinearTile(ossim_sint8(0), // dummy template variable + input, + output, + outputSubRect, + ul, + ur, + deltaUl, + deltaUr, + length); + break; + } + case OSSIM_UINT16: + case OSSIM_USHORT11: + { + resampleBilinearTile(ossim_uint16(0), // dummy template variable + input, + output, + outputSubRect, + ul, + ur, + deltaUl, + deltaUr, + length); + break; + } + case OSSIM_SINT16: + { + resampleBilinearTile(ossim_sint16(0), // dummy template variable + input, + output, + outputSubRect, + ul, + ur, + deltaUl, + deltaUr, + length); + break; + } + case OSSIM_UINT32: + { + resampleBilinearTile(ossim_uint32(0), // dummy template variable + input, + output, + outputSubRect, + ul, + ur, + deltaUl, + deltaUr, + length); + break; + } + case OSSIM_SINT32: + { + resampleBilinearTile(ossim_sint32(0), // dummy template variable + input, + output, + outputSubRect, + ul, + ur, + deltaUl, + deltaUr, + length); + break; + } + case OSSIM_FLOAT32: + case OSSIM_NORMALIZED_FLOAT: + { + resampleBilinearTile(ossim_float32(0.0), // dummy template variable + input, + output, + outputSubRect, + ul, + ur, + deltaUl, + deltaUr, + length); + break; + } + case OSSIM_FLOAT64: + case OSSIM_NORMALIZED_DOUBLE: + { + resampleBilinearTile(ossim_float64(0.0), // dummy template variable + input, + output, + outputSubRect, + ul, + ur, + deltaUl, + deltaUr, + length); + break; + } + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimFilterResampler::resample error: unknown scalar type: " + << scalarType << endl; + } + } +} + + +ossimFilter* ossimFilterResampler::createNewFilter( + ossimFilterResamplerType filterType, + ossimFilterResamplerType& result) +{ + switch(filterType) + { + case ossimFilterResampler_NEAREST_NEIGHBOR: + { + return new ossimNearestNeighborFilter(); + } + case ossimFilterResampler_BOX: + { + return new ossimBoxFilter(); + } + case ossimFilterResampler_GAUSSIAN: + { + return new ossimGaussianFilter(); + } + case ossimFilterResampler_CUBIC: + { + return new ossimCubicFilter(); + } + case ossimFilterResampler_HANNING: + { + return new ossimHanningFilter(); + } + case ossimFilterResampler_HAMMING: + { + return new ossimHammingFilter(); + } + case ossimFilterResampler_LANCZOS: + { + return new ossimLanczosFilter(); + } + case ossimFilterResampler_CATROM: + { + return new ossimCatromFilter(); + } + case ossimFilterResampler_MITCHELL: + { + return new ossimMitchellFilter(); + } + case ossimFilterResampler_BLACKMAN: + { + return new ossimBlackmanFilter(); + } + case ossimFilterResampler_BLACKMAN_SINC: + { + return new ossimBlackmanSincFilter(); + } + case ossimFilterResampler_BLACKMAN_BESSEL: + { + return new ossimBlackmanBesselFilter(); + } + case ossimFilterResampler_QUADRATIC: + { + return new ossimQuadraticFilter(); + } + case ossimFilterResampler_TRIANGLE: + { + return new ossimTriangleFilter(); + } + case ossimFilterResampler_HERMITE: + { + return new ossimHermiteFilter(); + } + case ossimFilterResampler_BELL: + { + return new ossimGaussianFilter(); + } + case ossimFilterResampler_BSPLINE: + { + return new ossimBSplineFilter(); + } + } + + result = ossimFilterResampler_NEAREST_NEIGHBOR; + return new ossimNearestNeighborFilter(); +} + +void ossimFilterResampler::setScaleFactor(const ossimDpt& scale) +{ + theScaleFactor = scale; + if(fabs(theScaleFactor.x) <= FLT_EPSILON) + { + theScaleFactor.x = 1.0; + } + if(fabs(theScaleFactor.y) <= FLT_EPSILON) + { + theScaleFactor.y = 1.0; + } + + theInverseScaleFactor.x = 1.0/theScaleFactor.x; + theInverseScaleFactor.y = 1.0/theScaleFactor.y; +} + +template <class T> void ossimFilterResampler::resampleBilinearTile( + T dummy, + const ossimRefPtr<ossimImageData>& input, + ossimRefPtr<ossimImageData>& output, + const ossimIrect& outputSubRect, + const ossimDpt& inputUl, + const ossimDpt& inputUr, + const ossimDpt& deltaUl, + const ossimDpt& deltaUr, + const ossimDpt& outLength) +{ +// std::cout << "INPUT = \n" << *input << std::endl +// << "OUTPUT = \n" << *output << std::endl +// << "inputUL= " << inputUl << std::endl +// << "inputUR= " << inputUr << std::endl +// << "deltaUL= " << deltaUl << std::endl +// << "deltaUr= " << deltaUr << std::endl +// << "outlength= " << outLength << std::endl; + ossim_uint32 band,centerOffset; + ossim_float64 tmpFlt64,stepSizeWidth,stepSizeHeight; + + if(outLength.x>1) { + stepSizeWidth = 1.0/(outLength.x-1.0); + } else { + stepSizeWidth = 1.0; + } + + if(outLength.y>1) { + stepSizeHeight = 1.0/(outLength.y-1.0); + } else { + stepSizeHeight = 1.0; + } + + // INPUT INFORMATION + ossim_uint32 inWidth = input->getWidth(); + ossim_uint32 inBandSize = input->getSizePerBand(); // fix for out-of-bounds check OLK 06/2005 + ossim_uint32 BANDS = input->getNumberOfBands(); + ossimIrect inputRect = input->getImageRectangle(); + + // OUTPUT INFORMATION + const ossim_float64* NULL_PIX = output->getNullPix(); + const ossim_float64* MIN_PIX = output->getMinPix(); + const ossim_float64* MAX_PIX = output->getMaxPix(); + ossimIrect outputRect = output->getImageRectangle(); + ossim_uint32 resultRectH = outputSubRect.height(); + ossim_uint32 resultRectW = outputSubRect.width(); + ossim_uint32 outputRectW = outputRect.width(); + + // calculate the offset into the data so we can refer to it at 0 index. + ossim_uint32 resultOffset=(outputSubRect.ul().y - outputRect.ul().y)*outputRectW + + (outputSubRect.ul().x - outputRect.ul().x); + + // make a local copy of the band pointers (at resultOffset) + ossim_float64 *densityvals=new ossim_float64[BANDS]; + ossim_float64 *pixelvals=new ossim_float64[BANDS]; + const T* *inputBuf = new const T*[BANDS]; + T* *resultBuf = new T*[BANDS]; + if(!pixelvals||!inputBuf||!resultBuf) + { + return; + } + + for(band = 0; band < BANDS; ++band) + { + inputBuf[band] = static_cast<const T*>(input->getBuf(band)); + resultBuf[band] = static_cast<T*>(output->getBuf(band))+resultOffset; + } + + // FILTER INFORMAION + ossim_uint32 xkernel_width = theFilterTable.getWidth();; + ossim_uint32 ykernel_height = theFilterTable.getHeight(); + double xkernel_half_width = theFilterTable.getXSupport(); + double ykernel_half_height = theFilterTable.getYSupport(); + + double initialx = inputUl.x-inputRect.ul().x; + double initialy = inputUl.y-inputRect.ul().y; + double terminalx = inputUr.x-inputRect.ul().x; + double terminaly = inputUr.y-inputRect.ul().y; + double pointx,pointy,deltaX,deltaY; + ossim_int32 starty,startx; + + // USING NEAREST NEIGHBOR + if(xkernel_width==0 || ykernel_height==0) + { + for(ossim_uint32 resultY = 0; resultY < resultRectH; ++resultY) + { +// deltaX = (terminalx-initialx) * stepSizeWidth; +// deltaY = (terminaly-initialy) * stepSizeHeight; + // this should be stepsize width for both since we are traversing horizontal + deltaX = (terminalx-initialx) * stepSizeWidth; + deltaY = (terminaly-initialy) * stepSizeWidth; + pointx = initialx; + pointy = initialy; + for(ossim_uint32 resultX = 0; resultX < resultRectW; ++resultX) + { + // just sample center in input space. + centerOffset = irint(pointy)*inWidth + irint(pointx); + for(band=0;band<BANDS;++band) + { + resultBuf[band][resultX] = inputBuf[band][centerOffset]; + } + pointy += deltaY; + pointx += deltaX; + } // End of loop in x direction. + + // increment pointers to where we are now. + for(band=0;band<BANDS;++band) + { + resultBuf[band] += outputRectW; + } + initialx += deltaUl.x; + initialy += deltaUl.y; + terminalx += deltaUr.x; + terminaly += deltaUr.y; + } // End of loop in y direction. + + // USING A KERNEL + } + else + { + const double* kernel; + ossim_uint32 iy,ix,sourceIndex,nullCount; + for(ossim_uint32 resultY = 0; resultY < resultRectH; ++resultY) + { + deltaX = (terminalx-initialx) * stepSizeWidth; + deltaY = (terminaly-initialy) * stepSizeWidth; + pointx = initialx; + pointy = initialy; + for(ossim_uint32 resultX = 0; resultX < resultRectW; ++resultX) + { + starty = irint(pointy - ykernel_half_height + .5); + startx = irint(pointx - xkernel_half_width + .5); + centerOffset = (ossim_uint32)((starty+ykernel_half_height)*inWidth + + (startx+xkernel_half_width)); + sourceIndex = starty*inWidth+startx; + + // look at center pixel, make sure they aren't all null. + nullCount=0; + if(centerOffset<inBandSize) + { + for (band=0;band<BANDS;++band) + { + if(inputBuf[band][centerOffset]==static_cast<T>(NULL_PIX[band])) + { + ++nullCount; + } + } + // the center of the kernel is outside the input space, just set null. + } + else + { + nullCount=BANDS; + } + + // make sure we have non-null data and we fit within the inputBuf. + if ( nullCount==BANDS || (sourceIndex>=inBandSize)) + { + // we don't need to continue, just assign null! + for (band=0;band<BANDS;++band) + { + resultBuf[band][resultX] = static_cast<T>(NULL_PIX[band]); + } + } + else + { + kernel = theFilterTable.getClosestWeights(pointx,pointy); + if(kernel) + { + // reset the pixel/density sums for each band to zero. + memset(densityvals,'\0',sizeof(ossim_float64)*BANDS); + memset(pixelvals,'\0',sizeof(ossim_float64)*BANDS); + + // apply kernel to input space. + for (iy=0;((iy<ykernel_height)&&(sourceIndex<inBandSize));++iy) + { + for (ix = 0;((ix<xkernel_width)&&(sourceIndex<inBandSize));++ix) + { + tmpFlt64=*kernel; // pixel weight; + for(band=0;band<BANDS;++band) + { + if(inputBuf[band][sourceIndex]!=NULL_PIX[band]) + { + densityvals[band] += tmpFlt64; + pixelvals[band] += (inputBuf[band][sourceIndex]*tmpFlt64); + } + } + ++sourceIndex; + ++kernel; + if(sourceIndex>=inBandSize) + { + break; + } + } + sourceIndex+=(inWidth-xkernel_width); + } + + // actually assign the value to the output + for (band = 0; band < BANDS; ++band) + { + if(densityvals[band]<=FLT_EPSILON) + { + tmpFlt64 = pixelvals[band]; + } + else + { + // normalize + tmpFlt64 = pixelvals[band]/densityvals[band]; + } + // clamp + tmpFlt64 = (tmpFlt64>=MIN_PIX[band]?(tmpFlt64<MAX_PIX[band]?tmpFlt64:MAX_PIX[band]):MIN_PIX[band]); + // set resultant pixel value. + resultBuf[band][resultX] = static_cast<T>(tmpFlt64); + } + + // we didn't get a filter kernel, just set NULL in this disaster. + } + else + { + for (band=0;band<BANDS;++band) + { + resultBuf[band][resultX] = static_cast<T>(NULL_PIX[band]); + } + } + } + pointy += deltaY; + pointx += deltaX; + } // End of loop in x direction. + + // increment pointers to where we are now. + for(band=0;band<BANDS;++band) + { + resultBuf[band] += outputRectW; + } + initialx += deltaUl.x; + initialy += deltaUl.y; + terminalx += deltaUr.x; + terminaly += deltaUr.y; + } // End of loop in y direction. + } // USING A KERNEL END + + delete [] densityvals; + delete [] pixelvals; + delete [] resultBuf; + delete [] inputBuf; +} + +ossimString ossimFilterResampler::getFilterTypeAsString(ossimFilterResamplerType type)const +{ + switch(type) + { + case ossimFilterResampler_NEAREST_NEIGHBOR: + { + return "nearest neighbor"; + } + case ossimFilterResampler_BOX: + { + return "box"; + } + case ossimFilterResampler_GAUSSIAN: + { + return "gaussian"; + } + case ossimFilterResampler_CUBIC: + { + return "cubic"; + } + case ossimFilterResampler_HANNING: + { + return "hanning"; + } + case ossimFilterResampler_HAMMING: + { + return "hamming"; + } + case ossimFilterResampler_LANCZOS: + { + return "lanczos"; + } + case ossimFilterResampler_MITCHELL: + { + return "mitchell"; + } + case ossimFilterResampler_CATROM: + { + return "catrom"; + } + case ossimFilterResampler_BLACKMAN: + { + return "blackman"; + } + case ossimFilterResampler_BLACKMAN_SINC: + { + return "sinc"; + } + case ossimFilterResampler_BLACKMAN_BESSEL: + { + return "bessel"; + } + case ossimFilterResampler_QUADRATIC: + { + return "quadratic"; + } + case ossimFilterResampler_TRIANGLE: + { + return "bilinear"; + } + case ossimFilterResampler_HERMITE: + { + return "hermite"; + } + case ossimFilterResampler_BELL: + { + return "gaussian"; + } + case ossimFilterResampler_BSPLINE: + { + return "bspline"; + } + } + + return "nearest neighbor"; +} + +void ossimFilterResampler::getFilterTypes(std::vector<ossimString>& filterTypes)const +{ + filterTypes.push_back("nearest neighbor"); + filterTypes.push_back("bilinear"); + filterTypes.push_back("cubic"); +// filterTypes.push_back("bell"); + filterTypes.push_back("bessel"); + filterTypes.push_back("blackman"); + filterTypes.push_back("box"); + filterTypes.push_back("bspline"); + filterTypes.push_back("catrom"); + filterTypes.push_back("gaussian"); + filterTypes.push_back("hanning"); + filterTypes.push_back("hamming"); + filterTypes.push_back("hermite"); + filterTypes.push_back("lanczos"); + filterTypes.push_back("mitchell"); + filterTypes.push_back("quadratic"); + filterTypes.push_back("sinc"); +} + + +ossimFilterResampler::ossimFilterResamplerType ossimFilterResampler::getFilterType(const ossimString& type)const +{ + ossimString typeUpper = type; + typeUpper = typeUpper.upcase(); + + if(typeUpper.contains("BOX")) + { + return ossimFilterResampler_BOX; + } + else if(typeUpper.contains("NEAREST")) + { + return ossimFilterResampler_NEAREST_NEIGHBOR; + } + else if(typeUpper.contains("GAUSSIAN")) + { + return ossimFilterResampler_GAUSSIAN; + } + else if(typeUpper.contains("HANNING")) + { + return ossimFilterResampler_HANNING; + } + else if(typeUpper.contains("HAMMING")) + { + return ossimFilterResampler_HAMMING; + } + else if(typeUpper.contains("LANCZOS")) + { + return ossimFilterResampler_LANCZOS; + } + else if(typeUpper.contains("MITCHELL")) + { + return ossimFilterResampler_MITCHELL; + } + else if(typeUpper.contains("CATROM")) + { + return ossimFilterResampler_CATROM; + } + else if(typeUpper.contains("CUBIC")) + { + return ossimFilterResampler_CUBIC; + } + else if(typeUpper.contains("BESSEL")) + { + return ossimFilterResampler_BLACKMAN_BESSEL; + } + else if(typeUpper.contains("SINC")) + { + return ossimFilterResampler_BLACKMAN_SINC; + } + else if(typeUpper.contains("BLACKMAN")) + { + return ossimFilterResampler_BLACKMAN; + } + else if(typeUpper.contains("QUADRATIC")) + { + return ossimFilterResampler_QUADRATIC; + } + else if(typeUpper.contains("TRIANGLE")) + { + return ossimFilterResampler_TRIANGLE; + } + else if(typeUpper.contains("BILINEAR")) + { + return ossimFilterResampler_TRIANGLE; + } + else if(typeUpper.contains("HERMITE")) + { + return ossimFilterResampler_HERMITE; + } +// else if(typeUpper.contains("BELL")) +// { +// return ossimFilterResampler_BELL; +// } + else if(typeUpper.contains("BSPLINE")) + { + return ossimFilterResampler_BSPLINE; + } + + return ossimFilterResampler_NEAREST_NEIGHBOR; +} + +void ossimFilterResampler::getKernelSupport(double& x, double& y)const +{ + const ossimFilter* horizontalFilter = getHorizontalFilter(); + const ossimFilter* verticalFilter = getVerticalFilter(); + + if(!horizontalFilter) + { + x = 0.0; + } + else + { +// x = theBlurFactor*ossimMax(1.0/theScaleFactor.x, 1.0)* +// horizontalFilter->getSupport(); + x = horizontalFilter->getSupport(); + } + + if(!verticalFilter) + { + y = 0.0; + } + else + { +// y = theBlurFactor*ossimMax(1.0/theScaleFactor.y, 1.0)* +// verticalFilter->getSupport(); + y = verticalFilter->getSupport(); + } +} + +const ossimFilter* ossimFilterResampler::getHorizontalFilter()const +{ + if(theScaleFactor.x < 1) + { + return theMinifyFilter; + } + + return theMagnifyFilter; +} + +const ossimFilter* ossimFilterResampler::getVerticalFilter()const +{ + if(theScaleFactor.y < 1) + { + return theMinifyFilter; + } + + return theMagnifyFilter; +} + +void ossimFilterResampler::setFilterType(const ossimString& type) +{ + setFilterType(type, type); +} + +void ossimFilterResampler::setFilterType(ossimFilterResamplerType filterType) +{ + setFilterType(filterType, filterType); +} +void ossimFilterResampler::setFilterType(const ossimString& minifyType, + const ossimString& magnifyType) +{ + setFilterType(getFilterType(minifyType), + getFilterType(magnifyType)); +} + +void ossimFilterResampler::setMinifyFilterType(const ossimString& minifyType) +{ + setMinifyFilterType(getFilterType(minifyType)); +} + +void ossimFilterResampler::setMagnifyFilterType(const ossimString& magnifyType) +{ + setMagnifyFilterType(getFilterType(magnifyType)); +} + +void ossimFilterResampler::setMinifyFilterType(ossimFilterResamplerType filterType) +{ + setFilterType(filterType, + theMagnifyFilterType); +} + +void ossimFilterResampler::setMagnifyFilterType(ossimFilterResamplerType filterType) +{ + setFilterType(theMinifyFilterType,filterType); +} + +ossimString ossimFilterResampler::getMinifyFilterTypeAsString()const +{ + return getFilterTypeAsString(theMinifyFilterType); +} + +ossimString ossimFilterResampler::getMagnifyFilterTypeAsString()const +{ + return getFilterTypeAsString(theMagnifyFilterType); +} + +void ossimFilterResampler::setFilterType( + ossimFilterResamplerType minifyFilterType, + ossimFilterResamplerType magnifyFilterType) +{ + if(theMinifyFilter) + { + delete theMinifyFilter; + theMinifyFilter = NULL; + } + if(theMagnifyFilter) + { + delete theMagnifyFilter; + theMagnifyFilter = NULL; + } + + theMinifyFilterType = minifyFilterType; + theMagnifyFilterType = magnifyFilterType; + + theMinifyFilter = createNewFilter(minifyFilterType, theMinifyFilterType); + theMagnifyFilter = createNewFilter(magnifyFilterType, theMagnifyFilterType); + computeTable(); +} + +ossim_float64 ossimFilterResampler::getBlurFactor()const +{ + return theBlurFactor; +} + +void ossimFilterResampler::setBlurFactor(ossim_float64 blur) +{ + theBlurFactor = blur; +} + +bool ossimFilterResampler::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + ossimKeywordNames::SCALE_X_KW, + theScaleFactor.x, + true); + kwl.add(prefix, + ossimKeywordNames::SCALE_Y_KW, + theScaleFactor.y, + true); + kwl.add(prefix, + "minify_type", + getFilterTypeAsString(theMinifyFilterType), + true); + kwl.add(prefix, + "magnify_type", + getFilterTypeAsString(theMagnifyFilterType), + true); + + return true; +} + +bool ossimFilterResampler::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimString scalex = kwl.find(prefix, + ossimKeywordNames::SCALE_X_KW); + theScaleFactor.x = scalex.toDouble(); + + ossimString scaley = kwl.find(prefix, + ossimKeywordNames::SCALE_Y_KW); + theScaleFactor.y = scaley.toDouble(); + + ossimString minify = kwl.find(prefix, + "minify_type"); + ossimString magnify = kwl.find(prefix, + "magnify_type"); + + + if(fabs(theScaleFactor.x) <= FLT_EPSILON) + { + theScaleFactor.x = 1.0; + } + if(fabs(theScaleFactor.y) <= FLT_EPSILON) + { + theScaleFactor.y = 1.0; + } + + theInverseScaleFactor.x = 1.0/theScaleFactor.x; + theInverseScaleFactor.y = 1.0/theScaleFactor.y; + + setFilterType(getFilterType(minify), + getFilterType(magnify)); + + return true; +} + +void ossimFilterResampler::computeTable() +{ + theFilterTable.buildTable(32, *theMagnifyFilter); +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/resample/ossimFilterResampler.h b/Utilities/OSSIM/ossim_core/imaging/resample/ossimFilterResampler.h new file mode 100644 index 0000000000..6e3ae12c5a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/resample/ossimFilterResampler.h @@ -0,0 +1,151 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Contributor: +// David A. Horner (DAH) http://dave.thehorners.com +// +//************************************************************************* +// $Id: ossimFilterResampler.h,v 1.13 2005/09/21 14:15:59 gpotts Exp $ +#ifndef ossimFilterResampler_HEADER +#define ossimFilterResampler_HEADER + +#include <vector> +#include <base/data_types/ossimString.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimIrect.h> +#include <imaging/ossimImageData.h> +#include <imaging/filters/ossimFilter.h> +#include <imaging/filters/ossimFilterTable.h> + +class OSSIMDLLEXPORT ossimFilterResampler +{ +public: + enum ossimFilterResamplerType + { + ossimFilterResampler_NEAREST_NEIGHBOR = 0, + ossimFilterResampler_BOX = 1, + ossimFilterResampler_GAUSSIAN = 2, + ossimFilterResampler_CUBIC = 3, + ossimFilterResampler_HANNING = 4, + ossimFilterResampler_HAMMING = 5, + ossimFilterResampler_LANCZOS = 6, + ossimFilterResampler_MITCHELL = 7, + ossimFilterResampler_CATROM = 8, + ossimFilterResampler_BLACKMAN = 9, + ossimFilterResampler_BLACKMAN_SINC = 10, + ossimFilterResampler_BLACKMAN_BESSEL = 11, + ossimFilterResampler_QUADRATIC = 12, + ossimFilterResampler_TRIANGLE = 13, + ossimFilterResampler_HERMITE = 14, + ossimFilterResampler_BELL = 15, + ossimFilterResampler_BSPLINE = 16 + + }; + ossimFilterResampler(); + virtual ~ossimFilterResampler(); + + virtual void resample(const ossimRefPtr<ossimImageData>& input, + ossimRefPtr<ossimImageData>& output, + const ossimDpt& ul, + const ossimDpt& ur, + const ossimDpt& deltaUl, + const ossimDpt& deltaUr, + const ossimDpt& length); + + virtual void resample(const ossimRefPtr<ossimImageData>& input, + ossimRefPtr<ossimImageData>& output, + const ossimIrect& outputSubRect, + const ossimDpt& ul, + const ossimDpt& ur, + const ossimDpt& deltaUl, + const ossimDpt& deltaUr, + const ossimDpt& length); + + void setFilterType(ossimFilterResamplerType filterType); + void setFilterType(ossimFilterResamplerType minifyFilterType, + ossimFilterResamplerType magnifyFilterType); + void setFilterType(const ossimString& type); + void setFilterType(const ossimString& minifyType, + const ossimString& magnifyType); + + void setMinifyFilterType(const ossimString& minifyType); + void setMagnifyFilterType(const ossimString& magnifyType); + void setMinifyFilterType(ossimFilterResamplerType filterType); + void setMagnifyFilterType(ossimFilterResamplerType filterType); + ossimString getMinifyFilterTypeAsString()const; + ossimString getMagnifyFilterTypeAsString()const; + void setScaleFactor(const ossimDpt& scale); + void setBlurFactor(ossim_float64 blur); + + void setBoundingInputRect(const ossimIrect& rect) + { + theInputRect = rect; + } + ossimIrect getBoundingInputRect()const + { + return theInputRect; + } + + ossim_float64 getBlurFactor()const; + + const ossimDpt& getScaleFactor()const + { + return theScaleFactor; + } + /*! + * Saves the state of this object. + */ + virtual bool saveState(ossimKeywordlist& kwl, const char* prefix=0)const; + + /*! + * Loads the state of this object. + */ + virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix=0); + + virtual void getKernelSupport(double& x, + double & y)const; + + virtual void getFilterTypes(std::vector<ossimString>& filterTypes)const; + +private: + const ossimFilter* getHorizontalFilter()const; + const ossimFilter* getVerticalFilter()const; + + template <class T> + void resampleBilinearTile(T dummy, + const ossimRefPtr<ossimImageData>& input, + ossimRefPtr<ossimImageData>& output, + const ossimIrect& outputSubRect, + const ossimDpt& inputUl, + const ossimDpt& inputUr, + const ossimDpt& deltaUl, + const ossimDpt& deltaUr, + const ossimDpt& outLength); + + void computeTable(); + ossimString getFilterTypeAsString(ossimFilterResamplerType type)const; + ossimFilterResamplerType getFilterType(const ossimString& type)const; + ossimFilter* createNewFilter(ossimFilterResamplerType filterType, + ossimFilterResamplerType& result); + + + ossimFilter* theMinifyFilter; + ossimFilter* theMagnifyFilter; + ossimFilterTable theFilterTable; + + ossimFilterResamplerType theMinifyFilterType; + ossimFilterResamplerType theMagnifyFilterType; + ossimDpt theScaleFactor; + ossimDpt theInverseScaleFactor; + + ossimIrect theInputRect; + ossim_float64 theBlurFactor; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/resample/ossimResampler.cpp b/Utilities/OSSIM/ossim_core/imaging/resample/ossimResampler.cpp new file mode 100644 index 0000000000..e53582f371 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/resample/ossimResampler.cpp @@ -0,0 +1,1259 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// +// Description: +// +// Contains class definition for ossimResampler. +// +//******************************************************************* +// $Id: ossimResampler.cpp,v 1.51 2005/06/07 19:20:22 dburken Exp $ + + +#include <iostream> +using namespace std; +#include <imaging/resample/ossimResampler.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimDpt3d.h> +#include <base/common/ossimCommon.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/common/ossimKeywordNames.h> +#include <base/context/ossimNotifyContext.h> +#include <imaging/ossimImageData.h> +#include <imaging/filters/ossimFilter.h> +#include <imaging/patch/ossimTilePatch.h> +#include <imaging/formats/ossimImageHandler.h> + +RTTI_DEF1(ossimResampler, "ossimResampler", ossimConnectableObject) + + +static const char* RESAMPLER_CONVOLUTION_TYPE_KW = "convolution_type"; +static const char* RESAMPLER_SCALE_X_KW = "scale_x"; +static const char* RESAMPLER_SCALE_Y_KW = "scale_y"; +static const char* RESAMPLER_CUBIC_PARAMETER_KW = "cubic_parameter"; + +ossimResampler::ossimResampler() + :ossimConnectableObject(NULL,0,0,true, false), + theOutputToInputRatio(1,1), + theResamplerType(ossimResampler_NONE), + theTableWidthX(0), + theTableWidthY(0), + theTableHeight(0), + theKernelWidth(0), + theKernelHeight(0), + theWeightTableX(NULL), + theWeightTableY(NULL), + theCubicAdjustableParameter(-.5) +{ +} + +ossimResampler::~ossimResampler() +{ + deleteWeightTable(); +} + +void ossimResampler::resample(ossimImageData* input, + ossimImageData* output) +{ + if(!input|| + !output || + !input->getBuf() || + !output->getBuf()) + { + return; + } + + if(theWeightTableX&&theWeightTableY) + { + ossimScalarType scalarType = input->getScalarType(); + switch(scalarType) + { + case OSSIM_UINT8: + { + resampleTile(ossim_uint8(0), // dummy template variable + input, + output); + break; + } + case OSSIM_UINT16: + case OSSIM_USHORT11: + { + resampleTile(ossim_uint16(0), // dummy template variable + input, + output); + break; + } + case OSSIM_SSHORT16: + { + resampleTile(ossim_sint16(0), // dummy template variable + input, + output); + break; + } + case OSSIM_UINT32: + { + resampleTile(ossim_uint32(0), // dummy template variable + input, + output); + break; + } + case OSSIM_FLOAT32: + case OSSIM_NORMALIZED_FLOAT: + { + resampleTile(ossim_float32(0.0), // dummy template variable + input, + output); + break; + } + case OSSIM_FLOAT64: + case OSSIM_NORMALIZED_DOUBLE: + { + resampleTile(ossim_float64(0.0), // dummy template variable + input, + output); + break; + } + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimResampler::resample error: unknown scalar type: " + << scalarType + << endl; + + } + } + } + // convolve the input and copy to output. +} + +void ossimResampler::resample(ossimImageData* input, + ossimImageData* output, + const ossimDpt& ul, + const ossimDpt& ur, + const ossimDpt& deltaUl, + const ossimDpt& deltaUr, + const ossimDpt& length) +{ + resample(input, + output, + output->getImageRectangle(), + ul, + ur, + deltaUl, + deltaUr, + length); +} + +void ossimResampler::resample(ossimImageData* input, + ossimImageData* output, + const ossimIrect& outputSubRect, + const ossimDpt& ul, + const ossimDpt& ur, + const ossimDpt& deltaUl, + const ossimDpt& deltaUr, + const ossimDpt& length) +{ + if(!input|| + !output || + !input->getBuf() || + !output->getBuf()) + { + return; + } + + if(theWeightTableX&&theWeightTableY) + { + ossimScalarType scalarType = input->getScalarType(); + switch(scalarType) + { + case OSSIM_UINT8: + { + resampleTile(ossim_uint8(0), // dummy template variable + input, + output, + outputSubRect, + ul, + ur, + deltaUl, + deltaUr, + length); + break; + } + case OSSIM_UINT16: + case OSSIM_USHORT11: + { + resampleTile(ossim_uint16(0), // dummy template variable + input, + output, + outputSubRect, + ul, + ur, + deltaUl, + deltaUr, + length); + break; + } + case OSSIM_SINT16: + { + resampleTile(ossim_sint16(0), // dummy template variable + input, + output, + outputSubRect, + ul, + ur, + deltaUl, + deltaUr, + length); + break; + } + case OSSIM_UINT32: + { + resampleTile(ossim_uint32(0), // dummy template variable + input, + output, + outputSubRect, + ul, + ur, + deltaUl, + deltaUr, + length); + break; + } + case OSSIM_FLOAT32: + case OSSIM_NORMALIZED_FLOAT: + { + resampleTile(ossim_float32(0.0), // dummy template variable + input, + output, + outputSubRect, + ul, + ur, + deltaUl, + deltaUr, + length); + break; + } + case OSSIM_FLOAT64: + case OSSIM_NORMALIZED_DOUBLE: + { + resampleTile(ossim_float64(0.0), // dummy template variable + input, + output, + outputSubRect, + ul, + ur, + deltaUl, + deltaUr, + length); + break; + } + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimResampler::resample error: unknown scalar type: " + << scalarType + << endl; + } + } + } + +} + +void ossimResampler::resampleNearestNeighbor(ossimImageData* input, + ossimImageData* output, + const ossimIrect& outputSubRect, + const ossimDpt& ul, + const ossimDpt& ur, + const ossimDpt& deltaUl, + const ossimDpt& deltaUr, + const ossimDpt& length) +{ + if(!input|| + !output || + !input->getBuf() || + !output->getBuf()) + { + return; + } + + ossimScalarType scalarType = input->getScalarType(); + switch(scalarType) + { + case OSSIM_UINT8: + { + resampleTileNearestNeighbor(ossim_uint8(0),// dummy template variable + input, + output, + outputSubRect, + ul, + ur, + deltaUl, + deltaUr, + length); + break; + } + case OSSIM_UINT16: + case OSSIM_USHORT11: + { + resampleTileNearestNeighbor(ossim_uint16(0),// dummy template variable + input, + output, + outputSubRect, + ul, + ur, + deltaUl, + deltaUr, + length); + break; + } + case OSSIM_SINT16: + { + resampleTileNearestNeighbor(ossim_sint16(0),// dummy template variable + input, + output, + outputSubRect, + ul, + ur, + deltaUl, + deltaUr, + length); + break; + } + case OSSIM_UINT32: + { + resampleTileNearestNeighbor(ossim_uint32(0),// dummy template variable + input, + output, + outputSubRect, + ul, + ur, + deltaUl, + deltaUr, + length); + break; + } + case OSSIM_FLOAT32: + case OSSIM_NORMALIZED_FLOAT: + { + resampleTileNearestNeighbor(ossim_float32(0.0), + input, + output, + outputSubRect, + ul, + ur, + deltaUl, + deltaUr, + length); + break; + } + case OSSIM_FLOAT64: + case OSSIM_NORMALIZED_DOUBLE: + { + resampleTileNearestNeighbor(ossim_float64(0.0), + input, + output, + outputSubRect, + ul, + ur, + deltaUl, + deltaUr, + length); + break; + } + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimResampler::resample error: unknown scalar type: " + << scalarType + << endl; + } + } +} + +void ossimResampler::resampleNearestNeighbor(ossimImageData* input, + ossimImageData* output, + const ossimDpt& ul, + const ossimDpt& ur, + const ossimDpt& deltaUl, + const ossimDpt& deltaUr, + const ossimDpt& length) +{ + resampleNearestNeighbor(input, + output, + output->getImageRectangle(), + ul, + ur, + deltaUl, + deltaUr, + length); +} + + +template <class T> +void ossimResampler::resampleTile(T,// not used + ossimImageData* input, + ossimImageData* output) +{ + switch(input->getDataObjectStatus()) + { + case OSSIM_FULL: + { + resampleFullTile((T)0, input, output); + break; + } + case OSSIM_PARTIAL: + { + resamplePartialTile((T)0, input, output); + break; + } + default: + { + break; + } + } +} + +template <class T> +void ossimResampler::resamplePartialTile(T,// not used + ossimImageData* input, + ossimImageData* output) +{ + ossim_int32 maxInputSize = std::max(input->getWidth(), input->getHeight()); + ossim_int32 maxOutputSize = std::max(output->getWidth(), output->getHeight()); + ossim_int32 k; + double *h = new double[maxInputSize]; + int *Lx = new int[maxOutputSize]; + int *Ly = new int[maxOutputSize]; + ossim_int32 out_height = output->getHeight(); + ossim_int32 out_width = output->getWidth(); + ossim_int32 in_width = input->getWidth(); + ossim_int32 in_height = input->getHeight(); + ossim_int32 j; + ossim_int32 l; + + ossimIpt origin=output->getOrigin(); + ossimIpt scaledOriginShift(input->getOrigin()*-1); + + ossim_int32 evenKernelW = (ossim_int32)(!(theKernelWidth%2)); + ossim_int32 evenKernelH = (ossim_int32)(!(theKernelHeight%2)); + ossim_int32 kernelHorizontalShift = (ossim_int32)(-theKernelWidth/2.0+evenKernelW); + ossim_int32 kernelVerticalShift = (ossim_int32)(-theKernelHeight/2.0+evenKernelH); + + for (k = 0; k < maxOutputSize; k++) + { + Lx[k] = (ossim_int32)(scaledOriginShift.x+((k+origin.x)/ + theOutputToInputRatio.x)); + } + for (k = 0; k < maxOutputSize; k++) + { + Ly[k] = (ossim_int32)(scaledOriginShift.y+((k+origin.y)/ + theOutputToInputRatio.y)); + } + for(ossim_int32 band = 0; band < (ossim_int32)input->getNumberOfBands();++band) + { + const T* inputBuf = static_cast<T*>(input->getBuf(band)); + T* outputBuf = static_cast<T*>(output->getBuf(band)); + T minPix = static_cast<T>(input->getMinPix(band)); + T maxPix = static_cast<T>(input->getMaxPix(band)); + T np = static_cast<T>(input->getNullPix(band)); + + for (k = 0; k < out_height; k++) + { + ossim_int32 indexMod = (ossim_int32)fmod((k+origin.y), theOutputToInputRatio.y); + if(indexMod >= theTableWidthY) indexMod = theTableWidthY - 1; + if(indexMod <0) indexMod = 0; + for (j = 0; j < in_width; j++) + { + h[j] = 0.0; + ossim_int32 count = 0; + double lastValue = OSSIM_DBL_NAN; + for (l = 0; l < theKernelHeight; l++) + { + ossim_int32 index = Ly[k] + l + kernelVerticalShift; + if ((index >= 0) && (index < in_height)) + { + ossim_int32 offset = index*in_width +j; + if(!input->isNull(offset)) + { + lastValue = (double)inputBuf[offset]; + h[j] += lastValue * + theWeightTableY[theKernelHeight - l-1][indexMod]; + ++count; + } + // I think instead of skipping to next value I'll just assume 0 + + // this was code to skip to next non-null value and use it + // +// else +// { +// for(ossim_int32 templ = l; templ < theKernelHeight; ++templ) +// { +// index = Ly[k] + templ + kernelVerticalShift; +// offset = index*in_width +j; +// if(!input->isNull(offset)) +// { +// lastValue = (double)inputBuf[offset]; +// break; +// } +// } +// if(lastValue != OSSIM_DBL_NAN) +// { +// h[j] += lastValue * +// theWeightTableY[theKernelHeight - l-1][indexMod]; + +// ++count; +// } +// else +// { +// break; +// } +// } + } + } + if(!count) + { + h[j] = OSSIM_DBL_NAN; + } + } + for (ossim_int32 m = 0; m < out_width; m++) + { + double x = 0.0; + ossim_int32 indexMod = (ossim_int32)fmod((m+origin.x), theOutputToInputRatio.x); + if(indexMod >= theTableWidthX) indexMod = theTableWidthX-1; + if(indexMod <0) indexMod = 0; + + if(input->isNull(ossimIpt(Lx[m]-scaledOriginShift.x, Ly[k]-scaledOriginShift.y))) + { + outputBuf[k*out_width +m] = np; + } + else + { + double lastValue = OSSIM_DBL_NAN; + for (l = 0; l < theKernelWidth; l++) + { + ossim_int32 index = Lx[m] + l + kernelHorizontalShift; + if ((index >= 0) && (index < in_width)) + { + if(h[index] != OSSIM_DBL_NAN) + { + lastValue = h[index]; + x += h[index] * theWeightTableX[theKernelWidth - l-1][indexMod]; + } + + // I am commenting out the code that searches for the next + // non null value with the kernel range. This will have the + // same effect as multiplying by 0.0 for the NULL value. + // +// else +// { +// for(ossim_int32 templ = l; templ < l; ++templ) +// { +// ossim_int32 index = Lx[m] + templ + kernelHorizontalShift; +// if(h[index] != OSSIM_DBL_NAN) +// { +// lastValue = h[index]; +// break; +// } +// } +// if(lastValue != OSSIM_DBL_NAN) +// { +// x += lastValue * theWeightTableX[theKernelWidth - l-1][indexMod]; +// } +// } + } + } + if (x < minPix) + { + outputBuf[k*out_width +m] = static_cast<T>(minPix); + } + else if (x > maxPix) + { + outputBuf[k*out_width +m] = static_cast<T>(maxPix); + } + else + { + outputBuf[k*out_width +m] = static_cast<T>(x); + } + } + } + } + } + + delete [] h; + delete [] Lx; + delete [] Ly; +} + +template <class T> +void ossimResampler::resampleFullTile(T,// not used + ossimImageData* input, + ossimImageData* output) +{ + ossim_int32 maxInputSize = std::max(input->getWidth(), input->getHeight()); + ossim_int32 maxOutputSize = std::max(output->getWidth(), output->getHeight()); + ossim_int32 k; + double *h = new double[maxInputSize]; + ossim_int32 *Lx = new ossim_int32[maxOutputSize]; + ossim_int32 *Ly = new ossim_int32[maxOutputSize]; + ossim_int32 out_height = output->getHeight(); + ossim_int32 out_width = output->getWidth(); + ossim_int32 in_width = input->getWidth(); + ossim_int32 in_height = input->getHeight(); + ossim_int32 j; + ossim_int32 l; + + ossimIpt origin=output->getOrigin(); + ossimIpt scaledOriginShift(input->getOrigin()*-1); + + ossim_int32 evenKernelW = (ossim_int32)(!(theKernelWidth%2)); + ossim_int32 evenKernelH = (ossim_int32)(!(theKernelHeight%2)); + ossim_int32 kernelHorizontalShift = (ossim_int32)(-theKernelWidth/2.0+evenKernelW); + ossim_int32 kernelVerticalShift = (ossim_int32)(-theKernelHeight/2.0+evenKernelH); + + for (k = 0; k < maxOutputSize; k++) + { + Lx[k] = (ossim_int32)(scaledOriginShift.x+((k+origin.x)/ + theOutputToInputRatio.x)); + } + for (k = 0; k < maxOutputSize; k++) + { + Ly[k] = (ossim_int32)(scaledOriginShift.y+((k+origin.y)/ + theOutputToInputRatio.y)); + } + for(ossim_int32 band = 0; band < (ossim_int32)input->getNumberOfBands();++band) + { + const T* inputBuf = (const T*)(input->getBuf(band)); + T* outputBuf = (T*)(output->getBuf(band)); + double minPix = static_cast<T>(input->getMinPix()[band]); + double maxPix = static_cast<T>(input->getMaxPix()[band]); + + for (k = 0; k < out_height; k++) + { + int indexMod = (int)fmod((k+origin.y), theOutputToInputRatio.y); + if(indexMod >= theTableWidthY) indexMod = theTableWidthY - 1; + if(indexMod <0) indexMod = 0; + for (j = 0; j < in_width; j++) + { + h[j] = 0.0; + for (l = 0; l < theKernelHeight; l++) + { + ossim_int32 index = Ly[k] + l + kernelVerticalShift; + if ((index >= 0) && (index < in_height)) + { + h[j] += ((double)inputBuf[index*in_width +j]) * + theWeightTableY[theKernelHeight - l-1][indexMod]; + } + } + } + for (ossim_int32 m = 0; m < out_width; m++) + { + double x = 0.0; + int indexMod = (int)fmod((m+origin.x), theOutputToInputRatio.x); + if(indexMod >= theTableWidthX) indexMod = theTableWidthX-1; + if(indexMod <0) indexMod = 0; + + for (l = 0; l < theKernelWidth; l++) + { + ossim_int32 index = Lx[m] + l + kernelHorizontalShift; + if ((index >= 0) && (index < in_width)) + { + + x += h[index] * theWeightTableX[theKernelWidth - l-1][indexMod]; + } + } + if (x < minPix) + { + outputBuf[k*out_width +m] = static_cast<T>(minPix); + } + else if (x > maxPix) + { + outputBuf[k*out_width +m] = static_cast<T>(maxPix); + } + else + { + outputBuf[k*out_width +m] = static_cast<T>(x); + } + } + } + } + + delete [] h; + delete [] Lx; + delete [] Ly; +} + + + +template <class T> +void ossimResampler::resampleTile(T,// not used + ossimImageData* input, + ossimImageData* output, + const ossimIrect& outputSubRect, + const ossimDpt& inputUl, + const ossimDpt& inputUr, + const ossimDpt& deltaUl, + const ossimDpt& deltaUr, + const ossimDpt& outLength) +{ + ossimImageData* dupIn = input; + ossimDpt origin = input->getOrigin(); + ossimDpt newInputUl = inputUl; + ossimDpt newInputUr = inputUr; + ossimDpt newDeltaUl = deltaUl; + ossimDpt newDeltaUr = deltaUr; + + if(theResamplerType != ossimResampler_NEAREST_NEIGHBOR) + { + newInputUl = ossimDpt(inputUl.x * theOutputToInputRatio.x, + inputUl.y * theOutputToInputRatio.y); + newInputUr = ossimDpt(inputUr.x * theOutputToInputRatio.x, + inputUr.y * theOutputToInputRatio.y); + newDeltaUl = ossimDpt(deltaUl.x * theOutputToInputRatio.x, + deltaUl.y * theOutputToInputRatio.y); + newDeltaUr = ossimDpt(deltaUr.x * theOutputToInputRatio.x, + deltaUr.y * theOutputToInputRatio.y); + + ossimDpt newLl = newInputUl + newDeltaUl*outLength.y; + ossimDpt newLr = newInputUr + newDeltaUr*outLength.y; + + ossimDrect newBoundingRect(newInputUl, + newInputUr, + newLl, + newLr); + + + newBoundingRect = ossimDrect(newBoundingRect.ul() - ossimDpt(theKernelWidth, theKernelHeight), + newBoundingRect.lr() + ossimDpt(theKernelWidth, theKernelHeight)); + ossimIrect roundedRect = newBoundingRect; + origin = roundedRect.ul(); + + dupIn = new ossimImageData(NULL, + input->getScalarType(), + input->getNumberOfBands(), + roundedRect.width(), + roundedRect.height()); + dupIn->setOrigin(roundedRect.ul()); + dupIn->initialize(); + resampleTile(static_cast<T>(0), input, dupIn); + } + long inWidth = dupIn->getWidth(); + long inHeight = dupIn->getHeight(); + double stepSizeWidth = 1.0/outLength.x; + double stepSizeHeight = 1.0/outLength.y; + ossimIrect rect = dupIn->getImageRectangle(); + + ossimDpt startSave(newInputUl.x - rect.ul().x, + newInputUl.y - rect.ul().y ); + ossimDpt endSave(newInputUr.x - rect.ul().x, + newInputUr.y - rect.ul().y); + + ossimIrect outputRect = output->getImageRectangle(); + ossimIpt subRectUl = outputSubRect.ul(); + long subRectH = outputSubRect.height(); + long subRectW = outputSubRect.width(); + + ossimIpt outputRectUl = outputRect.ul(); + long outputRectW = outputRect.width(); + long resultOffset = (subRectUl.y - outputRectUl.y)*outputRectW + (subRectUl.x - outputRectUl.x); + + for(ossim_uint32 band = 0; band < input->getNumberOfBands(); band++) + { + T* resultBuf = static_cast<T*>(output->getBuf(band))+resultOffset; + const T *sourceBuf = static_cast<T*>(dupIn->getBuf(band)); + ossimDpt start = startSave; + ossimDpt end = endSave; + T np = (T)output->getNullPix(band); + + for(long y = 0; y < subRectH; y++) + { + double deltaX = (end.x - start.x)*stepSizeWidth; + double deltaY = (end.y - start.y)*stepSizeHeight; + ossimDpt pointXY = start; + + for(long x = 0; x < subRectW; x++) + { + int xPixel = pointXY.x<0?(int)floor(pointXY.x):(int)pointXY.x; + int yPixel = pointXY.y<0?(int)floor(pointXY.y):(int)pointXY.y; + + + if( (xPixel >=0) && (xPixel < inWidth) && + (yPixel >=0) && (yPixel < inHeight)) + { + resultBuf[x] = sourceBuf[yPixel*inWidth + xPixel]; + } + else + { + resultBuf[x] = np; + } + + pointXY.y += deltaY; + pointXY.x += deltaX; + } + resultBuf += outputRectW; + + start.x += newDeltaUl.x; + start.y += newDeltaUl.y; + end.x += newDeltaUr.x; + end.y += newDeltaUr.y; + } + } + if(theResamplerType != ossimResampler_NEAREST_NEIGHBOR) + { + delete dupIn; + } +} + +template <class T> +void ossimResampler::resampleTileNearestNeighbor(T, // dummy template variable + ossimImageData* input, + ossimImageData* output, + const ossimDpt& ul, + const ossimDpt& ur, + const ossimDpt& deltaUl, + const ossimDpt& deltaUr, + const ossimDpt& length) +{ + resampleTileNearestNeighbor((T)0, + input, + output, + output->getImageRectangle(), + ul, + ur, + deltaUl, + deltaUr, + length); +} + +template <class T> +void ossimResampler::resampleTileNearestNeighbor(T, // dummy template variable + ossimImageData* input, + ossimImageData* output, + const ossimIrect& outputSubRect, + const ossimDpt& ul, + const ossimDpt& ur, + const ossimDpt& deltaUl, + const ossimDpt& deltaUr, + const ossimDpt& length) +{ + long inWidth = input->getWidth(); + long inHeight = input->getHeight(); + double stepSizeWidth = 1.0/length.x; + double stepSizeHeight = 1.0/length.y; + ossimIrect rect = input->getImageRectangle(); + + ossimDpt startSave(ul.x - rect.ul().x, + ul.y - rect.ul().y ); + + ossimDpt endSave(ur.x - rect.ul().x, + ur.y - rect.ul().y); + + ossimIrect outputRect = output->getImageRectangle(); + ossimIpt subRectUl = outputSubRect.ul(); +// ossimIpt subRectUl((int)outputSubRect.ul().x, +// (int)outputSubRect.ul().y); + long subRectH = outputSubRect.height(); + long subRectW = outputSubRect.width(); + + ossimIpt outputRectUl = outputRect.ul(); + long outputRectW = outputRect.width(); + + long resultOffset = (subRectUl.y - outputRectUl.y)*outputRectW + (subRectUl.x - outputRectUl.x); + for(ossim_uint32 band = 0; band < input->getNumberOfBands(); band++) + { + T* resultBuf = static_cast<T*>(output->getBuf(band))+resultOffset; + const T *sourceBuf = static_cast<T*>(input->getBuf(band)); + ossimDpt start = startSave; + ossimDpt end = endSave; + T inNp = (T)input->getNullPix(band); + T outNp = (T)output->getNullPix(band); + + for(long y = 0; y < subRectH; y++) + { + double deltaX = (end.x - start.x)*stepSizeWidth; + double deltaY = (end.y - start.y)*stepSizeHeight; + ossimDpt pointXY = start; + + for(long x = 0; x < subRectW; x++) + { + int xPixel = pointXY.x<0?(int)floor(pointXY.x):(int)pointXY.x; + int yPixel = pointXY.y<0?(int)floor(pointXY.y):(int)pointXY.y; + + + if( (xPixel >=0) && (xPixel < inWidth) && + (yPixel >=0) && (yPixel < inHeight)) + { + T value = sourceBuf[yPixel*inWidth + xPixel]; + + if(value != inNp) + { + resultBuf[x] = value; + } + else + { + resultBuf[x] = outNp; + } + } + else + { + resultBuf[x] = outNp; + } + + pointXY.y += deltaY; + pointXY.x += deltaX; + } + resultBuf += outputRectW; + + start.x += deltaUl.x; + start.y += deltaUl.y; + end.x += deltaUr.x; + end.y += deltaUr.y; + } + } +} + +ossim_int32 ossimResampler::getKernelWidth()const +{ + return theKernelWidth; +} + +ossim_int32 ossimResampler::getKernelHeight()const +{ + return theKernelHeight; +} + +void ossimResampler::deleteWeightTable() +{ + if(theWeightTableX) + { + for(ossim_int32 index = 0; index < theTableHeight; ++index) + { + delete [] theWeightTableX[index]; + } + delete [] theWeightTableX; + + theWeightTableX = NULL; + } + if(theWeightTableY) + { + for(ossim_int32 index = 0; index < theTableHeight; ++index) + { + delete [] theWeightTableY[index]; + } + delete [] theWeightTableY; + + theWeightTableY = NULL; + } +} + +void ossimResampler::allocateWeightTable()//uint32 outWidth) +{ + if(theWeightTableX|| + theWeightTableY) + { + deleteWeightTable(); + } + + switch(theResamplerType) + { + case ossimResampler_BICUBIC: + { + theTableHeight = 4; + break; + } + case ossimResampler_BILINEAR: + { + theTableHeight = 2; + break; + } + case ossimResampler_NEAREST_NEIGHBOR: + { + theTableHeight = 1; + break; + } + case ossimResampler_NONE: + { + theResamplerType = ossimResampler_NEAREST_NEIGHBOR; + theTableHeight = 1; + break; + } + } + theTableWidthX = (ossim_int32)irint(theOutputToInputRatio.x); + theTableWidthY = (ossim_int32)irint(theOutputToInputRatio.y); + if(theTableWidthX&&theTableHeight) + { + theWeightTableX = new double*[theTableHeight]; + + for(ossim_int32 index = 0; index < theTableHeight; ++index) + { + theWeightTableX[index] = new double[theTableWidthX]; + } + } + if(theTableWidthY&&theTableHeight) + { + theWeightTableY = new double*[theTableHeight]; + + for(ossim_int32 index = 0; index < theTableHeight; ++index) + { + theWeightTableY[index] = new double[theTableWidthY]; + } + } +} + +void ossimResampler::generateWeightTable() +{ + if(theWeightTableX&& + theWeightTableY) + { +// ossim_int32 d = theOutputToInputRatio.theDen; +// ossim_int32 n = theOutputToInputRatio.theNum; + ossim_int32 i = 0; + + double x = 0.0; + + switch(theResamplerType) + { + case ossimResampler_NONE: + { + theResamplerType = ossimResampler_NEAREST_NEIGHBOR; + for (i = 0; i < theTableWidthY; i++) + { + theWeightTableY[0][i] = 1; + } + for (i = 0; i < theTableWidthX; i++) + { + theWeightTableX[0][i] = 1; + } + break; + } + case ossimResampler_NEAREST_NEIGHBOR: + { + for (i = 0; i < theTableWidthY; i++) + { + theWeightTableY[0][i] = 1; + } + for (i = 0; i < theTableWidthX; i++) + { + theWeightTableX[0][i] = 1; + } + break; + } + case ossimResampler_BILINEAR: + { + for (i = 0; i < theTableWidthX; i++) + { + x = (double)i/(double)(theTableWidthX); + theWeightTableX[0][i] = x; + theWeightTableX[1][i] = 1-x; + } + for (i = 0; i < theTableWidthY; i++) + { + x = (double)i/(double)(theTableWidthY); + theWeightTableY[0][i] = x; + theWeightTableY[1][i] = 1-x; + } + break; + } + case ossimResampler_BICUBIC: + { + for (i = 0; i < theTableWidthX; i++) + { + x = (double)i/(double)(theTableWidthX); + theWeightTableX[0][i] = getCubicC0(x); + theWeightTableX[1][i] = getCubicC1(x); + theWeightTableX[2][i] = getCubicC2(x); + theWeightTableX[3][i] = getCubicC3(x); + } + for (i = 0; i < theTableWidthY; i++) + { + x = (double)i/(double)(theTableWidthY); + theWeightTableY[0][i] = getCubicC0(x); + theWeightTableY[1][i] = getCubicC1(x); + theWeightTableY[2][i] = getCubicC2(x); + theWeightTableY[3][i] = getCubicC3(x); + } + break; + } + } + } +} + +void ossimResampler::setResamplerType(ossimResLevelResamplerType type) +{ + if(theResamplerType != type) + { + theResamplerType = type; + + switch(theResamplerType) + { + case ossimResampler_NONE: + { + theResamplerType = ossimResampler_NEAREST_NEIGHBOR; + theKernelWidth = 1; + theKernelHeight = 1; + + break; + } + case ossimResampler_NEAREST_NEIGHBOR: + { + theKernelWidth = 1; + theKernelHeight = 1; + + break; + } + case ossimResampler_BILINEAR: + { + theKernelWidth = 2; + theKernelHeight = 2; + + break; + } + case ossimResampler_BICUBIC: + { + theKernelWidth = 4; + theKernelHeight = 4; + + break; + } + } + + allocateWeightTable(); + generateWeightTable(); + } +} + +void ossimResampler::setRatio(double outputToInputRatio) +{ + // make it square + setRatio(ossimDpt(outputToInputRatio, outputToInputRatio)); +} + +void ossimResampler::setRatio(const ossimDpt& outputToInputRatio) +{ + // make it square + theOutputToInputRatio.x = (outputToInputRatio.x); + theOutputToInputRatio.y = (outputToInputRatio.y); + + if((theTableWidthX != irint(outputToInputRatio.x))|| + (theTableWidthY != irint(outputToInputRatio.y))) + { + allocateWeightTable(); + generateWeightTable(); + } +} + +double ossimResampler::getCubicC0(double t)const +{ + return ((-theCubicAdjustableParameter * t * t * t) + + (theCubicAdjustableParameter * t * t)); +} + +double ossimResampler::getCubicC1(double t)const +{ + return (-(theCubicAdjustableParameter + 2.0) * t * t * t + + (2.0 * theCubicAdjustableParameter + 3.0) * t * t - + theCubicAdjustableParameter * t); +} + +double ossimResampler::getCubicC2(double t)const +{ + return ((theCubicAdjustableParameter + 2.0) * t * t * t - + (theCubicAdjustableParameter + 3.0) * t * t + 1.0); +} + +double ossimResampler::getCubicC3(double t)const +{ + return ((theCubicAdjustableParameter * t * t * t) - + (2.0f * theCubicAdjustableParameter * t * t) + + (theCubicAdjustableParameter * t)); +} + +bool ossimResampler::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* resamplerType = kwl.find(prefix, RESAMPLER_CONVOLUTION_TYPE_KW); + const char* scaleX = kwl.find(prefix, RESAMPLER_SCALE_X_KW); + const char* scaleY = kwl.find(prefix, RESAMPLER_SCALE_Y_KW); + const char* cubicParameter= kwl.find(prefix, RESAMPLER_CUBIC_PARAMETER_KW); + + if(cubicParameter) + { + theCubicAdjustableParameter = ossimString(cubicParameter).toDouble(); + if(theCubicAdjustableParameter < -1) theCubicAdjustableParameter = -1; + if(theCubicAdjustableParameter > 0) theCubicAdjustableParameter = 0; + } + else + { + theCubicAdjustableParameter = -.5; + } + if(resamplerType) + { + ossimString test =ossimString(resamplerType).upcase().trim(); + + if( test == "BICUBIC") + { + setResamplerType(ossimResampler::ossimResampler_BICUBIC); + } + else if( test == "BILINEAR") + { + setResamplerType(ossimResampler::ossimResampler_BILINEAR); + } + else + { + setResamplerType(ossimResampler::ossimResampler_NEAREST_NEIGHBOR); + } + } + if(scaleX&&scaleY) + { + setRatio(ossimDpt(ossimString(scaleX).toDouble(), + ossimString(scaleY).toDouble())); + } + allocateWeightTable(); + generateWeightTable(); + + return ossimConnectableObject::loadState(kwl, prefix); +} + +bool ossimResampler::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimString resamplerType; + if(getResamplerType() == ossimResampler_BICUBIC) + { + resamplerType = "BICUBIC"; + } + else if(getResamplerType() == ossimResampler_BILINEAR) + { + resamplerType = "BILINEAR"; + } + else + { + resamplerType = "NEAREST_NEIGHBOR"; + } + kwl.add(prefix, + RESAMPLER_CONVOLUTION_TYPE_KW, + resamplerType.c_str(), + true); + + kwl.add(prefix, + RESAMPLER_SCALE_X_KW, + theOutputToInputRatio.x, + true); + + kwl.add(prefix, + RESAMPLER_SCALE_Y_KW, + theOutputToInputRatio.y, + true); + + kwl.add(prefix, + RESAMPLER_CUBIC_PARAMETER_KW, + theCubicAdjustableParameter, + true); + + return ossimConnectableObject::saveState(kwl, prefix); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/resample/ossimResampler.h b/Utilities/OSSIM/ossim_core/imaging/resample/ossimResampler.h new file mode 100644 index 0000000000..93fcea6751 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/resample/ossimResampler.h @@ -0,0 +1,240 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +//******************************************************************* +// $Id: ossimResampler.h,v 1.23 2003/05/13 11:31:06 dburken Exp $ + +#ifndef ossimResampler_HEADER +#define ossimResampler_HEADER + +#include "base/common/ossimConnectableObject.h" +#include "base/data_types/ossimIpt.h" +#include "base/data_types/ossimDrect.h" +#include "base/data_types/ossimRationalNumber.h" + +class ossimImageData; + +/*! + * This is currently implemented as a symmetric kernel resampler. + * It will use a lookup table idea to precompute + * + * The resampler will support Nearest neighbor, Bilinear and Bicubic + * + * The lookup table approach will be borrowed from Michael J. Aramini + * implementation of the Bicubic convolution: + * + * http://www.ultranet.com/~aramini/ + * under: + * Efficient Image Magnification by Bicubic Spline Interpolation. + */ +class ossimResampler : public ossimConnectableObject +{ +public: + enum ossimResLevelResamplerType + { + ossimResampler_NONE = 0, + ossimResampler_NEAREST_NEIGHBOR = 1, + ossimResampler_BILINEAR = 2, + ossimResampler_BICUBIC = 3 + }; + ossimResampler(); + + virtual ~ossimResampler(); + + + /*! + * Will apply the kernel to the input and write it to the output. + * + * Note: theTable is re-generated if the Max(out_width, out_height). + * changes from the previous call. + */ + virtual void resample(ossimImageData* input, // input buffer + ossimImageData* output); + + + virtual void resample(ossimImageData* input, + ossimImageData* output, + const ossimDpt& ul, + const ossimDpt& ur, + const ossimDpt& deltaUl, + const ossimDpt& deltaUr, + const ossimDpt& length); + + virtual void resample(ossimImageData* input, + ossimImageData* output, + const ossimIrect& outputSubRect, + const ossimDpt& ul, + const ossimDpt& ur, + const ossimDpt& deltaUl, + const ossimDpt& deltaUr, + const ossimDpt& length); + + virtual void resampleNearestNeighbor(ossimImageData* input, + ossimImageData* output, + const ossimIrect& outputSubRect, + const ossimDpt& ul, + const ossimDpt& ur, + const ossimDpt& deltaUl, + const ossimDpt& deltaUr, + const ossimDpt& length); + + virtual void resampleNearestNeighbor(ossimImageData* input, + ossimImageData* output, + const ossimDpt& ul, + const ossimDpt& ur, + const ossimDpt& deltaUl, + const ossimDpt& deltaUr, + const ossimDpt& length); + /*! + * Will re-allocate the table + */ + virtual void setResamplerType(ossimResLevelResamplerType type); + + virtual ossimResLevelResamplerType getResamplerType()const + { + return theResamplerType; + } + + virtual double getCubicParameter()const + { + return theCubicAdjustableParameter; + } + virtual void setCubicParameter(double parameter) + { + theCubicAdjustableParameter = parameter; + theCubicAdjustableParameter = theCubicAdjustableParameter<-1?-1:theCubicAdjustableParameter; + theCubicAdjustableParameter = theCubicAdjustableParameter>0?0:theCubicAdjustableParameter; + if(theResamplerType == ossimResampler_BICUBIC) + { + generateWeightTable(); + } + } + /*! + * Will reallocate the table + */ + void setRatio(double outputToInputRatio); + void setRatio(const ossimDpt& outputToInputRatio); + ossimDpt getRatio()const + { + return theOutputToInputRatio; + } + virtual ossim_int32 getKernelWidth()const; + virtual ossim_int32 getKernelHeight()const; + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + bool canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const + { + return false; + } +protected: + + ossimDpt theOutputToInputRatio; + ossimResLevelResamplerType theResamplerType; + + ossim_int32 theTableWidthX; + ossim_int32 theTableWidthY; + ossim_int32 theTableHeight; + ossim_int32 theKernelWidth; + ossim_int32 theKernelHeight; + /*! + */ + double **theWeightTableX; + double **theWeightTableY; + + /*! + * This adjustable parameter can vary between + * -1 to 0. as the paramter goes from 0 + * to -1 the output goes from blocky to smooth. + * The default value is -.5 + */ + double theCubicAdjustableParameter; + + template <class T> + void resampleTile(T, // dummy tmeplate variable + ossimImageData* input, + ossimImageData* output); + + template <class T> + void resampleFullTile(T, // dummy tmeplate variable + ossimImageData* input, + ossimImageData* output); + template <class T> + void resamplePartialTile(T, // dummy tmeplate variable + ossimImageData* input, + ossimImageData* output); + + template <class T> + void resampleTile(T, // dummy template variable + ossimImageData* input, + ossimImageData* output, + const ossimIrect& outputSubRect, + const ossimDpt& ul, + const ossimDpt& ur, + const ossimDpt& deltaUl, + const ossimDpt& deltaUr, + const ossimDpt& length); + + template <class T> + void resampleTileNearestNeighbor(T, // dummy template variable + ossimImageData* input, + ossimImageData* output, + const ossimDpt& ul, + const ossimDpt& ur, + const ossimDpt& deltaUl, + const ossimDpt& deltaUr, + const ossimDpt& length); + + template <class T> + void resampleTileNearestNeighbor(T, // dummy template variable + ossimImageData* input, + ossimImageData* output, + const ossimIrect& subRect, + const ossimDpt& ul, + const ossimDpt& ur, + const ossimDpt& deltaUl, + const ossimDpt& deltaUr, + const ossimDpt& length); + + virtual void deleteWeightTable(); + virtual void allocateWeightTable(); + virtual void generateWeightTable(); + + double getCubicC0(double t)const; + double getCubicC1(double t)const; + double getCubicC2(double t)const; + double getCubicC3(double t)const; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/tile_sources/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossim3x3ConvolutionFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossim3x3ConvolutionFilter.cpp new file mode 100644 index 0000000000..f80cfce18b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossim3x3ConvolutionFilter.cpp @@ -0,0 +1,632 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossim3x3ConvolutionFilter.cpp,v 1.15 2005/08/17 19:18:12 gpotts Exp $ + +#include <imaging/tile_sources/ossim3x3ConvolutionFilter.h> +#include <base/data_types/ossimIrect.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <base/property/ossimMatrixProperty.h> + +RTTI_DEF1(ossim3x3ConvolutionFilter, "ossim3x3ConvolutionFilter", ossimImageSourceFilter); + +ossim3x3ConvolutionFilter::ossim3x3ConvolutionFilter(ossimObject* owner) + :ossimImageSourceFilter(owner), + theTile(NULL), + theNullPixValue(0), + theMinPixValue(0), + theMaxPixValue(0) +{ + theKernel[0][0] = 0.0; theKernel[0][1] = 0.0; theKernel[0][2] = 0.0; + theKernel[1][0] = 0.0; theKernel[1][1] = 1.0; theKernel[1][2] = 0.0; + theKernel[2][0] = 0.0; theKernel[2][1] = 0.0; theKernel[2][2] = 0.0; + +} + +ossim3x3ConvolutionFilter::~ossim3x3ConvolutionFilter() +{ +} + +ossimRefPtr<ossimImageData> ossim3x3ConvolutionFilter::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if(!theInputConnection) + { + return theTile; + } + + if(!isSourceEnabled()) + { + return theInputConnection->getTile(tileRect, resLevel); + } + + //--- + // We have a 3x3 matrix so stretch the rect out to cover + // the required pixels. We only need 1 pixel to the left + // and right of the center pixel. + //--- + ossimIrect newRect(ossimIpt(tileRect.ul().x - 1, + tileRect.ul().y - 1), + ossimIpt(tileRect.lr().x + 1, + tileRect.lr().y + 1)); + + ossimRefPtr<ossimImageData> data = theInputConnection->getTile(newRect, + resLevel); + + if(!data.valid() || !data->getBuf()) + { + return data; + } + + // First time through or after an initialize()... + if (!theTile.valid()) + { + allocate(); + if (!theTile.valid()) // Should never happen! + { + return data; + } + } + + // First time through, after an initialize() or a setKernel()... + if (!theNullPixValue.size()) + { + computeNullMinMax(); + if (!theNullPixValue.size()) // Should never happen! + { + return data; + } + } + + theTile->setImageRectangle(tileRect); + theTile->makeBlank(); + + switch(data->getScalarType()) + { + case OSSIM_UCHAR: + { + if(data->getDataObjectStatus() == OSSIM_FULL) + { + convolveFull(static_cast<ossim_uint8>(0), data, theTile); + } + else + { + convolvePartial(static_cast<ossim_uint8>(0), data, theTile); + } + break; + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + if(data->getDataObjectStatus() == OSSIM_FULL) + { + convolveFull(static_cast<float>(0), data, theTile); + } + else + { + convolvePartial(static_cast<float>(0), data, theTile); + } + break; + } + case OSSIM_USHORT16: + case OSSIM_USHORT11: + { + if(data->getDataObjectStatus() == OSSIM_FULL) + { + convolveFull(static_cast<ossim_uint16>(0), data, theTile); + } + else + { + convolvePartial(static_cast<ossim_uint16>(0), data, theTile); + } + break; + } + case OSSIM_SSHORT16: + { + if(data->getDataObjectStatus() == OSSIM_FULL) + { + convolveFull(static_cast<ossim_sint16>(0), data, theTile); + } + else + { + convolvePartial(static_cast<ossim_sint16>(0), data, theTile); + } + break; + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + if(data->getDataObjectStatus() == OSSIM_FULL) + { + convolveFull(static_cast<double>(0), data, theTile); + } + else + { + convolvePartial(static_cast<double>(0), data, theTile); + } + break; + } + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossim3x3ConvolutionFilter::getTile WARNING:\n" + << "Scalar type = " << theTile->getScalarType() + << " Not supported by ossim3x3ConvolutionFilter" << endl; + break; + } + } + theTile->validate(); + + return theTile; +} + + +template<class T> void ossim3x3ConvolutionFilter::convolvePartial( + T, + ossimRefPtr<ossimImageData> inputData, + ossimRefPtr<ossimImageData> outputData) +{ + // let's set up some temporary variables so we don't + // have to call the functions in loops. Iknow that compilers + // typically optimize this out but if we are in debug mode + // with no optimization it will still run fast + // + double sum = 0.0; + ossim_int32 inputW = (ossim_int32)inputData->getWidth(); + ossim_int32 outputW = (ossim_int32)outputData->getWidth(); + ossim_int32 outputH = (ossim_int32)outputData->getHeight(); + ossim_int32 numberOfBands = (ossim_int32)inputData->getNumberOfBands(); + ossimIpt outputOrigin = outputData->getOrigin(); + ossimIpt inputOrigin = inputData->getOrigin(); + + ossim_int32 startInputOffset = ossimAbs(outputOrigin.y - inputOrigin.y)* + inputW + ossimAbs(outputOrigin.x - inputOrigin.x); + ossim_int32 ulKernelStart = -inputW - 1; + ossim_int32 leftKernelStart = -1; + ossim_int32 llKernelStart = inputW - 1; + + T* ulKernelStartBuf = NULL; + T* leftKernelStartBuf = NULL; + T* llKernelStartBuf = NULL; + + for(ossim_int32 band = 0; band < numberOfBands; ++band) + { + T* inputBuf = static_cast<T*>(inputData->getBuf(band))+startInputOffset; + T* outputBuf = static_cast<T*>(outputData->getBuf(band)); + T maxPix = static_cast<T>(getMaxPixelValue(band)); + T minPix = static_cast<T>(getMinPixelValue(band)); + T nullPix = static_cast<T>(inputData->getNullPix(band)); + T oNullPix = static_cast<T>(getNullPixelValue(band)); + + if(inputBuf&&outputBuf) + { + for(ossim_int32 row = 0; row < outputW; ++row) + { + ossim_int32 rowOffset = inputW*row; + ulKernelStartBuf = inputBuf + (rowOffset + ulKernelStart); + leftKernelStartBuf = inputBuf + (rowOffset + leftKernelStart); + llKernelStartBuf = inputBuf + (rowOffset + llKernelStart); + for(ossim_int32 col = 0; col < outputH; ++col) + { + + if((ulKernelStartBuf[0] != nullPix)&& + (ulKernelStartBuf[1] != nullPix)&& + (ulKernelStartBuf[2] != nullPix)&& + (leftKernelStartBuf[0] != nullPix)&& + (leftKernelStartBuf[1] != nullPix)&& + (leftKernelStartBuf[2] != nullPix)&& + (llKernelStartBuf[0] != nullPix)&& + (llKernelStartBuf[1] != nullPix)&& + (llKernelStartBuf[2] != nullPix)) + { + sum = theKernel[0][0]*(double)ulKernelStartBuf[0] + + theKernel[0][1]*(double)ulKernelStartBuf[1] + + theKernel[0][2]*(double)ulKernelStartBuf[2] + + theKernel[1][0]*(double)leftKernelStartBuf[0] + + theKernel[1][1]*(double)leftKernelStartBuf[1] + + theKernel[1][2]*(double)leftKernelStartBuf[2] + + theKernel[2][0]*(double)llKernelStartBuf[0] + + theKernel[2][1]*(double)llKernelStartBuf[1] + + theKernel[2][2]*(double)llKernelStartBuf[2]; + + if(sum > maxPix) + { + *outputBuf = maxPix; + } + else if(sum < minPix) + { + *outputBuf = minPix; + } + else + { + *outputBuf = static_cast<T>(sum); + } + } + else { + *outputBuf = oNullPix; + } + // + // Need to implement the convolution here + // + + ++ulKernelStartBuf; + ++leftKernelStartBuf; + ++llKernelStartBuf; + ++outputBuf; + } + } + } + } +} + +template<class T> void ossim3x3ConvolutionFilter::convolveFull( + T, + ossimRefPtr<ossimImageData> inputData, + ossimRefPtr<ossimImageData> outputData) +{ + // let's set up some temporary variables so we don't + // have to call the functions in loops. Iknow that compilers + // typically optimize this out but if we are in debug mode + // with no optimization it will still run fast + // + double sum = 0.0; + ossim_int32 inputW = static_cast<ossim_int32>(inputData->getWidth()); + ossim_uint32 outputW = outputData->getWidth(); + ossim_uint32 outputH = outputData->getHeight(); + ossim_uint32 numberOfBands = inputData->getNumberOfBands(); + ossimIpt outputOrigin = outputData->getOrigin(); + ossimIpt inputOrigin = inputData->getOrigin(); + + ossim_int32 startInputOffset = ossimAbs(outputOrigin.y - inputOrigin.y)* + inputW + ossimAbs(outputOrigin.x - inputOrigin.x); + ossim_int32 ulKernelStart = -inputW - 1; + ossim_int32 leftKernelStart = -1; + ossim_int32 llKernelStart = inputW - 1; + + T* ulKernelStartBuf = NULL; + T* leftKernelStartBuf = NULL; + T* llKernelStartBuf = NULL; + + for(ossim_uint32 band = 0; band < numberOfBands; ++band) + { + T* inputBuf = static_cast<T*>(inputData->getBuf(band))+startInputOffset; + T* outputBuf = static_cast<T*>(outputData->getBuf(band)); + T maxPix = static_cast<T>(getMaxPixelValue(band)); + T minPix = static_cast<T>(getMinPixelValue(band)); + + if(inputBuf&&outputBuf) + { + for(ossim_uint32 row = 0; row < outputW; ++row) + { + ossim_int32 rowOffset = inputW*row; + ulKernelStartBuf = inputBuf + (rowOffset + ulKernelStart); + leftKernelStartBuf = inputBuf + (rowOffset + leftKernelStart); + llKernelStartBuf = inputBuf + (rowOffset + llKernelStart); + for(ossim_uint32 col = 0; col < outputH; ++col) + { + sum = theKernel[0][0]*(double)ulKernelStartBuf[0] + + theKernel[0][1]*(double)ulKernelStartBuf[1] + + theKernel[0][2]*(double)ulKernelStartBuf[2] + + theKernel[1][0]*(double)leftKernelStartBuf[0] + + theKernel[1][1]*(double)leftKernelStartBuf[1] + + theKernel[1][2]*(double)leftKernelStartBuf[2] + + theKernel[2][0]*(double)llKernelStartBuf[0] + + theKernel[2][1]*(double)llKernelStartBuf[1] + + theKernel[2][2]*(double)llKernelStartBuf[2]; + + if(sum > maxPix) + { + *outputBuf = maxPix; + } + else if(sum < minPix) + { + *outputBuf = minPix; + } + else + { + *outputBuf = static_cast<T>(sum); + } + // + // Need to implement the convolution here. + // + + + ++ulKernelStartBuf; + ++leftKernelStartBuf; + ++llKernelStartBuf; + ++outputBuf; + } + } + } + } +} + +void ossim3x3ConvolutionFilter::initialize() +{ + //--- + // NOTE: + // Since initialize get called often sequentially we will wipe things slick + // but not reallocate to avoid multiple delete/allocates. + // + // On the first getTile call things will be reallocated/computed. + //--- + theTile = NULL; + clearNullMinMax(); +} + +void ossim3x3ConvolutionFilter::allocate() +{ + if(theInputConnection) + { + ossimImageDataFactory* idf = ossimImageDataFactory::instance(); + + theTile = idf->create(this, + this); + + theTile->initialize(); + } +} + +void ossim3x3ConvolutionFilter::setProperty(ossimRefPtr<ossimProperty> property) +{ + if(!property) return; + if(property->getName() == "Kernel") + { + ossimMatrixProperty* matrixProperty = PTR_CAST(ossimMatrixProperty, + property.get()); + if(matrixProperty) + { + theKernel[0][0] = (*matrixProperty)(0,0); + theKernel[1][0] = (*matrixProperty)(1,0); + theKernel[2][0] = (*matrixProperty)(2,0); + theKernel[0][1] = (*matrixProperty)(0,1); + theKernel[1][1] = (*matrixProperty)(1,1); + theKernel[2][1] = (*matrixProperty)(2,1); + theKernel[0][2] = (*matrixProperty)(0,2); + theKernel[1][2] = (*matrixProperty)(1,2); + theKernel[2][2] = (*matrixProperty)(2,2); + + } + else + { + ossimImageSourceFilter::setProperty(property); + } + } + else + { + ossimImageSourceFilter::setProperty(property); + } +} + +ossimRefPtr<ossimProperty> ossim3x3ConvolutionFilter::getProperty(const ossimString& name)const +{ + if(name == "Kernel") + { + ossimMatrixProperty* property = new ossimMatrixProperty(name); + property->resize(3,3); + (*property)(0,0) = theKernel[0][0]; + (*property)(1,0) = theKernel[1][0]; + (*property)(2,0) = theKernel[2][0]; + (*property)(0,1) = theKernel[0][1]; + (*property)(1,1) = theKernel[1][1]; + (*property)(2,1) = theKernel[2][1]; + (*property)(0,2) = theKernel[0][2]; + (*property)(1,2) = theKernel[1][2]; + (*property)(2,2) = theKernel[2][2]; + property->setCacheRefreshBit(); + + return property; + } + return ossimImageSourceFilter::getProperty(name); +} + +void ossim3x3ConvolutionFilter::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + ossimImageSourceFilter::getPropertyNames(propertyNames); + propertyNames.push_back("Kernel"); +} + +bool ossim3x3ConvolutionFilter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + "rows", + 3, + true); + + kwl.add(prefix, + "cols", + 3, + true); + + for(long row = 0; row < 3; ++row) + { + for(long col =0; col < 3; ++col) + { + ossimString newPrefix = "m" + + ossimString::toString(row+1) + "_" + + ossimString::toString(col+1); + kwl.add(prefix, + newPrefix, + theKernel[row][col], + true); + } + } + + + return ossimImageSourceFilter::saveState(kwl, prefix); +} + + +bool ossim3x3ConvolutionFilter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimString newPrefix = prefix; + newPrefix += ossimString("m"); + + for(long r = 0; r < 3; r++) + { + for(long c = 0; c < 3; c++) + { + theKernel[r][c] = 0.0; + + ossimString value = ossimString::toString(r+1); + value += "_"; + value += ossimString::toString(c+1); + + const char* v = kwl.find(newPrefix.c_str(), + value.c_str()); + if(v) + { + theKernel[r][c] = ossimString(v).toDouble(); + } + } + } + + return ossimImageSourceFilter::loadState(kwl, prefix); +} + +void ossim3x3ConvolutionFilter::getKernel(double kernel[3][3]) +{ + kernel[0][0] = theKernel[0][0]; + kernel[0][1] = theKernel[0][1]; + kernel[0][2] = theKernel[0][2]; + kernel[1][0] = theKernel[1][0]; + kernel[1][1] = theKernel[1][1]; + kernel[1][2] = theKernel[1][2]; + kernel[2][0] = theKernel[2][0]; + kernel[2][1] = theKernel[2][1]; + kernel[2][2] = theKernel[2][2]; +} + +void ossim3x3ConvolutionFilter::setKernel(double kernel[3][3]) +{ + theKernel[0][0] = kernel[0][0]; + theKernel[0][1] = kernel[0][1]; + theKernel[0][2] = kernel[0][2]; + theKernel[1][0] = kernel[1][0]; + theKernel[1][1] = kernel[1][1]; + theKernel[1][2] = kernel[1][2]; + theKernel[2][0] = kernel[2][0]; + theKernel[2][1] = kernel[2][1]; + theKernel[2][2] = kernel[2][2]; + + // Will be recomputed first getTile call. + clearNullMinMax(); +} + +double ossim3x3ConvolutionFilter::getNullPixelValue(ossim_uint32 band)const +{ + if( isSourceEnabled() && (band < theNullPixValue.size()) ) + { + return theNullPixValue[band]; + } + + return ossimGetDefaultNull(getOutputScalarType()); +} + +double ossim3x3ConvolutionFilter::getMinPixelValue(ossim_uint32 band)const +{ + if( isSourceEnabled() && (band < theMinPixValue.size()) ) + { + return theMinPixValue[band]; + } + + return ossimImageSource::getMinPixelValue(band); +} + +double ossim3x3ConvolutionFilter::getMaxPixelValue(ossim_uint32 band)const +{ + if( isSourceEnabled() && (band < theMaxPixValue.size()) ) + { + return theMaxPixValue[band]; + } + + return ossimImageSource::getMaxPixelValue(band); +} + +void ossim3x3ConvolutionFilter::clearNullMinMax() +{ + theNullPixValue.clear(); + theMinPixValue.clear(); + theMaxPixValue.clear(); +} + +void ossim3x3ConvolutionFilter::computeNullMinMax() +{ + const ossim_uint32 BANDS = getNumberOfOutputBands(); + + theNullPixValue.resize(BANDS); + theMinPixValue.resize(BANDS); + theMaxPixValue.resize(BANDS); + + ossim_float64 defaultNull = ossimGetDefaultNull(getOutputScalarType()); + ossim_float64 defaultMin = ossimGetDefaultMin(getOutputScalarType()); + ossim_float64 defaultMax = ossimGetDefaultMax(getOutputScalarType()); + + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + if(theInputConnection) + { + ossim_float64 inputNull = theInputConnection->getNullPixelValue(band); + ossim_float64 inputMin = theInputConnection->getMinPixelValue(band); + ossim_float64 inputMax = theInputConnection->getMaxPixelValue(band); + ossim_float64 tempMin = 0.0; + ossim_float64 tempMax = 0.0; + ossim_float64 k = 0.0; + for(int i=0;i<3;++i) + { + for(int j=0;j<3;++j) + { + k=theKernel[i][j]; + tempMin += (k<0.0) ? k*inputMax : k*inputMin; + tempMax += (k>0.0) ? k*inputMax : k*inputMin; + } + } + + if((inputNull < getMinPixelValue(band)) || + (inputNull > getMaxPixelValue(band))) + { + theNullPixValue[band] = inputNull; + } + else + { + theNullPixValue[band] = defaultNull; + } + + if((tempMin >= defaultMin) && (tempMin <= defaultMax)) + { + theMinPixValue[band] = tempMin; + } + else + { + theMinPixValue[band] = defaultMin; + } + + if((tempMax >= defaultMin) && (tempMax <= defaultMax)) + { + theMaxPixValue[band] = tempMax; + } + else + { + theMaxPixValue[band] = defaultMax; + } + + } + else // No input connection... + { + theNullPixValue[band] = defaultNull; + theMinPixValue[band] = defaultMin; + theMaxPixValue[band] = defaultMax; + } + + } // End of band loop. +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossim3x3ConvolutionFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossim3x3ConvolutionFilter.h new file mode 100644 index 0000000000..3facf1c1f6 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossim3x3ConvolutionFilter.h @@ -0,0 +1,97 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossim3x3ConvolutionFilter.h,v 1.9 2005/08/17 19:18:12 gpotts Exp $ +#ifndef ossim3x3ConvolutionFilter_HEADER +#define ossim3x3ConvolutionFilter_HEADER +#include <imaging/tile_sources/ossimImageSourceFilter.h> + + +class ossim3x3ConvolutionFilter : public ossimImageSourceFilter +{ +public: + ossim3x3ConvolutionFilter(ossimObject* owner=NULL); + virtual ~ossim3x3ConvolutionFilter(); + + virtual ossimString getShortName()const{return ossimString("3x3 Convolution");} + virtual ossimString getLongName()const{return ossimString("Convolves the input image with a 3x3 kernel");} + + virtual void getKernel(double kernel[3][3]); + + virtual void setKernel(double kernel[3][3]); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + + virtual void initialize(); + + virtual double getNullPixelValue(ossim_uint32 band=0) const; + virtual double getMinPixelValue(ossim_uint32 band=0) const; + virtual double getMaxPixelValue(ossim_uint32 band=0) const; + + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix = 0); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix = 0)const; + +protected: + + /** + * Allocates theTile. + */ + void allocate(); + + /** + * Clears data members theNullPixValue, theMinPixValue, and + * theMaxPixValue. + */ + void clearNullMinMax(); + + /** + * Computes null, min, and max considering input connection and theKernel. + */ + void computeNullMinMax(); + + ossimRefPtr<ossimImageData> theTile; + double theKernel[3][3]; + + vector<double> theNullPixValue; + vector<double> theMinPixValue; + vector<double> theMaxPixValue; + + /*! + * Convolve full means that the input data is full and has + * no null data. We don't have to compare for nulls here + */ + template<class T> + void convolveFull(T, + ossimRefPtr<ossimImageData> inputData, + ossimRefPtr<ossimImageData> outputData); + + /*! + * Convolve partial means that the input data is has some + * null data. We will have to compare nulls + */ + template<class T> + void convolvePartial(T, + ossimRefPtr<ossimImageData> inputData, + ossimRefPtr<ossimImageData> outputData); + + +TYPE_DATA +}; + +#endif /* #ifndef ossim3x3ConvolutionFilter_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandAverageFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandAverageFilter.cpp new file mode 100644 index 0000000000..7847cffdf1 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandAverageFilter.cpp @@ -0,0 +1,394 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimBandAverageFilter.cpp,v 1.9 2005/08/17 19:18:12 gpotts Exp $ +#include "ossimBandAverageFilter.h" + +// used for constructing and an ossimImageData object +#include "imaging/factory/ossimImageDataFactory.h" + +// used for error reporting and for general info reporting such as warnings +#include "base/context/ossimErrorContext.h" + +#include <sstream> +#include <iterator> + +static const char* WEIGHTS_KW = "weights"; + +RTTI_DEF1(ossimBandAverageFilter, + "ossimBandAverageFilter", + ossimImageSourceFilter); + +ossimBandAverageFilter::ossimBandAverageFilter() + :ossimImageSourceFilter(), + theTile(NULL) +{ +} + +ossimBandAverageFilter::ossimBandAverageFilter(ossimImageSource* input, + const std::vector<double>& weights) + :ossimImageSourceFilter(input), + theTile(NULL), + theWeights(weights) +{ +} + +ossimBandAverageFilter::~ossimBandAverageFilter() +{ +} + +ossim_uint32 ossimBandAverageFilter::getNumberOfOutputBands()const +{ + if(isSourceEnabled()) + { + return 1; + } + + return ossimImageSourceFilter::getNumberOfOutputBands(); +} + +ossimRefPtr<ossimImageData> ossimBandAverageFilter::getTile(const ossimIrect& rect, ossim_uint32 resLevel) +{ + // first we will check to see if we have an input connection + // + if(!theInputConnection) + { + // this will probably be null since we aren't initialized. + // we really need to creae a default blank tile in OSSIM that is returned + return theTile; + } + + ossimRefPtr<ossimImageData> inputData = + theInputConnection->getTile(rect, resLevel); + + if(!inputData.valid()) + { + return inputData; + } + + // If we are disabled or if the data object is empty or NULL or + // not enough bands we don't need to run our algorithm so return the input + // tile. + if(!isSourceEnabled() || + (inputData->getDataObjectStatus() == OSSIM_NULL)|| + (inputData->getDataObjectStatus() == OSSIM_EMPTY)|| + (inputData->getNumberOfBands() < 2)) + { + return inputData; + } + + // check to see if we are initialized + if(!theTile.valid()) + { + initialize(); + } + + theTile->setImageRectangle(rect); + + // now lets set up the template method to operate in native type and run + // the algorithm + // + switch(inputData->getScalarType()) + { + case OSSIM_UCHAR: + { + averageInput((ossim_uint8)0, // setup template variable + inputData); + break; + } + case OSSIM_USHORT11: + case OSSIM_USHORT16: + { + averageInput((ossim_uint16)0, // setup template variable + inputData); + break; + } + case OSSIM_SSHORT16: + { + averageInput((ossim_sint16)0, // setup template variable + inputData); + break; + } + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT: + { + averageInput((float)0, // setup template variable + inputData); + break; + } + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_DOUBLE: + { + averageInput((double)0, // setup template variable + inputData); + break; + } + default: + { + ossimSetError(getClassName(), + ossimErrorCodes::OSSIM_ERROR, + "Unsupported scalar type in file %d at line %d", + __FILE__, + __LINE__); + + + theTile->makeBlank(); + break; + } + } + + theTile->validate(); + + + return theTile; +} + + + +void ossimBandAverageFilter::initialize() +{ + ossimImageSourceFilter::initialize(); + + // theInputConnection is defined in ossimImageSourceFilter + // It is automatically set when an input is connected to this + // object + if(theInputConnection) + { + theTile = ossimImageDataFactory::instance()->create(this, this); + + // now initialize the tile + theTile->initialize(); + checkWeights(); + } +} + +double ossimBandAverageFilter::getNullPixelValue(ossim_uint32 band)const +{ + if(!isSourceEnabled()) + { + return ossimImageSourceFilter::getNullPixelValue(band); + } + // lets use the first band's null value as our null + return ossimImageSourceFilter::getMinPixelValue(0); +} + +double ossimBandAverageFilter::getMinPixelValue(ossim_uint32 band)const +{ + if(!isSourceEnabled()||!theInputConnection) + { + return ossimImageSourceFilter::getMinPixelValue(band); + } + + // loop through each band and find the min pix value + ossim_uint32 bandIndex = 0; + ossim_uint32 inputBands = theInputConnection->getNumberOfOutputBands(); + double minValue = ossimGetDefaultMax(OSSIM_DOUBLE); + for(bandIndex = 0; bandIndex < inputBands; ++bandIndex) + { + double minPix = theInputConnection->getMinPixelValue(bandIndex); + + if(minPix < minValue) + { + minValue = minPix; + } + } + + return minValue; +} + +double ossimBandAverageFilter::getMaxPixelValue(ossim_uint32 band)const +{ + if(!isSourceEnabled()) + { + return ossimImageSourceFilter::getMaxPixelValue(band); + } + + // loop through each band and find the max pix value + ossim_uint32 bandIndex = 0; + ossim_uint32 inputBands = theInputConnection->getNumberOfOutputBands(); + double maxValue = ossimGetDefaultMin(OSSIM_DOUBLE); + for(bandIndex = 0; bandIndex < inputBands; ++bandIndex) + { + double maxPix = theInputConnection->getMaxPixelValue(bandIndex); + + if(maxPix > maxValue) + { + maxValue = maxPix; + } + } + + return maxValue; +} + +void ossimBandAverageFilter::checkWeights() +{ + // we have not been initialzed yet + // + if(!theTile) + { + return; + } + + // Check to see if the weights array is the same size as the input + // list. If not then resize it and populate them with the same weight + // value. It does not matter if they sum to one since we will perform + // a weighted average in the execution of the algorithm + // + if(theWeights.size() != theTile->getNumberOfBands()) + { + theWeights.resize(theTile->getNumberOfBands()); + + std::fill(theWeights.begin(), theWeights.end(), 1); + } +} + + +template<class T> void ossimBandAverageFilter::averageInput( + T dummyVariable, // used only for template type, value ignored + ossimRefPtr<ossimImageData> inputDataObject) +{ + // since we have already checked the input for empty or + // null we will now execute the algorithm. We will make + // + // + std::vector<T*> inputBands(inputDataObject->getNumberOfBands()); + std::vector<double> nullValues(inputDataObject->getNumberOfBands()); + ossim_uint32 i = 0; + + // for efficiency we will copy the band pointers and + // null values so we don't have extra function calls + // on a per band basis + // + for(i = 0; i < inputDataObject->getNumberOfBands(); ++i) + { + inputBands[i] = static_cast<T*>(inputDataObject->getBuf(i)); + nullValues[i] = inputDataObject->getNullPix(i); + } + + // store the output buffer pointer + T* outputBuf = static_cast<T*>(theTile->getBuf(0)); + + // setup index values and boundary values + ossim_uint32 upperBound = theTile->getWidth()*theTile->getHeight(); + ossim_uint32 bandIndex = 0; + ossim_uint32 numberOfBands = inputDataObject->getNumberOfBands(); + double outputNullPix = theTile->getNullPix(0); + + for(i = 0; i < upperBound; ++i) + { + double value=0.0; + double sumWeights=0.0; + + // loop over each band only using the valid pixel data + // in the weighted average. + // + for(bandIndex = 0; bandIndex < numberOfBands; ++bandIndex) + { + // if valid then muliply the value by the weight and add it to + // current pixel value + if(*inputBands[bandIndex] != nullValues[bandIndex]) + { + value += theWeights[bandIndex]*((double)*inputBands[bandIndex]); + sumWeights += theWeights[bandIndex]; + } + // increment to the next pixel for the next time around + ++inputBands[bandIndex]; + } + + // check to see if we had any valid data. If we did the weight + // should be greater than 0 + if(sumWeights != 0.0) + { + value /= sumWeights; + } + else + { + // else we set the pixel to the output null value + value = outputNullPix; + } + // store the result in the outputBuffer. + *outputBuf = static_cast<T>(value); + + // advance the output buffer to the next pixel value + ++outputBuf; + } +} + + +bool ossimBandAverageFilter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + // get the value of the stored keyword + ossimString weightString = kwl.find(prefix, WEIGHTS_KW); + weightString = weightString.trim(); + + + theWeights.clear(); + if(weightString != "") + { + // split the string list into an array of strings + std::vector<ossimString> weightList = weightString.split(" "); + + // resize the weights to the size of the weight list + // + theWeights.resize(weightList.size()); + ossim_uint32 i = 0; + + // now store the weights to the array + for(i = 0; i < theWeights.size(); ++i) + { + theWeights[i] = weightList[i].toDouble(); + } + } + + // call base class to continue the load state + return ossimImageSourceFilter::loadState(kwl, prefix); +} + +bool ossimBandAverageFilter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + std::stringstream out; + + // copy the weights to a memory stream separated by space + std::copy(theWeights.begin(), + theWeights.end(), + ostream_iterator<double>(out, " ")); + + ossimString weightString = out.str(); + weightString = weightString.trim(); + + + kwl.add(prefix, // prefix to help uniquely id or attributes + WEIGHTS_KW, // the keyword to identity our attribute + weightString.c_str(), // the value + true); // overwrite if already in the keywordlist + + // call base classes save to allow us to pass the information up + return ossimImageSourceFilter::saveState(kwl, prefix); +} + +double ossimBandAverageFilter::getWeight(ossim_uint32 band)const +{ + if(band < theWeights.size()) + { + return theWeights[band]; + } + + return 0.0; +} + +void ossimBandAverageFilter::setWeight(ossim_uint32 band, double weight) +{ + if(band < theWeights.size()) + { + theWeights[band] = fabs(weight); + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandAverageFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandAverageFilter.h new file mode 100644 index 0000000000..cff28204d2 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandAverageFilter.h @@ -0,0 +1,109 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimBandAverageFilter.h,v 1.5 2005/08/17 19:18:12 gpotts Exp $ +#ifndef ossimBandAverageFilter_HEADER +#define ossimBandAverageFilter_HEADER +#include <vector> +#include "imaging/tile_sources/ossimImageSourceFilter.h" + +/** + * This filter outputs a single band that is the weighted average of all the + * input bands retrieved from the getTile. This filter will work with any + * input scalar type. Note the OSSIMDLLEXPORT is used for the different + * compilers that require importing and exporting symbols for shared library + * support. + */ +class OSSIMDLLEXPORT ossimBandAverageFilter : public ossimImageSourceFilter +{ +public: + ossimBandAverageFilter(); + ossimBandAverageFilter(ossimImageSource* input, + const std::vector<double>& weights); + virtual ~ossimBandAverageFilter(); + + /** + * The data object argument is deprecated and should not be used. + * eventually we will remove it from the base classes. This method will + * return 1 if our source is enabled else it calls the base class + * getNumberOfOutputBands. + */ + virtual ossim_uint32 getNumberOfOutputBands()const; + + /** + * Since this filter is going to operate in native pixel type we will use + * a tmeplate method to do this. It will check the scalar tpe of the input + * and then cat it to set the template variabel to be used within the + * template method averageInput. + */ + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect, + ossim_uint32 resLevel=0); + + /** + * Since we are merging all bands we will use the null pix of the + * first input band as our null pix. If we are disabled we just + * return the input s null + */ + virtual double getNullPixelValue(ossim_uint32 band=0)const; + + /** + * We will use the min of all bands as our min. If we aredisabled + * we just return the inputs min + */ + virtual double getMinPixelValue(ossim_uint32 band=0)const; + + /** + * We will use the max of all bands as our max. If we aredisabled + * we just return the inputs max + */ + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + + /** + * simple access method to get a weight + */ + double getWeight(ossim_uint32 band)const; + + /** + * Sinple access method to set the weight of a band, + * We make sure that it is a positive weight + */ + void setWeight(ossim_uint32 band, double weight); + + /** + * allocates its tile buffer + */ + virtual void initialize(); + + /** + * loads its weights to a keywordlist + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + /** + * Saves its weights to a keywordlist + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + +protected: + ossimRefPtr<ossimImageData> theTile; + std::vector<double> theWeights; + + void checkWeights(); + + template<class T> void averageInput( + T dummyVariable, // used only for template type, value ignored + ossimRefPtr<ossimImageData> inputDataObject); + +// for Runtime Type Info (RTTI) +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandClipFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandClipFilter.cpp new file mode 100644 index 0000000000..53ca44e45e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandClipFilter.cpp @@ -0,0 +1,697 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimBandClipFilter.cpp,v 1.16 2005/02/11 15:07:32 dburken Exp $ + +#include <imaging/tile_sources/ossimBandClipFilter.h> +#include <base/context/ossimNotifyContext.h> + +RTTI_DEF1(ossimBandClipFilter, "ossimBandClipFilter", ossimImageSourceFilter); + +ossimBandClipFilter::ossimBandClipFilter() + :ossimImageSourceFilter(), + theClipType(ossimBandClipType_NONE), + theTile(NULL) +{ + theTile = new ossimImageData(this, // I am the owner, + OSSIM_NORMALIZED_FLOAT, + 1); + theTile->initialize(); +} + +ossimBandClipFilter::ossimBandClipFilter(ossimImageSource* inputSource, + const vector<double>& minPix, + const vector<double>& maxPix, + ossimBandClipType clipType) + :ossimImageSourceFilter(inputSource), + theClipType(clipType), + theTile(NULL) +{ + theTile = new ossimImageData(this, // I am the owner, + OSSIM_NORMALIZED_FLOAT, + 1); + theTile->initialize(); + setMinMaxPix(minPix, maxPix); +} + +ossimBandClipFilter::ossimBandClipFilter(ossimImageSource* inputSource, + double minPix, + double maxPix, + ossimBandClipType clipType) + :ossimImageSourceFilter(inputSource), + theClipType(clipType), + theTile(NULL) +{ + theTile = new ossimImageData(this, // I am the owner, + OSSIM_NORMALIZED_FLOAT, + 1); + theTile->initialize(); + + theMinPix.push_back(minPix); + theMaxPix.push_back(maxPix); +} + +ossimBandClipFilter::~ossimBandClipFilter() +{ +} + +void ossimBandClipFilter::setClipType(ossimBandClipType clipType) +{ + theClipType = clipType; +} + +ossimBandClipFilter::ossimBandClipType ossimBandClipFilter::getClipType()const +{ + return theClipType; +} + +ossim_uint32 ossimBandClipFilter::getNumberOfValues()const +{ + // We make sure that all arrays have the same number + // of elements so we can use the size of any of them. + return theMinPix.size(); +} + +void ossimBandClipFilter::setNumberOfValues(ossim_uint32 size) +{ + + // lets do a non destructive set. That way we can + // grow or shrink the list without destroying + // the original values. + // + if(!size) + { + theMinPix.clear(); + theMaxPix.clear(); + theMedian.clear(); + return; + } + + + vector<double> tempMin = theMinPix; + vector<double> tempMax = theMaxPix; + + theMinPix.resize(size); + theMaxPix.resize(size); + theMedian.resize(size); + + ossim_uint32 upperBound = min(theMinPix.size(), tempMin.size()); + ossim_uint32 index = 0; + + for(index = 0; index < upperBound; ++index) + { + theMinPix[index] = tempMin[index]; + theMaxPix[index] = tempMax[index]; + + theMinPix[index] = theMinPix[index]>1?1:theMinPix[index]; + theMinPix[index] = theMinPix[index]<0?0:theMinPix[index]; + theMaxPix[index] = theMaxPix[index]>1?1:theMaxPix[index]; + theMaxPix[index] = theMaxPix[index]<0?0:theMaxPix[index]; + + theMedian[index] = (theMaxPix[index] + theMinPix[index])/2.0; + } + + for(;index < theMinPix.size();++index) + { + theMinPix[index] = OSSIM_DEFAULT_MIN_PIX_NORM_FLOAT; + theMaxPix[index] = OSSIM_DEFAULT_MAX_PIX_NORM_FLOAT; + theMedian[index] = (theMaxPix[index] + theMinPix[index])/2.0; + + theMedian[index] = (theMaxPix[index] + theMinPix[index])/2.0; + } +} + +void ossimBandClipFilter::setMinMaxPix(const vector<double>& minPix, + const vector<double>& maxPix) +{ + theMinPix = minPix; + theMaxPix = maxPix; + + setNumberOfValues(max(theMinPix.size(), theMaxPix.size())); +} + +const std::vector<double>& ossimBandClipFilter::getMinPixList()const +{ + return theMinPix; +} + +const std::vector<double> ossimBandClipFilter::getMaxPixList()const +{ + return theMaxPix; +} + +double ossimBandClipFilter::getMinPix(ossim_uint32 index)const +{ + return index<theMinPix.size()?theMinPix[index]:0; +} + +double ossimBandClipFilter::getMaxPix(ossim_uint32 index)const +{ + return index<theMaxPix.size()?theMaxPix[index]:0; +} + +ossimRefPtr<ossimImageData> ossimBandClipFilter::getTile( + const ossimIrect& rect, + ossim_uint32 resLevel) +{ + if(!theInputConnection) + { + return NULL; + } + + ossimRefPtr<ossimImageData> data = + theInputConnection->getTile(rect, resLevel); + if(!data.get()) + { + return data; + } + ossimDataObjectStatus status = data->getDataObjectStatus(); + if((status != OSSIM_NULL) && + (status != OSSIM_EMPTY)) + { + ossim_uint32 dw = data->getWidth(); + ossim_uint32 dh = data->getHeight(); + ossim_uint32 db = data->getNumberOfBands(); + + ossim_uint32 tw = theTile->getWidth(); + ossim_uint32 th = theTile->getHeight(); + ossim_uint32 tb = theTile->getNumberOfBands(); + + if(((tw*th)!=(dw*dh))|| + (tb != db)) + { + theTile = new ossimImageData(this, + OSSIM_NORMALIZED_FLOAT, + db, + dw, + dh); + theTile->initialize(); + } + + if(getNumberOfValues() != theTile->getNumberOfBands()) + { + // Should this go on??? (drb) + ossimNotify(ossimNotifyLevel_WARN) + << "ossimBandClipFilter::getTile\n" + << "getNumberOfValues() != theTile->getNumberOfBands" + << endl; + } + + data->copyTileToNormalizedBuffer(static_cast<float*>(theTile->getBuf())); + theTile->setDataObjectStatus(data->getDataObjectStatus()); + + switch(theClipType) + { + case ossimBandClipType_CLIP: + { + runClip(); + break; + } + case ossimBandClipType_CLAMP: + { + runClamp(); + break; + } + case ossimBandClipType_LINEAR_STRETCH: + { + runLinearStretch(); + break; + } + case ossimBandClipType_MEDIAN_STRETCH: + { + runMedianStretch(); + break; + } + default: + break; + } + data->copyNormalizedBufferToTile(static_cast<float*>(theTile->getBuf())); + } + + return data; +} + +void ossimBandClipFilter::runClip() +{ + ossim_uint32 offset = 0; + ossim_uint32 upperBound = theTile->getWidth()*theTile->getHeight(); + for(ossim_uint32 band =0; band < theTile->getNumberOfBands(); ++band) + { + float *buf = static_cast<float*>(theTile->getBuf(band)); + float minPix = theMinPix[band]; + float maxPix = theMaxPix[band]; + float nullPix = theTile->getNullPix(band); + + if(buf) + { + for(offset = 0; offset < upperBound; ++offset) + { + if((*buf < minPix)|| + (*buf > maxPix)) + { + *buf = nullPix; + } + ++buf; + } + } + } + theTile->validate(); +} + +void ossimBandClipFilter::runClamp() +{ + ossim_uint32 offset = 0; + ossim_uint32 upperBound = theTile->getWidth()*theTile->getHeight(); + for(ossim_uint32 band =0; band < theTile->getNumberOfBands(); ++band) + { + float *buf = static_cast<float*>(theTile->getBuf(band)); + float minPix = theMinPix[band]; + float maxPix = theMaxPix[band]; + float nullPix = theTile->getNullPix(band); + + if(buf) + { + if(theTile->getDataObjectStatus() == OSSIM_PARTIAL) + { + for(offset = 0; offset < upperBound; ++offset) + { + if(*buf != nullPix) + { + if(*buf < minPix) + { + *buf = minPix; + } + else if(*buf > maxPix) + { + *buf = maxPix; + } + } + ++buf; + } + } + else + { + for(offset = 0; offset < upperBound; ++offset) + { + if(*buf < minPix) + { + *buf = minPix; + } + else if(*buf > maxPix) + { + *buf = maxPix; + } + ++buf; + } + } + } + } +} + +void ossimBandClipFilter::runLinearStretch() +{ + ossim_uint32 bands = min(theTile->getNumberOfBands(), (ossim_uint32)theMinPix.size()); + ossim_uint32 w = theTile->getWidth(); + ossim_uint32 h = theTile->getHeight(); + ossim_uint32 upperBound = w*h; + const double* minPixArray = theTile->getMinPix(); + const double* maxPixArray = theTile->getMaxPix(); + + float* *bandArray = new float*[bands]; + ossim_uint32 band = 0; + for(band = 0; band < bands; ++band) + { + bandArray[band] = static_cast<float*>(theTile->getBuf(band)); + } + + if(theTile->getDataObjectStatus() == OSSIM_PARTIAL) + { + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + if(!theTile->isNull(offset)) + { + for(band = 0; band < bands; ++band) + { + double delta = theMaxPix[band] - theMinPix[band]; + double t = (bandArray[band][offset] - theMinPix[band])/delta; + if(t < 0) + { + bandArray[band][offset] = minPixArray[band]; + } + else if(t > 1) + { + bandArray[band][offset] = maxPixArray[band]; + } + else + { + bandArray[band][offset] = t; + } + } + } + } + } + else if(theTile->getDataObjectStatus() == OSSIM_FULL) + { + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + for(band = 0; band < bands; ++band) + { + double delta = theMaxPix[band] - theMinPix[band]; + double t = (bandArray[band][offset] - theMinPix[band])/delta; + + if(t < 0) + { + bandArray[band][offset] = minPixArray[band]; + } + else if(t > 1) + { + bandArray[band][offset] = maxPixArray[band]; + } + else + { + bandArray[band][offset] = t; + } + } + } + } + delete [] bandArray; + +} + +void ossimBandClipFilter::runMedianStretch() +{ + ossim_uint32 bands = theTile->getNumberOfBands(); + float* *bandArray = new float*[bands]; + ossim_uint32 band = 0; + + for(band = 0; band < bands; ++band) + { + bandArray[band] = static_cast<float*>(theTile->getBuf(band)); + } + ossim_uint32 upperBound = theTile->getWidth()*theTile->getHeight(); + + if(theTile->getDataObjectStatus() == OSSIM_PARTIAL) + { + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + if(!theTile->isNull(offset)) + { + for(band = 0; band < bands; ++band) + { + double side = (theMedian[band] - (double)bandArray[band][offset]); + + if(side > 0) // on the left + { + double delta = fabs(theMedian[band] - theMinPix[band]); + double t = ((double)bandArray[band][offset] - theMinPix[band])/delta; + if(t < 0) + { + bandArray[band][offset] = OSSIM_DEFAULT_MIN_PIX_NORM_FLOAT; + } + else if(t > 1) + { + bandArray[band][offset] = theMedian[band]; + } + else + { + bandArray[band][offset] = theMedian[band]*t; + } + } + else // on the right + { + double delta = theMaxPix[band] - theMedian[band]; + double t = ((double)bandArray[band][offset] - theMedian[band])/delta; + + if(t < 0) + { + bandArray[band][offset] = theMedian[band]; + } + else if(t > 1) + { + bandArray[band][offset] = OSSIM_DEFAULT_MAX_PIX_NORM_FLOAT; + } + else + { + bandArray[band][offset] = theMedian[band]+delta*t; + } + } + } + } + } + } + else if(theTile->getDataObjectStatus() == OSSIM_FULL) + { + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + for(band = 0; band < bands; ++band) + { + double side = (theMedian[band] - (double)bandArray[band][offset]); + + if(side > 0) // on the left + { + double delta = fabs(theMedian[band] - theMinPix[band]); + double t = ((double)bandArray[band][offset] - theMinPix[band])/delta; + if(t < 0) + { + bandArray[band][offset] = OSSIM_DEFAULT_MIN_PIX_NORM_FLOAT; + } + else if(t > 1) + { + bandArray[band][offset] = theMedian[band]; + } + else + { + bandArray[band][offset] = theMedian[band]*t; + } + } + else // on the right + { + double delta = theMaxPix[band] - theMedian[band]; + double t = ((double)bandArray[band][offset] - theMedian[band])/delta; + + if(t < 0) + { + bandArray[band][offset] = theMedian[band]; + } + else if(t > 1) + { + bandArray[band][offset] = OSSIM_DEFAULT_MAX_PIX_NORM_FLOAT; + } + else + { + bandArray[band][offset] = theMedian[band]+delta*t; + } + } + } + } + } + + delete [] bandArray; +} + +void ossimBandClipFilter::initialize() +{ + ossimImageSourceFilter::initialize(); + + if(theInputConnection) + { + ossim_uint32 bands = theInputConnection->getNumberOfOutputBands(); + + if(bands) + { + if(theMinPix.size() != bands) + { + setNumberOfValues(bands); + } + } + } +} + +bool ossimBandClipFilter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + bool result = ossimImageSourceFilter::loadState(kwl, prefix); + + if(result) + { + ossimString minRegExpression = ossimString("^(") + + ossimString(prefix) + + "min[0-9]+)"; + ossimString maxRegExpression = ossimString("^(") + + ossimString(prefix) + + "max[0-9]+)"; + ossimString medianRegExpression = ossimString("^(") + + ossimString(prefix) + + "median[0-9]+)"; + + ossim_uint32 numberOfMins = kwl.getNumberOfSubstringKeys(minRegExpression); + ossim_uint32 numberOfMaxs = kwl.getNumberOfSubstringKeys(maxRegExpression); + ossim_uint32 numberOfMedians = kwl.getNumberOfSubstringKeys(medianRegExpression); + theMinPix.clear(); + theMaxPix.clear(); + theMedian.clear(); + + if(numberOfMins != numberOfMaxs) + { + ossim_int32 temp = min(numberOfMins, numberOfMaxs); + numberOfMins = temp; + numberOfMaxs = temp; + } + if(numberOfMins> 0) + { + ossimString prefixMin = ossimString(prefix) + "min"; + ossimString prefixMax = ossimString(prefix) + "max"; + ossimString prefixMedian = ossimString(prefix) + "median"; + + ossim_uint32 numberOfMatches = 0; + ossim_uint32 index = 0; + const char* value=(const char*)NULL; + + while(numberOfMatches < numberOfMins) + { + value = kwl.find(prefixMin.c_str(), + ossimString::toString(index).c_str()); + if(value) + { + theMinPix.push_back(ossimString(value).toDouble()); + ++numberOfMatches; + } + ++index; + } + index = 0; + numberOfMatches = 0; + while(numberOfMatches < numberOfMaxs) + { + value = kwl.find(prefixMax.c_str(), + ossimString::toString(index).c_str()); + if(value) + { + theMaxPix.push_back(ossimString(value).toDouble()); + ++numberOfMatches; + } + ++index; + } + if(numberOfMedians != numberOfMins) + { + for(index = 0; index < theMaxPix.size(); ++index) + { + theMedian.push_back((theMinPix[index]+theMaxPix[index])/2.0); + } + } + else + { + index = 0; + numberOfMatches = 0; + while(numberOfMatches < numberOfMedians) + { + value = kwl.find(prefixMedian.c_str(), + ossimString::toString(index).c_str()); + if(value) + { + theMedian.push_back(ossimString(value).toDouble()); + ++numberOfMatches; + } + ++index; + } + } + } + } + const char* clip_type = kwl.find(prefix, "clip_type"); + if(clip_type) + { + ossimString clipType = clip_type; + clipType = clipType.upcase().trim(); + + if(clipType == "NONE") + { + theClipType = ossimBandClipType_NONE; + } + else if(clipType == "CLIP") + { + theClipType = ossimBandClipType_CLIP; + } + else if(clipType == "LINEAR_STRETCH") + { + theClipType = ossimBandClipType_LINEAR_STRETCH; + } + else if(clipType == "MEDIAN_STRETCH") + { + theClipType = ossimBandClipType_MEDIAN_STRETCH; + } + } + else + { + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimBandClipFilter::loadState NOTICE:\n" + << "Clip type not given defaulting to NONE" << endl; + theClipType = ossimBandClipType_NONE; + } + + return result; +} + +bool ossimBandClipFilter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimString minPrefix = ossimString("min"); + ossimString maxPrefix = ossimString("max"); + ossimString medianPrefix = ossimString("median"); + + for(ossim_uint32 index = 1; index <= getNumberOfValues(); ++index) + { + ossimString value = (minPrefix+ossimString::toString(index)); + kwl.add(prefix, + value.c_str(), + theMinPix[index-1], + true); + value = (maxPrefix+ossimString::toString(index)); + kwl.add(prefix, + value.c_str(), + theMaxPix[index-1], + true); + value = (medianPrefix+ossimString::toString(index)); + kwl.add(prefix, + value.c_str(), + theMedian[index-1], + true); + } + ossimString clipType; + switch(theClipType) + { + case ossimBandClipType_NONE: + { + clipType = "NONE"; + break; + } + case ossimBandClipType_CLIP: + { + clipType = "CLIP"; + break; + } + case ossimBandClipType_LINEAR_STRETCH: + { + clipType = "LINEAR_STRETCH"; + break; + } + case ossimBandClipType_MEDIAN_STRETCH: + { + clipType = "MEDIAN_STRETCH"; + break; + } + default: + break; + } + kwl.add(prefix, + "clip_type", + clipType.c_str(), + true); + + return ossimImageSourceFilter::saveState(kwl, prefix); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandClipFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandClipFilter.h new file mode 100644 index 0000000000..b0cde29bff --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandClipFilter.h @@ -0,0 +1,92 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimBandClipFilter.h,v 1.12 2005/02/11 15:07:32 dburken Exp $ +#ifndef ossimBandClipFilter_HEADER +#define ossimBandClipFilter_HEADER +#include <vector> +using namespace std; + +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +class ossimBandClipFilter : public ossimImageSourceFilter +{ +public: + /*! + * Specifies the type of clipping. The first will + * just clip and + */ + enum ossimBandClipType + { + ossimBandClipType_NONE = 0, + ossimBandClipType_CLIP = 1, + ossimBandClipType_CLAMP = 2, + ossimBandClipType_LINEAR_STRETCH = 3, + ossimBandClipType_MEDIAN_STRETCH = 4 + }; + + ossimBandClipFilter(); + ossimBandClipFilter(ossimImageSource*, + const vector<double>& minPix, + const vector<double>& maxPix, + ossimBandClipType clipType=ossimBandClipType_NONE); + + ossimBandClipFilter(ossimImageSource*, + double minPix, + double maxPix, + ossimBandClipType clipType=ossimBandClipType_NONE); + + virtual ~ossimBandClipFilter(); + + void setClipType(ossimBandClipType clipType); + + ossimBandClipType getClipType()const; + + virtual ossim_uint32 getNumberOfValues()const; + + void setNumberOfValues(ossim_uint32 size); + + void setMinMaxPix(const vector<double>& minPix, + const vector<double>& maxPix); + + const std::vector<double>& getMinPixList()const; + const std::vector<double> getMaxPixList()const; + + double getMinPix(ossim_uint32 index)const; + double getMaxPix(ossim_uint32 index)const; + + ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect, + ossim_uint32 resLevel=0); + + virtual void initialize(); + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix = NULL); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix = NULL)const; +protected: + + void runClip(); + void runClamp(); + void runLinearStretch(); + void runMedianStretch(); + + std::vector<double> theMinPix; // normalized min + std::vector<double> theMaxPix; // normalized max + std::vector<double> theMedian; // normalized median. + + ossimBandClipType theClipType; + ossimRefPtr<ossimImageData> theTile; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandMergeSource.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandMergeSource.cpp new file mode 100644 index 0000000000..8abc394d3b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandMergeSource.cpp @@ -0,0 +1,274 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimBandMergeSource.cpp,v 1.19 2005/08/16 17:35:59 gpotts Exp $ +#include <imaging/tile_sources/ossimBandMergeSource.h> +#include <imaging/ossimImageData.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <base/data_types/ossimIrect.h> + +RTTI_DEF1(ossimBandMergeSource, "ossimBandMergeSource", ossimImageCombiner) + +ossimBandMergeSource::ossimBandMergeSource() + :ossimImageCombiner(), + theNumberOfOutputBands(0), + theTile(NULL) +{ +} + +ossimBandMergeSource::ossimBandMergeSource(vector<ossimImageSource*>& inputSources) + :ossimImageCombiner(inputSources), + theNumberOfOutputBands(0), + theTile(NULL) +{ + initialize(); +} + +ossimBandMergeSource::~ossimBandMergeSource() +{ + theNumberOfOutputBands = 0; +} + +ossimRefPtr<ossimImageData> ossimBandMergeSource::getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if( ( getNumberOfInputs() == 1) || !isSourceEnabled() ) + { + return getNextTile(0, tileRect, resLevel); + } + + // test if initialized + if(!theTile.get()) + { + allocate(); + } + + if(!theTile.get()) + { + return getNextTile(0, tileRect, resLevel); + } + + long w = tileRect.width(); + long h = tileRect.height(); + long tileW = theTile->getWidth(); + long tileH = theTile->getHeight(); + if((w != tileW)|| + (h != tileH)) + { + theTile->setWidth(w); + theTile->setHeight(h); + if((w*h)!=(tileW*tileH)) + { + theTile->initialize(); + } + else + { + theTile->makeBlank(); + } + } + else + { + theTile->makeBlank(); + } + theTile->setOrigin(tileRect.ul()); + ossim_uint32 currentBand = 0; + ossim_uint32 maxBands = theTile->getNumberOfBands(); + ossim_uint32 inputIdx = 0; + for(inputIdx = 0; inputIdx < getNumberOfInputs(); ++inputIdx) + { + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, + getInput(inputIdx)); + ossimRefPtr<ossimImageData> currentTile = 0; + + if(input) + { + currentTile = input->getTile(tileRect, resLevel); + } + else + { + currentTile = 0; + } + ossim_uint32 maxInputBands = 0; + + if(!currentTile.get()) + { + maxInputBands = 1; + } + else if(currentTile->getNumberOfBands() == 0) + { + maxInputBands = 1; + } + else + { + maxInputBands = currentTile->getNumberOfBands(); + } + for(ossim_uint32 band = 0; + ( (band < maxInputBands) && + (currentBand < maxBands)); + ++band) + { + // clear the band with the actual NULL + theTile->fill(currentBand, theTile->getNullPix(band)); + + if(currentTile.valid()) + { + if((currentTile->getDataObjectStatus() != OSSIM_NULL) && + (currentTile->getDataObjectStatus() != OSSIM_EMPTY)) + { + memmove(theTile->getBuf(currentBand), + currentTile->getBuf(band), + currentTile->getSizePerBandInBytes()); + } + } + ++currentBand; + } + } + theTile->validate(); + + return theTile; +} + +double ossimBandMergeSource::getNullPixelValue(ossim_uint32 band)const +{ + ossim_uint32 currentBandCount = 0; + ossim_uint32 idx = 0; + + ossim_uint32 maxBands = getNumberOfOutputBands(); + if(!maxBands) return 0.0; + + while((currentBandCount < maxBands)&& + (idx < getNumberOfInputs())) + { + ossimImageSourceInterface* temp = PTR_CAST(ossimImageSourceInterface, getInput(idx)); + if(temp) + { + ossim_uint32 previousCount = currentBandCount; + currentBandCount += temp->getNumberOfOutputBands(); + + if(band < currentBandCount) + { + return temp->getNullPixelValue(band - previousCount); + } + } + ++idx; + } + + return OSSIM_DBL_NAN; +} + +double ossimBandMergeSource::getMinPixelValue(ossim_uint32 band)const +{ + ossim_uint32 currentBandCount = 0; + ossim_uint32 idx = 0; + + ossim_uint32 maxBands = getNumberOfOutputBands(); + if(!maxBands) return 0.0; + + while((currentBandCount < maxBands)&& + (idx < getNumberOfInputs())) + { + ossimImageSourceInterface* temp = PTR_CAST(ossimImageSourceInterface, getInput(idx)); + if(temp) + { + ossim_uint32 previousCount = currentBandCount; + currentBandCount += temp->getNumberOfOutputBands(); + + if(band < currentBandCount) + { + return temp->getMinPixelValue(band - previousCount); + } + } + ++idx; + } + + return 0.0; +} + +double ossimBandMergeSource::getMaxPixelValue(ossim_uint32 band)const +{ + ossim_uint32 currentBandCount = 0; + ossim_uint32 idx = 0; + + ossim_uint32 maxBands = getNumberOfOutputBands(); + if(!maxBands) return 0.0; + + while((currentBandCount < maxBands)&& + (idx < getNumberOfInputs())) + { + ossimImageSourceInterface* temp = PTR_CAST(ossimImageSourceInterface, getInput(idx)); + if(temp) + { + ossim_uint32 previousCount = currentBandCount; + currentBandCount += temp->getNumberOfOutputBands(); + + if(band < currentBandCount) + { + return temp->getMaxPixelValue(band - previousCount); + } + } + ++idx; + } + + return OSSIM_DBL_NAN; +} + +void ossimBandMergeSource::initialize() +{ + ossimImageCombiner::initialize(); + + if(theTile.get()) + { + theTile = NULL; + } + + theNumberOfOutputBands = computeNumberOfInputBands(); +} + +void ossimBandMergeSource::allocate() +{ + if(theNumberOfOutputBands) + { + theTile = ossimImageDataFactory::instance()->create(this, + this); + theTile->initialize(); + } +} + +ossim_uint32 ossimBandMergeSource::computeNumberOfInputBands()const +{ + ossim_uint32 result = 0; + ossim_uint32 size = getNumberOfInputs(); + for(ossim_uint32 index = 0; index < size; ++index) + { + ossimImageSourceInterface* temp = PTR_CAST(ossimImageSourceInterface, getInput(index)); + if(temp) + { + if(temp->getNumberOfOutputBands() == 0) + { + ++result; + } + else + { + result += temp->getNumberOfOutputBands(); + } + } + } + return result; +} + +ossim_uint32 ossimBandMergeSource::getNumberOfOutputBands() const +{ + if(!theNumberOfOutputBands) + { + return computeNumberOfInputBands(); + } + + return theNumberOfOutputBands; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandMergeSource.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandMergeSource.h new file mode 100644 index 0000000000..55e1170185 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandMergeSource.h @@ -0,0 +1,62 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimBandMergeSource.h,v 1.12 2005/07/22 21:55:37 dburken Exp $ +#ifndef ossimBandMergeSource_HEADER +#define ossimBandMergeSource_HEADER +#include <imaging/tile_sources/ossimImageCombiner.h> + +class ossimImageSourceConnection; +class ossimImageSource; + +class OSSIM_DLL ossimBandMergeSource : public ossimImageCombiner +{ +public: + ossimBandMergeSource(); + ossimBandMergeSource(vector<ossimImageSource*>& inputSources); + virtual ~ossimBandMergeSource(); + + /** + * This will merge all the bands from the input source list + * into one contiguous ossimImageData object. This is very + * useful when you want to split off an intesity channel in + * HSI and then run some algorithms on it and then merge it back. + * You can also try to do fusions by converting to an YCbCr and + * replace the Y or intensity channel with maybe a high-pass + * convolution on the pan. + */ + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect, + ossim_uint32 resLevel=0); + + virtual void initialize(); + + /** + * Returns the number of bands in a tile returned from this TileSource. + * Note: we are supporting sources that can have multiple data objects. + * If you want to know the scalar type of an object you can pass in the + */ + virtual ossim_uint32 getNumberOfOutputBands() const; + + virtual double getNullPixelValue(ossim_uint32 band=0)const; + virtual double getMinPixelValue(ossim_uint32 band=0)const; + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + +protected: + /** Performs allocation of "theTile". */ + void allocate(); + + ossim_uint32 theNumberOfOutputBands; + ossimRefPtr<ossimImageData> theTile; + + ossim_uint32 computeNumberOfInputBands()const; + +TYPE_DATA +}; +#endif /* #ifndef ossimBandMergeSource_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandSelector.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandSelector.cpp new file mode 100644 index 0000000000..758f964319 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandSelector.cpp @@ -0,0 +1,428 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt. +// +// Author: Garrett Potts +// +// Description: +// +// Contains class declaration for ossimBandSelector. +// +//******************************************************************* +// $Id: ossimBandSelector.cpp,v 1.23 2005/12/20 16:29:48 dburken Exp $ + +#include <iostream> +#include <algorithm> + +#include <imaging/tile_sources/ossimBandSelector.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/common/ossimKeywordNames.h> +#include <base/context/ossimNotifyContext.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <base/property/ossimStringProperty.h> + +RTTI_DEF1(ossimBandSelector,"ossimBandSelector", ossimImageSourceFilter) + +ossimBandSelector::ossimBandSelector() + : + ossimImageSourceFilter(), + theTile(NULL) +{ + theEnableFlag = false; // Start off disabled. +} + +ossimBandSelector::~ossimBandSelector() +{ + theTile = NULL; +} + +ossimRefPtr<ossimImageData> ossimBandSelector::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if (!theInputConnection) + { + return ossimRefPtr<ossimImageData>(); + } + + // Get the tile from the source. + ossimRefPtr<ossimImageData> t = theInputConnection->getTile(tileRect, + resLevel); + + if (!theEnableFlag) + { + return t; // This tile source bypassed, return the input tile source. + } + + if (isOrderedCorrectly()) + { + return t; // Input band order same as output band order. + } + + if(!theTile.valid()) // First time through, might not be initialized... + { + allocate(); + if (!theTile.valid()) + { + // Should never happen... + return t; // initialize failed. + } + } + + theTile->setImageRectangle(tileRect); + + if ( !t.valid() || + (t->getDataObjectStatus() == OSSIM_EMPTY) || + (t->getDataObjectStatus() == OSSIM_NULL) ) + { + //--- + // Since we're enabled, we must return our tile not "t" so the + // correct number of bands goes through the chain. + //--- + theTile->makeBlank(); + return theTile; + } + + // Copy selected bands to our tile. + for (ossim_uint32 i=0; i<theOutputBandList.size(); i++) + { + theTile->assignBand(t.get(), theOutputBandList[i], i); + } + + theTile->validate(); + + return theTile; +} + +void ossimBandSelector::setOutputBandList( + const vector<ossim_uint32>& outputBandList) +{ + theOutputBandList = outputBandList; // Assign the new list. + if(outputBandsWithinInputRange()) + { + theEnableFlag = true; // Enable + theTile = NULL; // Force an allocate call next getTile. + } + else if(theInputConnection) + { + theInputConnection->getOutputBandList(theOutputBandList); + } + else + { + theOutputBandList.clear(); + } +} + +ossim_uint32 ossimBandSelector::getNumberOfOutputBands() const +{ + if(theEnableFlag) + { + return theOutputBandList.size(); + } + + return getNumberOfInputBands(); +} + +void ossimBandSelector::initialize() +{ + // Base class will recapture "theInputConnection". + ossimImageSourceFilter::initialize(); + + if(theInputConnection) + { + if ( !theOutputBandList.size() || + (outputBandsWithinInputRange() == false ) ) + { + //--- + // First time through set the output band list to input. + //--- + theInputConnection->getOutputBandList(theOutputBandList); + } + + if ( theEnableFlag ) + { + if ( theTile.valid() ) + { + //--- + // Check for: + // - ordered correctly + // - band change + // - scalar change + //--- + if( isOrderedCorrectly() || + ( theTile->getNumberOfBands() != theOutputBandList.size() ) || + ( theTile->getScalarType() != + theInputConnection->getOutputScalarType() ) ) + { + theTile = NULL; // Don't need it. + } + } + } + else + { + theTile = NULL; + } + } + else // No input connection. + { + theTile = NULL; + } +} + +void ossimBandSelector::allocate() +{ + initialize(); // Update the connection. + + theTile = ossimImageDataFactory::instance()->create(this, this); + theTile->initialize(); +} + +double ossimBandSelector::getMinPixelValue(ossim_uint32 band)const +{ + if(theInputConnection) + { + if (theEnableFlag) + { + if(band < theOutputBandList.size()) + { + return theInputConnection-> + getMinPixelValue(theOutputBandList[band]); + } + } + else + { + return theInputConnection->getMinPixelValue(band); + } + } + return 0; +} + +double ossimBandSelector::getMaxPixelValue(ossim_uint32 band)const +{ + if(theInputConnection) + { + if (theEnableFlag) + { + if(band < theOutputBandList.size()) + { + return theInputConnection-> + getMaxPixelValue(theOutputBandList[band]); + } + } + else + { + return theInputConnection->getMaxPixelValue(band); + } + } + return 1.0/DBL_EPSILON; +} + +bool ossimBandSelector::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimString temp; + + kwl.add(prefix, + ossimKeywordNames::NUMBER_OUTPUT_BANDS_KW, + theOutputBandList.size(), + true); + + for(ossim_uint32 counter = 0; counter < theOutputBandList.size();counter++) + { + temp = ossimKeywordNames::BAND_KW; + temp += ossimString::toString(counter+1); + + kwl.add(prefix, + temp.c_str(), + ossimString::toString(theOutputBandList[counter]+1).c_str()); + } + + return ossimImageSourceFilter::saveState(kwl, prefix); +} + +bool ossimBandSelector::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimImageSourceFilter::loadState(kwl, prefix); + + // call ossimSource method to delete the list of objects + theOutputBandList.clear(); + ossimString copyPrefix = prefix; + + + ossimString regExpression = ossimString("^(") + copyPrefix + "band[0-9]+)"; + + vector<ossimString> keys = + kwl.getSubstringKeyList( regExpression ); + long numberOfBands = (long)keys.size(); + int offset = (copyPrefix+"band").size(); + int idx = 0; + std::vector<int> numberList(numberOfBands); + for(idx = 0; idx < (int)keys.size();++idx) + { + ossimString numberStr(keys[idx].begin() + offset, + keys[idx].end()); + numberList[idx] = numberStr.toInt(); + } + std::sort(numberList.begin(), numberList.end()); + for(idx=0;idx < (int)numberList.size();++idx) + { + const char* bandValue = kwl.find(copyPrefix, ("band"+ossimString::toString(numberList[idx])).c_str()); + theOutputBandList.push_back( ossimString(bandValue).toLong()-1); + } + + initialize(); + + return true; +} + +bool ossimBandSelector::isOrderedCorrectly() const +{ + if(theInputConnection) + { + std::vector<ossim_uint32> inputList; + theInputConnection->getOutputBandList(inputList); + + ossim_uint32 output_bands = theOutputBandList.size(); + + if(inputList.size() != output_bands) return false; + + for (ossim_uint32 i=0; i<output_bands; ++i) + { + if (inputList[i] != theOutputBandList[i]) return false; + } + return true; + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimBandSelector::isOrderedCorrectly() ERROR:" + << "Method called prior to initialization!\n"; + } + + return false; +} + +bool ossimBandSelector::outputBandsWithinInputRange() const +{ + if(theInputConnection) + { + const ossim_uint32 HIGHEST_BAND = + theInputConnection->getNumberOfOutputBands() - 1; + + const ossim_uint32 OUTPUT_BANDS = theOutputBandList.size(); + + for (ossim_uint32 i=0; i<OUTPUT_BANDS; ++i) + { + if (theOutputBandList[i] > HIGHEST_BAND) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimBandSelector::outputBandsWithinInputRange() ERROR:" + << "Output band great than highest input band." + << std::endl; + return false; + } + } + return true; + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimBandSelector::outputBandsWithinInputRange() ERROR:" + << "Method called prior to initialization!" << std::endl; + } + + return false; +} + +void ossimBandSelector::getOutputBandList( + std::vector<ossim_uint32>& bandList) const +{ + if ( theOutputBandList.size() ) + { + bandList = theOutputBandList; + } + else if (theInputConnection) + { + theInputConnection->getOutputBandList(bandList); + } + else + { + bandList.clear(); + } +} + +ossimString ossimBandSelector::getLongName()const +{ + return ossimString("Band Selector, maps an input band to the output band."); +} + +ossimString ossimBandSelector::getShortName()const +{ + return ossimString("Band Selector"); +} + +void ossimBandSelector::setProperty(ossimRefPtr<ossimProperty> property) +{ + ossim_uint32 i =0; + if(!property) return; + + if(property->getName() == "Selected bands") + { + ossimString str = property->valueToString(); + std::vector<ossimString> str_vec; + std::vector<ossim_uint32> int_vec; + + str.split( str_vec, "," ); + + for ( i = 0; i < str_vec.size(); ++i ) + { + int_vec.push_back( str_vec[i].toUInt32() ); + } + setOutputBandList( int_vec ); + } + else + { + ossimImageSourceFilter::setProperty(property); + } +} + +ossimRefPtr<ossimProperty> ossimBandSelector::getProperty(const ossimString& name)const +{ + ossim_uint32 i = 0; + if(name == "Selected bands") + { + std::vector<ossim_uint32> bands; + + getOutputBandList( bands ); + + std::vector<ossimString> bandNames; + + for(i = 0; i < bands.size(); i++) + { + bandNames.push_back( ossimString::toString( bands[i] ) ); + } + + ossimString str; + + str.join( bandNames, "," ); + + ossimStringProperty* stringProp = new ossimStringProperty("Selected bands", str); + + stringProp->clearChangeType(); + stringProp->setReadOnlyFlag(false); + stringProp->setCacheRefreshBit(); + + return stringProp; + } + + return ossimImageSourceFilter::getProperty(name); +} + +void ossimBandSelector::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + ossimImageSourceFilter::getPropertyNames(propertyNames); + propertyNames.push_back("Selected bands"); +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandSelector.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandSelector.h new file mode 100644 index 0000000000..a8f464120f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBandSelector.h @@ -0,0 +1,119 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt. +// +// Author: Garrett Potts +// +// Description: Contains class declaration for ossimBandSelector. +// +//******************************************************************* +// $Id: ossimBandSelector.h,v 1.10 2005/12/19 20:01:37 dburken Exp $ +#ifndef ossimBandSelector_HEADER +#define ossimBandSelector_HEADER + +#include <vector> +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +class ossimImageData; + +class OSSIMDLLEXPORT ossimBandSelector : public ossimImageSourceFilter +{ + +public: + ossimBandSelector(); + + virtual ~ossimBandSelector(); + + virtual ossimString getLongName() const; + virtual ossimString getShortName() const; + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + + /** + * Initializes bandList to the zero based order of output bands. + */ + virtual void getOutputBandList(std::vector<ossim_uint32>& bandList) const; + + /** + * Sets the output band list. + * + * @param outputBandList List of zero based bands. + * + * @note The input connection should be established prior to calling this. + * + * @note Bands can be duplicated. So if you have a single band input you + * can do a band list like "1, 1, 1". Any band within the list must be + * available from the input. So if you have a 3 band input bands must be + * constrained to zero based bands "0, 1, or 2". + * + * @note Calling this method does not enable filter so callers should do: + * theBandSelector->enableSource(); + * theBandSelector->setOutputBandList(bandList); + */ + virtual void setOutputBandList(const vector<ossim_uint32>& outputBandList); + + /** + * Returns the number of bands in a tile returned from this TileSource. + */ + virtual ossim_uint32 getNumberOfOutputBands() const; + + virtual void initialize(); + + virtual double getMinPixelValue(ossim_uint32 band=0)const; + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + + /** + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=NULL)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=NULL); + /** + * Override base class so that a disableSource event does not + * reinitialize the object and enable itself. + */ + //virtual void propertyEvent(ossimPropertyEvent& event); + //virtual void refreshEvent(ossimRefreshEvent& event); + + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + + +private: + + /** + * Called on first getTile, will initialize all data needed. + */ + void allocate(); + + /** + * @return true if theInputConnection->getOutputBandList is equal to + * this->theOutputBandList, false if not. + */ + bool isOrderedCorrectly() const; + + /** + * @return true if all bands in theOutputBandList are less than the + * number of input's bands. + */ + bool outputBandsWithinInputRange() const; + + + ossimRefPtr<ossimImageData> theTile; + vector<ossim_uint32> theOutputBandList; + + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBlendMosaic.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBlendMosaic.cpp new file mode 100644 index 0000000000..657f2dd40f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBlendMosaic.cpp @@ -0,0 +1,624 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimBlendMosaic.cpp,v 1.37 2005/06/30 15:14:57 gpotts Exp $ + +#include <imaging/tile_sources/ossimBlendMosaic.h> +#include <imaging/ossimImageData.h> +#include <base/data_types/ossimKeywordlist.h> +#include <imaging/factory/ossimImageDataFactory.h> + +RTTI_DEF1(ossimBlendMosaic, "ossimBlendMosaic", ossimImageMosaic) + +ossimBlendMosaic::ossimBlendMosaic() + : ossimImageMosaic(), + theNormResult(NULL) +{ +} + +ossimBlendMosaic::ossimBlendMosaic(vector<ossimImageSource*>& inputSources) + : ossimImageMosaic(inputSources), + theNormResult(NULL) +{ + initialize(); +} + +ossimBlendMosaic::~ossimBlendMosaic() +{ +} + +void ossimBlendMosaic::initialize() +{ + ossimImageMosaic::initialize(); + + allocate(); + + // if(theTile) + // { + // let's first check to see if all input scalars are the same. + // if they are then we will not have to normalize. Normalizing + // is slow and I only want to do it if we have to. + // + + // only allocate this space if we have to + if(hasDifferentInputs()) + { + theNormResult = new ossimImageData(this, + OSSIM_NORMALIZED_FLOAT, + theLargestNumberOfInputBands); + theNormResult->initialize(); + } + + if(theWeights.size() < theInputObjectList.size()) + { + for(ossim_uint32 index =theWeights.size(); + index < theInputObjectList.size(); + ++index) + { + theWeights.push_back(1.0); + } + } + // } +} + +ossimRefPtr<ossimImageData> ossimBlendMosaic::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + long w = tileRect.width(); + long h = tileRect.height(); + ossimIpt origin = tileRect.ul(); + if(!isSourceEnabled()) + { + return ossimImageMosaic::getTile(tileRect, resLevel); + } + + ossim_uint32 size = getNumberOfInputs(); + if(!theTile.get()) + { + // try to initialize + initialize(); + + // if we still don't have a buffer + // then we will leave + if(!theTile.get()) + { + return theTile; + } + } + + if(size == 0) + { + return ossimRefPtr<ossimImageData>(); + } + if(size == 1) + { + return ossimImageMosaic::getTile(tileRect, resLevel); + } + + long tileW = theTile->getWidth(); + long tileH = theTile->getHeight(); + if((w != tileW)|| + (h != tileH)) + { + theTile->setWidth(w); + theTile->setHeight(h); + if(hasDifferentInputs()) + { + theNormResult->setWidthHeight(w, h); + } + if((w*h)!=(tileW*tileH)) + { + theTile->initialize(); + + if(hasDifferentInputs()) + { + theNormResult->initialize(); + } + } + } + theTile->setOrigin(origin); + theTile->makeBlank(); + + switch(theTile->getScalarType()) + { + case OSSIM_UINT8: + { + if(!hasDifferentInputs()) + { + return combine(static_cast<ossim_uint8>(0), tileRect, resLevel); + } + else + { + return combineNorm(static_cast<ossim_uint8>(0), tileRect, + resLevel); + } + } + case OSSIM_SINT8: + { + if(!hasDifferentInputs()) + { + return combine(static_cast<ossim_sint8>(0), tileRect, resLevel); + } + else + { + return combineNorm(static_cast<ossim_sint8>(0), tileRect, + resLevel); + } + } + case OSSIM_FLOAT32: + case OSSIM_NORMALIZED_FLOAT: + { + if(!hasDifferentInputs()) + { + return combine(static_cast<float>(0), tileRect, resLevel); + } + else + { + return combineNorm(static_cast<float>(0), tileRect, resLevel); + } + } + case OSSIM_UINT16: + case OSSIM_USHORT11: + { + if(!hasDifferentInputs()) + { + return combine(static_cast<ossim_uint16>(0), tileRect, resLevel); + } + else + { + return combineNorm(static_cast<ossim_uint16>(0), tileRect, + resLevel); + } + } + case OSSIM_SINT16: + { + if(!hasDifferentInputs()) + { + return combine(static_cast<ossim_sint16>(0), tileRect, resLevel); + } + else + { + return combineNorm(static_cast<ossim_sint16>(0), tileRect, + resLevel); + } + } + case OSSIM_SINT32: + { + if(!hasDifferentInputs()) + { + return combine(static_cast<ossim_sint32>(0), tileRect, resLevel); + } + else + { + return combineNorm(static_cast<ossim_sint32>(0), tileRect, + resLevel); + } + } + case OSSIM_UINT32: + { + if(!hasDifferentInputs()) + { + return combine(static_cast<ossim_uint32>(0), tileRect, resLevel); + } + else + { + return combineNorm(static_cast<ossim_uint32>(0), tileRect, + resLevel); + } + } + case OSSIM_FLOAT64: + case OSSIM_NORMALIZED_DOUBLE: + { + if(!hasDifferentInputs()) + { + return combine(static_cast<double>(0), tileRect, resLevel); + } + else + { + return combineNorm(static_cast<double>(0), tileRect, resLevel); + } + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimBlendMosaic::getTile NOTICE:\n" + << "Scalar type = " << theTile->getScalarType() + << " Not supported by ossimImageMosaic" << endl; + } + } + + return ossimRefPtr<ossimImageData>(); +} + +template <class T> ossimRefPtr<ossimImageData> ossimBlendMosaic::combine( + T, + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + ossimRefPtr<ossimImageData> currentImageData=NULL; + ossim_uint32 band; + double currentWeight = 1.0; + double previousWeight = 1.0; + double sumOfWeights = 1; + long offset = 0; + long row = 0; + long col = 0; + + currentImageData = getNextTile(0, tileRect, resLevel); + + if(!currentImageData.get()) // if we don't have one then return theTile + { + return theTile; + } + + T** srcBands = new T*[theLargestNumberOfInputBands]; + T** destBands = new T*[theLargestNumberOfInputBands]; + T* nullPix = new T[theTile->getNumberOfBands()]; + + previousWeight = theWeights[theCurrentIndex]; + // // now get the previous weight and then combine the two into one. + // let's assign the bands + for(band = 0; band < theLargestNumberOfInputBands; ++band) + { + destBands[band] = static_cast<T*>(theTile->getBuf(band)); + nullPix[band] = static_cast<T>(theTile->getNullPix(band)); + } + while(currentImageData.get()) + { + ossimDataObjectStatus currentStatus = + currentImageData->getDataObjectStatus(); + + // set the current weight for the current tile. + currentWeight = theWeights[theCurrentIndex]; + + sumOfWeights = previousWeight+currentWeight; + if( (currentStatus != OSSIM_EMPTY) && + (currentStatus != OSSIM_NULL)) + { + long h = (long)currentImageData->getHeight(); + long w = (long)currentImageData->getWidth(); + offset = 0; + ossim_uint32 minNumberOfBands = currentImageData->getNumberOfBands(); + + // let's assign the bands + for(band = 0; band < minNumberOfBands; ++band) + { + srcBands[band] = static_cast<T*>(currentImageData->getBuf(band)); + } + for(;band < theLargestNumberOfInputBands; ++band) + { + srcBands[band] = srcBands[minNumberOfBands - 1]; + } + + if(currentStatus == OSSIM_PARTIAL) + { + for(row = 0; row < h; ++row) + { + for(col = 0; col < w; ++col) + { + if(!currentImageData->isNull(offset)) + { + for(band = 0; band < theLargestNumberOfInputBands; ++band) + { + if(destBands[band][offset] != nullPix[band]) + { +// destBands[band][offset] = static_cast<T>((destBands[band][offset]*(1.0-currentWeight) + +// srcBands[band][offset]*currentWeight)); + destBands[band][offset] = static_cast<T>((destBands[band][offset]*previousWeight + + srcBands[band][offset]*currentWeight)/(previousWeight+currentWeight)); + } + else + { + destBands[band][offset] = srcBands[band][offset]; + } + } + } + ++offset; + } + } + } + else + { + for(row = 0; row < h; ++row) + { + for(col = 0; col < w; ++col) + { + for(band = 0; band < theLargestNumberOfInputBands; ++band) + { + if(destBands[band][offset] != nullPix[band]) + { + destBands[band][offset] = static_cast<T>((destBands[band][offset]*previousWeight+ + srcBands[band][offset]*currentWeight)/(previousWeight + currentWeight)); + } + else + { + destBands[band][offset] = srcBands[band][offset]; + } + } + ++offset; + } + } + } + } + currentImageData = getNextTile(tileRect, resLevel); + previousWeight = (previousWeight+currentWeight)/2.0; + } + delete [] srcBands; + delete [] destBands; + delete [] nullPix; + theTile->validate(); + + return theTile; +} + +template <class T> ossimRefPtr<ossimImageData> ossimBlendMosaic::combineNorm( + T, + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + ossimRefPtr<ossimImageData> currentImageData=NULL; + ossim_uint32 band; + double currentWeight = 1.0; + double previousWeight = 1.0; + double sumOfWeights = 1; + long offset = 0; + long row = 0; + long col = 0; + + currentImageData = getNextNormTile(0, tileRect, resLevel); + + if(!currentImageData.get()) // if we don't have one then return theTile + { + return theTile; + } + theNormResult->makeBlank(); + float** srcBands = new float*[theLargestNumberOfInputBands]; + float** destBands = new float*[theLargestNumberOfInputBands]; + float* nullPix = new float[theTile->getNumberOfBands()]; + + previousWeight = theWeights[theCurrentIndex]; + // // now get the previous weight and then combine the two into one. + // let's assign the bands + for(band = 0; band < theLargestNumberOfInputBands; ++band) + { + destBands[band] = static_cast<float*>(theNormResult->getBuf(band)); + nullPix[band] = static_cast<float>(theNormResult->getNullPix(band)); + } + while(currentImageData.get()) + { + ossimDataObjectStatus currentStatus = currentImageData->getDataObjectStatus(); + + // set the current weight for the current tile. + currentWeight = theWeights[theCurrentIndex]; + + sumOfWeights = previousWeight+currentWeight; + if( (currentStatus != OSSIM_EMPTY) && + (currentStatus != OSSIM_NULL)) + { + long h = (long)currentImageData->getHeight(); + long w = (long)currentImageData->getWidth(); + offset = 0; + ossim_uint32 minNumberOfBands = currentImageData->getNumberOfBands(); + + // let's assign the bands + for(band = 0; band < minNumberOfBands; ++band) + { + srcBands[band] = static_cast<float*>(currentImageData->getBuf(band)); + } + for(;band < theLargestNumberOfInputBands; ++band) + { + srcBands[band] = srcBands[minNumberOfBands - 1]; + } + + if(currentStatus == OSSIM_PARTIAL) + { + for(row = 0; row < h; ++row) + { + for(col = 0; col < w; ++col) + { + if(!currentImageData->isNull(offset)) + { + for(band = 0; band < theLargestNumberOfInputBands; ++band) + { + if(destBands[band][offset] != nullPix[band]) + { + destBands[band][offset] = static_cast<float>((destBands[band][offset]*previousWeight + + srcBands[band][offset]*currentWeight)/(previousWeight+currentWeight)); + } + else + { + destBands[band][offset] = srcBands[band][offset]; + } + } + } + ++offset; + } + } + } + else + { + for(row = 0; row < h; ++row) + { + for(col = 0; col < w; ++col) + { + for(band = 0; band < theLargestNumberOfInputBands; ++band) + { + if(destBands[band][offset] != nullPix[band]) + { + destBands[band][offset] = static_cast<float>((destBands[band][offset]*previousWeight+ + srcBands[band][offset]*currentWeight)/(previousWeight + currentWeight)); + } + else + { + destBands[band][offset] = srcBands[band][offset]; + } + } + ++offset; + } + } + } + } + currentImageData = getNextNormTile(tileRect, resLevel); + previousWeight = (previousWeight+currentWeight)/2.0; + } + theNormResult->validate(); + theTile->copyNormalizedBufferToTile((float*)theNormResult->getBuf()); + delete [] srcBands; + delete [] destBands; + delete [] nullPix; + theTile->validate(); + + return theTile; +} + +bool ossimBlendMosaic::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + bool result = ossimImageMosaic::saveState(kwl, prefix); + + ossimString copyPrefix = prefix; + for(ossim_uint32 index = 0; index < theWeights.size(); ++index) + { + ossimString weightStr = ossimString("weight") + + ossimString::toString(index); + kwl.add(copyPrefix.c_str(), + weightStr.c_str(), + theWeights[index], + true); + } + + return result; +} + +bool ossimBlendMosaic::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + bool result = ossimImageMosaic::loadState(kwl, prefix); + long count = 0; + theWeights.clear(); + if(result) + { + ossimString copyPrefix = prefix; + ossimString regExpression = ossimString("^(") + copyPrefix + "weight[0-9]+)"; + long result = kwl.getNumberOfSubstringKeys(regExpression); + + long numberOfMatches = 0; + while(numberOfMatches < result) + { + ossimString value = ossimString("weight") + ossimString::toString(count); + + const char* lookup = kwl.find(copyPrefix.c_str(), + value.c_str()); + + if(lookup) + { + ++numberOfMatches; + theWeights.push_back(ossimString(lookup).toDouble()); + } + + ++count; + } + } + + return result; +} + + +void ossimBlendMosaic::setNumberOfWeights(ossim_uint32 numberOfWeights) +{ + if(numberOfWeights > theWeights.size()) + { + ossim_uint32 length = numberOfWeights - theWeights.size(); + for(ossim_uint32 index= 0; index < length; ++ index) + { + theWeights.push_back(1.0); + } + } + else if(numberOfWeights < theWeights.size()) + { + // copy the list + vector<double> temp(theWeights.begin(), + theWeights.begin()+numberOfWeights); + // now shrink + theWeights = temp; + } +} + +void ossimBlendMosaic::setAllWeightsTo(double value) +{ + for(ossim_uint32 index = 0; index < theWeights.size(); ++index) + { + theWeights[index] = value; + } +} + +void ossimBlendMosaic::normalizeWeights() +{ + double sumWeights=0.0; + ossim_uint32 index = 0; + for(index = 0; index < theWeights.size(); ++index) + { + sumWeights+=theWeights[index]; + } + if(sumWeights > 0.0) + { + for(index = 0; index < theWeights.size(); ++index) + { + theWeights[index] /= sumWeights; + } + } +} + +void ossimBlendMosaic::findMinMax(double& minValue, double& maxValue)const +{ + if(theWeights.size() > 0) + { + minValue = maxValue = theWeights[0]; + + for(ossim_uint32 index = 1; index < theWeights.size(); ++index) + { + minValue = minValue < theWeights[index]?minValue:theWeights[index]; + maxValue = maxValue > theWeights[index]?maxValue:theWeights[index]; + } + } +} + +void ossimBlendMosaic::setWeight(ossim_uint32 index, double weight) +{ + if(index < theWeights.size()) + { + theWeights[index] = weight; + } +} + +void ossimBlendMosaic::setWeights(const std::vector<double>& weights) +{ + theWeights = weights; +} + +const vector<double>& ossimBlendMosaic::getWeights()const +{ + return theWeights; +} + +double ossimBlendMosaic::getWeight(ossim_uint32 index) const +{ + if(index < theWeights.size()) + { + return theWeights[index]; + } + if(theWeights.size()) + { + return theWeights[theWeights.size()-1]; + } + return 0; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBlendMosaic.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBlendMosaic.h new file mode 100644 index 0000000000..9a6b1a9efe --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBlendMosaic.h @@ -0,0 +1,78 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimBlendMosaic.h,v 1.22 2005/02/11 15:07:32 dburken Exp $ +#ifndef ossimBlendMosaic_HEADER +#define ossimBlendMosaic_HEADER +#include <imaging/tile_sources/ossimImageMosaic.h> + +class OSSIMDLLEXPORT ossimBlendMosaic : public ossimImageMosaic +{ +public: + ossimBlendMosaic(); + ossimBlendMosaic(vector<ossimImageSource*>& inputSources); + virtual ~ossimBlendMosaic(); + virtual void initialize(); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& origin, + ossim_uint32 resLevel=0); + /** + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=NULL)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=NULL); + + void setWeight(ossim_uint32 index, double weight); + void setWeights(const std::vector<double>& weights); + + double getWeight(ossim_uint32 index) const; + const std::vector<double>& getWeights()const; + + + void setNumberOfWeights(ossim_uint32 numberOfWeights); + void setAllWeightsTo(double value); + + /** + * Will find the min and max values and then + * normalize all weights to be from 0 to 1 + */ + void normalizeWeights(); + void findMinMax(double& minValue, double& maxValue)const; + +protected: + vector<double> theWeights; + ossimRefPtr<ossimImageData> theNormResult; + /** + * If our inputs have output of different scalar + * types then we must normalize so we can blend + * different scalar data together. + */ + + + template <class T> + ossimRefPtr<ossimImageData> combine(T, + const ossimIrect& tileRect, + ossim_uint32); + template <class T> + ossimRefPtr<ossimImageData> combineNorm(T, + const ossimIrect& tileRect, + ossim_uint32); +TYPE_DATA +}; + +#endif /* #ifndef ossimBlendMosaic_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBrightnessContrastSource.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBrightnessContrastSource.cpp new file mode 100644 index 0000000000..a34273f751 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBrightnessContrastSource.cpp @@ -0,0 +1,314 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See LICENSE.txt file in the top level directory. +// +// Author: Garrett Potts +// +// Description: A brief description of the contents of the file. +// +//************************************************************************* +// $Id: ossimBrightnessContrastSource.cpp,v 1.21 2005/12/02 20:03:46 dburken Exp $ + +#include <imaging/tile_sources/ossimBrightnessContrastSource.h> +#include <imaging/ossimImageData.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <base/common/ossimConstants.h> +#include <base/common/ossimCommon.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/common/ossimTrace.h> +#include <base/data_types/color_space/ossimHsiVector.h> +#include <base/data_types/color_space/ossimNormRgbVector.h> +#include <base/property/ossimContainerProperty.h> +#include <base/property/ossimNumericProperty.h> + +RTTI_DEF1(ossimBrightnessContrastSource, + "ossimBrightnessContrastSource", + ossimImageSourceFilter) + +ossimBrightnessContrastSource::ossimBrightnessContrastSource() + :ossimImageSourceFilter(), + theBrightness(0.0), + theContrast(1.0) +{ +} + + +ossimBrightnessContrastSource::~ossimBrightnessContrastSource() +{ +} + +ossimRefPtr<ossimImageData> ossimBrightnessContrastSource::getTile( + const ossimIrect& tileRect, ossim_uint32 resLevel) +{ + ossimRefPtr<ossimImageData> tile = NULL; + + if(theInputConnection) + { + tile = theInputConnection->getTile(tileRect, resLevel); + + if(!tile.valid()) + { + return tile; + } + + if(!isSourceEnabled() || + (tile->getDataObjectStatus()==OSSIM_NULL)|| + (tile->getDataObjectStatus()==OSSIM_EMPTY)|| + ( (theBrightness == 0.0) && (theContrast == 1.0) ) ) + { + return tile; + } + + if(!theTile.valid() || !theNormTile.valid()) + { + allocate(); + } + + if(!theTile.valid() || !theNormTile.valid()) + { + return tile; + } + + theTile->setImageRectangle(tileRect); + theNormTile->setImageRectangle(tileRect); + + tile->copyTileToNormalizedBuffer((ossim_float32*)theNormTile->getBuf()); + theNormTile->setDataObjectStatus(tile->getDataObjectStatus()); + + if (theNormTile->getNumberOfBands() == 3) + { + processRgbTile(); + } + else + { + processNBandTile(); + } + + theTile->copyNormalizedBufferToTile((ossim_float32*) + theNormTile->getBuf()); + theTile->validate(); + return theTile; + } + + return tile; +} + +void ossimBrightnessContrastSource::processRgbTile() +{ + ossim_float32* bands[3]; + + bands[0] = (ossim_float32*)theNormTile->getBuf(0); + bands[1] = (ossim_float32*)theNormTile->getBuf(1); + bands[2] = (ossim_float32*)theNormTile->getBuf(2); + + ossim_uint32 offset = 0; + ossim_uint32 maxIdx = theNormTile->getWidth()*theNormTile->getHeight(); + ossimHsiVector hsi; + ossim_float32 i; + if(theNormTile->getDataObjectStatus() == OSSIM_FULL) + { + for(offset = 0; offset < maxIdx; ++offset) + { + ossimNormRgbVector rgb(bands[0][offset], bands[1][offset], bands[2][offset]); + hsi = rgb; + i = (hsi.getI()*theContrast + theBrightness); + if(i < OSSIM_DEFAULT_MIN_PIX_NORM_FLOAT) i = OSSIM_DEFAULT_MIN_PIX_NORM_FLOAT; + if(i > 1.0) i = 1.0; + hsi.setI(i); + rgb = hsi; + bands[0][offset] = rgb.getR(); + bands[1][offset] = rgb.getG(); + bands[2][offset] = rgb.getB(); + } + } + else + { + for(offset = 0; offset < maxIdx; ++offset) + { + if((bands[0][offset] != 0.0)&& + (bands[1][offset] != 0.0)&& + (bands[2][offset] != 0.0)) + { + ossimNormRgbVector rgb(bands[0][offset], bands[1][offset], bands[2][offset]); + hsi = rgb; + i = (hsi.getI()*theContrast + theBrightness); + if(i < OSSIM_DEFAULT_MIN_PIX_NORM_FLOAT) i = OSSIM_DEFAULT_MIN_PIX_NORM_FLOAT; + if(i > 1.0) i = 1.0; + hsi.setI(i); + rgb = hsi; + bands[0][offset] = rgb.getR(); + bands[1][offset] = rgb.getG(); + bands[2][offset] = rgb.getB(); + } + } + } +} + +void ossimBrightnessContrastSource::processNBandTile() +{ + const ossim_uint32 BANDS = theNormTile->getNumberOfBands(); + const ossim_uint32 PPB = theNormTile->getSizePerBand(); + const ossim_float32 MP = theNormTile->getMinNormalizedPix(); + + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + ossim_float32* buf = theNormTile->getFloatBuf(band); + + for (ossim_uint32 i = 0; i < PPB; ++i) + { + if (buf[i] != 0.0) + { + ossim_float32 p = buf[i] * theContrast + theBrightness; + buf[i] = (p < 1.0) ? ( (p > MP) ? p : 0.0 ) : 1.0; + } + } + } +} + +void ossimBrightnessContrastSource::initialize() +{ + ossimImageSourceFilter::initialize(); + + theTile = 0; + theNormTile = 0; +} + +void ossimBrightnessContrastSource::allocate() +{ + if( isSourceEnabled() && theInputConnection ) + { + theTile = ossimImageDataFactory::instance()->create(this, this); + if(theTile.valid()) + { + theNormTile = ossimImageDataFactory::instance()->create(this, + OSSIM_FLOAT32, + theTile->getNumberOfBands()); + } + if(theTile.valid() && theNormTile.valid()) + { + theTile->initialize(); + theNormTile->initialize(); + } + else + { + theTile = 0; + theNormTile = 0; + } + } +} + +void ossimBrightnessContrastSource::setProperty(ossimRefPtr<ossimProperty> property) +{ + if(!property) + { + return; + } + ossimString name = property->getName(); + if(name == "brightness") + { + theBrightness = property->valueToString().toDouble(); + } + else if(name == "contrast") + { + theContrast = property->valueToString().toDouble(); + } + else + { + ossimImageSourceFilter::setProperty(property); + } +} + +ossimRefPtr<ossimProperty> ossimBrightnessContrastSource::getProperty(const ossimString& name)const +{ + if(name == "brightness") + { + ossimNumericProperty* numeric = new ossimNumericProperty(name, + ossimString::toString(getBrightness()), + -1.0, 1.0); + numeric->setNumericType(ossimNumericProperty::ossimNumericPropertyType_FLOAT64); + numeric->setCacheRefreshBit(); + return numeric; + } + else if(name == "contrast") + { + ossimNumericProperty* numeric = new ossimNumericProperty(name, + ossimString::toString(getContrast()), + 0.0, 20.0); + numeric->setNumericType(ossimNumericProperty::ossimNumericPropertyType_FLOAT64); + numeric->setCacheRefreshBit(); + return numeric; + } + + return ossimImageSourceFilter::getProperty(name); +} + +void ossimBrightnessContrastSource::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + ossimImageSourceFilter::getPropertyNames(propertyNames); + + propertyNames.push_back("brightness"); + propertyNames.push_back("contrast"); +} + + +bool ossimBrightnessContrastSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* brightness = kwl.find(prefix, "brightness"); + const char* contrast = kwl.find(prefix, "contrast"); + + if(brightness) + { + theBrightness = ossimString(brightness).toDouble(); + } + if(contrast) + { + theContrast = ossimString(contrast).toDouble(); + } + + return ossimImageSourceFilter::loadState(kwl, prefix); +} + +bool ossimBrightnessContrastSource::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + "brightness", + theBrightness, + true); + kwl.add(prefix, + "contrast", + theContrast, + true); + + return ossimImageSourceFilter::saveState(kwl, prefix); +} + + +void ossimBrightnessContrastSource::setBrightnessContrast( + ossim_float64 brightness, ossim_float64 contrast) +{ + theBrightness = brightness; + theContrast = contrast; +} + +void ossimBrightnessContrastSource::setBrightness(ossim_float64 brightness) +{ + setBrightnessContrast(brightness, getContrast()); +} + +void ossimBrightnessContrastSource::setContrast(ossim_float64 contrast) +{ + setBrightnessContrast(getBrightness(), contrast); +} + +ossim_float64 ossimBrightnessContrastSource::getBrightness()const +{ + return theBrightness; +} + +ossim_float64 ossimBrightnessContrastSource::getContrast()const +{ + return theContrast; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBrightnessContrastSource.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBrightnessContrastSource.h new file mode 100644 index 0000000000..6c2d1bc28b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBrightnessContrastSource.h @@ -0,0 +1,132 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See LICENSE.txt file in the top level directory. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimBrightnessContrastSource.h,v 1.18 2005/12/02 20:01:15 dburken Exp $ +#ifndef ossimBrightnessContrastSource_HEADER +#define ossimBrightnessContrastSource_HEADER +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +class OSSIM_DLL ossimBrightnessContrastSource : public ossimImageSourceFilter +{ +public: + + /** + * Currently works in hsi space so must be one or three bands. + * + * Todo: Make work with nband. + */ + ossimBrightnessContrastSource(); + + virtual ~ossimBrightnessContrastSource(); + + /** + * Will apply the algorithm: + * i*c + b + * where b is brightnes + * c is contrast + * i is the input value. + * + */ + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + + /** + * @param brightness Value between -1.0 and +1.0 with zero being no + * brightness offset. + * + * @param contrast Value between 0.0 and 2.0 with 1.0 being no contrast + * adjustment. + */ + virtual void setBrightnessContrast(ossim_float64 brightness, + ossim_float64 contrast); + + /** + * @param brightness Value between -1.0 and +1.0 with zero being no + * brightness offset. + */ + virtual void setBrightness(ossim_float64 brightness); + + /** + * @param contrast Value between 0.0 and 2.0 with 1.0 being no contrast + * adjustment. + */ + virtual void setContrast(ossim_float64 contrast); + + /** @return Brightness value between -1.0 and +1.0. */ + virtual ossim_float64 getBrightness()const; + + /** @return Contrast value between 0.0 and +2.0. */ + virtual ossim_float64 getContrast()const; + + /** + * Calls base ossimImageSourceFilter::initialize() to reset connection if + * needed then nulls out tiles. + * + * @note This does not initialize tiles intentionally to avoid repeated + * deletes and news. Tiles will be initialized by allocate() method on + * the first getTile call after an initialize. + */ + virtual void initialize(); + + /*---------------------- PROPERTY INTERFACE ---------------------------*/ + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + /*--------------------- PROPERTY INTERFACE END ------------------------*/ + + /** + * Keywords searched for by this method. + * + * brightness: 0.0 + * + * contrast: 1.0 + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * Keywords saved to list by this method. + * + * brightness: 0.0 + * + * contrast: 1.0 + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; +protected: + + /** + * Called to initialize tiles by first get tile when theTile or theNormTile + * are not initialized. + */ + void allocate(); + + /** + * Applies the brightness contrast to tile. This method works in hsi + * space on the intensity channel; thus, preserving hue and saturation + * of an rgb pixel. Called if input has three bands. + */ + void processRgbTile(); + + /** + * Applies the brightness contrast to tile. This method simply applies + * brightness contrast to all bands. Called if input does not have + * three bands. + */ + void processNBandTile(); + + + ossim_float64 theBrightness; + ossim_float64 theContrast; + ossimRefPtr<ossimImageData> theTile; + ossimRefPtr<ossimImageData> theNormTile; + +TYPE_DATA +}; + +#endif /* End of "#ifndef ossimBrightnessContrastSource_HEADER" */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBrightnessMatch.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBrightnessMatch.cpp new file mode 100644 index 0000000000..a85c3553ea --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBrightnessMatch.cpp @@ -0,0 +1,247 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: A brief description of the contents of the file. +// +//************************************************************************* +// $Id: ossimBrightnessMatch.cpp,v 1.2 2005/09/08 14:14:55 gpotts Exp $ + +#include <imaging/tile_sources/ossimBrightnessMatch.h> +#include <imaging/ossimImageData.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <base/common/ossimConstants.h> +#include <base/common/ossimCommon.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/common/ossimTrace.h> +#include <base/data_types/color_space/ossimNormRgbVector.h> +#include <base/data_types/color_space/ossimHsiVector.h> +#include <base/property/ossimContainerProperty.h> +#include <base/property/ossimNumericProperty.h> + +RTTI_DEF1(ossimBrightnessMatch, + "ossimBrightnessMatch", + ossimImageSourceFilter) + +ossimBrightnessMatch::ossimBrightnessMatch() + :ossimImageSourceFilter(), + theTargetBrightness(0.5), + theInputBrightness(0.5) +{ + theInputBrightness = OSSIM_DBL_NAN; + theBrightnessContrastSource = new ossimBrightnessContrastSource; +} + + +ossimBrightnessMatch::~ossimBrightnessMatch() +{ +} + +ossimRefPtr<ossimImageData> ossimBrightnessMatch::getTile( + const ossimIrect& tileRect, ossim_uint32 resLevel) +{ + if(!isSourceEnabled()) + { + return ossimImageSourceFilter::getTile(tileRect, resLevel); + } + if(theInputConnection) + { + if(theInputBrightness == OSSIM_DBL_NAN) + { + computeInputBrightness(); + } + return theBrightnessContrastSource->getTile(tileRect, resLevel); + } + return 0; +} + +void ossimBrightnessMatch::initialize() +{ + theBrightnessContrastSource->connectMyInputTo(0, getInput()); + theNormTile = 0; +} + +void ossimBrightnessMatch::setProperty(ossimRefPtr<ossimProperty> property) +{ + if(!property) + { + return; + } + ossimString name = property->getName(); + if(name == "input_brightness") + { + theInputBrightness = property->valueToString().toDouble(); + theBrightnessContrastSource->setBrightness(theTargetBrightness-theInputBrightness); + } + else if(name == "target_brightness") + { + theTargetBrightness = property->valueToString().toDouble(); + theBrightnessContrastSource->setBrightness(theTargetBrightness-theInputBrightness); + } + else + { + ossimImageSourceFilter::setProperty(property); + } +} + +ossimRefPtr<ossimProperty> ossimBrightnessMatch::getProperty(const ossimString& name)const +{ + if(name == "target_brightness") + { + ossimNumericProperty* numeric = new ossimNumericProperty(name, + ossimString::toString(theTargetBrightness), + 0.0, 1.0); + numeric->setNumericType(ossimNumericProperty::ossimNumericPropertyType_FLOAT64); + numeric->setCacheRefreshBit(); + return numeric; + } + else if(name == "input_brightness") + { + ossimNumericProperty* numeric = new ossimNumericProperty(name, + ossimString::toString(theInputBrightness), + 0.0, 1.0); + numeric->setNumericType(ossimNumericProperty::ossimNumericPropertyType_FLOAT64); + numeric->setCacheRefreshBit(); + return numeric; + } + + return ossimImageSourceFilter::getProperty(name); +} + +void ossimBrightnessMatch::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + ossimImageSourceFilter::getPropertyNames(propertyNames); + + propertyNames.push_back("input_brightness"); + propertyNames.push_back("target_brightness"); +} + + +bool ossimBrightnessMatch::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* input_brightness = kwl.find(prefix, "input_brightness"); + const char* target_brightness = kwl.find(prefix, "target_brightness"); + + if(input_brightness) + { + theInputBrightness = ossimString(input_brightness).toDouble(); + } + if(target_brightness) + { + theTargetBrightness = ossimString(target_brightness).toDouble(); + } + + return ossimImageSourceFilter::loadState(kwl, prefix); +} + +bool ossimBrightnessMatch::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + "input_brightness", + theInputBrightness, + true); + kwl.add(prefix, + "target_brightness", + theTargetBrightness, + true); + + return ossimImageSourceFilter::saveState(kwl, prefix); +} + + +void ossimBrightnessMatch::computeInputBrightness() +{ + if(theInputConnection) + { + ossimIrect inputRect = getBoundingRect(); + ossim_uint32 rlevel = 0; + ossim_uint32 nlevels = getNumberOfDecimationLevels(); + if(nlevels>1) + { + while((ossimMax(inputRect.width(), inputRect.height()) > 2048)&& + (rlevel < nlevels)) + { + ++rlevel; + inputRect = getBoundingRect(rlevel); + } + } + ossimIpt centerPt = inputRect.midPoint(); + centerPt.x -= 1024; + centerPt.y -= 1024; + ossimIrect reqRect(centerPt.x, + centerPt.y, + centerPt.x + 2047, + centerPt.x + 2047); + reqRect = reqRect.clipToRect(inputRect); + ossimRefPtr<ossimImageData> inputTile = theInputConnection->getTile(reqRect, rlevel); + + if(inputTile.valid()) + { + theNormTile = new ossimImageData(0, + OSSIM_FLOAT32, + inputTile->getNumberOfBands()); + theNormTile->initialize(); + theNormTile->setImageRectangle(reqRect); + inputTile->copyTileToNormalizedBuffer((ossim_float32*)theNormTile->getBuf()); + theNormTile->setDataObjectStatus(inputTile->getDataObjectStatus()); + ossim_uint32 maxIdx = theNormTile->getWidth()*theNormTile->getHeight(); + ossim_float32* bands[3]; + double averageI = 0.0; + double count = 0.0; + ossim_uint32 offset = 0; + + bands[0] = (ossim_float32*)theNormTile->getBuf(); + if(theNormTile->getNumberOfBands()>2) + { + bands[1] = (ossim_float32*)theNormTile->getBuf(1); + bands[2] = (ossim_float32*)theNormTile->getBuf(2); + } + else + { + bands[1] = bands[0]; + bands[2] = bands[0]; + } + ossimHsiVector hsi; + if(theNormTile->getDataObjectStatus() == OSSIM_FULL) + { + count = maxIdx; + + for(offset = 0; offset < maxIdx; ++offset) + { + hsi = ossimNormRgbVector(bands[0][offset], bands[1][offset], bands[2][offset]); + + averageI += hsi.getI(); + } + } + else + { + for(offset = 0; offset < maxIdx; ++offset) + { + if((bands[0][offset] != 0.0)&& + (bands[1][offset] != 0.0)&& + (bands[2][offset] != 0.0)) + { + hsi = ossimNormRgbVector(bands[0][offset], bands[1][offset], bands[2][offset]); + averageI += hsi.getI(); + + ++count; + } + } + } + theInputBrightness = averageI / count; + theBrightnessContrastSource->setBrightness(theTargetBrightness-theInputBrightness); + } + else + { + theInputBrightness = .5; + } + } + theNormTile = 0; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBrightnessMatch.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBrightnessMatch.h new file mode 100644 index 0000000000..81bf871ff6 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBrightnessMatch.h @@ -0,0 +1,56 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: A brief description of the contents of the file. +// +//************************************************************************* +// $Id: ossimBrightnessMatch.h,v 1.1 2005/09/08 13:06:37 gpotts Exp $ +#ifndef ossimBrightnessMatch_HEADER +#define ossimBrightnessMatch_HEADER +#include <imaging/tile_sources/ossimImageSourceFilter.h> +#include "ossimBrightnessContrastSource.h" + +class ossimBrightnessMatch : public ossimImageSourceFilter +{ +public: + ossimBrightnessMatch(); + + + virtual ~ossimBrightnessMatch(); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + + + virtual void initialize(); + /*---------------------- PROPERTY INTERFACE ---------------------------*/ + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + /*--------------------- PROPERTY INTERFACE END ------------------------*/ + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; +protected: + double theTargetBrightness; + double theInputBrightness; + ossimRefPtr<ossimImageData> theNormTile; + + ossimRefPtr<ossimBrightnessContrastSource> theBrightnessContrastSource; + + ossimRefPtr<ossimImageData> runBrightnessMatch(); + + void computeInputBrightness(); +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBumpShadeTileSource.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBumpShadeTileSource.cpp new file mode 100644 index 0000000000..8e51597273 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBumpShadeTileSource.cpp @@ -0,0 +1,507 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimBumpShadeTileSource.cpp,v 1.43 2005/07/22 14:57:09 dburken Exp $ + +#include <imaging/tile_sources/ossimBumpShadeTileSource.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <imaging/ossimImageData.h> +#include <imaging/patch/ossimTilePatch.h> +#include <imaging/ossimImageData.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/common/ossimKeywordNames.h> +#include <base/data_types/ossimKeyword.h> +#include <base/data_types/ossimMatrix3x3.h> +#include <base/data_types/color_space/ossimRgbVector.h> +#include <imaging/tile_sources/ossimImageToPlaneNormalFilter.h> + +RTTI_DEF1(ossimBumpShadeTileSource, + "ossimBumpShadeTileSource", + ossimImageCombiner); + + +ossimBumpShadeTileSource::ossimBumpShadeTileSource() + :ossimImageCombiner(NULL, 2, 0, true, false), + theTile(NULL), + theLightSourceElevationAngle(45.0), + theLightSourceAzimuthAngle(45.0), + theLightDirection(3) +{ + initialize(); +} + +ossimBumpShadeTileSource::~ossimBumpShadeTileSource() +{ +} + +ossimRefPtr<ossimImageData> ossimBumpShadeTileSource::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if(!getInput(0)) return NULL; + + if(!theTile.get()) + { + initialize(); + } + + ossimImageSourceInterface* normalSource = + PTR_CAST(ossimImageSourceInterface, getInput(0)); + ossimImageSourceInterface* colorSource = + PTR_CAST(ossimImageSourceInterface, getInput(1)); + + if(!theTile.get()) + { + return ossimRefPtr<ossimImageData>(); + } + + long w = tileRect.width(); + long h = tileRect.height(); + ossimIpt origin = tileRect.ul(); + + theTile->setOrigin(origin); + + long tileW = theTile->getWidth(); + long tileH = theTile->getHeight(); + if((w != tileW)|| + (h != tileH)) + { + theTile->setWidth(w); + theTile->setHeight(h); + if((w*h)!=(tileW*tileH)) + { + theTile->initialize(); + } + } + + ossimRefPtr<ossimImageData> inputTile = NULL; + + if(isSourceEnabled()) + { + theTile->makeBlank(); + + if(colorSource) + { + + inputTile = colorSource->getTile(tileRect, resLevel); + } + ossimRefPtr<ossimImageData> normalData = normalSource->getTile(tileRect, resLevel); + if(!normalData) + { + return ossimRefPtr<ossimImageData>(); + } + if ( (normalData->getDataObjectStatus() == OSSIM_NULL) || + (normalData->getDataObjectStatus() == OSSIM_EMPTY)|| + (normalData->getNumberOfBands() != 3)|| + (normalData->getScalarType() != OSSIM_DOUBLE)) + { + return ossimRefPtr<ossimImageData>(); + } + ossim_float64* normalBuf[3]; + normalBuf[0] = static_cast<ossim_float64*>(normalData->getBuf(0)); + normalBuf[1] = static_cast<ossim_float64*>(normalData->getBuf(1)); + normalBuf[2] = static_cast<ossim_float64*>(normalData->getBuf(2)); + ossim_float64 normalNp = normalData->getNullPix(0); + // if we have some color data then use it for the bump + // else we will default to a grey scale bump shade + // + if(inputTile.get() && + (inputTile->getDataObjectStatus() != OSSIM_EMPTY) && + (inputTile->getDataObjectStatus() != OSSIM_NULL)) + + { + switch(inputTile->getScalarType()) + { + case OSSIM_UCHAR: + { + ossim_uint8* resultBuf[3]; + ossim_uint8* colorBuf[3]; + resultBuf[0] = static_cast<ossim_uint8*>(theTile->getBuf(0)); + resultBuf[1] = static_cast<ossim_uint8*>(theTile->getBuf(1)); + resultBuf[2] = static_cast<ossim_uint8*>(theTile->getBuf(2)); + colorBuf[0] = static_cast<ossim_uint8*>(inputTile->getBuf(0)); + if(inputTile->getBuf(1)) + { + colorBuf[1] = static_cast<ossim_uint8*>(inputTile->getBuf(1)); + } + else + { + colorBuf[1] = colorBuf[0]; + } + if(inputTile->getBuf(2)) + { + colorBuf[2] = static_cast<ossim_uint8*>(inputTile->getBuf(2)); + } + else + { + colorBuf[2] = colorBuf[0]; + } + + long h = theTile->getHeight(); + long w = theTile->getWidth(); + for(long y = 0; y < h; ++y) + { + for(long x = 0; x < w; ++x) + { + if((*normalBuf[0] != normalNp) && + (*normalBuf[1] != normalNp) && + (*normalBuf[2] != normalNp) ) + { + if((*colorBuf[0])||(*colorBuf[1])||(*colorBuf[2])) + { + computeColor(*resultBuf[0], + *resultBuf[1], + *resultBuf[2], + *normalBuf[0], + *normalBuf[1], + *normalBuf[2], + *colorBuf[0], + *colorBuf[1], + *colorBuf[2]); + } + else + { + computeColor(*resultBuf[0], + *resultBuf[1], + *resultBuf[2], + *normalBuf[0], + *normalBuf[1], + *normalBuf[2], + 255, + 255, + 255); + } + } + else + { + *resultBuf[0] = *colorBuf[0]; + *resultBuf[1] = *colorBuf[1]; + *resultBuf[2] = *colorBuf[2]; + } + resultBuf[0]++; + resultBuf[1]++; + resultBuf[2]++; + colorBuf[0]++; + colorBuf[1]++; + colorBuf[2]++; + normalBuf[0]++; + normalBuf[1]++; + normalBuf[2]++; + } + } + break; + } + default: + { + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimBumpShadeTileSource::getTile NOTICE:\n" + << "only 8-bit unsigned char is supported." << endl; + } + } + } + else + { + ossim_uint8* resultBuf[3]; + resultBuf[0] = static_cast<ossim_uint8*>(theTile->getBuf(0)); + resultBuf[1] = static_cast<ossim_uint8*>(theTile->getBuf(1)); + resultBuf[2] = static_cast<ossim_uint8*>(theTile->getBuf(2)); + long h = theTile->getHeight(); + long w = theTile->getWidth(); + for(long y = 0; y < h; ++y) + { + for(long x = 0; x < w; ++x) + { + if((*normalBuf[0] != normalNp) && + (*normalBuf[1] != normalNp) && + (*normalBuf[2] != normalNp) ) + { + computeColor(*resultBuf[0], + *resultBuf[1], + *resultBuf[2], + *normalBuf[0], + *normalBuf[1], + *normalBuf[2], + (ossim_uint8)255, + (ossim_uint8)255, + (ossim_uint8)255); + } + else + { + *resultBuf[0] = 0; + *resultBuf[1] = 0; + *resultBuf[2] = 0; + } + resultBuf[0]++; + resultBuf[1]++; + resultBuf[2]++; + normalBuf[0]++; + normalBuf[1]++; + normalBuf[2]++; + } + } + } + } + theTile->validate(); + return theTile; +} + +void ossimBumpShadeTileSource::computeColor(ossim_uint8& r, + ossim_uint8& g, + ossim_uint8& b, + ossim_float64 normalX, + ossim_float64 normalY, + ossim_float64 normalZ, + ossim_uint8 dr, + ossim_uint8 dg, + ossim_uint8 db)const +{ + double c = normalX*theLightDirection[0] + + normalY*theLightDirection[1] + + normalZ*theLightDirection[2]; + + if(fabs(c) > FLT_EPSILON) + { + r = ossimRgbVector::clamp(irint(c*dr), 1, 255); + g = ossimRgbVector::clamp(irint(c*dg), 1, 255); + b = ossimRgbVector::clamp(irint(c*db), 1, 255); + } + else + { + r = 1; + g = 1; + b = 1; + } +} + +ossimIrect ossimBumpShadeTileSource::getBoundingRect(ossim_uint32 resLevel)const +{ + ossimImageSourceInterface* source = PTR_CAST(ossimImageSourceInterface, getInput(0)); + if(source) + { + return source->getBoundingRect(resLevel); + } + ossimDrect rect; + rect.makeNan(); + return rect; +} + + +void ossimBumpShadeTileSource::getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result) const +{ + ossimImageSourceInterface* source = PTR_CAST(ossimImageSourceInterface, getInput(0)); + if(source) + { + return source->getDecimationFactor(resLevel, result); + } + + result.makeNan(); +} + +void ossimBumpShadeTileSource::getDecimationFactors(vector<ossimDpt>& decimations) const +{ + ossimImageSourceInterface* source = PTR_CAST(ossimImageSourceInterface, getInput(0)); + + if(source) + { + return source->getDecimationFactors(decimations); + } +} + +ossim_uint32 ossimBumpShadeTileSource::getNumberOfDecimationLevels()const +{ + ossimImageSourceInterface* source = PTR_CAST(ossimImageSourceInterface, getInput(0)); + + if(source) + { + return source->getNumberOfDecimationLevels(); + } + + return 0; +} + +ossim_uint32 ossimBumpShadeTileSource::getTileWidth()const +{ + ossimImageSourceInterface* source = PTR_CAST(ossimImageSourceInterface, getInput(0)); + if(source) + { + return source->getTileWidth(); + } + + return 128; +} + +ossim_uint32 ossimBumpShadeTileSource::getTileHeight()const +{ + ossimImageSourceInterface* source = PTR_CAST(ossimImageSourceInterface, getInput(0)); + if(source) + { + return source->getTileHeight(); + } + + return 128; +} + +void ossimBumpShadeTileSource::initialize() +{ + ossimImageCombiner::initialize(); + + theTile = ossimImageDataFactory::instance()->create(this, this); + theTile->initialize(); + computeLightDirection(); + +} + +void ossimBumpShadeTileSource::computeLightDirection() +{ + NEWMAT::Matrix m = ossimMatrix3x3::createRotationMatrix(theLightSourceElevationAngle, + 0.0, + theLightSourceAzimuthAngle); + NEWMAT::ColumnVector v(3); + v[0] = 0; + v[1] = 1; + v[2] = 0; + v = m*v; + // reflect Z. We need the Z pointing up from the surface and not into it. + // + ossimColumnVector3d d(v[0], v[1], -v[2]); + d = d.unit(); + theLightDirection[0] = d[0]; + theLightDirection[1] = d[1]; + theLightDirection[2] = d[2]; +} + +bool ossimBumpShadeTileSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* elevationAngle = kwl.find(prefix, ossimKeywordNames::ELEVATION_ANGLE_KW); + const char* azimuthAngle = kwl.find(prefix, ossimKeywordNames::AZIMUTH_ANGLE_KW); + + + if(elevationAngle) + { + theLightSourceElevationAngle = ossimString(elevationAngle).toDouble(); + } + + if(azimuthAngle) + { + theLightSourceAzimuthAngle = ossimString(azimuthAngle).toDouble(); + } + + computeLightDirection(); + + bool result = ossimImageSource::loadState(kwl, prefix); + + theInputListIsFixedFlag = true; + theOutputListIsFixedFlag = false; + if(!getNumberOfInputs()) setNumberOfInputs(2); + + return result; +} + +bool ossimBumpShadeTileSource::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + ossimKeywordNames::ELEVATION_ANGLE_KW, + theLightSourceElevationAngle, + true); + + kwl.add(prefix, + ossimKeywordNames::AZIMUTH_ANGLE_KW, + theLightSourceAzimuthAngle, + true); + + return ossimImageSource::saveState(kwl, prefix); +} + +ossimString ossimBumpShadeTileSource::getShortName()const +{ + return ossimString("bump shader"); +} + +ossimString ossimBumpShadeTileSource::getLongName()const +{ + return ossimString("Blinn's bump map filter"); +} + +ossim_uint32 ossimBumpShadeTileSource::getNumberOfOutputBands() const +{ + return 3; +} + +ossimScalarType ossimBumpShadeTileSource::getOutputScalarType() const +{ + return OSSIM_UCHAR; +} + +double ossimBumpShadeTileSource::getNullPixelValue()const +{ + return 0.0; +} + +double ossimBumpShadeTileSource::getMinPixelValue(ossim_uint32 /* band */)const +{ + return 1.0; +} + +double ossimBumpShadeTileSource::getMaxPixelValue(ossim_uint32 /* band */)const +{ + return 255.0; +} + +double ossimBumpShadeTileSource::getAzimuthAngle()const +{ + return theLightSourceAzimuthAngle; +} + +double ossimBumpShadeTileSource::getElevationAngle()const +{ + return theLightSourceElevationAngle; +} + +void ossimBumpShadeTileSource::setAzimuthAngle(double angle) +{ + theLightSourceAzimuthAngle = angle; +} + +void ossimBumpShadeTileSource::setElevationAngle(double angle) +{ + theLightSourceElevationAngle = angle; +} + +bool ossimBumpShadeTileSource::canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const +{ + return (object&& + ( (inputIndex>=0) && inputIndex < 2)&& + PTR_CAST(ossimImageSourceInterface, object)); + +} + +void ossimBumpShadeTileSource::connectInputEvent(ossimConnectionEvent& event) +{ + initialize(); +} + +void ossimBumpShadeTileSource::disconnectInputEvent(ossimConnectionEvent& event) +{ + initialize(); +} + +void ossimBumpShadeTileSource::propertyEvent(ossimPropertyEvent& event) +{ + initialize(); +} + +void ossimBumpShadeTileSource::refreshEvent(ossimRefreshEvent& event) +{ + initialize(); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBumpShadeTileSource.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBumpShadeTileSource.h new file mode 100644 index 0000000000..5b0e40b466 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimBumpShadeTileSource.h @@ -0,0 +1,271 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimBumpShadeTileSource.h,v 1.32 2005/02/11 15:07:32 dburken Exp $ +#ifndef ossimBumpShadeTileSource_HEADER +#define ossimBumpShadeTileSource_HEADER +#include "ossimImageCombiner.h" +#include "matrix/newmat.h" +#include "base/data_types/ossimColumnVector3d.h" +#include "base/common/events/ossimConnectableObjectListener.h" +#include "base/common/events/ossimPropertyEvent.h" +#include "ossimImageToPlaneNormalFilter.h" + +class ossimImageData; + +class ossimImageSourceConnection; + +/** + * This uses a derivative of Blinn's bump function to compute a 3-D + * looking image. The elevation data can be from Grey Scale image or from + * a Dted file. This class can take one or two inputs. The First input is an + * elevation input that is used to compute a perturbed Normal which is + * used in a simple lambertian shading equation. The second input is some + * color source (Grey or RGB) that defines the diffuse color used within + * the illumination equation for each pixel. If the diffuse color input is not + * supplied then an all white color is used for the color. There are several + * adjustable parameters that can be set: + * 1) the Incident light vector described by the Azimuth and Elevation Angle, + * 2) the pixel scale used along the x and y direction, and + * 3) the partial derivative matrix used for the partial derivative + * computation along the x and y direction. + * + * <pre> + * + * Some examples of good values: + * + * If we are using dted 90 meters as input for shading then: + * 1) set pixel scale to 180. Since the partials do 2*dx and 2*dy then + * the scale is 2*90meters = 180. + * 2) set azimuth angle to 45 and set elevation angle to 45 degrees. Change + * them to see the effects. + * 3) use the following matrix -1 0 1 + * -1 0 1 + * -1 0 1 + * & + * 1 1 1 + * 0 0 0 + * -1 -1 -1 + * + * for the partials along x and y directions respectively. These matrices + * + * (f(x+dx, y) - f(x-dx, y))/2*dx and + * (f(x, y+dy) - f(x, y-dy))/2*dy + * + * for an apprximate derivative about some point x, y + * + * If we are using pixel intesity (1 - 255) then set the scales to around + * 100. + * + * Note: varying the scales will vary the smoothness/roughness of the surface + * Smaller the scale the rougher the surface will look. + * + * The output of this source is always a 3-band 8-bit image. + * + * Keywords: + * type: ossimBumpShadeTileSource + * azimuth_angle: 45.000000000000000 + * elevation_angle: 45.000000000000000 + * scale_per_pixel_x: 180.000000000000000 // this is the 2*dx defined above + * scale_per_pixel_y: 180.000000000000000 // this is the 2*dy defined above + * + * the next set of keywords are optional and the default is as defined above. + * these define the matrix. + * + * + * A typical chain would look something like this: + * + * OrthoMosaicOfElevation-->Normals-->Renderer-->| + * |--> BumpShade-->Output + * ColorSource----------------------->Renderer-->| + * + * NOTE: "Normals" is an ossimImageToPlaneNormalFilter class + * + * </pre> + * + */ +class OSSIMDLLEXPORT ossimBumpShadeTileSource : public ossimImageCombiner +{ +public: + ossimBumpShadeTileSource(); + + /** + * The bump map input source is used to bump or shade the input color + * source. The input color source currently must be a 1 or 3 band + * image. Note that the output of this source is always + * 3 bands (r, g, b). + */ + ossimBumpShadeTileSource(ossimImageSource* colorSource, + ossimImageSource* bumpMapSource); + virtual ~ossimBumpShadeTileSource(); + + ossimString getShortName()const; + ossimString getLongName()const; + + ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + + /** + * Since the input bump souce is not used for bounding rect computation + * this call is passed on to theColorInputSource. + */ + virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0)const; + + virtual void getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result) const; + virtual void getDecimationFactors(vector<ossimDpt>& decimations) const; + virtual ossim_uint32 getNumberOfDecimationLevels()const; + + /** + * This should always return 3 + */ + virtual ossim_uint32 getNumberOfOutputBands() const; + + /** + * The output scalar type should always be 8-bit + */ + virtual ossimScalarType getOutputScalarType() const; + + /** + * the null pixel is 0.0. + * \return null pixel value is always 0 + * + */ + virtual double getNullPixelValue()const; + + /** + * the min pixel is 1.0. + * \return min pixel value is always 1 + * + */ + virtual double getMinPixelValue(ossim_uint32 band=0)const; + + /** + * the max pixel is 255. + * \return max pixel value is always 255 + * + */ + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + + /** + * Returns the current tile width. This is passed to first input. + * \return Returns the tile width. + */ + virtual ossim_uint32 getTileWidth()const; + + /** + * Returns the current tile height. This is passed to first input. + * \return Returns the tile height.. + */ + virtual ossim_uint32 getTileHeight()const; + + /** + * \return Returns the rotation of the incident vector.. + */ + virtual double getAzimuthAngle()const; + + /** + * \return Returns the elevation of the incident vector. + */ + virtual double getElevationAngle()const; + + /** + * + */ + virtual void setAzimuthAngle(double angle); + + /** + * + */ + virtual void setElevationAngle(double angle); + + /** + * + */ + virtual void initialize(); + + /** + * + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * + */ + bool canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const; + + /** + * + */ + virtual void connectInputEvent(ossimConnectionEvent& event); + + /** + * + */ + virtual void disconnectInputEvent(ossimConnectionEvent& event); + + /** + * + */ + virtual void propertyEvent(ossimPropertyEvent& event); + + virtual void refreshEvent(ossimRefreshEvent& event); + + /** + * Will re-compute the light direction given the elevation angle and + * azimuth angle. + */ + void computeLightDirection(); + +protected: + /** + * The result of the illumination equation is stored in + * here. This is populated on each call to getTile. + */ + ossimRefPtr<ossimImageData> theTile; + + /** + * Used for the light vector computation. + */ + double theLightSourceElevationAngle; + + /** + * Used for the light vector computation. + */ + double theLightSourceAzimuthAngle; + + /** + * This is computed from the elevation and + * azimuth angles of the light source. + */ + NEWMAT::ColumnVector theLightDirection; + + void computeColor(ossim_uint8& r, + ossim_uint8& g, + ossim_uint8& b, + ossim_float64 normalX, + ossim_float64 normalY, + ossim_float64 normalZ, + ossim_uint8 dr, + ossim_uint8 dg, + ossim_uint8 db)const; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimCacheTileSource.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimCacheTileSource.cpp new file mode 100644 index 0000000000..af08946116 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimCacheTileSource.cpp @@ -0,0 +1,357 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +// ossimCacheTileSource. +//******************************************************************* +// $Id: ossimCacheTileSource.cpp,v 1.55 2005/08/17 19:18:12 gpotts Exp $ +#include <base/common/ossimTrace.h> +#include <imaging/tile_sources/ossimCacheTileSource.h> +#include <imaging/ossimImageData.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <base/common/ossimKeywordNames.h> +#include <base/data_types/ossimKeywordlist.h> + +#ifndef NULL +# include <stddef.h> +#endif +static ossimTrace traceDebug("ossimCacheTileSource:debug"); + +RTTI_DEF1(ossimCacheTileSource, "ossimCacheTileSource", ossimImageSourceFilter); + +ossimCacheTileSource::ossimCacheTileSource() + : ossimImageSourceFilter(), + theCacheId(ossimAppFixedTileCache::instance()->newTileCache()), + theTile(0), + theCachingEnabled(true), + theEventProgressFlag(false) +{ + theBoundingRect.makeNan(); + theFixedTileSize = ossimAppFixedTileCache::instance()->getTileSize(theCacheId); + theCacheRLevel = 0; +} + +ossimCacheTileSource::ossimCacheTileSource(ossimImageSource* inputSource) + : ossimImageSourceFilter(inputSource), + theCacheId(ossimAppFixedTileCache::instance()->newTileCache()), + theTile(0), + theCachingEnabled(true), + theEventProgressFlag(false) +{ + theBoundingRect.makeNan(); + theFixedTileSize = ossimAppFixedTileCache::instance()->getTileSize(theCacheId); + theCacheRLevel = 0; +} + +ossimCacheTileSource::~ossimCacheTileSource() +{ + ossimAppFixedTileCache::instance()->deleteCache(theCacheId); + + theCacheId = -1; + theBoundingRect.makeNan(); +} + +void ossimCacheTileSource::flush() +{ + ossimAppFixedTileCache::instance()->flush(theCacheId); +} + +void ossimCacheTileSource::initialize() +{ + ossimImageSourceFilter::initialize(); + flush(); + theCacheRLevel = 999999999; + + theTile = NULL; +} + +void ossimCacheTileSource::allocate() +{ + theTile = NULL; + if(theInputConnection) + { + theTile = ossimImageDataFactory::instance()->create(this, + this); + theTile->initialize(); + } +} + +ossimRefPtr<ossimImageData> ossimCacheTileSource::getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimCacheTileSource::getTile DEBUG: Entered ..." << std::endl; + } + if(!theInputConnection) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimCacheTileSource::getTile DEBUG: Leaving with theInputConnection NULL ..." << std::endl; + } + return 0; + } + + if(!isSourceEnabled()) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimCacheTileSource::getTile DEBUG: Source not enabled so leaving ..." << std::endl; + } + return theInputConnection->getTile(tileRect, resLevel); + } + + if(!theTile.get()) + { + allocate(); + } + + if(!theTile.get()) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimCacheTileSource::getTile DEBUG: Unable to allocate tile so leaving ..." << std::endl; + } + return 0; + } + + if(resLevel != theCacheRLevel) + { + flush(); + theCacheRLevel = 9999999; + allocate(); + theBoundingRect = getBoundingRect(resLevel); + if(theBoundingRect.hasNans()) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimCacheTileSource::getTile DEBUG: bounding rect has nans so leaving ..." << std::endl; + } + return 0; + } + theFixedTileSize = ossimAppFixedTileCache::instance()->getTileSize(theCacheId); + theBoundingRect.stretchToTileBoundary(theFixedTileSize); + ossimAppFixedTileCache::instance()->setRect(theCacheId, + theBoundingRect); + theCacheRLevel = resLevel; + } + + theTile->setImageRectangle(tileRect); + theTile->makeBlank(); + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimCacheTileSource::getTile DEBUG: filling tile and leaving ..." << std::endl; + } + return fillTile(resLevel); +} + +ossimRefPtr<ossimImageData> ossimCacheTileSource::fillTile( + ossim_uint32 resLevel) +{ + ossimRefPtr<ossimImageData> tempTile = NULL; + fireProgressEvent(0.0); + ossimIrect boundingRect = theBoundingRect; + ossimIrect tileRect = theTile->getImageRectangle(); + + ossimIrect allignedRect = tileRect.clipToRect(boundingRect); + + if (allignedRect.hasNans()) + { + theTile->makeBlank(); + return theTile; + } + + allignedRect.stretchToTileBoundary(theFixedTileSize); + ossimAppFixedTileCache::ossimAppFixedCacheId cacheId = theCacheId; + + // check to see if we need to loop + if((allignedRect == tileRect)&& + (static_cast<ossim_int32>(tileRect.width()) == theFixedTileSize.x)&& + (static_cast<ossim_int32>(tileRect.height()) == theFixedTileSize.y)) + { + ossimIpt origin = tileRect.ul(); + if(theCachingEnabled) + { + tempTile = ossimAppFixedTileCache::instance()->getTile(cacheId, origin); + } + if(!tempTile.valid()) + { + tempTile = theInputConnection->getTile(tileRect, resLevel); + + if(tempTile.valid()) + { + if((tempTile->getBuf())&& + (tempTile->getDataObjectStatus()!=OSSIM_EMPTY)&& + theCachingEnabled) + { + ossimAppFixedTileCache::instance()->addTile(cacheId, tempTile); + } + } + } + + if(tempTile.valid()) + { + if((tempTile->getDataObjectStatus() != OSSIM_NULL)&& + (tempTile->getDataObjectStatus() != OSSIM_EMPTY)) + { + + theTile->setDataObjectStatus(tempTile->getDataObjectStatus()); + theTile->loadTile(tempTile.get()); + } + } + fireProgressEvent(100.0); + } + else + { + long boundaryHeight = allignedRect.height(); + long boundaryWidth = allignedRect.width(); + ossimIpt origin(allignedRect.ul()); + long totalTiles = (boundaryHeight/theFixedTileSize.y)* + (boundaryWidth/theFixedTileSize.x); + long currentTile = 0; + for(long row = 0; row < boundaryHeight; row+=theFixedTileSize.y) + { + origin.x = allignedRect.ul().x; + for(long col = 0; col < boundaryWidth; col+=theFixedTileSize.x) + { + ++currentTile; + if(theCachingEnabled) + { + tempTile = ossimAppFixedTileCache::instance()->getTile(cacheId, + origin); + } + else + { + tempTile = 0; + } + if(!tempTile.valid()) + { + ossimIrect rect(origin.x, + origin.y, + origin.x + theFixedTileSize.x-1, + origin.y + theFixedTileSize.y-1); + + tempTile = theInputConnection->getTile(rect, resLevel); + + if(tempTile.valid()) + { + if(theTile->getBuf()&& + (tempTile->getDataObjectStatus()!=OSSIM_EMPTY)&& + theCachingEnabled) + { + ossimAppFixedTileCache::instance()->addTile(cacheId, tempTile); + } + } + } + if(tempTile.valid()) + { + if(tempTile->getBuf()&& + (tempTile->getDataObjectStatus()!=OSSIM_EMPTY)) + { + theTile->loadTile(tempTile.get()); + } + } + double percent = 100.0*((double)currentTile/(double)totalTiles); + fireProgressEvent(percent); + origin.x += theFixedTileSize.x; + } + origin.y += theFixedTileSize.y; + } + fireProgressEvent(100); + } + + theTile->validate(); + + return theTile; +} + +ossim_uint32 ossimCacheTileSource::getTileWidth() const +{ + return theFixedTileSize.x; +} + +ossim_uint32 ossimCacheTileSource::getTileHeight() const +{ + return theFixedTileSize.y; +} + +bool ossimCacheTileSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimAppFixedTileCache::instance()->deleteCache(theCacheId); + theCacheId = ossimAppFixedTileCache::instance()->newTileCache(); + const char* cachingEnabled = kwl.find(prefix, ossimKeywordNames::ENABLE_CACHE_KW); + + if(cachingEnabled) + { + theCachingEnabled = ossimString(cachingEnabled).toBool(); + } + + bool result = ossimImageSourceFilter::loadState(kwl, prefix); + initialize(); + return result; +} + +bool ossimCacheTileSource::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + ossimKeywordNames::ENABLE_CACHE_KW, + (long)theCachingEnabled, + true); + + return ossimImageSourceFilter::saveState(kwl, prefix); +} + + +ossimString ossimCacheTileSource::getLongName()const +{ + return ossimString("Tile Cache , cache for ossimImageData objects."); +} + +ossimString ossimCacheTileSource::getShortName()const +{ + return ossimString("Tile Cache"); +} + +void ossimCacheTileSource::setCachingEnabledFlag(bool value) +{ + if(!value && theCachingEnabled) + { + flush(); + } + theCachingEnabled = value; +} + +void ossimCacheTileSource::setEventProgressFlag(bool value) +{ + theEventProgressFlag = value; +} + +ossimIpt ossimCacheTileSource::getTileSize() +{ + return theFixedTileSize; +} + +void ossimCacheTileSource::setTileSize(const ossimIpt& size) +{ + theFixedTileSize = size; +} + +void ossimCacheTileSource::fireProgressEvent(double percentComplete) +{ + if(theEventProgressFlag) + { + ossimProcessProgressEvent event(this, percentComplete); + fireEvent(event); + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimCacheTileSource.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimCacheTileSource.h new file mode 100644 index 0000000000..b0dadcd8fa --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimCacheTileSource.h @@ -0,0 +1,75 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +// ossimCacheTileSource. +//******************************************************************* +// $Id: ossimCacheTileSource.h,v 1.27 2005/02/11 15:07:32 dburken Exp $ +#ifndef ossimCacheTileSource_HEADER +#define ossimCacheTileSource_HEADER +#include <imaging/tile_sources/ossimImageSourceFilter.h> +#include <imaging/cache/ossimAppFixedTileCache.h> +#include <base/common/events/ossimProcessProgressEvent.h> + +/** Cache Tile Source */ +class OSSIMDLLEXPORT ossimCacheTileSource : public ossimImageSourceFilter +{ +public: + /** + * Will construct a new Application cache + */ + ossimCacheTileSource(); + ossimCacheTileSource(ossimImageSource* inputSource); + virtual ~ossimCacheTileSource(); + + virtual ossimString getLongName() const; + virtual ossimString getShortName() const; + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + virtual void initialize(); + virtual void flush(); + virtual void setCachingEnabledFlag(bool value); + virtual void setEventProgressFlag(bool value); + + void changeTileSize(const ossimIpt& size); + ossimIpt getTileSize(); + void setTileSize(const ossimIpt& size); + + virtual ossim_uint32 getTileWidth() const; + virtual ossim_uint32 getTileHeight() const; + + bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + +protected: + + void allocate(); + + ossimAppFixedTileCache::ossimAppFixedCacheId theCacheId; + + ossimRefPtr<ossimImageData> theTile; + ossimIpt theFixedTileSize; + bool theCachingEnabled; + bool theEventProgressFlag; + ossim_uint32 theCacheRLevel; + ossimIrect theBoundingRect; + + virtual void fireProgressEvent(double percentComplete); + + virtual ossimRefPtr<ossimImageData> fillTile(ossim_uint32 resLevel); + +TYPE_DATA +}; + + +#endif /* end of "#ifndef ossimCacheTileSource_HEADER" */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimCastTileSourceFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimCastTileSourceFilter.cpp new file mode 100644 index 0000000000..fafc5a5b11 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimCastTileSourceFilter.cpp @@ -0,0 +1,688 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimCastTileSourceFilter.cpp,v 1.30 2005/08/17 19:18:12 gpotts Exp $ +#include <imaging/tile_sources/ossimCastTileSourceFilter.h> +#include <imaging/ossimU8ImageData.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/misc/lookup_tables/ossimScalarTypeLut.h> +#include <base/property/ossimStringProperty.h> + +RTTI_DEF1( ossimCastTileSourceFilter, + "ossimCastTileSourceFilter", + ossimImageSourceFilter ); + +ossimCastTileSourceFilter::ossimCastTileSourceFilter(ossimImageSource* input, + ossimScalarType scalarType) + :ossimImageSourceFilter(NULL,input), + theTile(NULL), + theOutputScalarType(scalarType) +{ +} + +ossimCastTileSourceFilter::~ossimCastTileSourceFilter() +{ +} + +ossimRefPtr<ossimImageData> ossimCastTileSourceFilter::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + ossimRefPtr<ossimImageData> inputTile; + + if(theInputConnection) + { + inputTile = theInputConnection->getTile(tileRect, resLevel); + } + return applyCast(inputTile); +} + +ossimScalarType ossimCastTileSourceFilter::getOutputScalarType() const +{ + if(isSourceEnabled()) + { + return theOutputScalarType; + } + else if(theInputConnection) + { + return theInputConnection->getOutputScalarType(); + } + + return OSSIM_SCALAR_UNKNOWN; +} + +double ossimCastTileSourceFilter::getNullPixelValue(ossim_uint32 band)const +{ + if(!isSourceEnabled()) + { + if(theInputConnection) + { + return theInputConnection->getNullPixelValue(band); + } + } + return ossimGetDefaultNull(getOutputScalarType()); +} + +double ossimCastTileSourceFilter::getMinPixelValue(ossim_uint32 band)const +{ + if(!isSourceEnabled()) + { + if(theInputConnection) + { + return theInputConnection->getMinPixelValue(band); + } + } + + if(theInputConnection) + { + double tempMin = theInputConnection->getMinPixelValue(band); + + double defaultMin = ossimGetDefaultMin(theOutputScalarType); + double defaultMax = ossimGetDefaultMax(theOutputScalarType); + + if((tempMin >= defaultMin) && (tempMin <= defaultMax)) + { + defaultMin = tempMin; + } + + return defaultMin; + } + + return ossimImageSource::getMinPixelValue(band); +} + +double ossimCastTileSourceFilter::getMaxPixelValue(ossim_uint32 band)const +{ + if(!isSourceEnabled()) + { + if(theInputConnection) + { + return theInputConnection->getMaxPixelValue(band); + } + } + if(theInputConnection) + { + double tempMax = theInputConnection->getMaxPixelValue(band); + + double defaultMax = ossimGetDefaultMax(theOutputScalarType); + double defaultMin = ossimGetDefaultMin(theOutputScalarType); + + if((tempMax >= defaultMin) && (tempMax <= defaultMax)) + { + defaultMax = tempMax; + } + + return defaultMax; + } + return ossimImageSource::getMaxPixelValue(band); +} + +ossimRefPtr<ossimImageData> ossimCastTileSourceFilter::applyCast( + ossimRefPtr<ossimImageData> inputTile) +{ + if(!inputTile.valid()) + { + return inputTile; + } + + if(!theTile.valid() || + (theTile->getNumberOfBands() != inputTile->getNumberOfBands())) + { + allocate(inputTile); + } + else + { + ossim_int32 tw =inputTile->getWidth(); + ossim_int32 th =inputTile->getHeight(); + ossim_int32 w = theTile->getWidth(); + ossim_int32 h = theTile->getHeight(); + theTile->setWidthHeight(tw, th); + + if((w*h != tw*th)) + { + theTile->initialize(); + } + else + { + theTile->makeBlank(); + } + theTile->setOrigin(inputTile->getOrigin()); + } + + if( (inputTile->getDataObjectStatus()==OSSIM_EMPTY) || + (inputTile->getDataObjectStatus()==OSSIM_NULL)) + { + return theTile; + } + + switch(inputTile->getScalarType()) + { + case OSSIM_UINT8: + { + ossim_uint8** bands = new ossim_uint8*[inputTile->getNumberOfBands()]; + + for(ossim_uint32 band = 0; + band < inputTile->getNumberOfBands(); + ++band) + { + bands[band] = static_cast<ossim_uint8*>(inputTile->getBuf(band)); + } + castInputToOutput(bands, + inputTile->getNullPix(), + inputTile->getDataObjectStatus()==OSSIM_PARTIAL); + delete [] bands; + break; + } + case OSSIM_SINT8: + { + ossim_sint8** bands = new ossim_sint8*[inputTile->getNumberOfBands()]; + + for(ossim_uint32 band = 0; + band < inputTile->getNumberOfBands(); + ++band) + { + bands[band] = static_cast<ossim_sint8*>(inputTile->getBuf(band)); + } + castInputToOutput(bands, + inputTile->getNullPix(), + inputTile->getDataObjectStatus()==OSSIM_PARTIAL); + delete [] bands; + break; + } + case OSSIM_UINT16: + case OSSIM_USHORT11: + { + ossim_uint16** bands = + new ossim_uint16*[inputTile->getNumberOfBands()]; + + for(ossim_uint32 band = 0; + band < inputTile->getNumberOfBands(); + ++band) + { + bands[band] = static_cast<ossim_uint16*>(inputTile->getBuf(band)); + } + castInputToOutput(bands, + inputTile->getNullPix(), + inputTile->getDataObjectStatus()==OSSIM_PARTIAL); + delete [] bands; + break; + } + case OSSIM_SINT16: + { + ossim_sint16** bands = + new ossim_sint16*[inputTile->getNumberOfBands()]; + + for(ossim_uint32 band = 0; + band < inputTile->getNumberOfBands(); + ++band) + { + bands[band] = static_cast<ossim_sint16*>(inputTile->getBuf(band)); + } + castInputToOutput(bands, + inputTile->getNullPix(), + inputTile->getDataObjectStatus()==OSSIM_PARTIAL); + delete [] bands; + break; + } + case OSSIM_SINT32: + { + ossim_sint32** bands = + new ossim_sint32*[inputTile->getNumberOfBands()]; + + for(ossim_uint32 band = 0; + band < inputTile->getNumberOfBands(); + ++band) + { + bands[band] = static_cast<ossim_sint32*>(inputTile->getBuf(band)); + } + castInputToOutput(bands, + inputTile->getNullPix(), + inputTile->getDataObjectStatus()==OSSIM_PARTIAL); + delete [] bands; + break; + } + case OSSIM_UINT32: + { + ossim_uint32** bands = + new ossim_uint32*[inputTile->getNumberOfBands()]; + + for(ossim_uint32 band = 0; + band < inputTile->getNumberOfBands(); + ++band) + { + bands[band] = static_cast<ossim_uint32*>(inputTile->getBuf(band)); + } + castInputToOutput(bands, + inputTile->getNullPix(), + inputTile->getDataObjectStatus()==OSSIM_PARTIAL); + delete [] bands; + break; + } + case OSSIM_FLOAT32: + case OSSIM_NORMALIZED_FLOAT: + { + float** bands = new float*[inputTile->getNumberOfBands()]; + + for(ossim_uint32 band = 0; + band < inputTile->getNumberOfBands(); + ++band) + { + bands[band] = static_cast<float*>(inputTile->getBuf(band)); + } + castInputToOutput(bands, + inputTile->getNullPix(), + inputTile->getDataObjectStatus()==OSSIM_PARTIAL); + delete [] bands; + break; + } + case OSSIM_FLOAT64: + case OSSIM_NORMALIZED_DOUBLE: + { + double** bands = new double*[inputTile->getNumberOfBands()]; + + for(ossim_uint32 band = 0; + band < inputTile->getNumberOfBands(); + ++band) + { + bands[band] = static_cast<double*>(inputTile->getBuf(band)); + } + castInputToOutput(bands, + inputTile->getNullPix(), + inputTile->getDataObjectStatus()==OSSIM_PARTIAL); + delete [] bands; + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + break; + } + } + +// theTile->setDataObjectStatus(inputTile->getDataObjectStatus()); + theTile->validate(); + return theTile; +} + +void ossimCastTileSourceFilter::setOutputScalarType(ossimScalarType scalarType) +{ + ossimScalarType old_type = theOutputScalarType; + theOutputScalarType = scalarType; + + if ( (theOutputScalarType != old_type)) + { + // must reinitialize... + theTile = NULL; + initialize(); + } +} + +void ossimCastTileSourceFilter::setOutputScalarType(ossimString scalarType) +{ + int scalar = + ossimScalarTypeLut::instance()->getEntryNumber(scalarType.c_str()); + + if (scalar != ossimLookUpTable::NOT_FOUND) + { + setOutputScalarType(static_cast<ossimScalarType>(scalar)); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimCastTileSourceFilter::setOutputScalarType WARN:" + << "\nUnknown scalar type: " << scalarType.c_str() << endl; + } +} + +ossimString ossimCastTileSourceFilter::getOutputScalarTypeString()const +{ + return ossimScalarTypeLut::instance()->getEntryString(theOutputScalarType); +} + +void ossimCastTileSourceFilter::initialize() +{ + ossimImageSourceFilter::initialize(); + + if (theOutputScalarType == OSSIM_SCALAR_UNKNOWN) + { + // default to OSSIM_UCHAR + theOutputScalarType = OSSIM_UCHAR; + } +} + +bool ossimCastTileSourceFilter::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + ossimImageSourceFilter::saveState(kwl, prefix); + + kwl.add(prefix, + ossimKeywordNames::SCALAR_TYPE_KW, + ossimScalarTypeLut::instance()->getEntryString(theOutputScalarType), + true); + + return true; +} + +bool ossimCastTileSourceFilter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimImageSourceFilter::loadState(kwl, prefix); + + if (kwl.getErrorStatus() == ossimErrorCodes::OSSIM_ERROR) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimScalarRemapper::loadState WARN:\n" + << " ERROR detected in keyword list! State not loaded." + << endl; + return false; + } + + int scalar = ossimScalarTypeLut::instance()->getEntryNumber(kwl, prefix); + + if (scalar != ossimLookUpTable::NOT_FOUND) + { + theOutputScalarType = static_cast<ossimScalarType>(scalar); + } + + return true; +} + +template<class inType> +void ossimCastTileSourceFilter::castInputToOutput(inType **inBuffer, + const double *nullPix, + bool inPartialFlag) +{ + switch(theTile->getScalarType()) + { + case OSSIM_UINT8: + { + ossim_uint8** bands = new ossim_uint8*[theTile->getNumberOfBands()]; + + for(ossim_uint32 band = 0; band < theTile->getNumberOfBands(); ++band) + { + bands[band] = static_cast<ossim_uint8*>(theTile->getBuf(band)); + } + + castInputToOutput(inBuffer, + nullPix, + inPartialFlag, + bands, + theTile->getNullPix(), + theTile->getNumberOfBands()); + delete [] bands; + break; + } + case OSSIM_SINT8: + { + ossim_sint8** bands = new ossim_sint8*[theTile->getNumberOfBands()]; + + for(ossim_uint32 band = 0; band < theTile->getNumberOfBands(); ++band) + { + bands[band] = static_cast<ossim_sint8*>(theTile->getBuf(band)); + } + + castInputToOutput(inBuffer, + nullPix, + inPartialFlag, + bands, + theTile->getNullPix(), + theTile->getNumberOfBands()); + delete [] bands; + break; + } + case OSSIM_SINT16: + { + ossim_sint16** bands = new ossim_sint16*[theTile->getNumberOfBands()]; + + for(ossim_uint32 band = 0; band < theTile->getNumberOfBands(); ++band) + { + bands[band] = static_cast<ossim_sint16*>(theTile->getBuf(band)); + } + + castInputToOutput(inBuffer, + nullPix, + inPartialFlag, + bands, + theTile->getNullPix(), + theTile->getNumberOfBands()); + delete [] bands; + break; + } + case OSSIM_UINT16: + case OSSIM_USHORT11: + { + ossim_uint16** bands = new ossim_uint16*[theTile->getNumberOfBands()]; + + for(ossim_uint32 band = 0; band < theTile->getNumberOfBands(); ++band) + { + bands[band] = static_cast<ossim_uint16*>(theTile->getBuf(band)); + } + + castInputToOutput(inBuffer, + nullPix, + inPartialFlag, + bands, + theTile->getNullPix(), + theTile->getNumberOfBands()); + delete [] bands; + break; + } + case OSSIM_UINT32: + { + ossim_uint32** bands = new ossim_uint32*[theTile->getNumberOfBands()]; + + for(ossim_uint32 band = 0; band < theTile->getNumberOfBands(); ++band) + { + bands[band] = static_cast<ossim_uint32*>(theTile->getBuf(band)); + } + + castInputToOutput(inBuffer, + nullPix, + inPartialFlag, + bands, + theTile->getNullPix(), + theTile->getNumberOfBands()); + delete [] bands; + break; + } + case OSSIM_SINT32: + { + ossim_sint32** bands = new ossim_sint32*[theTile->getNumberOfBands()]; + + for(ossim_uint32 band = 0; band < theTile->getNumberOfBands(); ++band) + { + bands[band] = static_cast<ossim_sint32*>(theTile->getBuf(band)); + } + + castInputToOutput(inBuffer, + nullPix, + inPartialFlag, + bands, + theTile->getNullPix(), + theTile->getNumberOfBands()); + delete [] bands; + break; + } + + case OSSIM_FLOAT32: + case OSSIM_NORMALIZED_FLOAT: + { + float** bands = new float*[theTile->getNumberOfBands()]; + + for(ossim_uint32 band = 0; band < theTile->getNumberOfBands(); ++band) + { + bands[band] = static_cast<float*>(theTile->getBuf(band)); + } + + castInputToOutput(inBuffer, + nullPix, + inPartialFlag, + bands, + theTile->getNullPix(), + theTile->getNumberOfBands()); + delete [] bands; + break; + } + case OSSIM_FLOAT64: + case OSSIM_NORMALIZED_DOUBLE: + { + double** bands = new double*[theTile->getNumberOfBands()]; + + for(ossim_uint32 band = 0; band < theTile->getNumberOfBands(); ++band) + { + bands[band] = static_cast<double*>(theTile->getBuf(band)); + } + + castInputToOutput(inBuffer, + nullPix, + inPartialFlag, + bands, + theTile->getNullPix(), + theTile->getNumberOfBands()); + delete [] bands; + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimCastTileSourceFilter::castInputToOutput WARN:\n" + << "Scalar not set in ossimCastTileSourceFilter" << endl; + break; + } + } +} + +template<class inType, class outType> +void ossimCastTileSourceFilter::castInputToOutput(inType *inBuffer[], + const double *nullInPix, + bool inPartialFlag, + outType *outBuffer[], + const double *nullOutPix, + ossim_uint32 numberOfBands) +{ + ossim_uint32 size = theTile->getWidth()*theTile->getHeight(); + if(!inPartialFlag) + { + for(ossim_uint32 band = 0; band < numberOfBands; ++band) + { + outType outMin = static_cast<outType>(theTile->getMinPix(band)); + outType outMax = static_cast<outType>(theTile->getMaxPix(band)); + + for(ossim_uint32 offset = 0; offset < size; ++offset) + { + double temp = inBuffer[band][offset]; + if(temp < outMin) temp = outMin; + if(temp > outMax) temp = outMax; + outBuffer[band][offset] = static_cast<outType>(temp); + } + } + } + else + { + for(ossim_uint32 band = 0; band < numberOfBands; ++band) + { + inType np = static_cast<inType>(nullInPix[band]); + outType outNp = static_cast<outType>(nullOutPix[band]); + outType outMin = static_cast<outType>(theTile->getMinPix(band)); + outType outMax = static_cast<outType>(theTile->getMaxPix(band)); + + for(ossim_uint32 offset = 0; offset < size; ++offset) + { + if(inBuffer[band][offset] != np) + { + double temp = inBuffer[band][offset]; + if(temp < outMin) temp = outMin; + if(temp > outMax) temp = outMax; + outBuffer[band][offset] = static_cast<outType>(temp); + } + else + { + outBuffer[band][offset] = static_cast<outType>(outNp); + + } + } + } + } +} + +void ossimCastTileSourceFilter::allocate(const ossimRefPtr<ossimImageData> inputTile) +{ + theTile = ossimImageDataFactory::instance()->create( + this, + getOutputScalarType(), + inputTile->getNumberOfBands(), + inputTile->getWidth(), + inputTile->getHeight()); + theTile->initialize(); + theTile->setOrigin(inputTile->getOrigin()); +} + +void ossimCastTileSourceFilter::propertyEvent(ossimPropertyEvent& event) +{ +} + +void ossimCastTileSourceFilter::refreshEvent(ossimRefreshEvent& event) +{ +} + +void ossimCastTileSourceFilter::setProperty(ossimRefPtr<ossimProperty> property) +{ + if(property->getName() == ossimKeywordNames::SCALAR_TYPE_KW) + { + int scalar = ossimScalarTypeLut::instance()->getEntryNumber(property->valueToString()); + + if (scalar != ossimLookUpTable::NOT_FOUND) + { + setOutputScalarType(static_cast<ossimScalarType>(scalar)); + } + } + else + { + ossimImageSourceFilter::setProperty(property); + } +} + +ossimRefPtr<ossimProperty> ossimCastTileSourceFilter::getProperty(const ossimString& name)const +{ + ossimRefPtr<ossimProperty> resultProperty; + if(name == ossimKeywordNames::SCALAR_TYPE_KW) + { + ossimStringProperty* stringProperty = new ossimStringProperty(name, + ossimScalarTypeLut::instance()->getEntryString(theOutputScalarType), + false); + + stringProperty->addConstraint(ossimScalarTypeLut::instance()->getEntryString(OSSIM_UINT8)); + stringProperty->addConstraint(ossimScalarTypeLut::instance()->getEntryString(OSSIM_SINT8)); + stringProperty->addConstraint(ossimScalarTypeLut::instance()->getEntryString(OSSIM_UINT16)); + stringProperty->addConstraint(ossimScalarTypeLut::instance()->getEntryString(OSSIM_SINT16)); + stringProperty->addConstraint(ossimScalarTypeLut::instance()->getEntryString(OSSIM_UINT32)); + stringProperty->addConstraint(ossimScalarTypeLut::instance()->getEntryString(OSSIM_SINT32)); + stringProperty->addConstraint(ossimScalarTypeLut::instance()->getEntryString(OSSIM_FLOAT32)); + stringProperty->addConstraint(ossimScalarTypeLut::instance()->getEntryString(OSSIM_FLOAT64)); + + stringProperty->setCacheRefreshBit(); + resultProperty = stringProperty; + } + else + { + resultProperty = ossimImageSourceFilter::getProperty(name); + } + return resultProperty; +} + +void ossimCastTileSourceFilter::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + ossimImageSourceFilter::getPropertyNames(propertyNames); + + propertyNames.push_back(ossimKeywordNames::SCALAR_TYPE_KW); +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimCastTileSourceFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimCastTileSourceFilter.h new file mode 100644 index 0000000000..38dac7c45a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimCastTileSourceFilter.h @@ -0,0 +1,93 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimCastTileSourceFilter.h,v 1.16 2005/08/17 19:18:12 gpotts Exp $ +#ifndef ossimCastTileSourceFilter_HEADER +#define ossimCastTileSourceFilter_HEADER + +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +class ossimCastTileSourceFilter : public ossimImageSourceFilter +{ +public: + ossimCastTileSourceFilter(ossimImageSource* inputSource=NULL, + ossimScalarType scalarType=OSSIM_UCHAR); + virtual ~ossimCastTileSourceFilter(); + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + virtual void initialize(); + virtual ossimScalarType getOutputScalarType() const; + + virtual ossimString getOutputScalarTypeString()const; + + /** + * Sets the output scalar type. + */ + virtual void setOutputScalarType(ossimScalarType scalarType); + virtual void setOutputScalarType(ossimString scalarType); + + /** + * Sets the current resolution level. Returns true on success, false + * on error. + */ + virtual double getNullPixelValue(ossim_uint32 band)const; + virtual double getMinPixelValue(ossim_uint32 band=0)const; + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + + ossimRefPtr<ossimImageData> applyCast(ossimRefPtr<ossimImageData> input); + + /** + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=NULL)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=NULL); + + /** + * Override base class so that a disableSource event does not + * reinitialize the object and enable itself. + */ + virtual void propertyEvent(ossimPropertyEvent& event); + virtual void refreshEvent(ossimRefreshEvent& event); + + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + +protected: + + void allocate(const ossimRefPtr<ossimImageData> inputTile); + + ossimRefPtr<ossimImageData> theTile; + ossimScalarType theOutputScalarType; + + template<class inType> + void castInputToOutput(inType **inBuffer, + const double *nullPix, + bool inPartialFlag); + + template<class inType, class outType> + void castInputToOutput(inType *inBuffer[], + const double *nullInPix, + bool inPartialFlag, + outType *outBuffer[], + const double *nullOutPix, + ossim_uint32 numberOfBands); +TYPE_DATA +}; + +#endif /* #ifndef ossimCastTileSourceFilter_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimClosestToCenterCombiner.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimClosestToCenterCombiner.cpp new file mode 100644 index 0000000000..ebef27ba0e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimClosestToCenterCombiner.cpp @@ -0,0 +1,141 @@ +//******************************************************************* +// Copyright (C) 2005 Garrett Potts. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimClosestToCenterCombiner.cpp,v 1.2 2005/09/22 17:20:56 gpotts Exp $ +#include "ossimClosestToCenterCombiner.h" +#include <imaging/factory/ossimImageDataFactory.h> + +RTTI_DEF1(ossimClosestToCenterCombiner, "ossimClosestToCenterCombiner", ossimImageMosaic); + +ossimClosestToCenterCombiner::ossimClosestToCenterCombiner() + :ossimImageMosaic() +{ +} + +ossimRefPtr<ossimImageData> ossimClosestToCenterCombiner::getTile(const ossimIrect& rect, + ossim_uint32 resLevel) +{ + if(!isSourceEnabled()) + { + return ossimImageMosaic::getTile(rect, resLevel); + } + if(!theTile.valid()) + { + allocate(); + if(!theTile.valid()) + { + return 0; + } + } + theTile->setImageRectangle(rect); + theTile->makeBlank(); + std::vector<ossimClosestToCenterCombinerInfo > normTileList; + ossimRefPtr<ossimImageData> currentTile = getNextNormTile(0, rect); + while(currentTile.valid()) + { + normTileList.push_back(ossimClosestToCenterCombinerInfo((ossimImageData*)currentTile->dup(), + theCurrentIndex)); + currentTile = getNextNormTile(rect, resLevel); + } + + + if(normTileList.size() == 1) + { + theTile->copyNormalizedBufferToTile((ossim_float32*)normTileList[0].theTile->getBuf()); + } + else if(normTileList.size() > 1) + { + ossimRefPtr<ossimImageData> copyTile = ossimImageDataFactory::instance()->create(0, + OSSIM_NORMALIZED_FLOAT); + copyTile->setImageRectangleAndBands(rect, + getNumberOfOutputBands()); + copyTile->initialize(); + + ossim_int32 idx = 0; + ossim_uint32 w = rect.width(); + ossim_uint32 h = rect.height(); + ossim_uint32 idxW = 0; + ossim_uint32 idxH = 0; + ossimIpt origin = rect.ul(); + ossimIpt ulPt = rect.ul(); + ossim_uint32 band = 0; + ossim_uint32 bands = copyTile->getNumberOfBands(); + ossim_uint32 srcBandIdx = 0; + std::vector<ossim_float32*> bandList(bands); + + for(band = 0; band < bands; ++band) + { + bandList[band] = (ossim_float32*)copyTile->getBuf(band); + } + ossim_uint32 offset = 0; + origin.y = ulPt.y; + for(idxH = 0; idxH < h; ++idxH) + { + origin.x = ulPt.x; + for(idxW = 0; idxW < w;++idxW) + { + idx = findIdx(normTileList, origin, offset); + + if(idx >=0) + { + for(band = 0; band < bands; ++band) + { + srcBandIdx = ossimMin(normTileList[idx].theTile->getNumberOfBands(), band); + + bandList[band][offset] = *(((ossim_float32*)normTileList[idx].theTile->getBuf(srcBandIdx))+offset); + } + } + ++offset; + ++origin.x; + } + ++origin.y; + } + theTile->copyNormalizedBufferToTile((ossim_float32*)copyTile->getBuf()); + } + + theTile->validate(); + + return theTile; + +} + +ossim_int32 ossimClosestToCenterCombiner::findIdx(const std::vector<ossimClosestToCenterCombinerInfo >& normTileList, + const ossimIpt& pt, ossim_uint32 offset)const +{ + ossim_float32 distance = 1000000; + ossim_int32 returnIdx = -1; + ossim_float32 tempDistance; + ossim_int32 idx = 0; + ossim_int32 maxIdx = normTileList.size(); + ossimIpt midPt; + ossimIrect rect; + for(idx = 0; idx < maxIdx; ++ idx) + { + rect = theFullResBounds[ normTileList[idx].theIndex ]; + midPt = rect.midPoint(); + + tempDistance = (pt-midPt).length(); + if(tempDistance < distance) + { + if(normTileList[idx].theTile->getDataObjectStatus() == OSSIM_FULL) + { + distance = tempDistance; + returnIdx = idx; + } + else if(!normTileList[idx].theTile->isNull(offset)) + { + distance = tempDistance; + returnIdx = idx; + } + } + } + + return returnIdx; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimClosestToCenterCombiner.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimClosestToCenterCombiner.h new file mode 100644 index 0000000000..4365ed9952 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimClosestToCenterCombiner.h @@ -0,0 +1,60 @@ +//******************************************************************* +// Copyright (C) 2005 Garrett Potts. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimClosestToCenterCombiner.h,v 1.2 2005/09/22 17:20:47 gpotts Exp $ +#ifndef ossimClosestToCenterCombiner_HEADER +#define ossimClosestToCenterCombiner_HEADER +#include <vector> +#include "ossimImageMosaic.h" +/** + * This implements a closest to center combiner. + * + * It will first grab all images overlapping a given rectangle query. The first non-null + * closest pixel to the center of the image is used. This basically uses only pixels along + * the "sweet" spot of the image. This combiner is typically used when there is overlapping + * sensor data. + * + */ +class ossimClosestToCenterCombiner : public ossimImageMosaic +{ +public: + ossimClosestToCenterCombiner(); + + /** + * Executes the ossimClosestToCenterCombiner algorithm. sets the pixels to the closest + * Valid value. This simulates a sweet spot cutter. + * + * @param rect The region of interest. + * @param resLevel. For this combiner this is assumed to always be 0 + */ + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect, + ossim_uint32 resLevel=0); +protected: + class ossimClosestToCenterCombinerInfo + { + public: + ossimClosestToCenterCombinerInfo(ossimRefPtr<ossimImageData> tile, + ossim_int32 idx) + :theTile(tile), + theIndex(idx) + { + } + ossimRefPtr<ossimImageData> theTile; + ossim_int32 theIndex; + }; + + + ossim_int32 findIdx(const std::vector<ossimClosestToCenterCombinerInfo >& normTileList, + const ossimIpt& pt, ossim_uint32 offset)const; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimColorNormalizedFusion.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimColorNormalizedFusion.cpp new file mode 100644 index 0000000000..976da1cf36 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimColorNormalizedFusion.cpp @@ -0,0 +1,144 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: Color normalized fusion +// +//************************************************************************* +// $Id: ossimColorNormalizedFusion.cpp,v 1.6 2005/02/11 15:07:32 dburken Exp $ + +#include <imaging/tile_sources/ossimColorNormalizedFusion.h> +#include <base/context/ossimErrorContext.h> +#include <base/common/ossimErrorCodes.h> + +RTTI_DEF1(ossimColorNormalizedFusion, + "ossimColorNormalizedFusion", + ossimFusionCombiner); + +ossimColorNormalizedFusion::ossimColorNormalizedFusion() + : ossimFusionCombiner() +{ +} + +ossimColorNormalizedFusion::ossimColorNormalizedFusion(ossimObject* owner) + : ossimFusionCombiner(owner) +{ +} + +ossimColorNormalizedFusion::~ossimColorNormalizedFusion() +{ +} + +ossimRefPtr<ossimImageData> ossimColorNormalizedFusion::getTile( + const ossimIrect& rect, + ossim_uint32 resLevel) +{ + ossimRefPtr<ossimImageData> inputTile = getNormTile(rect, resLevel); + + if(!inputTile.valid()) + { + return NULL; + } + if(!theInputConnection||!theIntensityConnection) + { + return NULL; + } + + if((inputTile->getDataObjectStatus() == OSSIM_NULL)|| + (inputTile->getDataObjectStatus() == OSSIM_EMPTY)) + { + return NULL; + } + + if(theTile.valid()) + { + theTile->setImageRectangleAndBands(rect, inputTile->getNumberOfBands()); + } + + + ossim_float32* redBuff = (ossim_float32*)inputTile->getBuf(0); + ossim_float32* grnBuff = (ossim_float32*)inputTile->getBuf(1); + ossim_float32* bluBuff = (ossim_float32*)inputTile->getBuf(2); + + if(!redBuff||!grnBuff||!bluBuff) + { + return inputTile; + } + ossimRefPtr<ossimImageData> inputIntensity = getNormIntensity(rect, resLevel); + + if((!inputIntensity.valid()) || + (!inputIntensity->getBuf()) || + (inputIntensity->getDataObjectStatus() == OSSIM_EMPTY)) + { + return inputTile; + } + + ossim_float32* mono_buff = (ossim_float32*)inputIntensity->getBuf(0); + + // Since NULL_PIX_VALUE is only used for Pix8 comparisons cast it now. + const float NULL_PIX_VALUE = (ossim_float32)inputIntensity->getNullPix(0); + const float MIN_PIX_VALUE = (ossim_float32)inputIntensity->getMinPix(0); + const float MAX_PIX_VALUE = (ossim_float32)inputIntensity->getMaxPix(0); + + float rgb_sum; + float r_wt; // Weight of red to rgb_sum. + float g_wt; // Weight of green to rgb_sum. + float b_wt; // Weight of blue to rgb_sum. + float iVal; + float redVal; + float greenVal; + float blueVal; + + int size = theTile->getWidth()*theTile->getHeight(); + + for (int i = 0; i < size; i++) + { + //*** + // If no intensity source, or, no rgb source make output pixels null. + //*** + if ( (mono_buff[i] == NULL_PIX_VALUE) || + (redBuff[i] == NULL_PIX_VALUE && + grnBuff[i] == NULL_PIX_VALUE && + bluBuff[i] == NULL_PIX_VALUE) ) + + { + redBuff[i] = NULL_PIX_VALUE; + grnBuff[i] = NULL_PIX_VALUE; + bluBuff[i] = NULL_PIX_VALUE; + } + else + { + redVal = redBuff[i]; + greenVal = grnBuff[i]; + blueVal = bluBuff[i]; + rgb_sum = redVal + greenVal + blueVal + 3; + r_wt = 3 * (redVal + 1) / rgb_sum; + g_wt = 3 * (greenVal + 1) / rgb_sum; + b_wt = 3 * (blueVal + 1) / rgb_sum; + iVal = mono_buff[i] + 1; + + redVal = r_wt * iVal - 1; + greenVal = g_wt * iVal - 1; + blueVal = b_wt * iVal - 1; + + // Clip to max pixel value of radiometry. + if (redVal > MAX_PIX_VALUE) redVal = MAX_PIX_VALUE; + if (greenVal > MAX_PIX_VALUE) greenVal = MAX_PIX_VALUE; + if (blueVal > MAX_PIX_VALUE) blueVal = MAX_PIX_VALUE; + + // Assign chip value, clamp to min pixel value of radiometry if zero. + redBuff[i] = (float)(redVal>0.0 ? redVal : MIN_PIX_VALUE); + grnBuff[i] = (float)(greenVal>0.0 ? greenVal : MIN_PIX_VALUE); + bluBuff[i] = (float)(blueVal>0.0 ? blueVal : MIN_PIX_VALUE); + } + } // End of loop through pixels in chip. + theTile->copyNormalizedBufferToTile((float*)inputTile->getBuf()); + theTile->validate(); + + return theTile; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimColorNormalizedFusion.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimColorNormalizedFusion.h new file mode 100644 index 0000000000..f73f6a9fed --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimColorNormalizedFusion.h @@ -0,0 +1,32 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: Color normalized fusion +// +//************************************************************************* +// $Id: ossimColorNormalizedFusion.h,v 1.4 2005/02/11 15:07:32 dburken Exp $ +#ifndef ossimColorNormalizedFusion_HEADER +#define ossimColorNormalizedFusion_HEADER +#include "ossimFusionCombiner.h" + +class ossimColorNormalizedFusion : public ossimFusionCombiner +{ +public: + + ossimColorNormalizedFusion(); + ossimColorNormalizedFusion(ossimObject* owner); + virtual ~ossimColorNormalizedFusion(); + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect, + ossim_uint32 resLevel=0); + +protected: +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimConvolutionFilter1D.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimConvolutionFilter1D.cpp new file mode 100644 index 0000000000..29c00d5afc --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimConvolutionFilter1D.cpp @@ -0,0 +1,638 @@ +//******************************************************************* +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +//************************************************************************* +// $Id: ossimConvolutionFilter1D.cpp,v 1.1 2005/09/12 11:35:39 gpotts Exp $ + + +#include <imaging/tile_sources/ossimConvolutionFilter1D.h> +#include <base/data_types/ossimIrect.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <base/property/ossimMatrixProperty.h> +#include <base/property/ossimBooleanProperty.h> +#include <base/property/ossimNumericProperty.h> + +RTTI_DEF1(ossimConvolutionFilter1D, "ossimConvolutionFilter1D", ossimImageSourceFilter); + +#define PROPNAME_KERNELSIZE "KernelSize" +#define PROPNAME_KERNEL "Kernel" +#define PROPNAME_ISHZ "Horizontal" +#define PROPNAME_CENTEROFFSET "CenterOffset" + + +ossimConvolutionFilter1D::ossimConvolutionFilter1D(ossimObject* owner) + :ossimImageSourceFilter(owner), + theCenterOffset(0), + theTile(NULL), + theIsHz(true), + theNullPixValue(0), + theMinPixValue(0), + theMaxPixValue(0) +{ + //sets up an identity convolution + theKernel.push_back(1.0); +} + +ossimConvolutionFilter1D::~ossimConvolutionFilter1D() +{ +} + +ossimRefPtr<ossimImageData> ossimConvolutionFilter1D::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if(!theInputConnection) + { + return theTile; + } + + if(!isSourceEnabled()) + { + return theInputConnection->getTile(tileRect, resLevel); + } + + //--- + // We have a 1xn or nx1 matrix, + a center offset + // so stretch the input rect out to cover the required pixels + //--- + ossimIrect newRect; + ossim_int32 kl = theKernel.size(); //kernel length + if (theIsHz) + { + //horizontal kernel (row kernel) + newRect = ossimIrect(ossimIpt(tileRect.ul().x - theCenterOffset, + tileRect.ul().y), + ossimIpt(tileRect.lr().x - theCenterOffset + kl -1, + tileRect.lr().y)); + } else { + //vertical kernel + newRect = ossimIrect(ossimIpt(tileRect.ul().x, + tileRect.ul().y - theCenterOffset), + ossimIpt(tileRect.lr().x, + tileRect.lr().y - theCenterOffset + kl -1)); + } + ossimRefPtr<ossimImageData> data = theInputConnection->getTile(newRect, + resLevel); + + if(!data.valid() || !data->getBuf()) + { + return data; + } + + // First time through or after an initialize()... + if (!theTile.valid()) + { + allocate(); + if (!theTile.valid()) // Should never happen! + { + return data; + } + } + + // First time through, after an initialize() or a setKernel()... + if (!theNullPixValue.size()) + { + computeNullMinMax(); + if (!theNullPixValue.size()) // Should never happen! + { + return data; + } + } + + theTile->setImageRectangle(tileRect); + theTile->makeBlank(); + + switch(data->getScalarType()) + { + case OSSIM_UCHAR: + { + if(data->getDataObjectStatus() == OSSIM_FULL) + { + convolveFull(static_cast<ossim_uint8>(0), data, theTile); + } + else + { + convolvePartial(static_cast<ossim_uint8>(0), data, theTile); + } + break; + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + if(data->getDataObjectStatus() == OSSIM_FULL) + { + convolveFull(static_cast<float>(0), data, theTile); + } + else + { + convolvePartial(static_cast<float>(0), data, theTile); + } + break; + } + case OSSIM_USHORT16: + case OSSIM_USHORT11: + { + if(data->getDataObjectStatus() == OSSIM_FULL) + { + convolveFull(static_cast<ossim_uint16>(0), data, theTile); + } + else + { + convolvePartial(static_cast<ossim_uint16>(0), data, theTile); + } + break; + } + case OSSIM_SSHORT16: + { + if(data->getDataObjectStatus() == OSSIM_FULL) + { + convolveFull(static_cast<ossim_sint16>(0), data, theTile); + } + else + { + convolvePartial(static_cast<ossim_sint16>(0), data, theTile); + } + break; + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + if(data->getDataObjectStatus() == OSSIM_FULL) + { + convolveFull(static_cast<double>(0), data, theTile); + } + else + { + convolvePartial(static_cast<double>(0), data, theTile); + } + break; + } + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimConvolutionFilter1D::getTile WARNING:\n" + << "Scalar type = " << theTile->getScalarType() + << " Not supported by ossimConvolutionFilter1D" << endl; + break; + } + } + theTile->validate(); + + return theTile; +} + + +template<class T> void ossimConvolutionFilter1D::convolvePartial( + T, + ossimRefPtr<ossimImageData> inputData, + ossimRefPtr<ossimImageData> outputData) +{ + // there may be NULL pixels in the input + ossim_int32 inputW = static_cast<ossim_int32>(inputData->getWidth()); + ossim_uint32 outputW = outputData->getWidth(); + ossim_uint32 outputH = outputData->getHeight(); + ossim_uint32 numberOfBands = inputData->getNumberOfBands(); + + ossim_uint32 klength=theKernel.size(),k; + ossim_int32 incrK = theIsHz ? 1 : inputW; //kernel increment in input : one col or one row + ossim_int32 iRow = inputW - outputW; //jump to go to next row + + double sum=0.0; + T* iKP; //kernel covered input pointer + + ossim_int32 iCo = incrK*theCenterOffset; //center pixel offset within the input buffer + + for(ossim_uint32 band = 0; band < numberOfBands; ++band) + { + T* inputBuf = static_cast<T*>(inputData->getBuf(band)); + T* outputBuf = static_cast<T*>(outputData->getBuf(band)); + T maxPix = static_cast<T>(getMaxPixelValue(band)); + T minPix = static_cast<T>(getMinPixelValue(band)); + T nullPix = static_cast<T>(inputData->getNullPix(band)); + T oNullPix = static_cast<T>(getNullPixelValue(band)); + + if(inputBuf&&outputBuf) + { + for(ossim_uint32 row = 0; row < outputH; ++row) + { + for(ossim_uint32 col = 0; col < outputW; ++col) + { + //center pixel may not be NULL + if (inputBuf[iCo] != nullPix) + { + iKP = inputBuf; + sum = 0.0; + for(k=0;k<klength;++k) + { + if (*iKP != nullPix) //just sum on non-NULL pixels (potential normailzation issue) + { + sum += theKernel[k] * (double)(*iKP); + } + iKP += incrK; + } + + if(sum > maxPix) + { + *outputBuf = maxPix; + } + else if(sum < minPix) + { + *outputBuf = minPix; + } + else + { + *outputBuf = static_cast<T>(sum); + } + } else { + *outputBuf = oNullPix; + } + // move curent center position + inputBuf += 1; + outputBuf += 1; + } + //move current center position + inputBuf += iRow; + //outputBuf += 0; + } + } + } + + +} + +template<class T> void ossimConvolutionFilter1D::convolveFull( + T, + ossimRefPtr<ossimImageData> inputData, + ossimRefPtr<ossimImageData> outputData) +{ + //inputData must be displaced according to the Kernel size and theCenterOffset +isHz + ossim_int32 inputW = static_cast<ossim_int32>(inputData->getWidth()); + ossim_uint32 outputW = outputData->getWidth(); + ossim_uint32 outputH = outputData->getHeight(); + ossim_uint32 numberOfBands = inputData->getNumberOfBands(); + + ossim_uint32 klength=theKernel.size(), k; + ossim_int32 incrK = theIsHz ? 1 : inputW; //kernel increment in input : one col or one row + ossim_int32 iRow = inputW - outputW; //jump to go to next row + + double sum=0.0; + T* iKP; //kernel covered input pointer + + for(ossim_uint32 band = 0; band < numberOfBands; ++band) + { + T* inputBuf = static_cast<T*>(inputData->getBuf(band)); + T* outputBuf = static_cast<T*>(outputData->getBuf(band)); + T maxPix = static_cast<T>(getMaxPixelValue(band)); + T minPix = static_cast<T>(getMinPixelValue(band)); + + if(inputBuf&&outputBuf) + { + for(ossim_uint32 row = 0; row < outputH; ++row) + { + for(ossim_uint32 col = 0; col < outputW; ++col) + { + sum = 0.0; + iKP = inputBuf; + for(k=0;k<klength;++k) + { + sum += theKernel[k] * (double)(*iKP); + iKP += incrK; + } + + if(sum > maxPix) + { + *outputBuf = maxPix; + } + else if(sum < minPix) + { + *outputBuf = minPix; + } + else + { + *outputBuf = static_cast<T>(sum); + } + // move curent center position + inputBuf += 1; + outputBuf += 1; + } + //move current center position + inputBuf += iRow; + //outputBuf += 0; + } + } + } +} + +void ossimConvolutionFilter1D::initialize() +{ + //--- + // NOTE: + // Since initialize get called often sequentially we will wipe things slick + // but not reallocate to avoid multiple delete/allocates. + // + // On the first getTile call things will be reallocated/computed. + //--- + theTile = NULL; + clearNullMinMax(); +} + +void ossimConvolutionFilter1D::allocate() +{ + if(theInputConnection) + { + ossimImageDataFactory* idf = ossimImageDataFactory::instance(); + + theTile = idf->create(this, + this); + + theTile->initialize(); + } +} + +void ossimConvolutionFilter1D::setProperty(ossimRefPtr<ossimProperty> property) +{ + if(!property) return; + + if(property->getName() == PROPNAME_KERNEL) + { + ossimMatrixProperty* matrixProperty = PTR_CAST(ossimMatrixProperty, + property.get()); + if(matrixProperty) + { + ossim_uint32 nc=matrixProperty->getNumberOfCols(); + theKernel.resize(nc); + for(ossim_uint32 i=0;i<nc;++i) + { + theKernel[i] = (*matrixProperty)(0,i); + } + clearNullMinMax(); + } + else + { + ossimImageSourceFilter::setProperty(property); + } + } else if (property->getName() == PROPNAME_ISHZ) { + ossimBooleanProperty* booleanProperty = PTR_CAST(ossimBooleanProperty, + property.get()); + if(booleanProperty) + { + theIsHz = booleanProperty->getBoolean(); + } + } else if (property->getName() == PROPNAME_CENTEROFFSET) { + ossimNumericProperty* numProperty = PTR_CAST(ossimNumericProperty, + property.get()); + if(numProperty) + { + theCenterOffset = numProperty->asInt32(); + } + } else if (property->getName() == PROPNAME_KERNELSIZE) { + ossimNumericProperty* numProperty = PTR_CAST(ossimNumericProperty, + property.get()); + if(numProperty) + { + theKernel.resize(numProperty->asUInt32()); + clearNullMinMax(); + } + } else { + ossimImageSourceFilter::setProperty(property); + } +} + +ossimRefPtr<ossimProperty> ossimConvolutionFilter1D::getProperty(const ossimString& name)const +{ + if(name == PROPNAME_KERNEL) + { + ossimMatrixProperty* property = new ossimMatrixProperty(name); + property->resize(1,theKernel.size()); + for(ossim_uint32 i=0;i<theKernel.size();++i) + { + (*property)(0,i) = theKernel[i]; + } + property->setCacheRefreshBit(); + return property; + } else if (name==PROPNAME_ISHZ) { + ossimBooleanProperty* property = new ossimBooleanProperty(name,theIsHz); + property->setCacheRefreshBit(); + return property; + } else if (name==PROPNAME_CENTEROFFSET) { + ossimNumericProperty* property = new ossimNumericProperty(name,ossimString::toString(theCenterOffset)); + property->setNumericType(ossimNumericProperty::ossimNumericPropertyType_INT); //restrict to int type + property->setCacheRefreshBit(); + return property; + } else if (name == PROPNAME_KERNELSIZE) { + ossimNumericProperty* property = new ossimNumericProperty(name,ossimString::toString(theKernel.size()),1.0,100.0); + property->setNumericType(ossimNumericProperty::ossimNumericPropertyType_INT); //restrict to int type + property->setCacheRefreshBit(); + return property; + } + return ossimImageSourceFilter::getProperty(name); +} + +void ossimConvolutionFilter1D::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + ossimImageSourceFilter::getPropertyNames(propertyNames); + propertyNames.push_back(PROPNAME_KERNELSIZE); + propertyNames.push_back(PROPNAME_KERNEL); + propertyNames.push_back(PROPNAME_CENTEROFFSET); + propertyNames.push_back(PROPNAME_ISHZ); +} + +bool ossimConvolutionFilter1D::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + PROPNAME_KERNELSIZE, + theKernel.size(), + true); + kwl.add(prefix, + PROPNAME_CENTEROFFSET, + theCenterOffset, + true); + kwl.add(prefix, + PROPNAME_ISHZ, + theIsHz?"true":"false", //use string instead of boolean + true); + + for(ossim_uint32 row = 0; row < theKernel.size(); ++row) + { + ossimString newPrefix = "k" + ossimString::toString(row); + kwl.add(prefix, + newPrefix, + theKernel[row], + true); + } + + + return ossimImageSourceFilter::saveState(kwl, prefix); +} + + +bool ossimConvolutionFilter1D::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + //find kernel size + ossim_uint32 iks=0; + const char* ks = kwl.find(prefix, PROPNAME_KERNELSIZE); + if(ks) + { + iks = ossimString(ks).toUInt32(); + if (iks<1) + { + cerr<<"ossimConvolutionFilter1D : warning bad "<< PROPNAME_KERNELSIZE <<" in state"<<endl; + iks=0; + } + } else { + iks=0; + cerr<<"ossimConvolutionFilter1D : warning no "<< PROPNAME_KERNELSIZE <<" in state"<<endl; + } + + //load other props + const char* co = kwl.find(prefix, PROPNAME_CENTEROFFSET); + if(co) + { + setCenterOffset(ossimString(co).toUInt32()); + } else { + cerr<<"ossimConvolutionFilter1D : warning no "<< PROPNAME_CENTEROFFSET<<" in state"<<endl; + } + const char* ih = kwl.find(prefix, PROPNAME_ISHZ); + if(ih) + { + setIsHorizontal(ossimString(ih).toBool()); + } else { + cerr<<"ossimConvolutionFilter1D : warning no "<<PROPNAME_ISHZ<<" in state"<<endl; + } + + //load kernel values + ossimString newPrefix = prefix; + newPrefix += ossimString("k"); + theKernel.resize(iks); + for(ossim_uint32 r=0; r<iks; ++r) + { + ossimString value = ossimString::toString(r); + + const char* v = kwl.find(newPrefix.c_str(), + value.c_str()); + if(v) + { + theKernel[r] = ossimString(v).toDouble(); + } else { + cerr<<"ossimConvolutionFilter1D : warning no value for "<<newPrefix<<" in state"<<endl; + theKernel[r] = 0.0; + } + } + clearNullMinMax(); + + return ossimImageSourceFilter::loadState(kwl, prefix); +} + +void ossimConvolutionFilter1D::setKernel(const std::vector<ossim_float64>& aKernel) +{ + theKernel = aKernel; + // Will be recomputed first getTile call. + clearNullMinMax(); +} + +double ossimConvolutionFilter1D::getNullPixelValue(ossim_uint32 band)const +{ + if( isSourceEnabled() && (band < theNullPixValue.size()) ) + { + return theNullPixValue[band]; + } + + return ossimGetDefaultNull(getOutputScalarType()); +} + +double ossimConvolutionFilter1D::getMinPixelValue(ossim_uint32 band)const +{ + if( isSourceEnabled() && (band < theMinPixValue.size()) ) + { + return theMinPixValue[band]; + } + + return ossimImageSource::getMinPixelValue(band); +} + +double ossimConvolutionFilter1D::getMaxPixelValue(ossim_uint32 band)const +{ + if( isSourceEnabled() && (band < theMaxPixValue.size()) ) + { + return theMaxPixValue[band]; + } + + return ossimImageSource::getMaxPixelValue(band); +} + +void ossimConvolutionFilter1D::clearNullMinMax() +{ + theNullPixValue.clear(); + theMinPixValue.clear(); + theMaxPixValue.clear(); +} + +void ossimConvolutionFilter1D::computeNullMinMax() +{ + const ossim_uint32 BANDS = getNumberOfOutputBands(); + + theNullPixValue.resize(BANDS); + theMinPixValue.resize(BANDS); + theMaxPixValue.resize(BANDS); + + ossim_float64 defaultNull = ossimGetDefaultNull(getOutputScalarType()); + ossim_float64 defaultMin = ossimGetDefaultMin(getOutputScalarType()); + ossim_float64 defaultMax = ossimGetDefaultMax(getOutputScalarType()); + + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + if(theInputConnection) + { + ossim_float64 inputNull = theInputConnection->getNullPixelValue(band); + ossim_float64 inputMin = theInputConnection->getMinPixelValue(band); + ossim_float64 inputMax = theInputConnection->getMaxPixelValue(band); + ossim_float64 tempMin = 0.0; + ossim_float64 tempMax = 0.0; + ossim_float64 k = 0.0; + for(ossim_uint32 i=0;i<theKernel.size();++i) + { + k=theKernel[i]; + tempMin += (k<0.0) ? k*inputMax : k*inputMin; + tempMax += (k>0.0) ? k*inputMax : k*inputMin; + } + + if((tempMin >= defaultMin) && (tempMin <= defaultMax)) + { + theMinPixValue[band] = tempMin; + } + else + { + theMinPixValue[band] = defaultMin; + } + + if((tempMax >= defaultMin) && (tempMax <= defaultMax)) + { + theMaxPixValue[band] = tempMax; + } + else + { + theMaxPixValue[band] = defaultMax; + } + if((inputNull < theMinPixValue[band]) || + (inputNull > theMaxPixValue[band])) + { + theNullPixValue[band] = inputNull; + } + else + { + theNullPixValue[band] = defaultNull; + } + + } + else // No input connection... + { + theNullPixValue[band] = defaultNull; + theMinPixValue[band] = defaultMin; + theMaxPixValue[band] = defaultMax; + } + + } // End of band loop. +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimConvolutionFilter1D.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimConvolutionFilter1D.h new file mode 100644 index 0000000000..66602919dc --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimConvolutionFilter1D.h @@ -0,0 +1,102 @@ +//******************************************************************* +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// class ossimImageGaussianFilter : tile source +// class ossimConvolutionFilter1D +// one dimensional convolution +// +// efficient for gradients & separable convolution kernels (like gaussian) +//******************************************************************* +// $Id: ossimConvolutionFilter1D.h,v 1.2 2005/09/12 13:39:07 gpotts Exp $ + +#ifndef ossimConvolutionFilter1D_HEADER +#define ossimConvolutionFilter1D_HEADER + +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +class OSSIM_DLL ossimConvolutionFilter1D : public ossimImageSourceFilter +{ +public: + //! own class methods + ossimConvolutionFilter1D(ossimObject* owner=NULL); + virtual ~ossimConvolutionFilter1D(); + + virtual inline const std::vector<ossim_float64>& getKernel()const { return theKernel; } + virtual void setKernel(const std::vector<ossim_float64>& aKernel); + + virtual inline bool isHorizontal()const { return theIsHz; } + virtual inline void setIsHorizontal(bool aIsHz) { theIsHz = aIsHz; } + + virtual inline ossim_int32 getCenterOffset()const { return theCenterOffset; } + virtual inline void setCenterOffset(ossim_int32 aCenterOffset) { theCenterOffset = aCenterOffset; } + + //! inherited methods + virtual ossimString getShortName()const{return ossimString("1D Convolution");} + virtual ossimString getLongName()const{return ossimString("Convolves the input image with a one dimensional convolution kernel");} + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect,ossim_uint32 resLevel=0); + + virtual void initialize(); + + virtual double getNullPixelValue(ossim_uint32 band=0) const; + virtual double getMinPixelValue(ossim_uint32 band=0) const; + virtual double getMaxPixelValue(ossim_uint32 band=0) const; + + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + + virtual bool loadState(const ossimKeywordlist& kwl,const char* prefix = 0); + virtual bool saveState(ossimKeywordlist& kwl,const char* prefix = 0)const; + +protected: + + /** + * Allocates theTile. + */ + void allocate(); + + /** + * Clears data members theNullPixValue, theMinPixValue, and + * theMaxPixValue. + */ + void clearNullMinMax(); + + /** + * Computes null, min, and max considering input connection and theKernel. + */ + void computeNullMinMax(); + + /*! + * Convolve full means that the input data is full and has + * no null data. We don't have to compare for nulls here + */ + template<class T> + void convolveFull(T, + ossimRefPtr<ossimImageData> inputData, + ossimRefPtr<ossimImageData> outputData); + + /*! + * Convolve partial means that the input data is has some + * null data. We will have to compare nulls + */ + template<class T> + void convolvePartial(T, + ossimRefPtr<ossimImageData> inputData, + ossimRefPtr<ossimImageData> outputData); + + //! offset of center point in the Kernel + ossim_int32 theCenterOffset; + ossimRefPtr<ossimImageData> theTile; + std::vector<ossim_float64> theKernel; + bool theIsHz; //! isHorizontal convolution? + + std::vector<double> theNullPixValue; + std::vector<double> theMinPixValue; + std::vector<double> theMaxPixValue; + +TYPE_DATA +}; + +#endif /* #ifndef ossimConvolutionFilter1D_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimConvolutionSource.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimConvolutionSource.cpp new file mode 100644 index 0000000000..d2405e22ce --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimConvolutionSource.cpp @@ -0,0 +1,525 @@ +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimConvolutionSource.cpp,v 1.17 2005/12/08 13:56:23 gpotts Exp $ + +#include <imaging/tile_sources/ossimConvolutionSource.h> +#include <imaging/ossimImageData.h> +#include <imaging/filters/ossimDiscreteConvolutionKernel.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimKeyword.h> + +static const ossimKeyword NUMBER_OF_MATRICES = ossimKeyword("number_of_matrices", ""); +static const ossimKeyword NUMBER_OF_ROWS = ossimKeyword("rows", ""); +static const ossimKeyword NUMBER_OF_COLS = ossimKeyword("cols", ""); + +RTTI_DEF1(ossimConvolutionSource, "ossimConvolutionSource", ossimImageSourceFilter); + +ossimConvolutionSource::ossimConvolutionSource() + : ossimImageSourceFilter(), + theTile(NULL) +{ +} + +ossimConvolutionSource::ossimConvolutionSource(ossimImageSource* inputSource, + const NEWMAT::Matrix& convolutionMatrix) + : ossimImageSourceFilter(inputSource), + theTile(NULL) +{ + theConvolutionKernelList.push_back(new ossimDiscreteConvolutionKernel(convolutionMatrix)); + setKernelInformation(); + initialize(); +} + +ossimConvolutionSource::ossimConvolutionSource(ossimImageSource* inputSource, + const vector<NEWMAT::Matrix>& convolutionList) + : ossimImageSourceFilter(inputSource), + theTile(NULL) +{ + setConvolutionList(convolutionList); +} + +ossimConvolutionSource::~ossimConvolutionSource() +{ + deleteConvolutionList(); +} + +void ossimConvolutionSource::setConvolution(const double* kernel, + int nrows, + int ncols, + bool doWeightedAverage) +{ + NEWMAT::Matrix m(nrows, ncols); + const double* tempPtr = kernel; + for(int row = 0; row < nrows; ++row) + { + for(int col = 0; col < ncols; ++col) + { + m[row][col] =*tempPtr; + ++tempPtr; + } + } + + setConvolution(m, doWeightedAverage); +} + +void ossimConvolutionSource::setConvolutionList(const vector<NEWMAT::Matrix>& convolutionList, + bool doWeightedAverage) +{ + deleteConvolutionList(); + ossim_uint32 idx; + for(idx = 0; idx < convolutionList.size(); ++idx) + { + theConvolutionKernelList.push_back(new ossimDiscreteConvolutionKernel(convolutionList[idx], + doWeightedAverage)); + } + + setKernelInformation(); +} + +ossimRefPtr<ossimImageData> ossimConvolutionSource::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if(!theInputConnection) return ossimRefPtr<ossimImageData>(); + + if((!isSourceEnabled())|| + (theConvolutionKernelList.size() < 1)) + { + return theInputConnection->getTile(tileRect, resLevel); + } + + if(!theTile.valid()) + { + allocate(); + if(!theTile.valid()) // Throw exception??? + { + return theInputConnection->getTile(tileRect, resLevel); + } + } + + ossim_uint32 w = tileRect.width(); + ossim_uint32 h = tileRect.height(); + ossim_uint32 tw = theTile->getWidth(); + ossim_uint32 th = theTile->getHeight(); + theTile->setWidth(w); + theTile->setHeight(h); + if((w*h)!=(tw*th)) + { + theTile->initialize(); + theTile->makeBlank(); + } + else + { + theTile->makeBlank(); + } + theTile->setOrigin(tileRect.ul()); + long offsetX = (theMaxKernelWidth)/2; + long offsetY = (theMaxKernelHeight)/2; + ossimIrect requestRect(tileRect.ul().x - offsetX, + tileRect.ul().y - offsetY, + tileRect.lr().x + offsetX, + tileRect.lr().y + offsetY); + + ossimRefPtr<ossimImageData> input = theInputConnection->getTile(requestRect, + resLevel); + + if(!input.valid() || + (input->getDataObjectStatus() == OSSIM_NULL)|| + (input->getDataObjectStatus() == OSSIM_EMPTY)) + { + return input; + } + switch(theTile->getScalarType()) + { + case OSSIM_UCHAR: + { + if(theConvolutionKernelList.size() == 1) + { + convolve(static_cast<ossim_uint8>(0), + input, + theConvolutionKernelList[0]); + } + else + { + ossim_uint32 upperBound = theConvolutionKernelList.size(); + ossim_uint32 idx; + for(idx = 0; idx < upperBound; ++idx) + { + convolve(static_cast<ossim_uint8>(0), + input, + theConvolutionKernelList[idx]); + input->loadTile(theTile.get()); + } + } + break; + } + case OSSIM_USHORT16: + case OSSIM_USHORT11: + { + if(theConvolutionKernelList.size() == 1) + { + convolve(static_cast<ossim_uint16>(0), + input, + theConvolutionKernelList[0]); + } + else + { + ossim_uint32 upperBound = theConvolutionKernelList.size(); + ossim_uint32 idx; + for(idx = 0; idx < upperBound; ++idx) + { + convolve(static_cast<ossim_uint16>(0), + input, + theConvolutionKernelList[idx]); + input->loadTile(theTile.get()); + } + } + break; + } + case OSSIM_SSHORT16: + { + if(theConvolutionKernelList.size() == 1) + { + convolve(static_cast<ossim_sint16>(0), + input, + theConvolutionKernelList[0]); + } + else + { + ossim_uint32 upperBound = theConvolutionKernelList.size(); + ossim_uint32 idx; + for(idx = 0; idx < upperBound; ++idx) + { + convolve(static_cast<ossim_sint16>(0), + input, + theConvolutionKernelList[idx]); + input->loadTile(theTile.get()); + } + } + break; + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + if(theConvolutionKernelList.size() == 1) + { + convolve(static_cast<float>(0), + input, + theConvolutionKernelList[0]); + } + else + { + ossim_uint32 upperBound = theConvolutionKernelList.size(); + ossim_uint32 idx; + for(idx = 0; idx < upperBound; ++idx) + { + convolve(static_cast<float>(0), + input, + theConvolutionKernelList[idx]); + input->loadTile(theTile.get()); + } + } + break; + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + if(theConvolutionKernelList.size() == 1) + { + convolve(static_cast<double>(0), + input, + theConvolutionKernelList[0]); + } + else + { + ossim_uint32 upperBound = theConvolutionKernelList.size(); + ossim_uint32 idx; + for(idx = 0; idx < upperBound; ++idx) + { + convolve(static_cast<double>(0), + input, + theConvolutionKernelList[idx]); + input->loadTile(theTile.get()); + } + } + break; + } + default: + { + theTile->loadTile(input.get()); + } + } + theTile->validate(); + return theTile; +} + +template <class T> +void ossimConvolutionSource::convolve(T dummyVariable, + ossimRefPtr<ossimImageData> inputTile, + ossimDiscreteConvolutionKernel* kernel) +{ + ossimIpt startOrigin = theTile->getOrigin(); + + // Make sure that the patch is not empty or NULL + // + ossimIpt startDelta(startOrigin.x - inputTile->getOrigin().x, + startOrigin.y - inputTile->getOrigin().y); + + ossimDataObjectStatus status = inputTile->getDataObjectStatus(); + // let's setup some variables that we will need to do the + // convolution algorithm. + // + ossimIrect patchRect = inputTile->getImageRectangle(); + long tileHeight = theTile->getHeight(); + long tileWidth = theTile->getWidth(); + long outputBands = theTile->getNumberOfBands(); + long convolutionWidth = kernel->getWidth(); + long convolutionHeight = kernel->getHeight(); + long convolutionOffsetX= convolutionWidth/2; + long convolutionOffsetY= convolutionHeight/2; + long patchWidth = patchRect.width(); + long convolutionTopLeftOffset = 0; + long convolutionCenterOffset = 0; + + long outputOffset = 0; + T min = 0; + T max = 0; + T np = 0; + const double* minPix = inputTile->getMinPix(); + const double* maxPix = inputTile->getMaxPix(); + const double* nullPix = inputTile->getNullPix(); + double convolveResult = 0; + + if(status == OSSIM_PARTIAL) // must check for NULLS + { + for(long y = 0; y <tileHeight; y++) + { + convolutionCenterOffset = patchWidth*(startDelta.y + y) + startDelta.x; + convolutionTopLeftOffset = patchWidth*(startDelta.y + y - convolutionOffsetY) + startDelta.x-convolutionOffsetX; + + for(long x =0; x < tileWidth; x++) + { + if(!inputTile->isNull(convolutionCenterOffset)) + { + for(long b = 0; b < outputBands; ++b) + { + T* buf = (T*)(inputTile->getBuf(b)) + convolutionTopLeftOffset; + T* outBuf = (T*)(theTile->getBuf(b)); + kernel->convolveSubImage(buf, + patchWidth, + convolveResult, + (T)nullPix[b]); + convolveResult = convolveResult < minPix[b]? minPix[b]:convolveResult; + convolveResult = convolveResult > maxPix[b]? maxPix[b]:convolveResult; + + outBuf[outputOffset] = (T)convolveResult; + } + } + else + { + theTile->setNull(outputOffset); + + } + ++convolutionCenterOffset; + ++convolutionTopLeftOffset; + ++outputOffset; + } + } + } + else // do not need to check for nulls here. + { + for(long b = 0; b < outputBands; ++b) + { + double convolveResult = 0; + const T* buf = (const T*)inputTile->getBuf(b); + T* outBuf = (T*)(theTile->getBuf(b)); + min=(T)minPix[b]; + max=(T)maxPix[b]; + np =(T)nullPix[b]; + outputOffset = 0; + + for(long y = 0; y <tileHeight; y++) + { + convolutionTopLeftOffset = patchWidth*(startDelta.y + y - convolutionOffsetY) + startDelta.x-convolutionOffsetX; + + for(long x =0; x < tileWidth; x++) + { + kernel->convolveSubImage(&buf[convolutionTopLeftOffset], + patchWidth, + convolveResult, + np); + convolveResult = convolveResult < min? min:convolveResult; + convolveResult = convolveResult > max?max:convolveResult; + outBuf[outputOffset] = (T)convolveResult; + ++outputOffset; + ++convolutionTopLeftOffset; + } + } + } + } +} + +void ossimConvolutionSource::initialize() +{ + ossimImageSourceFilter::initialize(); + theTile = NULL; +} + +void ossimConvolutionSource::allocate() +{ + if(theInputConnection) + { + theTile = ossimImageDataFactory::instance()->create(this, + theInputConnection); + theTile->initialize(); + } +} + +bool ossimConvolutionSource::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + long numberOfMatrices = 0; + for(long m = 0; m < (long)theConvolutionKernelList.size();++m) + { + if(theConvolutionKernelList[m]) + { + ++numberOfMatrices; + const NEWMAT::Matrix& kernel = theConvolutionKernelList[m]->getKernel(); + ossimString mPrefix = "m" + + ossimString::toString(numberOfMatrices) + + "."; + kwl.add(prefix, + (mPrefix + "rows").c_str(), + kernel.Nrows(), + true); + + kwl.add(prefix, + (mPrefix + "cols").c_str(), + kernel.Ncols(), + true); + + for(long row = 0; row < kernel.Nrows(); ++row) + { + for(long col =0; col < kernel.Ncols(); ++col) + { + ossimString newPrefix = mPrefix + + ossimString::toString(row+1) + "_" + + ossimString::toString(col+1); + kwl.add(prefix, + newPrefix, + kernel[row][col], + true); + } + } + } + } + + + kwl.add(prefix, + NUMBER_OF_MATRICES, + numberOfMatrices, + true); + + return ossimImageSourceFilter::saveState(kwl, prefix); +} + + +bool ossimConvolutionSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + deleteConvolutionList(); + + const char* numberOfMatrices = kwl.find(prefix, NUMBER_OF_MATRICES); + + long matrixCount = ossimString(numberOfMatrices).toLong(); + long numberOfMatches = 0; + long index = 0; + while(numberOfMatches < matrixCount) + { + ossimString newPrefix = prefix; + newPrefix += ossimString("m"); + newPrefix += ossimString::toString(index); + newPrefix += ossimString("."); + + const char* rows = kwl.find((newPrefix+NUMBER_OF_ROWS.key()).c_str()); + const char* cols = kwl.find((newPrefix+NUMBER_OF_COLS.key()).c_str()); + + if(rows&&cols) + { + ++numberOfMatches; + long numberOfRows = ossimString(rows).toLong(); + long numberOfCols = ossimString(cols).toLong(); + NEWMAT::Matrix convolutionMatrix(numberOfRows, numberOfCols); + + + for(long r = 1; r <= numberOfRows; r++) + { + for(long c = 1; c <= numberOfCols; c++) + { + convolutionMatrix[r-1][c-1] = 0.0; + + ossimString value = ossimString::toString(r); + value += "_"; + value += ossimString::toString(c); + + const char* v = kwl.find(newPrefix.c_str(), + value.c_str()); + if(v) + { + convolutionMatrix[r-1][c-1] = ossimString(v).toDouble(); + } + } + } + theConvolutionKernelList.push_back(new ossimDiscreteConvolutionKernel(convolutionMatrix)); + } + ++index; + } + setKernelInformation(); + return ossimImageSourceFilter::loadState(kwl, prefix); +} + +void ossimConvolutionSource::setKernelInformation() +{ + long index; + + if(theConvolutionKernelList.size() > 0) + { + theMaxKernelWidth = theConvolutionKernelList[0]->getWidth(); + theMaxKernelHeight = theConvolutionKernelList[0]->getHeight(); + + for(index = 1; index < (long)theConvolutionKernelList.size(); ++index) + { + long w = theConvolutionKernelList[index]->getWidth(); + long h = theConvolutionKernelList[index]->getHeight(); + theMaxKernelWidth = theMaxKernelWidth < w?w:theMaxKernelWidth; + theMaxKernelHeight = theMaxKernelHeight < h?h:theMaxKernelHeight; + } + } +} + +void ossimConvolutionSource::deleteConvolutionList() +{ + for(long index = 0; index < (long)theConvolutionKernelList.size(); ++index) + { + delete theConvolutionKernelList[index]; + } + + theConvolutionKernelList.clear(); +} + +void ossimConvolutionSource::setConvolution(const NEWMAT::Matrix& convolutionMatrix, bool doWeightedAverage) +{ + std::vector<NEWMAT::Matrix> m; + + m.push_back(convolutionMatrix); + + setConvolutionList(m, doWeightedAverage); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimConvolutionSource.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimConvolutionSource.h new file mode 100644 index 0000000000..ce07a7f226 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimConvolutionSource.h @@ -0,0 +1,72 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimConvolutionSource.h,v 1.13 2005/12/07 20:21:17 gpotts Exp $ +#ifndef ossimConvolutionSource_HEADER +#define ossimConvolutionSource_HEADER +#include <vector> +#include <iostream> +#include <matrix/newmat.h> +using namespace std; + +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +class ossimTilePatch; +class ossimDiscreteConvolutionKernel; + +class ossimConvolutionSource : public ossimImageSourceFilter +{ +public: + ossimConvolutionSource(); + ossimConvolutionSource(ossimImageSource* inputSource, + const NEWMAT::Matrix& convolutionMatix); + ossimConvolutionSource(ossimImageSource* inputSource, + const vector<NEWMAT::Matrix>& convolutionList); + virtual ~ossimConvolutionSource(); + + virtual void setConvolution(const double* kernel, int nrows, int ncols, bool doWeightedAverage=false); + virtual void setConvolution(const NEWMAT::Matrix& convolutionMatrix, bool doWeightedAverage=false); + virtual void setConvolutionList(const vector<NEWMAT::Matrix>& convolutionList, bool doWeightedAverage=false); + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=NULL)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=NULL); + + ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, ossim_uint32 resLevel=0); + + virtual void initialize(); + +protected: + + void allocate(); + + ossimRefPtr<ossimImageData> theTile; + long theMaxKernelWidth; + long theMaxKernelHeight; + + vector<ossimDiscreteConvolutionKernel*> theConvolutionKernelList; + virtual void setKernelInformation(); + virtual void deleteConvolutionList(); + + template<class T> + void convolve(T dummyVariable, + ossimRefPtr<ossimImageData> inputTile, + ossimDiscreteConvolutionKernel* kernel); + + +TYPE_DATA +}; + +#endif /* #ifndef ossimConvolutionSource_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEastingNorthingCutter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEastingNorthingCutter.cpp new file mode 100644 index 0000000000..cf55781626 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEastingNorthingCutter.cpp @@ -0,0 +1,209 @@ +//---------------------------------------------------------------------------- +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// $Id: ossimEastingNorthingCutter.cpp,v 1.5 2005/10/03 13:16:40 gpotts Exp $ +//---------------------------------------------------------------------------- + +#include <sstream> +#include <imaging/tile_sources/ossimEastingNorthingCutter.h> +#include <projections/map_projections/ossimMapProjection.h> +#include <base/common/ossimKeywordNames.h> +#include <base/common/ossimTrace.h> + +RTTI_DEF2(ossimEastingNorthingCutter, "ossimEastingNorthingCutter", ossimRectangleCutFilter, ossimViewInterface); + +static ossimTrace traceDebug(ossimString("ossimEastingNorthingCutter:debug")); + + +ossimEastingNorthingCutter::ossimEastingNorthingCutter(ossimObject* owner, + ossimImageSource* inputSource) + :ossimRectangleCutFilter(owner, + inputSource), + ossimViewInterface(0), + theViewProjection(0) +{ + theUlEastingNorthing.makeNan(); + theLrEastingNorthing.makeNan(); + theCutType = OSSIM_RECTANGLE_NULL_OUTSIDE; +} + +ossimEastingNorthingCutter::ossimEastingNorthingCutter(ossimImageSource* inputSource) + :ossimRectangleCutFilter(inputSource), + ossimViewInterface(0), + theViewProjection(0) +{ + theUlEastingNorthing.makeNan(); + theLrEastingNorthing.makeNan(); + theCutType = OSSIM_RECTANGLE_NULL_OUTSIDE; +} + +ossimEastingNorthingCutter::~ossimEastingNorthingCutter() +{ + if(theViewProjection) + { + delete theViewProjection; + theViewProjection = 0; + } +} + +void ossimEastingNorthingCutter::setEastingNorthingRectangle(const ossimDpt& ul, + const ossimDpt& lr) +{ + theUlEastingNorthing = ul; + theLrEastingNorthing = lr; + + transformVertices(); +} + +ossimDpt ossimEastingNorthingCutter::getUlEastingNorthing()const +{ + return theUlEastingNorthing; +} + +ossimDpt ossimEastingNorthingCutter::getLrEastingNorthing()const +{ + return theLrEastingNorthing; +} + + +void ossimEastingNorthingCutter::initialize() +{ + ossimRectangleCutFilter::initialize(); + transformVertices(); +} + +bool ossimEastingNorthingCutter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + "ul_en", + ossimString::toString(theUlEastingNorthing.x) + " " + + ossimString::toString(theUlEastingNorthing.y), + true); + kwl.add(prefix, + "lr_en", + ossimString::toString(theLrEastingNorthing.x) + " " + + ossimString::toString(theLrEastingNorthing.y), + true); + + return ossimRectangleCutFilter::saveState(kwl, prefix); +} + +bool ossimEastingNorthingCutter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char *ul = kwl.find(prefix, + "ul_en"); + const char *lr = kwl.find(prefix, + "lr_en"); + + theUlEastingNorthing.makeNan(); + theLrEastingNorthing.makeNan(); + + if(ul) + { + istringstream in(ul); + + in >> theUlEastingNorthing.x >> theUlEastingNorthing.y; + } + + if(lr) + { + istringstream in(lr); + + in >> theLrEastingNorthing.x >> theLrEastingNorthing.y; + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimEastingNorthingCutter::loadState DEBUG:" + << "\ntheUlEastingNorthing: " << theUlEastingNorthing + << "\ntheLrEastingNorthing: " << theLrEastingNorthing + << endl; + } + + return ossimRectangleCutFilter::loadState(kwl, prefix); +} + +bool ossimEastingNorthingCutter::setView(ossimObject* baseObject, + bool ownsTheView) +{ + ossimProjection* tempProj = PTR_CAST(ossimProjection, + baseObject); + if(!tempProj) + { + return false; + } + + if(theViewProjection) + { + delete theViewProjection; + theViewProjection = 0; + } + + if(ownsTheView) + { + theViewProjection = tempProj; + } + else + { + theViewProjection = (ossimProjection*)tempProj->dup(); + } + + transformVertices(); + + return true; +} + +ossimObject* ossimEastingNorthingCutter::getView() +{ + return theViewProjection; +} + +const ossimObject* ossimEastingNorthingCutter::getView()const +{ + return theViewProjection; +} + +void ossimEastingNorthingCutter::transformVertices() +{ + theRectangle.makeNan(); + + if(theUlEastingNorthing.hasNans()|| + theLrEastingNorthing.hasNans()|| + (!theViewProjection)) + { + return; + } + + ossimMapProjection* mapProj = PTR_CAST(ossimMapProjection, + theViewProjection); + ossimDpt ul; + ossimDpt lr; + ossimDpt easting; + ossimDpt northing; + if(mapProj) + { + mapProj->eastingNorthingToLineSample(theUlEastingNorthing, ul); + mapProj->eastingNorthingToLineSample(theLrEastingNorthing, lr); + + ossimDrect drect(ul.x, ul.y, lr.x, lr.y); + + theRectangle = drect; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimEastingNorthingCutter::transformVertices DEBUG:" + << "original drect: " << drect + << "\ntheRectangle: " << theRectangle + << endl; + } + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEastingNorthingCutter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEastingNorthingCutter.h new file mode 100644 index 0000000000..b2d8ca115e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEastingNorthingCutter.h @@ -0,0 +1,45 @@ +#ifndef ossimEastingNorthingCutter_HEADER +#define ossimEastingNorthingCutter_HEADER +#include "ossimRectangleCutFilter.h" +#include "base/common/ossimViewInterface.h" + +class ossimProjection; +class ossimEastingNorthingCutter : public ossimRectangleCutFilter, + public ossimViewInterface +{ +public: + ossimEastingNorthingCutter(ossimObject* owner, + ossimImageSource* inputSource=NULL); + ossimEastingNorthingCutter(ossimImageSource* inputSource=NULL); + virtual ~ossimEastingNorthingCutter(); + + void setEastingNorthingRectangle(const ossimDpt& ul, + const ossimDpt& lr); + ossimDpt getUlEastingNorthing()const; + ossimDpt getLrEastingNorthing()const; + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual bool setView(ossimObject* baseObject, + bool ownsTheView = false); + + virtual ossimObject* getView(); + virtual const ossimObject* getView()const; + + virtual void initialize(); + +protected: + ossimDpt theUlEastingNorthing; + ossimDpt theLrEastingNorthing; + + ossimProjection* theViewProjection; + + + void transformVertices(); +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEdgeFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEdgeFilter.cpp new file mode 100644 index 0000000000..c74109e89a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEdgeFilter.cpp @@ -0,0 +1,545 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimEdgeFilter.cpp,v 1.9 2005/08/17 19:18:12 gpotts Exp $ +#include <imaging/tile_sources/ossimEdgeFilter.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <imaging/ossimImageData.h> +#include <base/property/ossimStringProperty.h> + +RTTI_DEF1(ossimEdgeFilter, "ossimEdgeFilter", ossimImageSourceFilter); + +ossimEdgeFilter::ossimEdgeFilter(ossimObject* owner) + :ossimImageSourceFilter(owner), + theTile(NULL), + theFilterType("Sobel") +{ +} + +ossimEdgeFilter::ossimEdgeFilter(ossimImageSource* inputSource) + :ossimImageSourceFilter(inputSource), + theTile(NULL), + theFilterType("Sobel") +{ +} + +ossimEdgeFilter::ossimEdgeFilter(ossimObject* owner, + ossimImageSource* inputSource) + :ossimImageSourceFilter(owner, inputSource), + theTile(NULL), + theFilterType("Sobel") +{ +} + +ossimRefPtr<ossimImageData> ossimEdgeFilter::getTile(const ossimIrect& rect, + ossim_uint32 resLevel) +{ + if(!isSourceEnabled()) + { + return ossimImageSourceFilter::getTile(rect, resLevel); + } + + // expand the rect out to cver the 3x3 horizontal and vertical + // kernel. + // + ossimIrect requestRect = rect; + + adjustRequestRect(requestRect); + + ossimRefPtr<ossimImageData> inputData = + ossimImageSourceFilter::getTile(requestRect, resLevel); + + if(!inputData.valid() || (!inputData->getBuf())) + { + return inputData; + } + + if(!theTile.valid()) initialize(); + if(!theTile.valid()) return theTile; + + theTile->setImageRectangleAndBands(rect, inputData->getNumberOfBands()); + + switch(theTile->getScalarType()) + { + case OSSIM_UCHAR: + { + runFilter((ossim_uint8)0, + inputData); + break; + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + runFilter((ossim_float32)0, + inputData); + break; + } + case OSSIM_USHORT16: + case OSSIM_USHORT11: + { + runFilter((ossim_uint16)0, + inputData); + break; + } + case OSSIM_SSHORT16: + { + runFilter((ossim_sint16)0, + inputData); + break; + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + runFilter((ossim_float64)0, + inputData); + break; + } + default: + { + ossimNotify(ossimNotifyLevel_WARN) << "ossimEdgeFilter::getTile WARN: Scalar type = " << theTile->getScalarType() + << " Not supported by ossimEdgeFilter" << std::endl; + break; + } + } + + return theTile; +} + +void ossimEdgeFilter::initialize() +{ + ossimImageSourceFilter::initialize(); + + theTile = NULL; + + if(!isSourceEnabled()) + { + return; + } + + theTile = ossimImageDataFactory::instance()->create(this, this); + if(theTile.valid()) + { + theTile->initialize(); + } +} + +void ossimEdgeFilter::getFilterTypeNames( + std::vector<ossimString>& filterNames)const +{ + filterNames.push_back("Laplacian"); + filterNames.push_back("Prewitt"); + filterNames.push_back("Roberts"); + filterNames.push_back("Sobel"); +} + +ossimString ossimEdgeFilter::getFilterType()const +{ + return theFilterType; +} + +void ossimEdgeFilter::setFilterType(const ossimString& filterType) +{ + ossimString tempFilterType = filterType; + tempFilterType = tempFilterType.downcase(); + + if(tempFilterType.contains("sob")) + { + tempFilterType = "Sobel"; + } + else if(tempFilterType.contains("lap")) + { + tempFilterType = "Laplacian"; + } + else if(tempFilterType.contains("prew")) + { + tempFilterType = "Prewitt"; + } + else if(tempFilterType.contains("rob")) + { + tempFilterType = "Roberts"; + } + else + { + tempFilterType = "Sobel"; + } +} + +void ossimEdgeFilter::setProperty(ossimRefPtr<ossimProperty> property) +{ + if(!property) return; + + if(property->getName() == "Edge type") + { + theFilterType = property->valueToString(); + } +} + +ossimRefPtr<ossimProperty> ossimEdgeFilter::getProperty(const ossimString& name)const +{ + if(name == "Edge type") + { + std::vector<ossimString> filterNames; + + getFilterTypeNames(filterNames); + ossimStringProperty* stringProp = new ossimStringProperty("Edge type", + theFilterType, + false, + filterNames); + stringProp->clearChangeType(); + stringProp->setReadOnlyFlag(false); + stringProp->setCacheRefreshBit(); + + return stringProp; + } + + return ossimImageSourceFilter::getProperty(name); +} + +void ossimEdgeFilter::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + ossimImageSourceFilter::getPropertyNames(propertyNames); + + propertyNames.push_back("Edge type"); +} + + +void ossimEdgeFilter::adjustRequestRect(ossimIrect& requestRect)const +{ + ossimString filterType = theFilterType; + filterType = filterType.downcase(); + ossimIrect rect = requestRect; + if(filterType.contains("sob")|| + filterType.contains("lap")|| + filterType.contains("pre")) + { + requestRect = ossimIrect(rect.ul().x - 1, + rect.ul().y - 1, + rect.lr().x + 1, + rect.lr().y + 1); + } + else if(filterType.contains("rob")) + { + requestRect = ossimIrect(rect.ul().x, + rect.ul().y, + rect.lr().x + 1, + rect.lr().y + 1); + } + else + { + requestRect = ossimIrect(rect.ul().x - 1, + rect.ul().y - 1, + rect.lr().x + 1, + rect.lr().y + 1); + } +} + +template <class T> +void ossimEdgeFilter::runFilter(T dummyVariable, + ossimRefPtr<ossimImageData> inputData) +{ + ossimString filterType = theFilterType; + filterType = filterType.downcase(); + + if(filterType.contains("sobel")) + { + runSobelFilter(dummyVariable, inputData); + } + else if(filterType.contains("lap")) + { + runLaplacianFilter(dummyVariable, inputData); + } + else if(filterType.contains("pre")) + { + runPrewittFilter(dummyVariable, inputData); + } + else if(filterType.contains("rob")) + { + runRobertsFilter(dummyVariable, inputData); + } + else + { + theTile->makeBlank(); + } +} + +template <class T> +void ossimEdgeFilter::runSobelFilter(T dummyVariable, + ossimRefPtr<ossimImageData> inputData) +{ + ossim_uint32 bandIdx = 0; + ossim_uint32 numberOfBands = inputData->getNumberOfBands(); + double horizontalValue = 0.0; + double verticalValue = 0.0; + double value = 0.0; + // ossim_uint32 valueIdx = 0; + ossim_uint32 x = 0; + ossim_uint32 y = 0; + ossim_uint32 width = theTile->getWidth(); + ossim_uint32 height = theTile->getHeight(); + ossim_int32 rowIncrement = inputData->getWidth(); + ossim_int32 rowIncrement2 = 2*inputData->getWidth(); + + for(bandIdx = 0; bandIdx < numberOfBands; ++bandIdx) + { + T* inputBuf = static_cast<T*>(inputData->getBuf(bandIdx)); + T* outputBuf = static_cast<T*>(theTile->getBuf(bandIdx)); + T np = static_cast<T>(theTile->getNullPix(bandIdx)); + T minP = static_cast<T>(theTile->getMinPix(bandIdx)); + T maxP = static_cast<T>(theTile->getMaxPix(bandIdx)); + + if(inputBuf&&outputBuf) + { + for(y = 0; y < height; ++y) + { + for(x = 0; x < width; ++x) + { + if( (*(inputBuf + rowIncrement + 1) != np)) + { + horizontalValue = ((double)inputBuf[0] - (double)inputBuf[rowIncrement2]) + + ((double)(inputBuf[1]*2.0) - (double)( inputBuf[rowIncrement2+1]*2.0)) + + ((double)(inputBuf[2]) - (double)(inputBuf[rowIncrement2+2])); + + verticalValue = ((double)(inputBuf[2]) + (double)inputBuf[rowIncrement+2]*2.0 + (double)inputBuf[rowIncrement2+2]) - + (double)(inputBuf[0] + 2.0*(double)inputBuf[rowIncrement] + (double)inputBuf[rowIncrement2]); + + value = sqrt(horizontalValue*horizontalValue + verticalValue*verticalValue); + + if((value == np) || + (value < minP)) + { + *outputBuf = (static_cast<T>(minP)); + } + else if(value > maxP) + { + *outputBuf = (static_cast<T>(maxP)); + } + else + { + *outputBuf = (static_cast<T>(value)); + } + + } + else + { + *outputBuf = np; + } + ++outputBuf; + ++inputBuf; + } + inputBuf+=2; + } + } + } + theTile->validate(); +} + +template <class T> +void ossimEdgeFilter::runPrewittFilter(T dummyVariable, + ossimRefPtr<ossimImageData> inputData) +{ + ossim_uint32 bandIdx = 0; + ossim_uint32 numberOfBands = inputData->getNumberOfBands(); + double horizontalValue = 0.0; + double verticalValue = 0.0; + double value = 0.0; + // ossim_uint32 valueIdx = 0; + ossim_uint32 x = 0; + ossim_uint32 y = 0; + ossim_uint32 width = theTile->getWidth(); + ossim_uint32 height = theTile->getHeight(); + ossim_int32 rowIncrement = inputData->getWidth(); + ossim_int32 rowIncrement2 = 2*inputData->getWidth(); + + for(bandIdx = 0; bandIdx < numberOfBands; ++bandIdx) + { + T* inputBuf = static_cast<T*>(inputData->getBuf(bandIdx)); + T* outputBuf = static_cast<T*>(theTile->getBuf(bandIdx)); + T np = static_cast<T>(theTile->getNullPix(bandIdx)); + T minP = static_cast<T>(theTile->getMinPix(bandIdx)); + T maxP = static_cast<T>(theTile->getMaxPix(bandIdx)); + + if(inputBuf&&outputBuf) + { + for(y = 0; y < height; ++y) + { + for(x = 0; x < width; ++x) + { + if( (*(inputBuf + rowIncrement + 1) != np)) + { + horizontalValue = ((double)inputBuf[0] - (double)inputBuf[rowIncrement2]) + + ((double)(inputBuf[1]) - (double)( inputBuf[rowIncrement2+1])) + + ((double)(inputBuf[2]) - (double)(inputBuf[rowIncrement2+2])); + + verticalValue = ((double)(inputBuf[2]) + (double)inputBuf[rowIncrement+2] + (double)inputBuf[rowIncrement2+2]) - + ((double)inputBuf[0] + (double)inputBuf[rowIncrement] + (double)inputBuf[rowIncrement2]); + + value = sqrt(horizontalValue*horizontalValue + verticalValue*verticalValue); + + if((value == np) || + (value < minP)) + { + *outputBuf = (static_cast<T>(minP)); + } + else if(value > maxP) + { + *outputBuf = (static_cast<T>(maxP)); + } + else + { + *outputBuf = (static_cast<T>(value)); + } + + } + else + { + *outputBuf = np; + } + ++outputBuf; + ++inputBuf; + } + inputBuf+=2; + } + } + } + theTile->validate(); +} + +template <class T> +void ossimEdgeFilter::runRobertsFilter(T dummyVariable, + ossimRefPtr<ossimImageData> inputData) +{ + ossim_uint32 bandIdx = 0; + ossim_uint32 numberOfBands = inputData->getNumberOfBands(); + double v1 = 0.0; + double v2 = 0.0; + double value = 0.0; + // ossim_uint32 valueIdx = 0; + ossim_uint32 x = 0; + ossim_uint32 y = 0; + ossim_uint32 width = theTile->getWidth(); + ossim_uint32 height = theTile->getHeight(); + ossim_int32 rowIncrement = inputData->getWidth(); + + for(bandIdx = 0; bandIdx < numberOfBands; ++bandIdx) + { + T* inputBuf = static_cast<T*>(inputData->getBuf(bandIdx)); + T* outputBuf = static_cast<T*>(theTile->getBuf(bandIdx)); + T np = static_cast<T>(theTile->getNullPix(bandIdx)); + T minP = static_cast<T>(theTile->getMinPix(bandIdx)); + T maxP = static_cast<T>(theTile->getMaxPix(bandIdx)); + + if(inputBuf&&outputBuf) + { + for(y = 0; y < height; ++y) + { + for(x = 0; x < width; ++x) + { + if( (*inputBuf) != np) + { + v1 = (double)inputBuf[0] - (double)(inputBuf[rowIncrement+1]); + + v2 = (double)inputBuf[1] - (double)inputBuf[rowIncrement]; + + value = sqrt(v1*v1 + v2*v2); + + if((value == np) || + (value < minP)) + { + *outputBuf = (static_cast<T>(minP)); + } + else if(value > maxP) + { + *outputBuf = (static_cast<T>(maxP)); + } + else + { + *outputBuf = (static_cast<T>(value)); + } + + } + else + { + *outputBuf = np; + } + ++outputBuf; + ++inputBuf; + } + ++inputBuf; + } + } + } + theTile->validate(); +} + +template <class T> +void ossimEdgeFilter::runLaplacianFilter(T dummyVariable, + ossimRefPtr<ossimImageData> inputData) +{ + ossim_uint32 bandIdx = 0; + ossim_uint32 numberOfBands = inputData->getNumberOfBands(); + // double horizontalValue = 0.0; + // double verticalValue = 0.0; + double value = 0.0; + // ossim_uint32 valueIdx = 0; + ossim_uint32 x = 0; + ossim_uint32 y = 0; + ossim_uint32 width = theTile->getWidth(); + ossim_uint32 height = theTile->getHeight(); + ossim_int32 rowIncrement = inputData->getWidth(); + ossim_int32 rowIncrement2 = 2*inputData->getWidth(); + + for(bandIdx = 0; bandIdx < numberOfBands; ++bandIdx) + { + T* inputBuf = static_cast<T*>(inputData->getBuf(bandIdx)); + T* outputBuf = static_cast<T*>(theTile->getBuf(bandIdx)); + T np = static_cast<T>(theTile->getNullPix(bandIdx)); + T minP = static_cast<T>(theTile->getMinPix(bandIdx)); + T maxP = static_cast<T>(theTile->getMaxPix(bandIdx)); + + if(inputBuf&&outputBuf) + { + for(y = 0; y < height; ++y) + { + for(x = 0; x < width; ++x) + { + if( (*(inputBuf + rowIncrement + 1) != np)) + { + + value = fabs(((double)inputBuf[rowIncrement + 1]*4.0) - + ((double)inputBuf[1] + (double)inputBuf[rowIncrement] + (double)inputBuf[rowIncrement + 2] + (double)inputBuf[rowIncrement2+1])); + + if((value == np) || + (value < minP)) + { + *outputBuf = (static_cast<T>(minP)); + } + else if(value > maxP) + { + *outputBuf = (static_cast<T>(maxP)); + } + else + { + *outputBuf = (static_cast<T>(value)); + } + + } + else + { + *outputBuf = np; + } + ++outputBuf; + ++inputBuf; + } + inputBuf+=2; + } + } + } + theTile->validate(); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEdgeFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEdgeFilter.h new file mode 100644 index 0000000000..7f422e6c0c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEdgeFilter.h @@ -0,0 +1,77 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimEdgeFilter.h,v 1.4 2005/08/17 19:18:12 gpotts Exp $ +#ifndef ossimEdgeFilter_HEADER +#define ossimEdgeFilter_HEADER +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +/** + * class ossimEdgeFilter + * + * This has default implementation for the certain filter types. For the + * different filter type please see method setFilterType. + * + * + */ +class ossimEdgeFilter : public ossimImageSourceFilter +{ +public: + ossimEdgeFilter(ossimObject* owner=NULL); + ossimEdgeFilter(ossimImageSource* inputSource); + ossimEdgeFilter(ossimObject* owner, + ossimImageSource* inputSource); + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect, + ossim_uint32 resLevel=0); + virtual void initialize(); + virtual void getFilterTypeNames(std::vector<ossimString>& filterNames)const; + virtual ossimString getFilterType()const; + /** + * The filter type can be one of the following strings. It is + * case insensitive for the compares. + * + * Sobel + * Laplacian + * Prewitt + * + */ + virtual void setFilterType(const ossimString& filterType); + + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + +protected: + ossimRefPtr<ossimImageData> theTile; + ossimString theFilterType; + + void adjustRequestRect(ossimIrect& requestRect)const; + + template <class T> + void runFilter(T dummyVariable, + ossimRefPtr<ossimImageData> inputData); + template <class T> + void runSobelFilter(T dummyVariable, + ossimRefPtr<ossimImageData> inputData); + template <class T> + void runPrewittFilter(T dummyVariable, + ossimRefPtr<ossimImageData> inputData); + template <class T> + void runLaplacianFilter(T dummyVariable, + ossimRefPtr<ossimImageData> inputData); + template <class T> + void runRobertsFilter(T dummyVariable, + ossimRefPtr<ossimImageData> inputData); + +TYPE_DATA +}; + + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEquationCombiner.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEquationCombiner.cpp new file mode 100644 index 0000000000..9955b7187d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEquationCombiner.cpp @@ -0,0 +1,3555 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimEquationCombiner.cpp,v 1.47 2005/07/01 13:32:24 dburken Exp $ + +#include <sstream> +using namespace std; + +#include <imaging/tile_sources/ossimEquationCombiner.h> +#include <imaging/tile_sources/ossimCastTileSourceFilter.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <imaging/tile_sources/ossimConvolutionSource.h> +#include <imaging/tile_sources/ossimSubImageTileSource.h> +#include <base/property/ossimStringProperty.h> +#include <matrix/newmatio.h> +#include <base/misc/lookup_tables/ossimScalarTypeLut.h> +#include <base/context/ossimNotifyContext.h> + +RTTI_DEF1(ossimEquationCombiner, "ossimEquationCombiner", ossimImageCombiner); + +static const char* EQUATION_KW = "equation"; + + +class ossimBinaryOpAdd : public ossimEquationCombiner::ossimBinaryOp +{ +public: + virtual double apply(double v1, double v2)const + { + return v1 + v2; + } +}; + +class ossimBinaryOpAnd : public ossimEquationCombiner::ossimBinaryOp +{ +public: + virtual double apply(double v1, double v2)const + { + return (double)(((ossim_uint32)v1) & ((ossim_uint32)v2)); + } +}; + +class ossimBinaryOpOr : public ossimEquationCombiner::ossimBinaryOp +{ +public: + virtual double apply(double v1, double v2)const + { + return (double)(((ossim_uint32)v1) | ((ossim_uint32)v2)); + } +}; + +class ossimBinaryOpXor : public ossimEquationCombiner::ossimBinaryOp +{ +public: + virtual double apply(double v1, double v2)const + { + return (double)(((ossim_uint32)v1) ^ ((ossim_uint32)v2)); + } +}; + +class ossimBinaryOpSub : public ossimEquationCombiner::ossimBinaryOp +{ +public: + virtual double apply(double v1, double v2)const + { + return v1 - v2; + } +}; + +class ossimBinaryOpMax : public ossimEquationCombiner::ossimBinaryOp +{ +public: + virtual double apply(double v1, double v2)const + { + return std::max(v1, v2); + } +}; + +class ossimBinaryOpMin : public ossimEquationCombiner::ossimBinaryOp +{ +public: + virtual double apply(double v1, double v2)const + { + return std::min(v1, v2); + } +}; + +class ossimBinaryOpMul : public ossimEquationCombiner::ossimBinaryOp +{ +public: + virtual double apply(double v1, double v2)const + { + return v1 * v2; + } +}; + +class ossimBinaryOpDiv : public ossimEquationCombiner::ossimBinaryOp +{ +public: + virtual double apply(double v1, double v2)const + { + if(fabs(v2)>FLT_EPSILON) + return v1 / v2; + + return 1.0/FLT_EPSILON; + } +}; + +class ossimBinaryOpMod : public ossimEquationCombiner::ossimBinaryOp +{ +public: + virtual double apply(double v1, double v2)const + { + if(fabs(v2)>FLT_EPSILON) + return fmod(v1,v2); + + return 1.0/FLT_EPSILON; + } +}; + +class ossimBinaryOpPow : public ossimEquationCombiner::ossimBinaryOp +{ +public: + virtual double apply(double v1, double v2)const + { + return pow(v1, v2); + } +}; +// boolean operators +class ossimBinaryOpEqual : public ossimEquationCombiner::ossimBinaryOp +{ +public: + virtual double apply(double v1, double v2)const + { + return (v1==v2)?1.0:0.0; + } +}; +class ossimBinaryOpGreater : public ossimEquationCombiner::ossimBinaryOp +{ +public: + virtual double apply(double v1, double v2)const + { + return (v1>v2)?1.0:0.0; + } +}; +class ossimBinaryOpGreaterOrEqual : public ossimEquationCombiner::ossimBinaryOp +{ +public: + virtual double apply(double v1, double v2)const + { + return (v1>=v2)?1.0:0.0; + } +}; +class ossimBinaryOpLess : public ossimEquationCombiner::ossimBinaryOp +{ +public: + virtual double apply(double v1, double v2)const + { + return (v1<v2)?1.0:0.0; + } +}; +class ossimBinaryOpLessOrEqual : public ossimEquationCombiner::ossimBinaryOp +{ +public: + virtual double apply(double v1, double v2)const + { + return (v1<=v2)?1.0:0.0; + } +}; +class ossimBinaryOpDifferent : public ossimEquationCombiner::ossimBinaryOp +{ +public: + virtual double apply(double v1, double v2)const + { + return (v1!=v2)?1.0:0.0; + } +}; +class ossimUnaryOpNot : public ossimEquationCombiner::ossimUnaryOp +{ +public: + virtual double apply(double v)const + { + return 1-v; + } +}; + +class ossimUnaryOpAbs : public ossimEquationCombiner::ossimUnaryOp +{ +public: + virtual double apply(double v)const + { + return fabs(v); + } +}; + +class ossimUnaryOpOnesComplement : public ossimEquationCombiner::ossimUnaryOp +{ +public: + virtual double apply(double v)const + { + return (double)((ossim_uint8)~((ossim_uint8)v)); + } +}; + +class ossimUnaryOpLog : public ossimEquationCombiner::ossimUnaryOp +{ +public: + virtual double apply(double v)const + { + return log(v); + } +}; + +class ossimUnaryOpLog10 : public ossimEquationCombiner::ossimUnaryOp +{ +public: + virtual double apply(double v)const + { + return log10(v); + } +}; + +class ossimUnaryOpNeg : public ossimEquationCombiner::ossimUnaryOp +{ +public: + virtual double apply(double v)const + { + return -v; + } +}; + +class ossimUnaryOpSqrt : public ossimEquationCombiner::ossimUnaryOp +{ +public: + virtual double apply(double v)const + { + if(v >= 0) + { + return sqrt(v); + } + + return -1; + } +}; + +class ossimUnaryOpExp : public ossimEquationCombiner::ossimUnaryOp +{ +public: + virtual double apply(double v)const + { + return exp(v); + } +}; + +class ossimUnaryOpSin : public ossimEquationCombiner::ossimUnaryOp +{ +public: + virtual double apply(double v)const + { + return sin(v); + } +}; + +class ossimUnaryOpSind : public ossimEquationCombiner::ossimUnaryOp +{ +public: + virtual double apply(double v)const + { + return sin(v*M_PI/180.0); + } +}; + +class ossimUnaryOpASin : public ossimEquationCombiner::ossimUnaryOp +{ +public: + virtual double apply(double v)const + { + if(v > 1) v = 1; + if(v < -1) v = -1; + return asin(v); + } +}; + +class ossimUnaryOpASind : public ossimEquationCombiner::ossimUnaryOp +{ +public: + virtual double apply(double v)const + { + if(v > 1) v = 1; + if(v < -1) v = -1; + return (180/M_PI)*asin(v); + } +}; + +class ossimUnaryOpACos : public ossimEquationCombiner::ossimUnaryOp +{ +public: + virtual double apply(double v)const + { + if(v > 1) v = 1; + if(v < -1) v = -1; + return acos(v); + } +}; + +class ossimUnaryOpACosd : public ossimEquationCombiner::ossimUnaryOp +{ +public: + virtual double apply(double v)const + { + if(v > 1) v = 1; + if(v < -1) v = -1; + return (180/M_PI)*acos(v); + } +}; + +class ossimUnaryOpCos : public ossimEquationCombiner::ossimUnaryOp +{ +public: + virtual double apply(double v)const + { + return cos(v); + } +}; + +class ossimUnaryOpCosd : public ossimEquationCombiner::ossimUnaryOp +{ +public: + virtual double apply(double v)const + { + return cos(v*M_PI/180.0); + } +}; + +class ossimUnaryOpTan : public ossimEquationCombiner::ossimUnaryOp +{ +public: + virtual double apply(double v)const + { + return tan(v); + } +}; + +class ossimUnaryOpTand : public ossimEquationCombiner::ossimUnaryOp +{ +public: + virtual double apply(double v)const + { + return tan(v*M_PI/180.0); + } +}; + +class ossimUnaryOpATan : public ossimEquationCombiner::ossimUnaryOp +{ +public: + virtual double apply(double v)const + { + return atan(v); + } +}; + +class ossimUnaryOpATand : public ossimEquationCombiner::ossimUnaryOp +{ +public: + virtual double apply(double v)const + { + return (180/M_PI)*atan(v); + } +}; + + +ossimEquationCombiner::ossimEquationCombiner() + :ossimImageCombiner(), + theOutputScalarType(OSSIM_FLOAT), + theEquation(""), + theLexer(NULL), + theTile(NULL), + theCastFilter(NULL), + theCastOutputFilter(NULL) +{ + theLexer = new ossimEquTokenizer; + theCastFilter = new ossimCastTileSourceFilter; + theCastFilter->setOutputScalarType(OSSIM_FLOAT); +} + +ossimEquationCombiner::~ossimEquationCombiner() +{ + if(theLexer) + { + delete theLexer; + theLexer = NULL; + } + + if(theCastFilter) + { + delete theCastFilter; + theCastFilter = (ossimCastTileSourceFilter*)NULL; + } + + if(theCastOutputFilter) + { + delete theCastOutputFilter; + theCastOutputFilter = NULL; + } + // make sure they are cleared + clearStacks(); +} + +double ossimEquationCombiner::getNullPixelValue(ossim_uint32 band)const +{ + + if(theEquation == "") + { + if(getInput()) + { + ossimImageSourceInterface* inter = PTR_CAST(ossimImageSourceInterface, getInput()); + if(inter) + { + return inter->getNullPixelValue(band); + } + } + } + return ossimImageSource::getNullPixelValue(band); +} + +double ossimEquationCombiner::getMinPixelValue(ossim_uint32 band)const +{ + if(theEquation == "") + { + if(getInput()) + { + ossimImageSourceInterface* inter = PTR_CAST(ossimImageSourceInterface, getInput()); + if(inter) + { + return inter->getMinPixelValue(band); + } + } + } + return ossimImageSource::getMinPixelValue(band); +} + +double ossimEquationCombiner::getMaxPixelValue(ossim_uint32 band)const +{ + if(theEquation == "") + { + if(getInput()) + { + ossimImageSourceInterface* inter = PTR_CAST(ossimImageSourceInterface, getInput()); + if(inter) + { + return inter->getMaxPixelValue(band); + } + } + } + return ossimImageSource::getMaxPixelValue(band); +} + +ossimScalarType ossimEquationCombiner::getOutputScalarType() const +{ + + if(theEquation == "") + { + if(getInput()) + { + ossimImageSourceInterface* inter = PTR_CAST(ossimImageSourceInterface, getInput()); + if(inter) + { + return inter->getOutputScalarType(); + } + } + } + + return theOutputScalarType; +} + + +ossimRefPtr<ossimImageData> ossimEquationCombiner::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if(!theTile) + { + initialize(); + } + long w = tileRect.width(); + long h = tileRect.height(); + long tw = theTile->getWidth(); + long th = theTile->getHeight(); + + if(theEquation != "") + { + theTile->setImageRectangle(tileRect); + + if(w*h != tw*th) + { + theTile->initialize(); + } + else + { + theTile->makeBlank(); + } + theCurrentResLevel = resLevel; + + ossimRefPtr<ossimImageData> outputTile = parseEquation(); + + if(theCastOutputFilter) + { + outputTile = theCastOutputFilter->applyCast(outputTile); + } + + return outputTile; + } + else + { + if(getInput()) + { + ossimImageSourceInterface* inter = + PTR_CAST(ossimImageSourceInterface, getInput()); + if(inter) + { + return inter->getTile(tileRect, resLevel); + } + } + } + + return ossimRefPtr<ossimImageData>(); +} + +void ossimEquationCombiner::setOutputScalarType(ossimScalarType scalarType) +{ + if(theOutputScalarType != scalarType) + { + theOutputScalarType = scalarType; + + if(theOutputScalarType == OSSIM_SCALAR_UNKNOWN) + { + theOutputScalarType = OSSIM_FLOAT; + } + if(theCastOutputFilter) + { + delete theCastOutputFilter; + theCastOutputFilter = NULL; + } + + if(theOutputScalarType != OSSIM_FLOAT) + { + theCastOutputFilter = new ossimCastTileSourceFilter; + theCastOutputFilter->setOutputScalarType(theOutputScalarType); + theCastOutputFilter->connectMyInputTo(0, this); + theCastOutputFilter->initialize(); + } + } +} + +void ossimEquationCombiner::setProperty(ossimRefPtr<ossimProperty> property) +{ + if(!property) return; + + if(property->getName() == "Equation") + { + theEquation = property->valueToString(); + } + else if(property->getName() == "Output scalar type") + { + setOutputScalarType(ossimScalarTypeLut::instance()-> + getScalarTypeFromString(property->valueToString())); + } + else + { + ossimImageCombiner::setProperty(property); + } +} + +ossimRefPtr<ossimProperty> ossimEquationCombiner::getProperty(const ossimString& name)const +{ + if(name == "Equation") + { + ossimStringProperty* stringProp = new ossimStringProperty("Equation", + theEquation, + false); + stringProp->clearChangeType(); + stringProp->setReadOnlyFlag(false); + stringProp->setCacheRefreshBit(); + + return stringProp; + } + else if(name == "Output scalar type") + { + ossimScalarTypeLut* sl = ossimScalarTypeLut::instance(); + + std::vector<ossimString> scalarNames; + + ossim_int32 tableSize = (ossim_int32)sl->getTableSize(); + ossim_int32 idx; + + for(idx = 0; idx < tableSize; ++idx) + { + scalarNames.push_back(sl->getEntryString(idx)); + } + ossimStringProperty* stringProp = new ossimStringProperty("Output scalar type", + sl->getEntryString((ossim_int32)theOutputScalarType), + false, + scalarNames); + stringProp->clearChangeType(); + stringProp->setReadOnlyFlag(false); + stringProp->setCacheRefreshBit(); + + return stringProp; + + } + + return ossimImageCombiner::getProperty(name); +} + +void ossimEquationCombiner::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + ossimImageCombiner::getPropertyNames(propertyNames); + propertyNames.push_back("Equation"); + propertyNames.push_back("Output scalar type"); +} + + +void ossimEquationCombiner::initialize() +{ + ossimImageCombiner::initialize(); + + theTile = ossimImageDataFactory::instance()->create(this, OSSIM_FLOAT, getNumberOfOutputBands(), getTileWidth(), getTileHeight()); + theTile->initialize(); + if(theCastOutputFilter) + { + theCastOutputFilter->initialize(); + } +} + +void ossimEquationCombiner::assignValue() +{ + if(!theValueStack.empty()) + { + if(theValueStack.top().type == OSSIM_EQU_IMAGE_DATA_TYPE) + { + ossimImageData* topData = theValueStack.top().d.imageDataValue; + ossim_uint32 minBands = std::min(theTile->getNumberOfBands(), + topData->getNumberOfBands()); + ossim_uint32 maxBands = theTile->getNumberOfBands(); + ossim_uint32 band = 0; + ossim_uint32 offset = 0; + ossim_uint32 size = theTile->getWidth()*theTile->getHeight(); + + if(topData->getDataObjectStatus() == OSSIM_PARTIAL) + { + for(band = 0; band < minBands; ++band) + { + float* inBuf = (float*)topData->getBuf(band); + float* outBuf = (float*)theTile->getBuf(band); + float np = topData->getNullPix(band); + if(outBuf && inBuf) + { + for(offset = 0; offset < size; ++offset) + { + if(*inBuf != np) + { + *outBuf = *inBuf; + } + ++outBuf; + ++inBuf; + } + } + } + for(;band < maxBands; ++band) + { + float* inBuf = (float*)topData->getBuf(minBands-1); + float* outBuf = (float*)theTile->getBuf(band); + float np = topData->getNullPix(band); + + if(outBuf && inBuf) + { + for(offset = 0; offset < size; ++offset) + { + if(*inBuf != np) + { + *outBuf = *inBuf; + } + ++outBuf; + ++inBuf; + } + } + } + + } + else if(topData->getDataObjectStatus() == OSSIM_FULL) + { + for(band = 0; band < minBands; ++band) + { + float* inBuf = (float*)theValueStack.top().d.imageDataValue->getBuf(band); + float* outBuf = (float*)theTile->getBuf(band); + if(outBuf && inBuf) + { + for(offset = 0; offset < size; ++offset) + { + *outBuf = *inBuf; + ++outBuf; + ++inBuf; + } + } + } + for(;band < maxBands; ++band) + { + float* inBuf = (float*)theValueStack.top().d.imageDataValue->getBuf(minBands-1); + float* outBuf = (float*)theTile->getBuf(band); + + if(outBuf && inBuf) + { + for(offset = 0; offset < size; ++offset) + { + *outBuf = *inBuf; + ++outBuf; + ++inBuf; + } + } + } + } + + // Delete the object indirectly through an ossimRefPtr. + ossimRefPtr<ossimImageData> id = theValueStack.top().d.imageDataValue; + id = NULL; + } + else + { + float* buf = static_cast<float*>(theTile->getBuf()); + ossim_uint32 size = theTile->getSize(); + float value = (float)theValueStack.top().d.doubleValue; + + for(ossim_uint32 offset = 0; offset < size; ++offset) + { + *buf = value; + ++buf; + } + } + + theValueStack.pop(); + } +} + +void ossimEquationCombiner::clearStacks() +{ + + while(!theValueStack.empty()) + { + if(theValueStack.top().type == OSSIM_EQU_IMAGE_DATA_TYPE) + { + // Delete the object indirectly through an ossimRefPtr. + ossimRefPtr<ossimImageData> id = theValueStack.top().d.imageDataValue; + id = NULL; + } + + theValueStack.pop(); + } +} + +void ossimEquationCombiner::clearArgList(vector<ossimEquValue>& argList) +{ + for(ossim_uint32 i = 0; i < argList.size(); ++i) + { + if(argList[i].type == OSSIM_EQU_IMAGE_DATA_TYPE) + { + if(argList[i].d.imageDataValue) + { + // Delete the object indirectly through an ossimRefPtr. + ossimRefPtr<ossimImageData> id = argList[i].d.imageDataValue; + id = NULL; + argList[i].d.imageDataValue = (ossimImageData*)NULL; + } + } + } + argList.clear(); +} + +void ossimEquationCombiner::deleteArgList(vector<ossimEquValue>& args) +{ + int i = 0; + + for(i = 0; i < (int)args.size(); ++i) + { + if(args[i].type == OSSIM_EQU_IMAGE_DATA_TYPE) + { + if(args[i].d.imageDataValue) + { + // Delete the object indirectly through an ossimRefPtr. + ossimRefPtr<ossimImageData> id = args[i].d.imageDataValue; + id = NULL; + args[i].d.imageDataValue = NULL; + } + } + } + + args.clear(); +} + +bool ossimEquationCombiner::parseArgList(vector<ossimEquValue>& args, + bool popValueStack) +{ + bool result = true; + + if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN) + { + theCurrentId = theLexer->yylex(); + do + { + if(parseExpression()) + { + if(!theValueStack.empty()) + { + args.push_back(theValueStack.top()); + if(popValueStack) + { + theValueStack.pop(); + } + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "The expression at arg " << (args.size()+1) + << " is empty" << endl; + + result = false; + } + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + <<"Unable to parse expression" << endl; + result = false; + } + + if(theCurrentId == OSSIM_EQU_TOKEN_COMMA) + { + theCurrentId = theLexer->yylex(); + } + else if(theCurrentId != OSSIM_EQU_TOKEN_RIGHT_PAREN) + { + ossimNotify(ossimNotifyLevel_WARN) + <<"Missing comma in argument list" << endl; + result = false; + } + + }while(result&&(theCurrentId != OSSIM_EQU_TOKEN_RIGHT_PAREN)); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "Starting left parenthesis missing from arg list" << endl; + result = false; + } + + if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN) + { + theCurrentId = theLexer->yylex(); // skip past right parenthesis + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + <<"No matching right parenthesis for arg list" << endl; + result = false; + } + + if(!result && popValueStack) + { + clearArgList(args); + } + return result; +} + +bool ossimEquationCombiner::parseAssignBand() +{ + bool result = true; + + vector<ossimEquValue> argList; + + if(parseArgList(argList)) + { + if((argList.size() == 3) || + (argList.size() == 4)) + { + ossimEquValue v3 = argList[2]; + ossimEquValue v2 = argList[1]; + ossimEquValue v1 = argList[0]; + + if(argList.size() == 3) + { + if((v1.type == OSSIM_EQU_IMAGE_DATA_TYPE) && + (v2.type == OSSIM_EQU_DOUBLE_TYPE)) + { + ossimImageData *data = (ossimImageData*)v1.d.imageDataValue->dup(); + ossimEquValue v; + + if(v3.type == OSSIM_EQU_IMAGE_DATA_TYPE) + { + if(data->getBuf()&& + v3.d.imageDataValue->getBuf()) + { + if((ossim_uint32)(v2.d.doubleValue) < data->getNumberOfBands()) + { + data->assignBand(v3.d.imageDataValue, + 0, + (ossim_uint32)v2.d.doubleValue); + + } + } + } + else + { + if(data->getBuf()&& + (ossim_uint32)v2.d.doubleValue < data->getNumberOfBands()) + { + ossim_uint32 upper = data->getWidth()*data->getHeight(); + float* buf = (float*)data->getBuf((ossim_uint32)v2.d.doubleValue); + float value = v3.d.doubleValue; + if(buf) + { + for(ossim_uint32 i = 0; i < upper; ++i) + { + *buf = value; + ++buf; + } + } + else + { + result = false; + } + } + } + if(result) + { + data->validate(); + v.type = OSSIM_EQU_IMAGE_DATA_TYPE; + v.d.imageDataValue = data; + theValueStack.push(v); + } + } + else + { + result = false; + } + } + else + { + ossimEquValue v4 = argList[3]; + if((v1.type == OSSIM_EQU_IMAGE_DATA_TYPE) && + (v2.type == OSSIM_EQU_DOUBLE_TYPE)&& + (v3.type == OSSIM_EQU_IMAGE_DATA_TYPE)&& + (v4.type == OSSIM_EQU_DOUBLE_TYPE)) + { + ossimImageData *data = (ossimImageData*)v1.d.imageDataValue->dup(); + ossimEquValue v; + v.type = OSSIM_EQU_IMAGE_DATA_TYPE; + v.d.imageDataValue = data; + if(data->getBuf()&&v3.d.imageDataValue->getBuf()) + { + + ossim_uint32 index1 = (ossim_uint32)v4.d.doubleValue; + ossim_uint32 index2 = (ossim_uint32)v2.d.doubleValue; + + if((index1 > data->getNumberOfBands()) || + (index1 > v3.d.imageDataValue->getNumberOfBands())) + { + result = false; + } + else + { + data->assignBand(v3.d.imageDataValue, + index1, + index2); + data->validate(); + } + + } + + theValueStack.push(v); + } + } + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "Invalid number of arguments to assign_band" << endl; + result = false; + } + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "unable to parse arguments for assign band" << endl; + result = false; + } + + clearArgList(argList); + + return result; +} + +bool ossimEquationCombiner::parseStdFuncs() +{ + bool result = true; + + switch(theCurrentId) + { + case OSSIM_EQU_TOKEN_ASSIGN_BAND: + { + theCurrentId = theLexer->yylex(); + if(!parseAssignBand()) + { + result = false; + } + + break; + } + case OSSIM_EQU_TOKEN_CONV: + { + theCurrentId = theLexer->yylex(); + vector<ossimEquValue> args; + if(parseArgList(args)) + { + ossimImageData* resultImage = (ossimImageData*)NULL; + if(applyConvolution(resultImage, + args)) + { + if(resultImage) + { + ossimEquValue v; + v.type = OSSIM_EQU_IMAGE_DATA_TYPE; + v.d.imageDataValue = resultImage; + + theValueStack.push(v); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "function conv error: resulting image is NULL" << endl; + result = false; + } + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "Unable to apply convolution" << endl; + result = false; + } + } + else + { + result = false; + } + + break; + } + case OSSIM_EQU_TOKEN_CLAMP: + { + theCurrentId = theLexer->yylex(); + vector<ossimEquValue> args; + if(parseArgList(args)) + { + ossimImageData* resultImage = (ossimImageData*)NULL; + if(applyClamp(resultImage, + args)) + { + if(resultImage) + { + ossimEquValue v; + v.type = OSSIM_EQU_IMAGE_DATA_TYPE; + v.d.imageDataValue = resultImage; + + theValueStack.push(v); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "function clamp error: resulting image is NULL" << endl; + result = false; + } + + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "Unable to apply clamp" << endl; + result = false; + } + } + else + { + result = false; + } + + break; + } + case OSSIM_EQU_TOKEN_BAND: + { + // need to parse the following rule for blurr function + // + // band(image data, number) + theCurrentId = theLexer->yylex(); + + + vector<ossimEquValue> argList; + + if(parseArgList(argList)) + { + if(argList.size() == 2) + { + ossimEquValue v1 = argList[0]; + ossimEquValue v2 = argList[1]; + ossimImageData* tempData = NULL; + ossim_uint32 bandNumber = 0; + if(v1.type == OSSIM_EQU_IMAGE_DATA_TYPE) + { + tempData = v1.d.imageDataValue; + } + else + { + result = false; + } + if(v2.type == OSSIM_EQU_DOUBLE_TYPE) + { + bandNumber = (ossim_uint32)(v2.d.doubleValue); + } + else + { + result = false; + } + if(bandNumber > tempData->getNumberOfBands()) + { + result = false; + } + if(result) + { + ossimImageData* data = new ossimImageData(this, + OSSIM_FLOAT, + 1); + data->setWidthHeight(tempData->getWidth(), + tempData->getHeight()); + data->setOrigin(tempData->getOrigin()); + data->setNullPix(tempData->getNullPix(bandNumber), + 0); + data->setMinPix(tempData->getMinPix(bandNumber), + 0); + data->setMaxPix(tempData->getMaxPix(bandNumber), + 0); + data->initialize(); + + if((tempData->getBuf())&& + (bandNumber < tempData->getNumberOfBands())) + { + data->assignBand(tempData, + bandNumber, + 0); + data->validate(); + } + ossimEquValue v; + v.type = OSSIM_EQU_IMAGE_DATA_TYPE; + v.d.imageDataValue = data; + theValueStack.push(v); + } + + if(tempData) + { + // Delete the object indirectly through an ossimRefPtr. + ossimRefPtr<ossimImageData> id = tempData; + tempData = NULL; + } + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "Invalid number of args in function band" << endl; + + result = false; + } + } + else + { + result = false; + } + + break; + } + case OSSIM_EQU_TOKEN_BLURR: + { + theCurrentId = theLexer->yylex(); + vector<ossimEquValue> args; + if(parseArgList(args)) + { + ossimImageData* resultImage = (ossimImageData*)NULL; + if(applyBlurr(resultImage, + args)) + { + if(resultImage) + { + ossimEquValue v; + v.type = OSSIM_EQU_IMAGE_DATA_TYPE; + v.d.imageDataValue = resultImage; + + theValueStack.push(v); + } + else + { + result = false; + } + } + else + { + result = false; + } + } + else + { + result = false; + } + + break; + } + case OSSIM_EQU_TOKEN_SHIFT: + { + theCurrentId = theLexer->yylex(); + vector<ossimEquValue> args; + if(parseArgList(args)) + { + ossimImageData* resultImage = (ossimImageData*)NULL; + if(applyShift(resultImage, + args)) + { + if(resultImage) + { + ossimEquValue v; + v.type = OSSIM_EQU_IMAGE_DATA_TYPE; + v.d.imageDataValue = resultImage; + + theValueStack.push(v); + } + else + { + result = false; + } + } + else + { + result = false; + } + } + else + { + result = false; + } + + break; + } + case OSSIM_EQU_TOKEN_MAX: + case OSSIM_EQU_TOKEN_MIN: + { + ossimBinaryOp* op = NULL; + if(theCurrentId == OSSIM_EQU_TOKEN_MIN) op = new ossimBinaryOpMin; + else op = new ossimBinaryOpMax; + + int argCount = 0; + theCurrentId = theLexer->yylex(); + if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN) + { + theCurrentId = theLexer->yylex(); + bool done = false; + while(!done) + { + if(parseExpression()) + { + + ++argCount; + if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN) + { + theCurrentId = theLexer->yylex(); + + done = true; + } + else if(theCurrentId == OSSIM_EQU_TOKEN_COMMA) + { + theCurrentId = theLexer->yylex(); + } + else + { + result = false; + done = true; + } + } + else + { + done = true; + result = false; + } + } + if((argCount > 1)&&result) + { + result = true; + + ossimEquValue v; + ossimEquValue v1; + ossimEquValue v2; + + v2 = theValueStack.top(); + theValueStack.pop(); + v1 = theValueStack.top(); + theValueStack.pop(); + argCount -=2; + + do + { + if(applyOp(*op, + v, + v1, + v2)) + { + theValueStack.push(v); + } + else + { + result = false; + argCount = 0; + + } + --argCount; + + if((argCount>0)&&result) + { + v2 = theValueStack.top(); + theValueStack.pop(); + v1 = theValueStack.top(); + theValueStack.pop(); + } + + }while((argCount > 0)&&(result)); + } + else + { + result = false; + } + } + else + { + result = false; + } + if(op) + { + delete op; + op = NULL; + } + break; + } + case OSSIM_EQU_TOKEN_ABS: + { + theCurrentId = theLexer->yylex(); + if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN) + { + theCurrentId = theLexer->yylex(); + result = parseExpression(); + if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN) + { + if(theValueStack.size() > 0) + { + theCurrentId = theLexer->yylex(); + ossimEquValue v; + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimUnaryOpAbs(), + v, + v1); + + theValueStack.push(v); + } + else + { + result = false; + } + } + } + else + { + result = false; + } + break; + } + case OSSIM_EQU_TOKEN_SIN: + { + theCurrentId = theLexer->yylex(); + if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN) + { + theCurrentId = theLexer->yylex(); + result = parseExpression(); + if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN) + { + if(theValueStack.size() > 0) + { + theCurrentId = theLexer->yylex(); + ossimEquValue v; + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimUnaryOpSin(), + v, + v1); + + theValueStack.push(v); + } + else + { + result = false; + } + } + } + else + { + result = false; + } + break; + } + case OSSIM_EQU_TOKEN_SIND: + { + theCurrentId = theLexer->yylex(); + if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN) + { + theCurrentId = theLexer->yylex(); + result = parseExpression(); + if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN) + { + if(theValueStack.size() > 0) + { + theCurrentId = theLexer->yylex(); + ossimEquValue v; + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimUnaryOpSind(), + v, + v1); + + theValueStack.push(v); + } + else + { + result = false; + } + } + } + else + { + result = false; + } + break; + } + case OSSIM_EQU_TOKEN_ASIN: + { + theCurrentId = theLexer->yylex(); + if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN) + { + theCurrentId = theLexer->yylex(); + result = parseExpression(); + if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN) + { + if(theValueStack.size() > 0) + { + theCurrentId = theLexer->yylex(); + ossimEquValue v; + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimUnaryOpASin(), + v, + v1); + + theValueStack.push(v); + } + else + { + result = false; + } + } + } + else + { + result = false; + } + break; + } + case OSSIM_EQU_TOKEN_ASIND: + { + theCurrentId = theLexer->yylex(); + if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN) + { + theCurrentId = theLexer->yylex(); + result = parseExpression(); + if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN) + { + if(theValueStack.size() > 0) + { + theCurrentId = theLexer->yylex(); + ossimEquValue v; + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimUnaryOpASind(), + v, + v1); + + theValueStack.push(v); + } + else + { + result = false; + } + } + } + else + { + result = false; + } + break; + } + case OSSIM_EQU_TOKEN_COS: + { + theCurrentId = theLexer->yylex(); + if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN) + { + theCurrentId = theLexer->yylex(); + result = parseExpression(); + if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN) + { + if(theValueStack.size() > 0) + { + theCurrentId = theLexer->yylex(); + ossimEquValue v; + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimUnaryOpCos(), + v, + v1); + + theValueStack.push(v); + } + else + { + result = false; + } + } + } + else + { + result = false; + } + break; + } + case OSSIM_EQU_TOKEN_COSD: + { + theCurrentId = theLexer->yylex(); + if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN) + { + theCurrentId = theLexer->yylex(); + result = parseExpression(); + if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN) + { + if(theValueStack.size() > 0) + { + theCurrentId = theLexer->yylex(); + ossimEquValue v; + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimUnaryOpCosd(), + v, + v1); + + theValueStack.push(v); + } + else + { + result = false; + } + } + } + else + { + result = false; + } + break; + } + case OSSIM_EQU_TOKEN_ACOS: + { + theCurrentId = theLexer->yylex(); + if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN) + { + theCurrentId = theLexer->yylex(); + result = parseExpression(); + if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN) + { + if(theValueStack.size() > 0) + { + theCurrentId = theLexer->yylex(); + ossimEquValue v; + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimUnaryOpACos(), + v, + v1); + + theValueStack.push(v); + } + else + { + result = false; + } + } + } + else + { + result = false; + } + break; + } + case OSSIM_EQU_TOKEN_ACOSD: + { + theCurrentId = theLexer->yylex(); + if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN) + { + theCurrentId = theLexer->yylex(); + result = parseExpression(); + if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN) + { + if(theValueStack.size() > 0) + { + theCurrentId = theLexer->yylex(); + ossimEquValue v; + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimUnaryOpACosd(), + v, + v1); + + theValueStack.push(v); + } + else + { + result = false; + } + } + } + else + { + result = false; + } + break; + } + case OSSIM_EQU_TOKEN_TAN: + { + theCurrentId = theLexer->yylex(); + if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN) + { + theCurrentId = theLexer->yylex(); + result = parseExpression(); + if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN) + { + if(theValueStack.size() > 0) + { + theCurrentId = theLexer->yylex(); + ossimEquValue v; + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimUnaryOpTan(), + v, + v1); + + theValueStack.push(v); + } + else + { + result = false; + } + } + } + else + { + result = false; + } + break; + } + case OSSIM_EQU_TOKEN_TAND: + { + theCurrentId = theLexer->yylex(); + if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN) + { + theCurrentId = theLexer->yylex(); + result = parseExpression(); + if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN) + { + if(theValueStack.size() > 0) + { + theCurrentId = theLexer->yylex(); + ossimEquValue v; + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimUnaryOpTand(), + v, + v1); + + theValueStack.push(v); + } + else + { + result = false; + } + } + } + else + { + result = false; + } + break; + } + case OSSIM_EQU_TOKEN_ATAN: + { + theCurrentId = theLexer->yylex(); + if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN) + { + theCurrentId = theLexer->yylex(); + result = parseExpression(); + if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN) + { + if(theValueStack.size() > 0) + { + theCurrentId = theLexer->yylex(); + ossimEquValue v; + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimUnaryOpATan(), + v, + v1); + + theValueStack.push(v); + } + else + { + result = false; + } + } + } + else + { + result = false; + } + break; + } + case OSSIM_EQU_TOKEN_ATAND: + { + theCurrentId = theLexer->yylex(); + if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN) + { + theCurrentId = theLexer->yylex(); + result = parseExpression(); + if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN) + { + if(theValueStack.size() > 0) + { + theCurrentId = theLexer->yylex(); + ossimEquValue v; + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimUnaryOpATand(), + v, + v1); + + theValueStack.push(v); + } + else + { + result = false; + } + } + } + else + { + result = false; + } + break; + } + case OSSIM_EQU_TOKEN_LOG: + { + theCurrentId = theLexer->yylex(); + if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN) + { + theCurrentId = theLexer->yylex(); + result = parseExpression(); + if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN) + { + if(theValueStack.size() > 0) + { + theCurrentId = theLexer->yylex(); + ossimEquValue v; + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimUnaryOpLog(), + v, + v1); + + theValueStack.push(v); + } + else + { + result = false; + } + } + } + else + { + result = false; + } + break; + } + case OSSIM_EQU_TOKEN_LOG10: + { + theCurrentId = theLexer->yylex(); + if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN) + { + theCurrentId = theLexer->yylex(); + result = parseExpression(); + if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN) + { + if(theValueStack.size() > 0) + { + theCurrentId = theLexer->yylex(); + ossimEquValue v; + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimUnaryOpLog10(), + v, + v1); + + theValueStack.push(v); + } + else + { + result = false; + } + } + } + else + { + result = false; + } + break; + } + case OSSIM_EQU_TOKEN_SQRT: + { + theCurrentId = theLexer->yylex(); + if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN) + { + theCurrentId = theLexer->yylex(); + result = parseExpression(); + if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN) + { + if(theValueStack.size() > 0) + { + theCurrentId = theLexer->yylex(); + ossimEquValue v; + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimUnaryOpSqrt(), + v, + v1); + + theValueStack.push(v); + } + else + { + result = false; + } + } + } + else + { + result = false; + } + break; + } + case OSSIM_EQU_TOKEN_EXP: + { + theCurrentId = theLexer->yylex(); + if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN) + { + theCurrentId = theLexer->yylex(); + result = parseExpression(); + if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN) + { + if(theValueStack.size() > 0) + { + theCurrentId = theLexer->yylex(); + ossimEquValue v; + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimUnaryOpExp(), + v, + v1); + + theValueStack.push(v); + } + else + { + result = false; + } + } + } + else + { + result = false; + } + break; + } + default: + { + result = false; + } + } + + return result; +} + +bool ossimEquationCombiner::parseUnaryFactor() +{ + bool result = false; + + + if(theCurrentId == OSSIM_EQU_TOKEN_MINUS) + { + theCurrentId = theLexer->yylex(); + + if(parseFactor()) + { + if(theValueStack.size() > 0) + { + ossimEquValue v; + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimUnaryOpNeg(), + v, + v1); + + theValueStack.push(v); + } + else + { + result = false; + } + + result = true; + } + else + { + result = false; + } + } + else if(theCurrentId == OSSIM_EQU_TOKEN_TILDE) + { + theCurrentId = theLexer->yylex(); + + if(parseFactor()) + { + if(theValueStack.size() > 0) + { + ossimEquValue v; + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimUnaryOpOnesComplement(), + v, + v1); + + theValueStack.push(v); + } + else + { + result = false; + } + + result = true; + } + else + { + result = false; + } + } + return result; +} + +bool ossimEquationCombiner::parseFactor() +{ + bool result = false; + + switch(theCurrentId) + { + case OSSIM_EQU_TOKEN_CONSTANT: + { + ossimEquValue v; + + v.type = OSSIM_EQU_DOUBLE_TYPE; + v.d.doubleValue = atof(theLexer->YYText()); + theValueStack.push(v); + + theCurrentId = theLexer->yylex(); + + result = true; + break; + } + case OSSIM_EQU_TOKEN_PI: + { + ossimEquValue v; + + v.type = OSSIM_EQU_DOUBLE_TYPE; + v.d.doubleValue = M_PI; + theValueStack.push(v); + + theCurrentId = theLexer->yylex(); + + result = true; + break; + } + case OSSIM_EQU_TOKEN_IMAGE_VARIABLE: + { + theCurrentId = theLexer->yylex(); + if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_ARRAY_BRACKET) + { + theCurrentId = theLexer->yylex(); + if(parseExpression()) + { + if(!theValueStack.empty()) + { + if(theValueStack.top().type == OSSIM_EQU_DOUBLE_TYPE) + { + if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_ARRAY_BRACKET) + { + theCurrentId = theLexer->yylex(); + ossim_uint32 index = (ossim_uint32)theValueStack.top().d.doubleValue; + theValueStack.pop(); + ossimRefPtr<ossimImageData> data = getNewImageData(index); + result = true; + if(data.valid()) + { + ossimEquValue v; + v.type = OSSIM_EQU_IMAGE_DATA_TYPE; + v.d.imageDataValue = data.release(); + theValueStack.push(v); + + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + <<"Data is NULL for array operation" << endl; + } + result = true; + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "Mismatched Right array bracket" << endl; + } + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "Expression between array brackets is not a number" + << endl; + } + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "no expression within array brackets" << endl; + } + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "Unabel to parse expression"<<endl; + } + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + <<"Need left array brackets to access an input source"<<endl; + } + + break; + } + case OSSIM_EQU_TOKEN_LEFT_PAREN: + { + theCurrentId = theLexer->yylex(); + if(parseExpression()) + { + if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN) + { + result = true; + theCurrentId = theLexer->yylex(); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "Right parenthesis missing" << endl; + result = false; + } + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "Unable to parse expression within parenthesis" << endl; + result = false; + } + + break; + } + } + if(!result) result = parseUnaryFactor(); + + if(!result) result = parseStdFuncs(); + + return result; +} + +bool ossimEquationCombiner::parseRestOfTerm() +{ + //--- + // Parse the following rule: + // RestOfTerm: * Factor RestOfTerm | / Factor RestOfTerm | + // ^ Factor RestOfTerm + //--- + bool result = true; + + switch(theCurrentId) + { + case OSSIM_EQU_TOKEN_MULT: + { + theCurrentId = theLexer->yylex(); + if(parseFactor()) + { + if(theValueStack.size() > 1) + { + ossimEquValue v; + + ossimEquValue v2 = theValueStack.top(); + theValueStack.pop(); + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimBinaryOpMul(), + v, + v1, + v2); + + theValueStack.push(v); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "Multiplication requires two arguments" << endl; + result = false; + } + if(result) + { + result = parseRestOfTerm(); + } + } + else + { + result = false; + } + break; + } + case OSSIM_EQU_TOKEN_DIV: + { + theCurrentId = theLexer->yylex(); + if(parseFactor()) + { + if(theValueStack.size() > 1) + { + ossimEquValue v; + + ossimEquValue v2 = theValueStack.top(); + theValueStack.pop(); + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimBinaryOpDiv(), + v, + v1, + v2); + + theValueStack.push(v); + } + else + { + result = false; + } + if(result) + { + result = parseRestOfTerm(); + } + } + else + { + result = false; + } + + break; + } + case OSSIM_EQU_TOKEN_XOR: + { + theCurrentId = theLexer->yylex(); + if(parseFactor()) + { + if(theValueStack.size() > 1) + { + ossimEquValue v; + + ossimEquValue v2 = theValueStack.top(); + theValueStack.pop(); + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimBinaryOpXor(), + v, + v1, + v2); + + theValueStack.push(v); + } + else + { + result = false; + } + if(result) + { + result = parseRestOfTerm(); + } + } + else + { + result = false; + } + + break; + } + case OSSIM_EQU_TOKEN_AMPERSAND: + { + theCurrentId = theLexer->yylex(); + if(parseFactor()) + { + if(theValueStack.size() > 1) + { + ossimEquValue v; + + ossimEquValue v2 = theValueStack.top(); + theValueStack.pop(); + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimBinaryOpAnd(), + v, + v1, + v2); + + theValueStack.push(v); + } + else + { + result = false; + } + if(result) + { + result = parseRestOfTerm(); + } + } + else + { + result = false; + } + + break; + } + case OSSIM_EQU_TOKEN_OR_BAR: + { + theCurrentId = theLexer->yylex(); + if(parseFactor()) + { + if(theValueStack.size() > 1) + { + ossimEquValue v; + + ossimEquValue v2 = theValueStack.top(); + theValueStack.pop(); + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimBinaryOpOr(), + v, + v1, + v2); + + theValueStack.push(v); + } + else + { + result = false; + } + if(result) + { + result = parseRestOfTerm(); + } + } + else + { + result = false; + } + + break; + } + case OSSIM_EQU_TOKEN_MOD: + { + theCurrentId = theLexer->yylex(); + if(parseFactor()) + { + if(theValueStack.size() > 1) + { + ossimEquValue v; + + ossimEquValue v2 = theValueStack.top(); + theValueStack.pop(); + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimBinaryOpMod(), + v, + v1, + v2); + + theValueStack.push(v); + } + else + { + result = false; + } + if(result) + { + result = parseRestOfTerm(); + } + } + else + { + result = false; + } + + break; + } + case OSSIM_EQU_TOKEN_POWER: + { + theCurrentId = theLexer->yylex(); + if(parseFactor()) + { + if(theValueStack.size() > 1) + { + ossimEquValue v; + + ossimEquValue v2 = theValueStack.top(); + theValueStack.pop(); + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimBinaryOpPow(), + v, + v1, + v2); + + theValueStack.push(v); + } + else + { + result = false; + } + if(result) + { + result = parseRestOfTerm(); + } + } + else + { + result = false; + } + break; + } + case OSSIM_EQU_TOKEN_BEQUAL: + { + theCurrentId = theLexer->yylex(); + if(parseFactor()) + { + if(theValueStack.size() > 1) + { + ossimEquValue v; + + ossimEquValue v2 = theValueStack.top(); + theValueStack.pop(); + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimBinaryOpEqual(), + v, + v1, + v2); + + theValueStack.push(v); + } + else + { + result = false; + } + if(result) + { + result = parseRestOfTerm(); + } + } + else + { + result = false; + } + + break; + } + case OSSIM_EQU_TOKEN_BGREATER: + { + theCurrentId = theLexer->yylex(); + if(parseFactor()) + { + if(theValueStack.size() > 1) + { + ossimEquValue v; + + ossimEquValue v2 = theValueStack.top(); + theValueStack.pop(); + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimBinaryOpGreater(), + v, + v1, + v2); + + theValueStack.push(v); + } + else + { + result = false; + } + if(result) + { + result = parseRestOfTerm(); + } + } + else + { + result = false; + } + + break; + } + case OSSIM_EQU_TOKEN_BGREATEROREQUAL: + { + theCurrentId = theLexer->yylex(); + if(parseFactor()) + { + if(theValueStack.size() > 1) + { + ossimEquValue v; + + ossimEquValue v2 = theValueStack.top(); + theValueStack.pop(); + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimBinaryOpGreaterOrEqual(), + v, + v1, + v2); + + theValueStack.push(v); + } + else + { + result = false; + } + if(result) + { + result = parseRestOfTerm(); + } + } + else + { + result = false; + } + + break; + } + case OSSIM_EQU_TOKEN_BLESS: + { + theCurrentId = theLexer->yylex(); + if(parseFactor()) + { + if(theValueStack.size() > 1) + { + ossimEquValue v; + + ossimEquValue v2 = theValueStack.top(); + theValueStack.pop(); + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimBinaryOpLess(), + v, + v1, + v2); + + theValueStack.push(v); + } + else + { + result = false; + } + if(result) + { + result = parseRestOfTerm(); + } + } + else + { + result = false; + } + + break; + } + case OSSIM_EQU_TOKEN_BLESSOREQUAL: + { + theCurrentId = theLexer->yylex(); + if(parseFactor()) + { + if(theValueStack.size() > 1) + { + ossimEquValue v; + + ossimEquValue v2 = theValueStack.top(); + theValueStack.pop(); + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimBinaryOpLessOrEqual(), + v, + v1, + v2); + + theValueStack.push(v); + } + else + { + result = false; + } + if(result) + { + result = parseRestOfTerm(); + } + } + else + { + result = false; + } + + break; + } + case OSSIM_EQU_TOKEN_BDIFFERENT: + { + theCurrentId = theLexer->yylex(); + if(parseFactor()) + { + if(theValueStack.size() > 1) + { + ossimEquValue v; + + ossimEquValue v2 = theValueStack.top(); + theValueStack.pop(); + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimBinaryOpDifferent(), + v, + v1, + v2); + + theValueStack.push(v); + } + else + { + result = false; + } + if(result) + { + result = parseRestOfTerm(); + } + } + else + { + result = false; + } + + break; + } + } + + return result; +} + +bool ossimEquationCombiner::parseTerm() +{ + // parse the following rule: + // + // Term : Factor RestOfTerm + + bool result = false; + + result = parseFactor(); + + if(result) + { + result = parseRestOfTerm(); + } + + return result; +} + +bool ossimEquationCombiner::parseRestOfExp() +{ + // parse the following rule: + // RestOfExpression : + Term RestOfExpression | - Term RestOfExpression | epsilon + // + bool result = true; + + if(theCurrentId == OSSIM_EQU_TOKEN_PLUS) + { + theCurrentId = theLexer->yylex(); + if(parseTerm()) + { + + if(theValueStack.size() > 1) + { + ossimEquValue v; + + ossimEquValue v2 = theValueStack.top(); + theValueStack.pop(); + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + + applyOp(ossimBinaryOpAdd(), + v, + v1, + v2); + + theValueStack.push(v); + } + else + { + result = false; + } + if(result) + { + result = parseRestOfExp(); + } + } + else + { + result = false; + } + } + else if(theCurrentId == OSSIM_EQU_TOKEN_MINUS) + { + theCurrentId = theLexer->yylex(); + if(parseTerm()) + { + if(theValueStack.size() > 1) + { + ossimEquValue v; + + ossimEquValue v2 = theValueStack.top(); + theValueStack.pop(); + ossimEquValue v1 = theValueStack.top(); + theValueStack.pop(); + + applyOp(ossimBinaryOpSub(), + v, + v1, + v2); + + theValueStack.push(v); + } + else + { + result = false; + } + if(result) + { + result = parseRestOfExp(); + } + } + else + { + result = false; + } + } + + return result; +} + +ossimRefPtr<ossimImageData> ossimEquationCombiner::getImageData(ossim_uint32 index) +{ + ossimRefPtr<ossimImageData> result; + ossimConnectableObject* obj = getInput(index); + + if(obj) + { + theCastFilter->connectMyInputTo(0, obj); + result= (theCastFilter->getTile(theTile->getImageRectangle(), + theCurrentResLevel)); + + if(result.valid()) + { + result->setMinPix(theTile->getMinPix(), theTile->getNumberOfBands()); + result->setMaxPix(theTile->getMaxPix(), theTile->getNumberOfBands()); + } + } + + return result; +} + +ossimRefPtr<ossimImageData> ossimEquationCombiner::getNewImageData( + ossim_uint32 index) +{ + ossimRefPtr<ossimImageData> result = getImageData(index); + + if(result.valid()) + { + if(result->getBuf()) + { + result = (ossimImageData*)result->dup(); + } + } + + return result; +} + +bool ossimEquationCombiner::parseExpression() +{ + // parse the following rule: + // expression : Term ResOfExpression + // + + bool result = false; + + if(parseTerm()) + { + result = parseRestOfExp(); + } + + return result; +} + +ossimRefPtr<ossimImageData> ossimEquationCombiner::parseEquation() +{ + ostringstream s; + + s << theEquation; + + istringstream inS(s.str()); + theLexer->switch_streams(&inS, &ossimNotify(ossimNotifyLevel_WARN)); + + theCurrentId = theLexer->yylex(); + + while(theCurrentId) + { + if(!parseExpression()) + { + break; + } + } + + if(!theValueStack.empty()) + { + assignValue(); + theTile->validate(); + clearStacks(); + } + + return theTile; +} + +bool ossimEquationCombiner::applyClamp(ossimImageData* &result, + const vector<ossimEquValue>& argList) +{ + if(result) + { + // Delete the object indirectly through an ossimRefPtr. + ossimRefPtr<ossimImageData> id = result; + id = NULL; + result = (ossimImageData*) NULL; + } + if(argList.size() <3) + { + return false; + } + + if(argList[0].type == OSSIM_EQU_DOUBLE_TYPE) + { + return false; + } + else if( (argList[1].type == OSSIM_EQU_DOUBLE_TYPE)&& + (argList[2].type == OSSIM_EQU_DOUBLE_TYPE)) + { + result = argList[0].d.imageDataValue; + + if(argList[0].d.imageDataValue) + { + ossimDataObjectStatus status = result->getDataObjectStatus(); + if((status != OSSIM_NULL) && + (status != OSSIM_EMPTY)) + { + double minValue = argList[1].d.doubleValue; + double maxValue = argList[2].d.doubleValue; + + if(minValue > maxValue) + { + std::swap(minValue, maxValue); + } + + int band = 0; + int offset = 0; + + int upperBoundBand = result->getNumberOfBands(); + int offsetUpperBound = result->getWidth()*result->getHeight(); + + if(status == OSSIM_PARTIAL) + { + for(band = 0; band < upperBoundBand; ++band) + { + float np = static_cast<float>(result->getNullPix(band)); + float *buf = static_cast<float*>(result->getBuf(band)); + for(offset = 0; offset < offsetUpperBound; ++ offset) + { + if( *buf != np ) + { + if( (*buf) < minValue) *buf = minValue; + else if( (*buf) >maxValue) *buf = maxValue; + } + ++buf; + } + } + } + else + { + for(band = 0; band < upperBoundBand; ++band) + { + float *buf = static_cast<float*>(result->getBuf(band)); + for(offset = 0; offset < offsetUpperBound; ++ offset) + { + if( (*buf) < minValue) *buf = minValue; + else if( (*buf) >maxValue) *buf = maxValue; + ++buf; + } + } + } + } + } + + return true; + } + return false; +} + +bool ossimEquationCombiner::applyConvolution(ossimImageData* &result, + const vector<ossimEquValue>& argList) +{ + if(result) + { + // Delete the object indirectly through an ossimRefPtr. + ossimRefPtr<ossimImageData> id = result; + id = NULL; + result = (ossimImageData*) NULL; + } + if(argList.size() <4) return false; + + for(ossim_uint32 i = 0; i < argList.size(); ++i) + { + if(argList[i].type != OSSIM_EQU_DOUBLE_TYPE) + { + return false; + } + } + + ossim_uint32 index = (ossim_uint32)argList[0].d.doubleValue; + int rows = (int)argList[1].d.doubleValue; + int cols = (int)argList[2].d.doubleValue; + + if((rows*cols) != (int)(argList.size()-3)) + { + return false; + } + + NEWMAT::Matrix m(rows,cols); + + int count = 3; + for(int r = 0; r< rows;++r) + { + for(int c=0;c<cols;++c) + { + m[r][c] = argList[count].d.doubleValue; + ++count; + } + } + ossimConnectableObject* obj = getInput(index); + if(obj) + { + ossimConvolutionSource* conv = new ossimConvolutionSource(NULL, m); + + conv->connectMyInputTo(0, obj); + theCastFilter->connectMyInputTo(0, conv); + + ossimRefPtr<ossimImageData> tempData = + theCastFilter->getTile(theTile->getImageRectangle(), + theCurrentResLevel); + if(tempData.valid()) + { + result = (ossimImageData*)tempData->dup(); + } + else + { + result = (ossimImageData*)theTile->dup(); + } + + delete conv; + } + if(result) + { + return true; + } + + return false; +} + +bool ossimEquationCombiner::applyBlurr(ossimImageData* &result, + const vector<ossimEquValue>& argList) +{ + if(result) + { + // Delete the object indirectly through an ossimRefPtr. + ossimRefPtr<ossimImageData> id = result; + id = NULL; + result = (ossimImageData*) NULL; + } + if(argList.size() !=3) return false; + + for(ossim_uint32 i = 0; i < argList.size(); ++i) + { + if(argList[i].type != OSSIM_EQU_DOUBLE_TYPE) + { + return false; + } + } + + ossim_uint32 index = (ossim_uint32)argList[0].d.doubleValue; + int rows = (int)argList[1].d.doubleValue; + int cols = (int)argList[2].d.doubleValue; + + NEWMAT::Matrix m(rows, cols); + + m = 1.0/(rows*cols); + + ossimConnectableObject* obj = getInput(index); + if(obj) + { + ossimConvolutionSource* conv = new ossimConvolutionSource(NULL, + m); + + conv->connectMyInputTo(0, obj); + theCastFilter->connectMyInputTo(0, conv); + theCastFilter->initialize(); + + ossimRefPtr<ossimImageData> tempData = + theCastFilter->getTile(theTile->getImageRectangle(), + theCurrentResLevel); + if(tempData.valid()) + { + result = (ossimImageData*)tempData->dup(); + } + delete conv; + } + + if(result) + { + return true; + } + + return false; +} + +bool ossimEquationCombiner::applyShift(ossimImageData* &result, + const vector<ossimEquValue>& argList) +{ + if(result) + { + // Delete the object indirectly through an ossimRefPtr. + ossimRefPtr<ossimImageData> id = result; + id = NULL; + result = (ossimImageData*) NULL; + } + if(argList.size() !=3) return false; + + for(ossim_uint32 i = 0; i < argList.size(); ++i) + { + if(argList[i].type != OSSIM_EQU_DOUBLE_TYPE) + { + return false; + } + } + + ossim_uint32 index = (ossim_uint32)argList[0].d.doubleValue; + int x = (int)argList[1].d.doubleValue; + int y = (int)argList[2].d.doubleValue; + + ossimConnectableObject* obj = getInput(index); + if(obj) + { + ossimSubImageTileSource* shiftSource = + new ossimSubImageTileSource(NULL, ossimIpt(x, y)); + + shiftSource->connectMyInputTo(0, obj); + theCastFilter->connectMyInputTo(0, shiftSource); + + ossimRefPtr<ossimImageData> tempData = + theCastFilter->getTile(theTile->getImageRectangle(), + theCurrentResLevel); + if(tempData.valid()) + { + result = (ossimImageData*)tempData->dup(); + } + delete shiftSource; + } + + if(result) + { + return true; + } + + return false; +} + +bool ossimEquationCombiner::applyOp(const ossimBinaryOp& op, + ossimEquValue& result, + ossimEquValue& v1, + ossimEquValue& v2) +{ + bool returnValue = true; + + if(v1.type == OSSIM_EQU_DOUBLE_TYPE) + { + if(v2.type == OSSIM_EQU_DOUBLE_TYPE) + { + result.type = OSSIM_EQU_DOUBLE_TYPE; + result.d.doubleValue = op.apply(v1.d.doubleValue, v2.d.doubleValue); + } + else if(v2.type == OSSIM_EQU_IMAGE_DATA_TYPE) + { + returnValue = applyOp(op, + v1.d.doubleValue, + v2.d.imageDataValue); + + result.type = OSSIM_EQU_IMAGE_DATA_TYPE; + result.d.imageDataValue = v2.d.imageDataValue; + } + else + { + returnValue = false; + } + } + else if(v1.type == OSSIM_EQU_IMAGE_DATA_TYPE) + { + if(v2.type == OSSIM_EQU_DOUBLE_TYPE) + { + + returnValue = applyOp(op, + v1.d.imageDataValue, + v2.d.doubleValue); + + result.type = OSSIM_EQU_IMAGE_DATA_TYPE; + result.d.imageDataValue = v1.d.imageDataValue; + returnValue = true; + } + else if(v2.type == OSSIM_EQU_IMAGE_DATA_TYPE) + { + returnValue = applyOp(op, + v1.d.imageDataValue, + v2.d.imageDataValue); + result.type = OSSIM_EQU_IMAGE_DATA_TYPE; + result.d.imageDataValue = v1.d.imageDataValue; + + // Delete the object indirectly through an ossimRefPtr. + ossimRefPtr<ossimImageData> id = v2.d.imageDataValue; + id = NULL; + v2.d.imageDataValue = (ossimImageData*)NULL; + returnValue = true; + } + else + { + returnValue = false; + } + } + else + { + returnValue = false; + } + + return returnValue; +} + +bool ossimEquationCombiner::applyOp(const ossimBinaryOp& op, + ossimImageData* v1, + double v2) +{ + float* buf = static_cast<float*>(v1->getBuf()); + if(!buf) return true; + ossimDataObjectStatus status = v1->getDataObjectStatus(); + + if(status == OSSIM_EMPTY || status == OSSIM_NULL) + { + return true; + } + + if(status == OSSIM_FULL ) + { + ossim_uint32 size = v1->getSize(); + float value = (static_cast<float>(v2)); + + for(ossim_uint32 i = 0; i < size; ++i) + { + *buf = (float)op.apply(*buf, value); + ++buf; + } + } + else + { + ossim_uint32 sizePerBand = v1->getSizePerBand(); + ossim_uint32 numberOfBands = v1->getNumberOfBands(); + + if(numberOfBands) + { + for(ossim_uint32 band = 0; band < numberOfBands; ++band) + { + float* buf = static_cast<float*>(v1->getBuf(band)); + + if(buf) + { + float np = static_cast<float>(v1->getNullPix()[band]); + + for(ossim_uint32 offset = 0; offset < sizePerBand;++offset) + { + if(*buf != np) + { + *buf = (float)op.apply(*buf, v2); + } + ++buf; + } + } + } + } + } + return true; +} + +bool ossimEquationCombiner::applyOp(const ossimBinaryOp& op, + double v1, + ossimImageData* v2) +{ + float* buf = static_cast<float*>(v2->getBuf()); + if(!buf) return true; + ossimDataObjectStatus status = v2->getDataObjectStatus(); + + if(status == OSSIM_EMPTY || status == OSSIM_NULL) + { + return true; + } + + if(status == OSSIM_FULL ) + { + ossim_uint32 size = v2->getSize(); + float value = (static_cast<float>(v1)); + + for(ossim_uint32 i = 0; i < size; ++i) + { + *buf = (float)op.apply(value, *buf); + ++buf; + } + } + else + { + ossim_uint32 sizePerBand = v2->getSizePerBand(); + ossim_uint32 numberOfBands = v2->getNumberOfBands(); + + if(numberOfBands) + { + for(ossim_uint32 band = 0; band < numberOfBands; ++band) + { + float* buf = static_cast<float*>(v2->getBuf(band)); + + if(buf) + { + float np = static_cast<float>(v2->getNullPix()[band]); + + for(ossim_uint32 offset = 0; offset < sizePerBand; ++offset) + { + if(*buf != np) + { + *buf = (float)op.apply((float)v1, *buf); + } + ++buf; + } + } + } + } + } + + return true; +} + +bool ossimEquationCombiner::applyOp(const ossimBinaryOp& op, + ossimImageData* v1, + ossimImageData* v2) +{ + ossim_uint32 minNumberOfBands = std::min(v1->getNumberOfBands(), v2->getNumberOfBands()); + ossim_uint32 maxNumberOfBands = std::max(v1->getNumberOfBands(), v2->getNumberOfBands()); + + ossim_uint32 size = v1->getWidth()*v1->getHeight(); + ossimDataObjectStatus status1 = v1->getDataObjectStatus(); + ossimDataObjectStatus status2 = v2->getDataObjectStatus(); + + float** bandV1 = new float*[maxNumberOfBands]; + float** bandV2 = new float*[maxNumberOfBands]; + float* bandV1Np = new float[maxNumberOfBands]; + float* bandV2Np = new float[maxNumberOfBands]; + ossim_uint32 band = 0; + for(band = 0; band < minNumberOfBands; ++band) + { + bandV1[band] = (float*)v1->getBuf(band); + bandV2[band] = (float*)v2->getBuf(band); + bandV1Np[band] = (float)v1->getNullPix(band); + bandV2Np[band] = (float)v2->getNullPix(band); + } + if(v1->getNumberOfBands() < v2->getNumberOfBands()) + { + for(band = 0; band < maxNumberOfBands; ++band) + { + bandV1[band] = (float*)v1->getBuf(minNumberOfBands-1); + bandV2[band] = (float*)v2->getBuf(band); + bandV1Np[band] = (float)v1->getNullPix(minNumberOfBands-1); + bandV2Np[band] = (float)v2->getNullPix(band); + } + } + else if(v2->getNumberOfBands() < v1->getNumberOfBands()) + { + for(band = 0; band < maxNumberOfBands; ++band) + { + bandV1[band] = (float*)v1->getBuf(band); + bandV2[band] = (float*)v2->getBuf(minNumberOfBands-1); + bandV1Np[band] = (float)v1->getNullPix(band); + bandV2Np[band] = (float)v2->getNullPix(minNumberOfBands-1); + } + } + + if(status1 == OSSIM_EMPTY) + { + if(status2 == OSSIM_FULL) + { + for(band = 0; band < maxNumberOfBands; ++band) + { + float* buf1 = bandV1[band]; + float* buf2 = bandV2[band]; + + for(ossim_uint32 i = 0; i < size; ++i) + { + *buf1 = *buf2; + ++buf1; + ++buf2; + } + } + } + else if(status2 == OSSIM_PARTIAL) + { + for(band = 0; band < maxNumberOfBands; ++band) + { + float* buf1 = bandV1[band]; + float* buf2 = bandV2[band]; + float nullPix2 = bandV2Np[band]; + for(ossim_uint32 i = 0; i < size; ++i) + { + if(*buf2 != nullPix2) + { + *buf1 = *buf2; + } + ++buf1; + ++buf2; + } + } + } + v1->setDataObjectStatus(status2); + } + else if((status1 == OSSIM_FULL)&& + (status2 == OSSIM_FULL)) + { + for(band = 0; band < maxNumberOfBands; ++band) + { + float* buf1 = bandV1[band]; + float* buf2 = bandV2[band]; + + for(ossim_uint32 i = 0; i < size; ++i) + { + *buf1 = op.apply(*buf1, *buf2); + ++buf1; + ++buf2; + } + } + } + else if((status1 == OSSIM_FULL)&& + (status2 == OSSIM_PARTIAL)) + { + for(band = 0; band < maxNumberOfBands; ++band) + { + float* buf1 = bandV1[band]; + float* buf2 = bandV2[band]; + float nullPix2 = bandV2Np[band]; + for(ossim_uint32 i = 0; i < size; ++i) + { + if(*buf2 != nullPix2) + { + *buf1 = op.apply(*buf1, *buf2); + } + + ++buf1; + ++buf2; + } + } + } + else if((status1 == OSSIM_PARTIAL)&& + (status2 == OSSIM_FULL)) + { + for(band = 0; band < maxNumberOfBands; ++band) + { + float* buf1 = bandV1[band]; + float* buf2 = bandV2[band]; + float nullPix1 = bandV1Np[band]; + for(ossim_uint32 i = 0; i < size; ++i) + { + if(*buf1 != nullPix1) + { + *buf1 = op.apply(*buf1, *buf2); + } + + ++buf1; + ++buf2; + } + } + } + else if((status1 == OSSIM_PARTIAL)&& + (status2 == OSSIM_PARTIAL)) + { + for(band = 0; band < maxNumberOfBands; ++band) + { + float* buf1 = bandV1[band]; + float* buf2 = bandV2[band]; + float nullPix1 = bandV1Np[band]; + float nullPix2 = bandV2Np[band]; + for(ossim_uint32 i = 0; i < size; ++i) + { + if((*buf1 != nullPix1)&& + (*buf2 != nullPix2)) + { + *buf1 = op.apply(*buf1, *buf2); + } + + ++buf1; + ++buf2; + } + } + } + + delete [] bandV1; + delete [] bandV2; + delete [] bandV1Np; + delete [] bandV2Np; + + return true; +} + + +bool ossimEquationCombiner::applyOp(const ossimUnaryOp& op, + ossimEquValue& result, + ossimEquValue& v) +{ + bool returnValue = true; + + if(v.type == OSSIM_EQU_DOUBLE_TYPE) + { + result.type = OSSIM_EQU_DOUBLE_TYPE; + result.d.doubleValue = op.apply(v.d.doubleValue); + } + else if(v.type == OSSIM_EQU_IMAGE_DATA_TYPE) + { + returnValue = applyOp(op, + v.d.imageDataValue); + result.type = OSSIM_EQU_IMAGE_DATA_TYPE; + result.d.imageDataValue = v.d.imageDataValue; + returnValue = true; + } + else + { + returnValue = false; + } + + return returnValue; +} + +bool ossimEquationCombiner::applyOp(const ossimUnaryOp& op, + ossimImageData* v) +{ + float* buf = static_cast<float*>(v->getBuf()); + if(!buf) return true; + ossimDataObjectStatus status = v->getDataObjectStatus(); + + if(status == OSSIM_EMPTY || status == OSSIM_NULL) + { + return true; + } + + if(status == OSSIM_FULL ) + { + ossim_uint32 size = v->getSize(); + + for(ossim_uint32 i = 0; i < size; ++i) + { + *buf = (float)op.apply(*buf); + ++buf; + } + } + else + { + ossim_uint32 sizePerBand = v->getSizePerBand(); + ossim_uint32 numberOfBands = v->getNumberOfBands(); + + if(numberOfBands) + { + for(ossim_uint32 band = 0; band < numberOfBands; ++band) + { + float* buf = static_cast<float*>(v->getBuf(band)); + + if(buf) + { + float np = static_cast<float>(v->getNullPix()[band]); + + for(ossim_uint32 offset = 0; offset < sizePerBand;++offset) + { + if(*buf != np) + { + *buf = (float)op.apply(*buf); + } + ++buf; + } + } + } + } + } + + return true; +} + +bool ossimEquationCombiner::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimString outputScalarType = + ossimScalarTypeLut::instance()->getEntryString(theOutputScalarType); + + kwl.add(prefix, + EQUATION_KW, + theEquation.c_str(), + true); + + kwl.add(prefix, + "output_scalar_type", + outputScalarType.c_str(), + true); + + return ossimImageCombiner::saveState(kwl, + prefix); +} + +bool ossimEquationCombiner::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* equ = kwl.find(prefix, EQUATION_KW); + const char* scalar = kwl.find(prefix, "output_scalar_type"); + + bool result = ossimImageCombiner::loadState(kwl, + prefix); + + if(equ) + { + theEquation = equ; + } + + if(scalar) + { + setOutputScalarType(ossimScalarTypeLut::instance()-> + getScalarTypeFromString(scalar)); + } + + return result; +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEquationCombiner.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEquationCombiner.h new file mode 100644 index 0000000000..f0c8775531 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEquationCombiner.h @@ -0,0 +1,311 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimEquationCombiner.h,v 1.29 2005/09/12 12:02:42 dburken Exp $ +#ifndef ossimEquationCombiner_HEADER +#define ossimEquationCombiner_HEADER +#include <imaging/tile_sources/ossimImageCombiner.h> +#include <base/misc/ossimEquTokenizer.h> +#include <stack> + +class ossimCastTileSourceFilter; + +/** + * Will combine the input data based on a supplied equation. + * + * This combiner uses the ossimEquTokenizer to create unique id's + * for all tokens in the formula. The parser is based on the following + * rules: + * + * <pre> + * + * Prog -> Expr EOF + * Expr -> Term RestExpr + * RestExpr -> + Term RestExpr | - Term RestExpr | <null> + * Term -> Storable RestTerm + * RestTerm -> * Factor RestTerm | / Factor RestTerm | <null> + * Factor -> number | R | ( Expr ) + * + * + * We support the following tokens: + * + * sin(x) takes the sine of the input + * sind(x) takes the sin of the input and assumes degree input + * cos(x) takes cosine of input + * cosd(x) takes the cosine of input and assumes input in degrees + * sqrt(x) takes square root of input + * log(x) takes the natural log of input + * log10(x) takes the log base 10 of the input + * exp(x) takes the e raised to the passed in argument + * abs(x) takes the absolute value of the passed in value + * min(x1, x2, ... xn) takes the min of all values in the list + * max(x1, x2, ... xn) takes the max of all values in the list. + * + * clamp(image_data, min, max) + * will clamp all data to be between the min max values. + * will set anything less than min to min and anythin + * larger than max to max + * + * band(image_data, num) returns a single band image object + * by selecting band num from input image i1. Note + * the first argument must be an image + * and the second argument must be a number + * + * shift(index, num_x, num_y) + * currently, the first argument must be an image + * variable(i1, i2, ... in) and x, and y must b numbers + * indicating the delta in that direction to shift the + * input. + * + * blurr(index, rows, cols) + * Will blurr the input image i with a + * rows-by-cols kernel. All values are equal + * weight. Note the fist argument must by an image + * variable (ex: i1, i2,....in). + * + * conv(index, rows, cols, <row ordered list of values> ) + * this allows you to define an arbitrary matrix. The + * <row ordered list of values> is a comma separated + * list of constant values. + * + * assign_band(image_data, num1, data2, num2) + * will take band num2 from image data2 and assign it to + * band num1 in data 1. + * + * assign_band(image_data, num1, data2) + * will take band 1 from image data2 and assign it to + * band num1 in data 1. + * + * assign_band(image_data, num1, num2) + * will assin to band num1 of data 1 the value of num2 + * + * x1 * x2 will multiply x1 and x2 + * x1 + x2 will add x1 and x2 + * x1 - x2 will subtract x1 and x2 + * x1 / x2 will divide x1 and x2 + * x1 ^ x2 will do a power, raises x1 to x2 + * x1 | x2 will do a bitwise or operation + * ( will do it in unisgned char precision) + * + * x1 & x2 will do a bitwise and operation + * ( will do it in unsigned char precision) + * + * ~x1 will do the ones complement of the input + * + * x1 xor x2 will do an xclusive or operation + * (will do it in unsigned char precision) + * + * - x1 will negative of x1 + * + * Boolean ops: 1=true, 0=false + * x1 > x2 + * x1 >= x2 + * x1 == x2 + * x1 <= x2 + * x1 < x2 + * x1 <> x2 + * + * Note: + * + * Currently an image input is reference by the variable i followed by + * the input image index from 1. So 1 referes to the first image + * all result are promoted to an image object. + * + * Bands are accesible with in[B], B starts from 0 + * + * Some examples: + * + * (in[0] + in[1])/2 + * Will take image 1 and add it to image 2 and average them. + * + * exp(sqrt(in[0])/4) + * Will take the root of the image and divide by 4 and then raise e to that + * amount. + * + * 128 + * Will return a constant value of 128 for all input bands. + * + * min(1,in[3],in[4], max(in[2],in[1])) + * + * shift(0, 1, 1) - i1 + * Will shift input 0 by 1 pixel along the diagonal and then subtract it + * from input 1. + * + * assign_band(i1, 1, blurr(i1, 5, 5), 2) + * Will assign to the first band of i1 the 2nd band of the 5x5 blurr of i1. + * + * conv(0, 3, 3, -1, -2, -1, 0, 0, 0, 1, 2, 1) + * Will convolve the first input connection with a 3x3 matrix. + * The args are row ordered: + * -1, -2, -1 + * 0, 0, 0 + * 1, 2, 1 + * + * NDVI: + * N=(in[0]-in[1])/(in[0]+in[1]) + * + * For indexed-type values,like NDVI, (with limited values) it is better + * to rescale between 0.0 and 1.0 and use type NormalizedFloat. + * + * Rescaled NDVI between 0 and 1: + * (N+1)/2 = in[0]/(in[0]+in[1]) + * + * </pre> + */ +class OSSIMDLLEXPORT ossimEquationCombiner : public ossimImageCombiner +{ +public: + ossimEquationCombiner(); + virtual ~ossimEquationCombiner(); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& origin, + ossim_uint32 resLevel=0); + + virtual void initialize(); + + virtual void setEquation(const ossimString& equ) + { + theEquation = equ; + } + virtual ossimString getEquation()const + { + return theEquation; + } + + virtual double getNullPixelValue(ossim_uint32 band=0)const; + virtual double getMinPixelValue(ossim_uint32 band=0)const; + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + virtual ossimScalarType getOutputScalarType() const; + + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + + + virtual void setOutputScalarType(ossimScalarType scalarType); + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + class ossimBinaryOp + { + public: + virtual ~ossimBinaryOp(){} + virtual double apply(double v1, double v2)const=0; + }; + class ossimUnaryOp + { + public: + virtual ~ossimUnaryOp(){} + virtual double apply(double v)const=0; + }; + +protected: + enum ossimEquValueType + { + OSSIM_EQU_TYPE_UNKNOWN = 0, + OSSIM_EQU_DOUBLE_TYPE = 1, + OSSIM_EQU_IMAGE_DATA_TYPE = 2 + }; + + union ossimEquDataType + { + double doubleValue; + ossimImageData* imageDataValue; + }; + + struct ossimEquValue + { + int type; + ossimEquDataType d; + }; + + ossimScalarType theOutputScalarType; + ossimString theEquation; + mutable ossimEquTokenizer *theLexer; + ossimRefPtr<ossimImageData> theTile; + ossimCastTileSourceFilter *theCastFilter; + ossimCastTileSourceFilter *theCastOutputFilter; + + mutable int theCurrentId; + mutable std::stack<ossimEquValue> theValueStack; + ossim_uint32 theCurrentResLevel; + virtual void assignValue(); + virtual void clearStacks(); + virtual void clearArgList(vector<ossimEquValue>& argList); + + virtual ossimRefPtr<ossimImageData> getImageData(ossim_uint32 index); + virtual ossimRefPtr<ossimImageData> getNewImageData(ossim_uint32 index); + + virtual void deleteArgList(vector<ossimEquValue>& args); + virtual bool parseArgList(vector<ossimEquValue>& args, + bool popValueStack = true); + + virtual ossimRefPtr<ossimImageData> parseEquation(); + + virtual bool parseAssignBand(); + virtual bool parseExpression(); + virtual bool parseRestOfExp(); + virtual bool parseTerm(); + virtual bool parseRestOfTerm(); + virtual bool parseFactor(); + virtual bool parseStdFuncs(); + virtual bool parseUnaryFactor(); + + virtual bool applyClamp(ossimImageData* &result, + const vector<ossimEquValue>& argList); + + virtual bool applyConvolution(ossimImageData* &result, + const vector<ossimEquValue>& argList); + + virtual bool applyBlurr(ossimImageData* &result, + const vector<ossimEquValue>& argList); + + virtual bool applyShift(ossimImageData* &result, + const vector<ossimEquValue>& argList); + + virtual bool applyOp(const ossimBinaryOp& op, + ossimEquValue& result, + ossimEquValue& v1, + ossimEquValue& v2); + + virtual bool applyOp(const ossimBinaryOp& op, + ossimImageData* v1, + double v2); + + virtual bool applyOp(const ossimBinaryOp& op, + double v1, + ossimImageData* v2); + + virtual bool applyOp(const ossimBinaryOp& op, + ossimImageData* v1, + ossimImageData* v2); + + + virtual bool applyOp(const ossimUnaryOp& op, + ossimEquValue& result, + ossimEquValue& v1); + + virtual bool applyOp(const ossimUnaryOp& op, + ossimImageData* v); + +TYPE_DATA +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEsriShapeFileCutter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEsriShapeFileCutter.cpp new file mode 100644 index 0000000000..77483974e4 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEsriShapeFileCutter.cpp @@ -0,0 +1,323 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimEsriShapeFileCutter.cpp,v 1.6 2005/09/15 12:28:44 gpotts Exp $ +#include <imaging/tile_sources/ossimEsriShapeFileCutter.h> + +RTTI_DEF2(ossimEsriShapeFileCutter, + "ossimEsriShapeFileCutter", + ossimImageSourceFilter, + ossimViewInterface); + +ossimEsriShapeFileCutter::ossimEsriShapeFileCutter() + :ossimImageSourceFilter(), + ossimViewInterface(), + theEsriShapeFile(NULL), + theMaskFilter(NULL) +{ + theObject = this; + theEsriShapeFile = new ossimEsriShapeFileFilter; + theEsriShapeFile->setFillFlag(true); + + theMaskFilter = new ossimMaskFilter; + + theMaskFilter->connectMyInputTo(1, + theEsriShapeFile); +} + +ossimEsriShapeFileCutter::~ossimEsriShapeFileCutter() +{ + if(theEsriShapeFile) + { + delete theEsriShapeFile; + theEsriShapeFile = NULL; + } + + if(theMaskFilter) + { + delete theMaskFilter; + theMaskFilter = NULL; + } +} + +ossimRefPtr<ossimImageData> ossimEsriShapeFileCutter::getTile( + const ossimIrect& rect, + ossim_uint32 resLevel) +{ + if(isSourceEnabled()) + { + if(theMaskFilter) + { + return theMaskFilter->getTile(rect, resLevel); + } + } + else + { + if(getInput()) + { + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, + getInput()); + + if(input) + { + return input->getTile(rect, resLevel); + } + } + } + + return NULL; +} + +void ossimEsriShapeFileCutter::initialize() +{ + if(theEsriShapeFile) + { + theEsriShapeFile->initialize(); + } + + + if(theMaskFilter) + { + theMaskFilter->disconnectMyInput((ossim_int32)0); + theMaskFilter->disconnectMyInput((ossim_int32)1); + theMaskFilter->connectMyInputTo((int)0, + getInput(0)); + theMaskFilter->connectMyInputTo(1, + theEsriShapeFile); + } +} + +bool ossimEsriShapeFileCutter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimString shapeFilePrefix = ossimString(prefix) + "shape_file_filter."; + ossimString maskPrefix = ossimString(prefix) + "mask."; + + theEsriShapeFile->loadState(kwl, shapeFilePrefix.c_str()); + theMaskFilter->loadState(kwl, maskPrefix.c_str()); + + return ossimImageSourceFilter::loadState(kwl, prefix); +} + +bool ossimEsriShapeFileCutter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimString shapeFilePrefix = ossimString(prefix) + "shape_file_filter."; + ossimString maskPrefix = ossimString(prefix) + "mask."; + + theEsriShapeFile->saveState(kwl, shapeFilePrefix.c_str()); + theMaskFilter->saveState(kwl, maskPrefix.c_str()); + + return ossimImageSourceFilter::saveState(kwl, prefix); +} + +void ossimEsriShapeFileCutter::getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result)const +{ + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, getInput(0)); + if(input) + { + input->getDecimationFactor(resLevel, result); + } +} + +ossimIrect ossimEsriShapeFileCutter::getBoundingRect(ossim_uint32 resLevel)const +{ + ossimIrect result; + result.makeNan(); + + if(theMaskFilter) + { + result = theMaskFilter->getBoundingRect(resLevel); + } + + return result; +} + +void ossimEsriShapeFileCutter::getDecimationFactors( + vector<ossimDpt>& decimations)const +{ + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(input) + { + input->getDecimationFactors(decimations); + } +} + +ossim_uint32 ossimEsriShapeFileCutter::getNumberOfDecimationLevels()const +{ + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(input) + { + return input->getNumberOfDecimationLevels(); + } + return 0; +} + +ossim_uint32 ossimEsriShapeFileCutter::getNumberOfOutputBands() const +{ + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(input) + { + return input->getNumberOfOutputBands(); + } + return 0; +} + +ossimScalarType ossimEsriShapeFileCutter::getOutputScalarType() const +{ + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(input) + { + return input->getOutputScalarType(); + } + + return OSSIM_SCALAR_UNKNOWN; +} + +void ossimEsriShapeFileCutter::getValidImageVertices( + vector<ossimIpt>& validVertices, + ossimVertexOrdering ordering, + ossim_uint32 resLevel) const +{ + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(input) + { + input->getValidImageVertices(validVertices, ordering, resLevel); + } +} + +ossim_uint32 ossimEsriShapeFileCutter::getTileWidth() const +{ + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(input) + { + return input->getTileWidth(); + } + + return 0; +} + +ossim_uint32 ossimEsriShapeFileCutter::getTileHeight() const +{ + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(input) + { + return input->getTileHeight(); + } + return 0; +} + +double ossimEsriShapeFileCutter::getNullPixelValue(ossim_uint32 band)const +{ + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(input) + { + return input->getNullPixelValue(band); + } + return 0; +} + +double ossimEsriShapeFileCutter::getMinPixelValue(ossim_uint32 band)const +{ + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(input) + { + return input->getMinPixelValue(band); + } + return 0; +} + +double ossimEsriShapeFileCutter::getMaxPixelValue(ossim_uint32 band)const +{ + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, getInput(0)); + if(input) + { + return input->getMaxPixelValue(band); + } + return 0; +} + +void ossimEsriShapeFileCutter::loadFile(const ossimFilename& filename) +{ + if(theEsriShapeFile) + { + theEsriShapeFile->loadShapeFile(filename); + } +} + +bool ossimEsriShapeFileCutter::setView(ossimObject* baseObject, + bool ownsTheView) +{ + if(theEsriShapeFile) + { + return theEsriShapeFile->setView(baseObject, ownsTheView); + } + + return false; +} + +ossimObject* ossimEsriShapeFileCutter::getView() +{ + if(theEsriShapeFile) + { + return theEsriShapeFile->getView(); + } + + return NULL;; +} + +const ossimObject* ossimEsriShapeFileCutter::getView()const +{ + if(theEsriShapeFile) + { + return theEsriShapeFile->getView(); + } + + return NULL;; +} + +ossimFilename ossimEsriShapeFileCutter::getFilename()const +{ + if(theEsriShapeFile) + { + return theEsriShapeFile->getFilename(); + } + + return ossimFilename(); +} + +void ossimEsriShapeFileCutter::setMaskType( + ossimMaskFilter::ossimFileSelectionMaskType type) +{ + if(theMaskFilter) + { + theMaskFilter->setMaskType(type); + } +} + +ossimMaskFilter::ossimFileSelectionMaskType ossimEsriShapeFileCutter::getMaskType()const +{ + if(theMaskFilter) + { + return theMaskFilter->getMaskType(); + } + + return ossimMaskFilter::OSSIM_MASK_TYPE_SELECT; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEsriShapeFileCutter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEsriShapeFileCutter.h new file mode 100644 index 0000000000..afc7e2da88 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimEsriShapeFileCutter.h @@ -0,0 +1,200 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimEsriShapeFileCutter.h,v 1.10 2005/09/15 12:28:44 gpotts Exp $ +#ifndef ossimEsriShapeFileCutter_HEADER +#define ossimEsriShapeFileCutter_HEADER +#include <imaging/tile_sources/ossimImageSourceFilter.h> +#include <base/common/ossimViewInterface.h> +#include <imaging/tile_sources/ossimMaskFilter.h> +#include <imaging/annotation/ossimEsriShapeFileFilter.h> + +/** + * This class wraps the ossimEsriShapeFileFilter and ossimMaskFilter to implement + * a composite cutter. + * + * the ossimEsriShapeFileFilter is saved with a shape_file_filter. prefix and the + * ossimMaskFilter is saved with a mask. prefix. Please see ossimEsriShapeFileFilter + * and ossimMaskFilter classes for their keywords. theborder size has an optional units + * associated with it. + * <pre> + * + * The border size can be us-feet, feet, meters, or degrees and is only applied + * to polygons. + * + * Example keyword list + * + * shape_file_filter.brush_color: 255 255 255 + * shape_file_filter.feature_name: + * shape_file_filter.filename: + * shape_file_filter.fill_flag: 0 + * shape_file_filter.max_quadtree_levels: 10 + * shape_file_filter.pen_color: 255 255 255 + * shape_file_filter.point_width_height: 1 1 + * shape_file_filter.thickness: 1 + * shape_file_filter.border_size: 50 meters + * shape_file_filter.type: ossimEsriShapeFileFilter + * mask.mask_type: select + * mask.type: ossimMaskFilter + + * </pre> + * + */ +class ossimEsriShapeFileCutter : public ossimImageSourceFilter, + public ossimViewInterface +{ +public: + /** + * allocates the mask and esri loader + */ + ossimEsriShapeFileCutter(); + + /** + * destroys the data members + */ + virtual ~ossimEsriShapeFileCutter(); + + /** + * Sent to the input + */ + virtual void getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result)const; + + /** + * The bounding rect call is passed to the mask filter + */ + virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0)const; + + /** + * The get tile call is passed to the mask filter + */ + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect, + ossim_uint32 resLevel=0); + + /** + * is passed to the filter and the shape file loader + */ + virtual void initialize(); + + /** + * passed to the input source. + */ + virtual void getDecimationFactors(vector<ossimDpt>& decimations)const; + + /** + * passed to the input source. + */ + virtual ossim_uint32 getNumberOfDecimationLevels()const; + + /** + * passed to the input source. + */ + virtual ossim_uint32 getNumberOfOutputBands() const; + + /** + * passed to the input source. + */ + virtual ossimScalarType getOutputScalarType() const; + + /** + * passed to the input source. + */ + virtual void getValidImageVertices( + vector<ossimIpt>& validVertices, + ossimVertexOrdering ordering=OSSIM_CLOCKWISE_ORDER, + ossim_uint32 resLevel=0)const; + + /** + * passed to the input source. + */ + virtual ossim_uint32 getTileWidth() const; + + /** + * passed to the input source. + */ + virtual ossim_uint32 getTileHeight() const; + + /** + * passed to the input source. + */ + virtual double getNullPixelValue(ossim_uint32 band)const; + + /** + * passed to the input source. + */ + virtual double getMinPixelValue(ossim_uint32 band=0)const; + + /** + * passed to the input source. + */ + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + + /** + * passed to the shape file to load the shape file that will be used + * by the mask filter as input. + */ + void loadFile(const ossimFilename& filename); + + /** + * this is here to support the view interface of the esri shape file. + * it passes view calls to the esri filter + */ + virtual bool setView(ossimObject* baseObject, + bool ownsTheView = false); + + /** + * this is here to support the view interface of the esri shape file. + * Will return the view setting for the esri shape file. + */ + virtual ossimObject* getView(); + + /** + * this is here to support the view interface of the esri shape file. + * Will return the view setting for the esri shape file. + */ + virtual const ossimObject* getView()const; + + /** + * Return the current esri shape file being used + */ + ossimFilename getFilename()const; + + /** + * Sets the mask type. Passes the call to the Mask filter. + */ + void setMaskType(ossimMaskFilter::ossimFileSelectionMaskType type); + + /** + * returns the mask type from the maks filter. + */ + ossimMaskFilter::ossimFileSelectionMaskType getMaskType()const; + + /** + * Passes load state call to the esri shape file loader with prefix + * shape_file_filter. Then passes the load state cll to the mask + * filter with prefix = mask. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * Passes save state call to the esri shape file loader with prefix + * shape_file_filter. Then passes the load state cll to the mask + * filter with prefix = mask. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; +protected: + ossimEsriShapeFileFilter* theEsriShapeFile; + ossimMaskFilter* theMaskFilter; +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimFeatherMosaic.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimFeatherMosaic.cpp new file mode 100644 index 0000000000..53f36fcddf --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimFeatherMosaic.cpp @@ -0,0 +1,474 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimFeatherMosaic.cpp,v 1.33 2005/05/09 12:39:40 dburken Exp $ + +#include <imaging/tile_sources/ossimFeatherMosaic.h> +#include <base/data_types/ossimDpt.h> +#include <imaging/ossimImageData.h> +#include <base/common/ossimConstants.h> +#include <base/data_types/ossimLine.h> +#include <base/common/ossimTrace.h> + +static ossimTrace traceDebug("ossimFeatherMosaic:debug"); + +RTTI_DEF1(ossimFeatherMosaic, "ossimFeatherMosaic", ossimImageMosaic); + +ossimFeatherMosaic::ossimFeatherMosaic() + :ossimImageMosaic(), + theInputFeatherInformation(NULL), + theAlphaSum(NULL), + theResult(NULL), + theFeatherInfoSize(0) +{ +} + +ossimFeatherMosaic::ossimFeatherMosaic(std::vector<ossimImageSource*>& inputSources) + :ossimImageMosaic(inputSources), + theInputFeatherInformation(NULL), + theAlphaSum(NULL), + theResult(NULL), + theFeatherInfoSize(0) +{ + initialize(); +} + +ossimFeatherMosaic::~ossimFeatherMosaic() +{ + if(theInputFeatherInformation) + { + delete [] theInputFeatherInformation; + theInputFeatherInformation = NULL; + } + theFeatherInfoSize = 0; +} + +ossimRefPtr<ossimImageData> ossimFeatherMosaic::getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + long w = tileRect.width(); + long h = tileRect.height(); + ossimIpt origin = tileRect.ul(); + + if(!isSourceEnabled()) + { + return ossimImageMosaic::getTile(tileRect, resLevel); + } + if(!theTile||!theAlphaSum||!theResult||!theInputFeatherInformation) + { + initialize(); + + if(!theTile||!theAlphaSum||!theResult||!theInputFeatherInformation) + { + return ossimImageMosaic::getTile(tileRect, resLevel); + } + } + ossim_uint32 size = getNumberOfInputs(); + theAlphaSum->setImageRectangle(tileRect); + theResult->setImageRectangle(tileRect); + + if(size == 0) + { + return ossimRefPtr<ossimImageData>(); + } + + if(size == 1) + { + return ossimImageMosaic::getTile(tileRect, resLevel); + } + + long tileW = theTile->getWidth(); + long tileH = theTile->getHeight(); + if((w != tileW)|| + (h != tileH)) + { + theTile->setWidth(w); + theTile->setHeight(h); + if((w*h)!=(tileW*tileH)) + { + theTile->initialize(); + } + } + theTile->setOrigin(origin); + theTile->makeBlank(); + + switch(theTile->getScalarType()) + { + case OSSIM_UCHAR: + { + return combine(static_cast<ossim_uint8>(0), + tileRect, resLevel); + } + case OSSIM_USHORT16: + case OSSIM_USHORT11: + { + return combine(static_cast<ossim_uint16>(0), + tileRect, resLevel); + } + case OSSIM_SSHORT16: + { + return combine(static_cast<ossim_sint16>(0), + tileRect, resLevel); + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + return combine(static_cast<double>(0), + tileRect, resLevel); + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + return combine(static_cast<float>(0), + tileRect, resLevel); + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimFeatherMosaic::getTile: error, unknown scalar type!!!" + << std::endl; + } + } + return ossimRefPtr<ossimImageData>(); +} + + +template <class T> ossimRefPtr<ossimImageData> ossimFeatherMosaic::combine( + T, + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + ossimRefPtr<ossimImageData> currentImageData; + ossim_uint32 band; + long upperBound = theTile->getWidth()*theTile->getHeight(); + long offset = 0; + long row = 0; + long col = 0; + long numberOfTilesProcessed = 0; + float *sumBand = static_cast<float*>(theAlphaSum->getBuf()); + float *bandRes = NULL; + ossimIpt point; + + theAlphaSum->fill(0.0); + theResult->fill(0.0); + + T** srcBands = new T*[theLargestNumberOfInputBands]; + T** destBands = new T*[theLargestNumberOfInputBands]; + + currentImageData = getNextTile(0, + tileRect, + resLevel); + if(!currentImageData.valid()) + { + delete [] srcBands; + delete [] destBands; + return currentImageData; + } + ossim_uint32 minNumberOfBands = currentImageData->getNumberOfBands(); + for(band = 0; band < minNumberOfBands; ++band) + { + srcBands[band] = static_cast<T*>(currentImageData->getBuf(band)); + destBands[band] = static_cast<T*>(theTile->getBuf(band)); + } + // if the src is smaller than the destination in number + // of bands we will just duplicate the last band. + for(;band < theLargestNumberOfInputBands; ++band) + { + srcBands[band] = srcBands[minNumberOfBands - 1]; + destBands[band] = static_cast<T*>(theTile->getBuf(band)); + } + + // most of the time we will not overlap so let's + // copy the first tile into destination and check later. + // + for(band = 0; band < theTile->getNumberOfBands();++band) + { + T* destBand = destBands[band]; + T* srcBand = srcBands[band]; + if(destBand&&srcBand) + { + for(offset = 0; offset < upperBound;++offset) + { + *destBand = *srcBand; + ++srcBand; ++destBand; + } + } + } + theTile->setDataObjectStatus(currentImageData->getDataObjectStatus()); + + while(currentImageData.valid()) + { + ossimDataObjectStatus currentStatus = currentImageData->getDataObjectStatus(); + point = currentImageData->getOrigin(); + long h = (long)currentImageData->getHeight(); + long w = (long)currentImageData->getWidth(); + if( (currentStatus != OSSIM_EMPTY) && + (currentStatus != OSSIM_NULL)) + { + ++numberOfTilesProcessed; + offset = 0; + minNumberOfBands = currentImageData->getNumberOfBands(); + for(band = 0; band < minNumberOfBands; ++band) + { + srcBands[band] = static_cast<T*>(currentImageData->getBuf(band)); + } + // if the src is smaller than the destination in number + // of bands we will just duplicate the last band. + for(;band < theLargestNumberOfInputBands; ++band) + { + srcBands[band] = srcBands[minNumberOfBands - 1]; + } + if(currentStatus == OSSIM_PARTIAL) + { + for(row = 0; row < h; ++row) + { + for(col = 0; col < w; ++col) + { + if(!currentImageData->isNull(offset)) + { + double weight = computeWeight(theCurrentIndex, + ossimDpt(point.x+col, + point.y+row)); + + for(band = 0; band < theLargestNumberOfInputBands; ++band) + { + bandRes = static_cast<float*>(theResult->getBuf(band)); + bandRes[offset] += (srcBands[band][offset]*weight); + } + sumBand[offset] += weight; + } + ++offset; + } + } + } + else + { + offset = 0; + + for(row = 0; row < h; ++row) + { + for(col = 0; col < w; ++col) + { + double weight = computeWeight(theCurrentIndex, + ossimDpt(point.x+col, + point.y+row)); + + for(band = 0; band < theLargestNumberOfInputBands; ++band) + { + bandRes = static_cast<float*>(theResult->getBuf(band)); + + bandRes[offset] += (srcBands[band][offset]*weight); + } + sumBand[offset] += weight; + ++offset; + } + } + } + } + currentImageData = getNextTile(tileRect, resLevel); + } + upperBound = theTile->getWidth()*theTile->getHeight(); + + if(numberOfTilesProcessed > 1) + { + const double* minPix = theTile->getMinPix(); + const double* maxPix = theTile->getMaxPix(); + const double* nullPix= theTile->getNullPix(); + for(offset = 0; offset < upperBound;++offset) + { + for(band = 0; band < theTile->getNumberOfBands();++band) + { + T* destBand = static_cast<T*>(theTile->getBuf(band)); + float* weightedBand = static_cast<float*>(theResult->getBuf(band)); + + // this should be ok to test 0.0 instead of + // FLT_EPSILON range for 0 since we set it. + if(sumBand[offset] != 0.0) + { + weightedBand[offset] = (weightedBand[offset])/sumBand[offset]; + if(weightedBand[offset]<minPix[band]) + { + weightedBand[offset] = minPix[band]; + } + else if(weightedBand[offset] > maxPix[band]) + { + weightedBand[offset] = maxPix[band]; + } + } + else + { + weightedBand[offset] = nullPix[band]; + } + destBand[offset] = static_cast<T>(weightedBand[offset]); + } + } + theTile->validate(); + } + + delete [] srcBands; + delete [] destBands; + + return theTile; +} + +double ossimFeatherMosaic::computeWeight(long index, + const ossimDpt& point)const +{ + ossimFeatherInputInformation& info = theInputFeatherInformation[index]; + double result = 0.0; + ossimDpt delta = point-info.theCenter; + + double length1 = fabs(delta.x*info.theAxis1.x + delta.y*info.theAxis1.y)/info.theAxis1Length; + double length2 = fabs(delta.x*info.theAxis2.x + delta.y*info.theAxis2.y)/info.theAxis2Length; + + if(length1 > length2) + { + result = (1.0 - length1); + } + else + { + result = (1.0 - length2); + } + if(result < 0) result = 0; + + return result; +} + +void ossimFeatherMosaic::initialize() +{ + ossimImageMosaic::initialize(); + + allocate(); + if(theTile.valid()) + { + theAlphaSum = new ossimImageData(this, + OSSIM_FLOAT, + 1, + theTile->getWidth(), + theTile->getHeight()); + theResult = new ossimImageData(this, + OSSIM_FLOAT, + theLargestNumberOfInputBands, + theTile->getWidth(), + theTile->getHeight()); + theAlphaSum->initialize(); + theResult->initialize(); + } + std::vector<ossimIpt> validVertices; + if(!getNumberOfInputs()) return; + + if(theInputFeatherInformation) + { + delete [] theInputFeatherInformation; + theInputFeatherInformation = NULL; + } + theFeatherInfoSize = getNumberOfInputs(); + theInputFeatherInformation = new ossimFeatherInputInformation[theFeatherInfoSize]; + for(long index = 0; index < theFeatherInfoSize; ++ index) + { + validVertices.clear(); + ossimImageSourceInterface* temp = PTR_CAST(ossimImageSourceInterface, getInput(index)); + if(temp) + { + temp->getValidImageVertices(validVertices, OSSIM_CLOCKWISE_ORDER); + theInputFeatherInformation[index].setVertexList(validVertices); + } + } +} + + +ossimFeatherMosaic::ossimFeatherInputInformation::ossimFeatherInputInformation(const std::vector<ossimIpt>& validVertices) +{ + setVertexList(validVertices); +} + + +void ossimFeatherMosaic::ossimFeatherInputInformation::setVertexList(const std::vector<ossimIpt>& validVertices) +{ + const char* MODULE = "ossimFeatherMosaic::ossimFeatherInputInformation::setVertexList()"; + + theValidVertices = validVertices; + + theCenter = ossimDpt(0,0); + theAxis1 = ossimDpt(1, 0); + theAxis2 = ossimDpt(0, 1); + theAxis1Length = 1; + theAxis2Length = 1; + + double xSum=0.0, ySum=0.0; + long upperBound = validVertices.size(); + if(upperBound) + { + for(long index = 0; index < upperBound; ++index) + { + xSum += validVertices[index].x; + ySum += validVertices[index].y; + } + + theCenter.x = xSum/upperBound; + theCenter.y = ySum/upperBound; + + // for now we just want a quick implementation of something + // and we know that we have 4 vertices for the bounding valid + // vertices. + // + if(upperBound == 4) + { + ossimDpt edgeDirection1 = validVertices[1] - validVertices[0]; + ossimDpt edgeDirection2 = validVertices[2] - validVertices[1]; + + theAxis1 = ossimDpt(-edgeDirection1.y, edgeDirection1.x); + + theAxis2 = ossimDpt(-edgeDirection2.y, edgeDirection2.x); + + theAxis1 = theAxis1/theAxis1.length(); + theAxis2 = theAxis2/theAxis2.length(); + + ossimLine line1(theCenter, + theCenter + theAxis1*2); + ossimLine line2(validVertices[1], + validVertices[0]); + ossimLine line3(theCenter, + theCenter + theAxis2*2); + ossimLine line4(validVertices[2], + validVertices[1]); + + ossimDpt intersectionPoint1 = line1.intersectInfinite(line2); + ossimDpt intersectionPoint2 = line3.intersectInfinite(line4); + + + theAxis1Length = irint((theCenter-intersectionPoint1).length()); + theAxis2Length = irint((theCenter-intersectionPoint2).length()); + + if(traceDebug()) + { + CLOG << "theAxis1Length: " << theAxis1Length << endl + << "theAxis2Length: " << theAxis2Length << endl + << "center: " << theCenter << endl; + } + } + } +} + +ostream& operator<<(ostream& out, + const ossimFeatherMosaic::ossimFeatherInputInformation& data) +{ + out << "center: " << data.theCenter << endl + << "axis1: " << data.theAxis1 << endl + << "axis2: " << data.theAxis2 << endl + << "axis1_length: " << data.theAxis1Length << endl + << "axis2_length: " << data.theAxis2Length << endl + << "valid vertices: " << endl; + std::copy(data.theValidVertices.begin(), + data.theValidVertices.end(), + std::ostream_iterator<ossimDpt>(out, "\n")); + return out; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimFeatherMosaic.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimFeatherMosaic.h new file mode 100644 index 0000000000..7f8dfdbe19 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimFeatherMosaic.h @@ -0,0 +1,87 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimFeatherMosaic.h,v 1.13 2005/02/11 15:07:33 dburken Exp $ +#ifndef ossimFeatherMosaic_HEADER +#define ossimFeatherMosaic_HEADER +#include <vector> +#include <iterator> + +#include <imaging/tile_sources/ossimImageMosaic.h> +#include <base/data_types/ossimDpt.h> + + +/** + * Performs a spatial blend accross overlapping regions + */ +class OSSIMDLLEXPORT ossimFeatherMosaic : public ossimImageMosaic +{ +public: + ossimFeatherMosaic(); + ossimFeatherMosaic(vector<ossimImageSource*>& inputSources); + virtual ~ossimFeatherMosaic(); + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& origin, + ossim_uint32 resLevel=0); + virtual void initialize(); + +protected: + /** + * This is only visible by this class and will remain here + * unless we want to move it later. + */ + class ossimFeatherInputInformation + { + + public: + ossimFeatherInputInformation(const vector<ossimIpt>& validVertices=vector<ossimIpt>()); + + void setVertexList(const vector<ossimIpt>& validVertices); + + ossimDpt theCenter; + ossimDpt theAxis1; + ossimDpt theAxis2; + double theAxis1Length; + double theAxis2Length; + std::vector<ossimIpt> theValidVertices; + + }; + + friend ostream& operator<<(ostream& out, + const ossimFeatherInputInformation& data); + + + /** + * will hold an array of input information + * + */ + ossimFeatherInputInformation* theInputFeatherInformation; + ossimRefPtr<ossimImageData> theAlphaSum; + ossimRefPtr<ossimImageData> theResult; + + /** + * Will hold the count for the feather information list. + */ + long theFeatherInfoSize; + + /** + * The dummy variable is used for the template type. See the getTile + * method for the call. + */ + template <class T> + ossimRefPtr<ossimImageData> combine(T dummyVariableNotUsed, + const ossimIrect& tileRect, + ossim_uint32 resLevel); + + virtual double computeWeight(long index, + const ossimDpt& point)const; +TYPE_DATA +}; + +#endif /* #ifndef ossimFeatherMosaic_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimFftFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimFftFilter.cpp new file mode 100644 index 0000000000..78edddaacd --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimFftFilter.cpp @@ -0,0 +1,472 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimFftFilter.cpp,v 1.4 2005/02/11 15:07:33 dburken Exp $ + +#include <imaging/tile_sources/ossimFftFilter.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <matrix/newmat.h> +#include <matrix/newmatap.h> +#include <imaging/tile_sources/ossimScalarRemapper.h> +#include <base/property/ossimStringProperty.h> + +RTTI_DEF1(ossimFftFilter, "ossimFftFilter", ossimImageSourceFilter); + +ossimFftFilter::ossimFftFilter(ossimObject* owner) + :ossimImageSourceFilter(owner), + theTile(0), + theDirectionType(ossimFftFilterDirectionType_FORWARD), + theScalarRemapper(new ossimScalarRemapper()) +{ + theScalarRemapper->setOutputScalarType(OSSIM_DOUBLE); +} + +ossimFftFilter::ossimFftFilter(ossimImageSource* inputSource) + :ossimImageSourceFilter(inputSource), + theTile(0), + theDirectionType(ossimFftFilterDirectionType_FORWARD), + theScalarRemapper(new ossimScalarRemapper()) +{ + theScalarRemapper->setOutputScalarType(OSSIM_DOUBLE); +} + +ossimFftFilter::ossimFftFilter(ossimObject* owner, + ossimImageSource* inputSource) + :ossimImageSourceFilter(owner, inputSource), + theTile(0), + theDirectionType(ossimFftFilterDirectionType_FORWARD), + theScalarRemapper(new ossimScalarRemapper()) +{ + theScalarRemapper->setOutputScalarType(OSSIM_DOUBLE); +} + +ossimFftFilter::~ossimFftFilter() +{ + if(theScalarRemapper) + { + delete theScalarRemapper; + theScalarRemapper = 0; + } +} + +ossimRefPtr<ossimImageData> ossimFftFilter::getTile(const ossimIrect& rect, + ossim_uint32 resLevel) +{ + if(!isSourceEnabled()) + { + return ossimImageSourceFilter::getTile(rect, resLevel); + } + + ossimIrect tempRequest = rect; + + ossim_uint32 w = rect.width(); + ossim_uint32 h = rect.height(); + + if(w & 1) + { + ++w; + } + if(h&1) + { + ++h; + } + + tempRequest = ossimIrect(rect.ul().x, + rect.ul().y, + rect.ul().x + (w-1), + rect.ul().y + (h-1)); + + ossimRefPtr<ossimImageData> input; + input = theScalarRemapper->getTile(tempRequest, resLevel); + + if(!input.valid()) return input; + + if(!theTile.valid()) initialize(); + if(!theTile.valid()) return theTile; + + theTile->setImageRectangle(rect); + ossimRefPtr<ossimImageData> tempTile = theTile; + + if(!input->getBuf()) + { + return theTile; + } + + if(rect != tempRequest) + { + tempTile = (ossimImageData*)theTile->dup(); + tempTile->setImageRectangle(tempRequest); + } + + runFft((ossim_float64)0, input, tempTile); + + if(tempTile != theTile) + { + theTile->loadTile(tempTile.get()); + } + + theTile->validate(); + + return theTile; +} + +void ossimFftFilter::initialize() +{ + ossimImageSourceFilter::initialize(); + + theTile = ossimImageDataFactory::instance()->create(this, this); + + if(theTile.valid()) + { + theTile->initialize(); + } + if(theDirectionType == ossimFftFilterDirectionType_FORWARD) + { + theScalarRemapper->setOutputScalarType(OSSIM_NORMALIZED_DOUBLE); + } + else + { + theScalarRemapper->setOutputScalarType(OSSIM_DOUBLE); + } + theScalarRemapper->connectMyInputTo(0, getInput()); +} + +ossimScalarType ossimFftFilter::getOutputScalarType() const +{ + if(!isSourceEnabled()) + { + return ossimImageSourceFilter::getOutputScalarType(); + } + + if(theDirectionType == ossimFftFilterDirectionType_FORWARD) + { + return OSSIM_DOUBLE; + } + + return OSSIM_NORMALIZED_DOUBLE; +} + +double ossimFftFilter::getNullPixelValue(ossim_uint32 band)const +{ + if(!isSourceEnabled()) + { + return ossimImageSourceFilter::getNullPixelValue(band); + } + if(theDirectionType == ossimFftFilterDirectionType_FORWARD) + { + return OSSIM_DBL_NAN; + } + + // it will invert to a normalized float output + return 0.0; +} + +double ossimFftFilter::getMinPixelValue(ossim_uint32 band)const +{ + if(!isSourceEnabled()) + { + return ossimImageSourceFilter::getMinPixelValue(band); + } + if(theDirectionType == ossimFftFilterDirectionType_FORWARD) + { + return OSSIM_DEFAULT_MIN_PIX_DOUBLE; + } + return OSSIM_DEFAULT_MIN_PIX_NORM_DOUBLE; +} + +double ossimFftFilter::getMaxPixelValue(ossim_uint32 band)const +{ + if(!isSourceEnabled()) + { + return ossimImageSourceFilter::getMaxPixelValue(band); + } + if(theDirectionType == ossimFftFilterDirectionType_FORWARD) + { + return OSSIM_DEFAULT_MAX_PIX_DOUBLE; + } + return OSSIM_DEFAULT_MAX_PIX_NORM_DOUBLE; +} + +ossim_uint32 ossimFftFilter::getNumberOfOutputBands() const +{ + if(!isSourceEnabled()) + { + return ossimImageSourceFilter::getNumberOfOutputBands(); + } + ossim_uint32 bands = ossimImageSourceFilter::getNumberOfOutputBands(); + + if(theDirectionType == ossimFftFilterDirectionType_FORWARD) + { + bands *=2; + } + else + { + bands /=2; + } + + return bands; +} + +void ossimFftFilter::setForward() +{ + theDirectionType = ossimFftFilterDirectionType_FORWARD; +} + +void ossimFftFilter::setInverse() +{ + theDirectionType = ossimFftFilterDirectionType_INVERSE; +} + +ossimString ossimFftFilter::getDirectionTypeAsString()const +{ + if(theDirectionType == ossimFftFilterDirectionType_FORWARD) + { + return "Forward"; + } + + return "Inverse"; +} + +void ossimFftFilter::setDirectionType(const ossimString& directionType) +{ + ossimString tempDirectionType = directionType; + tempDirectionType = tempDirectionType.downcase(); + + if(tempDirectionType.contains("forward")) + { + setDirectionType(ossimFftFilterDirectionType_FORWARD); + } + else + { + setDirectionType(ossimFftFilterDirectionType_INVERSE); + } +} + +void ossimFftFilter::setDirectionType(ossimFftFilterDirectionType directionType) +{ + theDirectionType = directionType; + if(theTile.valid()) + { + theTile = NULL; + } +} + +ossimRefPtr<ossimProperty> ossimFftFilter::getProperty(const ossimString& name)const +{ + if(name == "FFT Direction") + { + std::vector<ossimString> filterNames; + filterNames.push_back("Forward"); + filterNames.push_back("Inverse"); + ossimStringProperty* stringProp = new ossimStringProperty("FFT Direction", + getDirectionTypeAsString(), + false, + filterNames); + stringProp->setCacheRefreshBit(); + + return stringProp; + } + + return ossimImageSourceFilter::getProperty(name); +} + +void ossimFftFilter::setProperty(ossimRefPtr<ossimProperty> property) +{ + if(!property) return; + + if(property->getName() == "FFT Direction") + { + if(theTile.valid()) + { + theTile = NULL; + } + setDirectionType(property->valueToString()); + } + else + { + ossimImageSourceFilter::setProperty(property); + } +} + +void ossimFftFilter::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + ossimImageSourceFilter::getPropertyNames(propertyNames); + propertyNames.push_back("FFT Direction"); +} + + +template <class T> +void ossimFftFilter::runFft(T dummy, + ossimRefPtr<ossimImageData>& input, + ossimRefPtr<ossimImageData>& output) +{ + // T* inputBand = 0; + + NEWMAT::Matrix* realIn = new NEWMAT::Matrix(input->getHeight(), + input->getWidth()); + NEWMAT::Matrix* imgIn = new NEWMAT::Matrix(input->getHeight(), + input->getWidth()); + NEWMAT::Matrix* realOut = new NEWMAT::Matrix(input->getHeight(), + input->getWidth()); + NEWMAT::Matrix* imgOut = new NEWMAT::Matrix(input->getHeight(), + input->getWidth()); + ossim_uint32 bandIdx = 0; + ossim_uint32 w = input->getWidth(); + ossim_uint32 h = input->getHeight(); + ossim_uint32 x = 0; + ossim_uint32 y = 0; + if(theDirectionType == ossimFftFilterDirectionType_FORWARD) + { + ossim_uint32 bands = input->getNumberOfBands(); + for(bandIdx = 0; bandIdx < bands; ++bandIdx) + { + ossim_float64* bandReal = 0; + ossim_float64* bandImg = 0; + fillMatrixForward((T*)input->getBuf(bandIdx), + (T)input->getNullPix(bandIdx), + *realIn, + *imgIn); + NEWMAT::FFT2(*realIn, *imgIn, *realOut, *imgOut); + bandReal = (ossim_float64*)output->getBuf(2*bandIdx); + bandImg = (ossim_float64*)output->getBuf(2*bandIdx + 1); + if(bandReal&&bandImg) + { + for(y = 0; y < h; ++y) + { + for(x = 0; x < w; ++x) + { + *bandReal = (ossim_float64)((*realOut)[y][x]); + *bandImg = (ossim_float64)((*imgOut)[y][x]); + ++bandReal; + ++bandImg; + } + } + } + } + } + else + { + ossim_float64* bandReal = 0; + ossim_uint32 bands = input->getNumberOfBands(); + for(bandIdx = 0; bandIdx < bands; bandIdx+=2) + { + bandReal = (ossim_float64*)output->getBuf(bandIdx/2); + if(input->getBuf(bandIdx)&& + input->getBuf(bandIdx+1)) + { + fillMatrixInverse((T*)input->getBuf(bandIdx), + (T*)input->getBuf(bandIdx+1), + *realIn, + *imgIn); + NEWMAT::FFT2I(*realIn, *imgIn, *realOut, *imgOut); + for(y = 0; y < h; ++y) + { + for(x = 0; x < w; ++x) + { + *bandReal = (ossim_float64)((*realOut)[y][x]); + if(*bandReal > 1.0) + { + *bandReal = 1.0; + } + if(*bandReal < 0.0) + { + *bandReal = 0.0; + } + ++bandReal; + } + } + } + } + } + + delete realIn; + delete imgIn; + delete realOut; + delete imgOut; +} + +template <class T> +void ossimFftFilter::fillMatrixForward(T *realPart, + T nullPix, + NEWMAT::Matrix& real, + NEWMAT::Matrix& img)const +{ + ossim_uint32 w = real.Ncols(); + ossim_uint32 h = real.Nrows(); + ossim_uint32 yIdx = 0; + ossim_uint32 xIdx = 0; + + for(yIdx = 0; yIdx < h; ++yIdx) + { + for(xIdx = 0; xIdx < w; ++xIdx) + { + if((double)(*realPart) != nullPix) + { + real[yIdx][xIdx] = (double)(*realPart); + } + else + { + real[yIdx][xIdx] = 0.0; + } + + img[yIdx][xIdx] = 0.0; + + ++realPart; + } + } +} + +template <class T> +void ossimFftFilter::fillMatrixInverse(T *realPart, + T *imgPart, + NEWMAT::Matrix& real, + NEWMAT::Matrix& img)const +{ + ossim_uint32 w = real.Ncols(); + ossim_uint32 h = real.Nrows(); + ossim_uint32 yIdx = 0; + ossim_uint32 xIdx = 0; + + for(yIdx = 0; yIdx < h; ++yIdx) + { + for(xIdx = 0; xIdx < w; ++xIdx) + { + real[yIdx][xIdx] = (double)(*realPart); + img[yIdx][xIdx] = (double)(*imgPart); + + ++realPart; + ++imgPart; + } + } +} + + +bool ossimFftFilter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* direction = kwl.find(prefix, "fft_direction"); + if(direction) + { + setDirectionType(ossimString(direction)); + } + + return ossimImageSourceFilter::loadState(kwl, prefix); +} + +bool ossimFftFilter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + "fft_direction", + getDirectionTypeAsString(), + true); + + return ossimImageSourceFilter::saveState(kwl, prefix); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimFftFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimFftFilter.h new file mode 100644 index 0000000000..006f591004 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimFftFilter.h @@ -0,0 +1,86 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimFftFilter.h,v 1.3 2005/02/11 15:07:33 dburken Exp $ +#ifndef ossimFftFilter_HEADER +#define ossimFftFilter_HEADER +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +class ossimScalarRemapper; + +class ossimFftFilter : public ossimImageSourceFilter +{ +public: + enum ossimFftFilterDirectionType + { + ossimFftFilterDirectionType_FORWARD = 0, + ossimFftFilterDirectionType_INVERSE + }; + ossimFftFilter(ossimObject* owner=NULL); + ossimFftFilter(ossimImageSource* inputSource); + ossimFftFilter(ossimObject* owner, + ossimImageSource* inputSource); + virtual ~ossimFftFilter(); + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect, + ossim_uint32 resLevel=0); + virtual void initialize(); + virtual ossim_uint32 getNumberOfOutputBands() const; + virtual double getMinPixelValue(ossim_uint32 band=0)const; + /*! + * Returns the max pixel of the band. + */ + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + /*! + * Each band has a null pixel associated with it. The null pixel + * represents an invalid value. + */ + virtual double getNullPixelValue(ossim_uint32 band=0)const; + + virtual ossimScalarType ossimFftFilter::getOutputScalarType() const; + + void setForward(); + void setInverse(); + ossimString getDirectionTypeAsString()const; + void setDirectionType(const ossimString& directionType); + void setDirectionType(ossimFftFilterDirectionType directionType); + + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix = 0); + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix = 0)const; +protected: + ossimRefPtr<ossimImageData> theTile; + ossimFftFilterDirectionType theDirectionType; + ossimScalarRemapper* theScalarRemapper; + template <class T> + void runFft(T dummy, + ossimRefPtr<ossimImageData>& input, + ossimRefPtr<ossimImageData>& output); + + template <class T> + void fillMatrixForward(T *realPart, + T nullPix, + NEWMAT::Matrix& real, + NEWMAT::Matrix& img)const; + template <class T> + void fillMatrixInverse(T *realPart, + T *imgPart, + NEWMAT::Matrix& real, + NEWMAT::Matrix& img)const; + + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimFusionCombiner.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimFusionCombiner.cpp new file mode 100644 index 0000000000..ccbabbef9a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimFusionCombiner.cpp @@ -0,0 +1,191 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: Garrett Potts +// +// Description: implementation for base fusion +// +//************************************************************************* +// $Id: ossimFusionCombiner.cpp,v 1.10 2005/12/08 21:12:10 dburken Exp $ + +#include <imaging/tile_sources/ossimFusionCombiner.h> +#include <imaging/factory/ossimImageDataFactory.h> +RTTI_DEF1(ossimFusionCombiner, "ossimFusionCombiner", ossimImageCombiner); + +ossimFusionCombiner::ossimFusionCombiner() + :ossimImageCombiner(NULL, 2, 0, true, false), + theTile(NULL), + theNormTile(NULL), + theNormIntensity(NULL), + theInputConnection(NULL), + theIntensityConnection(NULL) +{ +} + +ossimFusionCombiner::ossimFusionCombiner(ossimObject* owner) + :ossimImageCombiner(owner, 2, 0, true, false), + theTile(NULL), + theNormTile(NULL), + theNormIntensity(NULL), + theInputConnection(NULL), + theIntensityConnection(NULL) +{} + +ossimFusionCombiner::~ossimFusionCombiner() +{ + theInputConnection = NULL; + theIntensityConnection = NULL; +} + +ossimIrect ossimFusionCombiner::getBoundingRect(ossim_uint32 resLevel) const +{ + ossimIrect result; + result.makeNan(); + if(theIntensityConnection) + { + result = theIntensityConnection->getBoundingRect(resLevel); + } + else if(theInputConnection) + { + result = theInputConnection->getBoundingRect(resLevel); + } + + return result; +} + +bool ossimFusionCombiner::canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const +{ + return ((inputIndex<2)&& + (PTR_CAST(ossimImageSourceInterface, object)||!object)); +} + +ossimScalarType ossimFusionCombiner::getOutputScalarType() const +{ + if(theInputConnection) + { + return theInputConnection->getOutputScalarType(); + } + + return ossimImageCombiner::getOutputScalarType(); +} + + +ossimRefPtr<ossimImageData> ossimFusionCombiner::getNormIntensity( + const ossimIrect& rect, + ossim_uint32 resLevel) +{ + if(theIntensityConnection) + { + ossimRefPtr<ossimImageData> data = + theIntensityConnection->getTile(rect, resLevel); + if(data.valid() && data->getBuf()) + { + if(!theNormIntensity.valid()) + { + theNormIntensity = new ossimImageData(this, + OSSIM_NORMALIZED_FLOAT, + data->getNumberOfBands(), + rect.width(), + rect.height()); + theNormIntensity->initialize(); + } + + theNormIntensity->setImageRectangleAndBands(rect, + data->getNumberOfBands()); + + data->copyTileToNormalizedBuffer((float*)theNormIntensity->getBuf()); + theNormIntensity->setDataObjectStatus(data->getDataObjectStatus()); + return theNormIntensity; + } + } + return ossimRefPtr<ossimImageData>(); +} + +ossimRefPtr<ossimImageData> ossimFusionCombiner::getNormTile( + const ossimIrect& rect, + ossim_uint32 resLevel) +{ + if(theInputConnection) + { + ossimRefPtr<ossimImageData> data = theInputConnection->getTile(rect, + resLevel); + if(data.valid() && data->getBuf()) + { + // make sure the tile result is updated if changed. + // + if((data->getNumberOfBands() != theTile->getNumberOfBands())|| + (data->getScalarType() != theTile->getScalarType())) + { + theTile = ossimImageDataFactory::instance()->create(this, + theInputConnection); + theTile->initialize(); + } + + if(!theNormTile.valid()) + { + theNormTile = new ossimImageData(this, + OSSIM_NORMALIZED_FLOAT, + data->getNumberOfBands(), + rect.width(), + rect.height()); + theNormTile->initialize(); + } + else if(theNormTile->getNumberOfBands() != data->getNumberOfBands()) + { + theNormTile = new ossimImageData(this, + OSSIM_NORMALIZED_FLOAT, + data->getNumberOfBands(), + rect.width(), + rect.height()); + theNormTile->initialize(); + + } + + theNormTile->setImageRectangleAndBands(rect, + data->getNumberOfBands()); + + data->copyTileToNormalizedBuffer((float*)theNormTile->getBuf()); + theNormTile->setDataObjectStatus(data->getDataObjectStatus()); + return theNormTile; + } + } + return ossimRefPtr<ossimImageData>(); +} + +void ossimFusionCombiner::initialize() +{ + ossimImageCombiner::initialize(); + + theInputConnection = PTR_CAST(ossimImageSourceInterface, getInput(0)); + theIntensityConnection = PTR_CAST(ossimImageSourceInterface, getInput(1)); + + if(getInput(0)&&getInput(1)) + { + ossimImageSourceInterface* temp = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + ossimImageSourceInterface* temp2 = PTR_CAST(ossimImageSourceInterface, + getInput(1)); + + if(temp&&temp2) + { + if((temp->getNumberOfOutputBands()==1)&& + (temp2->getNumberOfOutputBands()!=1)) + { + theIntensityConnection = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + theInputConnection = PTR_CAST(ossimImageSourceInterface, + getInput(1)); + } + } + } + + if(theInputConnection) + { + theTile = ossimImageDataFactory::instance()->create(this, + theInputConnection); + theTile->initialize(); + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimFusionCombiner.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimFusionCombiner.h new file mode 100644 index 0000000000..6991c191e5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimFusionCombiner.h @@ -0,0 +1,47 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: Implementation for Base fusion. +// This base class assumes two inputs where the second input is +// the intensity source. +// +//************************************************************************* +// $Id: ossimFusionCombiner.h,v 1.7 2005/02/11 15:07:33 dburken Exp $ +#ifndef ossimFusionCombiner_HEADER +#define ossimFusionCombiner_HEADER + +#include <imaging/tile_sources/ossimImageCombiner.h> + +class OSSIMDLLEXPORT ossimFusionCombiner : public ossimImageCombiner +{ +public: + ossimFusionCombiner(); + ossimFusionCombiner(ossimObject* owner); + virtual ~ossimFusionCombiner(); + virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0) const; + bool canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const; + ossimScalarType getOutputScalarType() const; + + virtual void initialize(); +protected: + ossimRefPtr<ossimImageData> theTile; + ossimRefPtr<ossimImageData> theNormTile; + ossimRefPtr<ossimImageData> theNormIntensity; + ossimImageSourceInterface* theInputConnection; + ossimImageSourceInterface* theIntensityConnection; + + ossimRefPtr<ossimImageData> getNormIntensity(const ossimIrect& rect, + ossim_uint32 resLevel); + ossimRefPtr<ossimImageData> getNormTile(const ossimIrect& rect, + ossim_uint32 resLevel); +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimGeoPolyCutter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimGeoPolyCutter.cpp new file mode 100644 index 0000000000..c5fa786645 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimGeoPolyCutter.cpp @@ -0,0 +1,353 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//************************************************************************* +// $Id: ossimGeoPolyCutter.cpp,v 1.18 2003/12/01 22:11:37 gpotts Exp $ +#include <algorithm> +#include "ossimGeoPolyCutter.h" +#include "projections/ossimProjection.h" +#include "base/common/ossimCommon.h" +#include "projections/factory/ossimProjectionFactoryRegistry.h" + +static const char* NUMBER_POLYGONS_KW = "number_polygons"; + +RTTI_DEF2(ossimGeoPolyCutter, "ossimGeoPolyCutter", ossimPolyCutter, ossimViewInterface) + +ossimGeoPolyCutter::ossimGeoPolyCutter() + : ossimPolyCutter(), + ossimViewInterface(NULL) +{ + ossimViewInterface::theObject = this; + theGeoPolygonList.push_back(ossimGeoPolygon()); + theViewProjection = NULL; + theOwnsViewFlag = false; +} + +ossimGeoPolyCutter::~ossimGeoPolyCutter() +{ + if(theOwnsViewFlag && theViewProjection) + { + delete theViewProjection; + + theViewProjection = NULL; + theOwnsViewFlag = false; + } +} + +bool ossimGeoPolyCutter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimString newPrefix = prefix; + + for(int i = 0; i < (int)thePolygonList.size();++i) + { + newPrefix = ossimString(prefix) + "geo_polygon" + ossimString::toString(i)+"."; + + theGeoPolygonList[i].saveState(kwl, newPrefix.c_str()); + } + kwl.add(prefix, + NUMBER_POLYGONS_KW, + (int)theGeoPolygonList.size(), + true); + + ossimString fillType = "null_inside"; + if(theCutType == OSSIM_POLY_NULL_OUTSIDE) + { + fillType = "null_outside"; + } + kwl.add(prefix, + "cut_type", + fillType.c_str(), + true); + + if(theViewProjection) + { + ossimString viewPrefix = prefix; + viewPrefix += "view."; + + theViewProjection->saveState(kwl, viewPrefix.c_str()); + } + + return ossimImageSourceFilter::saveState(kwl, prefix);; +} + +bool ossimGeoPolyCutter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimString copyPrefix(prefix); + ossimString polygons = ossimString("^(") + copyPrefix + "geo_polygon[0-9]+.)"; + vector<ossimString> keys = + kwl.getSubstringKeyList( polygons ); + int offset = (copyPrefix+"geo_polygon").size(); + + std::vector<int> numberList(keys.size()); + for(int idx = 0; idx < (int)numberList.size();++idx) + { + ossimString numberStr(keys[idx].begin() + offset, + keys[idx].end()); + numberList[idx] = numberStr.toInt(); + } + std::sort(numberList.begin(), numberList.end()); + + ossimString newPrefix; + thePolygonList.clear(); + for(int i = 0; i < (int)numberList.size();++i) + { + theGeoPolygonList.push_back(ossimGeoPolygon()); + newPrefix = copyPrefix+"geo_polygon"+ossimString::toString(numberList[i])+"."; + theGeoPolygonList[i].loadState(kwl, newPrefix.c_str()); + } + + const char* lookup = kwl.find(prefix, + "cut_type"); + if(lookup) + { + theCutType = OSSIM_POLY_NULL_INSIDE; + ossimString test = lookup; + if(test == "null_outside") + { + theCutType = OSSIM_POLY_NULL_OUTSIDE; + } + } + else + { + theCutType = OSSIM_POLY_NULL_OUTSIDE; + } + + ossimString viewPrefix = prefix; + viewPrefix += "view."; + ossimProjection* proj = ossimProjectionFactoryRegistry::instance()->createProjection(kwl, + viewPrefix); + if(proj) + { + if(theViewProjection&&theOwnsViewFlag) + { + delete theViewProjection; + } + theViewProjection = proj; + theOwnsViewFlag = true; + } + + transformVertices(); + return ossimImageSourceFilter::loadState(kwl, prefix); +} + + +void ossimGeoPolyCutter::setPolygon(const vector<ossimDpt>& polygon, + ossim_uint32 index) +{ + if(theViewProjection) + { + ossimPolyCutter::setPolygon(polygon); + invertPolygon(index); + } +} + +void ossimGeoPolyCutter::setPolygon(const vector<ossimIpt>& polygon, + ossim_uint32 index) +{ + if(theViewProjection) + { + ossimPolyCutter::setPolygon(polygon); + invertPolygon(index); + } +} + +void ossimGeoPolyCutter::setPolygon(const vector<ossimGpt>& polygon, + ossim_uint32 i) +{ + if(i < theGeoPolygonList.size()) + { + theGeoPolygonList[i] = polygon; + + transformVertices(i); + } +} + +void ossimGeoPolyCutter::setPolygon(const ossimGeoPolygon& polygon, + ossim_uint32 i) +{ + if(i < theGeoPolygonList.size()) + { + theGeoPolygonList[i] = polygon.getVertexList(); + + transformVertices(i); + } +} + + +void ossimGeoPolyCutter::addPolygon(const vector<ossimGpt>& polygon) +{ + theGeoPolygonList.push_back(polygon); + thePolygonList.push_back(ossimPolygon()); + + if(theViewProjection) + { + transformVertices(((int)theGeoPolygonList.size())-1); + } +} + +void ossimGeoPolyCutter::addPolygon(const vector<ossimIpt>& polygon) +{ + if(theViewProjection) + { + ossimPolyCutter::addPolygon(polygon); + theGeoPolygonList.push_back(ossimGeoPolygon()); + invertPolygon(thePolygonList.size()-1); + } +} + +void ossimGeoPolyCutter::addPolygon(const vector<ossimDpt>& polygon) +{ + if(theViewProjection) + { + ossimPolyCutter::addPolygon(polygon); + theGeoPolygonList.push_back(ossimGeoPolygon()); + invertPolygon(thePolygonList.size()-1); + } +} + +void ossimGeoPolyCutter::addPolygon(const ossimPolygon& polygon) +{ + if(theViewProjection) + { + ossimPolyCutter::addPolygon(polygon); + theGeoPolygonList.push_back(ossimGeoPolygon()); + invertPolygon(thePolygonList.size()-1); + } +} + +void ossimGeoPolyCutter::addPolygon(const ossimGeoPolygon& polygon) +{ + ossimPolyCutter::addPolygon(ossimPolygon()); + theGeoPolygonList.push_back(polygon); + + if(theViewProjection) + { + transformVertices(((int)theGeoPolygonList.size())-1); + } +} + +void ossimGeoPolyCutter::invertPolygon(int polygonNumber) +{ + if(!theViewProjection) return; + + + ossimPolygon& poly = thePolygonList[polygonNumber]; + ossimGeoPolygon& gpoly = theGeoPolygonList[polygonNumber]; + + gpoly.clear(); + gpoly.resize(poly.getVertexCount()); + int j = 0; + for(j = 0; j < (int)poly.getVertexCount(); ++j) + { + theViewProjection->lineSampleToWorld(poly[j], gpoly[j]); + } +} + +bool ossimGeoPolyCutter::setView(ossimObject* baseObject, + bool ownsTheView) +{ + if(PTR_CAST(ossimProjection, baseObject)) + { + if(theViewProjection && theOwnsViewFlag) + { + delete theViewProjection; + } + theViewProjection = PTR_CAST(ossimProjection, baseObject); + theOwnsViewFlag = ownsTheView; + + transformVertices(); + + return true; + } + + return false; +} + +ossimObject* ossimGeoPolyCutter::getView() +{ + return theViewProjection; +} + +const ossimObject* ossimGeoPolyCutter::getView()const +{ + return theViewProjection; +} + +void ossimGeoPolyCutter::transformVertices() +{ + if(!theViewProjection) return; + + if(theGeoPolygonList.size()) + { + if(theGeoPolygonList.size() != thePolygonList.size()) + { + thePolygonList.resize(theGeoPolygonList.size()); + } + int i = 0; + int j = 0; + for(i = 0; i < (int)theGeoPolygonList.size(); ++i) + { + ossimGeoPolygon& gpoly = theGeoPolygonList[i]; + ossimPolygon& poly = thePolygonList[i]; + int nvert = (int)gpoly.size(); + if((int)poly.getVertexCount() != nvert) + { + poly.resize(nvert); + } + for(j = 0; j < nvert; ++j) + { +// ossimDpt error; + theViewProjection->worldToLineSample(gpoly[j], poly[j]); +// theViewProjection->getRoundTripError(ossimIpt(poly[j]), error); +// poly[j] = poly[j] + error; + poly[j] = ossimDpt(irint(poly[j].x), + irint(poly[j].y)); + } + } + computeBoundingRect(); + } +} + +void ossimGeoPolyCutter::transformVertices(int i) +{ + if(!theViewProjection) return; + + ossimGeoPolygon& gpoly = theGeoPolygonList[i]; + ossimPolygon& poly = thePolygonList[i]; + int nvert = (int)gpoly.size(); + if((int)poly.getVertexCount() != nvert) + { + poly.resize(nvert); + } + int j = 0; + for(j = 0; j < nvert; ++j) + { +// ossimDpt error; + theViewProjection->worldToLineSample(gpoly[j], poly[j]); +// theViewProjection->getRoundTripError(poly[j], error); +// poly[j] = poly[j] + error; + poly[j] = ossimDpt(irint(poly[j].x), + irint(poly[j].y)); + } + + computeBoundingRect(); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimGeoPolyCutter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimGeoPolyCutter.h new file mode 100644 index 0000000000..0e868c64d6 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimGeoPolyCutter.h @@ -0,0 +1,251 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossimGeoPolyCutter.h,v 1.6 2006/01/03 20:47:12 gpotts Exp $ +#ifndef ossimGeoPolyCutter_HEADER +#define ossimGeoPolyCutter_HEADER +#include "ossimPolyCutter.h" +#include "base/common/ossimViewInterface.h" +#include "base/data_types/ossimGeoPolygon.h" +#include <vector> + +class ossimImageData; +class ossimProjection; + +/*! + * ossimGeoPolyCutter. + * + * This classes overrides the 2-d counter part ossimPolyCutter. It will automatically + * map 2-D to 3-D (ground) polygons if you add 2-D polygons and will automatically + * compute the forward transform when adding a ground polygon. + * + * you can set the view trough the ossimViewInterface by calling setView(object, true); + * it will cast to an ossimProjection and use that as the transformation. For igen this is + * set automatically and does not need to be set by the user. + * + * This class has no keywords but does use 2 prefix values to store out the view + * and the ground polygon for example if we have only one polygon then here is a sample + * keyword list for the polygons: NOTE we can have any number of polygons just increment + * the geo_polygon0 to geo_polygon1 .. geo_polygonN for the Nth one + * + * <pre> + * + * geo_polygon0.datum: WGE + * geo_polygon0.number_vertices: 18 + * geo_polygon0.type: ossimGeoPolygon + * geo_polygon0.v0: 38.023634368488452 -122.542245818545709 nan + * geo_polygon0.v1: 38.016619667868909 -122.548990722987568 nan + * geo_polygon0.v2: 38.018238444934966 -122.546292761210807 nan + * geo_polygon0.v3: 38.012932453440698 -122.547911538276864 nan + * geo_polygon0.v4: 38.014731094625191 -122.542065954427244 nan + * geo_polygon0.v5: 38.007446597827986 -122.541796158249582 nan + * geo_polygon0.v6: 38.009694899308606 -122.537569351466018 nan + * geo_polygon0.v7: 38.005108364288141 -122.537119691169892 nan + * geo_polygon0.v8: 38.008255986361007 -122.532353292030976 nan + * geo_polygon0.v9: 38.003039926925965 -122.531274107320272 nan + * geo_polygon0.v10: 38.013292181677599 -122.529565398195004 nan + * geo_polygon0.v11: 38.009874763427050 -122.526867436418243 nan + * geo_polygon0.v12: 38.019587425823332 -122.528306349365849 nan + * geo_polygon0.v13: 38.023904164666128 -122.537299555288328 nan + * geo_polygon0.v14: 38.024983349376825 -122.544584052085540 nan + * geo_polygon0.v15: 38.023904164666128 -122.548720926809878 nan + * geo_polygon0.v16: 38.022195455540853 -122.562210735693611 nan + * geo_polygon0.v17: 38.019317629645663 -122.562930192167400 nan + * + * + * the example for the view information is + * + * view.central_meridian: -123.000000000000000 + * view.datum: WGE + * view.decimal_degrees_per_pixel_lat: 0.000089932059225 + * view.decimal_degrees_per_pixel_lon: 0.000089932059225 + * view.ellipse_code: WE + * view.ellipse_name: WGS 84 + * view.false_easting: 0.000000000000000 + * view.false_northing: 0.000000000000000 + * view.major_axis: 6378137.000000000000000 + * view.meters_per_pixel_x: 10.000000000000000 + * view.meters_per_pixel_y: 10.000000000000000 + * view.minor_axis: 6356752.314199999906123 + * view.origin_latitude: 0.000000000000000 + * view.rotation: 0.000000000000000 + * view.scale_x: 1.000000000000000 + * view.scale_y: 1.000000000000000 + * view.tie_point_easting: 0.000000000000000 + * view.tie_point_lat: 0.000000000000000 + * view.tie_point_lon: -123.000000000000000 + * view.tie_point_northing: 0.000000000000000 + * view.translation_x: 0.000000000000000 + * view.translation_y: 0.000000000000000 + * view.type: ossimEquDistCylProjection + * + * </pre> + */ +class OSSIM_DLL ossimGeoPolyCutter : public ossimPolyCutter, + public ossimViewInterface +{ +public: + ossimGeoPolyCutter(); + virtual ~ossimGeoPolyCutter(); + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /*! + * Sets the polygon to the specified polygon index. + * /param polygon A vector of points in projected 2-D. + * /param i index of the polygon to change. + */ + virtual void setPolygon(const vector<ossimDpt>& polygon, + ossim_uint32 i = 0); + + /*! + * Sets the polygon to the specified polygon index. + * /param polygon A vector of points in projected 2-D. + * /param i index of the polygon to change. + */ + virtual void setPolygon(const vector<ossimIpt>& polygon, + ossim_uint32 i = 0); + + /*! + * Sets the polygon to the specified polygon index. + * /param polygon A Ground polygon. + * /param i index of the polygon to change. + */ + virtual void setPolygon(const vector<ossimGpt>& polygon, + ossim_uint32 i = 0); + + virtual void setPolygon(const ossimGeoPolygon& polygon, + ossim_uint32 i = 0); + /*! + * Will invert this polygon out to world space and add it to the + * polygon list + */ + virtual void addPolygon(const vector<ossimIpt>& polygon); + + /*! + * Will invert the passed in polygon to world space and add to the + * polygon list + */ + virtual void addPolygon(const vector<ossimDpt>& polygon); + + /*! + * Will add the ground polygon to the list + */ + virtual void addPolygon(const vector<ossimGpt>& polygon); + + /*! + * Will invert te polygon to ground and add. + */ + virtual void addPolygon(const ossimPolygon& polygon); + + /*! + * Will add the passed in polygon. + */ + virtual void addPolygon(const ossimGeoPolygon& polygon); + + /*! + * Will set the number of polygons and will call the base + * class set number of polygons. + */ + virtual void setNumberOfPolygons(ossim_uint32 count) + { + if(!count) + { + theGeoPolygonList.clear(); + } + else + { + theGeoPolygonList.resize(count); + } + ossimPolyCutter::setNumberOfPolygons(count); + } + /*! + * This should only be used for informational uses only. If updates + * are to be made please go through the access methods that change + * the polygon data. + */ + virtual std::vector<ossimGeoPolygon>& getGeoPolygonList() + { + return theGeoPolygonList; + } + virtual const std::vector<ossimGeoPolygon>& getGeoPolygonList()const + { + return theGeoPolygonList; + } + + /*! + * Will set the view to the passed in object. Once set it will project the + * ground polygon relative to the passed in view. + */ + virtual bool setView(ossimObject* baseObject, + bool ownsTheView = false); + + /*! + * \return The current view for this object. + */ + virtual ossimObject* getView(); + + /*! + * \return The constant pointer to the current view for this object. + */ + virtual const ossimObject* getView()const; + +protected: + /*! + * The view projection used to project the ground coordinates. + */ + ossimProjection* theViewProjection; + + /*! + * Specifies whether the view is owned by this object or not. + */ + bool theOwnsViewFlag; + + std::vector<ossimGeoPolygon> theGeoPolygonList; + + /*! + * Utility method used to invert any passed in projected polygons to + * be changed or added to the list. + * \param polygonNumber the index of the polygon to invert to ground. + */ + void invertPolygon(int polygonNumber); + + /*! + * Transforms all vertices based on the current theViewProjection. + */ + void transformVertices(); + + /*! + * Transforms the specified polygon index. + * \param i The polygon index to project. + */ + void transformVertices(int i); + +TYPE_DATA +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistoMatchRemapper.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistoMatchRemapper.cpp new file mode 100644 index 0000000000..39adc99724 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistoMatchRemapper.cpp @@ -0,0 +1,349 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimHistoMatchRemapper.cpp,v 1.11 2005/02/11 15:07:33 dburken Exp $ +#include <imaging/tile_sources/ossimHistoMatchRemapper.h> +#include <imaging/ossimImageData.h> +#include <imaging/ossimImageSource.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimKeywordlist.h> + +ossimHistoMatchRemapper::ossimHistoMatchRemapper() + : ossimImageSourceFilter() +{ + theBlankTile = NULL; +} + +ossimHistoMatchRemapper::ossimHistoMatchRemapper(ossimImageSource* inputSource, + const vector<double>& targetMeanPerBand, + const vector<double>& targetSigmaPerBand, + const vector<double>& inputMeanPerBand, + const vector<double>& inputSigmaPerBand) + : ossimImageSourceFilter(inputSource), + theTargetMeanPerBand(targetMeanPerBand), + theTargetSigmaPerBand(targetSigmaPerBand), + theInputMeanPerBand(inputMeanPerBand), + theInputSigmaPerBand(inputSigmaPerBand) +{ + theBlankTile = NULL; +} + + +ossimHistoMatchRemapper::~ossimHistoMatchRemapper() +{ +} + +ossimRefPtr<ossimImageData> ossimHistoMatchRemapper::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + ossimRefPtr<ossimImageData> tile; + if(theInputConnection) + { + tile = theInputConnection->getTile(tileRect, resLevel); + } + if(!tile.valid()) + { + return NULL; + } + if((tile.valid() && + ((tile->getDataObjectStatus()==OSSIM_NULL) || + (tile->getDataObjectStatus()==OSSIM_EMPTY)))) + + { + return tile; + } + + theBlankTile->setOrigin(tileRect.ul()); + ossim_uint32 numberOfBands = theInputMeanPerBand.size(); + + numberOfBands = numberOfBands>tile->getNumberOfBands()?tile->getNumberOfBands():numberOfBands; + double result = 0; + if(isSourceEnabled()) + { + long offsetBound = (long)(tile->getWidth()*tile->getHeight()); + if(tile->getScalarType() == OSSIM_UCHAR) + { + for(ossim_uint32 band = 0; band < numberOfBands; ++band) + { + unsigned char* buf = static_cast<unsigned char*>(tile->getBuf(band)); + for(long offset=0; offset < offsetBound;++offset) + { + // if the input has no deviation we will just + // do a shift to the target mean + if(fabs(theInputSigmaPerBand[band]) < FLT_EPSILON) + { + result = transLean(buf[offset], + theInputMeanPerBand[band], + theTargetMeanPerBand[band], + 0, + 255); + } + else + { + result = transLeanStretch(buf[offset], + theInputMeanPerBand[band], + theInputSigmaPerBand[band], + theTargetMeanPerBand[band], + theTargetSigmaPerBand[band], + 0, + 255); + } + result = ((result>255)?255:result); + result = ((result<0)?0:result); + + buf[offset] = (unsigned char)result; + } + } + } + } + + return tile; +} + +void ossimHistoMatchRemapper::initialize() +{ + if(!theInputConnection) + { + return; + } + theBlankTile = new ossimImageData(this, + theInputConnection->getOutputScalarType(), + theInputConnection->getNumberOfOutputBands()); +} + +const vector<double>& ossimHistoMatchRemapper::getInputMeanValues()const +{ + return theInputMeanPerBand; +} + +const vector<double>& ossimHistoMatchRemapper::getInputSigmaValues()const +{ + return theInputSigmaPerBand; +} + +const vector<double>& ossimHistoMatchRemapper::getTargetMeanValues()const +{ + return theTargetMeanPerBand; +} + +const vector<double>& ossimHistoMatchRemapper::getTargetSigmaValues()const +{ + return theTargetSigmaPerBand; +} + +void ossimHistoMatchRemapper::setInputMeanValues(const vector<double>& newValues) +{ + theInputMeanPerBand = newValues; +} + +void ossimHistoMatchRemapper::setInputSigmaValues(const vector<double>& newValues) +{ + theInputSigmaPerBand = newValues; +} + +void ossimHistoMatchRemapper::setTargetMeanValues(const vector<double>& newValues) +{ + theTargetMeanPerBand = newValues; +} + +void ossimHistoMatchRemapper::setTargetSigmaValues(const vector<double>& newValues) +{ + theTargetSigmaPerBand = newValues; +} + +double ossimHistoMatchRemapper::transLean // returns vOut +( + double vIn //!< input value to be transformed + , double vBias //!< bias value to be removed + , double vTarget //!< value that will replace bias + , double vMin //!< minimum valid value of vIn (inclusive) + , double vMax //!< maximum valid value of vIn (inclusive) +) +{ + // max change + const double vDelta = vTarget - vBias; + double weight=0.0; + + // weight max change dependend on proximity to end points + if (vIn <= vBias) + { + weight = fabs((vIn - vMin) / (vBias - vMin)); + } + else + { + weight = fabs((vMax - vIn) / (vMax - vBias)); + } + return (vIn + (vDelta * weight)); +}; + +double ossimHistoMatchRemapper::transLeanStretch // returns vOut + ( + double vIn //!< input value to be transformed + , double vBias //!< bias value to be removed + , double vBiasStretch //!< dispersion (+/-) about vBias + , double vTarget //!< value that will replace bias + , double vTargetStretch //!< dispersion (+/-) about vTarget + , double vMin //!< minimum valid value of vIn (inclusive) + , double vMax //!< maximum valid value of vIn (inclusive) + ) +{ + + // line segment end points + const double x1 = vMin; + const double x2 = vBias - vBiasStretch; + const double x3 = vBias + vBiasStretch; + const double x4 = vMax; + const double y1 = 0.0; + const double y2 = (vTarget + vTargetStretch) - (vBias + vBiasStretch); + const double y3 = (vTarget - vTargetStretch) - (vBias - vBiasStretch); + const double y4 = 0.0; + + + // perform appropriate linear lookup operation based on input value + double vOut = vIn; + if (vIn <= x2) + { + vOut = (vIn - x1) * (y2-y1)/(x2-x1) + y1 + vIn; + } + else + if (vIn <= x3) + { + vOut = (vIn - x2) * (y3-y2)/(x3-x2) + y2 + vIn; + } + else + { + vOut = (vIn - x3) * (y4-y3)/(x4-x3) + y3 + vIn; + } + + return vOut; +} + +bool ossimHistoMatchRemapper::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + theTargetMeanPerBand.clear(); + theTargetSigmaPerBand.clear(); + theInputMeanPerBand.clear(); + theInputSigmaPerBand.clear(); + long result = kwl.getNumberOfSubstringKeys(ossimString(prefix) + "target_mean[0-9]"); + ossim_uint32 numberOfMatches=0; + long index=0; + + // load target mean + while(numberOfMatches < static_cast<ossim_uint32>(result)) + { + ossimString key = prefix; + key += ossimString("target_mean"); + key += ossimString::toString(index); + const char* lookup = kwl.find(key.c_str()); + if(lookup) + { + theTargetMeanPerBand.push_back(ossimString(lookup).toDouble()); + ++numberOfMatches; + } + ++index; + } + numberOfMatches = 0; + index = 0; + result = kwl.getNumberOfSubstringKeys(ossimString(prefix) + "target_sigma[0-9]"); + // load target sigma + while(numberOfMatches < static_cast<ossim_uint32>(result)) + { + ossimString key = prefix; + key += ossimString("target_sigma"); + key += ossimString::toString(index); + const char* lookup = kwl.find(key.c_str()); + if(lookup) + { + theTargetSigmaPerBand.push_back(ossimString(lookup).toDouble()); + ++numberOfMatches; + } + ++index; + } + + numberOfMatches = 0; + index = 0; + result = kwl.getNumberOfSubstringKeys(ossimString(prefix) + "input_mean[0-9]"); + // load input mean + while(numberOfMatches < static_cast<ossim_uint32>(result)) + { + ossimString key = prefix; + key += ossimString("input_mean"); + key += ossimString::toString(index); + const char* lookup = kwl.find(key.c_str()); + if(lookup) + { + theInputMeanPerBand.push_back(ossimString(lookup).toDouble()); + ++numberOfMatches; + } + ++index; + } + + numberOfMatches = 0; + index = 0; + result = kwl.getNumberOfSubstringKeys(ossimString(prefix) + "input_sigma[0-9]"); + // load input sigma + while(numberOfMatches < static_cast<ossim_uint32>(result)) + { + ossimString key = prefix; + key += ossimString("input_sigma"); + key += ossimString::toString(index); + const char* lookup = kwl.find(key.c_str()); + if(lookup) + { + theInputSigmaPerBand.push_back(ossimString(lookup).toDouble()); + ++numberOfMatches; + } + ++index; + } + + return true; +} + +bool ossimHistoMatchRemapper::saveState(ossimKeywordlist& kwl, + const char* prefix) +{ + long index = 1; + for(index=1;index <= (long)theTargetMeanPerBand.size();++index) + { + ossimString key = ossimString("target_mean") + ossimString::toString(index); + kwl.add(prefix, + key.c_str(), + theTargetMeanPerBand[index-1], + true); + } + for(index=1;index <= (long)theTargetSigmaPerBand.size();++index) + { + ossimString key = ossimString("target_sigma") + ossimString::toString(index); + kwl.add(prefix, + key.c_str(), + theTargetSigmaPerBand[index-1], + true); + } + for(index=1;index <= (long)theInputMeanPerBand.size();++index) + { + ossimString key = ossimString("input_mean") + ossimString::toString(index); + kwl.add(prefix, + key.c_str(), + theInputMeanPerBand[index-1], + true); + } + for(index=1;index <= (long)theInputSigmaPerBand.size();++index) + { + ossimString key = ossimString("input_sigma") + ossimString::toString(index); + kwl.add(prefix, + key.c_str(), + theInputSigmaPerBand[index-1], + true); + } + return true; +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistoMatchRemapper.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistoMatchRemapper.h new file mode 100644 index 0000000000..e0270dedf3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistoMatchRemapper.h @@ -0,0 +1,95 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimHistoMatchRemapper.h,v 1.8 2005/02/11 15:07:33 dburken Exp $ +#ifndef ossimHistoMatchRemapper_HEADER +#define ossimHistoMatchRemapper_HEADER +#include <vector> +using namespace std; + +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +class ossimHistoMatchRemapper: public ossimImageSourceFilter +{ +public: + ossimHistoMatchRemapper(); + ossimHistoMatchRemapper(ossimImageSource* inputSource, + const vector<double>& targetMeanPerBand = vector<double>(), + const vector<double>& targetSigmaPerBand = vector<double>(), + const vector<double>& inputMeanPerBand = vector<double>(), + const vector<double>& inputSigmaPerBand = vector<double>() + ); + virtual ~ossimHistoMatchRemapper(); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + virtual void initialize(); + + const vector<double>& getInputMeanValues()const; + const vector<double>& getInputSigmaValues()const; + const vector<double>& getTargetMeanValues()const; + const vector<double>& getTargetSigmaValues()const; + + void setInputMeanValues(const vector<double>& newValues); + void setInputSigmaValues(const vector<double>& newValues); + void setTargetMeanValues(const vector<double>& newValues); + void setTargetSigmaValues(const vector<double>& newValues); + + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=NULL); + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=NULL); + +protected: + ossimRefPtr<ossimImageData> theBlankTile; + + vector<double> theTargetMeanPerBand; + vector<double> theTargetSigmaPerBand; + vector<double> theInputMeanPerBand; + vector<double> theInputSigmaPerBand; + + /** + * transLean + * @param vIn input value to be transformed + * @param vBias bias value to be removed + * @param vTarget value that will replace bias + * @param vMin minimum valid value of vIn (inclusive) + * @param vMax maximum valid value of vIn (inclusive) + * @return vOut + */ + double transLean(double vIn, + double vBias, + double vTarget, + double vMin, + double vMax); + + /** + * transLeanStretch + * @param vin Input value to be transformed. + * @param vBias Bias value to be removed. + * @param vBiasStretch dispersion (+/-) about vBias + * @param vTarget value that will replace bias + * @param vTargetStretch dispersion (+/-) about vTarget + * @param vMin minimum valid value of vIn (inclusive) + * @param vMax maximum valid value of vIn (inclusive) + * @return vOut + */ + double transLeanStretch(double vIn, + double vBias, + double vBiasStretch, + double vTarget, + double vTargetStretch, + double vMin, + double vMax); + +}; + +#endif /* #ifndef ossimHistoMatchRemapper_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramEqualization.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramEqualization.cpp new file mode 100644 index 0000000000..ccf576e8ad --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramEqualization.cpp @@ -0,0 +1,537 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimHistogramEqualization.cpp,v 1.45 2005/09/09 11:14:07 gpotts Exp $ +#include <imaging/tile_sources/ossimHistogramEqualization.h> +#include <base/data_types/ossimMultiResLevelHistogram.h> +#include <base/data_types/ossimMultiBandHistogram.h> +#include <base/data_types/ossimHistogram.h> +#include <base/common/ossimCommon.h> +#include <imaging/ossimImageData.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <base/common/ossimTrace.h> +#include <base/data_types/ossimKeyword.h> + +RTTI_DEF1(ossimHistogramEqualization, "ossimHistogramEqualization", ossimImageSourceHistogramFilter) + +static const ossimKeyword HISTOGRAM_INVERSE_FLAG_KW("inverse_flag", + "specifies whether the inverse should be done for the getTile"); + +static ossimTrace traceDebug("ossimHistogramEqualization:debug"); + +ossimHistogramEqualization::ossimHistogramEqualization() + : ossimImageSourceHistogramFilter(), + theTile(NULL), + theAccumulationHistogram(NULL), + theInverseFlag(false) +{ +} + +ossimHistogramEqualization::ossimHistogramEqualization(ossimImageSource* inputSource, + ossimMultiResLevelHistogram* histogram) + : ossimImageSourceHistogramFilter(inputSource, histogram), + theTile(NULL), + theAccumulationHistogram(NULL), + theInverseFlag(false) +{ + if(getHistogram()) + { + theAccumulationHistogram = getHistogram()->createAccumulationLessThanEqual(); + initializeLuts(); + } +} + +ossimHistogramEqualization::ossimHistogramEqualization(ossimImageSource* inputSource, + ossimMultiResLevelHistogram* histogram, + bool inverseFlag) + : ossimImageSourceHistogramFilter(inputSource, histogram), + theTile(NULL), + theAccumulationHistogram(NULL), + theInverseFlag(inverseFlag) +{ + if(getHistogram()) + { + theAccumulationHistogram = getHistogram()->createAccumulationLessThanEqual(); + initializeLuts(); + } +} + +ossimHistogramEqualization::~ossimHistogramEqualization() +{ + if(theAccumulationHistogram) + { + delete theAccumulationHistogram; + theAccumulationHistogram = NULL; + } + deleteLuts(); +} + +ossimRefPtr<ossimImageData> ossimHistogramEqualization::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if(!theInputConnection) + { + return NULL; + } + + ossimRefPtr<ossimImageData> inputTile = theInputConnection->getTile(tileRect, + resLevel); + + if(!inputTile.valid()) return inputTile; + + if (!isSourceEnabled()) + { + return inputTile; + } + + if(!theTile.valid()) + { + allocate(); // First time through... + } + + // if (!theTile) throw exception! + + // Set the origin, resize if needed of the output tile. + theTile->setImageRectangleAndBands(inputTile->getImageRectangle(), + inputTile->getNumberOfBands()); + + if( !inputTile.valid() || + inputTile->getDataObjectStatus() == OSSIM_NULL || + inputTile->getDataObjectStatus() == OSSIM_EMPTY ) + { + return theTile; + } + + if(!theAccumulationHistogram) + { + computeAccumulationHistogram(); + } + if(theForwardLut.size() == 0 || + theInverseLut.size() == 0) + { + initializeLuts(); + } + if((theForwardLut.size() == 0) || + (theInverseLut.size() == 0)) + { + return inputTile; + } + + switch(inputTile->getScalarType()) + { + case OSSIM_UCHAR: + { + return runEqualizationAlgorithm(static_cast<ossim_uint8>(0), + inputTile); + } + case OSSIM_USHORT11: + case OSSIM_UINT16: + { + return runEqualizationAlgorithm(static_cast<ossim_uint16>(0), + inputTile); + } + case OSSIM_SINT16: + { + return runEqualizationAlgorithm(static_cast<ossim_sint16>(0), + inputTile); + } + case OSSIM_UINT32: + { + return runEqualizationAlgorithm(static_cast<ossim_uint32>(0), + inputTile); + } + case OSSIM_SINT32: + { + return runEqualizationAlgorithm(static_cast<ossim_sint32>(0), + inputTile); + } + case OSSIM_FLOAT32: + { + return runEqualizationAlgorithm(static_cast<ossim_float32>(0), + inputTile); + } + case OSSIM_FLOAT64: + { + return runEqualizationAlgorithm(static_cast<ossim_float64>(0), + inputTile); + } + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHistogramEqualization::getTile WARNING: Unsupported scalar type." + << endl; + break; + } + } + + return inputTile; +} + +void ossimHistogramEqualization::setHistogram(ossimMultiResLevelHistogram* histogram) +{ + ossimImageSourceHistogramFilter::setHistogram(histogram); + computeAccumulationHistogram(); + initializeLuts(); +} + +bool ossimHistogramEqualization::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + bool result = ossimImageSourceHistogramFilter::saveState(kwl, prefix); + + kwl.add(prefix, + HISTOGRAM_INVERSE_FLAG_KW, + (long)theInverseFlag, + true); + + return result; +} + +bool ossimHistogramEqualization::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + static const char MODULE[] = "ossimHistogramEqualization::loadState"; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << " Entered..." + << "\nprefix: " << prefix << endl; + } + + const char* lookup = kwl.find(prefix, + HISTOGRAM_INVERSE_FLAG_KW); + if(lookup) + { + theInverseFlag = ossimString(lookup).toBool(); + } + if(ossimImageSourceHistogramFilter::loadState(kwl, prefix)) + { +// computeAccumulationHistogram(); +// initializeLuts(); + } + else + { + return false; + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:" << MODULE; + this->print(ossimNotify(ossimNotifyLevel_DEBUG)); + ossimNotify(ossimNotifyLevel_DEBUG) << "\nExited..." << endl; + } + + return true; +} + +void ossimHistogramEqualization::computeAccumulationHistogram() +{ + if(theAccumulationHistogram) + { + delete theAccumulationHistogram; + theAccumulationHistogram = NULL; + } + + if(getHistogram()) + { + theAccumulationHistogram = getHistogram()->createAccumulationLessThanEqual(); + } +} + +template <class T> +ossimRefPtr<ossimImageData> ossimHistogramEqualization::runEqualizationAlgorithm(T, ossimRefPtr<ossimImageData> tile) +{ + + if(!theAccumulationHistogram || + !getHistogram()) + { + return tile; + } + + // for now we will always pull from res 0 information + ossimMultiBandHistogram* histo = getHistogram()->getMultiBandHistogram(0); + + if(histo) + { + ossim_uint32 maxBands = ( (histo->getNumberOfBands() > + tile->getNumberOfBands())? + tile->getNumberOfBands(): + histo->getNumberOfBands()); + + long offsetUpperBound = tile->getHeight()*tile->getWidth(); + + for(ossim_uint32 band = 0; band < maxBands; ++band) + { + ossimHistogram* bandHisto = histo->getHistogram(band); + T* buf = static_cast<T*>(tile->getBuf(band)); + double *histoLut = band<theForwardLut.size()?theForwardLut[band]:NULL; + ossim_uint32 actualBand = theBandList[band]; + if(bandHisto) + { + if(buf&&histoLut&&(actualBand < histo->getNumberOfBands())) + { + if(theInverseFlag) + { + histoLut = theInverseLut[actualBand]; + } + if(histoLut) + { + if(tile->getDataObjectStatus() == OSSIM_FULL) + { + T minPix = (T)tile->getMinPix(actualBand); + T maxPix = (T)tile->getMaxPix(actualBand); + for(long offset = 0; offset < offsetUpperBound; ++offset) + { + ossim_int32 idx = bandHisto->GetIndex(buf[offset]); + + if(idx>=0) + { + T value = (T)(histoLut[idx]); + buf[offset] = value>maxPix?maxPix:value; + buf[offset] = value<minPix?minPix:value; + } + } + } + else + { + T minPix = (T)tile->getMinPix(actualBand); + T maxPix = (T)tile->getMaxPix(actualBand); + T nullPix = (T)tile->getNullPix(actualBand); + for(long offset = 0; offset < offsetUpperBound; ++offset) + { + ossim_int32 idx = bandHisto->GetIndex(buf[offset]); + + if((buf[offset]!=nullPix)&&(idx>=0)) + { + T value = (T)(histoLut[idx]); + buf[offset] = value>maxPix?maxPix:value; + buf[offset] = value<minPix?minPix:value; + } + else + { + buf[offset] = nullPix; + } + } + } + } + } + } + } + + tile->validate(); + } + + return tile; +} + +void ossimHistogramEqualization::initialize() +{ + // Base class will recapture "theInputConnection". + ossimImageSourceHistogramFilter::initialize(); + if(theTile.valid()) + { + theTile = NULL; + } +} + +void ossimHistogramEqualization::allocate() +{ + theBandList.clear(); + + if(theTile.valid()) + { + theTile = NULL; + } + + if(theInputConnection) + { + theInputConnection->getOutputBandList(theBandList); + theTile = ossimImageDataFactory::instance()->create(this, this); + if(theTile.valid()) + { + theTile->initialize(); + } + } +} + +void ossimHistogramEqualization::initializeLuts() +{ + if(theForwardLut.size() != 0 || + theInverseLut.size() != 0) + { + deleteLuts(); + } + if(!theAccumulationHistogram||!getHistogram()) + { + return; + } + ossimMultiBandHistogram* accumHisto = theAccumulationHistogram->getMultiBandHistogram(0); + ossimMultiBandHistogram* histogram = getHistogram()->getMultiBandHistogram(0); + ossimKeywordlist kwl; + theAccumulationHistogram->saveState(kwl); + + if(accumHisto&&histogram) + { + long maxBands = accumHisto->getNumberOfBands(); + + for(long band = 0; band < maxBands; ++band) + { + // first we grab pointers to the histogram and the accumulation + // histogram + ossimHistogram* h = accumHisto->getHistogram(band); + ossimHistogram* h2 = histogram->getHistogram(band); + + if(h&&h2) + { + // lets get the number of indices. + ossim_uint32 numberOfIndices = (ossim_uint32)h2->GetRes(); + vector<double> countForInverse(numberOfIndices); + + theForwardLut.push_back(new double[numberOfIndices]); + theInverseLut.push_back(new double[numberOfIndices]); + + // let's grab the counts array + const float* histoCounts = h->GetCounts(); + +// double maxIntensity = h2->GetMaxVal(); + double maxIntensity = h2->GetRangeMax(); + double maxCount = h->GetMaxCount(); + + // now pre compute the transforms + double *forwardLut = theForwardLut[band]; + double *inverseLut = theInverseLut[band]; + +// double minIntensity = h2->GetMinVal(); + double minIntensity = h2->GetRangeMin(); + double delta = maxIntensity-minIntensity; + ossim_uint32 idx = 0; + + // clear out the inverse + // + for(idx = 0; idx < numberOfIndices; ++ idx) + { + inverseLut[idx] = OSSIM_DBL_NAN; + } + for(idx = 0; idx < numberOfIndices; ++ idx) + { + forwardLut[idx] = minIntensity + (histoCounts[idx]/maxCount)*delta; + + ossim_int32 inverseIdx = h2->GetIndex(forwardLut[idx]); + if(inverseIdx >= 0) + { + inverseLut[inverseIdx] = minIntensity + delta*(idx/(ossim_float32)numberOfIndices); + } + } + + // now solve the inverse lut + // + ossim_uint32 idxStart = 0; + ossim_uint32 idxEnd = 0; + + while((inverseLut[idxEnd] == OSSIM_DBL_NAN)&&(idxEnd <numberOfIndices)){ ++idxEnd;} + if((idxStart!=idxEnd)&&(idxEnd<numberOfIndices)) + { + std::fill(inverseLut, + inverseLut+idxEnd, + inverseLut[idxEnd]); + } + idxStart = numberOfIndices-1; + while((inverseLut[idxStart] == OSSIM_DBL_NAN)&&(idxStart > 0)){ --idxStart;} + if(idxStart !=0) + { + std::fill(inverseLut+idxStart, + inverseLut+numberOfIndices, + inverseLut[idxStart]); + } + + idxStart = 0; + idxEnd = 0; + ossim_float32 valueStart = 0.0; + ossim_float32 valueEnd = 0.0; + + while(idxStart < numberOfIndices) + { + idxEnd = idxStart; + if(inverseLut[idxStart] == OSSIM_DBL_NAN) + { + while((inverseLut[idxEnd] == OSSIM_DBL_NAN)&&(idxEnd < (numberOfIndices-1))) ++idxEnd; + double length = (idxEnd-idxStart)+1; + valueEnd = inverseLut[idxEnd]; + double deltaVal = (valueEnd-valueStart); + ossim_uint32 tempIdx = idxStart; + ossim_float32 count = 1.0; + double t = 0.0; + while(tempIdx < idxEnd) + { + t = (count/length); + t = t>1.0?1.0:t; + inverseLut[tempIdx] = valueStart + deltaVal*t; + ++count; + ++tempIdx; + } + idxStart = idxEnd; + valueStart = valueEnd; + } + else + { + valueStart = inverseLut[idxStart]; + ++idxStart; + } + } + } + } + } +} + +bool ossimHistogramEqualization::setHistogram(const ossimFilename& filename) +{ + return ossimImageSourceHistogramFilter::setHistogram(filename); +} + +bool ossimHistogramEqualization::getInverseFlag()const +{ + return theInverseFlag; +} + +void ossimHistogramEqualization::setInverseFlag(bool inverseFlag) +{ + theInverseFlag = inverseFlag; +} + +void ossimHistogramEqualization::deleteLuts() +{ + long band = 0; + + for(band = 0; band < (long)theForwardLut.size(); ++band) + { + delete [] theForwardLut[band]; + } + theForwardLut.clear(); + + for(band = 0; band < (long)theInverseLut.size(); ++band) + { + delete [] theInverseLut[band]; + } + + theInverseLut.clear(); +} + +const ossimFilename& ossimImageSourceHistogramFilter::getHistogramFilename() const +{ + return theFilename; +} + +std::ostream& ossimHistogramEqualization::print(std::ostream& out) const +{ + // Base class... + return ossimImageSourceHistogramFilter::print(out); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramEqualization.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramEqualization.h new file mode 100644 index 0000000000..ce10c69677 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramEqualization.h @@ -0,0 +1,99 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimHistogramEqualization.h,v 1.19 2005/09/02 13:31:24 gpotts Exp $ +#ifndef ossimHistogramEqualization_HEADER +#define ossimHistogramEqualization_HEADER +#include <imaging/tile_sources/ossimImageSourceHistogramFilter.h> + +class OSSIMDLLEXPORT ossimHistogramEqualization : public ossimImageSourceHistogramFilter +{ +public: + ossimHistogramEqualization(); + ossimHistogramEqualization(ossimImageSource* inputSource, + ossimMultiResLevelHistogram* histogram); + ossimHistogramEqualization(ossimImageSource* inputSource, + ossimMultiResLevelHistogram* histogram, + bool inverseFlag); + virtual ~ossimHistogramEqualization(); + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + + virtual void setHistogram(ossimMultiResLevelHistogram* histogram); + virtual bool setHistogram(const ossimFilename& filename); + + virtual bool getInverseFlag()const; + virtual void initialize(); + virtual void setInverseFlag(bool inverseFlag); + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=NULL); + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=NULL)const; + + virtual std::ostream& print(std::ostream& out) const; + +protected: + + /** + * Called on first getTile, will initialize all data needed. + */ + void allocate(); + + ossimRefPtr<ossimImageData> theTile; + /*! + * This will be used in some of the histogram + * based operations. + */ + ossimMultiResLevelHistogram* theAccumulationHistogram; + + /*! + * Indicates if you should equalize or unequalize an input stream. + * If the inverse flag is true then it will indicate that we should + * assume that the input stream is already equalized and we should + * invert based on the current accumulation histogram. + * + * + * This flag is defaulted to false. + */ + bool theInverseFlag; + /*! + * We will create a LUT for each band that directly maps + * an input value to an equalized output. + */ + vector<double*> theForwardLut; + + /*! + * We will create a LUT for each band that directly maps + * an input value to an un-equalized output. + */ + vector<double*> theInverseLut; + + + std::vector<ossim_uint32> theBandList; + virtual void computeAccumulationHistogram(); + + template<class T> + ossimRefPtr<ossimImageData> runEqualizationAlgorithm(T dummyVariable, + ossimRefPtr<ossimImageData> tile); + + /*! + * We will pre-compute the luts for the forward and inverse + * equalization. Note: the inverse is a little more tricky + * and since we must fill the empty spots missed by the + * inverse. We use a linear interpolation between valid + * values for this. + */ + virtual void initializeLuts(); + virtual void deleteLuts(); + +TYPE_DATA +}; +#endif /* #ifndef ossimHistogramEqualization_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramMatchFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramMatchFilter.cpp new file mode 100644 index 0000000000..6e81b0e8c7 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramMatchFilter.cpp @@ -0,0 +1,248 @@ +#include "ossimHistogramMatchFilter.h" +#include <base/property/ossimFilenameProperty.h> +#include <base/property/ossimBooleanProperty.h> + +RTTI_DEF1(ossimHistogramMatchFilter, "ossimHistogramMatchFilter", ossimImageSourceFilter); +ossimHistogramMatchFilter::ossimHistogramMatchFilter() + :ossimImageSourceFilter(), + theAutoLoadInputHistogramFlag(false) +{ + theInputHistogramEqualizer = new ossimHistogramEqualization; + theTargetHistogramEqualizer = new ossimHistogramEqualization; + + theInputHistogramEqualizer->setInverseFlag(false); + theTargetHistogramEqualizer->setInverseFlag(true); + theTargetHistogramEqualizer->connectMyInputTo(0, theInputHistogramEqualizer.get()); +} + +ossimRefPtr<ossimImageData> ossimHistogramMatchFilter::getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if(isSourceEnabled()) + { + return theTargetHistogramEqualizer->getTile(tileRect, resLevel); + } + if(theAutoLoadInputHistogramFlag&& + (theInputHistogramFilename=="")) + { + autoLoadInputHistogram(); + } + if(theInputConnection) + { + return theInputConnection->getTile(tileRect, resLevel); + } + + return 0; +} + + +void ossimHistogramMatchFilter::setInputHistogram(const ossimFilename& inputHistogram) +{ + theInputHistogramFilename = inputHistogram; + theInputHistogramEqualizer->setHistogram(inputHistogram); + theInputHistogramEqualizer->initialize(); +} + +void ossimHistogramMatchFilter::setTargetHistogram(const ossimFilename& targetHistogram) +{ + theTargetHistogramFilename = targetHistogram; + theTargetHistogramEqualizer->setHistogram(targetHistogram); + theTargetHistogramEqualizer->initialize(); +} + +void ossimHistogramMatchFilter::connectInputEvent(ossimConnectionEvent& event) +{ + ossimImageSourceFilter::connectInputEvent(event); + if(getInput()) + { + theInputHistogramEqualizer->connectMyInputTo(0, getInput()); + theInputHistogramEqualizer->initialize(); + theTargetHistogramEqualizer->initialize(); + } + else + { + theInputHistogramEqualizer->disconnectMyInput(0, false, false); + theInputHistogramEqualizer->initialize(); + theTargetHistogramEqualizer->initialize(); + } +} + +void ossimHistogramMatchFilter::disconnectInputEvent(ossimConnectionEvent& event) +{ + ossimImageSourceFilter::disconnectInputEvent(event); + if(getInput()) + { + theInputHistogramEqualizer->connectMyInputTo(0, getInput()); + theInputHistogramEqualizer->initialize(); + theTargetHistogramEqualizer->initialize(); + } + else + { + theInputHistogramEqualizer->disconnectMyInput(0, false, false); + theInputHistogramEqualizer->initialize(); + theTargetHistogramEqualizer->initialize(); + } +} + +void ossimHistogramMatchFilter::initialize() +{ + ossimImageSourceFilter::initialize(); + if(theAutoLoadInputHistogramFlag) + { + if(theInputHistogramFilename == "") + { + autoLoadInputHistogram(); + } + } + + theInputHistogramEqualizer->initialize(); + theTargetHistogramEqualizer->initialize(); +} + +void ossimHistogramMatchFilter::setProperty(ossimRefPtr<ossimProperty> property) +{ + if(!property.valid()) return; + + ossimString name = property->getName(); + if(name == "input_histogram_filename") + { + setInputHistogram(ossimFilename(property->valueToString())); + return; + } + else if(name == "target_histogram_filename") + { + setTargetHistogram(ossimFilename(property->valueToString())); + return; + } + else if(name == "auto_load_input_histogram_flag") + { + theAutoLoadInputHistogramFlag = property->valueToString().toBool(); + if(theAutoLoadInputHistogramFlag) + { + initialize(); + } + return; + } + ossimImageSourceFilter::setProperty(property); +} + +ossimRefPtr<ossimProperty> ossimHistogramMatchFilter::getProperty(const ossimString& name)const +{ + if(name == "input_histogram_filename") + { + ossimFilenameProperty* filenameProp = + new ossimFilenameProperty(name, theInputHistogramFilename); + + filenameProp->setIoType(ossimFilenameProperty::ossimFilenamePropertyIoType_INPUT); + filenameProp->setCacheRefreshBit(); + return filenameProp; + } + else if(name == "target_histogram_filename") + { + ossimFilenameProperty* filenameProp = + new ossimFilenameProperty(name, theTargetHistogramFilename); + + filenameProp->setIoType(ossimFilenameProperty::ossimFilenamePropertyIoType_INPUT); + filenameProp->setCacheRefreshBit(); + + return filenameProp; + } + if(name == "auto_load_input_histogram_flag") + { + ossimBooleanProperty* boolProp = new ossimBooleanProperty(name, + theAutoLoadInputHistogramFlag); + boolProp->setCacheRefreshBit(); + return boolProp; + } + return ossimImageSourceFilter::getProperty(name); +} + +void ossimHistogramMatchFilter::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + ossimImageSourceFilter::getPropertyNames(propertyNames); + + propertyNames.push_back("auto_load_input_histogram_flag"); + propertyNames.push_back("input_histogram_filename"); + propertyNames.push_back("target_histogram_filename"); +} + +bool ossimHistogramMatchFilter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* inputFilename = kwl.find(prefix, "input_histogram_filename"); + const char* targetFilename = kwl.find(prefix, "target_histogram_filename"); + const char* autoLoadInputFlag = kwl.find(prefix, "auto_load_input_histogram_flag"); + + if(autoLoadInputFlag) + { + theAutoLoadInputHistogramFlag = ossimString(autoLoadInputFlag).toBool(); + } + + if(inputFilename&&!theAutoLoadInputHistogramFlag) + { + setInputHistogram(ossimFilename(inputFilename)); + } + else + { + setInputHistogram(ossimFilename("")); + } + + if(targetFilename) + { + setTargetHistogram(ossimFilename(targetFilename)); + } + else + { + setTargetHistogram(ossimFilename("")); + } + + return ossimImageSourceFilter::loadState(kwl, prefix); +} + +bool ossimHistogramMatchFilter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + if(theAutoLoadInputHistogramFlag) + { + kwl.add(prefix, + "input_histogram_filename", + "", + true); + } + else + { + kwl.add(prefix, + "input_histogram_filename", + theInputHistogramFilename.c_str(), + true); + } + kwl.add(prefix, + "target_histogram_filename", + theTargetHistogramFilename.c_str(), + true); + kwl.add(prefix, + "auto_load_input_histogram_flag", + theAutoLoadInputHistogramFlag, + true); + + + return ossimImageSourceFilter::saveState(kwl, prefix); +} + +void ossimHistogramMatchFilter::autoLoadInputHistogram() +{ + ossimConnectableObject* obj = findObjectOfType("ossimImageHandler", + CONNECTABLE_DIRECTION_INPUT); + if(obj) + { + ossimRefPtr<ossimProperty> prop = obj->getProperty("histogram_filename"); + if(prop.valid()) + { + ossimFilename inputHisto = ossimFilename(prop->valueToString()); + if(inputHisto.exists()) + { + setInputHistogram(inputHisto); + } + } + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramMatchFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramMatchFilter.h new file mode 100644 index 0000000000..3ccc897b71 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramMatchFilter.h @@ -0,0 +1,173 @@ +#ifndef ossimHistogramMatchFilter_HEADER +#define ossimHistogramMatchFilter_HEADER +#include "ossimImageSourceFilter.h" +#include "ossimHistogramEqualization.h" + +/** + * class ossimHistogramMatchFilter + * + * <pre> + * + * This class owns two ossimHistogramEqualization filters and will chain them together. It will + * make the left most filter the forward transform by transforming the input input to an equalized + * space defined by the input histogram. The right filter is the target histogram to match. It will + * take the equalized space and invert it to a target histogram. + * + * There is an auto load input histogram flag that if set true will always try to search for an input handler + * and get the input handlers histogram file. and set it. If this is enabled then the only other field that + * is required is to specify the target histogram. If a target histogram is not specified then the output + * + * will be an equalized image without the target applied. + * + * </pre> + */ +class OSSIM_DLL ossimHistogramMatchFilter : public ossimImageSourceFilter +{ +public: + ossimHistogramMatchFilter(); + + /** + * Calls the owned equalizers to create a match composite image. + * + * @return Histogram matched composite image + */ + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + /** + * Initializes the input and target equalizer filters. + */ + virtual void initialize(); + + /** + * @param inputHistogram Input histogram to load + */ + void setInputHistogram(const ossimFilename& inputHistogram); + + /** + * @param targetHistogram Target histogram to match + */ + void setTargetHistogram(const ossimFilename& targetHistogram); + + /** + * @param event Connection event + */ + virtual void connectInputEvent(ossimConnectionEvent& event); + + /** + * @param event Connection event + */ + virtual void disconnectInputEvent(ossimConnectionEvent& event); + + /** + * <pre> + * + * Valid properties are: + * + * auto_load_input_histogram_flag + * Is a boolean property and specifes whether or not the input histogram will be auto searched from + * the conected input source chain. + * + * input_histogram_filename + * Holds the input histogram filename + * + * output_histogram_filename + * holds the output histogram filename + * + * </pre> + * @param property Is the property to set. + */ + virtual void setProperty(ossimRefPtr<ossimProperty> property); + + /** + * Returns a property given the name + * + * Valid names are: + * auto_load_input_histogram_flag + * input_histogram_filename + * output_histogram_filename + * + * Example: + * + * ossimRefPtr<ossimProperty> prop = obj->getProperty("auto_load_input_histogram_flag"); + * + */ + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + + /** + * Returns a list of proeprties. + * + * <pre> + * + * Valid properties are: + * + * auto_load_input_histogram_flag + * Is a boolean property and specifes whether or not the input histogram will be auto searched from + * the conected input source chain. + * + * input_histogram_filename + * Holds the input histogram filename + * + * output_histogram_filename + * holds the output histogram filename + * + * </pre> + */ + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + + /** + * + * <pre> + * Keywords to search and load: + * + * auto_load_input_histogram_flag + * input_histogram_filename + * output_histogram_filename + * + * </pre> + * + * @param kwl Holds the keywords for this object to load prefixed by the passed in prefix parameter + * @param prefix Is the prefix value prepended to all keywords + * + * @return True if succesful or flase otherwise + * + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=NULL); + + /** + * + * <pre> + * Keywords: + * + * auto_load_input_histogram_flag + * input_histogram_filename + * output_histogram_filename + * + * </pre> + * + * @param kwl This object will store the keywords in kwl and prefix by the parameter prefix + * @param prefix Is the prefix value prepended to all keywords + * @return True if succesful or flase otherwise + * + */ + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=NULL)const; + +protected: + /** + * Will search the input chain and get the histogram_filename property of the image handler. + * Once retrieved it calls the setInputHistogram with the found histogram filename. It does nothing + * if the histogram filename does not exist + * + */ + void autoLoadInputHistogram(); + + ossimRefPtr<ossimHistogramEqualization> theInputHistogramEqualizer; + ossimRefPtr<ossimHistogramEqualization> theTargetHistogramEqualizer; + ossimFilename theInputHistogramFilename; + ossimFilename theTargetHistogramFilename; + bool theAutoLoadInputHistogramFlag; +TYPE_DATA +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramRemapper.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramRemapper.cpp new file mode 100644 index 0000000000..755e6f2f9b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramRemapper.cpp @@ -0,0 +1,1694 @@ +//******************************************************************* +// Copyright (C) 2003 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Histogram remapper class declaration. Derived from ossimTableRemapper. +// +// Remaps a tile based on mode and histogram clip points. +// +//************************************************************************* +// $Id: ossimHistogramRemapper.cpp,v 1.34 2005/09/27 11:03:17 gpotts Exp $ + +#include <imaging/tile_sources/ossimHistogramRemapper.h> +#include <base/data_types/ossimMultiResLevelHistogram.h> +#include <base/data_types/ossimMultiBandHistogram.h> +#include <base/data_types/ossimHistogram.h> +#include <base/common/ossimTrace.h> +#include <base/context/ossimNotifyContext.h> +#include <base/common/ossimKeywordNames.h> + +RTTI_DEF1(ossimHistogramRemapper, "ossimHistogramRemapper", ossimTableRemapper) + +static ossimTrace traceDebug("ossimHistogramRemapper:debug"); + +static const char* STRETCH_MODE[] = { "linear_one_piece", + "linear_1std_from_mean", + "linear_2std_from_mean", + "linear_3std_from_mean", + "linear_auto_min_max", + "stretch_unknown" }; + +static const char NORMALIZED_LOW_CLIP_POINT_KW[] = "normalized_low_clip_point"; +static const char NORMALIZED_HIGH_CLIP_POINT_KW[]="normalized_high_clip_point"; +static const char MID_POINT_KW[] = "mid_point"; +static const char MIN_OUTPUT_VALUE_KW[] = "min_output_value"; +static const char MAX_OUTPUT_VALUE_KW[] = "max_output_value"; +static const char STRETCH_MODE_KW[] = "stretch_mode"; +static const char HISTOGRAM_FILENAME_KW[] = "histogram_filename"; + +#ifdef OSSIM_ID_ENABLED +static const char OSSIM_ID[] = "$Id: ossimHistogramRemapper.cpp,v 1.34 2005/09/27 11:03:17 gpotts Exp $"; +#endif + +ossimHistogramRemapper::ossimHistogramRemapper(ossimObject* owner) + : + ossimTableRemapper(owner), // base class + theStretchMode(ossimHistogramRemapper::LINEAR_ONE_PIECE), + theDirtyFlag(false), + theHistogramOwnerFlag(false), + theHistogram(NULL), + theTableSizeInBytes(0), + theNormalizedLowClipPoint(), + theNormalizedHighClipPoint(), + theMidPoint(), + theBandList() +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimHistogramRemapper::ossimHistogramRemapper entered...\n"; +#ifdef OSSIM_ID_ENABLED + ossimNotify(ossimNotifyLevel_DEBUG) + << "OSSIM_ID: " << OSSIM_ID << "\n"; +#endif + } + + disableSource(); + + //--- + // We will control the allocation and deletion of "theTable" so set the + // base class ownership flag to false (ossimTableRemapper does not own). + //--- + setTableOwnership(false); +} + +ossimHistogramRemapper::ossimHistogramRemapper(ossimImageSource* inputSource) + : + ossimTableRemapper(NULL, inputSource), // base class + theStretchMode(ossimHistogramRemapper::LINEAR_ONE_PIECE), + theDirtyFlag(false), + theHistogramOwnerFlag(false), + theHistogram(NULL), + theTableSizeInBytes(0), + theNormalizedLowClipPoint(), + theNormalizedHighClipPoint(), + theMidPoint(), + theMinOutputValue(), + theMaxOutputValue(), + theBandList() +{ + initializeClips(); + + //--- + // We will control the allocation and deletion of "theTable" so set the + // base class ownership flag to false (ossimTableRemapper does not own). + //--- + setTableOwnership(false); +} + +ossimHistogramRemapper::ossimHistogramRemapper(ossimImageSource* inputSource, + ossimMultiResLevelHistogram* histogram, + bool own_histogram, + ossim_float64 low_clip, + ossim_float64 high_clip) + : + ossimTableRemapper(NULL, inputSource), // base class + theStretchMode(ossimHistogramRemapper::LINEAR_ONE_PIECE), + theDirtyFlag(false), + theHistogramOwnerFlag(own_histogram), + theHistogram(NULL), + theTableSizeInBytes(0), + theNormalizedLowClipPoint(), + theNormalizedHighClipPoint(), + theMidPoint(), + theMinOutputValue(), + theMaxOutputValue(), + theBandList() +{ + setHistogram(histogram); + setLowNormalizedClipPoint(low_clip); + setHighNormalizedClipPoint(high_clip); + + if (theDirtyFlag) + { + // Set the enable flag but let the table to be build on first getTile. + enableSource(); + } + + //--- + // We will control the allocation and deletion of "theTable" so set the + // base class ownership flag to false (ossimTableRemapper does not own). + //--- + setTableOwnership(false); +} + +ossimHistogramRemapper::~ossimHistogramRemapper() +{ + if (theHistogram && theHistogramOwnerFlag) + { + delete theHistogram; + theHistogram = NULL; + } + if (theTable) + { + delete [] theTable; + theTable = NULL; + } +} + +void ossimHistogramRemapper::initialize() +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimHistogramRemapper::initialize entered..." << endl; + } + + //--- + // Call the base class initialize. + // Note: This will reset "theInputConnection" if it changed... + //--- + ossimTableRemapper::initialize(); + + // Check the band list to see if it's changes. + vector<ossim_uint32> bandList; + getOutputBandList(bandList); + + if (theBandList.size() != 0 && bandList.size()) + { + if (theBandList.size() != bandList.size()) + { + // Somethings changed. Set everthing back. + initializeClips(); + setNullCount(); + if (theTable) + { + delete [] theTable; + theTable = NULL; + } + } + else + { + // Sizes same check the order. + for(ossim_uint32 band = 0; band < theBandList.size(); ++band) + { + if (theBandList[band] != bandList[band]) + { + initializeClips(); + setNullCount(); + break; + } + } + } + } + + // Update the band list with the latest. + theBandList = bandList; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimHistogramRemapper::initialize exited..." << endl; + } +} + +void ossimHistogramRemapper::reset() +{ + // We could delete theTable to free up memory??? + initializeClips(); +} + +void +ossimHistogramRemapper::setHistogram(ossimMultiResLevelHistogram* histogram, + bool own_histogram) +{ + if (theHistogram && theHistogramOwnerFlag) + { + // Clear out all the values. + reset(); + + delete theHistogram; + } + theHistogram = histogram; + theHistogramOwnerFlag = own_histogram; + setNullCount(); + + // Note: initializeClips before setNullCount since it relies on clips. + initializeClips(); + + if (theTable) + { + delete [] theTable; + theTable = NULL; + } +} + +bool ossimHistogramRemapper::openHistogram(const ossimFilename& histogram_file) +{ + ossimMultiResLevelHistogram* h = new ossimMultiResLevelHistogram(); + if (h->importHistogram(histogram_file)) + { + setHistogram(h, true); // True for, "I own it!" + return true; + } + + // Import failed if here! + delete h; + return false; +} + +ossimRefPtr<ossimImageData> ossimHistogramRemapper::getTile( + const ossimIrect& tile_rect, + ossim_uint32 resLevel) +{ + if ( theEnableFlag && (theDirtyFlag || !theTable) ) + { + buildTable(); + } + + return ossimTableRemapper::getTile(tile_rect, resLevel); +} + +void ossimHistogramRemapper::setLowNormalizedClipPoint(const ossim_float64& clip) +{ + const ossim_uint32 BANDS = getNumberOfInputBands(); + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + setLowNormalizedClipPoint(clip, band); + } +} + +void +ossimHistogramRemapper::setLowNormalizedClipPoint(const ossim_float64& clip, + ossim_uint32 zero_based_band) +{ + const ossim_uint32 BANDS = getNumberOfInputBands(); + + if (zero_based_band >= BANDS) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHistogramRemapper::setLowNormalizedClipPoint ERROR:" + << "\nband " << zero_based_band << " is out of range!" + << "\nhighest band: " << (BANDS-1) << endl; + } + + if (theNormalizedLowClipPoint.size() != BANDS) + { + initializeClips(); + } + + if ( clip != theNormalizedLowClipPoint[zero_based_band] && + clip < theNormalizedHighClipPoint[zero_based_band] ) + { + theDirtyFlag = true; + theNormalizedLowClipPoint[zero_based_band] = clip; + } + + if (theDirtyFlag) + { + verifyEnabled(); + } +} + +void +ossimHistogramRemapper::setHighNormalizedClipPoint(const ossim_float64& clip) +{ + const ossim_uint32 BANDS = getNumberOfInputBands(); + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + setHighNormalizedClipPoint(clip, band); + } +} + +void ossimHistogramRemapper::setHighNormalizedClipPoint(const ossim_float64& clip, ossim_uint32 zero_based_band) +{ + const ossim_uint32 BANDS = getNumberOfInputBands(); + + if (zero_based_band >= BANDS) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHistogramRemapper::setHighNormalizedClipPoint ERROR:" + << "\nband " << zero_based_band << " is out of range!" + << "\nhighest band: " << (BANDS-1) << endl; + } + + if (theNormalizedHighClipPoint.size() != BANDS) + { + initializeClips(); + } + + if ( clip != theNormalizedHighClipPoint[zero_based_band] && + clip > theNormalizedLowClipPoint[zero_based_band] ) + { + theDirtyFlag = true; + theNormalizedHighClipPoint[zero_based_band] = clip; + } + + if (theDirtyFlag) + { + verifyEnabled(); + } +} + +void ossimHistogramRemapper::setLowClipPoint(const ossim_float64& clip) +{ + const ossim_uint32 BANDS = getNumberOfInputBands(); + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + setLowClipPoint(clip, band); + } +} + +void ossimHistogramRemapper::setLowClipPoint(const ossim_float64& clip, + ossim_uint32 zero_based_band) +{ + if (!theHistogram) return; + + ossimHistogram* h = getHistogram(zero_based_band); + if (h) + { + ossim_float64 d = h->getLowFractionFromValue(clip); + if (d != OSSIM_FLT_NAN) + { + setLowNormalizedClipPoint(d, zero_based_band); + } + } +} + +void ossimHistogramRemapper::setHighClipPoint(const ossim_float64& clip) +{ + const ossim_uint32 BANDS = getNumberOfInputBands(); + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + setHighClipPoint(clip, band); + } +} + +void ossimHistogramRemapper::setHighClipPoint(const ossim_float64& clip, + ossim_uint32 zero_based_band) +{ + if (!theHistogram) return; + + ossimHistogram* h = getHistogram(zero_based_band); + if (h) + { + ossim_float64 d = h->getHighFractionFromValue(clip); + if (d != OSSIM_FLT_NAN) + { + d = 1.0-d; + setHighNormalizedClipPoint(d, zero_based_band); + } + } +} + +void ossimHistogramRemapper::setMidPoint(const ossim_float64& value) +{ + const ossim_uint32 BANDS = getNumberOfInputBands(); + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + setMidPoint(value, band); + } +} + +void ossimHistogramRemapper::setMidPoint(const ossim_float64& value, + ossim_uint32 zero_based_band) +{ + const ossim_uint32 BANDS = getNumberOfInputBands(); + + if (zero_based_band >= BANDS) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHistogramRemapper::setMidPoint ERROR:" + << "\nband " << zero_based_band << " is out of range!" + << "\nhighest band: " << (BANDS-1) << endl; + } + + if (theMidPoint.size() != BANDS) + { + initializeClips(); + } + + if (theMidPoint[zero_based_band] != value) + { + theDirtyFlag = true; + theMidPoint[zero_based_band] = value; + } + + if (theDirtyFlag) + { + verifyEnabled(); + } +} + +void ossimHistogramRemapper::setMinOutputValue(const ossim_float64& value) +{ + const ossim_uint32 BANDS = getNumberOfInputBands(); + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + setMinOutputValue(value, band); + } +} + +void ossimHistogramRemapper::setMinOutputValue(const ossim_float64& value, + ossim_uint32 zero_based_band) +{ + if (!theInputConnection) + { + return; + } + + const ossim_uint32 BANDS = getNumberOfInputBands(); + + if (zero_based_band >= BANDS) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHistogramRemapper::setMinOutputValue ERROR:" + << "\nband " << zero_based_band << " is out of range!" + << "\nhighest band: " << (BANDS-1) << endl; + } + + if (theMinOutputValue.size() != BANDS) + { + initializeClips(); + } + + if ( value != theMinOutputValue[zero_based_band] && + value >= theInputConnection->getMinPixelValue(zero_based_band) && + value < theMaxOutputValue[zero_based_band] ) + { + theDirtyFlag = true; + theMinOutputValue[zero_based_band] = value; + } + + if (theDirtyFlag) + { + verifyEnabled(); + } +} + +void ossimHistogramRemapper::setMaxOutputValue(const ossim_float64& value) +{ + const ossim_uint32 BANDS = getNumberOfInputBands(); + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + setMaxOutputValue(value, band); + } +} + +void ossimHistogramRemapper::setMaxOutputValue(const ossim_float64& value, + ossim_uint32 zero_based_band) +{ + if (!theInputConnection) + { + return; + } + + const ossim_uint32 BANDS = getNumberOfInputBands(); + + if (zero_based_band >= BANDS) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHistogramRemapper::setMidPoint ERROR:" + << "\nband " << zero_based_band << " is out of range!" + << "\nhighest band: " << (BANDS-1) << endl; + } + + if (theMaxOutputValue.size() != BANDS) + { + initializeClips(); + } + + if ( value != theMaxOutputValue[zero_based_band] && + value <= theInputConnection->getMaxPixelValue(zero_based_band) && + value > theMinOutputValue[zero_based_band] ) + { + theDirtyFlag = true; + theMaxOutputValue[zero_based_band] = value; + } + + if (theDirtyFlag) + { + verifyEnabled(); + } +} + +ossim_float64 ossimHistogramRemapper::getLowNormalizedClipPoint(ossim_uint32 zero_based_band) const +{ + if (theNormalizedLowClipPoint.size() == 0 || + zero_based_band >= getNumberOfInputBands()) + { + return OSSIM_DBL_NAN; + } + + if (zero_based_band >= theNormalizedLowClipPoint.size()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHistogramRemapper::getLowNormalizedClipPoint ERROR:" + << "\nband " << zero_based_band << " is out of range!" + << "\nhighest band: " << (theNormalizedLowClipPoint.size()-1) + << endl; + return OSSIM_DBL_NAN; + } + + return theNormalizedLowClipPoint[zero_based_band]; +} + +ossim_float64 ossimHistogramRemapper::getLowNormalizedClipPoint() const +{ + if (theNormalizedLowClipPoint.size() == 0) + { + return OSSIM_DBL_NAN; + } + + ossim_float64 d = 0.0; + const ossim_uint32 BANDS = theNormalizedLowClipPoint.size(); + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + d += getLowNormalizedClipPoint(band); + } + + return (d / BANDS); +} + +ossim_float64 ossimHistogramRemapper::getHighNormalizedClipPoint(ossim_uint32 zero_based_band) const +{ + if (theNormalizedHighClipPoint.size() == 0 || + zero_based_band >= getNumberOfInputBands()) + { + return OSSIM_DBL_NAN; + } + + if (zero_based_band >= theNormalizedHighClipPoint.size()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHistogramRemapper::getHighNormalizedClipPoint ERROR:" + << "\nband " << zero_based_band << " is out of range!" + << "\nhighest band: " << (theNormalizedHighClipPoint.size()-1) + << endl; + return OSSIM_DBL_NAN; + } + + return theNormalizedHighClipPoint[zero_based_band]; +} + +ossim_float64 ossimHistogramRemapper::getHighNormalizedClipPoint() const +{ + if (theNormalizedHighClipPoint.size() == 0) + { + return OSSIM_DBL_NAN; + } + + ossim_float64 d = 0.0; + const ossim_uint32 BANDS = theNormalizedHighClipPoint.size(); + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + d += getHighNormalizedClipPoint(band); + } + + return (d / BANDS); +} + +ossim_float64 ossimHistogramRemapper::getLowClipPoint(ossim_uint32 zero_based_band) const +{ + if(zero_based_band >= getNumberOfInputBands() || + !theHistogram || zero_based_band >= theNormalizedLowClipPoint.size()) + { + return OSSIM_DBL_NAN; + } + + if (theNormalizedLowClipPoint[zero_based_band] == 0.0) + { + return getMinPixelValue(zero_based_band); + } + + ossimHistogram* h = getHistogram(zero_based_band); + if (h) + { + ossim_float64 d = + h->LowClipVal(theNormalizedLowClipPoint[zero_based_band]); + + return floor(d); + } + + return OSSIM_DBL_NAN; +} + +ossim_float64 ossimHistogramRemapper::getLowClipPoint() const +{ + if (theNormalizedLowClipPoint.size() == 0 || !theHistogram) + { + return OSSIM_DBL_NAN; + } + + ossim_float64 d = 0.0; + const ossim_uint32 BANDS = getNumberOfInputBands(); + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + d += getLowClipPoint(band); + } + + return (d / BANDS); +} + +ossim_float64 ossimHistogramRemapper::getHighClipPoint(ossim_uint32 zero_based_band) const +{ + if(zero_based_band >= getNumberOfInputBands() || + !theHistogram || zero_based_band >= theNormalizedHighClipPoint.size()) + { + return OSSIM_DBL_NAN; + } + + if (theNormalizedHighClipPoint[zero_based_band] == 1.0) + { + return getMaxPixelValue(zero_based_band); + } + + ossimHistogram* h = getHistogram(zero_based_band); + if (h) + { + ossim_float64 d = + h->HighClipVal(1.0-theNormalizedHighClipPoint[zero_based_band]); + return ceil(d); + } + + return OSSIM_DBL_NAN; +} + +ossim_float64 ossimHistogramRemapper::getHighClipPoint() const +{ + if (theNormalizedHighClipPoint.size() == 0 || !theHistogram) + { + return OSSIM_DBL_NAN; + } + + ossim_float64 d = 0.0; + const ossim_uint32 BANDS = getNumberOfInputBands(); + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + d += getHighClipPoint(band); + } + + return (d / BANDS); +} + +ossim_float64 ossimHistogramRemapper::getMidPoint(ossim_uint32 zero_based_band) const +{ + if (theMidPoint.size() == 0 || + zero_based_band >= getNumberOfInputBands()) + { + return OSSIM_DBL_NAN; + } + + if (zero_based_band >= theMidPoint.size()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHistogramRemapper::getMidPoint ERROR:" + << "\nband " << zero_based_band << " is out of range!" + << "\nhighest band: " << (theMidPoint.size()-1) + << endl; + return OSSIM_DBL_NAN; + } + + return theMidPoint[zero_based_band]; +} + +ossim_float64 ossimHistogramRemapper::getMidPoint() const +{ + if (theMidPoint.size() == 0) + { + return OSSIM_DBL_NAN; + } + + ossim_float64 d = 0.0; + const ossim_uint32 BANDS = theMidPoint.size(); + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + d += getMidPoint(band); + } + + return (d / BANDS); +} + +ossim_float64 ossimHistogramRemapper::getMinOutputValue(ossim_uint32 zero_based_band) const +{ + if (theMinOutputValue.size() == 0 || + zero_based_band >= getNumberOfInputBands()) + { + return OSSIM_DBL_NAN; + } + + if (zero_based_band >= theMinOutputValue.size()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHistogramRemapper::getMinOutputValue ERROR:" + << "\nband " << zero_based_band << " is out of range!" + << "\nhighest band: " << (theMinOutputValue.size()-1) + << endl; + return OSSIM_DBL_NAN; + } + + return theMinOutputValue[zero_based_band]; +} + +ossim_float64 ossimHistogramRemapper::getMinOutputValue() const +{ + if (theMinOutputValue.size() == 0) + { + return OSSIM_DBL_NAN; + } + + ossim_float64 d = 0.0; + const ossim_uint32 BANDS = theMinOutputValue.size(); + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + d += getMinOutputValue(band); + } + + return (d / BANDS); +} + +ossim_float64 ossimHistogramRemapper::getMaxOutputValue(ossim_uint32 zero_based_band) const +{ + if (theMaxOutputValue.size() == 0 || + zero_based_band >= getNumberOfInputBands()) + { + return OSSIM_DBL_NAN; + } + + if (zero_based_band >= theMaxOutputValue.size()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHistogramRemapper::getMaxOutputValue ERROR:" + << "\nband " << zero_based_band << " is out of range!" + << "\nhighest band: " << (theMaxOutputValue.size()-1) + << endl; + return OSSIM_DBL_NAN; + } + + return theMaxOutputValue[zero_based_band]; +} + +ossim_float64 ossimHistogramRemapper::getMaxOutputValue() const +{ + if (theMaxOutputValue.size() == 0) + { + return OSSIM_DBL_NAN; + } + + ossim_float64 d = 0.0; + const ossim_uint32 BANDS = theMaxOutputValue.size(); + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + d += getMaxOutputValue(band); + } + + return (d / BANDS); +} + +bool ossimHistogramRemapper::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + static const char MODULE[] = "ossimHistogramRemapper::loadState"; + + if (traceDebug()) + { + CLOG << " Entered..." + << "\nprefix: " << prefix << endl; + } + + const char* lookup = NULL; + ossimString keyword; + + lookup = kwl.find(prefix, HISTOGRAM_FILENAME_KW); + if (lookup) + { + if ( !openHistogram(ossimFilename(lookup)) ) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHistogramRemapper::loadState ERROR!" + << "\nCould not open file: " << lookup + << "\nReturning..." << endl; + return false; + } + } + + //--- + // Get the band specific keywords. + // NOTES: + // - This loadState assumes the all keywords will have the same number + // of bands. + // - The set methods cannot be used here as there may not be a connection + // yet that they need. + //--- + ossim_uint32 bands = 0; + lookup = kwl.find(prefix, ossimKeywordNames::NUMBER_BANDS_KW); + if (lookup) + { + bands = ossimString::toUInt32(lookup); + } + else // For backwards compatibility. + { + // Use the low clip to find number of bands... + keyword = NORMALIZED_LOW_CLIP_POINT_KW; + bands = kwl.numberOf(prefix, keyword); + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimHistogramRemapper::loadState DEBUG:" + << "\nBands: " << bands + << endl; + } + + // Start with fresh clips. + initializeClips(bands); + + for (ossim_uint32 band = 0; band < bands; ++band) + { + // Get the low clip. + keyword = NORMALIZED_LOW_CLIP_POINT_KW; + keyword += "."; + keyword += ossimKeywordNames::BAND_KW; + keyword += ossimString::toString(band+1); + lookup = kwl.find(prefix, keyword); + if(lookup) + { + theNormalizedLowClipPoint[band] = atof(lookup); + } + + // Get the high clip. + keyword = NORMALIZED_HIGH_CLIP_POINT_KW; + keyword += "."; + keyword += ossimKeywordNames::BAND_KW; + keyword += ossimString::toString(band+1); + lookup = kwl.find(prefix, keyword); + if(lookup) + { + theNormalizedHighClipPoint[band] = atof(lookup); + } + + // Get the mid point. + keyword = MID_POINT_KW; + keyword += "."; + keyword += ossimKeywordNames::BAND_KW; + keyword += ossimString::toString(band+1); + lookup = kwl.find(prefix, keyword); + if(lookup) + { + theMidPoint[band] = atof(lookup); + } + + // Get the min output value. + keyword = MIN_OUTPUT_VALUE_KW; + keyword += "."; + keyword += ossimKeywordNames::BAND_KW; + keyword += ossimString::toString(band+1); + lookup = kwl.find(prefix, keyword); + if(lookup) + { + theMinOutputValue[band] = atof(lookup); + } + + // Get the max output value. + keyword = MAX_OUTPUT_VALUE_KW; + keyword += "."; + keyword += ossimKeywordNames::BAND_KW; + keyword += ossimString::toString(band+1); + lookup = kwl.find(prefix, keyword); + if(lookup) + { + theMaxOutputValue[band] = atof(lookup); + } + } + + lookup = kwl.find(prefix, STRETCH_MODE_KW); + if (lookup) + { + ossimString s = lookup; + s.downcase(); + if (s == STRETCH_MODE[ossimHistogramRemapper::LINEAR_ONE_PIECE]) + { + theStretchMode = ossimHistogramRemapper::LINEAR_ONE_PIECE; + } + else if (s == STRETCH_MODE[ossimHistogramRemapper::LINEAR_1STD_FROM_MEAN]) + { + theStretchMode = ossimHistogramRemapper::LINEAR_1STD_FROM_MEAN; + } + else if (s == STRETCH_MODE[ossimHistogramRemapper::LINEAR_2STD_FROM_MEAN]) + { + theStretchMode = ossimHistogramRemapper::LINEAR_2STD_FROM_MEAN; + } + else if (s == STRETCH_MODE[ossimHistogramRemapper::LINEAR_3STD_FROM_MEAN]) + { + theStretchMode = ossimHistogramRemapper::LINEAR_3STD_FROM_MEAN; + } + else if (s == STRETCH_MODE[ossimHistogramRemapper::LINEAR_AUTO_MIN_MAX]) + { + theStretchMode = ossimHistogramRemapper::LINEAR_AUTO_MIN_MAX; + } + else + { + theStretchMode = ossimHistogramRemapper::STRETCH_UNKNOWN; + } + } + + // Load the base class states... + bool status = ossimTableRemapper::loadState(kwl, prefix); + + //--- + // Check for the enable flag which would have been loaded be the base class + // loadState. If enabled, set the dirty flag so that the first getTile + // will cause a "buildTable()" call. + //--- + if (theEnableFlag) + { + theDirtyFlag = true; + } + + if (traceDebug()) + { + CLOG << "ossimHistogramRemapper::loadState DEBUG:" + << *this + << "\nExited..." << endl; + } + + return status; +} + +bool ossimHistogramRemapper::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + if (theHistogram) + { + kwl.add(prefix, + HISTOGRAM_FILENAME_KW, + theHistogram->getHistogramFile().c_str(), + true); + } + + kwl.add(prefix, + STRETCH_MODE_KW, + getStretchModeString().c_str(), + true); + + const ossim_uint32 BANDS = theNormalizedLowClipPoint.size(); + + kwl.add(prefix, + ossimKeywordNames::NUMBER_BANDS_KW, + BANDS, + true); + + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + ossimString keyword; + + // Save the low clip. + keyword = NORMALIZED_LOW_CLIP_POINT_KW; + keyword += "."; + keyword += ossimKeywordNames::BAND_KW; + keyword += ossimString::toString(band+1); + kwl.add(prefix, + keyword, + theNormalizedLowClipPoint[band], + true); + + // Save the high clip. + keyword = NORMALIZED_HIGH_CLIP_POINT_KW; + keyword += "."; + keyword += ossimKeywordNames::BAND_KW; + keyword += ossimString::toString(band+1); + kwl.add(prefix, + keyword, + theNormalizedHighClipPoint[band], + true); + + // Save the mid point. + keyword = MID_POINT_KW; + keyword += "."; + keyword += ossimKeywordNames::BAND_KW; + keyword += ossimString::toString(band+1); + kwl.add(prefix, + keyword, + theMidPoint[band], + true); + + // Save the min output value. + keyword = MIN_OUTPUT_VALUE_KW; + keyword += "."; + keyword += ossimKeywordNames::BAND_KW; + keyword += ossimString::toString(band+1); + kwl.add(prefix, + keyword, + theMinOutputValue[band], + true); + + // Save the max output value. + keyword = MAX_OUTPUT_VALUE_KW; + keyword += "."; + keyword += ossimKeywordNames::BAND_KW; + keyword += ossimString::toString(band+1); + kwl.add(prefix, + keyword, + theMaxOutputValue[band], + true); + } + + return ossimTableRemapper::saveState(kwl, prefix); +} + +void ossimHistogramRemapper::setStretchMode(StretchMode mode) +{ + if (theStretchMode != mode) + { + theDirtyFlag = true; + theStretchMode = mode; + } +} + +void ossimHistogramRemapper::buildTable() +{ + setupTable(); + + switch(theStretchMode) + { + case ossimHistogramRemapper::LINEAR_ONE_PIECE: + { + buildLinearTable(); + break; + } + case ossimHistogramRemapper::LINEAR_AUTO_MIN_MAX: + { + buildAutoLinearMinMaxTable(); + break; + } + case ossimHistogramRemapper::LINEAR_1STD_FROM_MEAN: + case ossimHistogramRemapper::LINEAR_2STD_FROM_MEAN: + case ossimHistogramRemapper::LINEAR_3STD_FROM_MEAN: + buildLinearTableStdFromMean(); + break; + + default: + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHistogramRemapper::buildTable ERROR!" + << "\nUnknown stretch type!" << endl; + break; + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimHistogramRemapper::buildTable DEBUG:\n" << endl; + print(ossimNotify(ossimNotifyLevel_DEBUG)); + } +} + +void ossimHistogramRemapper::buildLinearTable() +{ + switch (getOutputScalarType()) + { + case OSSIM_UCHAR: + { + buildLinearTable(ossim_uint8(0)); + break; + } + + case OSSIM_USHORT11: + case OSSIM_USHORT16: + { + buildLinearTable(ossim_uint16(0)); + break; + } + + case OSSIM_SSHORT16: + { + buildLinearTable(ossim_sint16(0)); + break; + } + + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT: + { + buildLinearTable(ossim_float32(0)); + break; + } + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_DOUBLE: + { + buildLinearTable(ossim_float64(0)); + break; + } + + case OSSIM_SCALAR_UNKNOWN: + default: + { + // Shouldn't hit this. + ossimNotify(ossimNotifyLevel_WARN) + << "ossimTableRemapper::buildTable OSSIM_SCALAR_UNKNOWN!" + << endl; + break; + } + + } // End of "switch (theTableType)" +} + +void ossimHistogramRemapper::buildAutoLinearMinMaxTable() +{ + switch (getOutputScalarType()) + { + case OSSIM_UCHAR: + { + buildAutoLinearMinMaxTableTemplate(ossim_uint8(0)); + break; + } + + case OSSIM_USHORT11: + case OSSIM_USHORT16: + { + buildAutoLinearMinMaxTableTemplate(ossim_uint16(0)); + break; + } + + case OSSIM_SSHORT16: + { + buildAutoLinearMinMaxTableTemplate(ossim_sint16(0)); + break; + } + + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT: + { + buildAutoLinearMinMaxTableTemplate(ossim_float32(0)); + break; + } + + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_DOUBLE: + { + buildAutoLinearMinMaxTableTemplate(ossim_float64(0)); + break; + } + + case OSSIM_SCALAR_UNKNOWN: + default: + { + // Shouldn't hit this. + ossimNotify(ossimNotifyLevel_WARN) + << "ossimTableRemapper::buildTable OSSIM_SCALAR_UNKNOWN!" + << endl; + break; + } + + } // End of "switch (theTableType)" +} + +template <class T> void ossimHistogramRemapper::buildLinearTable(T /* dummy */) +{ + // This builds a native table. + theTableType = ossimTableRemapper::NATIVE; + + const ossim_uint32 BANDS = getNumberOfInputBands(); + + // Sanity check. + if (theNormalizedLowClipPoint.size() != BANDS || !theHistogram) + { + theEnableFlag = false; + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHistogramRemapper::buildTable ERROR!" + << " Line: " << __LINE__ << endl; + return; + } + + T* table = reinterpret_cast<T*>(theTable); + ossim_uint32 index = 0; + + // Finally, build the table... + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + ossimHistogram* h = getHistogram(band); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimHistogramRemapper::buildLinearTable DEBUG:" + << "\nband: " << band + << "\nmean: " << h->GetMean() + << "\nstddev: " << h->GetStandardDev() + << endl; + } + + if (!h) + { + theEnableFlag = false; + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHistogramRemapper::buildTable ERROR!" + << " Line: " << __LINE__ << endl; + return; + } + + const T NULL_PIX = static_cast<T>(getNullPixelValue(band)); + const T MIN_PIX = static_cast<T>(theMinOutputValue[band]); + const T MAX_PIX = static_cast<T>(theMaxOutputValue[band]); + + ossim_float64 min_clip_value = + h->LowClipVal(theNormalizedLowClipPoint[band]); + ossim_float64 max_clip_value = + h->HighClipVal(1.0-theNormalizedHighClipPoint[band]); + min_clip_value = floor(min_clip_value); + max_clip_value = ceil(max_clip_value); + ossim_float64 gain = (MAX_PIX-MIN_PIX+1)/(max_clip_value-min_clip_value); + + table[index] = NULL_PIX; + ++index; + for (ossim_uint32 pix = 1; pix < theTableBinCount; ++pix) + { + ossim_float64 p = pix; + if (p <= min_clip_value) + { + p = MIN_PIX; + } + else if (p >= max_clip_value) + { + p = MAX_PIX; + } + else + { + p = ((p - min_clip_value) * gain) + MIN_PIX - 1.0; + } + + table[index] = static_cast<T>(p+0.5); + + ++index; + } + } // End of band loop. + + // Clear the dirty flag so the table's not rebuilt on the next getTile. + theDirtyFlag = false; +} + +template <class T> void ossimHistogramRemapper::buildAutoLinearMinMaxTableTemplate(T /* dummy */) +{ + const ossim_uint32 BANDS = getNumberOfInputBands(); + + // Sanity check. + if (theNormalizedLowClipPoint.size() != BANDS || !theHistogram) + { + theEnableFlag = false; + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHistogramRemapper::buildTable ERROR!" + << " Line: " << __LINE__ << endl; + return; + } + + + // Finally, build the table... + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + ossimHistogram* h = getHistogram(band); + if(h) + { + setLowClipPoint(h->GetMinVal()); + setHighClipPoint(h->GetMaxVal()); + } + } + + buildLinearTable(); +} + +void ossimHistogramRemapper::buildLinearTableStdFromMean() +{ + const ossim_uint32 BANDS = getNumberOfInputBands(); + + // Sanity check. + if (theNormalizedLowClipPoint.size() != BANDS || !theHistogram) + { + theEnableFlag = false; + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHistogramRemapper::buildTable ERROR!" + << " Line: " << __LINE__ << endl; + return; + } + + ossim_float64 multiplier = 1.0; + if (theStretchMode == LINEAR_2STD_FROM_MEAN) + { + multiplier = 2.0; + } + else if (theStretchMode == LINEAR_3STD_FROM_MEAN) + { + multiplier = 3.0; + } + + // Finally, build the table... + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + ossimHistogram* h = getHistogram(band); + ossim_float64 mean = h->GetMean(); + ossim_float64 stdDev = h->GetStandardDev(); + ossim_float64 lowClip = mean - (stdDev * multiplier); + ossim_float64 highClip = mean + (stdDev * multiplier); + + // Clamp to min/max. + if (lowClip < theMinOutputValue[band]) + { + lowClip = theMinOutputValue[band]; + } + if (highClip > theMaxOutputValue[band]) + { + highClip = theMaxOutputValue[band]; + } + + setLowClipPoint(lowClip, band); + setMidPoint(mean, band); + setHighClipPoint(highClip, band); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimHistogramRemapper::buildLinearStdFromMean DEBUG:" + << "\nband: " << band + << "\nmean: " << mean + << "\nstddev: " << stdDev + << "\nlow clip: " << lowClip + << "\nhigh clip: " << highClip + << endl; + } + } + + buildLinearTable(); +} + +void ossimHistogramRemapper::initializeClips() +{ + initializeClips(getNumberOfInputBands()); +} + +void ossimHistogramRemapper::initializeClips(ossim_uint32 bands) +{ + theEnableFlag = false; + theDirtyFlag = false; + + if (bands == 0) + { + return; + } + + theNormalizedLowClipPoint.resize(bands); + theNormalizedHighClipPoint.resize(bands); + theMidPoint.resize(bands); + theMinOutputValue.resize(bands); + theMaxOutputValue.resize(bands); + + for (ossim_uint32 band = 0; band < bands; ++band) + { + theNormalizedLowClipPoint[band] = 0.0; + theNormalizedHighClipPoint[band] = 1.0; + theMidPoint[band] = 0.0; + theMinOutputValue[band] = getMinPixelValue(band); + theMaxOutputValue[band] = getMaxPixelValue(band); + } +} + +void ossimHistogramRemapper::setNullCount() const +{ + // This will set the null bucket for all res zero bands to zero! + if (theHistogram) + { + const ossim_uint32 BANDS = theHistogram->getNumberOfBands();//getNumberOfInputBands(); + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + ossimHistogram* h = theHistogram->getHistogram(band); + if (h) + { + h->SetCount(0, 0); + } + } + } +} + +ossimHistogramRemapper::StretchMode ossimHistogramRemapper::getStretchMode() const +{ + return theStretchMode; +} + +ossimString ossimHistogramRemapper::getStretchModeString() const +{ + return ossimString(STRETCH_MODE[theStretchMode]); +} + +ossim_uint32 ossimHistogramRemapper::getNumberOfStretchModes() const +{ + return ossimHistogramRemapper::STRETCH_UNKNOWN; // last index +} + +ossimString +ossimHistogramRemapper::getStretchModeString(ossim_uint32 index) const +{ + if (index < ossimHistogramRemapper::STRETCH_UNKNOWN) + { + return ossimString(STRETCH_MODE[index]); + } + + return ossimString(STRETCH_MODE[ossimHistogramRemapper::STRETCH_UNKNOWN]); + +} + +ostream& ossimHistogramRemapper::print(ostream& os) const +{ + os << setiosflags(ios::fixed) << setprecision(15) + << "\nossimHistogramRemapper::print:" + << "\ntheStretchMode: " << getStretchModeString().c_str() + << "\ntheDirtyFlag: " << (theDirtyFlag?"true":"false") + << "\ntheHistogramOwnerFlag: " + << (theHistogramOwnerFlag?"true":"false") + << "\ntheHistogram: " << (theHistogram?"initialized":"null") + << "\ntheTableSizeInBytes: " << theTableSizeInBytes + << endl; + + const ossim_uint32 BANDS = theNormalizedLowClipPoint.size(); + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + os << "\ntheNormalizedLowClipPoint[" << band << "]: " + << theNormalizedLowClipPoint[band] + << "\ntheNormalizedHighClipPoint[" << band << "]: " + << theNormalizedHighClipPoint[band] + << "\ntheMidPoint[" << band << "]: " + << theMidPoint[band] + << "\ntheMinOutputValue[" << band << "]: " + << theMinOutputValue[band] + << "\ntheMaxOutputValue[" << band << "]: " + << theMaxOutputValue[band] + << endl; + } + + for (ossim_uint32 i = 0; i < theBandList.size(); ++i) + { + os << "theBandList[" << i << "]: " << theBandList[i] << endl; + } + + return ossimTableRemapper::print(os); +} + +void ossimHistogramRemapper::setupTable() +{ + const ossim_uint32 BANDS = getNumberOfInputBands(); + + if (theNormalizedLowClipPoint.size() == 0) + { + initializeClips(BANDS); + } + + ossim_uint32 values_per_band = 0; + ossim_uint32 bytes_per_pixel = 0; + + switch (theOutputScalarType) + { + case OSSIM_UCHAR: + values_per_band = 256; // 2 ^ 8 + bytes_per_pixel = 1; + theTableType = ossimTableRemapper::NATIVE; + break; + + case OSSIM_USHORT11: + values_per_band = 2048; // 2 ^ 11 + bytes_per_pixel = 2; + theTableType = ossimTableRemapper::NATIVE; + + break; + + case OSSIM_USHORT16: + case OSSIM_SSHORT16: + values_per_band = 65536; // 2 ^ 16 + bytes_per_pixel = 2; + theTableType = ossimTableRemapper::NATIVE; + break; + + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT: + bytes_per_pixel = 4; + break; + + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_DOUBLE: + bytes_per_pixel = 8; + theTableType = ossimTableRemapper::NORMALIZED; + break; + + default: + break; + } + + if ( theOutputScalarType == OSSIM_FLOAT || + theOutputScalarType == OSSIM_DOUBLE || + theOutputScalarType == OSSIM_NORMALIZED_FLOAT || + theOutputScalarType == OSSIM_NORMALIZED_DOUBLE ) + { + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + ossimHistogram* h = getHistogram(band); + + if (h) + { + if (h->GetRes() > static_cast<ossim_int32>(values_per_band)) + { + values_per_band = h->GetRes(); + } + } + } + } + + theTableBinCount = values_per_band; + theTableBandCount = BANDS; + + // Check the size of the table prior to deletion and making a new one. + ossim_uint32 size_in_bytes = values_per_band * BANDS * bytes_per_pixel; + + if (!theTable || (theTableSizeInBytes != size_in_bytes)) + { + if (theTable) + { + delete [] theTable; + } + theTable = new ossim_uint8[size_in_bytes]; + theTableSizeInBytes = size_in_bytes; + } + + //--- + // Last check for NaNs in key data members and set to some default if so. + // This could occur if someone stripped a keyword list down to a minimal + // set of keywords. + //--- + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + const double MIN = getMinPixelValue(band); + const double MAX = getMaxPixelValue(band); + + if ( theMinOutputValue[band] == OSSIM_DBL_NAN ) + { + theMinOutputValue[band] = MIN; + } + if ( theMaxOutputValue[band] == OSSIM_DBL_NAN ) + { + theMaxOutputValue[band] = MAX; + } + } +} + +void ossimHistogramRemapper::verifyEnabled() +{ + theEnableFlag = false; + + if (!theInputConnection) + { + //*** + // Since this filter can be constructed with no input connection do not + // output and error, simply return. + //*** + return; + } + + const ossim_uint32 BANDS = theNormalizedLowClipPoint.size(); + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + const double MIN = getMinPixelValue(band); + const double MAX = getMaxPixelValue(band); + + if ( theNormalizedLowClipPoint[band] != 0.0 || + theNormalizedHighClipPoint[band] != 1.0 || + // theMidPoint != 0.0 || ???? + theMinOutputValue[band] != MIN || + theMaxOutputValue[band] != MAX ) + { + theEnableFlag = true; + break; + } + } +} + +ossimHistogram* +ossimHistogramRemapper::getHistogram(ossim_uint32 zero_based_band, + ossim_uint32 res_level) const +{ + ossim_uint32 histogram_band = getHistogramBand(zero_based_band); + ossimHistogram* h = NULL; + + if (theHistogram) + { + if (histogram_band < theHistogram->getNumberOfBands()) + { + h = theHistogram->getHistogram(histogram_band, res_level); + } + } + + return h; +} + +ossimFilename ossimHistogramRemapper::getHistogramFile() const +{ + if (theHistogram) + { + return theHistogram->getHistogramFile(); + } + + return ossimFilename::NIL; +} + +ossim_uint32 +ossimHistogramRemapper::getHistogramBand(ossim_uint32 input_band) const +{ + vector<ossim_uint32> bandList; + getOutputBandList(bandList); + + const ossim_uint32 BANDS = bandList.size(); + + if (BANDS == 0) + { + return 0; + } + + return bandList[input_band]; +} + +ossimString ossimHistogramRemapper::getLongName()const +{ + return ossimString("Histogram Remapper, filter with controls for histogram stretching."); +} + +ossimString ossimHistogramRemapper::getShortName()const +{ + return ossimString("Histogram Remapper"); +} + +ostream& operator<<(ostream& os, const ossimHistogramRemapper& hr) +{ + return hr.print(os); +} + + +// Private to disallow use... +ossimHistogramRemapper::ossimHistogramRemapper(const ossimHistogramRemapper&) +{ +} + +// Private to disallow use... +ossimHistogramRemapper& ossimHistogramRemapper::operator=(const ossimHistogramRemapper&) +{ + return *this; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramRemapper.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramRemapper.h new file mode 100644 index 0000000000..89e89d12bd --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramRemapper.h @@ -0,0 +1,529 @@ +//******************************************************************* +// Copyright (C) 2003 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Histogram remapper class declaration. Derived from ossimTableRemapper. +// +// Remaps a tile based on mode and histogram clip points. This object uses +// a precomputed remap table for speed; hence, derived from the +// ossimTableRemapper +// +// NOTE on bands: +// +// - All methods take zero based bands. In other words the first +// band is band "0". +// +// - This objects band 0 is the same band 0 as it's input connection. If +// the band order was changed by a ossimBandSelector then this band 0 will +// not map to the histogram files band 0. To handle this, +// the "getOutputBandList()" method is used to get the correct histogram for +// the input band. +// +// - The "get" methods that do not take a band, simply return the average of +// all bands. This really only makes sense if all bands are the same +// but is provided for convenience. +// +//************************************************************************* +// $Id: ossimHistogramRemapper.h,v 1.17 2005/09/12 13:15:52 gpotts Exp $ +#ifndef ossimHistogramRemapper_HEADER +#define ossimHistogramRemapper_HEADER + +#include <imaging/tile_sources/ossimTableRemapper.h> + +class ossimMultiResLevelHistogram; +class ossimHistogram; + +class OSSIMDLLEXPORT ossimHistogramRemapper : public ossimTableRemapper +{ +public: + enum StretchMode + { + LINEAR_ONE_PIECE = 0, + LINEAR_1STD_FROM_MEAN = 1, + LINEAR_2STD_FROM_MEAN = 2, + LINEAR_3STD_FROM_MEAN = 3, + LINEAR_AUTO_MIN_MAX = 4, + STRETCH_UNKNOWN = 5 // Alway last as used for number of modes method. + + }; + + ossimHistogramRemapper(ossimObject* owner=NULL); + ossimHistogramRemapper(ossimImageSource* inputSource); + + /** + * NOTE: + * - If input chip source is mutiband this will set all band to same + * percentage of clip. + * - low_clip is a normalized percentage, 0.01 = one percent low clip. + * - high_clip is a normalized percentage, 0.99 = one percent high clip. + */ + ossimHistogramRemapper(ossimImageSource* inputSource, + ossimMultiResLevelHistogram* histogram, + bool own_histogram = true, + ossim_float64 low_clip = 0.0, + ossim_float64 high_clip = 1.0); + + + virtual ~ossimHistogramRemapper(); + + virtual ossimString getLongName() const; + virtual ossimString getShortName() const; + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tile_rect, + ossim_uint32 resLevel=0); + + virtual void initialize(); + + /** + * - Disables this source. + * - Sets all clip points to default. + * - Removes current table. + */ + void reset(); + + /** + * Sets remap mode to mode. + */ + void setStretchMode(StretchMode mode); + + /** + * Returns the current enumerated node. + */ + StretchMode getStretchMode() const; + + /** + * Returns the string for current remap mode. + */ + ossimString getStretchModeString() const; + + /** + * Returns the number of stretch modes. + */ + ossim_uint32 getNumberOfStretchModes() const; + + /** + * Returns the mode string for a given index. + * Returns "stretch_unknown" if index is out of range. + * + * NOTE: + * - If you're building gui buttons you can: + * // pseudo code... + * ossim_uint32 number_of_modes = remapper->getNumberOfModes() + * for (ossim_uint32 i = 0; i < number_of_modes; ++i) + * { + * addButton(getModeString(i).c_str()); + * } + */ + ossimString getStretchModeString(ossim_uint32 index) const; + + /** + * Sets the low clip point. + * + * Note on null bin: + * - The null bin is ignored when considering a percent of penetration from + * the low end. + * + * Notes on clip point: + * - If input chip source is mutiband this will set all band to same + * percentage of clip. + * - Clip points should be normalized between zero and one. + * - A low clip point of 0.0 means no penetration. + * - A low clip point of 0.02 means penetrate in two percent. + */ + void setLowNormalizedClipPoint(const ossim_float64& clip); + + /** + * Sets the low clip point for band. + * + * Note on null bin: + * - The null bin is ignored when considering a percent of penetration from + * the low end. + * + * Notes on clip points: + * - Clip point should be normalized between zero and one. + * - A low clip point of 0.0 means no penetration. + * - A low clip point of 0.02 means penetrate in two percent. + */ + void setLowNormalizedClipPoint(const ossim_float64& clip, + ossim_uint32 zero_based_band); + + /** + * Sets the high clip point. + * + * Notes on clip points: + * - If input chip source is mutiband this will set all band to same + * percentage of clip. + * - Clip point should be normalized between zero and one. + * - A high clip point of 1.0 means no penetration. + * - A high clip point of .98 mean a 2 % penetration from the high end. + */ + void setHighNormalizedClipPoint(const ossim_float64& clip); + + /** + * Sets the high clip point. + * + * Notes on clip points: + * - Clip point should be normalized between zero and one. + * - A high clip point of 1.0 means no penetration. + * - A high clip point of .98 mean a 2 % penetration from the high end. + */ + void setHighNormalizedClipPoint(const ossim_float64& clip, + ossim_uint32 zero_based_band); + + /** + * Sets the low clip point. + * + * Notes on clip point: + * - If input chip source is mutiband this will set all band to same + * percentage of clip. + * - Clip points are in DN values. + * - If histogram is not set no action is taken. + */ + void setLowClipPoint(const ossim_float64& clip); + + /** + * Sets the low clip point for band. + * + * Notes on clip points: + * - Clip points are DN values. + * - If histogram is not set no action is taken. + */ + void setLowClipPoint(const ossim_float64& clip, + ossim_uint32 zero_based_band); + + /** + * Sets the high clip point. + * + * Notes on clip points: + * - If input chip source is mutiband this will set all band to same + * percentage of clip. + * - Clip points are DN values. + * - If histogram is not set no action is taken. + */ + void setHighClipPoint(const ossim_float64& clip); + + /** + * Sets the high clip point. + * + * Notes on clip points: + * - Clip points are DN values. + * - If histogram is not set no action is taken. + */ + void setHighClipPoint(const ossim_float64& clip, + ossim_uint32 zero_based_band); + + /** + * Sets the mid clip point. + * + * Notes on clip points: + * - If input chip source is mutiband this will set all band to same + * percentage of clip. + */ + void setMidPoint(const ossim_float64& value); + + /** + * Sets the mid clip point for band. + */ + void setMidPoint(const ossim_float64& value, + ossim_uint32 zero_based_band); + + /** + * Sets the min output value. + * + * Notes on clip points: + * - If input chip source is mutiband this will set all band to same + * percentage of clip. + */ + void setMinOutputValue(const ossim_float64& value); + + /** + * Sets the min output value for band. + */ + void setMinOutputValue(const ossim_float64& value, + ossim_uint32 zero_based_band); + + /** + * Sets the max output value. + * + * Notes on clip points: + * - If input chip source is mutiband this will set all band to same + * percentage of clip. + */ + void setMaxOutputValue(const ossim_float64& value); + + /** + * Sets the min output value for band. + */ + void setMaxOutputValue(const ossim_float64& value, + ossim_uint32 zero_based_band); + + /** + * Returns the normalized low clip point for band. + * Will return OSSIM_DBL_NAN if: + * - Band is out of range. + * - Connection is not complete. + * - Histogram has not been set. + */ + ossim_float64 getLowNormalizedClipPoint(ossim_uint32 zero_based_band) const; + + /** + * Returns the normalized low clip point which is the average of all bands. + * + * Will return OSSIM_DBL_NAN if: + * - Band is out of range. + * - Connection is not complete. + * - Histogram has not been set. + */ + ossim_float64 getLowNormalizedClipPoint() const; + + /** + * Returns the normalized high clip point for band. + * + * Will return OSSIM_DBL_NAN if: + * - Band is out of range. + * - Connection is not complete. + * - Histogram has not been set. + */ + ossim_float64 getHighNormalizedClipPoint(ossim_uint32 zero_based_band) const; + /** + * Returns the normalized High clip point which is the average of all bands. + * + * Will return OSSIM_DBL_NAN if: + * - Band is out of range. + * - Connection is not complete. + * - Histogram has not been set. + */ + ossim_float64 getHighNormalizedClipPoint() const; + + /** + * Returns the low clip point for band. + * Clip points are DN values relative to the scalar type. + * + * Will return OSSIM_DBL_NAN if: + * - Band is out of range. + * - Connection is not complete. + * - Histogram has not been set. + */ + ossim_float64 getLowClipPoint(ossim_uint32 zero_based_band) const; + + /** + * Returns the low clip point which is the average of all bands. + * + * Will return OSSIM_DBL_NAN if: + * - Band is out of range. + * - Connection is not complete. + * - Histogram has not been set. + */ + ossim_float64 getLowClipPoint() const; + + /** + * Returns the high clip point for band. + * Clip points are DN values relative to the scalar type. + * + * Will return OSSIM_DBL_NAN if: + * - Band is out of range. + * - Connection is not complete. + * - Histogram has not been set. + */ + ossim_float64 getHighClipPoint(ossim_uint32 zero_based_band) const; + + /** + * Returns the high clip point which is the average of all bands. + * + * Will return OSSIM_DBL_NAN if: + * - Band is out of range. + * - Connection is not complete. + * - Histogram has not been set. + */ + ossim_float64 getHighClipPoint() const; + + + /** + * Returns the mid point for band + * + * Will return OSSIM_DBL_NAN if: + * - Band is out of range. + * - Connection is not complete. + * - Histogram has not been set. + */ + ossim_float64 getMidPoint(ossim_uint32 zero_based_band) const; + + /** + * Returns the mid clip point which is the average of all bands. + * + * Will return OSSIM_DBL_NAN if: + * - Band is out of range. + * - Connection is not complete. + * - Histogram has not been set. + */ + ossim_float64 getMidPoint() const; + + /** + * Returns the minimum output value for band. + * + * Will return OSSIM_DBL_NAN if: + * - Band is out of range. + * - Connection is not complete. + */ + ossim_float64 getMinOutputValue(ossim_uint32 zero_based_band) const; + + /** + * Returns the minimum output value which is the average of all bands. + * + * Will return OSSIM_DBL_NAN if: + * - Band is out of range. + * - Connection is not complete. + */ + ossim_float64 getMinOutputValue() const; + + /** + * Returns the maximum output value for band. + * + * Will return OSSIM_DBL_NAN if: + * - Band is out of range. + * - Connection is not complete. + */ + ossim_float64 getMaxOutputValue(ossim_uint32 zero_based_band) const; + + /** + * Returns the maximum output value which is the average of all bands. + * + * Will return OSSIM_DBL_NAN if: + * - Band is out of range. + * - Connection is not complete. + */ + ossim_float64 getMaxOutputValue() const; + + /** + * Sets the histogram. + * If (own_histogram == true) this object will delete theHistogram + * on destruction. + */ + void setHistogram(ossimMultiResLevelHistogram* histogram, + bool own_histogram = true); + + /** + * Returns pointer to histogram for band and reduced res level. + * - Band is zero based relative to the input connection. This will be + * remapped to the histogram band using the "getOutputBandList()" to + * get the correct histogram band. + * + * Will return NULL if: + * - band is out range + * - res_level is out of range + * - theHistogram has not been initialized yet. + */ + ossimHistogram* getHistogram(ossim_uint32 zero_based_band, + ossim_uint32 res_level=0) const; + + /** + * Open the histogram file. + * With this method the histogram is owned by this object. + * Returns true on success, false on error. + */ + bool openHistogram(const ossimFilename& histogram_file); + + /** + * Returns the currently opened histogram. + * Returns ossimFilename::NIL if no histogram is loaded. + */ + ossimFilename getHistogramFile() const; + + /** + * Method to the save the state to a keyword list. + * Returns true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. + * Returns true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + + virtual ostream& print(ostream& os) const; + + friend ostream& operator <<(ostream& os, const ossimHistogramRemapper& hr); + +private: + // Do not allow copy constructor, operator=. + ossimHistogramRemapper(const ossimHistogramRemapper& hr); + ossimHistogramRemapper& operator=(const ossimHistogramRemapper& hr); + + void buildTable(); + void buildLinearTable(); + void buildAutoLinearMinMaxTable(); + template <class T> void buildLinearTable(T dummy); + template <class T> void buildAutoLinearMinMaxTableTemplate(T dummy); + + /** + * Sets clip points using mean and standard deviations then calls + * buildLinearTable method. + */ + void buildLinearTableStdFromMean(); + + /** + * Uses getNumberOfInputBands() to determine BANDS then calls + * initializeClips(BANDS) + */ + void initializeClips(); + + /** + * Initializes data members to some default state and size. + */ + void initializeClips(ossim_uint32 bands); + + /* + * Sets the count of the null bin to 0 so that clips from the low end + * ignore the null bin. + */ + void setNullCount() const; + + /** + * Initialized base class (ossimTableRemapper) values: + * - theTableBinCount + * - theTableBandCount + * - theTableType + * - theTable (resizes if not correct size. + */ + void setupTable(); + + void verifyEnabled(); + + /** + * Returns the histogram band that maps to the input band. + * Note: + * - This uses the current band list from "getOutputBandList()". + */ + ossim_uint32 getHistogramBand(ossim_uint32 input_band) const; + + + StretchMode theStretchMode; + bool theDirtyFlag; + bool theHistogramOwnerFlag; + ossimMultiResLevelHistogram* theHistogram; + ossim_uint32 theTableSizeInBytes; + vector<ossim_float64> theNormalizedLowClipPoint; + vector<ossim_float64> theNormalizedHighClipPoint; + vector<ossim_float64> theMidPoint; + vector<ossim_float64> theMinOutputValue; + vector<ossim_float64> theMaxOutputValue; + + // Maps zero based band to histogram band. + vector<ossim_uint32> theBandList; + + TYPE_DATA +}; + +#endif /* #ifndef ossimHistogramRemapper_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramThreshholdFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramThreshholdFilter.cpp new file mode 100644 index 0000000000..3b8a714177 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramThreshholdFilter.cpp @@ -0,0 +1,259 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimHistogramThreshholdFilter.cpp,v 1.15 2005/05/09 12:39:40 dburken Exp $ +#include <imaging/tile_sources/ossimHistogramThreshholdFilter.h> +#include <base/data_types/ossimMultiResLevelHistogram.h> +#include <base/data_types/ossimMultiBandHistogram.h> +#include <base/data_types/ossimHistogram.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimKeyword.h> +#include <base/common/ossimCommon.h> +#include <imaging/ossimImageData.h> +#include <base/context/ossimErrorContext.h> + +static const ossimKeyword MIN_VALUE_PERCENT_KW("min_percent", + "min percentage clip"); + +static const ossimKeyword MAX_VALUE_PERCENT_KW("max_percent", + "max percentage value"); + + +RTTI_DEF1(ossimHistogramThreshholdFilter, "ossimHistogramThreshholdFilter", ossimImageSourceHistogramFilter) + +ossimHistogramThreshholdFilter::ossimHistogramThreshholdFilter() + : ossimImageSourceHistogramFilter(), + theMinValuePercent(0.0), + theMaxValuePercent(0.0) +{ +} + +ossimHistogramThreshholdFilter::ossimHistogramThreshholdFilter(double minValuePercent, + double maxValuePercent, + ossimImageSource* inputSource, + ossimMultiResLevelHistogram* histogram) + : ossimImageSourceHistogramFilter(inputSource, histogram), + theMinValuePercent(minValuePercent), + theMaxValuePercent(maxValuePercent) +{ +} + +ossimHistogramThreshholdFilter::~ossimHistogramThreshholdFilter() +{ +} + +ossimRefPtr<ossimImageData> ossimHistogramThreshholdFilter::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if(!theInputConnection) return NULL; + + ossimRefPtr<ossimImageData> inputTile = + theInputConnection->getTile(tileRect, resLevel); + + if(!isSourceEnabled()) + { + return inputTile; + } + if(inputTile.valid() && + inputTile->getBuf() && + (inputTile->getDataObjectStatus()!=OSSIM_EMPTY)) + { + switch(inputTile->getScalarType()) + { + case OSSIM_UCHAR: + { + return runThreshholdStretchAlgorithm((ossim_uint8)0, + inputTile); + } + case OSSIM_USHORT16: + case OSSIM_USHORT11: + { + return runThreshholdStretchAlgorithm((ossim_uint16)0, + inputTile); + } + case OSSIM_SSHORT16: + { + return runThreshholdStretchAlgorithm(static_cast<ossim_sint16>(0), + inputTile); + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + return runThreshholdStretchAlgorithm(static_cast<double>(0), + inputTile); + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + return runThreshholdStretchAlgorithm(static_cast<float>(0), + inputTile); + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + ossimSetError("ossimHistogramThreshholdFilter", + ossimErrorCodes::OSSIM_ERROR, + "Unknown scalar type"); + break; + } + } + } + + return inputTile; +} + + +bool ossimHistogramThreshholdFilter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + if(ossimImageSourceHistogramFilter::loadState(kwl, prefix)) + { + const char* minPercent = kwl.find(prefix, MIN_VALUE_PERCENT_KW); + const char* maxPercent = kwl.find(prefix, MAX_VALUE_PERCENT_KW); + + if(minPercent) + { + theMinValuePercent = ossimString(minPercent).toDouble(); + } + else + { + theMinValuePercent = 0.0; + } + if(maxPercent) + { + theMaxValuePercent = ossimString(maxPercent).toDouble(); + } + else + { + theMaxValuePercent = 0.0; + } + } + else + { + return false; + } + + return true; +} + +bool ossimHistogramThreshholdFilter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + if(ossimImageSourceHistogramFilter::saveState(kwl, prefix)) + { + kwl.add(prefix, + MIN_VALUE_PERCENT_KW, + theMinValuePercent, + true); + kwl.add(prefix, + MAX_VALUE_PERCENT_KW, + theMaxValuePercent, + true); + } + else + { + return false; + } + + return true; +} + +void ossimHistogramThreshholdFilter::initialize() +{ + ossimImageSourceHistogramFilter::initialize(); +} + +template <class T> +ossimRefPtr<ossimImageData> ossimHistogramThreshholdFilter::runThreshholdStretchAlgorithm(T dummyVariable, + ossimRefPtr<ossimImageData>& tile) +{ + if(!getHistogram()) + { + return tile; + } + + ossimMultiBandHistogram* histo = getHistogram()->getMultiBandHistogram(0); + if(histo) + { + ossim_uint32 maxBands = ( (histo->getNumberOfBands() > + tile->getNumberOfBands())? + tile->getNumberOfBands(): + histo->getNumberOfBands()); + + long offsetUpperBound = tile->getHeight()*tile->getWidth(); + + for(ossim_uint32 band = 0; band < maxBands; ++band) + { + ossimHistogram* h = histo->getHistogram(band); + T* buf = static_cast<T*>(tile->getBuf(band)); + + if(h&&buf) + { + T np = static_cast<T>(tile->getNullPix(band)); + T minPix = static_cast<T>(tile->getMinPix(band)); + T maxPix = static_cast<T>(tile->getMaxPix(band)); + double range = (maxPix - minPix); + double maxClip = (h->HighClipVal(theMaxValuePercent/100.0)/(double)h->GetRes()); + double minClip = (h->LowClipVal(theMinValuePercent/100.0)/(double)h->GetRes()); + ossim_float64 normPix; + double delta = fabs(maxClip - minClip); + if(delta > 0.0) + { + for(long offset = 0; offset < offsetUpperBound; ++offset) + { + if(buf[offset] != np) + { + normPix = ((double)buf[offset]-minPix)/range; + if(normPix <= minClip) + { + buf[offset] = minPix; + } + else if(normPix >= maxClip) + { + buf[offset] = maxPix; + } + else + { + double t = (normPix - minClip)/delta; + T value = static_cast<T>(minPix + range*t); + buf[offset] = value; + } + } + } + } + } + } + + tile->validate(); + } + + return tile; +} + +void ossimHistogramThreshholdFilter::setMinValuePercent(double minValue) +{ + theMinValuePercent = minValue; +} + +void ossimHistogramThreshholdFilter::setMaxValuePercent(double maxValue) +{ + theMaxValuePercent = maxValue; +} + +double ossimHistogramThreshholdFilter::getMinValuePercent()const +{ + return theMinValuePercent; +} + +double ossimHistogramThreshholdFilter::getMaxValuePercent()const +{ + return theMaxValuePercent; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramThreshholdFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramThreshholdFilter.h new file mode 100644 index 0000000000..c687292ef3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHistogramThreshholdFilter.h @@ -0,0 +1,51 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimHistogramThreshholdFilter.h,v 1.8 2005/02/11 15:07:33 dburken Exp $ +#ifndef ossimHistogramThreshholdFilter_HEADER +#define ossimHistogramThreshholdFilter_HEADER +#include <imaging/tile_sources/ossimImageSourceHistogramFilter.h> + +class ossimHistogramThreshholdFilter : public ossimImageSourceHistogramFilter +{ +public: + ossimHistogramThreshholdFilter(); + ossimHistogramThreshholdFilter(double minValuePercent, + double maxValuePercent, + ossimImageSource* inputSource, + ossimMultiResLevelHistogram* histogram); + virtual ~ossimHistogramThreshholdFilter(); + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + + virtual void setMinValuePercent(double minValue); + virtual void setMaxValuePercent(double maxValue); + + virtual double getMinValuePercent()const; + virtual double getMaxValuePercent()const; + + virtual void initialize(); + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + +protected: + + double theMinValuePercent; + double theMaxValuePercent; + template <class T> + ossimRefPtr<ossimImageData> runThreshholdStretchAlgorithm( + T dummyVariable, + ossimRefPtr<ossimImageData>& tile); + +TYPE_DATA +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHsiRemapper.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHsiRemapper.cpp new file mode 100644 index 0000000000..e0a1b0e820 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHsiRemapper.cpp @@ -0,0 +1,2751 @@ +//******************************************************************* +// Copyright (C) 2002 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Remapper to adjust hue, saturation and intensity. +// +//************************************************************************* +// $Id: ossimHsiRemapper.cpp,v 1.34 2005/11/14 21:48:37 dburken Exp $ + +#include <imaging/tile_sources/ossimHsiRemapper.h> +#include <base/common/ossimTrace.h> +#include <base/data_types/color_space/ossimNormRgbVector.h> +#include <base/data_types/color_space/ossimHsiVector.h> +#include <base/context/ossimNotifyContext.h> +#include <imaging/factory/ossimImageDataFactory.h> + +RTTI_DEF1(ossimHsiRemapper, "ossimHsiRemapper", ossimImageSourceFilter) + +static ossimTrace traceDebug("ossimHsiRemapper:debug"); + +//*** +// State keywords: +//*** +static const char MASTER_HUE_OFFSET_KW[] = "hsi_master_hue_offset"; +static const char MASTER_SATURATION_OFFSET_KW[] = "hsi_master_saturation_offset"; +static const char MASTER_INTENSITY_OFFSET_KW[] = "hsi_master_intensity_offset"; +static const char MASTER_INTENSITY_LOW_CLIP_KW[] = "hsi_master_intensity_low_clip"; +static const char MASTER_INTENSITY_HIGH_CLIP_KW[] = "hsi_master_intensity_high_clip"; + +static const char RED_HUE_OFFSET_KW[] = "hsi_red_hue_offset"; +static const char RED_HUE_LOW_RANGE_KW[] = "hsi_red_hue_low_range"; +static const char RED_HUE_HIGH_RANGE_KW[] = "hsi_red_hue_high_range"; +static const char RED_HUE_BLEND_RANGE_KW[] = "hsi_red_hue_blend_range"; +static const char RED_SATURATION_OFFSET_KW[] = "hsi_red_saturation_offset"; +static const char RED_INTENSITY_OFFSET_KW[] = "hsi_red_intensity_offset"; + +static const char YELLOW_HUE_OFFSET_KW[] = "hsi_yellow_hue_offset"; +static const char YELLOW_HUE_LOW_RANGE_KW[] = "hsi_yellow_hue_low_range"; +static const char YELLOW_HUE_HIGH_RANGE_KW[] = "hsi_yellow_hue_high_range"; +static const char YELLOW_HUE_BLEND_RANGE_KW[] = "hsi_yellow_hue_blend_range"; +static const char YELLOW_SATURATION_OFFSET_KW[] = "hsi_yellow_saturation_offset"; +static const char YELLOW_INTENSITY_OFFSET_KW[] = "hsi_yellow_intensity_offset"; + +static const char GREEN_HUE_OFFSET_KW[] = "hsi_green_hue_offset"; +static const char GREEN_HUE_LOW_RANGE_KW[] = "hsi_green_hue_low_range"; +static const char GREEN_HUE_HIGH_RANGE_KW[] = "hsi_green_hue_high_range"; +static const char GREEN_HUE_BLEND_RANGE_KW[] = "hsi_green_hue_blend_range"; +static const char GREEN_SATURATION_OFFSET_KW[] = "hsi_green_saturation_offset"; +static const char GREEN_INTENSITY_OFFSET_KW[] = "hsi_green_intensity_offset"; + +static const char CYAN_HUE_OFFSET_KW[] = "hsi_cyan_hue_offset"; +static const char CYAN_HUE_LOW_RANGE_KW[] = "hsi_cyan_hue_low_range"; +static const char CYAN_HUE_HIGH_RANGE_KW[] = "hsi_cyan_hue_high_range"; +static const char CYAN_HUE_BLEND_RANGE_KW[] = "hsi_cyan_hue_blend_range"; +static const char CYAN_SATURATION_OFFSET_KW[] = "hsi_cyan_saturation_offset"; +static const char CYAN_INTENSITY_OFFSET_KW[] = "hsi_cyan_intensity_offset"; + +static const char BLUE_HUE_OFFSET_KW[] = "hsi_blue_hue_offset"; +static const char BLUE_HUE_LOW_RANGE_KW[] = "hsi_blue_hue_low_range"; +static const char BLUE_HUE_HIGH_RANGE_KW[] = "hsi_blue_hue_high_range"; +static const char BLUE_HUE_BLEND_RANGE_KW[] = "hsi_blue_hue_blend_range"; +static const char BLUE_SATURATION_OFFSET_KW[] = "hsi_blue_saturation_offset"; +static const char BLUE_INTENSITY_OFFSET_KW[] = "hsi_blue_intensity_offset"; + +static const char MAGENTA_HUE_OFFSET_KW[] = "hsi_magenta_hue_offset"; +static const char MAGENTA_HUE_LOW_RANGE_KW[] = "hsi_magenta_hue_low_range"; +static const char MAGENTA_HUE_HIGH_RANGE_KW[] = "hsi_magenta_hue_high_range"; +static const char MAGENTA_HUE_BLEND_RANGE_KW[] = "hsi_magenta_hue_blend_range"; +static const char MAGENTA_SATURATION_OFFSET_KW[] = "hsi_magenta_saturation_offset"; +static const char MAGENTA_INTENSITY_OFFSET_KW[] = "hsi_magenta_intensity_offset"; + +static const char WHITE_OBJECT_CLIP_KW[] = "hsi_white_object_clip"; + +static const double DEFAULT_BLEND = 15.0; +static const double MAX_BLEND = 30.0; + +ossimHsiRemapper::ossimHsiRemapper() + : + ossimImageSourceFilter (), // base class + + theTile (NULL), + theBuffer (NULL), + theNormalizedMinPix (0.0), + + theMasterHueOffset (0.0), + theMasterSaturationOffset (0.0), + theMasterIntensityOffset (0.0), + theMasterIntensityLowClip (0.0), + theMasterIntensityHighClip (1.0), + + theRedHueOffset (0.0), + theRedHueLowRange (-30.0), + theRedHueHighRange (30.0), + theRedHueBlendRange (DEFAULT_BLEND), + theRedSaturationOffset (0.0), + theRedIntensityOffset (0.0), + + theYellowHueOffset (0.0), + theYellowHueLowRange (30.0), + theYellowHueHighRange (90.0), + theYellowHueBlendRange (DEFAULT_BLEND), + theYellowSaturationOffset (0.0), + theYellowIntensityOffset (0.0), + + theGreenHueOffset (0.0), + theGreenHueLowRange (90.0), + theGreenHueHighRange (150.0), + theGreenHueBlendRange (DEFAULT_BLEND), + theGreenSaturationOffset (0.0), + theGreenIntensityOffset (0.0), + + theCyanHueOffset (0.0), + theCyanHueLowRange (150.0), + theCyanHueHighRange (210.0), + theCyanHueBlendRange (DEFAULT_BLEND), + theCyanSaturationOffset (0.0), + theCyanIntensityOffset (0.0), + + theBlueHueOffset (0.0), + theBlueHueLowRange (210.0), + theBlueHueHighRange (270.0), + theBlueHueBlendRange (DEFAULT_BLEND), + theBlueSaturationOffset (0.0), + theBlueIntensityOffset (0.0), + + theMagentaHueOffset (0.0), + theMagentaHueLowRange (270.0), + theMagentaHueHighRange (330.0), + theMagentaHueBlendRange (DEFAULT_BLEND), + theMagentaSaturationOffset (0.0), + theMagentaIntensityOffset (0.0), + + theWhiteObjectClip (1.0) +{ + //*** + // Set the base class "theEnableFlag" to off since no adjustments have been + // made yet. + //*** + disableSource(); + + // Construction not complete. +} + +ossimHsiRemapper::~ossimHsiRemapper() +{ + theTile = NULL; + if (theBuffer) + { + delete [] theBuffer; + theBuffer = NULL; + } +} + +ossimRefPtr<ossimImageData> ossimHsiRemapper::getTile( + const ossimIrect& tile_rect, + ossim_uint32 resLevel) +{ + if(!theInputConnection) + { + return ossimRefPtr<ossimImageData>(); + } + + // Fetch tile from pointer from the input source. + ossimRefPtr<ossimImageData> inputTile = theInputConnection->getTile( + tile_rect, resLevel); + + // Check for remap bypass or a null tile return from input: + if (!theEnableFlag || !inputTile) + { + return inputTile; + } + + // Check for first time through or size change. + if ( !theTile.valid() || + tile_rect.height() != theTile->getHeight() || + tile_rect.width() != theTile->getWidth() ) + { + allocate(tile_rect); + } + + //--- + // Set the image rectangle of the tile. + // Note that this will resize the tiles buffers if + theTile->setImageRectangle(tile_rect); + + // Get its status. + ossimDataObjectStatus tile_status = inputTile->getDataObjectStatus(); + if ( (tile_status == OSSIM_NULL) || (tile_status == OSSIM_EMPTY) ) + { + theTile->makeBlank(); + return theTile; + } + + double* rgbBuf[3]; + const ossim_uint32 PPT = theTile->getSizePerBand(); // Pixels Per Tile + + rgbBuf[0] = theBuffer; + rgbBuf[1] = &(theBuffer[PPT]); + rgbBuf[2] = &(rgbBuf[1][PPT]); + + switch(inputTile->getNumberOfBands()) + { + case 1: + case 2: + { + // Copy the first band only. + inputTile->copyTileBandToNormalizedBuffer(0, rgbBuf[0]); + memcpy(rgbBuf[1], rgbBuf[0], PPT*sizeof(double)); + memcpy(rgbBuf[2], rgbBuf[0], PPT*sizeof(double)); + break; + } + case 3: + { + inputTile->copyTileToNormalizedBuffer(theBuffer); + break; + } + default: + { + inputTile->copyTileBandToNormalizedBuffer(0, rgbBuf[0]); + inputTile->copyTileBandToNormalizedBuffer(1, rgbBuf[1]); + inputTile->copyTileBandToNormalizedBuffer(2, rgbBuf[2]); + break; + } + } + + ossimNormRgbVector rgb; + ossimHsiVector hsi; + double r = 0.0; + double g = 0.0; + double b = 0.0; + double h = 0.0; + double s = 0.0; + double i = 0.0; + ossim_uint32 idx; + // Convert the rgb value to hsi and adjust values. + for (idx=0; idx<PPT; ++idx) + { + r = rgbBuf[0][idx]; + g = rgbBuf[1][idx]; + b = rgbBuf[2][idx]; + + rgb = ossimNormRgbVector(r,g,b); + hsi = rgb; + + h = hsi.getH(); + s = hsi.getS(); + i = hsi.getI(); + + if(i > FLT_EPSILON) + { + double h_offset = theMasterHueOffset; + double s_offset = theMasterSaturationOffset; + double i_offset = theMasterIntensityOffset; + + //*** + // Note: For the purpose of checking to see if in the red range, + // make the hue negative if it's >= 315.0 and < 360.0. + // The red low and high ranges are stored in the same manner. + //*** + double red_hue = h; + if (red_hue >= 315.0 && red_hue < 360.0) red_hue = red_hue - 360.0; + + if ( red_hue >= theRedHueLowRange && red_hue <= theRedHueHighRange) + { + // Adjust the reds. + + double bf = 1.0; // blend factor + if ( red_hue < (theRedHueLowRange + theRedHueBlendRange) ) + { + bf = (red_hue - theRedHueLowRange) / theRedHueBlendRange; + } + else if ( red_hue > (theRedHueHighRange - theRedHueBlendRange) ) + { + bf = (theRedHueHighRange - red_hue) / theRedHueBlendRange; + } + + h_offset += (theRedHueOffset * bf); + s_offset += (theRedSaturationOffset * bf); + i_offset += (theRedIntensityOffset * bf); + } + + if (h >= theYellowHueLowRange && h <= theYellowHueHighRange) + { + // Adjust the yellows. + + double bf = 1.0; // blend factor + if ( h < (theYellowHueLowRange + theYellowHueBlendRange) ) + { + bf = (h - theYellowHueLowRange) / theYellowHueBlendRange; + } + else if ( h > (theYellowHueHighRange - theYellowHueBlendRange) ) + { + bf = (theYellowHueHighRange - h) / theYellowHueBlendRange; + } + + h_offset += (theYellowHueOffset * bf); + s_offset += (theYellowSaturationOffset * bf); + i_offset += (theYellowIntensityOffset * bf); + } + + if (h >= theGreenHueLowRange && h <= theGreenHueHighRange) + { + // Adjust the greens. + + double bf = 1.0; // blend factor + if ( h < (theGreenHueLowRange + theGreenHueBlendRange) ) + { + bf = (h - theGreenHueLowRange) / theGreenHueBlendRange; + } + else if ( h > (theGreenHueHighRange - theGreenHueBlendRange) ) + { + bf = (theGreenHueHighRange - h) / theGreenHueBlendRange; + } + + h_offset += (theGreenHueOffset * bf); + s_offset += (theGreenSaturationOffset * bf); + i_offset += (theGreenIntensityOffset * bf); + } + + if (h >= theCyanHueLowRange && h <= theCyanHueHighRange) + { + // Adjust the cyans. + + double bf = 1.0; // blend factor + if ( h < (theCyanHueLowRange + theCyanHueBlendRange) ) + { + bf = (h - theCyanHueLowRange) / theCyanHueBlendRange; + } + else if ( h > (theCyanHueHighRange - theCyanHueBlendRange) ) + { + bf = (theCyanHueHighRange - h) / theCyanHueBlendRange; + } + + h_offset += (theCyanHueOffset * bf); + s_offset += (theCyanSaturationOffset * bf); + i_offset += (theCyanIntensityOffset * bf); + } + + if (h >= theBlueHueLowRange && h <= theBlueHueHighRange) + { + // Adjust the blues. + + double bf = 1.0; // blend factor + if ( h < (theBlueHueLowRange + theBlueHueBlendRange) ) + { + bf = (h - theBlueHueLowRange) / theBlueHueBlendRange; + } + else if ( h > (theBlueHueHighRange - theBlueHueBlendRange) ) + { + bf = (theBlueHueHighRange - h) / theBlueHueBlendRange; + } + + h_offset += (theBlueHueOffset * bf); + s_offset += (theBlueSaturationOffset * bf); + i_offset += (theBlueIntensityOffset * bf); + } + + if (h >= theMagentaHueLowRange && h <= theMagentaHueHighRange) + { + // Adjust the magentas. + + double bf = 1.0; // blend factor + if ( h < (theMagentaHueLowRange + theMagentaHueBlendRange) ) + { + bf = (h - theMagentaHueLowRange) / theMagentaHueBlendRange; + } + else if ( h > (theMagentaHueHighRange - theMagentaHueBlendRange) ) + { + bf = (theMagentaHueHighRange - h) / theMagentaHueBlendRange; + } + + h_offset += (theMagentaHueOffset * bf); + s_offset += (theMagentaSaturationOffset * bf); + i_offset += (theMagentaIntensityOffset * bf); + } + + // Apply the hue offset. + h += h_offset; + + // Make sure the hue is between 0 and 360... + if (h < 0.0) h += 360.0; + else if (h >= 360) h -= 360.0; + + // Apply the saturation offset clamping/clipping to 0.0/1.0. + s += s_offset; + s = (s > 0.0 ? (s < 1.0 ? s : 1.0) : 0.0); + + // Apply the intensity offset clamping/clipping to 0.0/1.0. + i += i_offset; + i = (i > 0.0 ? (i < 1.0 ? i : 1.0) : 0.0); + + // Stretch the intensity channel. +// i = (i - theMasterIntensityLowClip) * +// ( 1.0 / (theMasterIntensityHighClip - +// theMasterIntensityLowClip) ); + i = (i - theMasterIntensityLowClip)/(theMasterIntensityHighClip - + theMasterIntensityLowClip); + + hsi.setH(h); + hsi.setS(s); + hsi.setI(i); + + rgb = hsi; + + r = rgb.getR(); + g = rgb.getG(); + b = rgb.getB(); + if ( (theWhiteObjectClip < 1.0) && + (r > theWhiteObjectClip) && + (g > theWhiteObjectClip) && + (b > theWhiteObjectClip) ) + { + r = theWhiteObjectClip; + g = theWhiteObjectClip; + b = theWhiteObjectClip; + } + // Do min/max range check and assign back to buffer. + rgbBuf[0][idx] = r > theNormalizedMinPix ? (r < 1.0 ? r : 1.0) : + theNormalizedMinPix; + rgbBuf[1][idx] = g > theNormalizedMinPix ? (g < 1.0 ? g : 1.0) : + theNormalizedMinPix; + rgbBuf[2][idx] = b > theNormalizedMinPix ? (b < 1.0 ? b : 1.0) : + theNormalizedMinPix; + } // End of "if(i > FLT_EPSILON)" + else + { + rgbBuf[0][idx] = 0.0; + rgbBuf[1][idx] = 0.0; + rgbBuf[2][idx] = 0.0; + } + + } // End of loop through pixels in a tile. + // Copy the buffer to the output tile. + theTile->copyNormalizedBufferToTile(theBuffer); + + // Update the tile status. + theTile->validate(); + + return theTile; +} + +void ossimHsiRemapper::initialize() +{ + ossimImageSourceFilter::initialize(); + if (theTile.valid()) + { + theTile = NULL; + if(theBuffer) + { + delete []theBuffer; + theBuffer = NULL; + } + } +} + +void ossimHsiRemapper::allocate(const ossimIrect& rect) +{ + + if(theInputConnection) + { + theTile = ossimImageDataFactory::instance()->create(this,this); + theTile->initialize(); + + ossim_uint32 width = rect.width(); + ossim_uint32 height = rect.height(); + ossim_uint32 size = width * height * 3; // Buffer always 3 bands. + theBuffer = new double[size]; + memset(theBuffer, '\0', sizeof(double) * size); + + // Get the minimum normalized pixel value. + theNormalizedMinPix = calculateMinNormValue(); + } +} + +bool ossimHsiRemapper::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + static const char MODULE[] = "ossimHsiRemapper::loadState()"; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " entering..." << endl; + } + + // Make a prefix. + ossimString tmpPrefix; + if (prefix) tmpPrefix += prefix; + + const char* lookupReturn; + + lookupReturn = kwl.find(tmpPrefix.c_str(), MASTER_HUE_OFFSET_KW); + if(lookupReturn) + { + setMasterHueOffset(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), MASTER_SATURATION_OFFSET_KW); + if(lookupReturn) + { + setMasterSaturationOffset(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), MASTER_INTENSITY_OFFSET_KW); + if(lookupReturn) + { + setMasterIntensityOffset(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), MASTER_INTENSITY_LOW_CLIP_KW); + if(lookupReturn) + { + setMasterIntensityLowClip(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), MASTER_INTENSITY_HIGH_CLIP_KW); + if(lookupReturn) + { + setMasterIntensityHighClip(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), RED_HUE_OFFSET_KW); + if(lookupReturn) + { + setRedHueOffset(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), RED_HUE_LOW_RANGE_KW); + if(lookupReturn) + { + setRedHueLowRange(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), RED_HUE_HIGH_RANGE_KW); + if(lookupReturn) + { + setRedHueHighRange(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), RED_HUE_BLEND_RANGE_KW); + if(lookupReturn) + { + setRedHueBlendRange(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), RED_SATURATION_OFFSET_KW); + if(lookupReturn) + { + setRedSaturationOffset(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), RED_INTENSITY_OFFSET_KW); + if(lookupReturn) + { + setRedIntensityOffset(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), YELLOW_HUE_OFFSET_KW); + if(lookupReturn) + { + setYellowHueOffset(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), YELLOW_HUE_LOW_RANGE_KW); + if(lookupReturn) + { + setYellowHueLowRange(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), YELLOW_HUE_HIGH_RANGE_KW); + if(lookupReturn) + { + setYellowHueHighRange(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), YELLOW_HUE_BLEND_RANGE_KW); + if(lookupReturn) + { + setYellowHueBlendRange(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), YELLOW_SATURATION_OFFSET_KW); + if(lookupReturn) + { + setYellowSaturationOffset(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), YELLOW_INTENSITY_OFFSET_KW); + if(lookupReturn) + { + setYellowIntensityOffset(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), GREEN_HUE_OFFSET_KW); + if(lookupReturn) + { + setGreenHueOffset(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), GREEN_HUE_LOW_RANGE_KW); + if(lookupReturn) + { + setGreenHueLowRange(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), GREEN_HUE_HIGH_RANGE_KW); + if(lookupReturn) + { + setGreenHueHighRange(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), GREEN_HUE_BLEND_RANGE_KW); + if(lookupReturn) + { + setGreenHueBlendRange(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), GREEN_SATURATION_OFFSET_KW); + if(lookupReturn) + { + setGreenSaturationOffset(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), GREEN_INTENSITY_OFFSET_KW); + if(lookupReturn) + { + setGreenIntensityOffset(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), CYAN_HUE_OFFSET_KW); + if(lookupReturn) + { + setCyanHueOffset(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), CYAN_HUE_LOW_RANGE_KW); + if(lookupReturn) + { + setCyanHueLowRange(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), CYAN_HUE_HIGH_RANGE_KW); + if(lookupReturn) + { + setCyanHueHighRange(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), CYAN_HUE_BLEND_RANGE_KW); + if(lookupReturn) + { + setCyanHueBlendRange(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), CYAN_SATURATION_OFFSET_KW); + if(lookupReturn) + { + setCyanSaturationOffset(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), CYAN_INTENSITY_OFFSET_KW); + if(lookupReturn) + { + setCyanIntensityOffset(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), BLUE_HUE_OFFSET_KW); + if(lookupReturn) + { + setBlueHueOffset(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), BLUE_HUE_LOW_RANGE_KW); + if(lookupReturn) + { + setBlueHueLowRange(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), BLUE_HUE_HIGH_RANGE_KW); + if(lookupReturn) + { + setBlueHueHighRange(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), BLUE_HUE_BLEND_RANGE_KW); + if(lookupReturn) + { + setBlueHueBlendRange(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), BLUE_SATURATION_OFFSET_KW); + if(lookupReturn) + { + setBlueSaturationOffset(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), BLUE_INTENSITY_OFFSET_KW); + if(lookupReturn) + { + setBlueIntensityOffset(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), MAGENTA_HUE_OFFSET_KW); + if(lookupReturn) + { + setMagentaHueOffset(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), MAGENTA_HUE_LOW_RANGE_KW); + if(lookupReturn) + { + setMagentaHueLowRange(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), MAGENTA_HUE_HIGH_RANGE_KW); + if(lookupReturn) + { + setMagentaHueHighRange(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), MAGENTA_HUE_BLEND_RANGE_KW); + if(lookupReturn) + { + setMagentaHueBlendRange(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), MAGENTA_SATURATION_OFFSET_KW); + if(lookupReturn) + { + setMagentaSaturationOffset(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), MAGENTA_INTENSITY_OFFSET_KW); + if(lookupReturn) + { + setMagentaIntensityOffset(atof(lookupReturn)); + } + + lookupReturn = kwl.find(tmpPrefix.c_str(), WHITE_OBJECT_CLIP_KW); + if(lookupReturn) + { + setWhiteObjectClip(atof(lookupReturn)); + } + + //*** + // Initialize the base class. Do this last so that the enable/disable + // doesn't get overridden by the "set*" methods. + //*** + ossimImageSourceFilter::loadState(kwl, tmpPrefix.c_str()); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "" + << *this + << "\nreturning..." + << endl; + } + + return true; +} + +bool ossimHsiRemapper::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + static const char MODULE[] = "ossimHsiRemapper::saveStateTo()"; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << "entering..." << endl; + } + + // Call the base class getStateFrom. + ossimImageSourceFilter::saveState(kwl, prefix); + + kwl.add(prefix, MASTER_HUE_OFFSET_KW, theMasterHueOffset); + + kwl.add(prefix, MASTER_SATURATION_OFFSET_KW, theMasterSaturationOffset); + + kwl.add(prefix, MASTER_INTENSITY_OFFSET_KW, theMasterIntensityOffset); + + kwl.add(prefix, MASTER_INTENSITY_LOW_CLIP_KW, theMasterIntensityLowClip); + + kwl.add(prefix, MASTER_INTENSITY_HIGH_CLIP_KW, theMasterIntensityHighClip); + + kwl.add(prefix, RED_HUE_OFFSET_KW, theRedHueOffset); + + kwl.add(prefix, RED_HUE_LOW_RANGE_KW, theRedHueLowRange); + + kwl.add(prefix, RED_HUE_HIGH_RANGE_KW, theRedHueHighRange); + + kwl.add(prefix, RED_HUE_BLEND_RANGE_KW, theRedHueBlendRange); + + kwl.add(prefix, RED_SATURATION_OFFSET_KW, theRedSaturationOffset); + + kwl.add(prefix, RED_INTENSITY_OFFSET_KW, theRedIntensityOffset); + + kwl.add(prefix, YELLOW_HUE_OFFSET_KW, theYellowHueOffset); + + kwl.add(prefix, YELLOW_HUE_LOW_RANGE_KW, theYellowHueLowRange); + + kwl.add(prefix, YELLOW_HUE_HIGH_RANGE_KW, theYellowHueHighRange); + + kwl.add(prefix, YELLOW_HUE_BLEND_RANGE_KW, theYellowHueBlendRange); + + kwl.add(prefix, YELLOW_SATURATION_OFFSET_KW, theYellowSaturationOffset); + + kwl.add(prefix, YELLOW_INTENSITY_OFFSET_KW, theYellowIntensityOffset); + + kwl.add(prefix, GREEN_HUE_OFFSET_KW, theGreenHueOffset); + + kwl.add(prefix, GREEN_HUE_LOW_RANGE_KW, theGreenHueLowRange); + + kwl.add(prefix, GREEN_HUE_HIGH_RANGE_KW, theGreenHueHighRange); + + kwl.add(prefix, GREEN_HUE_BLEND_RANGE_KW, theGreenHueBlendRange); + + kwl.add(prefix, GREEN_SATURATION_OFFSET_KW, theGreenSaturationOffset); + + kwl.add(prefix, GREEN_INTENSITY_OFFSET_KW, theGreenIntensityOffset); + + kwl.add(prefix, CYAN_HUE_OFFSET_KW, theCyanHueOffset); + + kwl.add(prefix, CYAN_HUE_LOW_RANGE_KW, theCyanHueLowRange); + + kwl.add(prefix, CYAN_HUE_HIGH_RANGE_KW, theCyanHueHighRange); + + kwl.add(prefix, CYAN_HUE_BLEND_RANGE_KW, theCyanHueBlendRange); + + kwl.add(prefix, CYAN_SATURATION_OFFSET_KW, theCyanSaturationOffset); + + kwl.add(prefix, CYAN_INTENSITY_OFFSET_KW, theCyanIntensityOffset); + + kwl.add(prefix, BLUE_HUE_OFFSET_KW, theBlueHueOffset); + + kwl.add(prefix, BLUE_HUE_LOW_RANGE_KW, theBlueHueLowRange); + + kwl.add(prefix, BLUE_HUE_HIGH_RANGE_KW, theBlueHueHighRange); + + kwl.add(prefix, BLUE_HUE_BLEND_RANGE_KW, theBlueHueBlendRange); + + kwl.add(prefix, BLUE_SATURATION_OFFSET_KW, theBlueSaturationOffset); + + kwl.add(prefix, BLUE_INTENSITY_OFFSET_KW, theBlueIntensityOffset); + + kwl.add(prefix, MAGENTA_HUE_OFFSET_KW, theMagentaHueOffset); + + kwl.add(prefix, MAGENTA_HUE_LOW_RANGE_KW, theMagentaHueLowRange); + + kwl.add(prefix, MAGENTA_HUE_HIGH_RANGE_KW, theMagentaHueHighRange); + + kwl.add(prefix, MAGENTA_HUE_BLEND_RANGE_KW, theMagentaHueBlendRange); + + kwl.add(prefix, MAGENTA_SATURATION_OFFSET_KW, theMagentaSaturationOffset); + + kwl.add(prefix, MAGENTA_INTENSITY_OFFSET_KW, theMagentaIntensityOffset); + + kwl.add(prefix, WHITE_OBJECT_CLIP_KW, theWhiteObjectClip); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << "returning..." << endl; + } + + return true; +} + +void ossimHsiRemapper::resetGroup(int color_group) +{ + switch (color_group) + { + case RED: + resetRed(); + break; + case YELLOW: + resetYellow(); + break; + case GREEN: + resetGreen(); + break; + case CYAN: + resetCyan(); + break; + case BLUE: + resetBlue(); + break; + case MAGENTA: + resetMagenta(); + break; + case ALL: + resetMaster(); + break; + default: + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimHsiRemapper::setSaturationOffset NOTICE: Range error!" + << endl; + break; + } + verifyEnabled(); +} + +void ossimHsiRemapper::resetAll() +{ + theMasterHueOffset = 0.0; + theMasterSaturationOffset = 0.0; + theMasterIntensityOffset = 0.0; + theMasterIntensityLowClip = 0.0; + theMasterIntensityHighClip = 1.0; + + theRedHueOffset = 0.0; + theRedHueLowRange = -30.0; + theRedHueHighRange = 30.0; + theRedHueBlendRange = DEFAULT_BLEND; + theRedSaturationOffset = 0.0; + theRedIntensityOffset = 0.0; + + theYellowHueOffset = 0.0; + theYellowHueLowRange = 30.0; + theYellowHueHighRange = 90.0; + theYellowHueBlendRange = DEFAULT_BLEND; + theYellowSaturationOffset = 0.0; + theYellowIntensityOffset = 0.0; + + theGreenHueOffset = 0.0; + theGreenHueLowRange = 90.0; + theGreenHueHighRange = 150.0; + theGreenHueBlendRange = DEFAULT_BLEND; + theGreenSaturationOffset = 0.0; + theGreenIntensityOffset = 0.0; + + theCyanHueOffset = 0.0; + theCyanHueLowRange = 150.0; + theCyanHueHighRange = 210.0; + theCyanHueBlendRange = DEFAULT_BLEND; + theCyanSaturationOffset = 0.0; + theCyanIntensityOffset = 0.0; + + theBlueHueOffset = 0.0; + theBlueHueLowRange = 210.0; + theBlueHueHighRange = 270.0; + theBlueHueBlendRange = DEFAULT_BLEND; + theBlueSaturationOffset = 0.0; + theBlueIntensityOffset = 0.0; + + theMagentaHueOffset = 0.0; + theMagentaHueLowRange = 270.0; + theMagentaHueHighRange = 330.0; + theMagentaHueBlendRange = DEFAULT_BLEND; + theMagentaSaturationOffset = 0.0; + theMagentaIntensityOffset = 0.0; + + theWhiteObjectClip = 1.0; + + disableSource(); +} + +void ossimHsiRemapper::resetMaster() +{ + theMasterHueOffset = 0.0; + theMasterSaturationOffset = 0.0; + theMasterIntensityOffset = 0.0; + theMasterIntensityLowClip = 0.0; + theMasterIntensityHighClip = 1.0; + + verifyEnabled(); +} + +void ossimHsiRemapper::resetRed() +{ + theRedHueOffset = 0.0; + theRedHueLowRange = -30.0; + theRedHueHighRange = 30.0; + theRedHueBlendRange = DEFAULT_BLEND; + theRedSaturationOffset = 0.0; + theRedIntensityOffset = 0.0; + + verifyEnabled(); +} + +void ossimHsiRemapper::resetYellow() +{ + theYellowHueOffset = 0.0; + theYellowHueLowRange = 30.0; + theYellowHueHighRange = 90.0; + theYellowHueBlendRange = DEFAULT_BLEND; + theYellowSaturationOffset = 0.0; + theYellowIntensityOffset = 0.0; + + verifyEnabled(); +} + +void ossimHsiRemapper::resetGreen() +{ + theGreenHueOffset = 0.0; + theGreenHueLowRange = 90.0; + theGreenHueHighRange = 150.0; + theGreenHueBlendRange = DEFAULT_BLEND; + theGreenSaturationOffset = 0.0; + theGreenIntensityOffset = 0.0; + + verifyEnabled(); +} + +void ossimHsiRemapper::resetCyan() +{ + theCyanHueOffset = 0.0; + theCyanHueLowRange = 150.0; + theCyanHueHighRange = 210.0; + theCyanHueBlendRange = DEFAULT_BLEND; + theCyanSaturationOffset = 0.0; + theCyanIntensityOffset = 0.0; + + verifyEnabled(); +} + +void ossimHsiRemapper::resetBlue() +{ + theBlueHueOffset = 0.0; + theBlueHueLowRange = 210.0; + theBlueHueHighRange = 270.0; + theBlueHueBlendRange = DEFAULT_BLEND; + theBlueSaturationOffset = 0.0; + theBlueIntensityOffset = 0.0; + + verifyEnabled(); +} + +void ossimHsiRemapper::resetMagenta() +{ + theMagentaHueOffset = 0.0; + theMagentaHueLowRange = 270.0; + theMagentaHueHighRange = 330.0; + theMagentaHueBlendRange = DEFAULT_BLEND; + theMagentaSaturationOffset = 0.0; + theMagentaIntensityOffset = 0.0; + + verifyEnabled(); +} + +void ossimHsiRemapper::verifyEnabled() +{ + // Start off disabled... + disableSource(); + + if (!theInputConnection) + { + //*** + // Since this filter can be constructed with no input connection do not + // output and error, simply return. + //*** + return; + } + + if (theInputConnection->getNumberOfOutputBands() > 3) + { + // Only work on three band (rgb) images. + setErrorStatus(); + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::ossimHsiRemapper ERROR:" + << "\nRequires an RGB input source!" + << "\nInput source has " + << theInputConnection->getNumberOfOutputBands() + << " bands..." + << endl; + return; + } + + //*** + // Add all the offsets and the low clips. + // If greater than zero enable getTile method. + //*** + double d = theMasterHueOffset + + theMasterSaturationOffset + + theMasterIntensityOffset + + theMasterIntensityLowClip + + theRedHueOffset + + theRedSaturationOffset + + theRedIntensityOffset + + theYellowHueOffset + + theYellowSaturationOffset + + theYellowIntensityOffset + + theGreenHueOffset + + theGreenSaturationOffset + + theGreenIntensityOffset + + theCyanHueOffset + + theCyanSaturationOffset + + theCyanIntensityOffset + + theBlueHueOffset + + theBlueSaturationOffset + + theBlueIntensityOffset + + theMagentaHueOffset + + theMagentaSaturationOffset + + theMagentaIntensityOffset; + + if ( d != 0.0 || + theMasterIntensityHighClip != 1.0 || + theWhiteObjectClip != 1.0 ) + { + enableSource(); + } +} + +void ossimHsiRemapper::setMasterHueOffset(double offset) +{ + if (offset >= -180.0 && offset <= 180.0) + { + theMasterHueOffset = offset; + verifyEnabled(); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setMasterHueOffset range error:" + << "\nOffset of " << offset << " is out of range!" + << "\nMust be equal to or greater than -180.0 and less than" + << "\nor equal to 180.0" + << endl; + } +} + +void ossimHsiRemapper::setMasterSaturationOffset(double offset) +{ + if (offset >= -1.0 && offset <= 1.0) + { + theMasterSaturationOffset = offset; + verifyEnabled(); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setMasterSaturationOffset range error:" + << "\nOffset of " << offset << " is out of range!" + << "\nMust be equal to or greater than -1.0 and less than" + << "\nor equal to 1.0" + << endl; + } +} + +void ossimHsiRemapper::setMasterIntensityOffset(double offset) +{ + if (offset >= -1.0 && offset <= 1.0) + { + theMasterIntensityOffset = offset; + verifyEnabled(); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setMasterIntensityOffset range error:" + << "\nOffset of " << offset << " is out of range!" + << "\nMust be equal to or greater than -1.0 and less than" + << "\nor equal to 1.0" + << endl; + } +} + +void ossimHsiRemapper::setMasterIntensityLowClip(double clip) +{ + if (clip >= 0.0 && clip < theMasterIntensityHighClip) + { + theMasterIntensityLowClip = clip; + verifyEnabled(); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setMasterIntensityClip range error:" + << "\nLow clip of " << clip << " is out of range!" + << "\nMust be equal to or greater than 0.0 and less than" + << "\nthe high clip of " << theMasterIntensityHighClip + << endl; + } +} + +void ossimHsiRemapper::setMasterIntensityHighClip(double clip) +{ + if (clip <= 1.0 && clip > theMasterIntensityLowClip) + { + theMasterIntensityHighClip = clip; + verifyEnabled(); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setMasterIntensityHighClip range error:" + << "\nHigh clip of " << clip << " is out of range!" + << "\nMust be greater than low clip of " + << theMasterIntensityLowClip << " and less than 1.0" + << endl; + } +} + +void ossimHsiRemapper::setRedHueOffset(double offset) +{ + if (offset >= -180.0 && offset <= 180.0) + { + theRedHueOffset = offset; + verifyEnabled(); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setRedHueOffset range error:" + << "\nOffset of " << offset << " is out of range!" + << "\nMust be equal to or greater than -180.0 and less than" + << "\nor equal to 180.0" + << endl; + } +} + +void ossimHsiRemapper::setRedHueLowRange(double range) +{ + //*** + // Default red range: 330 - 30 + // Allow 315 to 15 as long as it's less than the high range. + // Note: Store the range as a negative if it's between 315 and 360. + //*** + double r = range; + double h = theRedHueHighRange; + + if (r >= 315.0 && r < 360.0) r = r - 360.0; + if (h >= 315.0 && h < 360.0) h = h - 360.0; + + if (r >= -45.0 && r <= 15.0 && r < h) + { + theRedHueLowRange = r; + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setRedHueLow range error:" + << "\nRange of " << range << " is out of range!" + << endl; + } +} + +void ossimHsiRemapper::setRedHueHighRange(double range) +{ + if (range == 360.0) range = 0.0; + + //*** + // Default red range: 330 - 30 + // Allow 345 to 45 as long as it's greater than the low range. + // Note: Store the range as a negative if it's between 345 and 360. + //*** + + double r = range; + double l = theRedHueLowRange; + + if (r >= 315.0 && r < 360.0) r = r - 360.0; + if (l >= 315.0 && l < 360.0) l = l - 360.0; + + if (r >= -15.0 && r <= 45 && l < r) + { + theRedHueHighRange = r; + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setRedHueHigh range error:" + << "\nRange of " << range << " is out of range!" + << endl; + } +} + +void ossimHsiRemapper::setRedHueBlendRange(double range) +{ + //*** + // Allowable range: 0.0 to 30.0 as long as it's not greater than the + // half range. If so snap it to half range. + //*** + if ( range >= 0.0 && + range <= MAX_BLEND ) + { + double half_range = (theRedHueHighRange - theRedHueLowRange) / 2.0; + + if (range <= half_range) + { + theRedHueBlendRange = range; + } + else + { + // Put it in the middle of the range. + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setRedHueBlendRange range error:" + << "\nRange of " << range << " is greater than the full range" + << "\ndivided by 2!" + << endl; + + theRedHueBlendRange = half_range; + } + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setRedHueBlendRange range error:" + << "\nRange of " << range << " is out of range!" + << endl; + } +} + +void ossimHsiRemapper::setRedSaturationOffset(double offset) +{ + if (offset >= -1.0 && offset <= 1.0) + { + theRedSaturationOffset = offset; + verifyEnabled(); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setRedSaturationOffset range error:" + << "\nOffset of " << offset << " is out of range!" + << "\nMust be equal to or greater than -1.0 and less than" + << "\nor equal to 1.0" + << endl; + } +} + +void ossimHsiRemapper::setRedIntensityOffset(double offset) +{ + if (offset >= -1.0 && offset <= 1.0) + { + theRedIntensityOffset = offset; + verifyEnabled(); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setRedIntensityOffset range error:" + << "\nOffset of " << offset << " is out of range!" + << "\nMust be equal to or greater than -1.0 and less than" + << "\nor equal to 1.0" + << endl; + } +} + +void ossimHsiRemapper::setYellowHueOffset(double offset) +{ + if (offset >= -180.0 && offset <= 180.0) + { + theYellowHueOffset = offset; + verifyEnabled(); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setYellowHueOffset range error:" + << "\nOffset of " << offset << " is out of range!" + << "\nMust be equal to or greater than -180.0 and less than" + << "\nor equal to 180.0" + << endl; + } +} + +void ossimHsiRemapper::setYellowHueLowRange(double range) +{ + //*** + // Default yellow range: 30 - 90 + // Allow 15 to 75 as long as it's less than the high range. + //*** + if ( range >= 15.0 && + range <= 75.0 && + range < theYellowHueHighRange ) + { + theYellowHueLowRange = range; + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setYellowHueLowRange range error:" + << "\nRange of " << range << " is out of range!" + << endl; + } +} + +void ossimHsiRemapper::setYellowHueHighRange(double range) +{ + //*** + // Default yellow range: 30 - 90 + // Allow 45 to 105 as long as it's greater than the low range. + //*** + if ( range >= 45.0 && + range <= 105.0 && + range > theYellowHueLowRange ) + { + theYellowHueHighRange = range; + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setYellowHueHighRange range error:" + << "\nRange of " << range << " is out of range!" + << endl; + } +} + +void ossimHsiRemapper::setYellowHueBlendRange(double range) +{ + //*** + // Allowable range: 0.0 to 30.0 as long as it's not greater than the + // half range. If so snap it to half range. + //*** + if ( range >= 0.0 && + range <= MAX_BLEND ) + { + double half_range = (theYellowHueHighRange - theYellowHueLowRange) / 2.0; + + if (range <= half_range) + { + theYellowHueBlendRange = range; + } + else + { + // Put it in the middle of the range. + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setYellowHueBlendRange range error:" + << "\nRange of " << range << " is greater than the full range" + << "\ndivided by 2!" + << endl; + + theYellowHueBlendRange = half_range; + } + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setYellowHueBlendRange range error:" + << "\nRange of " << range << " is out of range!" + << endl; + } +} + +void ossimHsiRemapper::setYellowSaturationOffset(double offset) +{ + if (offset >= -1.0 && offset <= 1.0) + { + theYellowSaturationOffset = offset; + verifyEnabled(); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setYellowSaturationOffset range error:" + << "\nOffset of " << offset << " is out of range!" + << "\nMust be equal to or greater than -1.0 and less than" + << "\nor equal to 1.0" + << endl; + } +} + +void ossimHsiRemapper::setYellowIntensityOffset(double offset) +{ + if (offset >= -1.0 && offset <= 1.0) + { + theYellowIntensityOffset = offset; + verifyEnabled(); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setYellowIntensityOffset range error:" + << "\nOffset of " << offset << " is out of range!" + << "\nMust be equal to or greater than -1.0 and less than" + << "\nor equal to 1.0" + << endl; + } +} + +void ossimHsiRemapper::setGreenHueOffset(double offset) +{ + if (offset >= -180.0 && offset <= 180.0) + { + theGreenHueOffset = offset; + verifyEnabled(); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setGreenHueOffset range error:" + << "\nOffset of " << offset << " is out of range!" + << "\nMust be equal to or greater than -180.0 and less than" + << "\nor equal to 180.0" + << endl; + } +} + +void ossimHsiRemapper::setGreenHueLowRange(double range) +{ + //*** + // Default green range: 90 - 150 + // Allow 75 to 135 as long as it's less than the high range. + //*** + + if ( range >= 75.0 && + range <= 135.0 && + range < theGreenHueHighRange ) + { + theGreenHueLowRange = range; + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setGreenHueLowRange range error:" + << "\nRange of " << range << " is out of range!" + << endl; + } +} + +void ossimHsiRemapper::setGreenHueHighRange(double range) +{ + //*** + // Default green range: 90 - 150 + // Allow 105 to 165 as long as it's greater than the low range. + //*** + + if ( range >= 105.0 && + range <= 165.0 && + range > theGreenHueLowRange ) + { + theGreenHueHighRange = range; + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setGreenHueHighRange range error:" + << "\nRange of " << range << " is out of range!" + << endl; + } +} + +void ossimHsiRemapper::setGreenHueBlendRange(double range) +{ + //*** + // Allowable range: 0.0 to 30.0 as long as it's not greater than the + // half range. If so snap it to half range. + //*** + if ( range >= 0.0 && + range <= MAX_BLEND ) + { + double half_range = (theGreenHueHighRange - theGreenHueLowRange) / 2.0; + + if (range <= half_range) + { + theGreenHueBlendRange = range; + } + else + { + // Put it in the middle of the range. + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setGreenHueBlendRange range error:" + << "\nRange of " << range << " is greater than the full range" + << "\ndivided by 2!" + << endl; + + theGreenHueBlendRange = half_range; + } + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setGreenHueBlendRange range error:" + << "\nRange of " << range << " is out of range!" + << endl; + } +} + +void ossimHsiRemapper::setGreenSaturationOffset(double offset) +{ + if (offset >= -1.0 && offset <= 1.0) + { + theGreenSaturationOffset = offset; + verifyEnabled(); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setGreenSaturationOffset range error:" + << "\nOffset of " << offset << " is out of range!" + << "\nMust be equal to or greater than -1.0 and less than" + << "\nor equal to 1.0" + << endl; + } +} + +void ossimHsiRemapper::setGreenIntensityOffset(double offset) +{ + if (offset >= -1.0 && offset <= 1.0) + { + theGreenIntensityOffset = offset; + verifyEnabled(); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setGreenIntensityOffset range error:" + << "\nOffset of " << offset << " is out of range!" + << "\nMust be equal to or greater than -1.0 and less than" + << "\nor equal to 1.0" + << endl; + } +} + +void ossimHsiRemapper::setCyanHueOffset(double offset) +{ + if (offset >= -180.0 && offset <= 180.0) + { + theCyanHueOffset = offset; + verifyEnabled(); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setCyanHueOffset range error:" + << "\nOffset of " << offset << " is out of range!" + << "\nMust be equal to or greater than -180.0 and less than" + << "\nor equal to 180.0" + << endl; + } +} + +void ossimHsiRemapper::setCyanHueLowRange(double range) +{ + //*** + // Default cyan range: 150 - 210 + // Allow 135 to 195 as long as it's less than the high range. + //*** + + if ( range >= 135.0 && + range <= 195.0 && + range < theCyanHueHighRange ) + { + theCyanHueLowRange = range; + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setCyanHueLowRange range error:" + << "\nRange of " << range << " is out of range!" + << endl; + } +} + +void ossimHsiRemapper::setCyanHueHighRange(double range) +{ + //*** + // Default cyan range: 150 - 210 + // Allow 165 to 225 as long as it's greater than the low range. + //*** + + if ( range >= 165.0 && + range <= 225.0 && + range > theCyanHueLowRange ) + { + theCyanHueHighRange = range; + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setCyanHueHighRange range error:" + << "\nRange of " << range << " is out of range!" + << endl; + } +} + +void ossimHsiRemapper::setCyanHueBlendRange(double range) +{ + //*** + // Allowable range: 0.0 to 30.0 as long as it's not greater than the + // half range. If so snap it to half range. + //*** + if ( range >= 0.0 && + range <= MAX_BLEND ) + { + double half_range = (theCyanHueHighRange - theCyanHueLowRange) / 2.0; + + if (range <= half_range) + { + theCyanHueBlendRange = range; + } + else + { + // Put it in the middle of the range. + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setCyanHueBlendRange range error:" + << "\nRange of " << range << " is greater than the full range" + << "\ndivided by 2!" + << endl; + + theCyanHueBlendRange = half_range; + } + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setCyanHueBlendRange range error:" + << "\nRange of " << range << " is out of range!" + << endl; + } +} + +void ossimHsiRemapper::setCyanSaturationOffset(double offset) +{ + if (offset >= -1.0 && offset <= 1.0) + { + theCyanSaturationOffset = offset; + verifyEnabled(); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setCyanSaturationOffset range error:" + << "\nOffset of " << offset << " is out of range!" + << "\nMust be equal to or greater than -1.0 and less than" + << "\nor equal to 1.0" + << endl; + } +} + +void ossimHsiRemapper::setCyanIntensityOffset(double offset) +{ + if (offset >= -1.0 && offset <= 1.0) + { + theCyanIntensityOffset = offset; + verifyEnabled(); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setCyanIntensityOffset range error:" + << "\nOffset of " << offset << " is out of range!" + << "\nMust be equal to or greater than -1.0 and less than" + << "\nor equal to 1.0" + << endl; + } +} + +void ossimHsiRemapper::setBlueHueOffset(double offset) +{ + if (offset >= -180.0 && offset <= 180.0) + { + theBlueHueOffset = offset; + verifyEnabled(); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setBlueHueOffset range error:" + << "\nOffset of " << offset << " is out of range!" + << "\nMust be equal to or greater than -180.0 and less than" + << "\nor equal to 180.0" + << endl; + } +} + +void ossimHsiRemapper::setBlueHueLowRange(double range) +{ + //*** + // Default blue range: 210 - 270 + // Allow 195 to 255 as long as it's less than the high range. + //*** + if ( range >= 195.0 && + range <= 255.0 && + range < theBlueHueHighRange ) + { + theBlueHueLowRange = range; + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setBlueHueLowRange range error:" + << "\nRange of " << range << " is out of range!" + << endl; + } +} + +void ossimHsiRemapper::setBlueHueHighRange(double range) +{ + //*** + // Default blue range: 210 - 270 + // Allow 225 to 285 as long as it's greater than the low range. + //*** + if ( range >= 225.0 && + range <= 285.0 && + range > theBlueHueLowRange ) + { + theBlueHueHighRange = range; + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setBlueHueHighRange range error:" + << "\nRange of " << range << " is out of range!" + << endl; + } +} + +void ossimHsiRemapper::setBlueHueBlendRange(double range) +{ + //*** + // Allowable range: 0.0 to 30.0 as long as it's not greater than the + // half range. If so snap it to half range. + //*** + if ( range >= 0.0 && + range <= MAX_BLEND ) + { + double half_range = (theBlueHueHighRange - theBlueHueLowRange) / 2.0; + + if (range <= half_range) + { + theBlueHueBlendRange = range; + } + else + { + // Put it in the middle of the range. + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setBlueHueBlendRange range error:" + << "\nRange of " << range << " is greater than the full range" + << "\ndivided by 2!" + << endl; + + theBlueHueBlendRange = half_range; + } + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setBlueHueBlendRange range error:" + << "\nRange of " << range << " is out of range!" + << endl; + } +} + +void ossimHsiRemapper::setBlueSaturationOffset(double offset) +{ + if (offset >= -1.0 && offset <= 1.0) + { + theBlueSaturationOffset = offset; + verifyEnabled(); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setBlueSaturationOffset range error:" + << "\nOffset of " << offset << " is out of range!" + << "\nMust be equal to or greater than -1.0 and less than" + << "\nor equal to 1.0" + << endl; + } +} + +void ossimHsiRemapper::setBlueIntensityOffset(double offset) +{ + if (offset >= -1.0 && offset <= 1.0) + { + theBlueIntensityOffset = offset; + verifyEnabled(); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setBlueIntensityOffset range error:" + << "\nOffset of " << offset << " is out of range!" + << "\nMust be equal to or greater than -1.0 and less than" + << "\nor equal to 1.0" + << endl; + } +} + +void ossimHsiRemapper::setMagentaHueOffset(double offset) +{ + if (offset >= -180.0 && offset <= 180.0) + { + theMagentaHueOffset = offset; + verifyEnabled(); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setMagentaHueOffset range error:" + << "\nOffset of " << offset << " is out of range!" + << "\nMust be equal to or greater than -180.0 and less than" + << "\nor equal to 180.0" + << endl; + } +} + +void ossimHsiRemapper::setMagentaHueLowRange(double range) +{ + //*** + // Default magenta range: 270 - 330 + // Allow 255 to 315 as long as it's less than the high range. + //*** + if ( range >= 255.0 && + range <= 315.0 && + range < theMagentaHueHighRange ) + { + theMagentaHueLowRange = range; + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setMagentaHueLowRange range error:" + << "\nRange of " << range << " is out of range!" + << endl; + } +} + +void ossimHsiRemapper::setMagentaHueHighRange(double range) +{ + //*** + // Default magenta range: 270 - 330 + // Allow 285 to 345 as long as it's greater than the low range. + //*** + if ( range >= 285.0 && + range <= 345.0 && + range > theMagentaHueLowRange ) + { + theMagentaHueHighRange = range; + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setMagentaHueHighRange range error:" + << "\nRange of " << range << " is out of range!" + << endl; + } +} + +void ossimHsiRemapper::setMagentaHueBlendRange(double range) +{ + //*** + // Allowable range: 0.0 to 30.0 as long as it's not greater than the + // half range. If so snap it to half range. + //*** + if ( range >= 0.0 && + range <= MAX_BLEND ) + { + double half_range = (theMagentaHueHighRange-theMagentaHueLowRange)/2.0; + + if (range <= half_range) + { + theMagentaHueBlendRange = range; + } + else + { + // Put it in the middle of the range. + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setMagentaHueBlendRange range error:" + << "\nRange of " << range << " is greater than the full range" + << "\ndivided by 2!" + << endl; + + theMagentaHueBlendRange = half_range; + } + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setMagentaHueBlendRange range error:" + << "\nRange of " << range << " is out of range!" + << endl; + } +} + +void ossimHsiRemapper::setMagentaSaturationOffset(double offset) +{ + if (offset >= -1.0 && offset <= 1.0) + { + theMagentaSaturationOffset = offset; + verifyEnabled(); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setMagentaSaturationOffset range error:" + << "\nOffset of " << offset << " is out of range!" + << "\nMust be equal to or greater than -1.0 and less than" + << "\nor equal to 1.0" + << endl; + } +} + +void ossimHsiRemapper::setMagentaIntensityOffset(double offset) +{ + if (offset >= -1.0 && offset <= 1.0) + { + theMagentaIntensityOffset = offset; + verifyEnabled(); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimHsiRemapper::setMagentaIntensityOffset range error:" + << "\nOffset of " << offset << " is out of range!" + << "\nMust be equal to or greater than -1.0 and less than" + << "\nor equal to 1.0" + << endl; + } +} + +double ossimHsiRemapper::calculateMinNormValue() +{ + static const char MODULE[] = "ossimHsiRemapper::calculateMinNormValue"; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " Entered..." << endl; + } + + if (!theTile) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " ERROR:" + << "\nClass not initialized!" + << endl; + return 0.0; + } + + double min_pix = theTile->getMinPix(0); + double max_pix = theTile->getMaxPix(0); + + for (ossim_uint32 band=1; band<theTile->getNumberOfBands(); ++band) + { + if (min_pix != theTile->getMinPix(band)) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE << " Warning:" + << "\nMixed minimum values for bands..." + << endl; + } + if (max_pix != theTile->getMaxPix(band)) + { + ossimNotify(ossimNotifyLevel_WARN) << " Warning:" + << "\nMixed maximum values for bands..." + << endl; + } + } + + if (min_pix < 0.0) + { + // + // Assigning some arbituary number for float data. + // This should really come from the normalizer (ossimImageData) of + // the data. + // + return OSSIM_DEFAULT_MIN_PIX_NORM_DOUBLE; + } + + return (min_pix / max_pix); +} + +ossim_uint32 ossimHsiRemapper::getNumberOfOutputBands() const +{ + if (theEnableFlag) // Always rgb tile out... + { + return 3; + } + + // Filter bypassed so getTile will return input tile. + return ossimImageSourceFilter::getNumberOfInputBands(); +} + + +double ossimHsiRemapper::getMasterHueOffset () const +{ + return theMasterHueOffset; +} + +double ossimHsiRemapper::getMasterSaturationOffset() const +{ + return theMasterSaturationOffset; +} + +double ossimHsiRemapper::getMasterIntensityOffset() const +{ + return theMasterIntensityOffset; +} + +double ossimHsiRemapper::getMasterIntensityLowClip() const +{ + return theMasterIntensityLowClip; +} + +double ossimHsiRemapper::getMasterIntensityHighClip() const +{ + return theMasterIntensityHighClip; +} + +double ossimHsiRemapper::getRedHueOffset() const +{ + return theRedHueOffset; +} + +double ossimHsiRemapper::getRedHueLowRange() const +{ + return theRedHueLowRange; +} + +double ossimHsiRemapper::getRedHueHighRange() const +{ + return theRedHueHighRange; +} + +double ossimHsiRemapper::getRedHueBlendRange() const +{ + return theRedHueBlendRange; +} + +double ossimHsiRemapper::getRedSaturationOffset() const +{ + return theRedSaturationOffset; +} + +double ossimHsiRemapper::getRedIntensityOffset() const +{ + return theRedIntensityOffset; +} + +double ossimHsiRemapper::getYellowHueOffset () const +{ + return theYellowHueOffset; +} + +double ossimHsiRemapper::getYellowHueLowRange() const +{ + return theYellowHueLowRange; +} + +double ossimHsiRemapper::getYellowHueHighRange() const +{ + return theYellowHueHighRange; +} + +double ossimHsiRemapper::getYellowHueBlendRange() const +{ + return theYellowHueBlendRange; +} + +double ossimHsiRemapper::getYellowSaturationOffset() const +{ + return theYellowSaturationOffset; +} + +double ossimHsiRemapper::getYellowIntensityOffset() const +{ + return theYellowIntensityOffset; +} + +double ossimHsiRemapper::getGreenHueOffset () const +{ + return theGreenHueOffset; +} + +double ossimHsiRemapper::getGreenHueLowRange() const +{ + return theGreenHueLowRange; +} + +double ossimHsiRemapper::getGreenHueHighRange() const +{ + return theGreenHueHighRange; +} + +double ossimHsiRemapper::getGreenHueBlendRange() const +{ + return theGreenHueBlendRange; +} + +double ossimHsiRemapper::getGreenSaturationOffset() const +{ + return theGreenSaturationOffset; +} + +double ossimHsiRemapper::getGreenIntensityOffset() const +{ + return theGreenIntensityOffset; +} + +double ossimHsiRemapper::getCyanHueOffset () const +{ + return theCyanHueOffset; +} + +double ossimHsiRemapper::getCyanHueLowRange() const +{ + return theCyanHueLowRange; +} + +double ossimHsiRemapper::getCyanHueHighRange() const +{ + return theCyanHueHighRange; +} + +double ossimHsiRemapper::getCyanHueBlendRange() const +{ + return theCyanHueBlendRange; +} + +double ossimHsiRemapper::getCyanSaturationOffset() const +{ + return theCyanSaturationOffset; +} + +double ossimHsiRemapper::getCyanIntensityOffset() const +{ + return theCyanIntensityOffset; +} + +double ossimHsiRemapper::getBlueHueOffset () const +{ + return theBlueHueOffset; +} + +double ossimHsiRemapper::getBlueHueLowRange() const +{ + return theBlueHueLowRange; +} + +double ossimHsiRemapper::getBlueHueHighRange() const +{ + return theBlueHueHighRange; +} + +double ossimHsiRemapper::getBlueHueBlendRange() const +{ + return theBlueHueBlendRange; +} + +double ossimHsiRemapper::getBlueSaturationOffset() const +{ + return theBlueSaturationOffset; +} + +double ossimHsiRemapper::getBlueIntensityOffset() const +{ + return theBlueIntensityOffset; +} + +double ossimHsiRemapper::getMagentaHueOffset () const +{ + return theMagentaHueOffset; +} + +double ossimHsiRemapper::getMagentaHueLowRange() const +{ + return theMagentaHueLowRange; +} + +double ossimHsiRemapper::getMagentaHueHighRange() const +{ + return theMagentaHueHighRange; +} + +double ossimHsiRemapper::getMagentaHueBlendRange() const +{ + return theMagentaHueBlendRange; +} + +double ossimHsiRemapper::getMagentaSaturationOffset() const +{ + return theMagentaSaturationOffset; +} + +double ossimHsiRemapper::getMagentaIntensityOffset() const +{ + return theMagentaIntensityOffset; +} + +void ossimHsiRemapper::setHueOffset(int color_group, double offset) +{ + switch (color_group) + { + case RED: + setRedHueOffset(offset); + break; + case YELLOW: + setYellowHueOffset(offset); + break; + case GREEN: + setGreenHueOffset(offset); + break; + case CYAN: + setCyanHueOffset(offset); + break; + case BLUE: + setBlueHueOffset(offset); + break; + case MAGENTA: + setMagentaHueOffset(offset); + break; + case ALL: + setMasterHueOffset(offset); + break; + default: + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimHsiRemapper::setHueOffset NOTICE: Range error!" << endl; + } +} + +void ossimHsiRemapper::setHueLowRange(int color_group, double range) +{ + switch (color_group) + { + case RED: + setRedHueLowRange(range); + break; + case YELLOW: + setYellowHueLowRange(range); + break; + case GREEN: + setGreenHueLowRange(range); + break; + case CYAN: + setCyanHueLowRange(range); + break; + case BLUE: + setBlueHueLowRange(range); + break; + case MAGENTA: + setMagentaHueLowRange(range); + break; + default: + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimHsiRemapper::setHueLowRange NOTICE: Range error!" + << endl; + } +} + +void ossimHsiRemapper::setHueHighRange(int color_group, double range) +{ + switch (color_group) + { + case RED: + setRedHueHighRange(range); + break; + case YELLOW: + setYellowHueHighRange(range); + break; + case GREEN: + setGreenHueHighRange(range); + break; + case CYAN: + setCyanHueHighRange(range); + break; + case BLUE: + setBlueHueHighRange(range); + break; + case MAGENTA: + setMagentaHueHighRange(range); + break; + default: + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimHsiRemapper::setHueHighRange NOTICE: Range error!" + << endl; + } +} + +void ossimHsiRemapper::setHueBlendRange(int color_group, double range) +{ + switch (color_group) + { + case RED: + setRedHueBlendRange(range); + break; + case YELLOW: + setYellowHueBlendRange(range); + break; + case GREEN: + setGreenHueBlendRange(range); + break; + case CYAN: + setCyanHueBlendRange(range); + break; + case BLUE: + setBlueHueBlendRange(range); + break; + case MAGENTA: + setMagentaHueBlendRange(range); + break; + default: + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimHsiRemapper::setHueBlendRange NOTICE: Range error!" + << endl; + } +} + +void ossimHsiRemapper::setSaturationOffset(int color_group, double offset) +{ + switch (color_group) + { + case RED: + setRedSaturationOffset(offset); + break; + case YELLOW: + setYellowSaturationOffset(offset); + break; + case GREEN: + setGreenSaturationOffset(offset); + break; + case CYAN: + setCyanSaturationOffset(offset); + break; + case BLUE: + setBlueSaturationOffset(offset); + break; + case MAGENTA: + setMagentaSaturationOffset(offset); + break; + case ALL: + setMasterSaturationOffset(offset); + break; + default: + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimHsiRemapper::setSaturationOffset NOTICE: Range error!" + << endl; + break; + } +} + +void ossimHsiRemapper::setIntensityOffset(int color_group, double offset) +{ + switch (color_group) + { + case RED: + setRedIntensityOffset(offset); + break; + case YELLOW: + setYellowIntensityOffset(offset); + break; + case GREEN: + setGreenIntensityOffset(offset); + break; + case CYAN: + setCyanIntensityOffset(offset); + break; + case BLUE: + setBlueIntensityOffset(offset); + break; + case MAGENTA: + setMagentaIntensityOffset(offset); + break; + case ALL: + setMasterIntensityOffset(offset); + break; + default: + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimHsiRemapper::setIntensityOffset NOTICE: Range error!" + << endl; + break; + } +} + +double ossimHsiRemapper::getHueOffset(int color_group) const +{ + switch (color_group) + { + case RED: + return getRedHueOffset(); + break; + case YELLOW: + return getYellowHueOffset(); + break; + case GREEN: + return getGreenHueOffset(); + break; + case CYAN: + return getCyanHueOffset(); + break; + case BLUE: + return getBlueHueOffset(); + break; + case MAGENTA: + return getMagentaHueOffset(); + break; + case ALL: + return getMasterHueOffset(); + break; + default: + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimHsiRemapper::getHueOffset NOTICE: Range error!" + << endl; + break; + } + return 0.0; +} + +double ossimHsiRemapper::getHueLowRange(int color_group) const +{ + switch (color_group) + { + case RED: + return getRedHueLowRange(); + break; + case YELLOW: + return getYellowHueLowRange(); + break; + case GREEN: + return getGreenHueLowRange(); + break; + case CYAN: + return getCyanHueLowRange(); + break; + case BLUE: + return getBlueHueLowRange(); + break; + case MAGENTA: + return getMagentaHueLowRange(); + break; + default: + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimHsiRemapper::getHueLowRange NOTICE: Range error!" + << endl; + break; + } + return 0.0; +} + +double ossimHsiRemapper::getHueHighRange(int color_group) const +{ + switch (color_group) + { + case RED: + return getRedHueHighRange(); + break; + case YELLOW: + return getYellowHueHighRange(); + break; + case GREEN: + return getGreenHueHighRange(); + break; + case CYAN: + return getCyanHueHighRange(); + break; + case BLUE: + return getBlueHueHighRange(); + break; + case MAGENTA: + return getMagentaHueHighRange(); + break; + default: + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimHsiRemapper::getHueHighRange NOTICE: Range error!" + << endl; + break; + } + return 0.0; +} + +double ossimHsiRemapper::getHueBlendRange(int color_group) const +{ + switch (color_group) + { + case RED: + return getRedHueBlendRange(); + break; + case YELLOW: + return getYellowHueBlendRange(); + break; + case GREEN: + return getGreenHueBlendRange(); + break; + case CYAN: + return getCyanHueBlendRange(); + break; + case BLUE: + return getBlueHueBlendRange(); + break; + case MAGENTA: + return getMagentaHueBlendRange(); + break; + default: + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimHsiRemapper::getHueBlendRange NOTICE: Range error!" + << endl; + break; + } + return 0.0; +} + +double ossimHsiRemapper::getSaturationOffset(int color_group) const +{ + switch (color_group) + { + case RED: + return getRedSaturationOffset(); + break; + case YELLOW: + return getYellowSaturationOffset(); + break; + case GREEN: + return getGreenSaturationOffset(); + break; + case CYAN: + return getCyanSaturationOffset(); + break; + case BLUE: + return getBlueSaturationOffset(); + break; + case MAGENTA: + return getMagentaSaturationOffset(); + break; + case ALL: + return getMasterSaturationOffset(); + break; + default: + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimHsiRemapper::getSaturationOffset NOTICE: Range error!" + << endl; + break; + } + return 0.0; +} + +double ossimHsiRemapper::getIntensityOffset(int color_group) const +{ + switch (color_group) + { + case RED: + return getRedIntensityOffset(); + break; + case YELLOW: + return getYellowIntensityOffset(); + break; + case GREEN: + return getGreenIntensityOffset(); + break; + case CYAN: + return getCyanIntensityOffset(); + break; + case BLUE: + return getBlueIntensityOffset(); + break; + case MAGENTA: + return getMagentaIntensityOffset(); + break; + case ALL: + return getMasterIntensityOffset(); + break; + default: + ossimNotify(ossimNotifyLevel_NOTICE) + << "ossimHsiRemapper::getIntensityOffset NOTICE: Range error!" + << endl; + break; + } + return 0.0; +} + +void ossimHsiRemapper::setWhiteObjectClip(double clip) +{ + if ( (clip >= .8) && (clip <= 1.0) ) + { + theWhiteObjectClip = clip; + verifyEnabled(); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "HsiRemapper::setWhiteObjectClip range error:" + << "\nClip of " << clip << " is out of range!" + << "\nMust be between .8 and 1.0" + << endl; + } +} + +double ossimHsiRemapper::getWhiteObjectClip() const +{ + return theWhiteObjectClip; +} + +void ossimHsiRemapper::resetWhiteObjectClip() +{ + theWhiteObjectClip = 1.0; + verifyEnabled(); +} + +ossimString ossimHsiRemapper::getLongName()const +{ + return ossimString("HSI Remapper, filter with controls for all HSI(Hue, Saturation, and Intensity) adjustments."); +} + +ossimString ossimHsiRemapper::getShortName()const +{ + return ossimString("HSI Remapper"); +} + +ostream& ossimHsiRemapper::print(ostream& os) const +{ + os << setiosflags(ios::fixed) << setprecision(2) + << "\nossimHsiRemapper:" + << "\ntheEnableFlag: " << theEnableFlag + + << "\ntheMasterHueOffset: " << theMasterHueOffset + << "\ntheMasterSaturationOffset: " << theMasterSaturationOffset + << "\ntheMasterIntensityOffset: " << theMasterIntensityOffset + << "\ntheMasterIntensityLowClip: " << theMasterIntensityLowClip + << "\ntheMasterIntensityHighClip: " << theMasterIntensityHighClip + + << "\ntheRedHueOffset: " << theRedHueOffset + << "\ntheRedHueLowRange: " << theRedHueLowRange + << "\ntheRedHueHighRange: " << theRedHueHighRange + << "\ntheRedSaturationOffset: " << theRedSaturationOffset + << "\ntheRedIntensityOffset: " << theRedIntensityOffset + + << "\ntheYellowHueOffset: " << theYellowHueOffset + << "\ntheYellowHueLowRange: " << theYellowHueLowRange + << "\ntheYellowHueHighRange: " << theYellowHueHighRange + << "\ntheYellowSaturationOffset: " << theYellowSaturationOffset + << "\ntheYellowIntensityOffset: " << theYellowIntensityOffset + + << "\ntheGreenHueOffset: " << theGreenHueOffset + << "\ntheGreenHueLowRange: " << theGreenHueLowRange + << "\ntheGreenHueHighRange: " << theGreenHueHighRange + << "\ntheGreenSaturationOffset: " << theGreenSaturationOffset + << "\ntheGreenIntensityOffset: " << theGreenIntensityOffset + + << "\ntheCyanHueOffset: " << theCyanHueOffset + << "\ntheCyanHueLowRange: " << theCyanHueLowRange + << "\ntheCyanHueHighRange: " << theCyanHueHighRange + << "\ntheCyanSaturationOffset: " << theCyanSaturationOffset + << "\ntheCyanIntensityOffset: " << theCyanIntensityOffset + + << "\ntheBlueHueOffset: " << theBlueHueOffset + << "\ntheBlueHueLowRange: " << theBlueHueLowRange + << "\ntheBlueHueHighRange: " << theBlueHueHighRange + << "\ntheBlueSaturationOffset: " << theBlueSaturationOffset + << "\ntheBlueIntensityOffset: " << theBlueIntensityOffset + + << "\ntheMagentaHueOffset: " << theMagentaHueOffset + << "\ntheMagentaHueLowRange: " << theMagentaHueLowRange + << "\ntheMagentaHueHighRange: " << theMagentaHueHighRange + << "\ntheMagentaSaturationOffset: " << theMagentaSaturationOffset + << "\ntheMagentaIntensityOffset: " << theMagentaIntensityOffset + + << "\ntheWhiteObjectClip: " << theWhiteObjectClip + << endl; + + return os; +} + +ostream& operator<<(ostream& os, const ossimHsiRemapper& hr) +{ + return hr.print(os); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHsiRemapper.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHsiRemapper.h new file mode 100644 index 0000000000..209f0c8f87 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHsiRemapper.h @@ -0,0 +1,251 @@ +//******************************************************************* +// Copyright (C) 2002 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Remapper to adjust hue, saturation and intensity. +// +//************************************************************************* +// $Id: ossimHsiRemapper.h,v 1.19 2005/11/14 21:48:37 dburken Exp $ + +#ifndef ossimHsiRemapper_HEADER +#define ossimHsiRemapper_HEADER + +#include "ossimImageSourceFilter.h" + +class OSSIMDLLEXPORT ossimHsiRemapper : public ossimImageSourceFilter +{ +public: + enum + { + RED = 0, + YELLOW = 1, + GREEN = 2, + CYAN = 3, + BLUE = 4, + MAGENTA = 5, + ALL = 6 + }; + + ossimHsiRemapper(); + + virtual ~ossimHsiRemapper(); + + virtual ossimString getLongName() const; + virtual ossimString getShortName() const; + + virtual void initialize(); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tile_rect, + ossim_uint32 resLevel=0); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + + ossim_uint32 getNumberOfOutputBands() const; + + virtual ostream& print(ostream& os) const; + + friend ostream& operator << (ostream& os, const ossimHsiRemapper& hr); + + void setHueOffset (int color_group, double offset); + void setHueLowRange (int color_group, double range); + void setHueHighRange (int color_group, double range); + void setHueBlendRange (int color_group, double range); + void setSaturationOffset (int color_group, double offset); + void setIntensityOffset (int color_group, double offset); + + void setMasterHueOffset (double offset); + void setMasterSaturationOffset (double offset); + void setMasterIntensityOffset (double offset); + void setMasterIntensityLowClip (double clip); + void setMasterIntensityHighClip (double clip); + + void setRedHueOffset (double offset); + void setRedHueLowRange (double range); + void setRedHueHighRange (double range); + void setRedHueBlendRange (double range); + void setRedSaturationOffset (double offset); + void setRedIntensityOffset (double offset); + + void setYellowHueOffset (double offset); + void setYellowHueLowRange (double range); + void setYellowHueHighRange (double range); + void setYellowHueBlendRange (double range); + void setYellowSaturationOffset (double offset); + void setYellowIntensityOffset (double offset); + + void setGreenHueOffset (double offset); + void setGreenHueLowRange (double range); + void setGreenHueHighRange (double range); + void setGreenHueBlendRange (double range); + void setGreenSaturationOffset (double offset); + void setGreenIntensityOffset (double offset); + + void setCyanHueOffset (double offset); + void setCyanHueLowRange (double range); + void setCyanHueHighRange (double range); + void setCyanHueBlendRange (double range); + void setCyanSaturationOffset (double offset); + void setCyanIntensityOffset (double offset); + + void setBlueHueOffset (double offset); + void setBlueHueLowRange (double range); + void setBlueHueHighRange (double range); + void setBlueHueBlendRange (double range); + void setBlueSaturationOffset (double offset); + void setBlueIntensityOffset (double offset); + + void setMagentaHueOffset (double offset); + void setMagentaHueLowRange (double range); + void setMagentaHueHighRange (double range); + void setMagentaHueBlendRange (double range); + void setMagentaSaturationOffset (double offset); + void setMagentaIntensityOffset (double offset); + + double getHueOffset (int color_group) const; + double getHueLowRange (int color_group) const; + double getHueHighRange (int color_group) const; + double getHueBlendRange (int color_group) const; + double getSaturationOffset (int color_group) const; + double getIntensityOffset (int color_group) const; + + double getMasterHueOffset () const; + double getMasterSaturationOffset () const; + double getMasterIntensityOffset () const; + double getMasterIntensityLowClip () const; + double getMasterIntensityHighClip () const; + + double getRedHueOffset () const; + double getRedHueLowRange () const; + double getRedHueHighRange () const; + double getRedHueBlendRange () const; + double getRedSaturationOffset () const; + double getRedIntensityOffset () const; + + double getYellowHueOffset () const; + double getYellowHueLowRange () const; + double getYellowHueHighRange () const; + double getYellowHueBlendRange () const; + double getYellowSaturationOffset () const; + double getYellowIntensityOffset () const; + + double getGreenHueOffset () const; + double getGreenHueLowRange () const; + double getGreenHueHighRange () const; + double getGreenHueBlendRange () const; + double getGreenSaturationOffset () const; + double getGreenIntensityOffset () const; + + double getCyanHueOffset () const; + double getCyanHueLowRange () const; + double getCyanHueHighRange () const; + double getCyanHueBlendRange () const; + double getCyanSaturationOffset () const; + double getCyanIntensityOffset () const; + + double getBlueHueOffset () const; + double getBlueHueLowRange () const; + double getBlueHueHighRange () const; + double getBlueHueBlendRange () const; + double getBlueSaturationOffset () const; + double getBlueIntensityOffset () const; + + double getMagentaHueOffset () const; + double getMagentaHueLowRange () const; + double getMagentaHueHighRange () const; + double getMagentaHueBlendRange () const; + double getMagentaSaturationOffset () const; + double getMagentaIntensityOffset () const; + + void setWhiteObjectClip (double clip); + double getWhiteObjectClip () const; + void resetWhiteObjectClip (); + + void resetGroup(int color_group); + void resetAll(); + void resetMaster(); + void resetRed(); + void resetYellow(); + void resetGreen(); + void resetCyan(); + void resetBlue(); + void resetMagenta(); + +protected: + void allocate(const ossimIrect& rect); + void verifyEnabled(); + double calculateMinNormValue(); + + ossimRefPtr<ossimImageData> theTile; + double* theBuffer; + double theNormalizedMinPix; + + double theMasterHueOffset; + double theMasterSaturationOffset; + double theMasterIntensityOffset; + double theMasterIntensityLowClip; + double theMasterIntensityHighClip; + + double theRedHueOffset; + double theRedHueLowRange; + double theRedHueHighRange; + double theRedHueBlendRange; + double theRedSaturationOffset; + double theRedIntensityOffset; + + double theYellowHueOffset; + double theYellowHueLowRange; + double theYellowHueHighRange; + double theYellowHueBlendRange; + double theYellowSaturationOffset; + double theYellowIntensityOffset; + + double theGreenHueOffset; + double theGreenHueLowRange; + double theGreenHueHighRange; + double theGreenHueBlendRange; + double theGreenSaturationOffset; + double theGreenIntensityOffset; + + double theCyanHueOffset; + double theCyanHueLowRange; + double theCyanHueHighRange; + double theCyanHueBlendRange; + double theCyanSaturationOffset; + double theCyanIntensityOffset; + + double theBlueHueOffset; + double theBlueHueLowRange; + double theBlueHueHighRange; + double theBlueHueBlendRange; + double theBlueSaturationOffset; + double theBlueIntensityOffset; + + double theMagentaHueOffset; + double theMagentaHueLowRange; + double theMagentaHueHighRange; + double theMagentaHueBlendRange; + double theMagentaSaturationOffset; + double theMagentaIntensityOffset; + + double theWhiteObjectClip; + + TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHsiToRgbSource.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHsiToRgbSource.cpp new file mode 100644 index 0000000000..96a5c8c347 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHsiToRgbSource.cpp @@ -0,0 +1,147 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimHsiToRgbSource.cpp,v 1.8 2005/02/11 15:07:33 dburken Exp $ +#include <imaging/tile_sources/ossimHsiToRgbSource.h> +#include <imaging/ossimImageData.h> +#include <base/common/ossimConstants.h> +#include <base/common/ossimCommon.h> +#include <base/data_types/color_space/ossimHsiVector.h> +#include <base/data_types/color_space/ossimRgbVector.h> +#include <imaging/factory/ossimImageDataFactory.h> + +RTTI_DEF1(ossimHsiToRgbSource, "ossimHsiToRgbSource", ossimImageSourceFilter) + +ossimHsiToRgbSource::ossimHsiToRgbSource() + :ossimImageSourceFilter(), + theBlankTile(NULL), + theTile(NULL) +{ +} + +ossimHsiToRgbSource::ossimHsiToRgbSource(ossimImageSource* inputSource) + : ossimImageSourceFilter(inputSource), + theBlankTile(NULL), + theTile(NULL) +{ +} + +ossimHsiToRgbSource::~ossimHsiToRgbSource() +{ +} + +ossimRefPtr<ossimImageData> ossimHsiToRgbSource::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if(!theInputConnection) + { + return NULL; // This filter requires an input. + } + + ossimRefPtr<ossimImageData> inputTile = + theInputConnection->getTile(tileRect, resLevel); + if(!isSourceEnabled()) + { + return inputTile; + } + + if(!theTile.valid()) + { + allocate(); // First time through... + } + + if( !inputTile.valid() || + inputTile->getDataObjectStatus() == OSSIM_NULL || + inputTile->getDataObjectStatus() == OSSIM_EMPTY ) + { + theBlankTile->setImageRectangle(tileRect); + return theBlankTile; + } + + if((inputTile->getNumberOfBands()==3)&& + (inputTile->getScalarType()==OSSIM_NORMALIZED_FLOAT)&& + (inputTile->getDataObjectStatus()!=OSSIM_NULL)) + { + // Set the origin, resize if needed of the output tile. + theTile->setImageRectangle(tileRect); + + ossim_uint8* outputBands[3]; + float* inputBands[3]; + outputBands[0] = static_cast<ossim_uint8*>(theTile->getBuf(0)); + outputBands[1] = static_cast<ossim_uint8*>(theTile->getBuf(1)); + outputBands[2] = static_cast<ossim_uint8*>(theTile->getBuf(2)); + inputBands[0] = static_cast<float*>(inputTile->getBuf(0)); + inputBands[1] = static_cast<float*>(inputTile->getBuf(1)); + inputBands[2] = static_cast<float*>(inputTile->getBuf(2)); + + long height = inputTile->getHeight(); + long width = inputTile->getWidth(); + long offset = 0; + for(long row = 0; row < height; ++row) + { + for(long col = 0; col < width; ++col) + { + ossimHsiVector hsi(inputBands[0][offset], + inputBands[1][offset], + inputBands[2][offset]); + + ossimRgbVector rgb(hsi); + + + outputBands[0][offset] = rgb.getR(); + outputBands[1][offset] = rgb.getG(); + outputBands[2][offset] = rgb.getB(); + + ++offset; + } + } + } + else + { + return inputTile; + } + + theTile->validate(); + + return theTile; +} + +void ossimHsiToRgbSource::initialize() +{ + ossimImageSourceFilter::initialize(); +} + +void ossimHsiToRgbSource::allocate() +{ + theBlankTile = ossimImageDataFactory::instance()->create(this, this); + theTile = (ossimImageData*)theBlankTile->dup(); + theTile->initialize(); +} + +ossimScalarType ossimHsiToRgbSource::getOutputScalarType() const +{ + return OSSIM_UCHAR; +} + +double ossimHsiToRgbSource::getNullPixelValue()const +{ + return 0.0; +} + +double ossimHsiToRgbSource::getMinPixelValue(ossim_uint32 band)const +{ + return OSSIM_DEFAULT_MIN_PIX_UCHAR; +} + +double ossimHsiToRgbSource::getMaxPixelValue(ossim_uint32 band)const +{ + return OSSIM_DEFAULT_MAX_PIX_UCHAR; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHsiToRgbSource.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHsiToRgbSource.h new file mode 100644 index 0000000000..f0cf88e6cd --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHsiToRgbSource.h @@ -0,0 +1,49 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimHsiToRgbSource.h,v 1.9 2005/02/11 15:07:33 dburken Exp $ +#ifndef ossimHsiToRgbSource_HEADER +#define ossimHsiToRgbSource_HEADER + +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +class ossimHsiToRgbSource : public ossimImageSourceFilter +{ +public: + ossimHsiToRgbSource(); + ossimHsiToRgbSource(ossimImageSource* inputSource); + virtual ~ossimHsiToRgbSource(); + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + + virtual ossimScalarType getOutputScalarType() const; + + virtual double getNullPixelValue()const; + virtual double getMinPixelValue(ossim_uint32 band=0)const; + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + + virtual void initialize(); +protected: + + /** + * Called on first getTile, will initialize all data needed. + */ + void allocate(); + + ossimRefPtr<ossimImageData> theBlankTile; + ossimRefPtr<ossimImageData> theTile; + + void initializeBuffers(ossimRefPtr<ossimImageData>& data); + +TYPE_DATA +}; + +#endif /* #ifndef ossimHsiToRgbSource_HEADER */ + diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHsvToRgbSource.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHsvToRgbSource.cpp new file mode 100644 index 0000000000..220d813c7d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHsvToRgbSource.cpp @@ -0,0 +1,159 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimHsvToRgbSource.cpp,v 1.8 2005/05/10 21:06:47 dburken Exp $ +#include <imaging/tile_sources/ossimHsvToRgbSource.h> +#include <imaging/ossimImageData.h> +#include <base/common/ossimConstants.h> +#include <base/common/ossimCommon.h> +#include <base/data_types/color_space/ossimHsvVector.h> +#include <base/data_types/color_space/ossimRgbVector.h> +#include <imaging/factory/ossimImageDataFactory.h> + +RTTI_DEF1(ossimHsvToRgbSource, "ossimHsvToRgbSource", ossimImageSourceFilter) + +ossimHsvToRgbSource::ossimHsvToRgbSource() + :ossimImageSourceFilter(), + theBlankTile(NULL), + theTile(NULL) +{ +} + +ossimHsvToRgbSource::ossimHsvToRgbSource(ossimImageSource* inputSource) + : ossimImageSourceFilter(inputSource), + theBlankTile(NULL), + theTile(NULL) +{ +} + +ossimHsvToRgbSource::~ossimHsvToRgbSource() +{ +} + +ossimRefPtr<ossimImageData> ossimHsvToRgbSource::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if(theInputConnection) + { + ossimRefPtr<ossimImageData> imageData = + theInputConnection->getTile(tileRect, resLevel); + + if(!imageData.valid()) return theBlankTile; + + if(!isSourceEnabled()) + { + return imageData; + } + + if(!theTile.valid()) allocate(); + if(!theTile.valid()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "Unable to initialize ossimHsvToRgbSource in getTile" + << std::endl; + return ossimRefPtr<ossimImageData>(); + } + + long w = tileRect.width(); + long h = tileRect.height(); + long tw = theTile->getWidth(); + long th = theTile->getHeight(); + + theBlankTile->setOrigin(tileRect.ul()); + theBlankTile->setWidthHeight(w, h); + theTile->setWidthHeight(w, h); + theTile->setOrigin(tileRect.ul()); + if( (tw*th) != (w*h)) + { + theTile->initialize(); + } + else + { + theTile->makeBlank(); + } + + if((imageData->getNumberOfBands()==3)&& + (imageData->getScalarType()==OSSIM_NORMALIZED_FLOAT)&& + (imageData->getDataObjectStatus()!=OSSIM_NULL)) + { + ossim_uint8* outputBands[3]; + float* inputBands[3]; + outputBands[0] = static_cast<ossim_uint8*>(theTile->getBuf(0)); + outputBands[1] = static_cast<ossim_uint8*>(theTile->getBuf(1)); + outputBands[2] = static_cast<ossim_uint8*>(theTile->getBuf(2)); + inputBands[0] = static_cast<float*>(imageData->getBuf(0)); + inputBands[1] = static_cast<float*>(imageData->getBuf(1)); + inputBands[2] = static_cast<float*>(imageData->getBuf(2)); + + long height = imageData->getHeight(); + long width = imageData->getWidth(); + long offset = 0; + for(long row = 0; row < height; ++row) + { + for(long col = 0; col < width; ++col) + { + ossimHsvVector hsv(inputBands[0][offset], + inputBands[1][offset], + inputBands[2][offset]); + + ossimRgbVector rgb(hsv); + + outputBands[0][offset] = rgb.getR(); + outputBands[1][offset] = rgb.getG(); + outputBands[2][offset] = rgb.getB(); + + ++offset; + } + } + } + else + { + return imageData; + } + theTile->validate(); + return theTile; + } + + return theBlankTile; +} + +void ossimHsvToRgbSource::initialize() +{ + theBlankTile = NULL; + theTile = NULL; +} + +void ossimHsvToRgbSource::allocate() +{ + theBlankTile = ossimImageDataFactory::instance()->create(this, this); + theTile = (ossimImageData*)theBlankTile->dup(); + theTile->initialize(); +} + +ossimScalarType ossimHsvToRgbSource::getOutputScalarType() const +{ + return OSSIM_UINT8; +} + +double ossimHsvToRgbSource::getNullPixelValue()const +{ + return 0; +} + +double ossimHsvToRgbSource::getMinPixelValue(ossim_uint32 band)const +{ + return OSSIM_DEFAULT_MIN_PIX_UCHAR; +} + +double ossimHsvToRgbSource::getMaxPixelValue(ossim_uint32 band)const +{ + return OSSIM_DEFAULT_MAX_PIX_UCHAR; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHsvToRgbSource.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHsvToRgbSource.h new file mode 100644 index 0000000000..94b7649ceb --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimHsvToRgbSource.h @@ -0,0 +1,42 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimHsvToRgbSource.h,v 1.6 2005/02/11 15:07:33 dburken Exp $ +#ifndef ossimHsvToRgbSource_HEADER +#define ossimJpegRgbToYCbCrSource_HEADER +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +class ossimHsvToRgbSource : public ossimImageSourceFilter +{ +public: + ossimHsvToRgbSource(); + ossimHsvToRgbSource(ossimImageSource* inputSource); + virtual ~ossimHsvToRgbSource(); + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + + virtual ossimScalarType getOutputScalarType() const; + virtual double getNullPixelValue()const; + virtual double getMinPixelValue(ossim_uint32 band=0)const; + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + + virtual void initialize(); + +protected: + + virtual void allocate(); + + ossimRefPtr<ossimImageData> theBlankTile; + ossimRefPtr<ossimImageData> theTile; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageCombiner.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageCombiner.cpp new file mode 100644 index 0000000000..1cf50affac --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageCombiner.cpp @@ -0,0 +1,689 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimImageCombiner.cpp,v 1.70 2005/10/13 20:17:49 gpotts Exp $ +#include <imaging/tile_sources/ossimImageCombiner.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimIrect.h> +#include <imaging/ossimImageData.h> +#include <base/common/ossimTrace.h> + +using namespace std; + +RTTI_DEF2(ossimImageCombiner, "ossimImageCombiner", ossimImageSource, ossimConnectableObjectListener) +static ossimTrace traceDebug ("ossimImageCombiner:debug"); + +ossimImageCombiner::ossimImageCombiner() + :ossimImageSource(NULL, + 0, + 0, + false, + false), + theLargestNumberOfInputBands(0), + theInputToPassThrough(0), + theHasDifferentInputs(false), + theNormTile(NULL), + + theCurrentIndex(0) +{ + theComputeFullResBoundsFlag = true; + // until something is set we will just set the blank tile + // to a 1 band unsigned char type + addListener((ossimConnectableObjectListener*)this); +} +ossimImageCombiner::ossimImageCombiner(ossimObject* owner, + int numberOfInputs, + int numberOfOutputs, + bool inputListIsFixedFlag, + bool outputListIsFixedFlag) + :ossimImageSource(owner, + numberOfInputs, + numberOfOutputs, + inputListIsFixedFlag, + outputListIsFixedFlag), + theLargestNumberOfInputBands(0), + theInputToPassThrough(0), + theHasDifferentInputs(false), + theNormTile(NULL), + theCurrentIndex(0) +{ + addListener((ossimConnectableObjectListener*)this); + theComputeFullResBoundsFlag = true; +} + +ossimImageCombiner::ossimImageCombiner(const std::vector<ossimImageSource*>& inputSources) + :ossimImageSource(NULL, + inputSources.size(), + 0, + false, + false), + theLargestNumberOfInputBands(0), + theInputToPassThrough(0), + theHasDifferentInputs(false), + theNormTile(NULL), + theCurrentIndex(0) +{ + theComputeFullResBoundsFlag = true; + for(ossim_uint32 index = 0; index < inputSources.size(); ++index) + { + connectMyInputTo(index, inputSources[index]); + } + addListener((ossimConnectableObjectListener*)this); + initialize(); +} + +ossimImageCombiner::~ossimImageCombiner() +{ + removeListener((ossimConnectableObjectListener*)this); +} + +void ossimImageCombiner::getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result) const +{ + if(getInput(0)) + { + ossimImageSourceInterface* temp = PTR_CAST(ossimImageSourceInterface, getInput(0)); + if(temp) + { + temp->getDecimationFactor(resLevel, result); + } + } + else + { + result.x = 1; + result.y = 1; + } +} + +void ossimImageCombiner::getDecimationFactors(vector<ossimDpt>& decimations) const +{ + if(getInput(0)) + { + ossimImageSourceInterface* temp = PTR_CAST(ossimImageSourceInterface, getInput(0)); + if(temp) + { + temp->getDecimationFactors(decimations); + } + } + else + { + decimations.push_back(ossimDpt(1,1)); + } +} + +ossim_uint32 ossimImageCombiner::getNumberOfDecimationLevels()const +{ + if(getInput(0)) + { + ossimImageSourceInterface* temp = PTR_CAST(ossimImageSourceInterface, getInput(0)); + if(temp) + { + return temp->getNumberOfDecimationLevels(); + } + } + + return 1; +} + +ossimIrect ossimImageCombiner::getBoundingRect(ossim_uint32 resLevel)const +{ + static const char* MODULE = "ossimImageCombiner::getBoundingRect"; + ossimIrect result; + if(theComputeFullResBoundsFlag) + { + precomputeBounds(); + } + + double scale = 1.0/std::pow(2.0, (double)resLevel); + ossimDpt scalar(scale, scale); + result.makeNan(); + + ossim_uint32 inputIndex = 0; + ossimImageSourceInterface* interface; + for(inputIndex = 0;inputIndex < getNumberOfInputs(); ++inputIndex) + { + interface = PTR_CAST(ossimImageSourceInterface, getInput(inputIndex)); + if(interface) + { + ossimIrect rect = theFullResBounds[inputIndex]; + if(result.hasNans()) + { + result = rect; + } + else if(!rect.hasNans()) + { + if(traceDebug()) + { + CLOG << "rect " << inputIndex << " = " << result << endl; + } + rect = rect*scale; + result = result.combine(rect); + } + } + } + if(traceDebug()) + { + CLOG << "resulting bounding rect = " << result << endl; + } + + return result; +} + +ossim_uint32 ossimImageCombiner::getNumberOfInputBands() const +{ + return theLargestNumberOfInputBands; +} + +ossimScalarType ossimImageCombiner::getOutputScalarType() const +{ + if(getInput(theInputToPassThrough)) + { + ossimImageSourceInterface* temp = PTR_CAST(ossimImageSourceInterface, getInput(theInputToPassThrough)); + if(temp) + { + return temp->getOutputScalarType(); + } + } + + return OSSIM_SCALAR_UNKNOWN; +} + +ossim_uint32 ossimImageCombiner::getTileWidth()const +{ + if(getInput(theInputToPassThrough)) + { + ossimImageSourceInterface* temp = PTR_CAST(ossimImageSourceInterface, getInput(theInputToPassThrough)); + if(temp) + { + return temp->getTileWidth(); + } + } + + return 1; +} + +ossim_uint32 ossimImageCombiner::getTileHeight()const +{ + if(getInput(theInputToPassThrough)) + { + ossimImageSourceInterface* temp = PTR_CAST(ossimImageSourceInterface, getInput(theInputToPassThrough)); + if(temp) + { + return temp->getTileHeight(); + } + } + + return 1; +} + +double ossimImageCombiner::getNullPixelValue(ossim_uint32 band)const +{ + if(getInput(theInputToPassThrough)) + { + ossimImageSourceInterface* temp = PTR_CAST(ossimImageSourceInterface, getInput(theInputToPassThrough)); + if(temp) + { + ossim_uint32 bands = temp->getNumberOfOutputBands(); + if(band < bands) + { + return temp->getNullPixelValue(band); + } + else + { + return temp->getNullPixelValue(bands-1); + } + } + } + + return 0.0; +} + +double ossimImageCombiner::getMinPixelValue(ossim_uint32 band)const +{ + const char* MODULE = "ossimImageCombiner::getMinPixelValue"; + + if(traceDebug()) + { + CLOG <<"entered..." << endl; + } + if(!getNumberOfInputs()) + { + return OSSIM_DBL_NAN; + } + double result = 1.0/DBL_EPSILON; + + for(ossim_uint32 index = 0; index < getNumberOfInputs();++index) + { + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, getInput(index)); + if(input) + { + ossim_uint32 bands = input->getNumberOfOutputBands(); + double temp = 0; + if(band < bands) + { + temp = input->getMinPixelValue(band); + } + else + { + temp = input->getMinPixelValue(bands-1); + } + + if(temp < result) + { + result = temp; + } + } + } + if(traceDebug()) + { + CLOG << "min pixel returned is = " << result; + } + if(traceDebug()) + { + CLOG <<"leaving..." << endl; + } + return result; +} + +double ossimImageCombiner::getMaxPixelValue(ossim_uint32 band)const +{ + const char* MODULE = "ossimImageCombiner::getMaxPixelValue"; + if(traceDebug()) + { + CLOG <<"entered..." << endl; + } + if(!getNumberOfInputs()) + { + return OSSIM_DBL_NAN; + } + double result = -1.0/DBL_EPSILON; + + for(ossim_uint32 idx = 0; idx < getNumberOfInputs();++idx) + { + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, getInput(idx)); + if(input) + { + ossim_uint32 bands = input->getNumberOfOutputBands(); + double temp = 0; + if(band < bands) + { + temp = input->getMaxPixelValue(band); + } + else + { + temp = input->getMaxPixelValue(bands-1); + } + if(temp > result) + { + result = temp; + } + } + } + + if(traceDebug()) + { + CLOG << "max pixel returned is = " << result; + } + if(traceDebug()) + { + CLOG <<"leaving..." << endl; + } + + return result; +} + +void ossimImageCombiner::initialize() +{ + + theLargestNumberOfInputBands = 0; + theComputeFullResBoundsFlag = true; + + // now find the largest number of bands + // + ossim_uint32 size = getNumberOfInputs(); + ossimScalarType scalarType = OSSIM_SCALAR_UNKNOWN; + ossim_uint32 scalarSizeInBytes = 0; + theInputToPassThrough = 0; + theHasDifferentInputs= false; + if(size > 0) + { + for(ossim_uint32 idx = 0; idx < size; ++idx) + { + ossimImageSourceInterface* temp = PTR_CAST(ossimImageSourceInterface, getInput(idx)); + if(temp) + { + ossim_uint32 numberOfBands = temp->getNumberOfOutputBands(); + if(numberOfBands > theLargestNumberOfInputBands) + { + theLargestNumberOfInputBands = numberOfBands; + } + ossimScalarType current = temp->getOutputScalarType(); + if(current != scalarType) + { + if(scalarType == OSSIM_SCALAR_UNKNOWN) + { + scalarType = current; + scalarSizeInBytes = ossimGetScalarSizeInBytes(scalarType); + theInputToPassThrough = idx; + } + else + { + theHasDifferentInputs = true; + if(scalarSizeInBytes < ossimGetScalarSizeInBytes(current)) + { + scalarType = current; + scalarSizeInBytes = ossimGetScalarSizeInBytes(current); + theInputToPassThrough = idx; + } + } + } + } + } + } +} + +bool ossimImageCombiner::loadState(const ossimKeywordlist& kwl, const char* prefix) +{ + bool result = ossimImageSource::loadState(kwl, prefix); + + return result; +} + +void ossimImageCombiner::updateRects() +{ + theComputeFullResBoundsFlag = true; +} + +ossimRefPtr<ossimImageData> ossimImageCombiner::getNextTile( + ossim_uint32 index, + const ossimIpt& origin, + ossim_uint32 resLevel) +{ + theCurrentIndex = (ossim_int32)index - 1; + return getNextTile(origin, resLevel); +} + +ossimRefPtr<ossimImageData> ossimImageCombiner::getNextTile( + ossim_uint32 index, + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + theCurrentIndex = (ossim_int32)index-1; + return getNextTile(tileRect, resLevel); +} + +ossimRefPtr<ossimImageData> ossimImageCombiner::getNextTile( + const ossimIpt& origin, + ossim_uint32 resLevel) +{ + ossim_int32 w = getTileWidth(); + ossim_int32 h = getTileHeight(); + + return getNextTile(ossimIrect(origin.x, + origin.y, + origin.x + w-1, + origin.y + h-1), + resLevel); +} + +ossimRefPtr<ossimImageData> ossimImageCombiner::getNextTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if(theComputeFullResBoundsFlag) + { + precomputeBounds(); + } + ossim_int32 size = getNumberOfInputs(); + + + if((theCurrentIndex+1) >= size) return NULL; + double scale = 1.0/std::pow(2.0, (double)resLevel); + ossimDpt scalar(scale, scale); + + ossimImageSourceInterface* temp = NULL; + ossimRefPtr<ossimImageData> result; + ossimDataObjectStatus status = OSSIM_NULL; + do + { + ++theCurrentIndex; + ossimIrect rect = theFullResBounds[theCurrentIndex]; + if(!rect.hasNans()) + { + rect = rect * scalar; + temp = PTR_CAST(ossimImageSourceInterface, + getInput(theCurrentIndex)); + if(rect.intersects(tileRect)&&temp) + { + + result = temp->getTile(tileRect, resLevel); + status = (result.valid() ? + result->getDataObjectStatus():OSSIM_NULL); + if((status == OSSIM_NULL)|| + (status == OSSIM_EMPTY)) + { + result = NULL; + } + } + else + { + status = OSSIM_NULL; + result = NULL; + } + } + else + { + status = OSSIM_NULL; + result = NULL; + } + + }while(!result&&(theCurrentIndex<size)); + + return result; +} + + +ossimRefPtr<ossimImageData> ossimImageCombiner::getNextNormTile( + ossim_uint32 index, + const ossimIpt& origin, + ossim_uint32 resLevel) +{ + theCurrentIndex = (ossim_int32)index - 1; + return getNextNormTile(origin, resLevel); +} + +ossimRefPtr<ossimImageData> ossimImageCombiner::getNextNormTile( + ossim_uint32 index, + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + theCurrentIndex = (ossim_int32)index-1; + return getNextNormTile(tileRect, resLevel); +} + +ossimRefPtr<ossimImageData> ossimImageCombiner::getNextNormTile( + const ossimIpt& origin, + ossim_uint32 resLevel) +{ + ossim_int32 w = getTileWidth(); + ossim_int32 h = getTileHeight(); + + return getNextNormTile(ossimIrect(origin.x, + origin.y, + origin.x + w-1, + origin.y + h-1), + resLevel); +} + +ossimRefPtr<ossimImageData> ossimImageCombiner::getNextNormTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + ossim_int32 size = getNumberOfInputs(); + + if(!theNormTile) + { + theNormTile = new ossimImageData(this, + OSSIM_NORMALIZED_FLOAT); + theNormTile->initialize(); + } + if((theCurrentIndex+1) >= size) return NULL; + + ossimRefPtr<ossimImageData> result = getNextTile(tileRect, resLevel); + + if(result.valid()) + { + theNormTile->setImageRectangleAndBands(result->getImageRectangle(), + result->getNumberOfBands()); + result->copyTileToNormalizedBuffer((float*)theNormTile->getBuf()); + + theNormTile->setDataObjectStatus(result->getDataObjectStatus()); + result = theNormTile; + } + + return result; +} + +ossim_uint32 ossimImageCombiner::getNumberOfOverlappingImages(const ossimIrect& rect, + ossim_uint32 resLevel)const +{ + if(theComputeFullResBoundsFlag) + { + precomputeBounds(); + } + double scale = 1.0/std::pow(2.0, (double)resLevel); + ossimDpt scalar(scale, scale); + ossim_uint32 result = 0; + ossim_uint32 maxIndex = getNumberOfInputs(); + for(ossim_uint32 inputIndex = 0; inputIndex < maxIndex; ++inputIndex) + { + if(!theFullResBounds[inputIndex].hasNans()) + { + ossimIrect boundingRect = theFullResBounds[inputIndex] * scalar; + if(rect.intersects(boundingRect)) + { + ++result; + } + } + } + + return result; +} + +void ossimImageCombiner::getOverlappingImages(std::vector<ossim_uint32>& result, + const ossimIrect& rect, + ossim_uint32 resLevel)const +{ + if(theComputeFullResBoundsFlag) + { + precomputeBounds(); + } + double scale = 1.0/std::pow(2.0, (double)resLevel); + ossimDpt scalar(scale, scale); + + ossim_uint32 inputIndex; + ossimIrect boundingRect; + for(inputIndex = 0; inputIndex < getNumberOfInputs(); ++inputIndex) + { + if(!theFullResBounds[inputIndex].hasNans()) + { + boundingRect = theFullResBounds[inputIndex]*scalar; + if(rect.intersects(boundingRect)) + { + result.push_back(inputIndex); + } + } + } +} + +void ossimImageCombiner::connectInputEvent(ossimConnectionEvent& event) +{ + initialize(); +} + +void ossimImageCombiner::disconnectInputEvent(ossimConnectionEvent& event) +{ + initialize(); +} + +void ossimImageCombiner::propertyEvent(ossimPropertyEvent& event) +{ + initialize(); +} + +void ossimImageCombiner::refreshEvent(ossimRefreshEvent& event) +{ + initialize(); +} + +bool ossimImageCombiner::hasDifferentInputs()const +{ + return theHasDifferentInputs; +} + +bool ossimImageCombiner::getImageGeometry(ossimKeywordlist& kwl, + const char* prefix) +{ + if(getInput(0)) + { + ossimImageSourceInterface* inter = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(inter) + { + return inter->getImageGeometry(kwl, prefix); + } + } + + return false; +} + +bool ossimImageCombiner::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + return ossimImageSource::saveState(kwl, prefix); +} + +bool ossimImageCombiner::canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const +{ + return (object&& PTR_CAST(ossimImageSourceInterface, object)); +} + +void ossimImageCombiner::precomputeBounds()const +{ + + ossim_uint32 inputSize = getNumberOfInputs(); + + if(inputSize) + { + ossimImageSourceInterface* tempInterface=0; + if(theFullResBounds.size() != inputSize) + { + theFullResBounds.resize(inputSize); + } + for(ossim_uint32 inputIndex = 0; inputIndex < inputSize; ++inputIndex) + { + tempInterface = PTR_CAST(ossimImageSourceInterface, getInput(inputIndex)); + if(tempInterface) + { + theFullResBounds[inputIndex] = tempInterface->getBoundingRect(); + } + else + { + theFullResBounds[inputIndex].makeNan(); + } + } + theComputeFullResBoundsFlag = false; + } + else + { + theFullResBounds.clear(); + } +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageCombiner.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageCombiner.h new file mode 100644 index 0000000000..6f1a9ed310 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageCombiner.h @@ -0,0 +1,132 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimImageCombiner.h,v 1.54 2005/10/17 19:18:05 gpotts Exp $ +#ifndef ossimImageCombiner_HEADER +#define ossimImageCombiner_HEADER +#include <vector> + +#include <imaging/ossimImageSource.h> +#include <base/common/events/ossimConnectableObjectListener.h> +#include <base/common/events/ossimPropertyEvent.h> + +/** + * This will be a base for all combiners. Combiners take N inputs and + * will produce a single output. + */ +class OSSIMDLLEXPORT ossimImageCombiner : public ossimImageSource, + public ossimConnectableObjectListener +{ +public: + ossimImageCombiner(); + ossimImageCombiner(ossimObject* owner, + int numberOfInputs, + int numberOfOutputs, + bool inputListIsFixedFlag, + bool outputListIsFixedFlag); + + ossimImageCombiner(const std::vector<ossimImageSource*>& inputSources); + virtual ~ossimImageCombiner(); + + virtual void getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result) const; + virtual void getDecimationFactors(vector<ossimDpt>& decimations) const; + virtual ossim_uint32 getNumberOfDecimationLevels() const; + + virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0) const; + + virtual bool getImageGeometry(ossimKeywordlist& kwl, + const char* prefix=NULL); + + virtual void initialize(); + virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix=NULL); + virtual bool saveState(ossimKeywordlist& kwl, const char* prefix=NULL)const; + + /** + * This will go through and precompute the + * bounding rects of each input image. + */ + virtual void updateRects(); + + /** + * Returns the number of bands available from the input. + */ + virtual ossim_uint32 getNumberOfInputBands()const; + virtual ossimScalarType getOutputScalarType() const; + virtual ossim_uint32 getTileWidth()const; + virtual ossim_uint32 getTileHeight()const; + + virtual double getNullPixelValue(ossim_uint32 band=0)const; + virtual double getMinPixelValue(ossim_uint32 band=0)const; + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + + /** + * Used to retrieve the number of overlapping images withint the given + * rect. + */ + virtual ossim_uint32 getNumberOfOverlappingImages(const ossimIrect& rect, + ossim_uint32 resLevel=0)const; + + /** + * Used to populate the result with the index of the overlapping images. + */ + virtual void getOverlappingImages(std::vector<ossim_uint32>& result, + const ossimIrect& rect, + ossim_uint32 resLevel=0)const; + + virtual ossimRefPtr<ossimImageData> getNextTile(ossim_uint32 index, + const ossimIpt& origin, + ossim_uint32 resLevel=0); + + virtual ossimRefPtr<ossimImageData> getNextTile(const ossimIpt& origin, + ossim_uint32 resLevel=0); + + virtual ossimRefPtr<ossimImageData> getNextTile(ossim_uint32 index, + const ossimIrect& origin, + ossim_uint32 resLevel=0); + + virtual ossimRefPtr<ossimImageData> getNextTile(const ossimIrect& origin, + ossim_uint32 resLevel=0); + + virtual ossimRefPtr<ossimImageData> getNextNormTile(ossim_uint32 index, + const ossimIpt& origin, + ossim_uint32 resLevel=0); + virtual ossimRefPtr<ossimImageData> getNextNormTile(const ossimIpt& origin, + ossim_uint32 resLevel=0); + + virtual ossimRefPtr<ossimImageData> getNextNormTile(ossim_uint32 index, + const ossimIrect& origin, + ossim_uint32 resLevel=0); + virtual ossimRefPtr<ossimImageData> getNextNormTile(const ossimIrect& origin, + ossim_uint32 resLevel=0); + + virtual bool canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const; + + virtual void connectInputEvent(ossimConnectionEvent& event); + virtual void disconnectInputEvent(ossimConnectionEvent& event); + virtual void propertyEvent(ossimPropertyEvent& event); + virtual void refreshEvent(ossimRefreshEvent& event); + virtual bool hasDifferentInputs()const; + +protected: + ossim_uint32 theLargestNumberOfInputBands; + ossim_uint32 theInputToPassThrough; + bool theHasDifferentInputs; + ossimRefPtr<ossimImageData> theNormTile; + ossim_int32 theCurrentIndex; + mutable std::vector<ossimIrect> theFullResBounds; + mutable bool theComputeFullResBoundsFlag; + void precomputeBounds()const; + +TYPE_DATA +}; + +#endif /* #ifndef ossimImageCombiner_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageGaussianFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageGaussianFilter.cpp new file mode 100644 index 0000000000..e1efef7305 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageGaussianFilter.cpp @@ -0,0 +1,198 @@ +//******************************************************************* +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// class ossimImageGaussianFilter : tile source +//******************************************************************* +// $Id: ossimImageGaussianFilter.cpp,v 1.2 2005/09/13 10:46:50 gpotts Exp $ +#include <cmath> +#include <imaging/tile_sources/ossimImageGaussianFilter.h> +#include <base/property/ossimNumericProperty.h> + +RTTI_DEF1(ossimImageGaussianFilter, "ossimImageGaussianFilter", ossimImageSourceFilter); + +//! property names +static const char* PROPERTYNAME_GAUSSSTD = "GaussStd"; + +ossimImageGaussianFilter::ossimImageGaussianFilter() + : ossimImageSourceFilter(), + theGaussStd(0.5) +{ + // ingredients: + // 2x ConvolutionFilter1D + theHF=new ossimConvolutionFilter1D(); + theVF=new ossimConvolutionFilter1D(); + + theHF->setIsHorizontal(true); + theVF->setIsHorizontal(false); + updateKernels(); + + //tie them up + theVF->connectMyInputTo(0,theHF); +} + +ossimImageGaussianFilter::~ossimImageGaussianFilter() +{ + delete theHF; + delete theVF; +} + +void ossimImageGaussianFilter::setProperty(ossimRefPtr<ossimProperty> property) +{ + if(!property) return; + + if (property->getName() == PROPERTYNAME_GAUSSSTD) { + ossimNumericProperty* sProperty = PTR_CAST(ossimNumericProperty, + property.get()); + if(sProperty) + { + setGaussStd(sProperty->asFloat64()); + } + } else { + ossimImageSourceFilter::setProperty(property); + } +} + +ossimRefPtr<ossimProperty> ossimImageGaussianFilter::getProperty(const ossimString& name)const +{ + if (name == PROPERTYNAME_GAUSSSTD) { + ossimNumericProperty* property = new ossimNumericProperty(name,ossimString::toString(getGaussStd()),1e-13,100.0); + property->setCacheRefreshBit(); + return property; + } + return ossimImageSourceFilter::getProperty(name); +} + +void ossimImageGaussianFilter::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + ossimImageSourceFilter::getPropertyNames(propertyNames); + propertyNames.push_back(PROPERTYNAME_GAUSSSTD); +} + +bool ossimImageGaussianFilter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + PROPERTYNAME_GAUSSSTD, + theGaussStd, + true); + + return ossimImageSourceFilter::saveState(kwl, prefix); +} + + +bool ossimImageGaussianFilter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* gs = kwl.find(prefix, PROPERTYNAME_GAUSSSTD); + if(gs) + { + setGaussStd(ossimString(gs).toUInt32()); + } else { + cerr<<"ossimImageGaussianFilter : warning no "<< PROPERTYNAME_GAUSSSTD<<" in loadState"<<endl; + } + + return ossimImageSourceFilter::loadState(kwl, prefix); +} + +void ossimImageGaussianFilter::setGaussStd(const ossim_float64& v) +{ + theGaussStd = v; + updateKernels(); +} + +void +ossimImageGaussianFilter::initialize() +{ + ossimImageSourceFilter::initialize(); + initializeProcesses(); +} + +ossimRefPtr<ossimImageData> +ossimImageGaussianFilter::getTile(const ossimIrect &tileRect,ossim_uint32 resLevel) +{ + if(isSourceEnabled()) + { + return theVF->getTile(tileRect, resLevel); + } + if(theInputConnection) + { + return theInputConnection->getTile(tileRect, resLevel); + } + + return 0; +} + +void +ossimImageGaussianFilter::initializeProcesses() +{ + theHF->initialize(); + theVF->initialize(); +} + +void +ossimImageGaussianFilter::connectInputEvent(ossimConnectionEvent &event) +{ + ossimImageSourceFilter::connectInputEvent(event); + if(getInput()) + { + theHF->connectMyInputTo(0, getInput()); + initializeProcesses(); + } + else + { + theHF->disconnectMyInput(0, false, false); + initializeProcesses(); + } +} + +void +ossimImageGaussianFilter::disconnectInputEvent(ossimConnectionEvent &event) +{ + ossimImageSourceFilter::disconnectInputEvent(event); + if(getInput()) + { + theHF->connectMyInputTo(0, getInput()); + initializeProcesses(); + } + else + { + theHF->disconnectMyInput(0, false, false); + initializeProcesses(); + } +} +void +ossimImageGaussianFilter::updateKernels() +{ + //update kernels based on GaussStd value :2.5 sigma on each side + // symetric kernel + static const ossim_float64 sigmaN = 2.5; + ossim_float64 sig22 = getGaussStd()*getGaussStd()*2.0; + + ossim_uint32 halfw = (ossim_uint32)(std::floor(getGaussStd() * sigmaN + 0.5)); + ossim_uint32 supsize = 2*halfw + 1; + + //fill with sym. gaussian (unnormalized) + vector<ossim_float64> newk(supsize); + ossim_float64 sum=1.0; + ossim_float64 v; + newk[halfw] = 1.0; + for(ossim_int32 i=(ossim_int32)halfw; i>0 ;--i) //reverse for summing + { + newk[halfw + i] = newk[halfw - i] = v = std::exp(-i*i/sig22); + sum += 2.0 * v; + } + + //normalize + ossim_float64 invsum=1.0/sum; + for(ossim_uint32 i=0; i<supsize ;++i) + { + newk[i] *= invsum; + } + + //send to 1d conv filters + theHF->setKernel(newk); + theVF->setKernel(newk); + theHF->setCenterOffset(halfw); + theVF->setCenterOffset(halfw); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageGaussianFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageGaussianFilter.h new file mode 100644 index 0000000000..138b22c81f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageGaussianFilter.h @@ -0,0 +1,54 @@ +//******************************************************************* +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// class ossimImageGaussianFilter : tile source +//******************************************************************* +// $Id: ossimImageGaussianFilter.h,v 1.2 2005/09/12 13:39:07 gpotts Exp $ +#ifndef ossimImageGaussianFilter_HEADER +#define ossimImageGaussianFilter_HEADER + +#include <imaging/tile_sources/ossimImageSourceFilter.h> +#include <imaging/tile_sources/ossimConvolutionFilter1D.h> + +class OSSIM_DLL ossimImageGaussianFilter : public ossimImageSourceFilter +{ +public: + //! own methods + ossimImageGaussianFilter(); + virtual ~ossimImageGaussianFilter(); + + inline ossim_float64 getGaussStd()const { return theGaussStd; } + void setGaussStd(const ossim_float64& v); + + //! inherited methods + virtual void initialize(); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect &tileRect,ossim_uint32 resLevel=0); + + virtual void connectInputEvent(ossimConnectionEvent &event); + virtual void disconnectInputEvent(ossimConnectionEvent &event); + + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + + virtual bool loadState(const ossimKeywordlist& kwl,const char* prefix = 0); + virtual bool saveState(ossimKeywordlist& kwl,const char* prefix = 0)const; + +protected: + //! protected methods + void initializeProcesses(); + void updateKernels(); + + //! parameters + ossim_float64 theGaussStd; + + //! subprocesses + ossimConvolutionFilter1D* theHF; //horizontal filter + ossimConvolutionFilter1D* theVF; //vertical filter + +TYPE_DATA +}; + +#endif /* #ifndef ossimImageGaussianFilter_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageMosaic.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageMosaic.cpp new file mode 100644 index 0000000000..1b51ac096a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageMosaic.cpp @@ -0,0 +1,532 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: implementation for image mosaic +// +//************************************************************************* +// $Id: ossimImageMosaic.cpp,v 1.65 2005/06/30 15:14:57 gpotts Exp $ + +#include <imaging/tile_sources/ossimImageMosaic.h> +#include <imaging/ossimImageData.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <base/common/ossimTrace.h> +static const ossimTrace traceDebug("ossimImageMosaic:debug"); + +using namespace std; + +RTTI_DEF1(ossimImageMosaic, "ossimImageMosaic", ossimImageCombiner) +ossimImageMosaic::ossimImageMosaic() + :ossimImageCombiner(), + theTile(NULL) +{ +} + +ossimImageMosaic::ossimImageMosaic(const vector<ossimImageSource*>& inputSources) + : ossimImageCombiner(inputSources), + theTile(NULL) +{ +} + + +ossimImageMosaic::~ossimImageMosaic() +{ +} + +ossimRefPtr<ossimImageData> ossimImageMosaic::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + long size = getNumberOfInputs(); + + // If there is only one in the mosaic then just return it. + if(size == 1) + { + return getNextTile(0, tileRect, resLevel); + } + + ossimIpt origin = tileRect.ul(); + ossim_uint32 w = tileRect.width(); + ossim_uint32 h = tileRect.height(); + + if(!theTile.valid()) + { + // try to initialize + allocate(); + + // if we still don't have a buffer + // then we will leave + if(!theTile.valid()) + { + return ossimRefPtr<ossimImageData>(); + } + } + + ossim_uint32 tileW = theTile->getWidth(); + ossim_uint32 tileH = theTile->getHeight(); + if((w != tileW)|| + (h != tileH)) + { + theTile->setWidth(w); + theTile->setHeight(h); + if((w*h)!=(tileW*tileH)) + { + theTile->initialize(); + } + } + theTile->setOrigin(origin); + + //--- + // General Note: + // + // Note: I will not check for disabled or enabled since we have + // no clear way to handle this within a mosaic. The default will be + // to do a simple a A over B type mosaic. Derived classes should + // check for the enabled and disabled and always + // use this default implementation if they are disabled. + //--- + + theTile->setOrigin(origin); + theTile->makeBlank(); + switch(theTile->getScalarType()) + { + case OSSIM_UCHAR: + { + if(!hasDifferentInputs()) + { + return combine(static_cast<ossim_uint8>(0), + tileRect, + resLevel); + } + else + { + return combineNorm(static_cast<ossim_uint8>(0), + tileRect, + resLevel); + } + } + case OSSIM_SINT8: + { + if(!hasDifferentInputs()) + { + return combine(static_cast<ossim_sint8>(0), + tileRect, + resLevel); + } + else + { + return combineNorm(static_cast<ossim_sint8>(0), + tileRect, + resLevel); + } + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + if(!hasDifferentInputs()) + { + return combine(static_cast<float>(0), + tileRect, + resLevel); + } + else + { + return combineNorm(static_cast<float>(0), + tileRect, + resLevel); + } + } + case OSSIM_USHORT16: + case OSSIM_USHORT11: + { + if(!hasDifferentInputs()) + { + return combine(static_cast<ossim_uint16>(0), + tileRect, + resLevel); + } + else + { + return combineNorm(static_cast<ossim_uint16>(0), + tileRect, + resLevel); + } + } + case OSSIM_SSHORT16: + { + if(!hasDifferentInputs()) + { + return combine(static_cast<ossim_sint16>(0), + tileRect, + resLevel); + } + else + { + return combineNorm(static_cast<ossim_sint16>(0), + tileRect, + resLevel); + } + } + case OSSIM_SINT32: + { + if(!hasDifferentInputs()) + { + return combine(static_cast<ossim_sint32>(0), + tileRect, + resLevel); + } + else + { + return combineNorm(static_cast<ossim_sint32>(0), + tileRect, + resLevel); + } + } + case OSSIM_UINT32: + { + if(!hasDifferentInputs()) + { + return combine(static_cast<ossim_uint32>(0), + tileRect, + resLevel); + } + else + { + return combineNorm(static_cast<ossim_uint32>(0), + tileRect, + resLevel); + } + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + if(!hasDifferentInputs()) + { + return combine(static_cast<double>(0), + tileRect, + resLevel); + } + else + { + return combineNorm(static_cast<double>(0), + tileRect, + resLevel); + } + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "Scalar type = " << theTile->getScalarType() + << " Not supported by ossimImageMosaic" << endl; + } + } + + return ossimRefPtr<ossimImageData>(); +} + +void ossimImageMosaic::initialize() +{ + ossimImageCombiner::initialize(); + theTile = NULL; +} + +void ossimImageMosaic::allocate() +{ + theTile = NULL; + + if( (getNumberOfInputs() > 0) && getInput(0) ) + { + theTile = ossimImageDataFactory::instance()->create(this, this); + theTile->initialize(); + } +} + +bool ossimImageMosaic::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + return ossimImageCombiner::saveState(kwl, prefix); +} + +bool ossimImageMosaic::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + return ossimImageCombiner::loadState(kwl, prefix); +} + +template <class T> ossimRefPtr<ossimImageData> ossimImageMosaic::combineNorm( + T,// dummy template variable + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + ossimRefPtr<ossimImageData> destination = theTile; + + ossimRefPtr<ossimImageData> currentImageData = + getNextNormTile(0, tileRect, resLevel); + + if(!currentImageData) + { + return currentImageData; + } + + float** srcBands = new float*[theLargestNumberOfInputBands]; + float* srcBandsNullPix = new float[theLargestNumberOfInputBands]; + T** destBands = new T*[theLargestNumberOfInputBands]; + T* destBandsNullPix = new T[theLargestNumberOfInputBands]; + T* destBandsMinPix = new T[theLargestNumberOfInputBands]; + T* destBandsMaxPix = new T[theLargestNumberOfInputBands]; + + ossim_uint32 band; + ossim_uint32 upperBound = destination->getWidth()*destination->getHeight(); + ossim_uint32 minNumberOfBands = currentImageData->getNumberOfBands(); + for(band = 0; band < minNumberOfBands; ++band) + { + srcBands[band] = static_cast<float*>(currentImageData->getBuf(band)); + srcBandsNullPix[band] = static_cast<float>(currentImageData->getNullPix(band)); + + destBands[band] = static_cast<T*>(theTile->getBuf(band)); + destBandsNullPix[band] = static_cast<T>(theTile->getNullPix(band)); + destBandsMinPix[band] = static_cast<T>(theTile->getMinPix(band)); + destBandsMaxPix[band] = static_cast<T>(theTile->getMaxPix(band)); + } + // if the src is smaller than the destination in number + // of bands we will just duplicate the last band. + for(;band < theLargestNumberOfInputBands; ++band) + { + srcBands[band] = static_cast<float*>(srcBands[minNumberOfBands - 1]); + srcBandsNullPix[band] = static_cast<float>(currentImageData->getNullPix(minNumberOfBands - 1)); + + destBands[band] = static_cast<T*>(theTile->getBuf(band)); + destBandsNullPix[band] = static_cast<T>(theTile->getNullPix(band)); + destBandsMinPix[band] = static_cast<T>(theTile->getMinPix(band)); + destBandsMaxPix[band] = static_cast<T>(theTile->getMaxPix(band)); + } + // most of the time we will not overlap so let's + // copy the first tile into destination and check later. + // + ossim_uint32 tempBandIdx = 0; + for(band = 0; band < theTile->getNumberOfBands();++band) + { + if(band < currentImageData->getNumberOfBands()) + { + theTile->copyNormalizedBufferToTile(band, + (float*)currentImageData->getBuf(band)); + ++tempBandIdx; + } + else + { + if(tempBandIdx) + { + theTile->copyNormalizedBufferToTile(band, + (float*)currentImageData->getBuf(tempBandIdx-1)); + } + } + } + destination->validate(); + + currentImageData = getNextNormTile(tileRect, resLevel); + + while(currentImageData.valid()) + { + ossim_uint32 minNumberOfBands = currentImageData->getNumberOfBands(); + ossimDataObjectStatus currentStatus = currentImageData->getDataObjectStatus(); + ossimDataObjectStatus destinationStatus = destination->getDataObjectStatus(); + + if(destinationStatus == OSSIM_FULL) + { + return destination; + } + for(band = 0; band < minNumberOfBands; ++band) + { + srcBands[band] = static_cast<float*>(currentImageData->getBuf(band)); + srcBandsNullPix[band] = static_cast<float>(currentImageData->getNullPix(band)); + } + // if the src is smaller than the destination in number + // of bands we will just duplicate the last band. + for(;band < theLargestNumberOfInputBands; ++band) + { + srcBands[band] = srcBands[minNumberOfBands - 1]; + srcBandsNullPix[band] = static_cast<T>(currentImageData->getNullPix(minNumberOfBands - 1)); + } + + if((destinationStatus == OSSIM_EMPTY)&& + (currentStatus != OSSIM_EMPTY)&& + (currentStatus != OSSIM_NULL)) + { + ossim_uint32 upperBound = destination->getWidth()*destination->getHeight(); + for(band=0; band < theLargestNumberOfInputBands; ++band) + { + float delta = destBandsMaxPix[band] - destBandsMinPix[band]; + float minP = destBandsMinPix[band]; + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + destBands[band][offset] = (T)( minP + delta*srcBands[band][offset]); + } + } + } + else if((destinationStatus == OSSIM_PARTIAL)&& + (currentStatus != OSSIM_EMPTY)&& + (currentStatus != OSSIM_NULL)) + { + for(band = 0; band < theLargestNumberOfInputBands; ++band) + { + + float delta = destBandsMaxPix[band] - destBandsMinPix[band]; + float minP = destBandsMinPix[band]; + for(ossim_uint32 offset = 0; + offset < upperBound; + ++offset) + { + + if(destBands[band][offset] == destBandsNullPix[band]) + { + destBands[band][offset] = (T)(minP + delta*srcBands[band][offset]); + } + } + } + } + destination->validate(); + + currentImageData = getNextNormTile(tileRect, resLevel); + } + // Cleanup... + delete [] srcBands; + delete [] destBands; + delete [] srcBandsNullPix; + delete [] destBandsNullPix; + delete [] destBandsMinPix; + delete [] destBandsMaxPix; + return destination; +} + +template <class T> ossimRefPtr<ossimImageData> ossimImageMosaic::combine( + T,// dummy template variable + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + ossimRefPtr<ossimImageData> destination = theTile; + + ossimRefPtr<ossimImageData> currentImageData = + getNextTile(0, tileRect, resLevel); + + T** srcBands = new T*[theLargestNumberOfInputBands]; + T* srcBandsNullPix = new T[theLargestNumberOfInputBands]; + T** destBands = new T*[theLargestNumberOfInputBands]; + T* destBandsNullPix = new T[theLargestNumberOfInputBands]; + + ossim_uint32 band; + ossim_uint32 upperBound = destination->getWidth()*destination->getHeight(); + ossim_uint32 bandIndex = 0; + if(!currentImageData) + { + return currentImageData; + } + ossim_uint32 offset=0; + ossim_uint32 minNumberOfBands = currentImageData->getNumberOfBands(); + for(band = 0; band < minNumberOfBands; ++band) + { + srcBands[band] = static_cast<T*>(currentImageData->getBuf(band)); + destBands[band] = static_cast<T*>(theTile->getBuf(band)); + srcBandsNullPix[band] = static_cast<T>(currentImageData->getNullPix(band)); + destBandsNullPix[band] = static_cast<T>(theTile->getNullPix(band)); + } + // if the src is smaller than the destination in number + // of bands we will just duplicate the last band. + for(;band < theLargestNumberOfInputBands; ++band) + { + srcBands[band] = static_cast<T*>(srcBands[minNumberOfBands - 1]); + destBands[band] = static_cast<T*>(theTile->getBuf(band)); + srcBandsNullPix[band] = static_cast<T>(currentImageData->getNullPix(minNumberOfBands - 1)); + destBandsNullPix[band] = static_cast<T>(theTile->getNullPix(band)); + } + // most of the time we will not overlap so let's + // copy the first tile into destination and check later. + // + for(band = 0; band < theTile->getNumberOfBands();++band) + { + T* destBand = destBands[band]; + T* srcBand = srcBands[band]; + if(destBand&&srcBand) + { + for(offset = 0; offset < upperBound;++offset) + { + *destBand = *srcBand; + ++srcBand; ++destBand; + } + } + } + destination->setDataObjectStatus(currentImageData->getDataObjectStatus()); + + currentImageData = getNextTile(tileRect, + resLevel); + + while(currentImageData.valid()) + { + ossim_uint32 minNumberOfBands = currentImageData->getNumberOfBands(); + ossimDataObjectStatus currentStatus = currentImageData->getDataObjectStatus(); + ossimDataObjectStatus destinationStatus = destination->getDataObjectStatus(); + + if(destinationStatus == OSSIM_FULL) + { + return destination; + } + for(band = 0; band < minNumberOfBands; ++band) + { + srcBands[band] = static_cast<T*>(currentImageData->getBuf(band)); + srcBandsNullPix[band] = static_cast<T>(currentImageData->getNullPix(band)); + } + // if the src is smaller than the destination in number + // of bands we will just duplicate the last band. + for(;band < theLargestNumberOfInputBands; ++band) + { + srcBands[band] = srcBands[minNumberOfBands - 1]; + srcBandsNullPix[band] = static_cast<T>(currentImageData->getNullPix(minNumberOfBands - 1)); + } + + if((destinationStatus == OSSIM_EMPTY)&& + (currentStatus != OSSIM_EMPTY)&& + (currentStatus != OSSIM_NULL)) + { + ossim_uint32 upperBound = destination->getWidth()*destination->getHeight(); + for(ossim_uint32 band=0; band < theLargestNumberOfInputBands; ++band) + { + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + destBands[band][offset] = srcBands[band][offset]; + } + } + } + else if((destinationStatus == OSSIM_PARTIAL)&& + (currentStatus != OSSIM_EMPTY)&& + (currentStatus != OSSIM_NULL)) + { + for(bandIndex = 0; bandIndex < theLargestNumberOfInputBands; ++bandIndex) + { + + for(ossim_uint32 offset = 0; + offset < upperBound; + ++offset) + { + if(destBands[bandIndex][offset] == destBandsNullPix[bandIndex]) + { + destBands[bandIndex][offset] = srcBands[bandIndex][offset]; + } + } + } + } + destination->validate(); + + currentImageData = getNextTile(tileRect, resLevel); + } + // Cleanup... + delete [] srcBands; + delete [] destBands; + delete [] srcBandsNullPix; + delete [] destBandsNullPix; + return destination; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageMosaic.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageMosaic.h new file mode 100644 index 0000000000..c11dab6103 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageMosaic.h @@ -0,0 +1,73 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimImageMosaic.h,v 1.28 2005/02/11 15:07:33 dburken Exp $ +#ifndef ossimImageMosaic_HEADER +#define ossimImageMosaic_HEADER +#include <vector> +using namespace std; + +#include <imaging/tile_sources/ossimImageCombiner.h> + + +/** + * An image mosaic is a simple combiner that will + * just do a simple mosaic. It just checks NULL pix values until it finds a + * pixel that is not empty and copies it out to the output. The list will + * have same size tiles and have the same number of bands. + */ +class OSSIMDLLEXPORT ossimImageMosaic : public ossimImageCombiner +{ +public: + ossimImageMosaic(); + ossimImageMosaic(const std::vector<ossimImageSource*>& inputSources); + virtual ~ossimImageMosaic(); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& origin, + ossim_uint32 resLevel=0); + + virtual void initialize(); + + /** + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +protected: + + /** + * Called on first getTile, will initialize all data needed. + */ + void allocate(); + + ossimRefPtr<ossimImageData> theTile; + + template <class T> ossimRefPtr<ossimImageData> combine( + T, // dummy template variable not used + const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + template <class T> ossimRefPtr<ossimImageData> combineNorm( + T, // dummy template variable not used + const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + +TYPE_DATA +}; + +#endif /* #ifndef ossimImageMosaic_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageRenderer.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageRenderer.cpp new file mode 100644 index 0000000000..7cdfe53c26 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageRenderer.cpp @@ -0,0 +1,1866 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimImageRenderer.cpp,v 1.259 2006/01/11 13:37:49 gpotts Exp $ + +#include <iostream> +using namespace std; + +#include <imaging/tile_sources/ossimImageRenderer.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimDpt3d.h> +#include <base/common/ossimCommon.h> +#include <base/common/ossimTrace.h> +#include <base/common/events/ossimProcessProgressEvent.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/common/ossimKeywordNames.h> +#include <base/common/ossimConnectableContainerInterface.h> +#include <base/common/ossimViewController.h> +#include <base/property/ossimStringProperty.h> +#include <base/property/ossimNumericProperty.h> +#include <imaging/ossimImageData.h> +#include <imaging/formats/ossimImageHandler.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <imaging/formats/ossimImageHandler.h> +#include <imaging/filters/ossimDiscrete3x3HatFilter.h> +#include <imaging/filters/ossimDiscreteNearestNeighbor.h> +#include <imaging/resample/ossimFilterResampler.h> +#include <imaging/resample/ossimResampler.h> +#include <projections/ossimImageViewTransform.h> +#include <projections/ossimImageViewProjectionTransform.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <projections/factory/ossimImageViewTransformFactory.h> +#include <projections/map_projections/ossimMapProjection.h> +#include <projections/map_projections/ossimEquDistCylProjection.h> + +#ifdef OSSIM_ID_ENABLED +static const char OSSIM_ID[] = "$Id: ossimImageRenderer.cpp,v 1.259 2006/01/11 13:37:49 gpotts Exp $"; +#endif + +static ossimTrace traceDebug("ossimImageRenderer:debug"); + +RTTI_DEF2(ossimImageRenderer, "ossimImageRenderer", ossimImageSourceFilter, ossimViewInterface); + + +void ossimImageRenderer::ossimRendererSubRectInfo::splitView(ossimImageViewTransform* transform, + ossimRendererSubRectInfo& ulRect, + ossimRendererSubRectInfo& urRect, + ossimRendererSubRectInfo& lrRect, + ossimRendererSubRectInfo& llRect)const +{ +#if 0 + ossimNotify(ossimNotifyLevel_DEBUG) + << "ulRect = " << ulRect + << "\nurRect = " << urRect + << "\nlrRect = " << lrRect + << "\nllRect = " << llRect << endl; +#endif + + ossimIrect vrect(theVul, + theVur, + theVlr, + theVll); + + ossimIrect tempUlRect; + ossimIrect tempUrRect; + ossimIrect tempLrRect; + ossimIrect tempLlRect; + + if((vrect.width() == 1)&& + (vrect.height() == 1)) + { + tempUlRect = vrect; + tempUrRect = vrect; + tempLrRect = vrect; + tempLlRect = vrect; + } + else + { + ossim_int32 w = vrect.width(); + ossim_int32 h = vrect.height(); + ossim_int32 w2 = w>>1; + ossim_int32 h2 = h>>1; + + if((w%2) == 0) // if even + { + if((h%2) == 0) // if even + { + tempUlRect = ossimIrect(theVul.x, + theVul.y, + theVul.x + (w2 - 1), + theVul.y + (h2 - 1)); + + tempUrRect = ossimIrect(theVul.x + w2, + theVul.y, + theVul.x + w2 + (w2 - 1), + theVul.y + (h2 - 1)); + + tempLrRect = ossimIrect(theVul.x + w2, + theVul.y + h2, + theVul.x + w2 + (w2 - 1), + theVul.y + h2 + (h2 - 1)); + + tempLlRect = ossimIrect(theVul.x, + theVul.y + h2, + theVul.x + (w2 - 1), + theVul.y + h2 + (h2 - 1)); + } + else // odd + { + tempUlRect = ossimIrect(theVul.x, + theVul.y, + theVul.x + (w2 - 1), + theVul.y + (h2)); + + tempUrRect = ossimIrect(theVul.x + w2, + theVul.y, + theVul.x + w2 + (w2 - 1), + theVul.y + (h2)); + + tempLrRect = ossimIrect(theVul.x + w2, + theVul.y + h2 + 1, + theVul.x + w2 + (w2 - 1), + theVul.y + h2 + (h2)); + + tempLlRect = ossimIrect(theVul.x, + theVul.y + h2 + 1, + theVul.x + (w2 - 1), + theVul.y + h2 + (h2)); + } + } + else // odd + { + if((h%2) == 0) // if even + { + tempUlRect = ossimIrect(theVul.x, + theVul.y, + theVul.x + (w2), + theVul.y + (h2 - 1)); + + tempUrRect = ossimIrect(theVul.x + w2 + 1, + theVul.y, + theVul.x + w2 + (w2), + theVul.y + (h2 - 1)); + + tempLrRect = ossimIrect(theVul.x + w2+1, + theVul.y + h2, + theVul.x + w2 + (w2), + theVul.y + h2 + (h2 - 1)); + + tempLlRect = ossimIrect(theVul.x, + theVul.y + h2, + theVul.x + (w2), + theVul.y + h2 + (h2 - 1)); + + } + else // odd + { + tempUlRect = ossimIrect(theVul.x, + theVul.y, + theVul.x + (w2), + theVul.y + (h2)); + + tempUrRect = ossimIrect(theVul.x + w2+1, + theVul.y, + theVul.x + w2 + (w2), + theVul.y + (h2)); + + tempLrRect = ossimIrect(theVul.x + w2+1, + theVul.y + h2+1, + theVul.x + w2 + (w2), + theVul.y + h2 + (h2)); + + tempLlRect = ossimIrect(theVul.x, + theVul.y + h2+1, + theVul.x + (w2), + theVul.y + h2 + (h2)); + } + } + } +#if 0 + ossimNotify(ossimNotifyLevel_DEBUG) + << "SPLIT++++++++++++++++++++++++++++++++++++++++++++" << endl + << "current = " << vrect << endl + << "ul = " << tempUlRect << endl + << "ur = " << tempUrRect << endl + << "lr = " << tempLrRect << endl + << "ll = " << tempLlRect << endl; +#endif + + ulRect.theVul = tempUlRect.ul(); + ulRect.theVur = tempUlRect.ur(); + ulRect.theVlr = tempUlRect.lr(); + ulRect.theVll = tempUlRect.ll(); + + urRect.theVul = tempUrRect.ul(); + urRect.theVur = tempUrRect.ur(); + urRect.theVlr = tempUrRect.lr(); + urRect.theVll = tempUrRect.ll(); + + lrRect.theVul = tempLrRect.ul(); + lrRect.theVur = tempLrRect.ur(); + lrRect.theVlr = tempLrRect.lr(); + lrRect.theVll = tempLrRect.ll(); + + llRect.theVul = tempLlRect.ul(); + llRect.theVur = tempLlRect.ur(); + llRect.theVlr = tempLlRect.lr(); + llRect.theVll = tempLlRect.ll(); + + ulRect.transformViewToImage(transform); + urRect.transformViewToImage(transform); + lrRect.transformViewToImage(transform); + llRect.transformViewToImage(transform); +} + +void ossimImageRenderer::ossimRendererSubRectInfo::transformImageToView(ossimImageViewTransform* transform) +{ + ossimDpt vul; + ossimDpt vur; + ossimDpt vlr; + ossimDpt vll; + transform->imageToView(theIul, + vul); + transform->imageToView(theIur, + vur); + transform->imageToView(theIlr, + vlr); + transform->imageToView(theIll, + vll); + + theVul = vul; + theVur = vur; + theVlr = vlr; + theVll = vll; + +} + +void ossimImageRenderer::ossimRendererSubRectInfo::transformViewToImage(ossimImageViewTransform* transform) +{ + + ossimDpt nvul = theVul; + ossimDpt nvur = theVur;; + ossimDpt nvlr = theVlr; + ossimDpt nvll = theVll; + + transform->viewToImage(nvul, + theIul); + transform->viewToImage(nvur, + theIur); + transform->viewToImage(nvlr, + theIlr); + transform->viewToImage(nvll, + theIll); + + + if(imageHasNans()) + { + theViewToImageScale.makeNan(); + } + else + { + theViewToImageScale = ossimDpt(1.0, 1.0); + + ossimDpt topDelta = theIur - theIul; + ossimDpt rightDelta = theIlr - theIur; + ossimDpt bottomDelta = theIll - theIlr; + ossimDpt leftDelta = theIul - theIll; + double topLen = topDelta.length(); + double bottomLen = bottomDelta.length(); + double rightLen = rightDelta.length(); + double leftLen = leftDelta.length(); + +// double averageHoriz = ((topLen + 1) + (bottomLen+1))*.5; +// double averageVert = ((leftLen+1) + (rightLen+1))*.5; + double averageHoriz = ((topLen) + (bottomLen))*.5; + double averageVert = ((leftLen) + (rightLen))*.5; + + + ossimDpt deltaViewP1P2 = theVul - theVur; + ossimDpt deltaViewP1P3 = theVul - theVll; + + double lengthViewP1P2 = deltaViewP1P2.length();//+1; + double lengthViewP1P3 = deltaViewP1P3.length();//+1; + + if(lengthViewP1P2 > FLT_EPSILON) + { + theViewToImageScale.x = averageHoriz/lengthViewP1P2; + } + else + { + theViewToImageScale.makeNan(); + } + if(lengthViewP1P3 > FLT_EPSILON) + { + theViewToImageScale.y = averageVert/lengthViewP1P3; + + } + else + { + theViewToImageScale.makeNan(); + } + + if(!theViewToImageScale.hasNans()) + { + theImageToViewScale.x = 1.0/theViewToImageScale.x; + theImageToViewScale.y = 1.0/theViewToImageScale.y; + } + else + { + theImageToViewScale.makeNan(); + } + } +} + +void ossimImageRenderer::ossimRendererSubRectInfo::stretchImageOut(bool enableRound) +{ + ossimDpt topDelta = theIur - theIul; + ossimDpt rightDelta = theIlr - theIur; + ossimDpt bottomDelta = theIll - theIlr; + ossimDpt leftDelta = theIul - theIll; + + topDelta = topDelta*(1.0/topDelta.length()); + rightDelta = rightDelta*(1.0/rightDelta.length()); + bottomDelta = bottomDelta*(1.0/bottomDelta.length()); + leftDelta = leftDelta*(1.0/leftDelta.length()); + + theIul = theIul + ((leftDelta - topDelta)*.5); + theIur = theIur + ((topDelta - rightDelta)*.5); + theIlr = theIlr + ((rightDelta - bottomDelta)*.5); + theIll = theIll + ((bottomDelta - leftDelta)*.5); + + if(enableRound) + { + theIul = ossimIpt(irint(theIul.x), + irint(theIul.y)); + theIur = ossimIpt(irint(theIur.x), + irint(theIur.y)); + theIlr = ossimIpt(irint(theIlr.x), + irint(theIlr.y)); + theIll = ossimIpt(irint(theIll.x), + irint(theIll.y)); + } +} + + +bool ossimImageRenderer::ossimRendererSubRectInfo::isIdentity()const +{ +// ossimDpt deltaP1P2 = theIul - theIur; +// ossimDpt deltaP1P3 = theIul - theIll; + +// ossimDpt deltaViewP1P2 = theVul - theVur; +// ossimDpt deltaViewP1P3 = theVul - theVll; + +// bool horizontalSigns = ossimGetSign(deltaP1P2.x)==ossimGetSign(deltaViewP1P2.x); +// bool verticalSigns = ossimGetSign(deltaP1P3.y)==ossimGetSign(deltaViewP1P3.y); + +// // check first to see if any horizontal or vertical flipping +// // +// if(horizontalSigns && verticalSigns) +// { +// // check scales to see if they are 1 +// if(fabs(1-theViewToImageScale.x) <= FLT_EPSILON && +// fabs(1-theViewToImageScale.y) <= FLT_EPSILON) +// { +// return true; +// } +// } + + double iulDelta = (theIul-theVul).length(); + double iurDelta = (theIur-theVur).length(); + double ilrDelta = (theIlr-theVlr).length(); + double illDelta = (theIll-theVll).length(); + + return ((iulDelta <= FLT_EPSILON)&& + (iurDelta <= FLT_EPSILON)&& + (ilrDelta <= FLT_EPSILON)&& + (illDelta <= FLT_EPSILON)); +} + +bool ossimImageRenderer::ossimRendererSubRectInfo::canBilinearInterpolate(ossimImageViewTransform* transform, + double error)const +{ + if(imageHasNans()) + { + return false; + } + ossimDpt imageToViewScale = getAbsValueImageToViewScales(); + + if(imageToViewScale.hasNans()) return false; + ossimDpt vUpper, vRight, vBottom, vLeft, vCenter; + ossimDpt iUpper, iRight, iBottom, iLeft, iCenter; + + getViewMids(vUpper, vRight, vBottom, vLeft, vCenter); + getImageMids(iUpper, iRight, iBottom, iLeft, iCenter); + + ossimDpt testCenter; + + ossimDpt iFullRes(iCenter.x*imageToViewScale.x, + iCenter.y*imageToViewScale.y); + + transform->viewToImage(vCenter, testCenter); + + if(testCenter.hasNans()) + { + return false; + } + ossimDpt testFullRes(testCenter.x*imageToViewScale.x, + testCenter.y*imageToViewScale.y); + + double errorCheck1 = (testFullRes - iFullRes).length(); + + iFullRes = ossimDpt(iUpper.x*imageToViewScale.x, + iUpper.y*imageToViewScale.y); + + transform->viewToImage(vUpper, testCenter); + if(testCenter.hasNans()) + { + return false; + } + testFullRes = ossimDpt(testCenter.x*imageToViewScale.x, + testCenter.y*imageToViewScale.y); + double errorCheck2 = (testFullRes - iFullRes).length(); + + iFullRes = ossimDpt(iRight.x*imageToViewScale.x, + iRight.y*imageToViewScale.y); + + transform->viewToImage(vRight, testCenter); + if(testCenter.hasNans()) + { + return false; + } + testFullRes = ossimDpt(testCenter.x*imageToViewScale.x, + testCenter.y*imageToViewScale.y); + double errorCheck3 = (testFullRes - iFullRes).length(); + + iFullRes = ossimDpt(iBottom.x*imageToViewScale.x, + iBottom.y*imageToViewScale.y); + + transform->viewToImage(vBottom, testCenter); + if(testCenter.hasNans()) + { + return false; + } + testFullRes = ossimDpt(testCenter.x*imageToViewScale.x, + testCenter.y*imageToViewScale.y); + double errorCheck4 = (testFullRes - iFullRes).length(); + + iFullRes = ossimDpt(iLeft.x*imageToViewScale.x, + iLeft.y*imageToViewScale.y); + + transform->viewToImage(vLeft, testCenter); + testFullRes = ossimDpt(testCenter.x*imageToViewScale.x, + testCenter.y*imageToViewScale.y); + double errorCheck5 = (testFullRes - iFullRes).length(); + + + return ((errorCheck1 < error)&& + (errorCheck2 < error)&& + (errorCheck3 < error)&& + (errorCheck4 < error)&& + (errorCheck5 < error)); + +} + + +void ossimImageRenderer::ossimRendererSubRectInfo::getViewMids(ossimDpt& upperMid, + ossimDpt& rightMid, + ossimDpt& bottomMid, + ossimDpt& leftMid, + ossimDpt& center)const +{ + + upperMid = (theVul + theVur)*.5; + rightMid = (theVur + theVlr)*.5; + bottomMid = (theVlr + theVll)*.5; + leftMid = (theVul + theVll)*.5; + center = (theVul + theVur + theVlr + theVll)*.25; +} + +void ossimImageRenderer::ossimRendererSubRectInfo::getImageMids(ossimDpt& upperMid, + ossimDpt& rightMid, + ossimDpt& bottomMid, + ossimDpt& leftMid, + ossimDpt& center)const +{ + if(imageHasNans()) + { + upperMid.makeNan(); + rightMid.makeNan(); + bottomMid.makeNan(); + leftMid.makeNan(); + center.makeNan(); + } + else + { + upperMid = (theIul + theIur)*.5; + rightMid = (theIur + theIlr)*.5; + bottomMid = (theIlr + theIll)*.5; + leftMid = (theIul + theIll)*.5; + center = (theIul + theIur + theIlr + theIll)*.25; + } +} + +ossimDpt ossimImageRenderer::ossimRendererSubRectInfo::getParametricCenter(const ossimDpt& ul, const ossimDpt& ur, + const ossimDpt& lr, const ossimDpt& ll)const +{ + ossimDpt top = ur - ul; + ossimDpt bottom = lr - ll; + + ossimDpt centerTop = ul + top * .5; + ossimDpt centerBottom = ll + bottom * .5; + + return centerBottom + (centerBottom - centerTop)*.5; +} + +ossimImageRenderer::ossimImageRenderer() + : + ossimImageSourceFilter(), + ossimViewInterface(NULL), + theResampler(NULL), + theBlankTile(NULL), + theTile(NULL), + theTemporaryBuffer(NULL), + theCachedTile(NULL), + theStartingResLevel(0), + theImageViewTransform(NULL), + theMaxRecursionLevel(5), + theAutoUpdateInputTransform(true) +{ + ossimViewInterface::theObject = this; + theResampler = new ossimFilterResampler(); + theImageViewTransform = new ossimImageViewProjectionTransform; + theBoundingRect.makeNan(); +// theInputRect.makeNan(); +// theOutputRect.makeNan(); +} + +ossimImageRenderer::ossimImageRenderer(ossimImageSource* inputSource, + ossimImageViewTransform* imageViewTrans) + : ossimImageSourceFilter(inputSource), + ossimViewInterface(NULL), + theResampler(NULL), + theBlankTile(NULL), + theTile(NULL), + theTemporaryBuffer(NULL), + theCachedTile(NULL), + theStartingResLevel(0), + theImageViewTransform(imageViewTrans), + theMaxRecursionLevel(5), + theAutoUpdateInputTransform(true) +{ + ossimViewInterface::theObject = this; + theResampler = new ossimFilterResampler(); + if(!theImageViewTransform) + { + theImageViewTransform = new ossimImageViewProjectionTransform; + } +} + +ossimImageRenderer::~ossimImageRenderer() +{ + if (theImageViewTransform) + { + delete theImageViewTransform; + theImageViewTransform = NULL; + } + + if(theResampler) + { + delete theResampler; + theResampler = NULL; + } +} + +ossimRefPtr<ossimImageData> ossimImageRenderer::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ +#if 0 + static const char MODULE[] = "ossimImageRenderer::getTile"; + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << "Requesting view rect = " + << tileRect << endl; + } +#endif + + // long w = tileRect.width(); + // long h = tileRect.height(); + // ossimIpt origin = tileRect.ul(); + + if(!theBlankTile.valid() || !theTile.valid()) + { + allocate(); + } + + if(!theTile.valid()) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimImageRenderer::getTile tile allocation failure!\n" + << endl; + } + return ossimImageSourceFilter::getTile(tileRect, resLevel); + } + + if(theBlankTile.valid()) + { + theBlankTile->setImageRectangle(tileRect); + } + + if(!theInputConnection) + { + return theBlankTile; + } + + if ( !isSourceEnabled()||(!theImageViewTransform)|| + (!theImageViewTransform->isValid()) ) + { + // This tile source bypassed, return the input tile source. + return theInputConnection->getTile(tileRect, resLevel); + } + + if(theBoundingViewRect.hasNans()) + { + theBoundingViewRect = getBoundingRect(); + } + if(theBoundingViewRect.width() < 4 && + theBoundingViewRect.height() < 4) + { + return theBlankTile; + } + ossimIrect rect = theBoundingViewRect; + if( !theInputConnection || !rect.intersects(tileRect) ) + { + return theBlankTile; + } + + if(!theTile) + { + return theInputConnection->getTile(tileRect, resLevel); + } + + // long tw = theTile->getWidth(); + // long th = theTile->getHeight(); + + theTile->setImageRectangle(tileRect); + theTile->makeBlank(); + + ossimRendererSubRectInfo subRectInfo(tileRect.ul(), + tileRect.ur(), + tileRect.lr(), + tileRect.ll()); + + subRectInfo.transformViewToImage(theImageViewTransform); +// std::cout << subRectInfo << std::endl; + if(subRectInfo.imageIsNan()) + { + return theBlankTile; + } + + +// if(subRectInfo.isIdentity()&& +// !subRectInfo.imageHasNans()) +// { +// return theInputConnection->getTile(tileRect, resLevel); +// } +// else +// { + recursiveResample(theTile, subRectInfo, 1); + theTile->validate(); +// } + return theTile; +} + +void ossimImageRenderer::recursiveResample(ossimRefPtr<ossimImageData> outputData, + const ossimRendererSubRectInfo& rectInfo, + ossim_uint32 level) +{ + ossimIrect tempViewRect = rectInfo.getViewRect(); + if(rectInfo.imageIsNan()) + { + return; + } + + if(tempViewRect.width() <2 && + tempViewRect.height() <2) + { + if(!rectInfo.imageHasNans()) + { + fillTile(outputData, + rectInfo); + } + return; + } + const double error = 1; + if(rectInfo.canBilinearInterpolate(theImageViewTransform, error)) + { // then draw the tile + fillTile(outputData, + rectInfo); + return; + } + else + { + // split into four subtiles + ossimRendererSubRectInfo ulRectInfo; + ossimRendererSubRectInfo urRectInfo; + ossimRendererSubRectInfo lrRectInfo; + ossimRendererSubRectInfo llRectInfo; + + rectInfo.splitView(theImageViewTransform, + ulRectInfo, + urRectInfo, + lrRectInfo, + llRectInfo); + + ossimDrect vrect = rectInfo.getViewRect(); + +#if 0 + ossimNotify(ossimNotifyLevel_DEBUG) + << "vrect = " << vrect + << "\nwidth = " << vrect.width() + << "\nheight = " << vrect.height() + << "\nlevel = " << level << endl; +#endif + bool scaleUlNeedsSplit = ((!ulRectInfo.canBilinearInterpolate(theImageViewTransform, error))|| + ulRectInfo.imageHasNans()); + bool scaleUrNeedsSplit = ((!urRectInfo.canBilinearInterpolate(theImageViewTransform, error))|| + urRectInfo.imageHasNans()); + bool scaleLrNeedsSplit = ((!lrRectInfo.canBilinearInterpolate(theImageViewTransform, error))|| + lrRectInfo.imageHasNans()); + bool scaleLlNeedsSplit = ((!llRectInfo.canBilinearInterpolate(theImageViewTransform, error))|| + llRectInfo.imageHasNans()); + + bool tooSmall = (vrect.width() < 4) && (vrect.height()<4); + // + if(!tooSmall) + { + if(scaleUlNeedsSplit|| + scaleUrNeedsSplit|| + scaleLrNeedsSplit|| + scaleLlNeedsSplit) + { + if(scaleUlNeedsSplit) + { + recursiveResample(outputData, + ulRectInfo, + level + 1); + } + else + { + fillTile(outputData, ulRectInfo); + } + if(scaleUrNeedsSplit) + { + recursiveResample(outputData, + urRectInfo, + level + 1); + } + else + { + fillTile(outputData, urRectInfo); + } + + if(scaleLrNeedsSplit) + { + recursiveResample(outputData, + lrRectInfo, + level + 1); + } + else + { + fillTile(outputData, lrRectInfo); + } + + if(scaleLlNeedsSplit) + { + recursiveResample(outputData, + llRectInfo, + level + 1); + } + else + { + fillTile(outputData, llRectInfo); + } + } + else + { + fillTile(outputData, + rectInfo); + } + } + else if(!rectInfo.imageHasNans()) + { + fillTile(outputData, + rectInfo); + } + } +} + +void ossimImageRenderer::fillTile(ossimRefPtr<ossimImageData> outputData, + const ossimRendererSubRectInfo& rectInfo) +{ + if(!outputData.valid() || !outputData->getBuf() || rectInfo.imageHasNans()) + { + return; + } + ossimIrect vrect = rectInfo.getViewRect(); + + ossimDpt imageToViewScale = rectInfo.getAbsValueImageToViewScales(); + + if(imageToViewScale.hasNans()) return; + + ossimDpt tile_size = ossimDpt(vrect.width(), vrect.height()); + double kernelSupportX, kernelSupportY; + double averageScale = (imageToViewScale.x + imageToViewScale.y)/2.0; + long closestFitResLevel = (long)floor(log(1.0/averageScale)/ + log(2.0)); + + ossim_uint32 resLevel = closestFitResLevel<0?0:closestFitResLevel; + resLevel += theStartingResLevel; + double closestScale = 1.0/pow((double)2.0,(double)resLevel); + + ossimDrect requestRect = rectInfo.getImageRect()*ossimDpt(closestScale,closestScale); + + ossimDpt nul(rectInfo.theIul.x*closestScale, + rectInfo.theIul.y*closestScale); + ossimDpt nll(rectInfo.theIll.x*closestScale, + rectInfo.theIll.y*closestScale); + ossimDpt nlr(rectInfo.theIlr.x*closestScale, + rectInfo.theIlr.y*closestScale); + ossimDpt nur(rectInfo.theIur.x*closestScale, + rectInfo.theIur.y*closestScale); + + ossimDpt newScale(imageToViewScale.x/closestScale, + imageToViewScale.y/closestScale); + + theResampler->setScaleFactor(newScale); + + theResampler->getKernelSupport(kernelSupportX, + kernelSupportY); + + ossimDrect boundingRect = ossimDrect(nul, + nll, + nlr, + nur); + + boundingRect = ossimIrect((ossim_int32)floor(boundingRect.ul().x - (kernelSupportX)-.5), + (ossim_int32)floor(boundingRect.ul().y - (kernelSupportY)-.5), + (ossim_int32)ceil(boundingRect.lr().x + (kernelSupportX)+.5), + (ossim_int32)ceil(boundingRect.lr().y + (kernelSupportY)+.5)); +// boundingRect = ossimIrect((ossim_int32)floor(boundingRect.ul().x - (kernelSupportX)), +// (ossim_int32)floor(boundingRect.ul().y - (kernelSupportY)), +// (ossim_int32)ceil(boundingRect.lr().x + (kernelSupportX)), +// (ossim_int32)ceil(boundingRect.lr().y + (kernelSupportY))); + + requestRect = boundingRect; + + // ossimIrect reqRect = requestRect; + + ossimRefPtr<ossimImageData> data; + if(theCachedTile.valid()) + { + ossimIrect cachedTileRect = theCachedTile->getImageRectangle(); +#if 0 + ossimNotify(ossimNotifyLevel_DEBUG) + << "cached tile rect = " << cachedTileRect << endl + << "requestRect = " << requestRect << endl; +#endif +#if 0 + if(requestRect.completely_within(cachedTileRect)&& + resLevel == theCachedTileResLevel) + { + // ossimNotify(ossimNotifyLevel_DEBUG) + // << "SETTING TO CACHED RECT" << endl; + data = theCachedTile; + } +#endif + } + + if(!data.valid()) + { +#if 0 + ossimNotify(ossimNotifyLevel_DEBUG) + << "--------------------Wiping out old cached rect" << endl; +#endif +// if( (requestRect.width() < 64 ) || (requestRect.height() < 64) ) +// { +// requestRect.stretchToTileBoundary(ossimIpt(64, 64)); +// } + data = getTileAtResLevel(requestRect, resLevel); + if(theCachedTile.valid()) + { + theCachedTile = NULL; + } +// if(data) +// { +// theCachedTileResLevel = resLevel; +// theCachedTile = (ossimImageData*)data->dup(); +// } + } + + ossimDataObjectStatus status = OSSIM_NULL; + if(data.valid()) + { + status = data->getDataObjectStatus(); + } + if( (status == OSSIM_NULL) || + (status == OSSIM_EMPTY)) + { + return; + } + + ossimDrect bounds = theBoundingRect; + // setup the clamp for the resampler + // +// if(static_cast<ossim_uint32>(resLevel) < theInputDecimationFactors.size()) +// { +// bounds = bounds*theInputDecimationFactors[resLevel]; +// } +// else if(theInputDecimationFactors.size() > 0) +// { + +// bounds = bounds*theInputDecimationFactors[theInputDecimationFactors.size()-1]; +// } + +// theResampler->setBoundingInputRect(bounds); + + bounds = bounds*ossimDpt(closestScale, closestScale); + theResampler->setBoundingInputRect(bounds); + + double denominatorX = 1.0; + double denominatorY = 1.0; + + if(tile_size.x > 2) + { + denominatorX = tile_size.x-1.0; + } + if(tile_size.y > 2) + { + denominatorY = tile_size.y-1.0; + } + theResampler->setScaleFactor(newScale); + theResampler->resample(data, + outputData, + rectInfo.getViewRect(), + nul, + nur, + ossimDpt( ( (nll.x - nul.x)/denominatorY ), + ( (nll.y - nul.y)/denominatorY ) ), + ossimDpt( ( (nlr.x - nur.x)/denominatorY ), + ( (nlr.y - nur.y)/denominatorY ) ), +// ossimDpt( ( (nll.x - nul.x)/denominatorX ), +// ( (nll.y - nul.y)/denominatorY ) ), +// ossimDpt( ( (nlr.x - nur.x)/denominatorX ), +// ( (nlr.y - nur.y)/denominatorY ) ), + tile_size); +// outputData->validate(); +} + +long ossimImageRenderer::computeClosestResLevel(const std::vector<ossimDpt>& decimationFactors, + double scale)const +{ + long result = 0; + long upper = (long)decimationFactors.size(); + bool done = false; + + if(upper > 1) + { + while((result < upper)&&!done) + { + if(scale < decimationFactors[result].x) + { + ++result; + } + else + { + done = true; + } + } + + // now use the higher res level and resample down + // + if(result) + { + --result; + } + } + return result; +} + +ossimIrect ossimImageRenderer::getBoundingRect(ossim_uint32 resLevel)const +{ + static const char* MODULE = "ossimImageRenderer::getBoundingRect()"; + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << "entered..." << endl; + } + if(!theBoundingViewRect.hasNans()) + { + return theBoundingViewRect; + } + + vector<ossimDpt> points(4); + +// if(!theOutputRect.hasNans()) return theOutputRect; + ossimDrect inputRect; + ossimIrect outputRect; + + inputRect.makeNan(); + outputRect.makeNan(); + + if(theInputConnection&&theImageViewTransform) + { + inputRect = theInputConnection->getBoundingRect(resLevel); + + if(isSourceEnabled()&&theImageViewTransform->isValid()) + { +// inputRect = ossimDrect(inputRect.ul().x, +// inputRect.ul().y, +// inputRect.lr().x, +// inputRect.lr().y); + +// theImageViewTransform->imageToView(inputRect.ul(), points[0]); +// theImageViewTransform->imageToView(inputRect.ur(), points[1]); +// theImageViewTransform->imageToView(inputRect.lr(), points[2]); +// theImageViewTransform->imageToView(inputRect.ll(), points[3]); + + + ossimDrect tempRect = theImageViewTransform->getImageToViewBounds(inputRect); + + theBoundingViewRect = ossimIrect(static_cast<int>(floor(tempRect.ul().x + 0.5)), + static_cast<int>(floor(tempRect.ul().y + 0.5)), + static_cast<int>(floor(tempRect.lr().x + 0.5)), + static_cast<int>(floor(tempRect.lr().y + 0.5))); + } + else + { + theBoundingViewRect = inputRect; + } + } + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " bounds = " + << outputRect + << "\n w, h = " << outputRect.width() << ", " + << outputRect.height() + << endl; + } + + return theBoundingViewRect; +} + +void ossimImageRenderer::initialize() +{ + //--- + // Call the base class initialize. + // Note: This will reset "theInputConnection" if it changed... + //--- + ossimImageSourceFilter::initialize(); + + theBoundingViewRect.makeNan(); + theBoundingRect.makeNan(); + + if (theInputConnection) + { + theBoundingRect = theInputConnection->getBoundingRect(); + } + + if (theImageViewTransform) + { + ossimImageViewProjectionTransform* trans + = PTR_CAST(ossimImageViewProjectionTransform, + theImageViewTransform); + if(trans) + { + if(PTR_CAST(ossimMapProjection, trans->getImageProjection()) || + (!trans->getImageProjection())|| + (!trans->getViewProjection())) + { + checkTransform(); + } + } + } + + if (theResampler) + { + theResampler->setBoundingInputRect(theBoundingRect); + } + + theInputDecimationFactors.clear(); + + deallocate(); +// if (theInputConnection && theTile.valid()) +// { +// if ( theInputConnection->getNumberOfOutputBands() != +// theTile->getNumberOfBands()) +// { +// //--- +// // This will wide things slick and force an allocate() call on first +// // getTile(). +// //--- +// deallocate(); +// } +// } +} + +void ossimImageRenderer::deallocate() +{ + theTile = NULL; + theBlankTile = NULL; + theTemporaryBuffer = NULL; + theCachedTile = NULL; +} + +void ossimImageRenderer::allocate() +{ + deallocate(); + + if(theInputConnection) + { + theTile = ossimImageDataFactory::instance()->create(this, this); + theBlankTile = ossimImageDataFactory::instance()->create(this, this); + + theTile->initialize(); + theBoundingRect = theInputConnection->getBoundingRect(); + } +} + +bool ossimImageRenderer::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + if(theImageViewTransform) + { + ossimString newPrefix = ossimString(prefix) + ossimString("image_view_trans."); + + theImageViewTransform->saveState(kwl, newPrefix.c_str()); + } + if(theResampler) + { + theResampler->saveState(kwl, + (ossimString(prefix)+"resampler.").c_str()); + } + return ossimImageSource::saveState(kwl, prefix); +} + +bool ossimImageRenderer::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimImageRenderer::loadState entered..." << endl; + +#ifdef OSSIM_ID_ENABLED + ossimNotify(ossimNotifyLevel_DEBUG) + << "OSSIM_ID: " << OSSIM_ID << endl; +#endif + } + + ossimString newPrefix = ossimString(prefix) + ossimString("image_view_trans."); + bool result = ossimImageSourceFilter::loadState(kwl, prefix); + theInputDecimationFactors.clear(); + + if(theResampler) + { + theResampler->loadState(kwl, + (ossimString(prefix)+"resampler.").c_str()); + } + if(theImageViewTransform) + { + delete theImageViewTransform; + theImageViewTransform = NULL; + } + theImageViewTransform = ossimImageViewTransformFactory::instance()->createTransform(kwl, newPrefix.c_str()); + if(!theImageViewTransform) + { + theImageViewTransform = new ossimImageViewProjectionTransform; + } + return result; +} + +void ossimImageRenderer::setImageViewTransform(ossimImageViewTransform* transform) +{ + if(theImageViewTransform) + { + delete theImageViewTransform; + } + theImageViewTransform = transform; + + ossimImageViewProjectionTransform* trans = PTR_CAST(ossimImageViewProjectionTransform, + theImageViewTransform); + if(trans) + { + if(!trans->getImageProjection()) + { + checkTransform(); + } + } + +} + +bool ossimImageRenderer::setView(ossimObject* baseObject, + bool ownsTheView) +{ + bool result = false; + theBoundingViewRect.makeNan(); + if(theImageViewTransform) + { + result = theImageViewTransform->setView(baseObject, + ownsTheView); + } + + return result; +} + +ossimObject* ossimImageRenderer::getView() +{ + if(theImageViewTransform) + { + return theImageViewTransform->getView(); + } + return NULL; +} + +const ossimObject* ossimImageRenderer::getView()const +{ + if(theImageViewTransform) + { + return theImageViewTransform->getView(); + } + return NULL; +} + +void ossimImageRenderer::getValidImageVertices(vector<ossimIpt>& validVertices, + ossimVertexOrdering ordering, + ossim_uint32 resLevel)const +{ + if(theInputConnection&&theImageViewTransform&&theImageViewTransform->isValid()) + { + theInputConnection->getValidImageVertices(validVertices, ordering, resLevel); + if(isSourceEnabled()) + { + long inputSize = validVertices.size(); + if(inputSize) + { + ossimDpt viewPt; + // transform each point to the view + for(long index = 0; index < inputSize; ++index) + { + theImageViewTransform->imageToView(validVertices[index], viewPt); + + // round it to the nearest pixel + // + validVertices[index] = ossimIpt(viewPt); + } + } + } + } +} + +bool ossimImageRenderer::getImageGeometry(ossimKeywordlist& kwl, + const char* prefix) +{ + if(isSourceEnabled()&&getView()) + { + const ossimObject* view = getView(); + + bool result = view->saveState(kwl, prefix); + + return result; + } + else + { + if(theInputConnection) + { + return theInputConnection->getImageGeometry(kwl, prefix); + } + } + + return false; +} + +void ossimImageRenderer::connectInputEvent(ossimConnectionEvent& event) +{ + theInputConnection = PTR_CAST(ossimImageSourceInterface, getInput(0)); + // All this code in here will change after the demo. For now we need a + // way to bring every one up with a projection. Later we will have to + // tie to a projection source. + // + if(!theImageViewTransform) + { + theImageViewTransform = new ossimImageViewProjectionTransform; + } + + checkTransform(); + + initialize(); + +} + +void ossimImageRenderer::disconnectInputEvent(ossimConnectionEvent& event) +{ + ossimImageViewProjectionTransform* transform = PTR_CAST(ossimImageViewProjectionTransform, + theImageViewTransform); + if(transform) + { + transform->setImageProjection(NULL, true); + } + + theInputConnection = NULL; + theInputDecimationFactors.clear(); +} + +void ossimImageRenderer::propertyEvent(ossimPropertyEvent& event) +{ + checkTransform(); + initialize(); +} + + +void ossimImageRenderer::setProperty(ossimRefPtr<ossimProperty> property) +{ + ossimString tempName = property->getName(); + + if(tempName == "Filter type") + { + if(theResampler) + { + theResampler->setFilterType(property->valueToString()); + } + } +// else if(tempName == "Blur factor") +// { +// if(theResampler) +// { +// theResampler->setBlurFactor(property->valueToString().toDouble()); +// } +// } + else + { + ossimImageSourceFilter::setProperty(property); + } +} + +ossimRefPtr<ossimProperty> ossimImageRenderer::getProperty(const ossimString& name)const +{ + ossimString tempName = name; + + if(tempName == "Filter type") + { + std::vector<ossimString> filterNames; + theResampler->getFilterTypes(filterNames); + + ossimStringProperty* stringProp = new ossimStringProperty("Filter type", + theResampler->getMinifyFilterTypeAsString(), + false, + filterNames); + stringProp->clearChangeType(); + stringProp->setReadOnlyFlag(false); + stringProp->setCacheRefreshBit(); + + return stringProp; + } +// else if(tempName == "Blur factor") +// { +// ossimNumericProperty* numericProperty = new ossimNumericProperty("Blur factor", +// ossimString::toString((double)theResampler->getBlurFactor())); + +// numericProperty->setConstraints(0.0, 50.0); +// numericProperty->setNumericType(ossimNumericProperty::ossimNumericPropertyType_FLOAT64); +// numericProperty->setCacheRefreshBit(); + +// return numericProperty; +// } + + return ossimImageSourceFilter::getProperty(name); +} + +void ossimImageRenderer::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + ossimImageSourceFilter::getPropertyNames(propertyNames); + + propertyNames.push_back("Filter type"); +// propertyNames.push_back("Blur factor"); +} + + +void ossimImageRenderer::checkTransform() +{ + theBoundingViewRect.makeNan(); + if(!isSourceEnabled()) + { + return; + } + + + + // All this code in here might change after the demo. For now we need a + // way to bring every one up with a projection. Later we will have to + // tie to a projection source. + ossimImageViewProjectionTransform* transform = PTR_CAST(ossimImageViewProjectionTransform, + theImageViewTransform); + ossimImageSourceInterface* inter = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + + // we will only check for projection transforms + if(!transform||!inter) return; + + ossimProjection* proj = NULL; + +// if(theAutoUpdateInputTransform)//|| +// (!transform->getImageProjection())) +// { + if(!transform->getImageProjection()|| + PTR_CAST(ossimMapProjection, transform->getImageProjection())) + { + ossimKeywordlist kwl; + inter->getImageGeometry(kwl); + + proj = ossimProjectionFactoryRegistry::instance()->createProjection(kwl); + transform->setImageProjection(proj, true); + } + else + { + proj = transform->getImageProjection(); + } +// } + + if(proj) + { + if(!transform->getView()) // check to see if we found a view controller and the view was set + { // if not then we will create a default output projection + ossimProjection* newProj = (ossimProjection*)NULL; + ossimMapProjection* mapProj = (ossimMapProjection*)NULL; + if(PTR_CAST(ossimMapProjection, proj)) + { + newProj = (ossimProjection*)proj->dup(); // Make a copy... + + } + else + { + newProj = new ossimEquDistCylProjection; + } + mapProj = PTR_CAST(ossimMapProjection, newProj); + if(mapProj) + { + ossimDpt meters = proj->getMetersPerPixel(); + + double GSD = (meters.x + meters.y)/2.0; + meters.x = GSD; + meters.y = GSD; + mapProj->setUlGpt(proj->origin()); + mapProj->setOrigin(proj->origin()); + mapProj->setMetersPerPixel(meters); + } + transform->setViewProjection(newProj); + } +// } + } + else + { + transform->setImageProjection(NULL, true); + } +} + + +void ossimImageRenderer::getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result)const +{ + if(isSourceEnabled()) + { + result = ossimDpt(1,1); + } + else + { + ossimImageSourceFilter::getDecimationFactor(resLevel, + result); + } +} + +void ossimImageRenderer::getDecimationFactors(vector<ossimDpt>& decimations)const +{ + if(isSourceEnabled()) + { + decimations.push_back(ossimDpt(1,1)); + } + else + { + ossimImageSourceFilter::getDecimationFactors(decimations); + } +} + +ossim_uint32 ossimImageRenderer::getNumberOfDecimationLevels()const +{ + if(isSourceEnabled()) + { + return 1; + } + + return ossimImageSourceFilter::getNumberOfDecimationLevels(); +} +void ossimImageRenderer::stretchQuadOut(const ossimDpt& amount, + ossimDpt& ul, + ossimDpt& ur, + ossimDpt& lr, + ossimDpt& ll) +{ + ossimDpt upper = ur - ul; + ossimDpt right = lr - ur; + ossimDpt bottom = ll - lr; + ossimDpt left = ul - ll; + + upper = (upper*(1.0 / upper.length())); + upper.x *= amount.x; + upper.y *= amount.y; + right = (right*(1.0 / right.length())); + right.x *= amount.x; + right.y *= amount.y; + bottom = (bottom*(1.0 / bottom.length())); + bottom.x *= amount.x; + bottom.y *= amount.y; + left = (left*(1.0 / left.length())); + left.x *= amount.x; + left.y *= amount.y; + + + ul = ul - upper + left; + ur = ur + upper - right; + lr = lr + left - bottom; + ll = ll - left + bottom; +} + +ossimRefPtr<ossimImageData> ossimImageRenderer::getTileAtResLevel(const ossimIrect& boundingRect, + ossim_uint32 resLevel) +{ + if(!theInputConnection) + { + theBlankTile->setImageRectangle(boundingRect); + + return theBlankTile; + } + + ossim_uint32 levels = theInputConnection->getNumberOfDecimationLevels(); + + // ossim_uint32 maxValue = (ossim_uint32)ossimMax((ossim_uint32)theBoundingRect.width(), + // (ossim_uint32)theBoundingRect.height()); + + if(resLevel == 0) + { + return theInputConnection->getTile(boundingRect); + } + if(resLevel < levels) + { + if(theInputConnection) + { + return theInputConnection->getTile(boundingRect, + resLevel); + } + else + { + return theBlankTile; + } + } + else + { + // check to see how many decimations we must achiev for the + // request + // + int decimations = (resLevel - (levels-1)); + ossimIpt tileSize(theInputConnection->getTileWidth(), + theInputConnection->getTileHeight()); + + ossim_int32 multiplier = (1 << decimations); + + ossim_int32 xIndex = 0; + ossim_int32 yIndex = 0; + + // adjust the tilesize so it at least will cover the multiplier + // We will probably come up with something better later but for now + // this will do. + if(multiplier > tileSize.x) + { + tileSize.x = multiplier; + } + if(multiplier > tileSize.y) + { + tileSize.y = multiplier; + } + + // set the rect that covers the requested RLevel to the valid RLevel. + // the valid RLevel is what is available on the input side. + // + ossimIrect requestedRectAtValidRLevel = boundingRect; + requestedRectAtValidRLevel.stretchToTileBoundary(tileSize); + ossimIrect mappedRequestedRect = requestedRectAtValidRLevel; + requestedRectAtValidRLevel = requestedRectAtValidRLevel*((double)multiplier); + + if(!theTemporaryBuffer) + { + theTemporaryBuffer = (ossimImageData*)theBlankTile->dup(); + theTemporaryBuffer->setImageRectangle(mappedRequestedRect); + theTemporaryBuffer->initialize(); + } + else + { + theTemporaryBuffer->setImageRectangle(mappedRequestedRect); + theTemporaryBuffer->makeBlank(); + } + + ossim_uint32 totalCount = ((requestedRectAtValidRLevel.lr().y-requestedRectAtValidRLevel.ul().y)* + (requestedRectAtValidRLevel.lr().x-requestedRectAtValidRLevel.ul().x)); + ossim_uint32 currentCount = 0; + ossimIrect boundingRect = theInputConnection->getBoundingRect(levels-1); + for(yIndex = requestedRectAtValidRLevel.ul().y;yIndex < requestedRectAtValidRLevel.lr().y; yIndex += tileSize.y) + { + for(xIndex = requestedRectAtValidRLevel.ul().x; xIndex < requestedRectAtValidRLevel.lr().x; xIndex+=tileSize.x) + { + ossimIrect request(xIndex, + yIndex, + xIndex + (tileSize.x-1), + yIndex + (tileSize.y-1)); + ossimRefPtr<ossimImageData> data = theInputConnection->getTile(request, levels-1); + + if(data.valid() && (data->getDataObjectStatus()!=OSSIM_EMPTY)&& + data->getBuf()&& + boundingRect.intersects(request)) + { + switch(data->getScalarType()) + { + case OSSIM_UINT8: + { + resampleTileToDecimation((ossim_uint8)0, + theTemporaryBuffer, + data, + multiplier); + break; + } + case OSSIM_SINT16: + { + resampleTileToDecimation((ossim_sint16)0, + theTemporaryBuffer, + data, + multiplier); + break; + } + case OSSIM_UINT16: + case OSSIM_USHORT11: + { + resampleTileToDecimation((ossim_uint16)0, + theTemporaryBuffer, + data, + multiplier); + break; + } + case OSSIM_FLOAT32: + case OSSIM_NORMALIZED_FLOAT: + { + resampleTileToDecimation((ossim_float32)0, + theTemporaryBuffer, + data, + multiplier); + break; + } + case OSSIM_FLOAT64: + case OSSIM_NORMALIZED_DOUBLE: + { + resampleTileToDecimation((ossim_float64)0, + theTemporaryBuffer, + data, + multiplier); + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + break; + } + } + } + ++currentCount; + fireProgressEvent((double)currentCount/ + (double)totalCount); + + } + } + } + theTemporaryBuffer->validate(); + return theTemporaryBuffer; +} + +template <class T> +void ossimImageRenderer::resampleTileToDecimation(T dummyVariable, + ossimRefPtr<ossimImageData> result, + ossimRefPtr<ossimImageData> tile, + ossim_uint32 multiplier) +{ + if(tile->getDataObjectStatus() == OSSIM_EMPTY || + !tile->getBuf()) + { + return; + } + + ossim_int32 maxX = (ossim_int32)tile->getWidth(); + ossim_int32 maxY = (ossim_int32)tile->getHeight(); + ossim_int32 resultHeight = result->getHeight(); + ossim_int32* offsetX = new ossim_int32[maxX]; + ossim_int32* offsetY = new ossim_int32[maxY]; + ossim_int32 i = 0; + ossim_int32 resultWidth = (ossim_int32)result->getWidth(); + ossimIpt tileOrigin = tile->getOrigin(); + ossimIpt resultOrigin = result->getOrigin(); + + // create a lookup table. that maps the tile to the result + for(i = 0; i < maxX; ++i) + { + offsetX[i] = (i+tileOrigin.x)/(ossim_int32)multiplier - resultOrigin.x; + if(offsetX[i] < 0 ) + { + offsetX[i] = 0; + } + else if(offsetX[i] >= resultWidth) + { + offsetX[i] = resultWidth-1; + } + } + for(i = 0; i < maxY; ++i) + { + offsetY[i] = ( ((i+tileOrigin.y)/(ossim_int32)multiplier) - resultOrigin.y); + if(offsetY[i] < 0 ) + { + offsetY[i] = 0; + } + else if(offsetY[i] >= resultHeight) + { + offsetY[i] = resultHeight-1; + } + offsetY[i] *= resultWidth; + } + + if(tile->getDataObjectStatus() == OSSIM_FULL) + { + ossim_int32 numberOfBands = (ossim_int32)std::min(result->getNumberOfBands(), + tile->getNumberOfBands()); + ossim_int32 band = 0; + for(band = 0; band < numberOfBands; ++band) + { + T* tileBuf = static_cast<T*>(tile->getBuf(band)); + T* resultBuf = static_cast<T*>(result->getBuf(band)); + ossim_int32 dx = 0; + ossim_int32 dy = 0; + ossim_int32 boxAverageX = 0; + ossim_int32 boxAverageY = 0; + for(dy = 0; dy < maxY; dy+=multiplier) + { + for(dx = 0; dx < maxX; dx+=multiplier) + { + double sum = 0.0; + for(boxAverageY = 0; + ((boxAverageY < (ossim_int32)multiplier)&& + ((boxAverageY+dy)<maxY)); ++boxAverageY) + { + for(boxAverageX = 0; + ((boxAverageX < (ossim_int32)multiplier)&& + ((boxAverageX+dx)<maxX)); ++boxAverageX) + { + sum += tileBuf[((boxAverageY+dy)*maxX + boxAverageX + dx)]; + } + } + sum /= (double)(multiplier*multiplier); + resultBuf[ offsetX[dx] + offsetY[dy] ] = (T)sum; + } + } + } + } + else + { + ossim_int32 numberOfBands = (ossim_int32)std::min(result->getNumberOfBands(), + tile->getNumberOfBands()); + ossim_int32 band = 0; + for(band = 0; band < numberOfBands; ++band) + { + T* tileBuf = static_cast<T*>(tile->getBuf(band)); + T* resultBuf = static_cast<T*>(result->getBuf(band)); + T tileBufNp = static_cast<T>(tile->getNullPix(band)); + ossim_int32 dx = 0; + ossim_int32 dy = 0; + ossim_int32 boxAverageX = 0; + ossim_int32 boxAverageY = 0; + for(dy = 0; dy < maxY; dy+=multiplier) + { + for(dx = 0; dx < maxX; dx+=multiplier) + { + double sum = 0.0; + if(tileBuf[((dy+(multiplier>>1))*maxX + dx+(multiplier>>1))] != tileBufNp) + { + ossim_uint32 nullCount = 0; + for(boxAverageY = 0; + ((boxAverageY < (ossim_int32)multiplier)&& + ((boxAverageY+dy)<maxY)); ++boxAverageY) + { + for(boxAverageX = 0; + ((boxAverageX < (ossim_int32)multiplier)&& + ((boxAverageX+dx)<maxX)); ++boxAverageX) + { + T value = tileBuf[((boxAverageY+dy)*maxX + boxAverageX + dx)]; + if(value != tileBufNp) + { + sum += value; + } + else + { + ++nullCount; + } + } + } + ossim_uint32 area = multiplier*multiplier; + sum /= (double)(area); + if(nullCount!= area) + { + resultBuf[ offsetX[dx] + offsetY[dy] ] = (T)sum; + } + } + } + } + } + + } + + delete [] offsetX; + delete [] offsetY; +} + +ossimString ossimImageRenderer::getLongName() const +{ + return ossimString("Image Renderer"); +} + +ossimString ossimImageRenderer::getShortName() const +{ + return ossimString("Image Renderer"); +} + + void ossimImageRenderer::enableSource() +{ + ossimImageSourceFilter::enableSource(); + checkTransform(); + initialize(); +} + +void ossimImageRenderer::fireProgressEvent(double percentComplete) +{ + ossimProcessProgressEvent event(this, percentComplete); + fireEvent(event); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageRenderer.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageRenderer.h new file mode 100644 index 0000000000..c47386ede4 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageRenderer.h @@ -0,0 +1,402 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimImageRenderer.h,v 1.63 2005/11/09 14:31:23 gpotts Exp $ + +#ifndef ossimImageRenderer_HEADER +#define ossimImageRenderer_HEADER +#include <imaging/tile_sources/ossimImageSourceFilter.h> +#include <base/common/ossimViewInterface.h> +#include <base/data_types/ossimRationalNumber.h> + +class ossimImageViewTransform; +class ossimImageData; +class ossimDiscreteConvolutionKernel; +class ossimFilterResampler; + +class OSSIMDLLEXPORT ossimImageRenderer : public ossimImageSourceFilter, + public ossimViewInterface +{ +public: + ossimImageRenderer(); + ossimImageRenderer(ossimImageSource* inputSource, + ossimImageViewTransform* imageViewTrans = NULL); + virtual ~ossimImageRenderer(); + + virtual ossimString getLongName() const; + virtual ossimString getShortName() const; + + virtual void enableSource(); + + /** + * the resampler will need the tile request to come from the view. + * It will use the view to transoform this to world and then use the + * image's projection to get it into final line sample. This way + * the resampler can fill a tile width by height on the screen + * correctly. + */ + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& origin, + ossim_uint32 resLevel=0); + + virtual void initialize(); + + /** + * TheResampler will adjust the rect to whatever the view is. So it + * will project the full image rect onto the view and return the upright + * bounding rect. + */ + virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0)const; + + /** + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + void setImageViewTransform(ossimImageViewTransform* transform); + ossimImageViewTransform* getImageViewTransform(){return theImageViewTransform;} + + virtual bool getImageGeometry(ossimKeywordlist& kwl, + const char* prefix=0); + virtual bool setView(ossimObject* baseObject, + bool ownsTheView = false); + ossimFilterResampler* getResampler() + { + return theResampler; + } + virtual ossimObject* getView(); + virtual const ossimObject* getView()const; + + virtual void getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result)const; + virtual void getDecimationFactors(vector<ossimDpt>& decimations)const; + virtual ossim_uint32 getNumberOfDecimationLevels()const; + + + virtual void setAutoUpdateInputTransformFlag(bool flag) + { + theAutoUpdateInputTransform = flag; + } + /** + * ordering specifies how the vertices should be arranged. + * valid image vertices is basically the tightly fit convex hull + * of the image. Usually an image has NULL values and are + * internally not upright rectangular. This can cause + * problems some spatial filters. + * + * We need to make sure that the resampler overrides this method. + * it needs to transform the vertices to the view's side. + */ + virtual void getValidImageVertices(vector<ossimIpt>& validVertices, + ossimVertexOrdering ordering=OSSIM_CLOCKWISE_ORDER, + ossim_uint32 resLevel=0)const; + + void connectInputEvent(ossimConnectionEvent& event); + void disconnectInputEvent(ossimConnectionEvent& event); + void propertyEvent(ossimPropertyEvent& event); + + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + +private: + + + class ossimRendererSubRectInfo + { + public: + friend std::ostream& operator <<(std::ostream& out, + const ossimRendererSubRectInfo& rhs) + { + return out << "vul: " << rhs.theVul << endl + << "vur: " << rhs.theVur << endl + << "vlr: " << rhs.theVlr << endl + << "vll: " << rhs.theVll << endl + << "iul: " << rhs.theIul << endl + << "iur: " << rhs.theIur << endl + << "ilr: " << rhs.theIlr << endl + << "ill: " << rhs.theIll << endl + << "scale: " << rhs.theViewToImageScale << endl; + + } + ossimRendererSubRectInfo() + { + theVul.makeNan(); + theVur.makeNan(); + theVlr.makeNan(); + theVll.makeNan(); + theIul.makeNan(); + theIur.makeNan(); + theIlr.makeNan(); + theIll.makeNan(); + theViewToImageScale.makeNan(); + theImageToViewScale.makeNan(); + } + ossimRendererSubRectInfo(const ossimDpt& vul, + const ossimDpt& vur, + const ossimDpt& vlr, + const ossimDpt& vll) + :theVul(vul), + theVur(vur), + theVlr(vlr), + theVll(vll) + { + theIul.makeNan(); + theIur.makeNan(); + theIlr.makeNan(); + theIll.makeNan(); + theViewToImageScale.makeNan(); + theImageToViewScale.makeNan(); + } + + bool imageHasNans()const + { + return ( theIul.hasNans()|| + theIur.hasNans()|| + theIlr.hasNans()|| + theIll.hasNans()); + } + + bool imageIsNan()const + { + return ( theIul.hasNans()&& + theIur.hasNans()&& + theIlr.hasNans()&& + theIll.hasNans()); + } + bool viewHasNans()const + { + return ( theVul.hasNans()|| + theVur.hasNans()|| + theVlr.hasNans()|| + theVll.hasNans()); + } + bool viewIsNan()const + { + return ( theVul.hasNans()&& + theVur.hasNans()&& + theVlr.hasNans()&& + theVll.hasNans()); + } + void splitView(ossimImageViewTransform* transform, + ossimRendererSubRectInfo& ulRect, + ossimRendererSubRectInfo& urRect, + ossimRendererSubRectInfo& lrRect, + ossimRendererSubRectInfo& llRect)const; + + void transformViewToImage(ossimImageViewTransform* transform); + void transformImageToView(ossimImageViewTransform* transform); + + void roundToInteger() + { + theIul = ossimIpt(theIul); + theIur = ossimIpt(theIur); + theIlr = ossimIpt(theIlr); + theIll = ossimIpt(theIll); + + theVul = ossimIpt(theVul); + theVur = ossimIpt(theVur); + theVlr = ossimIpt(theVlr); + theVll = ossimIpt(theVll); + } + void stretchImageOut(bool enableRound=false); + ossimDrect getViewRect()const + { + return ossimDrect(theVul, + theVur, + theVlr, + theVll); + } + ossimDrect getImageRect()const + { + return ossimDrect(theIul, + theIur, + theIlr, + theIll); + } + void roundImageToInteger() + { + theIul = ossimIpt(theIul); + theIur = ossimIpt(theIur); + theIlr = ossimIpt(theIlr); + theIll = ossimIpt(theIll); + } + void roundViewToInteger() + { + theVul = ossimIpt(theVul); + theVur = ossimIpt(theVur); + theVlr = ossimIpt(theVlr); + theVll = ossimIpt(theVll); + } + bool isViewEqual(const ossimRendererSubRectInfo& infoRect)const + { + return ( (theVul == infoRect.theVul)&& + (theVur == infoRect.theVur)&& + (theVlr == infoRect.theVlr)&& + (theVll == infoRect.theVll)); + } + bool isViewEqual(const ossimDrect& viewRect)const + { + return ( (theVul == viewRect.ul())&& + (theVur == viewRect.ur())&& + (theVlr == viewRect.lr())&& + (theVll == viewRect.ll())); + } + ossimDpt getAbsValueViewToImageScales()const + { + if(theViewToImageScale.hasNans()) + { + return theImageToViewScale; + } + return ossimDpt(fabs(theViewToImageScale.x), + fabs(theViewToImageScale.y)); + } + ossimDpt getAbsValueImageToViewScales()const + { + if(theImageToViewScale.hasNans()) + { + return theImageToViewScale; + } + + return ossimDpt(fabs(theImageToViewScale.x), + fabs(theImageToViewScale.y)); + } + bool isViewAPoint()const + { + return ((theVul == theVur)&& + (theVul == theVlr)&& + (theVul == theVll)); + } + bool isIdentity()const; + bool canBilinearInterpolate(ossimImageViewTransform* transform, + double error)const; + + ossimDpt getParametricCenter(const ossimDpt& ul, const ossimDpt& ur, + const ossimDpt& lr, const ossimDpt& ll)const; + + void getViewMids(ossimDpt& upperMid, + ossimDpt& rightMid, + ossimDpt& bottomMid, + ossimDpt& leftMid, + ossimDpt& center)const; + + void getImageMids(ossimDpt& upperMid, + ossimDpt& rightMid, + ossimDpt& bottomMid, + ossimDpt& leftMid, + ossimDpt& center)const; + + ossimDpt theIul; + ossimDpt theIur; + ossimDpt theIlr; + ossimDpt theIll; + + ossimIpt theVul; + ossimIpt theVur; + ossimIpt theVlr; + ossimIpt theVll; + + ossimDpt theViewToImageScale; + ossimDpt theImageToViewScale; + + }; + + void recursiveResample(ossimRefPtr<ossimImageData> outputData, + const ossimRendererSubRectInfo& rectInfo, + ossim_uint32 level); + + + void fillTile(ossimRefPtr<ossimImageData> outputData, + const ossimRendererSubRectInfo& rectInfo); + + ossimIrect getBoundingImageRect()const; + + + /** + *this is called on a property event and on input connection changes. + */ + void checkTransform(); + + void computeRects(); + + ossimRefPtr<ossimImageData> getTileAtResLevel(const ossimIrect& boundingRect, + ossim_uint32 resLevel); + template <class T> + void resampleTileToDecimation(T dummyVariable, + ossimRefPtr<ossimImageData> result, + ossimRefPtr<ossimImageData> tile, + ossim_uint32 multiplier); + + long computeClosestResLevel(const std::vector<ossimDpt>& decimationFactors, + double scale)const; + void stretchQuadOut(const ossimDpt& amount, + ossimDpt& ul, + ossimDpt& ur, + ossimDpt& lr, + ossimDpt& ll); + + /** + * Called on first getTile, will initialize all data needed. + */ + void allocate(); + + /** + * Deletes all allocated tiles. + */ + void deallocate(); + + virtual void fireProgressEvent(double percentComplete); + + ossimFilterResampler* theResampler; + ossimRefPtr<ossimImageData> theBlankTile; + ossimRefPtr<ossimImageData> theTile; + ossimRefPtr<ossimImageData> theTemporaryBuffer; + ossimRefPtr<ossimImageData> theCachedTile; + ossim_uint32 theCachedTileResLevel; + + /** + * This is going to allow us to chain multiple + * renderers together. So if we have one + * renderer doing a scale and they pass an r-level + * down and we have another renderer within the + * chain he will be starting at a different r-level. + * The default will be r-level 0 request coming + * from the right. + */ + ossim_uint32 theStartingResLevel; + ossimImageViewTransform *theImageViewTransform; + mutable ossimIrect theBoundingRect; + mutable ossimIrect theBoundingViewRect; + + /** + * Holds a pre-computed input rect. + */ +// ossimIrect theInputRect; + + /** + * Holds a precomputed output rect. + */ +// ossimIrect theOutputRect; + + ossim_uint32 theMaxRecursionLevel; + bool theAutoUpdateInputTransform; + vector<ossimDpt> theInputDecimationFactors; +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageSharpenFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageSharpenFilter.cpp new file mode 100644 index 0000000000..f63054cada --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageSharpenFilter.cpp @@ -0,0 +1,368 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimImageSharpenFilter.cpp,v 1.8 2005/02/11 15:07:33 dburken Exp $ +#include <imaging/tile_sources/ossimImageSharpenFilter.h> +#include <base/data_types/ossimIrect.h> +#include <imaging/factory/ossimImageDataFactory.h> + +RTTI_DEF1(ossimImageSharpenFilter, "ossimImageSharpenFilter", ossimImageSourceFilter); + +ossimImageSharpenFilter::ossimImageSharpenFilter(ossimObject* owner) + :ossimImageSourceFilter(owner), + theTile(NULL) +{ +} + +ossimImageSharpenFilter::~ossimImageSharpenFilter() +{ +} + +ossimRefPtr<ossimImageData> ossimImageSharpenFilter::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if(!theInputConnection) + { + return NULL; + } + + if(!isSourceEnabled()) + { + return theInputConnection->getTile(tileRect, resLevel); + } + + // we have a 3x3 matrix so stretch the rect out to cover + // the required pixels + // + ossimIrect newRect(ossimIpt(tileRect.ul().x - 1, + tileRect.ul().y - 1), + ossimIpt(tileRect.lr().x + 1, + tileRect.lr().y + 1)); + + ossimRefPtr<ossimImageData> data = + theInputConnection->getTile(newRect, resLevel); + + if ( !data.valid() || + ( data->getDataObjectStatus() == OSSIM_NULL ) || + ( data->getDataObjectStatus() == OSSIM_EMPTY ) ) + { + // Caller wants tileRect, not newRect so don't return "data". + return theInputConnection->getTile(tileRect, resLevel); + } + + if (!theTile) + { + allocate(); // First time through... + } + + long w = tileRect.width(); + long h = tileRect.height(); + long tileW = theTile->getWidth(); + long tileH = theTile->getHeight(); + if((w != tileW)|| + (h != tileH)) + { + theTile->setWidth(w); + theTile->setHeight(h); + if((w*h)!=(tileW*tileH)) + { + theTile->initialize(); + } + else + { + theTile->makeBlank(); + } + } + else + { + theTile->makeBlank(); + } + theTile->setOrigin(tileRect.ul()); + + switch(data->getScalarType()) + { + case OSSIM_UCHAR: + { + if(data->getDataObjectStatus() == OSSIM_FULL) + { + sharpenFull(static_cast<ossim_uint8>(0), + data, + theTile); + } + else + { + sharpenPartial(static_cast<ossim_uint8>(0), + data, + theTile); + } + break; + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + if(data->getDataObjectStatus() == OSSIM_FULL) + { + sharpenFull(static_cast<float>(0), + data, + theTile); + } + else + { + sharpenPartial(static_cast<float>(0), + data, + theTile); + } + break; + } + case OSSIM_USHORT16: + case OSSIM_USHORT11: + { + if(data->getDataObjectStatus() == OSSIM_FULL) + { + sharpenFull(static_cast<ossim_uint16>(0), + data, + theTile); + } + else + { + sharpenPartial(static_cast<ossim_uint16>(0), + data, + theTile); + } + break; + } + case OSSIM_SSHORT16: + { + if(data->getDataObjectStatus() == OSSIM_FULL) + { + sharpenFull(static_cast<ossim_sint16>(0), + data, + theTile); + } + else + { + sharpenPartial(static_cast<ossim_sint16>(0), + data, + theTile); + } + break; + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + if(data->getDataObjectStatus() == OSSIM_FULL) + { + sharpenFull(static_cast<double>(0), + data, + theTile); + } + else + { + sharpenPartial(static_cast<double>(0), + data, + theTile); + } + break; + } + default: + { + ossimNotify(ossimNotifyLevel_WARN) << "ossimImageSharpenFilter::getTile WARNING: Scalar type = " << theTile->getScalarType() << " Not supported!" << std::endl; + break; + } + } + theTile->validate(); + + return theTile; +} + + +template<class T> void ossimImageSharpenFilter::sharpenPartial( + T, + const ossimRefPtr<ossimImageData>& inputData, + ossimRefPtr<ossimImageData>& outputData) +{ + double sum = 0.0; + ossim_int32 inputW = (ossim_int32)inputData->getWidth(); + ossim_int32 outputW = (ossim_int32)outputData->getWidth(); + ossim_int32 outputH = (ossim_int32)outputData->getHeight(); + ossim_int32 numberOfBands = (ossim_int32)inputData->getNumberOfBands(); + ossimIpt outputOrigin = outputData->getOrigin(); + ossimIpt inputOrigin = inputData->getOrigin(); + + ossim_int32 startInputOffset = ossimAbs(outputOrigin.y - inputOrigin.y)* + inputW + ossimAbs(outputOrigin.x - inputOrigin.x); + ossim_int32 ulKernelStart = -inputW - 1; + ossim_int32 leftKernelStart = -1; + ossim_int32 llKernelStart = inputW - 1; + + const T* ulKernelStartBuf = NULL; + const T* leftKernelStartBuf = NULL; + const T* llKernelStartBuf = NULL; + + for(ossim_int32 band = 0; band < numberOfBands; ++band) + { + const T* inputBuf = static_cast<const T*>(inputData->getBuf(band)) + + startInputOffset; + T* outputBuf = static_cast<T*>(outputData->getBuf(band)); + T maxPix = static_cast<T>(inputData->getMaxPix(band)); + T minPix = static_cast<T>(inputData->getMinPix(band)); + T nullPix = static_cast<T>(inputData->getNullPix(band)); + + if(inputBuf&&outputBuf) + { + for(ossim_int32 row = 0; row < outputW; ++row) + { + ossim_int32 rowOffset = inputW*row; + ulKernelStartBuf = inputBuf + (rowOffset + ulKernelStart); + leftKernelStartBuf = inputBuf + (rowOffset + leftKernelStart); + llKernelStartBuf = inputBuf + (rowOffset + llKernelStart); + for(ossim_int32 col = 0; col < outputH; ++col) + { + if((ulKernelStartBuf[0] != nullPix)&& + (ulKernelStartBuf[1] != nullPix)&& + (ulKernelStartBuf[2] != nullPix)&& + (leftKernelStartBuf[0] != nullPix)&& + (leftKernelStartBuf[1] != nullPix)&& + (leftKernelStartBuf[2] != nullPix)&& + (llKernelStartBuf[0] != nullPix)&& + (llKernelStartBuf[1] != nullPix)&& + (llKernelStartBuf[2] != nullPix)) + { + sum = -1.0*(double)ulKernelStartBuf[0] + -2.0*(double)ulKernelStartBuf[1] + -1.0*(double)ulKernelStartBuf[2] + + -2.0*(double)leftKernelStartBuf[0] + 16.0*(double)leftKernelStartBuf[1] + -2.0*(double)leftKernelStartBuf[2] + + -1.0*(double)llKernelStartBuf[0] + -2.0*(double)llKernelStartBuf[1] + -1.0*(double)llKernelStartBuf[2]; + sum /= 4.0; + + if(sum > maxPix) + { + *outputBuf = maxPix; + } + else if(sum < minPix || ((T)sum == nullPix)) + { + *outputBuf = minPix; + } + else + { + *outputBuf = static_cast<T>(sum); + } + } + else + { + *outputBuf = nullPix; + } + + ++ulKernelStartBuf; + ++leftKernelStartBuf; + ++llKernelStartBuf; + ++outputBuf; + } + } + } + } +} + +template<class T> void ossimImageSharpenFilter::sharpenFull( + T, + const ossimRefPtr<ossimImageData>& inputData, + ossimRefPtr<ossimImageData>& outputData) +{ + double sum = 0.0; + ossim_int32 inputW = (ossim_int32)inputData->getWidth(); + ossim_int32 outputW = (ossim_int32)outputData->getWidth(); + ossim_int32 outputH = (ossim_int32)outputData->getHeight(); + ossim_int32 numberOfBands = (ossim_int32)inputData->getNumberOfBands(); + ossimIpt outputOrigin = outputData->getOrigin(); + ossimIpt inputOrigin = inputData->getOrigin(); + + ossim_int32 startInputOffset = ossimAbs(outputOrigin.y - inputOrigin.y)* + inputW + ossimAbs(outputOrigin.x - inputOrigin.x); + ossim_int32 ulKernelStart = -inputW - 1; + ossim_int32 leftKernelStart = -1; + ossim_int32 llKernelStart = inputW - 1; + + const T* ulKernelStartBuf = NULL; + const T* leftKernelStartBuf = NULL; + const T* llKernelStartBuf = NULL; + + for(ossim_int32 band = 0; band < numberOfBands; ++band) + { + const T* inputBuf = static_cast<const T*>(inputData->getBuf(band)) + + startInputOffset; + T* outputBuf = static_cast<T*>(outputData->getBuf(band)); + T maxPix = static_cast<T>(inputData->getMaxPix(band)); + T minPix = static_cast<T>(inputData->getMinPix(band)); + T nullPix = static_cast<T>(inputData->getNullPix(band)); + + if(inputBuf&&outputBuf) + { + for(ossim_int32 row = 0; row < outputW; ++row) + { + ossim_int32 rowOffset = inputW*row; + ulKernelStartBuf = inputBuf + (rowOffset + ulKernelStart); + leftKernelStartBuf = inputBuf + (rowOffset + leftKernelStart); + llKernelStartBuf = inputBuf + (rowOffset + llKernelStart); + for(ossim_int32 col = 0; col < outputH; ++col) + { + sum = -1.0*(double)ulKernelStartBuf[0] + -2.0*(double)ulKernelStartBuf[1] + -1.0*(double)ulKernelStartBuf[2] + + -2.0*(double)leftKernelStartBuf[0] + 16.0*(double)leftKernelStartBuf[1] + -2.0*(double)leftKernelStartBuf[2] + + -1.0*(double)llKernelStartBuf[0] + -2.0*(double)llKernelStartBuf[1] + -1.0*(double)llKernelStartBuf[2]; + sum /= 4.0; + + if(sum > maxPix) + { + *outputBuf = maxPix; + } + else if((sum < minPix) || (sum == nullPix)) + { + *outputBuf = minPix; + } + else + { + *outputBuf = static_cast<T>(sum); + } + + ++ulKernelStartBuf + ; + ++leftKernelStartBuf; + ++llKernelStartBuf; + ++outputBuf; + } + } + } + } +} + +void ossimImageSharpenFilter::initialize() +{ + // Hmmm... (drb) +} + +void ossimImageSharpenFilter::allocate() +{ + theTile = NULL; + if(theInputConnection) + { + ossimImageDataFactory* idf = ossimImageDataFactory::instance(); + theTile = idf->create(this, this); + theTile->initialize(); + } +} + +ossimString ossimImageSharpenFilter::getShortName() const +{ + return ossimString("Sharpen"); +} + +ossimString ossimImageSharpenFilter::getLongName() const +{ + return ossimString("Sharpens the input input"); +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageSharpenFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageSharpenFilter.h new file mode 100644 index 0000000000..185b08a14b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageSharpenFilter.h @@ -0,0 +1,60 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimImageSharpenFilter.h,v 1.6 2005/02/11 15:07:33 dburken Exp $ +#ifndef ossimImageSharpenFilter_HEADER +#define ossimImageSharpenFilter_HEADER +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +class OSSIMDLLEXPORT ossimImageSharpenFilter : public ossimImageSourceFilter +{ +public: + ossimImageSharpenFilter(ossimObject* owner=NULL); + virtual ~ossimImageSharpenFilter(); + + virtual ossimString getShortName()const; + virtual ossimString getLongName()const; + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + + virtual void initialize(); + +protected: + + /** + * Called on first getTile, will initialize all data needed. + */ + virtual void allocate(); + + ossimRefPtr<ossimImageData> theTile; + + /*! + * Convolve full means that the input data is full and has + * no null data. We don't have to compare for nulls here + */ + template<class T> + void sharpenFull(T, + const ossimRefPtr<ossimImageData>& inputData, + ossimRefPtr<ossimImageData>& outputData); + + /*! + * Convolve partial means that the input data is has some + * null data. We will have to compare nulls + */ + template<class T> + void sharpenPartial(T, + const ossimRefPtr<ossimImageData>& inputData, + ossimRefPtr<ossimImageData>& outputData); + +TYPE_DATA +}; + +#endif /* #ifndef ossimImageSharpenFilter_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageSourceFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageSourceFilter.cpp new file mode 100644 index 0000000000..7e9c1326e8 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageSourceFilter.cpp @@ -0,0 +1,340 @@ + +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +//******************************************************************* +// $Id: ossimImageSourceFilter.cpp,v 1.49 2005/09/15 12:28:44 gpotts Exp $ + +#include <imaging/tile_sources/ossimImageSourceFilter.h> +#include <base/common/ossimTrace.h> +#include <base/property/ossimProperty.h> + +static ossimTrace traceDebug("ossimImageSourceFilter:degug"); + +RTTI_DEF2(ossimImageSourceFilter, "ossimImageSourceFilter", ossimImageSource, ossimConnectableObjectListener) + +ossimImageSourceFilter::ossimImageSourceFilter(ossimObject* owner) + : ossimImageSource(owner, + 1, // number of inputs + 0, // number of outputs + true, // input's fixed + false), // outputs ar not fixed + theInputConnection(NULL) +{ + addListener((ossimConnectableObjectListener*)this); +} + +ossimImageSourceFilter::ossimImageSourceFilter(ossimImageSource* inputSource) + : ossimImageSource(NULL, + 1, + 0, + true, + false), + theInputConnection(inputSource) +{ + if(inputSource) + { + connectMyInputTo(0, inputSource); + } + addListener((ossimConnectableObjectListener*)this); +} + +ossimImageSourceFilter::ossimImageSourceFilter(ossimObject* owner, + ossimImageSource* inputSource) + : ossimImageSource(owner, + 1, + 0, + true, + false), + theInputConnection(inputSource) +{ + if(inputSource) + { + theInputObjectList[0] = inputSource; + inputSource->connectMyOutputTo(this, false); + } + addListener((ossimConnectableObjectListener*)this); +} + + +ossimImageSourceFilter::~ossimImageSourceFilter() +{ + removeListener((ossimConnectableObjectListener*)this); + theInputConnection = NULL; +} + +ossimRefPtr<ossimImageData> ossimImageSourceFilter::getTile( + const ossimIrect& rect, + ossim_uint32 resLevel) +{ + if(theInputConnection) + { + return theInputConnection->getTile(rect, resLevel); + } + + return ossimRefPtr<ossimImageData>(NULL); +} + +ossimIrect ossimImageSourceFilter::getBoundingRect(ossim_uint32 resLevel) const +{ + if(theInputConnection) + { + return theInputConnection->getBoundingRect(resLevel); + } + ossimIrect rect; + rect.makeNan(); + + return rect; +} + +void ossimImageSourceFilter::getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result) const +{ + if(theInputConnection) + { + theInputConnection->getDecimationFactor(resLevel, + result); + } + else // Ok assume square and powers of 2 + { + double dec = 1.0/pow((double)2.0,(double)resLevel); + result.x = dec; + result.y = dec; + } +} + +void ossimImageSourceFilter::getDecimationFactors(vector<ossimDpt>& decimations) const +{ + if(theInputConnection) + { + theInputConnection->getDecimationFactors(decimations); + } +} + +ossim_uint32 ossimImageSourceFilter::getNumberOfDecimationLevels()const +{ + if(theInputConnection) + { + return theInputConnection->getNumberOfDecimationLevels(); + } + + return 0; +} + +ossim_uint32 ossimImageSourceFilter::getNumberOfInputBands()const +{ + if(theInputConnection) + { + return theInputConnection->getNumberOfOutputBands(); + } + + return 0; +} + +ossimScalarType ossimImageSourceFilter::getOutputScalarType() const +{ + if(theInputConnection) + { + return theInputConnection->getOutputScalarType(); + } + + return OSSIM_SCALAR_UNKNOWN; +} + +void ossimImageSourceFilter::getValidImageVertices(vector<ossimIpt>& validVertices, + ossimVertexOrdering ordering, + ossim_uint32 resLevel)const +{ + if(theInputConnection) + { + theInputConnection->getValidImageVertices(validVertices, ordering, resLevel); + } +} + +ossim_uint32 ossimImageSourceFilter::getTileWidth() const +{ + if(theInputConnection) + { + return theInputConnection->getTileWidth(); + } + + return 0; +} + +ossim_uint32 ossimImageSourceFilter::getTileHeight() const +{ + if(theInputConnection) + { + return theInputConnection->getTileHeight(); + } + + return 0; +} + +void ossimImageSourceFilter::initialize() +{ + theInputConnection = PTR_CAST(ossimImageSourceInterface, getInput(0)); +} + +bool ossimImageSourceFilter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + bool result = ossimImageSource::loadState(kwl, prefix); + + // make sure we have 1 input. + setNumberOfInputs(1); + + // we will fix the input + if(!theInputListIsFixedFlag) + { + theInputListIsFixedFlag = true; + } + + return result; +} + +bool ossimImageSourceFilter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + return ossimImageSource::saveState(kwl, prefix); +} + + +bool ossimImageSourceFilter::canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const +{ + + return ((PTR_CAST(ossimImageSourceInterface, object)||!object) && ( inputIndex == 0 ) ); +} + +void ossimImageSourceFilter::connectInputEvent(ossimConnectionEvent& event) +{ + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimImageSourceFilter::connectInputEvent: "; + + if(getInput()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "to" << getInput()->getClassName() << std::endl; + } + else + { + ossimNotify(ossimNotifyLevel_DEBUG) << "to NULL" << std::endl; + } + } + theInputConnection = PTR_CAST(ossimImageSourceInterface, getInput(0)); + initialize(); + if(traceDebug()) + { + if(theInputConnection) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "theInputConnection was set to " << getInput()->getClassName() << std::endl; + } + else + { + ossimNotify(ossimNotifyLevel_DEBUG) << "theInputConnection was set to NULL" << std::endl; + } + ossimNotify(ossimNotifyLevel_DEBUG) << "Leaving ossimImageSourceFilter::connectInput" << std::endl; + } +} +void ossimImageSourceFilter::disconnectInputEvent(ossimConnectionEvent& event) +{ + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimImageSourceFilter::disconnectInputEvent" << std::endl; + } + theInputConnection = PTR_CAST(ossimImageSourceInterface, getInput(0)); + initialize(); + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "Leaving ossimImageSourceFilter::disconnectInput" << std::endl; + } +} +void ossimImageSourceFilter::propertyEvent(ossimPropertyEvent& event) +{ + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimImageSourceFilter::propertyEvent DEBUG: Entering..." << std::endl; + } + initialize(); + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimImageSourceFilter::propertyEvent DEBUG: Leaving..." << std::endl; + } +} + +void ossimImageSourceFilter::refreshEvent(ossimRefreshEvent& event) +{ + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimImageSourceFilter::refreshEvent " << std::endl; + } + initialize(); + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimImageSourceFilter::refreshEvent " << std::endl; + } +} + +double ossimImageSourceFilter::getNullPixelValue(ossim_uint32 band)const +{ + if(theInputConnection) + { + return theInputConnection->getNullPixelValue(band); + } + return ossimImageSource::getNullPixelValue(band); +} + +double ossimImageSourceFilter::getMinPixelValue(ossim_uint32 band)const +{ + if(theInputConnection) + { + return theInputConnection->getMinPixelValue(band); + } + return ossimImageSource::getMinPixelValue(band); +} + +double ossimImageSourceFilter::getMaxPixelValue(ossim_uint32 band)const +{ + if(theInputConnection) + { + return theInputConnection->getMaxPixelValue(band); + } + return ossimImageSource::getMaxPixelValue(band); +} + +void ossimImageSourceFilter::getOutputBandList(std::vector<ossim_uint32>& bandList) const +{ + if(theInputConnection) + { + return theInputConnection->getOutputBandList(bandList); + } + + return ossimImageSource::getOutputBandList(bandList); +} + +void ossimImageSourceFilter::setProperty(ossimRefPtr<ossimProperty> property) +{ + ossimImageSource::setProperty(property); +} + +ossimRefPtr<ossimProperty> ossimImageSourceFilter::getProperty(const ossimString& name)const +{ + return ossimImageSource::getProperty(name); + +} + +void ossimImageSourceFilter::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + ossimImageSource::getPropertyNames(propertyNames); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageSourceFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageSourceFilter.h new file mode 100644 index 0000000000..04e1900c38 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageSourceFilter.h @@ -0,0 +1,115 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +//******************************************************************* +// $Id: ossimImageSourceFilter.h,v 1.49 2005/09/15 12:28:44 gpotts Exp $ +#ifndef ossimImageSourceFilter_HEADER +#define ossimImageSourceFilter_HEADER +#include <imaging/ossimImageSource.h> +#include <base/common/events/ossimConnectableObjectListener.h> +#include <base/common/events/ossimConnectionEvent.h> + +class OSSIMDLLEXPORT ossimImageSourceFilter : public ossimImageSource, + public ossimConnectableObjectListener +{ +public: + ossimImageSourceFilter(ossimObject* owner=NULL); + ossimImageSourceFilter(ossimImageSource* inputSource); + ossimImageSourceFilter(ossimObject* owner, + ossimImageSource* inputSource); + virtual ~ossimImageSourceFilter(); + + virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0)const; + virtual void getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result)const; + virtual void getDecimationFactors(vector<ossimDpt>& decimations)const; + virtual ossim_uint32 getNumberOfDecimationLevels()const; + + /*! + * Returns the input connection's output band list. + * If not connected calls ossimImageSource::getOutputBandList. + */ + virtual void getOutputBandList(std::vector<ossim_uint32>& bandList) const; + + /*! + * Returns the number of bands available from the input. + */ + virtual ossim_uint32 getNumberOfInputBands()const; + + virtual ossimScalarType getOutputScalarType() const; + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect, + ossim_uint32 resLevel=0); + + /*! + * ordering specifies how the vertices should be arranged. + * valid image vertices is basically the tightly fit convex hull + * of the image. Usually an image has NULL values and are + * internally not upright rectangular. This can cause + * problems some spatial filters. + * + * The default implementation is to return the bounding rect. + */ + virtual void getValidImageVertices(vector<ossimIpt>& validVertices, + ossimVertexOrdering ordering=OSSIM_CLOCKWISE_ORDER, + ossim_uint32 resLevel=0)const; + + virtual ossim_uint32 getTileWidth() const; + + virtual ossim_uint32 getTileHeight() const; + + virtual void initialize(); + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * getNullPixelValue + * Returns the null pixel value of input connection if connected. + * Returns OSSIM_DBL_NAN if not connected. + */ + virtual double getNullPixelValue(ossim_uint32 band=0)const; + + /*! + * getMinPixelValue + * Returns the null pixel value of input connection if connected. + * Returns OSSIM_DBL_NAN if not connected. + */ + virtual double getMinPixelValue(ossim_uint32 band=0)const; + + /*! + * getMaxPixelValue + * Returns the null pixel value of input connection if connected. + * Returns OSSIM_DBL_NAN if not connected. + */ + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + + bool canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const; + virtual void connectInputEvent(ossimConnectionEvent& event); + virtual void disconnectInputEvent(ossimConnectionEvent& event); + virtual void propertyEvent(ossimPropertyEvent& event); + virtual void refreshEvent(ossimRefreshEvent& event); + + + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + +protected: + ossimImageSourceInterface* theInputConnection; +TYPE_DATA +}; + +#endif /* #ifndef ossimImageSourceFilter_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageSourceHistogramFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageSourceHistogramFilter.cpp new file mode 100644 index 0000000000..c374f5c36b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageSourceHistogramFilter.cpp @@ -0,0 +1,238 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimImageSourceHistogramFilter.cpp,v 1.12 2005/08/31 15:47:42 gpotts Exp $ +#include "ossimImageSourceHistogramFilter.h" +#include "base/common/ossimHistogramSource.h" +#include "base/data_types/ossimMultiResLevelHistogram.h" +#include "base/data_types/ossimMultiBandHistogram.h" +#include "base/data_types/ossimHistogram.h" +#include "base/common/ossimCommon.h" +#include "imaging/ossimImageData.h" +#include "base/data_types/ossimKeyword.h" +#include "base/data_types/ossimKeywordlist.h" + +static const ossimKeyword PROPRIETARY_FILENAME_KW("proprietary_filename", + "imports a proprietary file"); + +static const ossimKeyword HISTOGRAM_FILENAME_KW("histogram_filename", + "read an OSSIM histogram file"); + + +RTTI_DEF1(ossimImageSourceHistogramFilter, "ossimImageSourceHistogramFilter", ossimImageSourceFilter) + +ossimImageSourceHistogramFilter::ossimImageSourceHistogramFilter() + :ossimImageSourceFilter(), + theCurrentResLevel(0), + theHistogram(NULL), + theFilename("") +{ + setNumberOfInputs(2); + theInputListIsFixedFlag = true; +} + +ossimImageSourceHistogramFilter::ossimImageSourceHistogramFilter(ossimImageSource* inputSource, + ossimMultiResLevelHistogram* histogram) + : ossimImageSourceFilter(inputSource), + theCurrentResLevel(0), + theHistogram(histogram), + theFilename("") +{ + setNumberOfInputs(2); + theInputListIsFixedFlag = true; +} + +ossimImageSourceHistogramFilter::~ossimImageSourceHistogramFilter() +{ + if(theHistogram) + { + delete theHistogram; + theHistogram = NULL; + } +} + + +void ossimImageSourceHistogramFilter::setHistogram(ossimMultiResLevelHistogram* histogram) +{ + if(theHistogram&& + theHistogram!=histogram) + { + delete theHistogram; + theHistogram = NULL; + + } + theHistogram = histogram; + + if(theHistogram) + { + theHistogram->setBinCount(0, 0); + } +} + +bool ossimImageSourceHistogramFilter::setHistogram(const ossimFilename& filename) +{ + ossimMultiResLevelHistogram* histogram = new ossimMultiResLevelHistogram; + + bool result = histogram->importHistogram(filename); + + if(result) + { + theFilename = filename; + setHistogram(histogram); + } + else + { + delete histogram; + histogram = 0; + } + + return result; +} + +ossimMultiResLevelHistogram* ossimImageSourceHistogramFilter::getHistogram() +{ + if(!getInput(1)) + { + return theHistogram; + } + else + { + ossimHistogramSource* histoSource = PTR_CAST(ossimHistogramSource, getInput(1)); + if(histoSource) + { + return histoSource->getHistogram(); + } + } + + return (ossimMultiResLevelHistogram*)NULL; +} + +const ossimMultiResLevelHistogram* ossimImageSourceHistogramFilter::getHistogram()const +{ + if(!getInput(1)) + { + return theHistogram; + } + else + { + ossimHistogramSource* histoSource = PTR_CAST(ossimHistogramSource, getInput(1)); + if(histoSource) + { + return histoSource->getHistogram(); + } + } + + return (ossimMultiResLevelHistogram*)NULL; +} + +bool ossimImageSourceHistogramFilter::canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const +{ + if(object) + { + if(PTR_CAST(ossimImageSourceInterface, object) && ( inputIndex == 0 )) + { + return true; + } + else if(PTR_CAST(ossimHistogramSource, object) && ( inputIndex == 1 )) + { + return true; + } + } + + return false; +} + +void ossimImageSourceHistogramFilter::connectInputEvent(ossimConnectionEvent& event) +{ + theInputConnection = PTR_CAST(ossimImageSourceInterface, getInput(0)); + if(PTR_CAST(ossimHistogramSource, event.getNewObject())) + { + // only initialize if it's a new object + initialize(); + } +} + +bool ossimImageSourceHistogramFilter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + bool result = ossimImageSourceFilter::saveState(kwl, prefix); + + kwl.add(prefix, + HISTOGRAM_FILENAME_KW, + theFilename, + true); + + return result; +} + +bool ossimImageSourceHistogramFilter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* proprietaryName = kwl.find(prefix, PROPRIETARY_FILENAME_KW); + const char* ossimName = kwl.find(prefix, HISTOGRAM_FILENAME_KW); + bool result = true; + ossimFilename file; + + if(proprietaryName) + { + theFilename = ossimFilename(proprietaryName); + } + else if(ossimName) + { + if(!theHistogram) + { + theHistogram = new ossimMultiResLevelHistogram; + } + theFilename = ossimFilename(ossimName); + + } + + if(theFilename.exists()&&(theFilename!="")) + { + if(!theHistogram) + { + theHistogram = new ossimMultiResLevelHistogram; + } + result = theHistogram->importHistogram(theFilename); + } + if(theHistogram) + { + theHistogram->setBinCount(0, 0); + } + + result = ossimImageSourceFilter::loadState(kwl, prefix); + + setNumberOfInputs(2); + theInputListIsFixedFlag = true; + + return result; +} + +std::ostream& ossimImageSourceHistogramFilter::print(std::ostream& out) const +{ + + out << "ossimImageSourceHistogramFilter::print:\n" + << "theFilename: " << endl; + + return ossimImageSourceFilter::print(out); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageSourceHistogramFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageSourceHistogramFilter.h new file mode 100644 index 0000000000..27f24fee29 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageSourceHistogramFilter.h @@ -0,0 +1,65 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimImageSourceHistogramFilter.h,v 1.7 2004/05/19 17:53:29 dburken Exp $ +#ifndef ossimImageSourceHistogramFilter_HEADER +#define ossimImageSourceHistogramFilter_HEADER +#include <imaging/tile_sources/ossimImageSourceFilter.h> +#include <base/data_types/ossimFilename.h> +class ossimMultiResLevelHistogram; + +class OSSIMDLLEXPORT ossimImageSourceHistogramFilter : public ossimImageSourceFilter +{ +public: + ossimImageSourceHistogramFilter(); + ossimImageSourceHistogramFilter(ossimImageSource* inputSource, + ossimMultiResLevelHistogram* histogram); + virtual ~ossimImageSourceHistogramFilter(); + virtual void setHistogram(ossimMultiResLevelHistogram* histogram); + virtual bool setHistogram(const ossimFilename& filename); + virtual const ossimFilename& getHistogramFilename()const; + virtual ossimMultiResLevelHistogram* getHistogram(); + virtual const ossimMultiResLevelHistogram* getHistogram()const; + + bool canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const; + + virtual void connectInputEvent(ossimConnectionEvent& event); + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix = NULL); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix = NULL)const; + + virtual std::ostream& print(std::ostream& out) const; + +protected: + long theCurrentResLevel; + +private: + ossimMultiResLevelHistogram* theHistogram; + ossimFilename theFilename; + +TYPE_DATA +}; + +#endif /* #ifndef ossimImageSourceHistogramFilter_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageToPlaneNormalFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageToPlaneNormalFilter.cpp new file mode 100644 index 0000000000..e430e8d382 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageToPlaneNormalFilter.cpp @@ -0,0 +1,432 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimImageToPlaneNormalFilter.cpp,v 1.9 2005/05/09 12:39:40 dburken Exp $ +#include <imaging/tile_sources/ossimImageToPlaneNormalFilter.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <projections/ossimProjection.h> +#include <base/common/ossimKeywordNames.h> + +static const char* SMOOTHNESS_FACTOR_KW="smoothness_factor"; + +RTTI_DEF1(ossimImageToPlaneNormalFilter, "ossimImageToPlaneNormalFilter", ossimImageSourceFilter); + +ossimImageToPlaneNormalFilter::ossimImageToPlaneNormalFilter() + :ossimImageSourceFilter(), + theTile(NULL), + theBlankTile(NULL), + theTrackScaleFlag(true), + theXScale(1.0), + theYScale(1.0), + theSmoothnessFactor(1.0) +{ +} + +ossimImageToPlaneNormalFilter::ossimImageToPlaneNormalFilter(ossimImageSource* inputSource) + :ossimImageSourceFilter(inputSource), + theTile(NULL), + theBlankTile(NULL), + theTrackScaleFlag(true), + theXScale(1.0), + theYScale(1.0), + theSmoothnessFactor(1.0) +{ +} + +ossimRefPtr<ossimImageData> ossimImageToPlaneNormalFilter::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + + if(!isSourceEnabled()||!theInputConnection) + { + return ossimImageSourceFilter::getTile(tileRect, resLevel); + } + + if(!theTile.valid()) + { + initialize(); + } + + if(!theTile.valid()) + { + return ossimImageSourceFilter::getTile(tileRect, resLevel); + } + + theTile->setImageRectangle(tileRect); + theBlankTile->setImageRectangle(tileRect); + + ossimIrect requestRect(tileRect.ul().x - 1, + tileRect.ul().y - 1, + tileRect.lr().x + 1, + tileRect.lr().y + 1); + ossimRefPtr<ossimImageData> input = + theInputConnection->getTile(requestRect, resLevel); + + if(!input||(input->getDataObjectStatus()==OSSIM_EMPTY)||!input->getBuf()) + { + return theBlankTile; + } + + double oldScaleX = theXScale; + double oldScaleY = theYScale; + + if(resLevel > 0) + { + ossimDpt scaleFactor; + theInputConnection->getDecimationFactor(resLevel, scaleFactor); + + if(!scaleFactor.hasNans()) + { + theXScale /= scaleFactor.x; + theYScale /= scaleFactor.y; + } + } + + computeNormals(input, + theTile); + + theXScale = oldScaleX; + theYScale = oldScaleY; + + theTile->validate(); + + return theTile; +} + + +void ossimImageToPlaneNormalFilter::initialize() +{ + if(theInputConnection) + { + theTile = ossimImageDataFactory::instance()->create(this, this); + theBlankTile = (ossimImageData*)(theTile->dup()); + theTile->initialize(); + + + if(theTrackScaleFlag) + { + ossimKeywordlist kwl; + theInputConnection->getImageGeometry(kwl); + + ossimProjection* proj = ossimProjectionFactoryRegistry::instance()-> + createProjection(kwl); + + if(proj) + { + ossimDpt pt = proj->getMetersPerPixel(); + + if(!pt.hasNans()) + { + theXScale = pt.x; + theYScale = pt.y; + } + } + } + } +} + +void ossimImageToPlaneNormalFilter::computeNormals( + ossimRefPtr<ossimImageData>& inputTile, + ossimRefPtr<ossimImageData>& outputTile) +{ + switch(inputTile->getScalarType()) + { + case OSSIM_SSHORT16: + { + computeNormalsTemplate((ossim_sint16)0, + inputTile, + outputTile); + break; + } + case OSSIM_UCHAR: + { + computeNormalsTemplate((ossim_uint8)0, + inputTile, + outputTile); + break; + } + case OSSIM_USHORT11: + case OSSIM_USHORT16: + { + computeNormalsTemplate((ossim_uint16)0, + inputTile, + outputTile); + break; + } + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_DOUBLE: + { + computeNormalsTemplate((ossim_float64)0, + inputTile, + outputTile); + break; + } + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT: + { + computeNormalsTemplate((ossim_float32)0, + inputTile, + outputTile); + break; + } + default: + break; + } +} + +template <class T> void ossimImageToPlaneNormalFilter::computeNormalsTemplate( + T inputScalarTypeDummy, + ossimRefPtr<ossimImageData>& inputTile, + ossimRefPtr<ossimImageData>& outputTile) +{ + T np = (T)inputTile->getNullPix(0); + double outNp1 = outputTile->getNullPix(0); + double outNp2 = outputTile->getNullPix(1); + double outNp3 = outputTile->getNullPix(2); + + double* outX = (double*)outputTile->getBuf(0); + double* outY = (double*)outputTile->getBuf(1); + double* outZ = (double*)outputTile->getBuf(2); + ossim_int32 y = 0; + ossim_int32 x = 0; + ossim_int32 iw = inputTile->getWidth(); + ossim_int32 ow = outputTile->getWidth(); + ossim_int32 oh = outputTile->getHeight(); + T* row1 = (T*)inputTile->getBuf(); + T* row2 = row1+iw; + T* row3 = row2+iw; + ossimColumnVector3d pX; + ossimColumnVector3d pY; + ossimColumnVector3d leftX; + ossimColumnVector3d rightX; + ossimColumnVector3d topY; + ossimColumnVector3d bottomY; + + ossimColumnVector3d normal; + + + for(y = 0; y < oh; ++y) + { + for(x = 0; x < ow; ++x) + { + if((row1[0] == np)|| + (row1[1] == np)|| + (row1[2] == np)|| + (row2[0] == np)|| + (row2[1] == np)|| + (row2[2] == np)|| + (row3[0] == np)|| + (row3[1] == np)|| + (row3[2] == np)) + { + *outX = outNp1; + *outY = outNp2; + *outZ = outNp3; + } + else + { +// dhX = ((double)row1[2] - (double)row1[0])+ +// ((double)row2[2] - (double)row2[0])+ +// ((double)row3[2] - (double)row3[0]); + +// dhY = ((double)row1[0] - (double)row3[0])+ +// ((double)row1[1] - (double)row3[1])+ +// ((double)row1[2] - (double)row3[2]); + +// dhX = (-(double)row1[2] + (double)row1[0])+ +// (-(double)row2[2] + (double)row2[0])+ +// (-(double)row3[2] + (double)row3[0]); + +// dhY = (-(double)row1[0] + (double)row3[0])+ +// (-(double)row1[1] + (double)row3[1])+ +// (-(double)row1[2] + (double)row3[2]); + + leftX[0] = -theXScale*theSmoothnessFactor; + leftX[1] = 0.0; + leftX[2] = ((double)row1[0] + (double)row2[0]+ (double)row3[0])/3.0; + + rightX[0] = theXScale*theSmoothnessFactor; + rightX[1] = 0.0; + rightX[2] = ((double)row1[2] + (double)row2[2]+ (double)row3[2])/3.0; + + topY[0] = 0.0; + topY[1] = theYScale*theSmoothnessFactor; + topY[2] = ((double)row1[0] + (double)row1[1] + (double)row1[2])/3.0; + + bottomY[0] = 0.0; + bottomY[1] = -theYScale*theSmoothnessFactor; + bottomY[2] = ((double)row3[0] + (double)row3[1] + (double)row3[2])/3.0; + + pX = (rightX - leftX).unit(); + pY = (topY - bottomY).unit(); +// pX[0] = theXScale*theSmoothnessFactor; +// pX[1] = 0.0; +// pX[2] = dhX; + +// pY[0] = 0.0; +// pY[1] = theYScale*theSmoothnessFactor; +// pY[2] = dhY; + +// pX = pX.unit(); +// pY = pY.unit(); + normal = pX.cross(pY).unit(); + + normal = normal.unit(); + *outX = normal[0]; + *outY = normal[1]; + *outZ = normal[2]; + } + + ++outX; + ++outZ; + ++outY; + + ++row1; + ++row2; + ++row3; + } + row1+=2; + row2+=2; + row3+=2; + } +} + +bool ossimImageToPlaneNormalFilter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimString scaleX = kwl.find(prefix, ossimKeywordNames::SCALE_PER_PIXEL_X_KW); + ossimString scaleY = kwl.find(prefix, ossimKeywordNames::SCALE_PER_PIXEL_Y_KW); + ossimString trackFlag = kwl.find(prefix, "track_scale_flag"); + ossimString smoothness = kwl.find(prefix, SMOOTHNESS_FACTOR_KW); + + if(scaleX != "") + { + theXScale = scaleX.toDouble(); + } + if(scaleY != "") + { + theYScale = scaleY.toDouble(); + } + if(trackFlag != "") + { + theTrackScaleFlag = trackFlag.toBool(); + } + if(smoothness!="") + { + theSmoothnessFactor = smoothness.toDouble(); + } + + return ossimImageSourceFilter::loadState(kwl, prefix); +} + +bool ossimImageToPlaneNormalFilter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + ossimKeywordNames::SCALE_PER_PIXEL_X_KW, + theXScale, + true); + + kwl.add(prefix, + ossimKeywordNames::SCALE_PER_PIXEL_Y_KW, + theXScale, + true); + + kwl.add(prefix, + "track_scale_flag", + (ossim_uint32)theTrackScaleFlag, + true); + + kwl.add(prefix, + SMOOTHNESS_FACTOR_KW, + theSmoothnessFactor, + true); + + return ossimImageSourceFilter::saveState(kwl, prefix); +} + +double ossimImageToPlaneNormalFilter::getMinPixelValue(ossim_uint32 band)const +{ + if(!isSourceEnabled()) + { + return ossimImageSourceFilter::getMinPixelValue(band); + } + return -1; +} + +double ossimImageToPlaneNormalFilter::getMaxPixelValue(ossim_uint32 band)const +{ + if(!isSourceEnabled()) + { + return ossimImageSourceFilter::getMaxPixelValue(band); + } + return 1.0; +} + +ossimScalarType ossimImageToPlaneNormalFilter::getOutputScalarType() const +{ + if(isSourceEnabled()) + { + return OSSIM_DOUBLE; + } + + return ossimImageSourceFilter::getOutputScalarType(); +} + +ossim_uint32 ossimImageToPlaneNormalFilter::getNumberOfOutputBands() const +{ + if(isSourceEnabled()) + { + return 3; + } + return ossimImageSourceFilter::getNumberOfOutputBands(); +} + +void ossimImageToPlaneNormalFilter::setXScale(const double& scale) +{ + theXScale = scale; +} + +double ossimImageToPlaneNormalFilter::getXScale()const +{ + return theXScale; +} + +double ossimImageToPlaneNormalFilter::getYScale()const +{ + return theYScale; +} + +void ossimImageToPlaneNormalFilter::setYScale(const double& scale) +{ + theYScale = scale; +} + +void ossimImageToPlaneNormalFilter::setTrackScaleFlag(bool flag) +{ + theTrackScaleFlag = flag; +} + +bool ossimImageToPlaneNormalFilter::getTrackScaleFlag()const +{ + return theTrackScaleFlag; +} + +void ossimImageToPlaneNormalFilter::setSmoothnessFactor(double value) +{ + theSmoothnessFactor = value; +} + +double ossimImageToPlaneNormalFilter::getSmoothnessFactor()const +{ + return theSmoothnessFactor; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageToPlaneNormalFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageToPlaneNormalFilter.h new file mode 100644 index 0000000000..d997c6536e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimImageToPlaneNormalFilter.h @@ -0,0 +1,67 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimImageToPlaneNormalFilter.h,v 1.5 2005/02/25 21:20:54 dburken Exp $ +#ifndef ossimImageToPlaneNormalFilter_HEADER +#define ossimImageToPlaneNormalFilter_HEADER +#include "ossimImageSourceFilter.h" + +class OSSIMDLLEXPORT ossimImageToPlaneNormalFilter : public ossimImageSourceFilter +{ +public: + ossimImageToPlaneNormalFilter(); + ossimImageToPlaneNormalFilter(ossimImageSource* inputSource); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + + virtual double getMinPixelValue(ossim_uint32 band=0)const; + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + + virtual ossimScalarType getOutputScalarType() const; + virtual ossim_uint32 getNumberOfOutputBands() const; + + void setXScale(const double& scale); + void setYScale(const double& scale); + + double getXScale()const; + double getYScale()const; + + void setTrackScaleFlag(bool flag); + bool getTrackScaleFlag()const; + + void setSmoothnessFactor(double value); + double getSmoothnessFactor()const; + + bool loadState(const ossimKeywordlist& kwl, + const char* prefix); + bool saveState(ossimKeywordlist& kwl, + const char* prefix)const; + virtual void initialize(); + +protected: + ossimRefPtr<ossimImageData> theTile; + ossimRefPtr<ossimImageData> theBlankTile; + + bool theTrackScaleFlag; + double theXScale; + double theYScale; + double theSmoothnessFactor; + virtual void computeNormals(ossimRefPtr<ossimImageData>& inputTile, + ossimRefPtr<ossimImageData>& outputTile); + + template <class T> + void computeNormalsTemplate(T inputScalarTypeDummy, + ossimRefPtr<ossimImageData>& inputTile, + ossimRefPtr<ossimImageData>& outputTile); +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimIndexToRgbLutFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimIndexToRgbLutFilter.cpp new file mode 100644 index 0000000000..137c425cf0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimIndexToRgbLutFilter.cpp @@ -0,0 +1,626 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimIndexToRgbLutFilter.cpp,v 1.26 2005/08/30 15:08:51 gpotts Exp $ +#include <imaging/tile_sources/ossimIndexToRgbLutFilter.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <base/data_types/color_space/ossimRgbVector.h> +#include <base/common/ossimConstants.h> +#include <base/common/ossimCommon.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/common/ossimTrace.h> +#include <base/property/ossimFilenameProperty.h> +#include <base/property/ossimStringProperty.h> + +static const ossimTrace traceDebug("ossimIndexToRgbLutFilter:debug"); + +RTTI_DEF1(ossimIndexToRgbLutFilter, "ossimIndexToRgbLutFilter", ossimImageSourceFilter); + +static const char* MIN_VALUE_KW = "min_value"; +static const char* MAX_VALUE_KW = "max_value"; +static const char* INTERPOLATION_TYPE_KW = "interpolation_type"; + +ossimIndexToRgbLutFilter::ossimIndexToRgbLutFilter() + :ossimImageSourceFilter(), + theMinValue(OSSIM_DBL_NAN), + theMaxValue(OSSIM_DBL_NAN), + theMinMaxDeltaLength(OSSIM_DBL_NAN), + theMinValueOverride(false), + theMaxValueOverride(false), + theInterpolationType(ossimIndexToRgbLutFilter_NEAREST), + theTile(NULL), + theLutFile("") +{ +} + +ossimIndexToRgbLutFilter::ossimIndexToRgbLutFilter(ossimImageSource* inputSource, + const ossimRgbLutDataObject& lut, + double minValue, + double maxValue, + ossimIndexToRgbLutFilterInterpolationType interpolationType) + :ossimImageSourceFilter(inputSource), + theLut(lut), + theMinValue(minValue), + theMaxValue(maxValue), + theMinValueOverride(false), + theMaxValueOverride(false), + theInterpolationType(interpolationType), + theTile(NULL), + theLutFile("") +{ + if(theMinValue > theMaxValue) + { + double temp = theMinValue; + theMinValue = theMaxValue; + theMaxValue = temp; + } + theMinMaxDeltaLength = theMaxValue - theMinValue; + +} + +ossimIndexToRgbLutFilter::~ossimIndexToRgbLutFilter() +{ +} + +ossimRefPtr<ossimImageData> ossimIndexToRgbLutFilter::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if(!theInputConnection) + { + return ossimRefPtr<ossimImageData>(); + } + ossimRefPtr<ossimImageData> tile = theInputConnection->getTile(tileRect, + resLevel); + if(!tile) + { + return 0; + } + + if(!theTile) + { + allocate(); + if (!theTile) + { + return theTile; + } + } + + theTile->setImageRectangle(tileRect); + + theTile->setDataObjectStatus(OSSIM_FULL); + theTile->makeBlank(); + + if(tile->getBuf()&& + tile->getDataObjectStatus() != OSSIM_EMPTY) + { + return convertInputTile(tile); + } + + return theTile; + +// if ( theTile->getDataObjectStatus() != OSSIM_EMPTY ) +// { +// theTile->makeBlank(); +// } + +} + +ossimRefPtr<ossimImageData> ossimIndexToRgbLutFilter::convertInputTile(const ossimRefPtr<ossimImageData>& tile) +{ + ossim_uint8* outBuf[3]; + outBuf[0] = (ossim_uint8*)(theTile->getBuf(0)); + outBuf[1] = (ossim_uint8*)(theTile->getBuf(1)); + outBuf[2] = (ossim_uint8*)(theTile->getBuf(2)); + long numberOfEntries = (long)theLut.getNumberOfEntries(); + + if(!numberOfEntries) + { + return ossimRefPtr<ossimImageData>(); + } + + long maxLength = tile->getWidth()*tile->getHeight(); + ossimRgbVector color; + + switch(tile->getScalarType()) + { + case OSSIM_SSHORT16: + { + ossim_sint16* buf = (ossim_sint16*)(tile->getBuf()); + + for(long index = 0; index < maxLength; ++index) + { + if(!tile->isNull(index)) + { + double colorIndex; + normalizeValue(*buf, colorIndex); + getColorNormIndex(colorIndex, color); + outBuf[0][index] = color.getR(); + outBuf[1][index] = color.getG(); + outBuf[2][index] = color.getB(); + } + else + { + outBuf[0][index] = 0; + outBuf[1][index] = 0; + outBuf[2][index] = 0; + } + ++buf; + } + break; + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + float* buf = (float*)(tile->getBuf()); + + for(long index = 0; index < maxLength; ++index) + { + if(!tile->isNull(index)) + { + double colorIndex; + normalizeValue(*buf, colorIndex); + getColorNormIndex(colorIndex, color); + outBuf[0][index] = color.getR(); + outBuf[1][index] = color.getG(); + outBuf[2][index] = color.getB(); + } + else + { + outBuf[0][index] = 0; + outBuf[1][index] = 0; + outBuf[2][index] = 0; + } + ++buf; + } + break; + } + case OSSIM_UCHAR: + { + ossim_uint8* buf = (ossim_uint8*)(tile->getBuf()); + + for(long index = 0; index < maxLength; ++index) + { + if(!tile->isNull(index)) + { + double colorIndex; + normalizeValue(*buf, colorIndex); + getColorNormIndex(colorIndex, color); + + outBuf[0][index] = color.getR(); + outBuf[1][index] = color.getG(); + outBuf[2][index] = color.getB(); + } + else + { + outBuf[0][index] = 0; + outBuf[1][index] = 0; + outBuf[2][index] = 0; + } + ++buf; + } + break; + } + case OSSIM_USHORT16: + case OSSIM_USHORT11: + { + ossim_uint16* buf = (ossim_uint16*)(tile->getBuf()); + + for(long index = 0; index < maxLength; ++index) + { + if(!tile->isNull(index)) + { + double colorIndex; + normalizeValue(*buf, colorIndex); + getColorNormIndex(colorIndex, color); + outBuf[0][index] = color.getR(); + outBuf[1][index] = color.getG(); + outBuf[2][index] = color.getB(); + } + else + { + outBuf[0][index] = 0; + outBuf[1][index] = 0; + outBuf[2][index] = 0; + } + ++buf; + } + break; + } + default: + break; + } + theTile->validate(); + return theTile; +} + +void ossimIndexToRgbLutFilter::allocate() +{ + if(!theInputConnection) return; + + theTile = ossimImageDataFactory::instance()->create(this, 3, this); + if(theTile.valid()) + { + theTile->initialize(); + } +} + +void ossimIndexToRgbLutFilter::initialize() +{ + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimIndexToRgbLutFilter::initialize() DEBUG: Entered .... " << std::endl; + } + ossimImageSourceFilter::initialize(); + + theTile = NULL; + if(!theInputConnection) + { + return; + } + if(!theMinValueOverride) + { + theMinValue = theInputConnection->getMinPixelValue(0); + } + if(!theMaxValueOverride) + { + theMaxValue = theInputConnection->getMaxPixelValue(0); + } + if(theMinValue > theMaxValue) + { + swap(theMinValue, theMaxValue); + } + theMinMaxDeltaLength = theMaxValue - theMinValue; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "theInputConnection Pointer = " << theInputConnection + << "\nossimIndexToRgbLutFilter::initialize() DEBUG: Leaving .... " + << std::endl; + } + +} + +void ossimIndexToRgbLutFilter::setProperty(ossimRefPtr<ossimProperty> property) +{ + if(property.valid()) + { + ossimString value = property->valueToString(); + value = value.trim(); + + if(property->getName() == "Lut file") + { + setLut(ossimFilename(property->valueToString())); + } + else if(property->getName() == "Interpolation type") + { + value=value.downcase(); + if(value == "linear") + { + setInterpolationType(ossimIndexToRgbLutFilter_LINEAR); + } + else + { + setInterpolationType(ossimIndexToRgbLutFilter_NEAREST); + } + } + else + { + ossimImageSourceFilter::setProperty(property); + } + } +} + +ossimRefPtr<ossimProperty> ossimIndexToRgbLutFilter::getProperty(const ossimString& name)const +{ + if(name == "Lut file") + { + ossimFilenameProperty* filenameProperty = new ossimFilenameProperty(name, theLutFile); + if(filenameProperty) + { + filenameProperty->setIoType(ossimFilenameProperty::ossimFilenamePropertyIoType_INPUT); + filenameProperty->clearChangeType(); + filenameProperty->setCacheRefreshBit(); + filenameProperty->setReadOnlyFlag(false); + + return filenameProperty; + } + } + else if(name == "Interpolation type") + { + std::vector<ossimString> options; + options.push_back("nearest"); + options.push_back("linear"); + ossimString value = "nearest"; + if(theInterpolationType == ossimIndexToRgbLutFilter_LINEAR) + { + value = "linear"; + } + + ossimStringProperty* stringProperty = new ossimStringProperty(name, + value, + false, + options); + + stringProperty->clearChangeType(); + stringProperty->setCacheRefreshBit(); + stringProperty->setReadOnlyFlag(false); + + return stringProperty; + } + + return ossimImageSourceFilter::getProperty(name); +} + +void ossimIndexToRgbLutFilter::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + ossimImageSourceFilter::getPropertyNames(propertyNames); + propertyNames.push_back("Lut file"); + propertyNames.push_back("Interpolation type"); +} + +void ossimIndexToRgbLutFilter::normalizeValue(double value, + double& normalizedValue) +{ + // map to normalized elevation within our range of values + normalizedValue = (value - theMinValue)/theMinMaxDeltaLength; + if(normalizedValue > 1) normalizedValue = 1; + if(normalizedValue < 0) normalizedValue = 0; +} + +void ossimIndexToRgbLutFilter::getColorNormIndex(double index, + ossimRgbVector& result) +{ + long numberOfEntries = theLut.getNumberOfEntries(); + index*=numberOfEntries; + if(theInterpolationType == ossimIndexToRgbLutFilter_LINEAR) + { + int lutIndex = (long)index; + + double lutT = index - lutIndex; + + int lutIndex2 = lutIndex+1; + if(lutIndex2>=numberOfEntries) lutIndex2 = numberOfEntries-1; + + result = theLut[lutIndex]*(1.0-lutT) + + theLut[lutIndex2]*(lutT); + + } + else + { + int i = irint(index); + i = i < 0?0:i; + i = i >numberOfEntries?numberOfEntries:i; + result = theLut[i]; + } +} + +void ossimIndexToRgbLutFilter::getColor(double index, + ossimRgbVector& result) +{ + if(theInterpolationType == ossimIndexToRgbLutFilter_LINEAR) + { + long numberOfEntries = theLut.getNumberOfEntries(); + int lutIndex = (int)index; + + double lutT = index - lutIndex; + int lutIndex2 = lutIndex+1; + + if(lutIndex2>=numberOfEntries) lutIndex2 = numberOfEntries-1; + + result = theLut[lutIndex]*(1.0-lutT) + + theLut[lutIndex2]*(lutT); + } + else + { + result = theLut[irint(index)]; + } +} + +bool ossimIndexToRgbLutFilter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + MIN_VALUE_KW, + theMinValue, + true); + + kwl.add(prefix, + MAX_VALUE_KW, + theMaxValue, + true); + + ossimString interpolationType = "nearest"; + switch(theInterpolationType) + { + case ossimIndexToRgbLutFilter_LINEAR: + { + interpolationType = "linear"; + } + default: + break; + } + kwl.add(prefix, + INTERPOLATION_TYPE_KW, + interpolationType.c_str(), + true); + + ossimString newPrefix = ossimString(prefix)+ "lut."; + if(theLutFile != "") + { + kwl.add(newPrefix.c_str(), "lut_file", theLutFile.c_str(), true); + ossimKeywordlist kwl2; + theLut.saveState(kwl2); + } + else + { + theLut.saveState(kwl, newPrefix.c_str()); + } + + return ossimImageSourceFilter::saveState(kwl, prefix); +} + +bool ossimIndexToRgbLutFilter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* minValue = kwl.find(prefix, + MIN_VALUE_KW); + const char* maxValue = kwl.find(prefix, + MAX_VALUE_KW); + + const char* interpolationType = kwl.find(prefix, + INTERPOLATION_TYPE_KW); + + theInterpolationType = ossimIndexToRgbLutFilter_NEAREST; + if(interpolationType) + { + ossimString interp = ossimString(interpolationType).trim().upcase(); + if(interp == "LINEAR") + { + theInterpolationType = ossimIndexToRgbLutFilter_LINEAR; + } + } + if(minValue) + { + theMinValue = ossimString(minValue).toDouble(); + theMinValueOverride = true; + + } + else + { + theMinValueOverride = false; + } + + if(maxValue) + { + theMaxValue = ossimString(maxValue).toDouble(); + theMaxValueOverride = true; + } + else + { + theMaxValueOverride = false; + } + if((theMinValue != OSSIM_DBL_NAN) && + (theMaxValue != OSSIM_DBL_NAN)) + { + if(theMinValue > theMaxValue) + { + double temp = theMinValue; + theMinValue = theMaxValue; + theMaxValue = temp; + } + theMinMaxDeltaLength = theMaxValue - theMinValue; + } + else + { + theMinMaxDeltaLength = OSSIM_DBL_NAN; + } + ossimString newPrefix = ossimString(prefix)+ "lut."; + + const char* file = kwl.find(newPrefix.c_str(), "lut_file"); + if(file) + { + theLutFile = file; + } + else + { + theLutFile = ""; + } + theLut.loadState(kwl, newPrefix.c_str()); + + bool result = ossimImageSourceFilter::loadState(kwl, prefix); + + return result; +} + +ossim_uint32 ossimIndexToRgbLutFilter::getNumberOfOutputBands() const +{ + if(isSourceEnabled()) + { + return 3; + } + return ossimImageSourceFilter::getNumberOfOutputBands(); +} + +ossimScalarType ossimIndexToRgbLutFilter::getOutputScalarType() const +{ + if(isSourceEnabled()) + { + return OSSIM_UCHAR; + } + + return ossimImageSourceFilter::getOutputScalarType(); +} + +void ossimIndexToRgbLutFilter::setLut(ossimRgbLutDataObject& lut) +{ + theLut = lut; +} + +void ossimIndexToRgbLutFilter::setLut(const ossimFilename& file) +{ + theLutFile = file; + if(file.exists()) + { + ossimKeywordlist kwl(file.c_str()); + theLut.loadState(kwl); + } +} + +ossimFilename ossimIndexToRgbLutFilter::getLutFile()const +{ + return theLutFile; +} + +double ossimIndexToRgbLutFilter::getMinValue()const +{ + return theMinValue; +} + +double ossimIndexToRgbLutFilter::getMaxValue()const +{ + return theMaxValue; +} + +void ossimIndexToRgbLutFilter::setMinValue(double value) +{ + theMinValue = value; +} + +void ossimIndexToRgbLutFilter::setMaxValue(double value) +{ + theMaxValue = value; +} + +double ossimIndexToRgbLutFilter::getNullPixelValue()const +{ + return 0.0; +} + +double ossimIndexToRgbLutFilter::getMinPixelValue(ossim_uint32 band)const +{ + return 1.0; +} + +double ossimIndexToRgbLutFilter::getMaxPixelValue(ossim_uint32 band)const +{ + return 255.0; +} + +ossimIndexToRgbLutFilter::ossimIndexToRgbLutFilterInterpolationType ossimIndexToRgbLutFilter::getInterpolationType()const +{ + return theInterpolationType; +} + +void ossimIndexToRgbLutFilter::setInterpolationType(ossimIndexToRgbLutFilterInterpolationType type) +{ + theInterpolationType = type; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimIndexToRgbLutFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimIndexToRgbLutFilter.h new file mode 100644 index 0000000000..6eddc44a5d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimIndexToRgbLutFilter.h @@ -0,0 +1,205 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimIndexToRgbLutFilter.h,v 1.17 2005/02/11 15:07:33 dburken Exp $ +#ifndef ossimIndexToRgbLutFilter_HEADER +#define ossimIndexToRgbLutFilter_HEADER +#include <base/data_types/color_space/ossimRgbVector.h> +#include <base/common/ossimRgbLutDataObject.h> +#include <base/data_types/ossimFilename.h> +#include <imaging/tile_sources/ossimImageSourceFilter.h> +#include <vector> + +class ossimImageData; + +/** + * The output is an 8-bit pseudo color of the input + * data. This class implements a generic way to color code + * any form of input data. It will use theMinValue + * theMaxValue to color code the input data. Note + * this class only operates on one input band since + * it assumes the input is an index. It also uses + * an ossimRgbLutDataObject that is an array of color + * data or ossimRgbVector data. It will convert + * the input into normalized form and then map + * it uniformly to the color in the RGB Lut (Lookup Table). + * <pre> + * + * Note: You can tell this filter if it should use the + * nearest entry for the output color or linearly + * interpolate the entries for smooth coloring. + * + * Example keyword list: + * + * type: ossimIndexToRgbLutFilter + * // if the max_value and min_value is given it will use these for normalizing the + * // input data to be between 0 and 1. If not given it will query the min max + * // from the input + * + * max_value: 2164.000000000000000 + * min_value: -3.000000000000000 + * + * // it owns an ossimRgbLutDataObject and has prefix value lut. + * + * // the value can be nearest or linear. This describes how the + * // color value is computed. If it falls bewteen 2 color values + * // for example, 1.4 it will go to entries 1 and 2 and interpolate + * // if linear is set else it will return the color at entry 1 if + * // nearest is set. + * + * interpolation_type: linear + * + * // the rest of the keywords is the lookup table. + * // NOTE: you do not have to have the same number of entries as you do + * // input range indices. Just know that the lowest value is mapped + * // to 0 and the highest value is mapped to number of entires -1. + * + * If you want to load from a file then just do: + * + * lut.lut_file: <full path to lut file> + * + * If you have the lut table in line then it must look like this: + * + * lut.entry0.b: 204 + * lut.entry0.g: 102 + * lut.entry0.r: 1 + * lut.entry1.b: 255 + * lut.entry1.g: 204 + * lut.entry1.r: 153 + * lut.entry2.b: 204 + * lut.entry2.g: 204 + * lut.entry2.r: 51 + * lut.entry3.b: 255 + * lut.entry3.g: 1 + * lut.entry3.r: 1 + * lut.entry4.b: 204 + * lut.entry4.g: 1 + * lut.entry4.r: 204 + * lut.entry5.b: 204 + * lut.entry5.g: 51 + * lut.entry5.r: 255 + * lut.entry6.b: 51 + * lut.entry6.g: 1 + * lut.entry6.r: 102 + * lut.entry7.b: 255 + * lut.entry7.g: 255 + * lut.entry7.r: 255 + * lut.number_of_entries: 8 + * lut.type: ossimRgbLutDataObject + * + * + * + * </pre> + */ +class ossimIndexToRgbLutFilter : public ossimImageSourceFilter +{ +public: + enum ossimIndexToRgbLutFilterInterpolationType + { + ossimIndexToRgbLutFilter_NEAREST = 0, + ossimIndexToRgbLutFilter_LINEAR = 1 + }; + /** + * Initializes the min value to 0 and the max value to 4000. + */ + ossimIndexToRgbLutFilter(); + ossimIndexToRgbLutFilter(ossimImageSource* inputSource, + const ossimRgbLutDataObject& rgbLut, + double minValue, + double maxValue, + ossimIndexToRgbLutFilterInterpolationType interpolationType); + virtual ~ossimIndexToRgbLutFilter(); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& origin, + ossim_uint32 resLevel=0); + + ossim_uint32 getNumberOfOutputBands() const; + + virtual ossimScalarType getOutputScalarType() const; + + void setLut(ossimRgbLutDataObject& lut); + void setLut(const ossimFilename& file); + + ossimFilename getLutFile()const; + + double getMinValue()const; + double getMaxValue()const; + + void setMinValue(double value); + void setMaxValue(double value); + + virtual double getNullPixelValue()const; + virtual double getMinPixelValue(ossim_uint32 band=0)const; + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + + ossimIndexToRgbLutFilterInterpolationType getInterpolationType()const; + void setInterpolationType(ossimIndexToRgbLutFilterInterpolationType type); + + virtual void initialize(); + + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + + /** + * Saves the state of this object. + * + * Keywords are: min_value + * max_value + * lut.<lut keywords> -> look at the + * ossimRgbLutDataObject for the keywords that + * follow after the "." . + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=NULL)const; + + /** + * Loads the state of this object. + * + * looks for keywords: + * min_value + * max_value + * lut.<lut keywords> -> look at the + * ossimRgbLutDataObject for the keywords that + * follow after the "." . + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=NULL); +protected: + + /** + * Called on first getTile, will initialize all data needed. + */ + void allocate(); + + ossimRgbLutDataObject theLut; + double theMinValue; + double theMaxValue; + double theMinMaxDeltaLength; + bool theMinValueOverride; + bool theMaxValueOverride; + + ossimIndexToRgbLutFilterInterpolationType theInterpolationType; + ossimRefPtr<ossimImageData> theTile; + ossimFilename theLutFile; + + virtual void normalizeValue(double value, + double& normalizedValue); + virtual void getColorNormIndex(double index, ossimRgbVector& result); + virtual void getColor(double index, ossimRgbVector& result); + virtual ossimRefPtr<ossimImageData> convertInputTile(const ossimRefPtr<ossimImageData>& tile); + /** + * Precomputed from the theMaxValue - theMinValue + */ + +TYPE_DATA +}; + +#endif /* #ifndef ossimIndexToRgbLutFilter_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimIntensityAdjustmentFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimIntensityAdjustmentFilter.cpp new file mode 100644 index 0000000000..9232895cb1 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimIntensityAdjustmentFilter.cpp @@ -0,0 +1,287 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimIntensityAdjustmentFilter.cpp,v 1.5 2005/02/11 15:07:33 dburken Exp $ +#include "ossimIntensityAdjustmentFilter.h" +#include "imaging/factory/ossimImageDataFactory.h" +#include "base/data_types/color_space/ossimHsvVector.h" +#include "base/data_types/color_space/ossimRgbVector.h" + +RTTI_DEF1(ossimIntensityAdjustmentFilter, "ossimIntensityAdjustmentFilter", ossimImageSourceFilter); + +ossimIntensityAdjustmentFilter::ossimIntensityAdjustmentFilter() + :ossimImageSourceFilter(), + theMeanIntensityTarget(OSSIM_DBL_NAN), + theNormTile(NULL), + theTile(NULL), + theBlankTile(NULL) +{ + theGridBounds.makeNan(); +} + +ossimIntensityAdjustmentFilter::~ossimIntensityAdjustmentFilter() +{ +} + +ossimRefPtr<ossimImageData> ossimIntensityAdjustmentFilter::getTile( + const ossimIrect& rect, + ossim_uint32 resLevel) +{ + if (!theTile.valid()) + { + allocate(); // first time through. + } + + if(theBlankTile.valid()) + { + theBlankTile->setImageRectangle(rect); + } + if(!theInputConnection) + { + return theBlankTile; + } + ossimRefPtr<ossimImageData> data = + theInputConnection->getTile(rect, resLevel); + + if(!isSourceEnabled()) + { + return data; + } + theTile->setImageRectangle(rect); + theNormTile->setImageRectangle(rect); + loadNormTile(data); + + if(theMeanIntensityTarget == OSSIM_DBL_NAN) + { + theMeanIntensityTarget = theMeanIntensityGrid.meanValue(); + } + + loadNormTile(data); + + if((theNormTile->getDataObjectStatus()!=OSSIM_NULL)&& + (theNormTile->getDataObjectStatus()!=OSSIM_EMPTY)) + { + float* buf[3]; + if(data->getNumberOfBands() == 3) + { + buf[0] = (float*)theNormTile->getBuf(0); + buf[1] = (float*)theNormTile->getBuf(1); + buf[2] = (float*)theNormTile->getBuf(2); + } + else + { + buf[0] = (float*)theNormTile->getBuf(0); + buf[1] = (float*)theNormTile->getBuf(0); + buf[2] = (float*)theNormTile->getBuf(0); + + } + ossim_int32 y = 0; + ossim_int32 x = 0; + ossim_int32 upperY = theNormTile->getHeight(); + ossim_int32 upperX = theNormTile->getWidth(); + ossimIpt origin = rect.ul(); + + for(y = 0; y < upperY; ++y) + { + for(x = 0; x < upperX; ++x) + { + ossimIpt pt = ossimIpt(origin.x + x, + origin.y + y) - theGridBounds.ul(); + + if((buf[0] != 0) && + (buf[1] != 0) && + (buf[2] != 0)) + { + + ossimRgbVector rgb((ossim_uint8)(*(buf[0])*255.0), + (ossim_uint8)(*(buf[1])*255.0), + (ossim_uint8)(*(buf[2])*255.0)); + ossimHsvVector hsv(rgb); + + hsv.setV(matchTargetMean(hsv.getV(), + theMeanIntensityGrid(pt.x, pt.y), + theMeanIntensityTarget, + theNormTile->getMinPix(0), + theNormTile->getMaxPix(0))); + ossimRgbVector result(hsv); + + *buf[0] = result.getR()/255.0; + *buf[1] = result.getG()/255.0; + *buf[2] = result.getB()/255.0; + } + + ++buf[0]; + ++buf[1]; + ++buf[2]; + } + } + } + theTile->copyNormalizedBufferToTile((float*)theNormTile->getBuf()); + theTile->validate(); + + return theTile; +} + +void ossimIntensityAdjustmentFilter::initialize() +{ + ossimImageSourceFilter::initialize(); + + theNormTile = NULL; + theBlankTile = NULL; + + if(theInputConnection) + { + theGridBounds = theInputConnection->getBoundingRect(); + } + else + { + theGridBounds.makeNan(); + } +} + +void ossimIntensityAdjustmentFilter::allocate() +{ + theBlankTile = ossimImageDataFactory::instance()->create(this, this); + theTile = (ossimImageData*)theBlankTile->dup(); + theTile->initialize(); +} + +void ossimIntensityAdjustmentFilter::createAndPopulateGrid(const ossimIpt& spacing, + double targetMean) +{ + if(theInputConnection) + { + ossim_uint32 x = 0; + ossim_uint32 y = 0; + + theGridBounds = theInputConnection->getBoundingRect(); + + ossimDrect rect(0, + 0, + theGridBounds.width()-1, + theGridBounds.height()-1); + + theMeanIntensityGrid = ossimDblGrid(rect, + ossimDpt(spacing), + 0); + + for(y = 0; y <= theGridBounds.height(); y+=spacing.y) + { + for(x = 0; x <= theGridBounds.width(); x+=spacing.x) + { + ossimIpt ul(x - 16, + y - 16); + + ossimIrect sampleRect(ul.x, + ul.y, + ul.x + 31, + ul.y + 31); + ossimRefPtr<ossimImageData> data = theInputConnection->getTile(sampleRect); + double mean = computeMeanIntensity(data); + theMeanIntensityGrid.setNearestNode(ossimDpt(x, y), mean); + } + } +// theMeanIntensityGrid.interpolateNullValuedNodes(); + } + theMeanIntensityTarget = targetMean; +} + +double ossimIntensityAdjustmentFilter::computeMeanIntensity( + ossimRefPtr<ossimImageData>& data) +{ + double result = 0; + double divisor = 0; + + if(data.valid() && + (data->getDataObjectStatus()!=OSSIM_NULL)&& + (data->getDataObjectStatus()!=OSSIM_EMPTY)) + { + loadNormTile(data); + + int i = 0; + int upper = data->getWidth()*data->getHeight(); + float* buf[3]; + if(data->getNumberOfBands() == 3) + { + buf[0] = (float*)theNormTile->getBuf(0); + buf[1] = (float*)theNormTile->getBuf(1); + buf[2] = (float*)theNormTile->getBuf(2); + } + else + { + buf[0] = (float*)theNormTile->getBuf(); + buf[1] = (float*)theNormTile->getBuf(); + buf[2] = (float*)theNormTile->getBuf(); + } + for(i = 0; i < upper; ++i) + { + ossimRgbVector rgb((ossim_uint8)(*(buf[0])*255.0), + (ossim_uint8)(*(buf[1])*255.0), + (ossim_uint8)(*(buf[2])*255.0)); + ossimHsvVector hsv(rgb); + if(hsv.getV() > 0.0) + { + result += hsv.getV(); + divisor += 1.0; + } + ++buf[0]; + ++buf[1]; + ++buf[2]; + } + } + + if(divisor > 0.0) + { + result /= divisor; + } + return result; +} + +void ossimIntensityAdjustmentFilter::loadNormTile(ossimRefPtr<ossimImageData>& data) +{ + if(!theNormTile) + { + theNormTile = ossimImageDataFactory::instance()->create(this, + OSSIM_NORMALIZED_FLOAT, + data->getNumberOfBands(), + data->getWidth(), + data->getHeight()); + theNormTile->initialize(); + } + else + { + theNormTile->setImageRectangle(data->getImageRectangle()); + } + data->copyTileToNormalizedBuffer((float*)theNormTile->getBuf()); + theNormTile->validate(); +} + +double ossimIntensityAdjustmentFilter::matchTargetMean(double inputValue, + double meanValue, + double targetMean, + double minValue, + double maxValue) +{ + // max change + const double delta = targetMean - meanValue; + double weight=0.0; + + // weight max change dependend on proximity to end points + if (inputValue <= meanValue) + { + weight = fabs((inputValue - minValue) / (meanValue - minValue)); + } + else + { + weight = fabs((maxValue - inputValue) / (maxValue - meanValue)); + } + + return (inputValue + (delta * weight)); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimIntensityAdjustmentFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimIntensityAdjustmentFilter.h new file mode 100644 index 0000000000..3401870c00 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimIntensityAdjustmentFilter.h @@ -0,0 +1,74 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimIntensityAdjustmentFilter.h,v 1.3 2005/02/11 15:07:33 dburken Exp $ +#ifndef ossimIntensityAdjustmentFilter_HEADER +#define ossimIntensityAdjustmentFilter_HEADER +#include "ossimImageSourceFilter.h" +#include "base/data_types/ossimDblGrid.h" + +class ossimIntensityAdjustmentFilter : public ossimImageSourceFilter +{ +public: + ossimIntensityAdjustmentFilter(); + virtual ~ossimIntensityAdjustmentFilter(); + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect, + ossim_uint32 resLevel=0); + + const ossimIrect& getGridBounds()const + { + return theGridBounds; + } + virtual void setIntensityGrid(const ossimDblGrid& grid) + { + theMeanIntensityGrid = grid; + } + void setMeanIntensityTarget(double targetMean) + { + theMeanIntensityTarget = targetMean; + } + double getMeanIntensityTarget()const + { + return theMeanIntensityTarget; + } + ossimDblGrid& getMeanIntensityGrid() + { + return theMeanIntensityGrid; + } + const ossimDblGrid& getMeanIntensityGrid()const + { + return theMeanIntensityGrid; + } + void createAndPopulateGrid(const ossimIpt& spacing, double targetMean = .5); + + virtual void initialize(); +protected: + + virtual void allocate(); + + ossimDblGrid theMeanIntensityGrid; + double theMeanIntensityTarget; + ossimRefPtr<ossimImageData> theNormTile; + ossimRefPtr<ossimImageData> theTile; + ossimRefPtr<ossimImageData> theBlankTile; + + ossimIrect theGridBounds; + + double computeMeanIntensity(ossimRefPtr<ossimImageData>& data); + void loadNormTile(ossimRefPtr<ossimImageData>& data); + double matchTargetMean(double inputValue, + double meanValue, + double targetMean, + double minValue, + double maxValue); + +TYPE_DATA +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimJpegYCbCrToRgbSource.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimJpegYCbCrToRgbSource.cpp new file mode 100644 index 0000000000..4d3390ade0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimJpegYCbCrToRgbSource.cpp @@ -0,0 +1,114 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimJpegYCbCrToRgbSource.cpp,v 1.6 2005/02/11 15:07:33 dburken Exp $ +#include <imaging/tile_sources/ossimJpegYCbCrToRgbSource.h> +#include <imaging/ossimImageData.h> +#include <base/common/ossimConstants.h> +#include <base/common/ossimCommon.h> +#include <base/data_types/color_space/ossimJpegYCbCrVector.h> +#include <base/data_types/color_space/ossimRgbVector.h> + +RTTI_DEF1(ossimJpegYCbCrToRgbSource, + "ossimJpegYCbCrToRgbSource" , + ossimImageSourceFilter) + +ossimJpegYCbCrToRgbSource::ossimJpegYCbCrToRgbSource() + :ossimImageSourceFilter(), + theBlankTile() +{ +} + +ossimJpegYCbCrToRgbSource::ossimJpegYCbCrToRgbSource(ossimImageSource* inputSource) + : ossimImageSourceFilter(inputSource), + theBlankTile() +{ +} + +ossimJpegYCbCrToRgbSource::~ossimJpegYCbCrToRgbSource() +{ +} + +void ossimJpegYCbCrToRgbSource::initialize() +{ + ossimImageSourceFilter::initialize(); +} + +void ossimJpegYCbCrToRgbSource::allocate() +{ + theBlankTile = new ossimImageData(this, + OSSIM_UCHAR, + 3); +} + +ossimRefPtr<ossimImageData> ossimJpegYCbCrToRgbSource::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if (!theBlankTile.valid()) + { + allocate(); // first time through. + } + + if(theBlankTile.valid()) + { + theBlankTile->setOrigin(tileRect.ul()); + theBlankTile->setWidthHeight(tileRect.width(), tileRect.height()); + } + + if(theInputConnection) + { + ossimRefPtr<ossimImageData> imageData = + theInputConnection->getTile(tileRect, resLevel); + + if(!imageData.valid()) + { + return theBlankTile; + } + if((isSourceEnabled())&& + (imageData->getNumberOfBands()==3)&& + (imageData->getScalarType()==OSSIM_UCHAR)&& + (imageData->getDataObjectStatus()!=OSSIM_NULL)&& + (imageData->getDataObjectStatus()!=OSSIM_EMPTY)) + { + ossim_uint8* bands[3]; + + bands[0] = static_cast<ossim_uint8*>(imageData->getBuf(0)); + bands[1] = static_cast<ossim_uint8*>(imageData->getBuf(1)); + bands[2] = static_cast<ossim_uint8*>(imageData->getBuf(2)); + + long height = imageData->getHeight(); + long width = imageData->getWidth(); + long offset = 0; + for(long row = 0; row < height; ++row) + { + for(long col = 0; col < width; ++col) + { + + ossimJpegYCbCrVector ycbcr(bands[0][offset], + bands[1][offset], + bands[2][offset]); + ossimRgbVector rgb(ycbcr); + + + bands[0][offset] = rgb.getR(); + bands[1][offset] = rgb.getG(); + bands[2][offset] = rgb.getB(); + + ++offset; + } + } + imageData->validate(); + } + return imageData; + } + + return theBlankTile; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimJpegYCbCrToRgbSource.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimJpegYCbCrToRgbSource.h new file mode 100644 index 0000000000..4fe2c8ddad --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimJpegYCbCrToRgbSource.h @@ -0,0 +1,37 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimJpegYCbCrToRgbSource.h,v 1.5 2005/02/11 15:07:33 dburken Exp $ +#ifndef ossimJpegYCbCrToRgbSource_HEADER +#define ossimJpegYCbCrToRgbSource_HEADER +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +class ossimJpegYCbCrToRgbSource : public ossimImageSourceFilter +{ +public: + ossimJpegYCbCrToRgbSource(); + ossimJpegYCbCrToRgbSource(ossimImageSource* inputSource); + virtual ~ossimJpegYCbCrToRgbSource(); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& origin, + ossim_uint32 resLevel=0); + + virtual void initialize(); + +protected: + + virtual void allocate(); + + ossimRefPtr<ossimImageData> theBlankTile; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimLandsatTopoCorrectionFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimLandsatTopoCorrectionFilter.cpp new file mode 100644 index 0000000000..9729ed9457 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimLandsatTopoCorrectionFilter.cpp @@ -0,0 +1,361 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimLandsatTopoCorrectionFilter.cpp,v 1.6 2005/05/09 12:39:40 dburken Exp $ +#include <imaging/tile_sources/ossimLandsatTopoCorrectionFilter.h> +#include <imaging/tile_sources/ossimImageToPlaneNormalFilter.h> +#include <support_data/ff_l7/ossimFfL7.h> +#include <imaging/formats/ossimImageHandler.h> +#include <base/data_types/ossimDirectory.h> +#include <base/misc/ossim2dLinearRegression.h> +#include <base/context/ossimNotifyContext.h> +#include <base/common/ossimKeywordNames.h> + +#include <iostream> + +RTTI_DEF1(ossimLandsatTopoCorrectionFilter, "ossimLandsatTopoCorrectionFilter",ossimTopographicCorrectionFilter); +ossimLandsatTopoCorrectionFilter::ossimLandsatTopoCorrectionFilter() + :ossimTopographicCorrectionFilter(), + theLandsatHeader("") +{ +} + +ossimLandsatTopoCorrectionFilter::~ossimLandsatTopoCorrectionFilter() +{ +} + +ossimLandsatTopoCorrectionFilter::ossimLandsatTopoCorrectionFilter(ossimImageSource* colorSource, + ossimImageSource* elevSource, + const ossimFilename& landsatFileName) + :ossimTopographicCorrectionFilter(colorSource, + elevSource), + theLandsatHeader(landsatFileName) +{ +} + +void ossimLandsatTopoCorrectionFilter::initialize() +{ + + ossimTopographicCorrectionFilter::initialize(); + if(theLandsatHeader == "") + { + setLandsatHeader(findLandsatHeader()); + } + else + { + setLandsatHeader(theLandsatHeader); + } +} + +void ossimLandsatTopoCorrectionFilter::setLandsatHeader(const ossimFilename& header) +{ + if(header != "") + { + theLandsatHeader = header; + ossimFfL7 headerL7(header.c_str()); + theGain = headerL7.theGain; + theBias = headerL7.theBias; + theLightSourceElevationAngle = headerL7.theSunElevation; + theLightSourceAzimuthAngle = headerL7.theSunAzimuth; + computeLightDirection(); + theJulianDay = headerL7.getJulianDay(); + } +} + +ossimFilename ossimLandsatTopoCorrectionFilter::findLandsatHeader() +{ + ossimFilename result; + + if(!getInput(0)) + { + return result; + } + vector<ossimConnectableObject*> handlerList; + + getInput(0)->findAllInputsOfType(handlerList, + STATIC_TYPE_INFO(ossimImageHandler), + true, + true); + + ossimImageHandler* handler = NULL; + + if(handlerList.size()) + { + handler = (ossimImageHandler*)handlerList[0]; + } + + if(handler) + { + ossimFilename imageFile = handler->getFilename(); + imageFile.setExtension("fst"); + if(imageFile.exists()) + { + result = imageFile; + } + else + { + imageFile.setExtension("FST"); + if(imageFile.exists()) + { + result = imageFile; + } + else + { + ossimDirectory dir; + + if(dir.open(imageFile.path())) + { + vector<ossimFilename> fileList; + + dir.findAllFilesThatMatch(fileList, + ".*.fst"); + if(fileList.size() <1) + { + dir.findAllFilesThatMatch(fileList, + ".*.FST"); + } + for(int i = 0; i < (int)fileList.size(); ++i) + { + if(fileList[i].contains("_hpn")|| + fileList[i].contains("_hrf")|| + fileList[i].contains("_htm")) + { + result = fileList[i]; + break; + } + } + } + } + } + } + return result; +} + +// void ossimLandsatTopoCorrectionFilter::addRegressionPoints(std::vector<ossim2dLinearRegression>& regressionPoints, +// ossimImageData* colorData, +// ossimImageData* normalData) +// { +// ossim_uint32 b = 0; + +// for(b = 0; b < colorData->getNumberOfBands(); ++b) +// { +// ossim_float64* normalBands[3]; +// normalBands[0] = normalData->getBuf(0); +// normalBands[1] = normalData->getBuf(1); +// normalBands[2] = normalData->getBuf(2); +// ossim_float64* colorData = +// } + +#if 0 +void ossimLandsatTopoCorrectionFilter::computeC() +{ + theCComputedFlag = false; + ossim_uint32 totalNumberOfPixelsUsed = 0; + if(getInput(0)&&getInput(1)) + { + std::vector<ossim2dLinearRegression> linearRegression(6); + + ossimImageSourceInterface* colorSource = PTR_CAST(ossimImageSourceInterface, getInput(0)); + ossimImageSourceInterface* normalSource = PTR_CAST(ossimImageSourceInterface, getInput(1)); + ossimFfL7 headerL7(theLandsatHeader.c_str()); + + if(theLandsatHeader == "") + { + ossimNotify(ossimNotifyLevel_WARN) << "No landsat header found " << std::endl; + return; + } + if(colorSource->getNumberOfOutputBands() < 6) + { + ossimNotify(ossimNotifyLevel_WARN) << "The color source needs all the vir bands from the landsat" << std::endl + << "Not enough bands to process the request" << std::endl; + return; + } + + ossimIrect normalRect = normalSource->getBoundingRect(); + ossimIrect colorRect = colorSource->getBoundingRect(); + ossimIrect clipRect = normalRect.clipToRect(colorRect); + ossimIpt ul = clipRect.ul(); + ossimIpt lr = clipRect.lr(); + long julianDay = headerL7.getJulianDay(); + double d2 =pow( (double)(1 - 0.01674 * cosd(0.9856*(julianDay-4)) ), 2.0); + ossim_uint32 numberOfPixelsUsedForTile = 0; + for(int y = ul.y; ((y < lr.y)&&(totalNumberOfPixelsUsed<1000));++y) + { + for(int x = ul.x; ((x < lr.x)&&(totalNumberOfPixelsUsed<1000)); ++x) + { + ossimIrect reqRect(x, + y, + x + 127, + y + 127); + ossimIrect reqClip = reqRect.clipToRect(clipRect); + ossimImageData* colorData = colorSource->getTile(reqClip, 0); + ossimImageData* normalData = normalSource->getTile(reqClip, 0); + ossim_uint8* colorBands[6]; + double* normalBands[3]; + double normalBandsNp[3]; + ossim_uint8 colorBandsNp[6]; + colorBands[0] = (ossim_uint8*)colorData->getBuf(0); + colorBands[1] = (ossim_uint8*)colorData->getBuf(1); + colorBands[2] = (ossim_uint8*)colorData->getBuf(2); + colorBands[3] = (ossim_uint8*)colorData->getBuf(3); + colorBands[4] = (ossim_uint8*)colorData->getBuf(4); + colorBands[5] = (ossim_uint8*)colorData->getBuf(5); + colorBandsNp[0] = (ossim_uint8)colorData->getNullPix(0); + colorBandsNp[1] = (ossim_uint8)colorData->getNullPix(1); + colorBandsNp[2] = (ossim_uint8)colorData->getNullPix(2); + colorBandsNp[3] = (ossim_uint8)colorData->getNullPix(3); + colorBandsNp[4] = (ossim_uint8)colorData->getNullPix(4); + colorBandsNp[5] = (ossim_uint8)colorData->getNullPix(5); + normalBands[0] = (double*)normalData->getBuf(0); + normalBands[1] = (double*)normalData->getBuf(1); + normalBands[2] = (double*)normalData->getBuf(2); + normalBandsNp[0] = normalData->getNullPix(0); + normalBandsNp[1] = normalData->getNullPix(1); + normalBandsNp[2] = normalData->getNullPix(2); + ossim_uint32 offset = 0; + ossim_uint32 numberOfPixels = reqClip.width()*reqClip.height(); + numberOfPixelsUsedForTile = 0; + for(offset = 0; ((offset < numberOfPixels)&&(numberOfPixelsUsedForTile < 10)); ++offset) + { + if((*colorBands[0] != colorBandsNp[0])&& + (*colorBands[1] != colorBandsNp[1])&& + (*colorBands[2] != colorBandsNp[2])&& + (*colorBands[3] != colorBandsNp[3])&& + (*colorBands[4] != colorBandsNp[4])&& + (*colorBands[5] != colorBandsNp[5])&& + (*normalBands[0] != normalBandsNp[0])&& + (*normalBands[1] != normalBandsNp[1])&& + (*normalBands[2] != normalBandsNp[2])) + { + double ndviTest = (((double)*colorBands[3] - (double)*colorBands[2])/ + ((double)*colorBands[3] + (double)*colorBands[2])); + if(ndviTest > 0.0) + { + double radiance5 = theBias[5]+(*colorBands[5]*theGain[5]); +// double p = (M_PI*radiance5*d2)/(esun[5]*cosd(90-theLightSourceAzimuthAngle)); + +// if(p < .05) + { + double cosineI = ((*normalBands[0])*theLightDirection[0] + + (*normalBands[1])*theLightDirection[1] + + (*normalBands[2])*theLightDirection[2]); + + double radiance0 = theBias[0]+(*colorBands[0]*theGain[0]); + double radiance1 = theBias[1]+(*colorBands[1]*theGain[1]); + double radiance2 = theBias[2]+(*colorBands[2]*theGain[2]); + double radiance3 = theBias[3]+(*colorBands[3]*theGain[3]); + double radiance4 = theBias[4]+(*colorBands[4]*theGain[4]); + cosineI = fabs(cosineI); + if(cosineI > 1.0) cosineI = 1.0; + if(cosineI < 0.0) cosineI = 0.0; + cosineI = acos(cosineI); +// // linearRegression[0].addPoint(ossimDpt( cosineI,(double)(*colorBands[0]))); +// // linearRegression[1].addPoint(ossimDpt( cosineI,(double)(*colorBands[1]))); +// // linearRegression[2].addPoint(ossimDpt( cosineI,(double)(*colorBands[2]))); +// // linearRegression[3].addPoint(ossimDpt( cosineI,(double)(*colorBands[3]))); +// // linearRegression[4].addPoint(ossimDpt( cosineI,(double)(*colorBands[4]))); +// // linearRegression[5].addPoint(ossimDpt( cosineI,(double)(*colorBands[5]))); + + linearRegression[0].addPoint(ossimDpt( cosineI,radiance0)); + linearRegression[1].addPoint(ossimDpt( cosineI,radiance1)); + linearRegression[2].addPoint(ossimDpt( cosineI,radiance2)); + linearRegression[3].addPoint(ossimDpt( cosineI,radiance3)); + linearRegression[4].addPoint(ossimDpt( cosineI,radiance4)); + linearRegression[5].addPoint(ossimDpt( cosineI,radiance5)); + + ++numberOfPixelsUsedForTile; + ++totalNumberOfPixelsUsed; + } + } + } + ++colorBands[0]; + ++colorBands[1]; + ++colorBands[2]; + ++colorBands[3]; + ++colorBands[4]; + ++colorBands[5]; + ++normalBands[0]; + ++normalBands[1]; + ++normalBands[2]; + } + } + } + if(totalNumberOfPixelsUsed > 2) + { + linearRegression[0].solve(); + linearRegression[1].solve(); + linearRegression[2].solve(); + linearRegression[3].solve(); + linearRegression[4].solve(); + linearRegression[5].solve(); + + ossimNotify(ossimNotifyLevel_INFO) << "linear regression results = " << endl + << linearRegression[0] << endl + << linearRegression[1] << endl + << linearRegression[2] << endl + << linearRegression[3] << endl + << linearRegression[4] << endl + << linearRegression[5] << endl; + double b,m; + linearRegression[0].getEquation(m, b); + theC[0] = b/m; + linearRegression[1].getEquation(m, b); + theC[1] = b/m; + linearRegression[2].getEquation(m, b); + theC[2] = b/m; + linearRegression[3].getEquation(m, b); + theC[3] = b/m; + linearRegression[4].getEquation(m, b); + theC[4] = b/m; + linearRegression[5].getEquation(m, b); + theC[5] = b/m; + } + else + { + ossimNotify(ossimNotifyLevel_INFO) << "No points found in regression test" << endl; + } + + } + else + { + ossimNotify(ossimNotifyLevel_WARN) << "No input connected to the ossimLandsatTopoCorrectionFilter" << std::endl; + return; + } + + theCComputedFlag = true; +} +#endif + +bool ossimLandsatTopoCorrectionFilter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimTopographicCorrectionFilter::loadState(kwl, prefix); + const char* filename = kwl.find(prefix, ossimKeywordNames::FILENAME_KW); + + if(filename) + { + setLandsatHeader(filename); + } + + return true; +} + +bool ossimLandsatTopoCorrectionFilter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimTopographicCorrectionFilter::saveState(kwl, prefix); + + kwl.add(prefix, + ossimKeywordNames::FILENAME_KW, + theLandsatHeader.c_str(), + true); + + return true; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimLandsatTopoCorrectionFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimLandsatTopoCorrectionFilter.h new file mode 100644 index 0000000000..21be0287ac --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimLandsatTopoCorrectionFilter.h @@ -0,0 +1,54 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossimLandsatTopoCorrectionFilter.h,v 1.5 2004/04/09 19:11:34 gpotts Exp $ +#ifndef ossimLandsatTopoCorrectionFilter_HEADER +#define ossimLandsatTopoCorrectionFilter_HEADER +#include <base/data_types/ossimFilename.h> +#include <imaging/tile_sources/ossimTopographicCorrectionFilter.h> + +class OSSIMDLLEXPORT ossimLandsatTopoCorrectionFilter : public ossimTopographicCorrectionFilter +{ +public: + ossimLandsatTopoCorrectionFilter(); + virtual ~ossimLandsatTopoCorrectionFilter(); + ossimLandsatTopoCorrectionFilter(ossimImageSource* colorSource, + ossimImageSource* elevSource, + const ossimFilename& landsatFileName=ossimFilename("")); + virtual void initialize(); + virtual void setLandsatHeader(const ossimFilename& header); + virtual ossimFilename getLandsatHeader()const + { + return theLandsatHeader; + } + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; +protected: + ossimFilename theLandsatHeader; + ossimFilename findLandsatHeader(); +// virtual void computeC(); +TYPE_DATA +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimLocalCorrelationFusion.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimLocalCorrelationFusion.cpp new file mode 100644 index 0000000000..54e8e0b256 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimLocalCorrelationFusion.cpp @@ -0,0 +1,432 @@ +//******************************************************************* +// Copyright (C) 2005 Garrett Potts +// +// LICENSE: See top level LICENSE.txt +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimLocalCorrelationFusion.cpp,v 1.13 2005/12/12 12:57:28 gpotts Exp $ +#include "ossimLocalCorrelationFusion.h" +#include <matrix/newmat.h> +#include <matrix/newmatio.h> +#include <base/misc/ossim2dLinearRegression.h> +#include <base/data_types/color_space/ossimNormRgbVector.h> +#include <base/data_types/color_space/ossimHsiVector.h> +#include <imaging/factory/ossimImageDataFactory.h> + +RTTI_DEF2(ossimLocalCorrelationFusion, "ossimLocalCorrelationFusion", ossimFusionCombiner, ossimAdjustableParameterInterface); + + +static const ossim_uint32 REGRESSION_COEFFICIENT_ATTENUATOR_OFFSET = 0; +static const ossim_uint32 REGRESSION_COEFFICIENT_CLAMP_OFFSET = 1; +static const ossim_uint32 HIGH_PASS_GAIN_OFFSET = 2; +static const ossim_uint32 PAN_BLURR_WIDTH_OFFSET = 3; +static const ossim_uint32 NUMBER_OF_ADJUSTABLE_PARAMETERS = 4; + +ossimLocalCorrelationFusion::ossimLocalCorrelationFusion() + :theBlurrKernelWidth(1.5), + theHighPassKernelWidth(3), + theRegressionWidth(5) +{ + theLowPassFilter = new ossimImageGaussianFilter; + theHighPassFilter = new ossimConvolutionSource; + + setFilters(); + + initAdjustableParameters(); +} + +ossimLocalCorrelationFusion::~ossimLocalCorrelationFusion() +{ +} + +ossimRefPtr<ossimImageData> ossimLocalCorrelationFusion::getTile(const ossimIrect& rect, + ossim_uint32 resLevel) +{ + if(!theInputConnection) + { + return ossimRefPtr<ossimImageData>(); + } + + if (!theIntensityConnection) + { + return theInputConnection->getTile(rect, resLevel); + } + + ossim_int32 regressionW2 = (ossim_int32)ceil(theRegressionWidth/2.0); + + ossimIrect expandedRegressionRect(rect.ul().x - regressionW2, + rect.ul().y - regressionW2, + rect.lr().x + regressionW2, + rect.lr().y + regressionW2); + + if(!theNormLowPassTile.valid()) + { + theNormLowPassTile = new ossimImageData(this, + OSSIM_NORMALIZED_FLOAT, + 1, + expandedRegressionRect.width(), + expandedRegressionRect.height()); + theNormHighPassTile = new ossimImageData(this, + OSSIM_NORMALIZED_FLOAT, + 1, + expandedRegressionRect.width(), + expandedRegressionRect.height()); + theNormLowPassTile->initialize(); + theNormHighPassTile->initialize(); + theNormLowPassTile->makeBlank(); + theNormHighPassTile->makeBlank(); + } + + theNormLowPassTile->setImageRectangle(expandedRegressionRect); + theNormHighPassTile->setImageRectangle(expandedRegressionRect); + theNormLowPassTile->makeBlank(); + theNormHighPassTile->makeBlank(); + + if(!theLowPassFilter->getInput() && getInput()) + { + initialize(); + } + + ossimRefPtr<ossimImageData> lowTile = theLowPassFilter->getTile(expandedRegressionRect, resLevel); + ossimRefPtr<ossimImageData> highTile = theHighPassFilter->getTile(expandedRegressionRect, resLevel); +// ossimRefPtr<ossimImageData> highTile = getNormIntensity(expandedRegressionRect, resLevel); + ossimIpt ul = rect.ul(); + ossimIpt origin; + + // if we don't have valid low and high pass then return the input color tile + // in its original format + // + if(!lowTile.valid()||!highTile.valid()) + { + return theInputConnection->getTile(rect, resLevel); + } + + if((lowTile->getDataObjectStatus() == OSSIM_EMPTY)|| + (!lowTile->getBuf()) || + (highTile->getDataObjectStatus() == OSSIM_EMPTY)|| + (!highTile->getBuf())) + { + return theInputConnection->getTile(rect, resLevel); + } + + ossimRefPtr<ossimImageData> normColorData = getNormTile(expandedRegressionRect, resLevel); + + ossim_uint32 y = 0; + ossim_uint32 x = 0; + ossim_uint32 w = theTile->getWidth(); + ossim_uint32 h = theTile->getHeight(); + + theTile->makeBlank(); + theTile->setImageRectangle(rect); + + if(!normColorData.valid()) + { + return 0; +// return theTile; + } + + if((normColorData->getDataObjectStatus() == OSSIM_EMPTY)|| + !normColorData->getBuf()) + { + return theTile; + } + ossimRefPtr<ossimImageData> normColorOutputData = (ossimImageData*)normColorData->dup(); + normColorOutputData->setImageRectangle(rect); + normColorOutputData->loadTile(normColorData.get()); + + ossim_float64 slopeResult = 0.0; + ossim_uint32 idx = 0; + std::vector<ossim_float32*> bands(normColorData->getNumberOfBands()); + + lowTile->copyTileToNormalizedBuffer((ossim_float32*)theNormLowPassTile->getBuf()); + + highTile->copyTileToNormalizedBuffer((ossim_float32*)theNormHighPassTile->getBuf()); + theNormLowPassTile->validate(); + theNormHighPassTile->validate(); + ossimRefPtr<ossimImageData> lowPan = (ossimImageData*)theNormLowPassTile->dup(); + lowPan->setImageRectangle(rect); + lowPan->loadTile(theNormLowPassTile.get()); + ossimRefPtr<ossimImageData> highPan = (ossimImageData*)theNormHighPassTile->dup(); + highPan->setImageRectangle(rect); + highPan->loadTile(theNormHighPassTile.get()); + + ossim_float32* panHigh = (ossim_float32*)highPan->getBuf(); + ossim_float32* panLow = (ossim_float32*)lowPan->getBuf(); + for(idx = 0; idx < bands.size(); ++idx) + { + bands[idx] = (ossim_float32*)normColorOutputData->getBuf(idx); + } + double panAttenuator = computeParameterOffset(REGRESSION_COEFFICIENT_ATTENUATOR_OFFSET); + double delta = 0.0; + ossim_uint32 bandsSize = bands.size(); + ossim_float64 slopeClamp = computeParameterOffset(REGRESSION_COEFFICIENT_CLAMP_OFFSET); + ossim_float64 minSlope = -slopeClamp; + ossim_float64 maxSlope = slopeClamp; + for(y = 0; y < h; ++y) + { + origin.y = ul.y + y; + for(x = 0; x < w; ++x) + { + origin.x = ul.x + x; + +// if(computeRegression(slopeResult, +// origin, +// theNormLowPassTile, +// normColorData, +// 0)) +// { +// delta = panAttenuator*slopeResult*(*panHigh - *panLow); + + for(idx = 0; idx < bandsSize; ++idx) + { + if(*bands[idx] != 0.0) // if band is not null + { + if(computeRegression(slopeResult, + origin, + theNormLowPassTile, + normColorData, + idx)) + { + if(slopeResult < minSlope) slopeResult = minSlope; + if(slopeResult > maxSlope) slopeResult = maxSlope; + delta = panAttenuator*slopeResult*(*panHigh - *panLow); + ossim_float32 normMinPix = (ossim_float32)normColorOutputData->getMinPix(idx); + *bands[idx] += delta; + if(*bands[idx] > 1.0) *bands[idx] = 1.0; + if(*bands[idx] < normMinPix) *bands[idx] = normMinPix; + } + } + ++bands[idx]; + } + ++panHigh; + ++panLow; + } + } + + theTile->copyNormalizedBufferToTile((ossim_float32*)normColorOutputData->getBuf()); + theTile->validate(); + + return theTile; +} + +void ossimLocalCorrelationFusion::initialize() +{ + ossimFusionCombiner::initialize(); + if(!theIntensityConnection) + { + theLowPassFilter->disconnect(); + theHighPassFilter->disconnect(); + } + else + { + theLowPassFilter->connectMyInputTo(0, PTR_CAST(ossimConnectableObject, + theIntensityConnection->getObject())); + theHighPassFilter->connectMyInputTo(0, PTR_CAST(ossimConnectableObject, + theIntensityConnection->getObject())); + setFilters(); + theLowPassFilter->initialize(); + theHighPassFilter->initialize(); + } +} + +void ossimLocalCorrelationFusion::setFilters() +{ + theLowPassFilter->setGaussStd(theBlurrKernelWidth); + + theHighPassMatrix = NEWMAT::Matrix(theHighPassKernelWidth, theHighPassKernelWidth); + theHighPassMatrix = 0; + theHighPassMatrix[theHighPassKernelWidth>>1][theHighPassKernelWidth>>1] = 1; + + // adjust the gain for the high pass filter + // + NEWMAT::Matrix high = theHighPassMatrix; + + ossim_float64 kernelW2 = theHighPassKernelWidth*theHighPassKernelWidth; + double gain = computeParameterOffset(HIGH_PASS_GAIN_OFFSET)*(kernelW2); + double multiplier = gain/(kernelW2); + high = -multiplier; + ossim_int32 cx = theHighPassKernelWidth>>1; + ossim_int32 cy = theHighPassKernelWidth>>1; + + if(gain > FLT_EPSILON) + { + high[cy][cx] = multiplier* ( (kernelW2-1)+kernelW2/gain); + } + else + { + high = 0.0; + high[cy][cx] = 1.0; + } + + theHighPassFilter->setConvolution(high); +} + +bool ossimLocalCorrelationFusion::computeRegression(ossim_float64& slopeResult, + const ossimIpt& origin, + const ossimRefPtr<ossimImageData> panData, + const ossimRefPtr<ossimImageData> colorData, + ossim_uint32 colorBandIdx) +{ + bool result = false; + slopeResult = 0.0; + if(panData.valid()&&colorData.valid()) + { + ossim_int32 regW2 = (ossim_int32)(theRegressionWidth>>1); + ossimIrect rect = panData->getImageRectangle(); + const ossim_float32* colorDataPtr = (const ossim_float32*)colorData->getBuf(colorBandIdx); + const ossim_float32* colorDataPtr2 = (const ossim_float32*)colorData->getBuf(colorBandIdx); + +// const ossim_float32* colorDataPtrBands[3]={0}; + +// if(colorData->getNumberOfBands() <2) +// { +// colorDataPtrBands[0] = (ossim_float32*)colorData->getBuf(0); +// } +// else if(colorData->getNumberOfBands() <3) +// { +// colorDataPtrBands[0] = (ossim_float32*)colorData->getBuf(0); +// colorDataPtrBands[1] = (ossim_float32*)colorData->getBuf(1); +// } +// else +// { +// colorDataPtrBands[0] = (ossim_float32*)colorData->getBuf(0); +// colorDataPtrBands[1] = (ossim_float32*)colorData->getBuf(1); +// colorDataPtrBands[2] = (ossim_float32*)colorData->getBuf(2); +// } + const ossim_float32* panDataPtr = (const ossim_float32*)panData->getBuf(); + const ossim_float32* panDataPtr2 = (const ossim_float32*)panData->getBuf(); +// if(!panDataPtr || !colorDataPtrBands[0]) return result; + if(!panDataPtr || !colorDataPtr) return result; + + ossim_float64 panNp = panData->getNullPix(0); + ossim_float64 colorNp = colorData->getNullPix(0); + ossim_int32 w = (ossim_int32)rect.width(); + ossim_int32 offset = (ossim_int32)( ((origin.y-rect.ul().y) - regW2)*w + + ((origin.x-rect.ul().x) - regW2)); + + ossim_uint32 y = 0; + ossim_uint32 x = 0; + ossim_uint32 idx = 0; + ossim2dLinearRegression regression; + ossim_uint32 offsetColorBand; + + for(y = 0; y < theRegressionWidth; ++y) + { + offsetColorBand = (offset + y*w); + panDataPtr = panDataPtr2 + offsetColorBand; + colorDataPtr = colorDataPtr2 + offsetColorBand; + for(x = 0; x < theRegressionWidth; ++x) + { +// if((*panDataPtr != panNp)&& +// (colorDataPtrBands[0][offsetColorBand] != colorNp)&& +// (colorDataPtrBands[1][offsetColorBand] != colorNp)&& +// (colorDataPtrBands[2][offsetColorBand] != colorNp)) +// { + if((*panDataPtr != panNp)&& + (*colorDataPtr != colorNp)) + { +// ossimNormRgbVector rgbV(colorDataPtrBands[0][offsetColorBand], +// colorDataPtrBands[1][offsetColorBand], +// colorDataPtrBands[2][offsetColorBand]); +// ossimHsiVector hsi(rgbV); + + regression.addPoint(ossimDpt(*panDataPtr, *colorDataPtr)); +// regression.addPoint(ossimDpt(*panDataPtr, hsi.getI())); + ++idx; + } + ++panDataPtr; +// ++offsetColorBand; + ++colorDataPtr; + } + } + if(idx > 2) + { + double slope, intercept; + result = true; + regression.solve(); + regression.getEquation(slope, + intercept); + + slopeResult = slope; + } + } + + return result; +} + +void ossimLocalCorrelationFusion::initAdjustableParameters() +{ + resizeAdjustableParameterArray(NUMBER_OF_ADJUSTABLE_PARAMETERS); + + setAdjustableParameter(REGRESSION_COEFFICIENT_ATTENUATOR_OFFSET, + 0.0); + setParameterDescription(REGRESSION_COEFFICIENT_ATTENUATOR_OFFSET, + "Attenuator"); + setParameterSigma(REGRESSION_COEFFICIENT_ATTENUATOR_OFFSET, + 2.0); + setParameterCenter(REGRESSION_COEFFICIENT_ATTENUATOR_OFFSET, + 1.0); + + + setAdjustableParameter(REGRESSION_COEFFICIENT_CLAMP_OFFSET, + 0.0); + setParameterDescription(REGRESSION_COEFFICIENT_CLAMP_OFFSET, + "Regression clamp"); + setParameterSigma(REGRESSION_COEFFICIENT_CLAMP_OFFSET, + 10.0); + setParameterCenter(REGRESSION_COEFFICIENT_CLAMP_OFFSET, + 10.0); + + + setAdjustableParameter(HIGH_PASS_GAIN_OFFSET, + -1.0); + setParameterDescription(HIGH_PASS_GAIN_OFFSET, + "High pass gain"); + setParameterSigma(HIGH_PASS_GAIN_OFFSET, + 1); + setParameterCenter(HIGH_PASS_GAIN_OFFSET, + 1.0); + + setAdjustableParameter(PAN_BLURR_WIDTH_OFFSET, + -1); + setParameterDescription(PAN_BLURR_WIDTH_OFFSET, + "Blurring kernel width"); + setParameterSigma(PAN_BLURR_WIDTH_OFFSET, + 7); + setParameterCenter(PAN_BLURR_WIDTH_OFFSET, + 7.5); + + + setParameterOffset(PAN_BLURR_WIDTH_OFFSET, + 1.5); + setParameterOffset(REGRESSION_COEFFICIENT_CLAMP_OFFSET, + 4.0); +} + +void ossimLocalCorrelationFusion::adjustableParametersChanged() +{ +// std::cout << "Parameter offset = " << computeParameterOffset(2) << std::endl; + theBlurrKernelWidth = (ossim_uint32)(irint(computeParameterOffset(PAN_BLURR_WIDTH_OFFSET))); +} + + +bool ossimLocalCorrelationFusion::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + ossimFusionCombiner::saveState(kwl, prefix); + saveAdjustments(kwl, prefix); + + return true; +} + +bool ossimLocalCorrelationFusion::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimFusionCombiner::loadState(kwl, prefix); + loadAdjustments(kwl, prefix); + + + return true; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimLocalCorrelationFusion.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimLocalCorrelationFusion.h new file mode 100644 index 0000000000..48e2dbb737 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimLocalCorrelationFusion.h @@ -0,0 +1,88 @@ +//******************************************************************* +// Copyright (C) 2005 Garrett Potts +// +// LICENSE: See top level LICENSE.txt +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimLocalCorrelationFusion.h,v 1.5 2005/12/12 12:50:16 gpotts Exp $ +#ifndef ossimLocalCorrelationFusion_HEADER +#define ossimLocalCorrelationFusion_HEADER +#include "ossimFusionCombiner.h" +#include "ossimConvolutionSource.h" +#include "ossimImageGaussianFilter.h" +#include <base/misc/ossimAdjustableParameterInterface.h> + +/** + * This implements a Local correlation fusion based on the paper: + * + * "A Local Correlation Approach For the Fusion of Remote Sensing Data With Different + * Spatial Resolution In Forestry Applications" + * by J. Hill, C. Diemer, O. Stover, and Th. Udelhoven + * Published in: + * International Archives of Photogrammetry and Remote Sensing, Vol 32, Part 7-4-3 W6, + * Valladolid, Spain, 3-4 June, 1999 + * + * A new band is computed by the formula: + * + * ColorHigh = ColorLow + RegressionSlope*(PanHigh-PanLow); + * + * Adjustable paraemters have been added to clamp the regression slope and attenuate + * colorLowOffset value and blurring the Pan. + * + * ColorHigh = ColorLow + Clamp(RegressionSlope)*Attenuator(PanHigh-PanLow); + * + * The regression coefficient is coputed for each color band. + */ +class OSSIM_DLL ossimLocalCorrelationFusion : public ossimFusionCombiner, + public ossimAdjustableParameterInterface +{ +public: + ossimLocalCorrelationFusion(); + virtual ~ossimLocalCorrelationFusion(); + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect, + ossim_uint32 resLevel=0); + virtual void initialize(); + + virtual ossimObject* getBaseObject() + { + return this; + } + virtual const ossimObject* getBaseObject()const + { + return this; + } + virtual void initAdjustableParameters(); + virtual void adjustableParametersChanged(); + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0) const; + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +protected: + void setFilters(); + bool computeRegression(ossim_float64& slopeResult, + const ossimIpt& origin, + ossimRefPtr<ossimImageData> panData, + ossimRefPtr<ossimImageData> colorData, + ossim_uint32 colorBandIdx); + + ossim_float64 theBlurrKernelWidth; + ossim_uint32 theHighPassKernelWidth; + ossim_uint32 theRegressionWidth; + // These are low and high pass filters for the single pan band + // + ossimRefPtr<ossimImageGaussianFilter> theLowPassFilter; + ossimRefPtr<ossimConvolutionSource> theHighPassFilter; + ossimRefPtr<ossimImageData> theNormLowPassTile; + ossimRefPtr<ossimImageData> theNormHighPassTile; + ossimRefPtr<ossimImageData> theNormColorData; + + NEWMAT::Matrix theHighPassMatrix; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimMaskFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimMaskFilter.cpp new file mode 100644 index 0000000000..9b2a05ad9d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimMaskFilter.cpp @@ -0,0 +1,798 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: A brief description of the contents of the file. +// +//************************************************************************* +// $Id: ossimMaskFilter.cpp,v 1.15 2005/09/15 12:28:44 gpotts Exp $ + +#include <imaging/tile_sources/ossimMaskFilter.h> +#include <imaging/ossimImageData.h> +#include <imaging/ossimImageSourceInterface.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <base/context/ossimNotifyContext.h> + +static const char * MASK_FILTER_MASK_TYPE_KW = "mask_type"; + +RTTI_DEF1(ossimMaskFilter, "ossimMaskFilter", ossimImageCombiner); + +ossimMaskFilter::ossimMaskFilter(ossimObject* owner) + : ossimImageCombiner(owner, + 2, + 0, + true, + false), + theMaskType(OSSIM_MASK_TYPE_SELECT), + theTile(NULL) +{ +} + +ossimMaskFilter::ossimMaskFilter(ossimImageSource* imageSource, + ossimImageSource* maskSource) + :ossimImageCombiner(NULL, + 2, + 0, + true, + false), + theMaskType(OSSIM_MASK_TYPE_SELECT), + theTile(NULL) +{ + connectMyInputTo(0, imageSource); + connectMyInputTo(1, maskSource); +} + +ossimMaskFilter::ossimMaskFilter(ossimObject* owner, + ossimImageSource* imageSource, + ossimImageSource* maskSource) + :ossimImageCombiner(owner, + 2, + 0, + true, + false), + theMaskType(OSSIM_MASK_TYPE_SELECT), + theTile(NULL) + +{ + connectMyInputTo(0, imageSource); + connectMyInputTo(1, maskSource); +} + +ossimMaskFilter::~ossimMaskFilter() +{ +} + +ossimRefPtr<ossimImageData> ossimMaskFilter::getTile(const ossimIrect& rect, + ossim_uint32 resLevel) +{ + ossimImageSourceInterface* imageSource = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + + // we will check to see if it's a fileMaskSource + // + ossimImageSourceInterface* maskSource = PTR_CAST(ossimImageSourceInterface, + getInput(1)); + + ossimRefPtr<ossimImageData> imageSourceData; + ossimRefPtr<ossimImageData> maskSourceData; + + if(imageSource) + { + imageSourceData = imageSource->getTile(rect, resLevel); + } + + if(!isSourceEnabled()) + { + return imageSourceData; + } + + if(maskSource) + { + maskSourceData = maskSource->getTile(rect, resLevel); + } + + if (!theTile.valid()) + { + allocate(); + } + + if(!imageSourceData.valid() || !theTile.valid()) + { + ossimRefPtr<ossimImageData>(); + } + + theTile->setOrigin(rect.ul()); + if(theTile->getImageRectangle() != rect) + { + theTile->setImageRectangle(rect); + theTile->initialize(); + } + if(!imageSourceData.valid()) + { + return theTile; + } + if(!maskSourceData.valid()) + { + return imageSourceData; + } + + if(imageSourceData->getDataObjectStatus() != OSSIM_NULL) + { + return executeMaskFilter(imageSourceData, maskSourceData); + } + + return theTile; +} + +bool ossimMaskFilter::canConnectMyInputTo(ossim_int32 index, + const ossimConnectableObject* object)const +{ + return (PTR_CAST(ossimImageSourceInterface, object)!= NULL); +} + +void ossimMaskFilter::initialize() +{ + ossimImageCombiner::initialize(); + if(getInput(0)) + { + // Force an allocate on the next getTile. + theTile = NULL; + } +} + +void ossimMaskFilter::allocate() +{ + if(getInput(0)) + { + theTile = ossimImageDataFactory::instance()->create(this, this); + theTile->initialize(); + } +} + +ossimRefPtr<ossimImageData> ossimMaskFilter::executeMaskFilter(ossimRefPtr<ossimImageData> imageSourceData, + ossimRefPtr<ossimImageData> maskSourceData) +{ + if(!theTile) + { + theTile = (ossimImageData*)imageSourceData->dup(); + if(!theTile->getBuf()) + { + theTile->initialize(); + } + } + else + { + ossim_uint32 tw = theTile->getWidth(); + ossim_uint32 th = theTile->getHeight(); + ossim_uint32 dw = imageSourceData->getWidth(); + ossim_uint32 dh = imageSourceData->getHeight(); + + theTile->setWidthHeight(imageSourceData->getWidth(), + imageSourceData->getHeight()); + theTile->setOrigin(imageSourceData->getOrigin()); + if((tw*th) != (dw*dh)) + { + theTile->initialize(); + } + theTile->setDataObjectStatus(imageSourceData->getDataObjectStatus()); + } + theTile->loadTile(imageSourceData.get()); + theTile->setDataObjectStatus(imageSourceData->getDataObjectStatus()); + switch(theMaskType) + { + case OSSIM_MASK_TYPE_SELECT: + { + return executeMaskFilterSelect(theTile, + maskSourceData); + } + case OSSIM_MASK_TYPE_INVERT: + { + return executeMaskFilterInvertSelect(theTile, + maskSourceData); + } + case OSSIM_MASK_TYPE_WEIGHTED: + { + return executeMaskFilterWeighted(theTile, + maskSourceData); + } + } + + return imageSourceData; +} + +ossimRefPtr<ossimImageData> ossimMaskFilter::executeMaskFilterSelect(ossimRefPtr<ossimImageData> imageSourceData, + ossimRefPtr<ossimImageData> maskSourceData) +{ + if(maskSourceData->getScalarType() != OSSIM_UCHAR) + { + ossimNotify(ossimNotifyLevel_WARN) << "ossimMaskFilter::executeMaskFilterSelect WARNING: Only uchar masks are supported" << endl; + return imageSourceData; + } + + switch(imageSourceData->getScalarType()) + { + case OSSIM_UCHAR: + { + executeMaskFilterSelection((ossim_uint8)0, + (ossim_uint8)0, + imageSourceData, + maskSourceData); + break; + } + case OSSIM_USHORT11: + case OSSIM_USHORT16: + { + executeMaskFilterSelection((ossim_uint16)0, + (ossim_uint8)0, + imageSourceData, + maskSourceData); + break; + } + case OSSIM_SSHORT16: + { + executeMaskFilterSelection((ossim_sint16)0, + (ossim_uint8)0, + imageSourceData, + maskSourceData); + break; + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + executeMaskFilterSelection((float)0, + (ossim_uint8)0, + imageSourceData, + maskSourceData); + break; + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + executeMaskFilterSelection((double)0, + (ossim_uint8)0, + imageSourceData, + maskSourceData); + break; + } + default: + { + ossimNotify(ossimNotifyLevel_WARN) << "ossimMaskFilter::executeMaskFilterSelect WARNING: Unknown scalar type" << endl; + break; + } + } + + return theTile; +} + +ossimRefPtr<ossimImageData> ossimMaskFilter::executeMaskFilterInvertSelect(ossimRefPtr<ossimImageData> imageSourceData, + ossimRefPtr<ossimImageData> maskSourceData) +{ + if(maskSourceData->getScalarType() != OSSIM_UCHAR) + { + ossimNotify(ossimNotifyLevel_WARN) << "ossimMaskFilter::executeMaskFilterSelect WARNING: Only uchar masks are supported" << endl; + return imageSourceData; + } + + switch(imageSourceData->getScalarType()) + { + case OSSIM_UCHAR: + { + executeMaskFilterInvertSelection((ossim_uint8)0, + (ossim_uint8)0, + imageSourceData, + maskSourceData); + break; + } + case OSSIM_USHORT11: + case OSSIM_USHORT16: + { + executeMaskFilterInvertSelection((ossim_uint16)0, + (ossim_uint8)0, + imageSourceData, + maskSourceData); + break; + } + case OSSIM_SSHORT16: + { + executeMaskFilterInvertSelection((ossim_sint16)0, + (ossim_uint8)0, + imageSourceData, + maskSourceData); + break; + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + executeMaskFilterInvertSelection((float)0, + (ossim_uint8)0, + imageSourceData, + maskSourceData); + break; + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + executeMaskFilterInvertSelection((double)0, + (ossim_uint8)0, + imageSourceData, + maskSourceData); + break; + } + default: + { + ossimNotify(ossimNotifyLevel_WARN) << "ossimMaskFilter::executeMaskFilterSelect WARNING: Unknown scalar type" << endl; + break; + } + } + + return theTile; +} + +ossimRefPtr<ossimImageData> ossimMaskFilter::executeMaskFilterWeighted(ossimRefPtr<ossimImageData> imageSourceData, + ossimRefPtr<ossimImageData> maskSourceData) +{ + if(maskSourceData->getScalarType() != OSSIM_UCHAR) + { + ossimNotify(ossimNotifyLevel_WARN) << "ossimMaskFilter::executeMaskFilterSelect WARNING: Only uchar masks are supported" << endl; + return imageSourceData; + } + + switch(imageSourceData->getScalarType()) + { + case OSSIM_UCHAR: + { + executeMaskFilterWeighted((ossim_uint8)0, + (ossim_uint8)0, + imageSourceData, + maskSourceData); + break; + } + case OSSIM_USHORT11: + case OSSIM_USHORT16: + { + executeMaskFilterWeighted((ossim_uint16)0, + (ossim_uint8)0, + imageSourceData, + maskSourceData); + break; + } + case OSSIM_SSHORT16: + { + executeMaskFilterWeighted((ossim_sint16)0, + (ossim_uint8)0, + imageSourceData, + maskSourceData); + break; + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + executeMaskFilterWeighted((float)0, + (ossim_uint8)0, + imageSourceData, + maskSourceData); + break; + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + executeMaskFilterWeighted((double)0, + (ossim_uint8)0, + imageSourceData, + maskSourceData); + break; + } + default: + { + ossimNotify(ossimNotifyLevel_WARN) << "ossimMaskFilter::executeMaskFilterSelect WARNING: Unknown scalar type" << endl; + break; + } + } + + return theTile; +} + +template <class inputT, class maskT> +ossimRefPtr<ossimImageData> ossimMaskFilter::executeMaskFilterSelection(inputT dummyInput, + maskT dummyMask, + ossimRefPtr<ossimImageData> imageSourceData, + ossimRefPtr<ossimImageData> maskSourceData) +{ + ossimDataObjectStatus maskDataStatus = maskSourceData->getDataObjectStatus(); + ossimDataObjectStatus inputDataStatus = imageSourceData->getDataObjectStatus(); + + if( (maskDataStatus == OSSIM_NULL)|| + (maskDataStatus == OSSIM_EMPTY)) + { + theTile->makeBlank(); + return theTile; + + } + if( (inputDataStatus == OSSIM_NULL)|| + (inputDataStatus == OSSIM_EMPTY)|| + (maskDataStatus == OSSIM_FULL)) + { + return theTile; + } + if(maskDataStatus == OSSIM_FULL) + { + return theTile; + } + + ossim_uint32 maskBands = maskSourceData->getNumberOfBands(); + ossim_uint32 inputBands = imageSourceData->getNumberOfBands(); + if(maskBands&&inputBands) + { + ossim_uint32 maxOffset = theTile->getWidth()*theTile->getHeight(); + for(ossim_uint32 band = 0; band < inputBands; ++band) + { + maskT* bufMask = (maskT*)maskSourceData->getBuf(); + inputT* bufIn = (inputT*)imageSourceData->getBuf(band); + inputT* bufOut = (inputT*)theTile->getBuf(band); + inputT np = (inputT)theTile->getNullPix(band); + ossim_uint32 offset = 0; + for(offset = 0; offset < maxOffset; ++offset) + { + if(*bufMask) + { + *bufOut = *bufIn; + } + else + { + *bufOut = np; + } + ++bufOut; + ++bufIn; + ++bufMask; + } + } + theTile->validate(); + } + + return theTile; +} + +template <class inputT, class maskT> +ossimRefPtr<ossimImageData> ossimMaskFilter::executeMaskFilterInvertSelection(inputT dummyInput, + maskT dummyMask, + ossimRefPtr<ossimImageData> imageSourceData, + ossimRefPtr<ossimImageData> maskSourceData) +{ + ossimDataObjectStatus maskDataStatus = maskSourceData->getDataObjectStatus(); + ossimDataObjectStatus inputDataStatus = imageSourceData->getDataObjectStatus(); + + if((maskDataStatus == OSSIM_NULL) || + (maskDataStatus == OSSIM_EMPTY)) + { + return theTile; + } + if( (inputDataStatus == OSSIM_NULL)|| + (inputDataStatus == OSSIM_EMPTY)) + { + return theTile; + } + + if(maskDataStatus == OSSIM_FULL) + { + theTile->makeBlank(); + + return theTile; + } + + ossim_uint32 maskBands = maskSourceData->getNumberOfBands(); + ossim_uint32 inputBands = imageSourceData->getNumberOfBands(); + if(maskBands&&inputBands) + { + ossim_uint32 maxOffset = theTile->getWidth()*theTile->getHeight(); + for(ossim_uint32 band = 0; band < inputBands; ++band) + { + maskT* bufMask = (maskT*)maskSourceData->getBuf(); + inputT* bufIn = (inputT*)imageSourceData->getBuf(band); + inputT* bufOut = (inputT*)theTile->getBuf(band); + inputT np = (inputT)theTile->getNullPix(band); + ossim_uint32 offset = 0; + for(offset = 0; offset < maxOffset; ++offset) + { + if(!*bufMask) + { + *bufOut = *bufIn; + } + else + { + *bufOut = np; + } + ++bufOut; + ++bufIn; + ++bufMask; + } + } + theTile->validate(); + } + + return theTile; +} + +template <class inputT, class maskT> +ossimRefPtr<ossimImageData> ossimMaskFilter::executeMaskFilterWeighted(inputT dummyInput, + maskT dummyMask, + ossimRefPtr<ossimImageData> imageSourceData, + ossimRefPtr<ossimImageData> maskSourceData) +{ + ossimDataObjectStatus maskDataStatus = maskSourceData->getDataObjectStatus(); + ossimDataObjectStatus inputDataStatus = imageSourceData->getDataObjectStatus(); + + if( (maskDataStatus == OSSIM_NULL)|| + (maskDataStatus == OSSIM_EMPTY)) + { + theTile->makeBlank(); + return theTile; + + } + if( (inputDataStatus == OSSIM_NULL)|| + (inputDataStatus == OSSIM_EMPTY)) + { + return theTile; + } + + ossim_uint32 maskBands = maskSourceData->getNumberOfBands(); + ossim_uint32 inputBands = imageSourceData->getNumberOfBands(); + if(maskBands&&inputBands) + { + ossim_uint32 maxOffset = theTile->getWidth()*theTile->getHeight(); + for(ossim_uint32 band = 0; band < inputBands; ++band) + { + maskT* bufMask = (maskT*)maskSourceData->getBuf(); + inputT* bufIn = (inputT*)imageSourceData->getBuf(band); + inputT* bufOut = (inputT*)theTile->getBuf(band); + inputT np = (inputT)theTile->getNullPix(band); + inputT minp = (inputT)theTile->getMinPix(band); + ossim_uint32 offset = 0; + + if(inputDataStatus == OSSIM_PARTIAL) + { + for(offset = 0; offset < maxOffset; ++offset) + { + if(*bufIn != np) + { + *bufOut = (inputT)((*bufIn)*((double)(*bufMask)/255.0)); + if((*bufOut != np)&& + (*bufOut < minp)) + { + *bufOut = minp; + } + } + else + { + *bufOut = np; + } + ++bufOut; + ++bufIn; + ++bufMask; + } + } + else + { + for(offset = 0; offset < maxOffset; ++offset) + { + *bufOut = (inputT)((*bufIn)*((double)(*bufMask)/255.0)); + if((*bufOut != np)&& + (*bufOut < minp)) + { + *bufOut = minp; + } + ++bufOut; + ++bufIn; + ++bufMask; + } + } + } + theTile->validate(); + } + + return theTile; +} + + +ossimIrect ossimMaskFilter::getBoundingRect(ossim_uint32 resLevel)const +{ + ossimIrect result; + result.makeNan(); + + ossimImageSourceInterface* imageSource = PTR_CAST(ossimImageSourceInterface, getInput(0)); + if(imageSource) + { + result = imageSource->getBoundingRect(resLevel); + } + return result; +} + +bool ossimMaskFilter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + bool result = ossimImageCombiner::loadState(kwl, prefix); + + theInputListIsFixedFlag = true; + theOutputListIsFixedFlag = false; + setNumberOfInputs(2); + + ossimString selectionType = kwl.find(prefix, MASK_FILTER_MASK_TYPE_KW); + + selectionType = selectionType.upcase(); + if(selectionType != "") + { + if(selectionType == "SELECT") + { + theMaskType = OSSIM_MASK_TYPE_SELECT; + } + else if(selectionType == "INVERT") + { + theMaskType = OSSIM_MASK_TYPE_INVERT; + } + else if(selectionType == "WEIGHTED") + { + theMaskType = OSSIM_MASK_TYPE_WEIGHTED; + } + } + + return result; +} + +bool ossimMaskFilter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimString maskType; + + switch(theMaskType) + { + case OSSIM_MASK_TYPE_SELECT: + { + maskType = "select"; + break; + } + case OSSIM_MASK_TYPE_INVERT: + { + maskType = "invert"; + break; + } + case OSSIM_MASK_TYPE_WEIGHTED: + { + maskType = "weighted"; + break; + } + } + + kwl.add(prefix, + MASK_FILTER_MASK_TYPE_KW, + maskType.c_str(), + true); + + return ossimImageCombiner::saveState(kwl, prefix); +} +void ossimMaskFilter::getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result)const +{ + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(input) + { + input->getDecimationFactor(resLevel, result); + } +} + +void ossimMaskFilter::getDecimationFactors(vector<ossimDpt>& decimations)const +{ + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(input) + { + input->getDecimationFactors(decimations); + } +} + +ossim_uint32 ossimMaskFilter::getNumberOfDecimationLevels()const +{ + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(input) + { + return input->getNumberOfDecimationLevels(); + } + return 0; +} + +ossim_uint32 ossimMaskFilter::getNumberOfOutputBands() const +{ + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(input) + { + return input->getNumberOfOutputBands(); + } + return 0; +} + +ossimScalarType ossimMaskFilter::getOutputScalarType() const +{ + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(input) + { + return input->getOutputScalarType(); + } + + return OSSIM_SCALAR_UNKNOWN; +} + +void ossimMaskFilter::getValidImageVertices( + vector<ossimIpt>& validVertices, + ossimVertexOrdering ordering, + ossim_uint32 resLevel)const +{ + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(input) + { + input->getValidImageVertices(validVertices, ordering, resLevel); + } +} + +ossim_uint32 ossimMaskFilter::getTileWidth() const +{ + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(input) + { + return input->getTileWidth(); + } + + return 0; +} + +ossim_uint32 ossimMaskFilter::getTileHeight() const +{ + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(input) + { + return input->getTileHeight(); + } + return 0; +} + +double ossimMaskFilter::getNullPixelValue(ossim_uint32 band)const +{ + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(input) + { + return input->getNullPixelValue(band); + } + return 0; +} + +double ossimMaskFilter::getMinPixelValue(ossim_uint32 band)const +{ + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(input) + { + return input->getMinPixelValue(band); + } + return 0; +} + +double ossimMaskFilter::getMaxPixelValue(ossim_uint32 band)const +{ + ossimImageSourceInterface* input = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(input) + { + return input->getMaxPixelValue(band); + } + return 0; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimMaskFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimMaskFilter.h new file mode 100644 index 0000000000..ebfdc842bd --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimMaskFilter.h @@ -0,0 +1,234 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: A brief description of the contents of the file. +// +//************************************************************************* +// $Id: ossimMaskFilter.h,v 1.13 2005/09/15 12:28:44 gpotts Exp $ +#ifndef ossimMaskFilter_HEADER +#define ossimMaskFilter_HEADER +#include <imaging/tile_sources/ossimImageCombiner.h> + +/** + * <pre> + * class ossimMaskFilter + * + * Requires 2 inputs. The first input is assumed to be the image input + * and the second input is assumed to be the mask data. It will only + * use one band of the mask and multi band masks are not supported. + * + * the number of bands, min pix, max pix, null pix ...etc are mapped + * to the first input. + * + * Keywords: + * mask_type: + * + * keywords description + * mask_type This keyword can have the following values: + * select, invert, or weighted. + * - select will use the input data and every where + * the mask is greater than 0 it will copy the input to the output. + * - invert will use the input data and every where the mask is 0 it + * will copy the input to the output else it will place a null in + * the output. + * - weighted will normalize the mask between 0 and 1 and then multiply + * the input by that normalized value and copy to the output. + * + * example of keywords: + * + * mask_type: select + * + * </pre> + */ +class OSSIMDLLEXPORT ossimMaskFilter : public ossimImageCombiner +{ +public: + /** + * Enumeration used to identify what the selection type for this mask is to be + * A list of events: + * - OSSIM_MASK_TYPE_SELECT + * is used as a true false mask. If the mask is non zero + * then the input is kept if it's 0 then the input is nulled out. + * - OSSIM_MASK_TYPE_INVERT + * has the inverted rule of the above. If the input is tru then the output is nulled + * else the input is kept + * - OSSIM_MASK_TYPE_WEIGHTED + * works as a multiplier of the input data. The mask is normalized to be between 0 and 1 + * and multiplies the input by that normalized value. + */ + enum ossimFileSelectionMaskType + { + OSSIM_MASK_TYPE_SELECT = 1, /**< standard select if mask is true then keep */ + OSSIM_MASK_TYPE_INVERT = 2, /**< standard invert if mask is true the don't keep */ + OSSIM_MASK_TYPE_WEIGHTED = 3 /**< weighted operation. Normalize the mask and multiply the input */ + }; + + /** + * Constructor. + */ + ossimMaskFilter(ossimObject* owner=NULL); + + /** + * Constructs with two inputs + */ + ossimMaskFilter(ossimImageSource* imageSource, + ossimImageSource* maskSource); + + + /** + * Constructs with two inputs and an owner + */ + ossimMaskFilter(ossimObject* owner, + ossimImageSource* imageSource, + ossimImageSource* maskSource); + + /** + * Will delete its owned tile. + */ + virtual ~ossimMaskFilter(); + + /** + * Sets the mask type. + * \param type The mask algorithm type to be used. see ossimFileSelectionMaskType + */ + virtual void setMaskType(ossimFileSelectionMaskType type) + { + theMaskType = type; + } + + /** + * Returns the current mask algorithm used. + * \return the current ossimFileSelectionMaskType used. + */ + virtual ossimFileSelectionMaskType getMaskType()const + { + return theMaskType; + } + + /** + * Returns the bounding rect in pixel space for this object. + * \param resLevel optional res level argument is given. + * \return The bounding rect. It will pass the inputs bounding + * rect since it does not update the bounds. + */ + virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0)const; + + /** + * Main entry point for the algorithm. + * \param rect + * + */ + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect, + ossim_uint32 resLevel=0); + + virtual void initialize(); + virtual void getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result)const; + virtual void getDecimationFactors(vector<ossimDpt>& decimations)const; + + virtual ossim_uint32 getNumberOfDecimationLevels()const; + + virtual ossim_uint32 getNumberOfOutputBands() const; + + virtual ossimScalarType getOutputScalarType() const; + + virtual void getValidImageVertices(vector<ossimIpt>& validVertices, + ossimVertexOrdering ordering=OSSIM_CLOCKWISE_ORDER, + ossim_uint32 resLevel=0)const; + + virtual ossim_uint32 getTileWidth() const; + + virtual ossim_uint32 getTileHeight() const; + + virtual double getNullPixelValue(ossim_uint32 band)const; + + virtual double getMinPixelValue(ossim_uint32 band=0)const; + + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + virtual bool canConnectMyInputTo(ossim_int32 index, + const ossimConnectableObject* object)const; + + virtual ossimRefPtr<ossimImageData> executeMaskFilter( + ossimRefPtr<ossimImageData> imageSourceData, + ossimRefPtr<ossimImageData> maskSourceData); + +protected: + + void allocate(); + + /** + * will execute the section algorithm. everywhere the mask is not 0 it + * copies the input data to the output and everywhere the input is null it + * writes a null pixel to the output. + */ + ossimRefPtr<ossimImageData> executeMaskFilterSelect( + ossimRefPtr<ossimImageData> imageSourceData, + ossimRefPtr<ossimImageData> maskSourceData); + + /** + * will execute the invert selection algorithm. everywhere the mask is 0 + * it copies the input data to the output else it outputs null. + */ + ossimRefPtr<ossimImageData> executeMaskFilterInvertSelect( + ossimRefPtr<ossimImageData> imageSourceData, + ossimRefPtr<ossimImageData> maskSourceData); + + /** + * will execute the weighted algorithm. It normalizes the mask value to + * be between 0 and 1 and multiplies the input data by that value and + * outputs it. + */ + ossimRefPtr<ossimImageData> executeMaskFilterWeighted( + ossimRefPtr<ossimImageData> imageSourceData, + ossimRefPtr<ossimImageData> maskSourceData); + + + template <class inputT, class maskT> + ossimRefPtr<ossimImageData> executeMaskFilterSelection( + inputT dummyInput, + maskT dummyMask, + ossimRefPtr<ossimImageData> imageSourceData, + ossimRefPtr<ossimImageData> maskSourceData); + + template <class inputT, class maskT> + ossimRefPtr<ossimImageData> executeMaskFilterInvertSelection( + inputT dummyInput, + maskT dummyMask, + ossimRefPtr<ossimImageData> imageSourceData, + ossimRefPtr<ossimImageData> maskSourceData); + + template <class inputT, class maskT> + ossimRefPtr<ossimImageData> executeMaskFilterWeighted( + inputT dummyInput, + maskT dummyMask, + ossimRefPtr<ossimImageData> imageSourceData, + ossimRefPtr<ossimImageData> maskSourceData); + + /** + * Member variable that holds the algorithm type to run on the calls to getTile. + */ + ossimFileSelectionMaskType theMaskType; + + /** + * Member used to store the result of the applied algorithm type. This is returned + * from the call to getTile. + */ + ossimRefPtr<ossimImageData> theTile; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimMaxMosaic.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimMaxMosaic.cpp new file mode 100644 index 0000000000..30fb01031b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimMaxMosaic.cpp @@ -0,0 +1,547 @@ +//******************************************************************* +// Copyright (C) 2005 SANZ Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Kenneth Melero (kmelero@sanz.com) +// +// Description: This combiner is designed to "float" the maximum pixel value +// of all inputs to top of the mosaic output. +// +//************************************************************************* +// $Id: ossimMaxMosaic.cpp,v 1.3 2005/06/30 15:14:57 gpotts Exp $ + +#include <imaging/tile_sources/ossimMaxMosaic.h> +#include <imaging/ossimImageData.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <base/common/ossimTrace.h> + +static const ossimTrace traceDebug("ossimMaxMosaic:debug"); + +using namespace std; + +RTTI_DEF1(ossimMaxMosaic, "ossimMaxMosaic", ossimImageCombiner) +ossimMaxMosaic::ossimMaxMosaic() + :ossimImageCombiner(), + theTile(NULL) +{ +} + +ossimMaxMosaic::ossimMaxMosaic(const vector<ossimImageSource*>& inputSources) + : ossimImageCombiner(inputSources), + theTile(NULL) +{ +} + + +ossimMaxMosaic::~ossimMaxMosaic() +{ +} + +ossimRefPtr<ossimImageData> ossimMaxMosaic::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + long size = getNumberOfInputs(); + + // If there is only one in the mosaic then just return it. + if(size == 1) + { + return getNextTile(0, tileRect, resLevel); + } + + ossimIpt origin = tileRect.ul(); + ossim_uint32 w = tileRect.width(); + ossim_uint32 h = tileRect.height(); + + if(!theTile.valid()) + { + // First time through... + allocate(); + + // If we still don't have a buffer then we will leave. + if(!theTile.valid()) + { + return ossimRefPtr<ossimImageData>(); + } + } + + ossim_uint32 tileW = theTile->getWidth(); + ossim_uint32 tileH = theTile->getHeight(); + if((w != tileW)|| + (h != tileH)) + { + theTile->setWidth(w); + theTile->setHeight(h); + if((w*h)!=(tileW*tileH)) + { + theTile->initialize(); + } + } + theTile->setOrigin(origin); + + //--- + // General Note: + // + // Note: I will not check for disabled or enabled since we have + // no clear way to handle this within a mosaic. The default will be + // to do a simple a A over B type mosaic. Derived classes should + // check for the enabled and disabled and always + // use this default implementation if they are disabled. + //--- + theTile->setOrigin(origin); + theTile->makeBlank(); + switch(theTile->getScalarType()) + { + case OSSIM_UCHAR: + { + if(!hasDifferentInputs()) + { + return combine(static_cast<ossim_uint8>(0), + tileRect, + resLevel); + } + else + { + return combineNorm(static_cast<ossim_uint8>(0), + tileRect, + resLevel); + } + } + case OSSIM_SINT8: + { + if(!hasDifferentInputs()) + { + return combine(static_cast<ossim_sint8>(0), + tileRect, + resLevel); + } + else + { + return combineNorm(static_cast<ossim_sint8>(0), + tileRect, + resLevel); + } + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + if(!hasDifferentInputs()) + { + return combine(static_cast<float>(0), + tileRect, + resLevel); + } + else + { + return combineNorm(static_cast<float>(0), + tileRect, + resLevel); + } + } + case OSSIM_USHORT16: + case OSSIM_USHORT11: + { + if(!hasDifferentInputs()) + { + return combine(static_cast<ossim_uint16>(0), + tileRect, + resLevel); + } + else + { + return combineNorm(static_cast<ossim_uint16>(0), + tileRect, + resLevel); + } + } + case OSSIM_SSHORT16: + { + if(!hasDifferentInputs()) + { + return combine(static_cast<ossim_sint16>(0), + tileRect, + resLevel); + } + else + { + return combineNorm(static_cast<ossim_sint16>(0), + tileRect, + resLevel); + } + } + case OSSIM_SINT32: + { + if(!hasDifferentInputs()) + { + return combine(static_cast<ossim_sint32>(0), + tileRect, + resLevel); + } + else + { + return combineNorm(static_cast<ossim_sint32>(0), + tileRect, + resLevel); + } + } + case OSSIM_UINT32: + { + if(!hasDifferentInputs()) + { + return combine(static_cast<ossim_uint32>(0), + tileRect, + resLevel); + } + else + { + return combineNorm(static_cast<ossim_uint32>(0), + tileRect, + resLevel); + } + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + if(!hasDifferentInputs()) + { + return combine(static_cast<double>(0), + tileRect, + resLevel); + } + else + { + return combineNorm(static_cast<double>(0), + tileRect, + resLevel); + } + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "Scalar type = " << theTile->getScalarType() + << " Not supported by ossimMaxMosaic" << endl; + } + } + + return ossimRefPtr<ossimImageData>(); +} + +void ossimMaxMosaic::initialize() +{ + ossimImageCombiner::initialize(); + theTile = NULL; +} + +void ossimMaxMosaic::allocate() +{ + theTile = NULL; + + if( (getNumberOfInputs() > 0) && getInput(0) ) + { + theTile = ossimImageDataFactory::instance()->create(this, this); + theTile->initialize(); + } +} + +bool ossimMaxMosaic::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + return ossimImageCombiner::saveState(kwl, prefix); +} + +bool ossimMaxMosaic::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + return ossimImageCombiner::loadState(kwl, prefix); +} + +template <class T> ossimRefPtr<ossimImageData> ossimMaxMosaic::combineNorm( + T,// dummy template variable + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + ossimRefPtr<ossimImageData> destination = theTile; + + ossimRefPtr<ossimImageData> currentImageData = + getNextNormTile(0, tileRect, resLevel); + + if(!currentImageData) + { + return currentImageData; + } + + float** srcBands = new float*[theLargestNumberOfInputBands]; + float* srcBandsNullPix = new float[theLargestNumberOfInputBands]; + T** destBands = new T*[theLargestNumberOfInputBands]; + T* destBandsNullPix = new T[theLargestNumberOfInputBands]; + T* destBandsMinPix = new T[theLargestNumberOfInputBands]; + T* destBandsMaxPix = new T[theLargestNumberOfInputBands]; + + ossim_uint32 band; + ossim_uint32 upperBound = destination->getWidth()*destination->getHeight(); + ossim_uint32 minNumberOfBands = currentImageData->getNumberOfBands(); + for(band = 0; band < minNumberOfBands; ++band) + { + srcBands[band] = static_cast<float*>(currentImageData->getBuf(band)); + srcBandsNullPix[band] = static_cast<float>(currentImageData->getNullPix(band)); + + destBands[band] = static_cast<T*>(theTile->getBuf(band)); + destBandsNullPix[band] = static_cast<T>(theTile->getNullPix(band)); + destBandsMinPix[band] = static_cast<T>(theTile->getMinPix(band)); + destBandsMaxPix[band] = static_cast<T>(theTile->getMaxPix(band)); + } + // if the src is smaller than the destination in number + // of bands we will just duplicate the last band. + for(;band < theLargestNumberOfInputBands; ++band) + { + srcBands[band] = static_cast<float*>(srcBands[minNumberOfBands - 1]); + srcBandsNullPix[band] = static_cast<float>(currentImageData->getNullPix(minNumberOfBands - 1)); + + destBands[band] = static_cast<T*>(theTile->getBuf(band)); + destBandsNullPix[band] = static_cast<T>(theTile->getNullPix(band)); + destBandsMinPix[band] = static_cast<T>(theTile->getMinPix(band)); + destBandsMaxPix[band] = static_cast<T>(theTile->getMaxPix(band)); + } + // most of the time we will not overlap so let's + // copy the first tile into destination and check later. + // + ossim_uint32 tempBandIdx = 0; + for(band = 0; band < theTile->getNumberOfBands();++band) + { + if(band < currentImageData->getNumberOfBands()) + { + theTile->copyNormalizedBufferToTile(band, + (float*)currentImageData->getBuf(band)); + ++tempBandIdx; + } + else + { + if(tempBandIdx) + { + theTile->copyNormalizedBufferToTile(band, + (float*)currentImageData->getBuf(tempBandIdx-1)); + } + } + } + destination->validate(); + + currentImageData = getNextNormTile(tileRect, resLevel); + + while(currentImageData.valid()) + { + ossim_uint32 minNumberOfBands = currentImageData->getNumberOfBands(); + ossimDataObjectStatus currentStatus = currentImageData->getDataObjectStatus(); + ossimDataObjectStatus destinationStatus = destination->getDataObjectStatus(); + + if(destinationStatus == OSSIM_FULL) + { + return destination; + } + for(band = 0; band < minNumberOfBands; ++band) + { + srcBands[band] = static_cast<float*>(currentImageData->getBuf(band)); + srcBandsNullPix[band] = static_cast<float>(currentImageData->getNullPix(band)); + } + // if the src is smaller than the destination in number + // of bands we will just duplicate the last band. + for(;band < theLargestNumberOfInputBands; ++band) + { + srcBands[band] = srcBands[minNumberOfBands - 1]; + srcBandsNullPix[band] = static_cast<T>(currentImageData->getNullPix(minNumberOfBands - 1)); + } + + if((destinationStatus == OSSIM_EMPTY)&& + (currentStatus != OSSIM_EMPTY)&& + (currentStatus != OSSIM_NULL)) + { + ossim_uint32 upperBound = destination->getWidth()*destination->getHeight(); + for(band=0; band < theLargestNumberOfInputBands; ++band) + { + float delta = destBandsMaxPix[band] - destBandsMinPix[band]; + float minP = destBandsMinPix[band]; + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + destBands[band][offset] = (T)( minP + delta*srcBands[band][offset]); + } + } + } + else if((destinationStatus == OSSIM_PARTIAL)&& + (currentStatus != OSSIM_EMPTY)&& + (currentStatus != OSSIM_NULL)) + { + for(band = 0; band < theLargestNumberOfInputBands; ++band) + { + + float delta = destBandsMaxPix[band] - destBandsMinPix[band]; + float minP = destBandsMinPix[band]; + for(ossim_uint32 offset = 0; + offset < upperBound; + ++offset) + { + + if(destBands[band][offset] == destBandsNullPix[band]) + { + destBands[band][offset] = (T)(minP + delta*srcBands[band][offset]); + } + } + } + } + destination->validate(); + + currentImageData = getNextNormTile(tileRect, resLevel); + } + // Cleanup... + delete [] srcBands; + delete [] srcBandsNullPix; + delete [] destBands; + delete [] destBandsNullPix; + delete [] destBandsMinPix; + delete [] destBandsMaxPix; + + return destination; +} + +template <class T> ossimRefPtr<ossimImageData> ossimMaxMosaic::combine( + T,// dummy template variable + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + ossimRefPtr<ossimImageData> destination = theTile; + + ossimRefPtr<ossimImageData> currentImageData = + getNextTile(0, tileRect, resLevel); + + T** srcBands = new T*[theLargestNumberOfInputBands]; + T* srcBandsNullPix = new T[theLargestNumberOfInputBands]; + T** destBands = new T*[theLargestNumberOfInputBands]; + T* destBandsNullPix = new T[theLargestNumberOfInputBands]; + + ossim_uint32 band; + ossim_uint32 upperBound = destination->getWidth()*destination->getHeight(); + ossim_uint32 bandIndex = 0; + if(!currentImageData) + { + return currentImageData; + } + ossim_uint32 offset=0; + ossim_uint32 minNumberOfBands = currentImageData->getNumberOfBands(); + for(band = 0; band < minNumberOfBands; ++band) + { + srcBands[band] = static_cast<T*>(currentImageData->getBuf(band)); + destBands[band] = static_cast<T*>(theTile->getBuf(band)); + srcBandsNullPix[band] = static_cast<T>(currentImageData->getNullPix(band)); + destBandsNullPix[band] = static_cast<T>(theTile->getNullPix(band)); + } + // if the src is smaller than the destination in number + // of bands we will just duplicate the last band. + for(;band < theLargestNumberOfInputBands; ++band) + { + srcBands[band] = static_cast<T*>(srcBands[minNumberOfBands - 1]); + destBands[band] = static_cast<T*>(theTile->getBuf(band)); + srcBandsNullPix[band] = static_cast<T>(currentImageData->getNullPix(minNumberOfBands - 1)); + destBandsNullPix[band] = static_cast<T>(theTile->getNullPix(band)); + } + // most of the time we will not overlap so let's + // copy the first tile into destination and check later. + // + for(band = 0; band < theTile->getNumberOfBands();++band) + { + T* destBand = destBands[band]; + T* srcBand = srcBands[band]; + if(destBand&&srcBand) + { + for(offset = 0; offset < upperBound;++offset) + { + *destBand = *srcBand; + ++srcBand; ++destBand; + } + } + } + destination->setDataObjectStatus(currentImageData->getDataObjectStatus()); + + currentImageData = getNextTile(tileRect, + resLevel); + + while(currentImageData.valid()) + { + ossim_uint32 minNumberOfBands = currentImageData->getNumberOfBands(); + ossimDataObjectStatus currentStatus = currentImageData->getDataObjectStatus(); + ossimDataObjectStatus destinationStatus = destination->getDataObjectStatus(); + + for(band = 0; band < minNumberOfBands; ++band) + { + srcBands[band] = static_cast<T*>(currentImageData->getBuf(band)); + srcBandsNullPix[band] = static_cast<T>(currentImageData->getNullPix(band)); + } + // if the src is smaller than the destination in number + // of bands we will just duplicate the last band. + for(;band < theLargestNumberOfInputBands; ++band) + { + srcBands[band] = srcBands[minNumberOfBands - 1]; + srcBandsNullPix[band] = static_cast<T>(currentImageData->getNullPix(minNumberOfBands - 1)); + } + + + if((destinationStatus == OSSIM_PARTIAL)&& + (currentStatus != OSSIM_EMPTY)&& + (currentStatus != OSSIM_NULL)) + { + for(bandIndex = 0; bandIndex < theLargestNumberOfInputBands; ++bandIndex) + { + + for(ossim_uint32 offset = 0; + offset < upperBound; + ++offset) + { + if(srcBands[bandIndex][offset] > destBands[bandIndex][offset]) + { + destBands[bandIndex][offset] = srcBands[bandIndex][offset]; + } + } + } + } + else + { + ossim_uint32 upperBound = destination->getWidth()*destination->getHeight(); + for(ossim_uint32 band=0; band < theLargestNumberOfInputBands; ++band) + { + for(ossim_uint32 offset = 0; offset < upperBound; ++offset) + { + if(srcBands[band][offset] > destBands[band][offset]) + { + destBands[band][offset] = srcBands[band][offset]; + } + } + } + } + + destination->validate(); + + currentImageData = getNextTile(tileRect, resLevel); + } + // Cleanup... + delete [] srcBands; + delete [] srcBandsNullPix; + delete [] destBands; + delete [] destBandsNullPix; + return destination; +} + +ossimString ossimMaxMosaic::getShortName()const +{ + return ossimString("ossimMaxMosaic"); +} + +ossimString ossimMaxMosaic::getLongName()const +{ + return ossimString("Max Mosaic"); +} + +ossimString ossimMaxMosaic::getDescription()const +{ + return ossimString("Combiner which puts maximum dn value on image."); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimMaxMosaic.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimMaxMosaic.h new file mode 100644 index 0000000000..a53de26926 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimMaxMosaic.h @@ -0,0 +1,79 @@ +//******************************************************************* +// Copyright (C) 2005 SANZ Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Kenneth Melero (kmelero@sanz.com) +// +// Description: This combiner is designed to "float" the maximum pixel value +// of all inputs to the top of the mosaic output. +// +//************************************************************************* +// $Id: ossimMaxMosaic.h,v 1.1 2005/04/15 14:49:10 dburken Exp $ +#ifndef ossimMaxMosaic_HEADER +#define ossimMaxMosaic_HEADER + +#include <vector> +#include <imaging/tile_sources/ossimImageCombiner.h> + + +/** + * An image mosaic is a simple combiner that will + * just do a simple mosaic. It just checks NULL pix values until it finds a + * pixel that is not empty and copies it out to the output. The list will + * have same size tiles and have the same number of bands. + */ +class OSSIMDLLEXPORT ossimMaxMosaic : public ossimImageCombiner +{ +public: + ossimMaxMosaic(); + ossimMaxMosaic(const std::vector<ossimImageSource*>& inputSources); + virtual ~ossimMaxMosaic(); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& origin, + ossim_uint32 resLevel=0); + + virtual void initialize(); + + /** + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual ossimString getShortName() const; + virtual ossimString getLongName() const; + virtual ossimString getDescription()const; + +protected: + + /** + * Called on first getTile, will initialize all data needed. + */ + void allocate(); + + ossimRefPtr<ossimImageData> theTile; + + template <class T> ossimRefPtr<ossimImageData> combine( + T, // dummy template variable not used + const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + template <class T> ossimRefPtr<ossimImageData> combineNorm( + T, // dummy template variable not used + const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimMultiBandHistogramTileSource.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimMultiBandHistogramTileSource.cpp new file mode 100644 index 0000000000..8f29cb8003 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimMultiBandHistogramTileSource.cpp @@ -0,0 +1,371 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimMultiBandHistogramTileSource.cpp,v 1.6 2005/05/09 12:39:40 dburken Exp $ +#include <imaging/tile_sources/ossimMultiBandHistogramTileSource.h> +#include <base/data_types/ossimMultiResLevelHistogram.h> +#include <base/data_types/ossimMultiBandHistogram.h> +#include <base/data_types/ossimHistogram.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimKeyword.h> +#include <base/common/ossimCommon.h> +#include <imaging/ossimImageData.h> +#include <base/context/ossimNotifyContext.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <algorithm> + +static const char* MIN_VALUE_PERCENT_KW = "min_percent"; +static const char* MAX_VALUE_PERCENT_KW = "max_percent"; +static const char* ALGORITHM_KW = "algorithm"; + +RTTI_DEF1(ossimMultiBandHistogramTileSource, + "ossimMultiBandHistogramTileSource", + ossimImageSourceHistogramFilter) + +ossimMultiBandHistogramTileSource::ossimMultiBandHistogramTileSource() + : ossimImageSourceHistogramFilter(), + theTile(NULL), + theAlgorithm(OSSIM_HISTOGRAM_LINEAR_STRETCH_ALGORITHM) +{ + disableSource(); +} + +ossimMultiBandHistogramTileSource::ossimMultiBandHistogramTileSource(double minValuePercent, + double maxValuePercent, + ossimImageSource* inputSource, + ossimMultiResLevelHistogram* histogram) + : ossimImageSourceHistogramFilter(inputSource, histogram), + theTile(NULL), + theAlgorithm(OSSIM_HISTOGRAM_LINEAR_STRETCH_ALGORITHM) +{ + disableSource(); +} + +ossimMultiBandHistogramTileSource::~ossimMultiBandHistogramTileSource() +{ +} + +ossimRefPtr<ossimImageData> ossimMultiBandHistogramTileSource::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if(!theInputConnection) return NULL; + + ossimRefPtr<ossimImageData> inputTile = theInputConnection->getTile(tileRect, + resLevel); + + if(!isSourceEnabled() || !inputTile.valid()) + { + return inputTile; + } + + if(!theTile.valid()) + { + allocate(); // First time through... + } + + if( !theTile.valid() || + !theMinValuePercentArray.size() || + !theMaxValuePercentArray.size() ) + { + return inputTile; + } + + theTile->setImageRectangle(tileRect); + if(inputTile->getBuf()&& + (inputTile->getDataObjectStatus()!=OSSIM_EMPTY)) + { + theTile->loadTile(inputTile.get()); + switch(inputTile->getScalarType()) + { + case OSSIM_UCHAR: + { + return runLinearStretchAlgorithm((ossim_uint8)0, + theTile); + } + case OSSIM_USHORT16: + case OSSIM_USHORT11: + { + return runLinearStretchAlgorithm((ossim_uint16)0, + theTile); + } + case OSSIM_SSHORT16: + { + return runLinearStretchAlgorithm(static_cast<ossim_sint16>(0), + theTile); + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + return runLinearStretchAlgorithm(static_cast<double>(0), + theTile); + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + return runLinearStretchAlgorithm(static_cast<float>(0), + theTile); + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + ossimSetError("ossimMultiBandHistogramTileSource", + ossimErrorCodes::OSSIM_ERROR, + "Unknown scalar type"); + break; + } + } + theTile->validate(); + return theTile; + } + + return inputTile; +} + +void ossimMultiBandHistogramTileSource::initialize() +{ + ossimImageSourceHistogramFilter::initialize(); + + // Force an allocate on the next getTile. + theTile = NULL; +} + +void ossimMultiBandHistogramTileSource::allocate() +{ + theTile = ossimImageDataFactory::instance()->create(this, this); + + if(theTile.valid()) + { + theTile->initialize(); + + ossim_uint32 numberOfBands = theTile->getNumberOfBands(); + ossim_uint32 i = 0; + if(numberOfBands) + { + std::vector<double> copyArray; + + if(numberOfBands > theMinValuePercentArray.size()) + { + copyArray = theMinValuePercentArray; + theMinValuePercentArray.resize(numberOfBands); + if(numberOfBands < copyArray.size()) + { + std::copy(copyArray.begin(), + copyArray.end(), + theMinValuePercentArray.begin()); + } + else + { + std::copy(copyArray.begin(), + copyArray.begin() + copyArray.size(), + theMinValuePercentArray.begin()); + } + } + if(numberOfBands != theMaxValuePercentArray.size()) + { + copyArray = theMaxValuePercentArray; + theMaxValuePercentArray.resize(numberOfBands); + if(numberOfBands < copyArray.size()) + { + std::copy(copyArray.begin(), + copyArray.end(), + theMaxValuePercentArray.begin()); + } + else + { + std::copy(copyArray.begin(), + copyArray.begin() + copyArray.size(), + theMaxValuePercentArray.begin()); + } + } + if(numberOfBands > theMinValuePercentArray.size()) + { + for(i = theMinValuePercentArray.size(); i < numberOfBands; ++i) + { + theMinValuePercentArray[i] = 0.0; + theMaxValuePercentArray[i] = 0.0; + } + } + } + } +} + +bool ossimMultiBandHistogramTileSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + theMinValuePercentArray.clear(); + theMaxValuePercentArray.clear(); + if(ossimImageSourceHistogramFilter::loadState(kwl, prefix)) + { + ossimNotify(ossimNotifyLevel_INFO) << "ossimMultiBandHistogramTileSource::loadState INFO: histogram filter was loaded" << std::endl; + ossimString regExpression = ossimString("^(") + ossimString(prefix) + ossimString(MIN_VALUE_PERCENT_KW) + ossimString("[0-9]+)"); + + long numberOfSources = kwl.getNumberOfSubstringKeys(regExpression); + + unsigned long numberOfMatches = 0; + ossim_uint32 i = 0; + while(numberOfMatches < static_cast<unsigned long>(numberOfSources)) + { + ossimString key = ossimString(MIN_VALUE_PERCENT_KW) + ossimString::toString(i); + const char* value = kwl.find(prefix, key); + if(value) + { + theMinValuePercentArray.push_back(ossimString(value).toDouble()); + ++numberOfMatches; + } + ++i; + } + + numberOfMatches = 0; + i = 0; + regExpression = ossimString("^(") + ossimString(prefix) + ossimString(MAX_VALUE_PERCENT_KW) + ossimString("[0-9]+)"); + numberOfSources = kwl.getNumberOfSubstringKeys(regExpression); + while(numberOfMatches < static_cast<unsigned long>(numberOfSources)) + { + ossimString key = ossimString(MAX_VALUE_PERCENT_KW) + ossimString::toString(i); + const char* value = kwl.find(prefix, key); + + if(value) + { + theMaxValuePercentArray.push_back(ossimString(value).toDouble()); + ++numberOfMatches; + } + ++i; + } + + ossimString algorithm = kwl.find(prefix, + ALGORITHM_KW); + algorithm = algorithm.downcase(); + theAlgorithm = OSSIM_HISTOGRAM_LINEAR_STRETCH_ALGORITHM; + if(algorithm != "") + { + if(algorithm.contains("linear")) + { + theAlgorithm = OSSIM_HISTOGRAM_LINEAR_STRETCH_ALGORITHM; + } + } + } + return true; +} + +bool ossimMultiBandHistogramTileSource::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimImageSourceHistogramFilter::saveState(kwl, prefix); + ossim_int32 i = 0; + + for(i = 0; i< (ossim_int32)theMinValuePercentArray.size();++i) + { + kwl.add(prefix, + ossimString(MIN_VALUE_PERCENT_KW) + ossimString::toString(i), + theMinValuePercentArray[i], + true); + } + for(i = 0; i< (ossim_int32)theMaxValuePercentArray.size();++i) + { + kwl.add(prefix, + ossimString(MAX_VALUE_PERCENT_KW) + ossimString::toString(i), + theMaxValuePercentArray[i], + true); + } + ossimString algorithmString; + + switch(theAlgorithm) + { + case OSSIM_HISTOGRAM_LINEAR_STRETCH_ALGORITHM: + { + algorithmString = "linear_stretch"; + break; + } + case OSSIM_HISTOGRAM_NO_ALGORITHM: + { + algorithmString = "none"; + break; + } + default: + { + algorithmString = "none"; + break; + } + } + + kwl.add(prefix, + ALGORITHM_KW, + algorithmString.c_str(), + true); + + return true; +} + +template <class T> +ossimRefPtr<ossimImageData> ossimMultiBandHistogramTileSource::runLinearStretchAlgorithm(T dummyVariable, + ossimRefPtr<ossimImageData>& tile) +{ + if(!getHistogram()) + { + return tile; + } + + ossimMultiBandHistogram* histo = getHistogram()->getMultiBandHistogram(theCurrentResLevel); + if(histo) + { + ossim_uint32 maxBands = ( (histo->getNumberOfBands() > + tile->getNumberOfBands())? + tile->getNumberOfBands(): + histo->getNumberOfBands()); + + long offsetUpperBound = tile->getHeight()*tile->getWidth(); + + for(ossim_uint32 band = 0; band < maxBands; ++band) + { + ossimHistogram* h = histo->getHistogram(band); + + T* buf = static_cast<T*>(tile->getBuf(band)); + T np = static_cast<T>(tile->getNullPix(band)); + T minPix = static_cast<T>(tile->getMinPix(band)); + T maxPix = static_cast<T>(tile->getMaxPix(band)); + T range = (maxPix - minPix); + if(h&&buf) + { + + double maxClip = minPix + (h->HighClipVal(theMaxValuePercentArray[band])/(double)h->GetRes())*range; + double minClip = minPix + (h->LowClipVal(theMinValuePercentArray[band])/(double)h->GetRes())*range; + double delta = (maxClip - minClip); + + if(fabs(delta) > 0.0) + { + for(long offset = 0; offset < offsetUpperBound; ++offset) + { + if(buf[offset] != np) + { + if(buf[offset] < minClip) + { + buf[offset] = minPix; + } + else if(buf[offset] > maxClip) + { + buf[offset] = maxPix; + } + else + { + T value = static_cast<T>(minPix + ((buf[offset] - minClip)/delta)*range); + buf[offset] = value>maxPix?maxPix:value; + } + } + } + } + } + } + + tile->validate(); + } + + return tile; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimMultiBandHistogramTileSource.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimMultiBandHistogramTileSource.h new file mode 100644 index 0000000000..72e4b5bad5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimMultiBandHistogramTileSource.h @@ -0,0 +1,103 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimMultiBandHistogramTileSource.h,v 1.4 2005/02/11 15:07:33 dburken Exp $ +#ifndef ossimMultiBandHistogramTileSource_HEADER +#define ossimMultiBandHistogramTileSource_HEADER +#include "ossimImageSourceHistogramFilter.h" +#include <vector> +class OSSIMDLLEXPORT ossimMultiBandHistogramTileSource : public ossimImageSourceHistogramFilter +{ +public: + enum ossimMultiBandHistogramAlgorithm + { + OSSIM_HISTOGRAM_NO_ALGORITHM = 0, + OSSIM_HISTOGRAM_LINEAR_STRETCH_ALGORITHM = 1 + }; + ossimMultiBandHistogramTileSource(); + ossimMultiBandHistogramTileSource(double minValuePercent, + double maxValuePercent, + ossimImageSource* inputSource, + ossimMultiResLevelHistogram* histogram); + virtual ~ossimMultiBandHistogramTileSource(); + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + + virtual void setMinValuePercent(const std::vector<double>& arrayPercents) + { + theMinValuePercentArray = arrayPercents; + } + virtual void setMaxValuePercent(const std::vector<double>& arrayPercents) + { + theMaxValuePercentArray = arrayPercents; + } + virtual void setMinValuePercent(ossim_uint32 arrayIndex, + double minValue) + { + if(arrayIndex < theMinValuePercentArray.size()) + { + theMinValuePercentArray[arrayIndex] = minValue; + } + } + virtual void setMaxValuePercent(ossim_uint32 arrayIndex, + double maxValue) + { + if(arrayIndex < theMaxValuePercentArray.size()) + { + theMaxValuePercentArray[arrayIndex] = maxValue; + } + } + virtual double getMinValuePercent(ossim_uint32 arrayIndex)const + { + if(arrayIndex < theMinValuePercentArray.size()) + { + return theMinValuePercentArray[arrayIndex]; + } + return OSSIM_DBL_NAN; + } + virtual double getMaxValuePercent(ossim_uint32 arrayIndex)const + { + if(arrayIndex < theMaxValuePercentArray.size()) + { + return theMaxValuePercentArray[arrayIndex]; + } + return OSSIM_DBL_NAN; + } + virtual ossim_uint32 getNumberOfMinValues()const + { + return theMinValuePercentArray.size(); + } + virtual ossim_uint32 getNumberOfMaxValues()const + { + return theMinValuePercentArray.size(); + } + virtual void initialize(); + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + +protected: + + void allocate(); + + ossimRefPtr<ossimImageData> theTile; + ossimMultiBandHistogramAlgorithm theAlgorithm; + std::vector<double> theMinValuePercentArray; + std::vector<double> theMaxValuePercentArray; + + template <class T> ossimRefPtr<ossimImageData> runLinearStretchAlgorithm( + T dummyVariable, + ossimRefPtr<ossimImageData>& tile); + +TYPE_DATA +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimNBandToIndexFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimNBandToIndexFilter.cpp new file mode 100644 index 0000000000..1155004034 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimNBandToIndexFilter.cpp @@ -0,0 +1,551 @@ +//******************************************************************* +// Copyright (C) 2005 Garrett Potts +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimNBandToIndexFilter.cpp,v 1.4 2005/11/09 14:31:23 gpotts Exp $ + +#include <imaging/tile_sources/ossimNBandToIndexFilter.h> +#include <imaging/ossimImageData.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <base/common/ossimKeywordNames.h> +#include <base/property/ossimFilenameProperty.h> +#include <base/property/ossimBooleanProperty.h> +#include <base/context/ossimNotifyContext.h> + + +static const char* KEEP_QUANTIZED_VALUE_FLAG_KW = "keep_quantized_value_flag"; + +RTTI_DEF1(ossimNBandToIndexFilter, + "ossimNBandToIndexFilter", + ossimImageSourceFilter); + +ossimNBandToIndexFilter::ossimNBandToIndexFilter() + :ossimImageSourceFilter(), + theLut(0), + theTile(0), + theKeepQuantizedValueFlag(false) +{ +} + +ossimNBandToIndexFilter::~ossimNBandToIndexFilter() +{ +} + +void ossimNBandToIndexFilter::initialize() +{ + ossimImageSourceFilter::initialize(); + + // Force allocate on next getTile. + theTile = 0; + if(theLut.valid()) + { + if(theKeepQuantizedValueFlag) + { + ossimNBandLutDataObject::LUT_ENTRY_TYPE minValue; + ossimNBandLutDataObject::LUT_ENTRY_TYPE maxValue; + ossim_uint32 bands = theLut->getNumberOfBands(); + ossim_uint32 idx = 0; + if(theMinValues.size() != bands) + { + theMinValues.resize(bands); + theMaxValues.resize(bands); + theNullValues.resize(bands); + } + std::fill(theNullValues.begin(), + theNullValues.end(), 0); + for(idx = 0; idx < bands; ++idx) + { + theLut->getMinMax(idx, minValue, maxValue); + theMinValues[idx] = minValue; + theMaxValues[idx] = maxValue; + theNullValues[idx] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(ossimImageSourceFilter::getNullPixelValue(idx)); + } + } + else + { + if(theMinValues.size() != 1) + { + theMinValues.resize(1); + theMaxValues.resize(1); + theNullValues.resize(1); + } + theMinValues[0] = 0; + theMaxValues[0] = theLut->getNumberOfEntries()-1; + theNullValues[0] = theLut->getNullPixelIndex(); + } + } +} + +void ossimNBandToIndexFilter::allocate() +{ + theTile = 0; + + if(isSourceEnabled()&&theInputConnection) + { + theTile = ossimImageDataFactory::instance()->create(this, this); + if(theTile.valid()) + { + theTile->initialize(); + } + } +} + +void ossimNBandToIndexFilter::disableSource() +{ + ossimImageSourceFilter::disableSource(); + theTile = 0; +} + +ossimRefPtr<ossimImageData> ossimNBandToIndexFilter::getTile(const ossimIrect& origin, + ossim_uint32 resLevel) +{ + if(!isSourceEnabled()) + { + return ossimImageSourceFilter::getTile(origin, resLevel); + } + if(!theInputConnection) + { + return ossimRefPtr<ossimImageData>(); + } + + if(!theTile.valid()) + { + allocate(); + } + + ossimRefPtr<ossimImageData> input = theInputConnection->getTile(origin, + resLevel); + + if(!theTile.valid() || !input.valid()) + { + return input; + } + + theTile->setImageRectangle(origin); + theTile->setDataObjectStatus(OSSIM_FULL); + theTile->makeBlank(); + + return convertInputTile(input.get()); +} + +ossimRefPtr<ossimImageData> ossimNBandToIndexFilter::convertInputTile(ossimImageData* tile) +{ + switch(getOutputScalarType()) + { + case OSSIM_UINT8: + { + return convertOutputTileTemplate((ossim_uint8)0, + tile); + break; + } + case OSSIM_UINT16: + { + return convertOutputTileTemplate((ossim_uint16)0, + tile); + break; + } + case OSSIM_UINT32: + { + return convertOutputTileTemplate((ossim_uint32)0, + tile); + break; + } + default: + { + ossimNotify(ossimNotifyLevel_WARN) << "ossimNBandToIndexFilter::convertInputTile: Unsupported scalar type for conversion" << std::endl; + } + } + + return theTile; +} + +template <class T> +ossimRefPtr<ossimImageData> ossimNBandToIndexFilter::convertOutputTileTemplate(T outputDummy, + ossimImageData* inputTile) +{ + switch(inputTile->getScalarType()) + { + case OSSIM_UINT8: + { + return convertInputTileToOutputTemplate((ossim_uint8)0, + outputDummy, + inputTile); + break; + } + case OSSIM_SINT8: + { + return convertInputTileToOutputTemplate((ossim_sint8)0, + outputDummy, + inputTile); + } + case OSSIM_UINT16: + { + return convertInputTileToOutputTemplate((ossim_uint16)0, + outputDummy, + inputTile); + } + case OSSIM_SINT32: + { + return convertInputTileToOutputTemplate((ossim_sint32)0, + outputDummy, + inputTile); + } + case OSSIM_UINT32: + { + return convertInputTileToOutputTemplate((ossim_uint32)0, + outputDummy, + inputTile); + } + default: + { + ossimNotify(ossimNotifyLevel_WARN) << "convertInputTileToOutputTemplate::convertOutputTileTemplate: Unsupported scalar type for conversion." << std::endl; + } + } + + return theTile; +} + +template <class T1, class T2> +ossimRefPtr<ossimImageData> ossimNBandToIndexFilter::convertInputTileToOutputTemplate(T1 inputDummy, + T2 outputDummy, + ossimImageData* inputTile) +{ + if (!inputTile) + { + return theTile; + } + + const ossim_uint32 BANDS = inputTile->getNumberOfBands(); + + if (!BANDS) + { + return theTile; + } +// T2** outBand = (T2*)theTile->getBuf(); + + ossim_uint32 numberOfBands = theLut->getNumberOfBands(); + + ossimNBandLutDataObject::LUT_ENTRY_TYPE* bandValues = new ossimNBandLutDataObject::LUT_ENTRY_TYPE[numberOfBands]; + + memset(bandValues, 0, sizeof(ossimNBandLutDataObject::LUT_ENTRY_TYPE)*numberOfBands); + numberOfBands = ossimMin(BANDS, + numberOfBands); + if(!numberOfBands) return theTile; + T1** band = new T1*[numberOfBands]; + T2** outBand = new T2*[numberOfBands]; + ossim_int32 idx = 0; + + for(idx = 0; idx < (ossim_int32)numberOfBands; ++idx) + { + band[idx] = (T1*)inputTile->getBuf(idx); + outBand[idx] = (T2*)theTile->getBuf(idx); + } + if(band[0]) + { + if(inputTile->getDataObjectStatus() == OSSIM_FULL) + { + ossim_uint32 upper = inputTile->getWidth()*inputTile->getHeight(); + ossim_uint32 idx2=0; + for(ossim_uint32 offset = 0; offset < upper; ++offset) + { + for(idx2 = 0; idx2 < numberOfBands; ++idx2) + { + bandValues[idx2] = *band[idx2]; + ++band[idx2]; + } + idx = theLut->findIndex(bandValues); + + if(!theKeepQuantizedValueFlag) + { + *outBand[0] = (T2)idx; + ++outBand[0]; + } + else + { + for(idx2 = 0; idx2 < numberOfBands; ++idx2) + { + if(idx >=0) + { + *outBand[idx2] = (T2)(*theLut)[idx][idx2]; + ++outBand[idx2]; + } + } + } + } + } + else if(inputTile->getDataObjectStatus() == OSSIM_PARTIAL) + { + ossim_uint32 upper = inputTile->getWidth()*inputTile->getHeight(); + ossim_uint32 idx2=0; + for(ossim_uint32 offset = 0; offset < upper; ++offset) + { + for(idx2 = 0; idx2 < numberOfBands; ++idx2) + { + bandValues[idx2] = *band[idx2]; + ++band[idx2]; + } + idx = -1; + if(!inputTile->isNull(offset)) + { + idx = theLut->findIndex(bandValues); + } + if(!theKeepQuantizedValueFlag) + { + if(idx>=0) + { + *outBand[0] = (T2)idx; + } + ++outBand[0]; + } + else + { + for(idx2 = 0; idx2 < numberOfBands; ++idx2) + { + if(idx >=0) + { + if(idx>=0) + { + *outBand[idx2] = (T2)(*theLut)[idx][idx2]; + } + } + ++outBand[idx2]; + } + } + } + } + } + if(theKeepQuantizedValueFlag) + { + theTile->validate(); + } + else + { + theTile->setDataObjectStatus(OSSIM_FULL); + } + return theTile; +} + +bool ossimNBandToIndexFilter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimString newPrefix = prefix; + newPrefix = newPrefix + "lut."; + + if(theLut.valid()) + { + theLut->saveState(kwl, newPrefix.c_str()); + } + + kwl.add(prefix, + KEEP_QUANTIZED_VALUE_FLAG_KW, + theKeepQuantizedValueFlag?"true":"false", + true); + + return ossimImageSourceFilter::saveState(kwl, prefix); +} + +bool ossimNBandToIndexFilter::loadState(const ossimKeywordlist& kwl, const char* prefix) +{ + ossimString newPrefix = prefix; + newPrefix = newPrefix + "lut."; + + if(!theLut.valid()) + { + theLut = new ossimNBandLutDataObject; + } + theLut->loadState(kwl, newPrefix.c_str()); + + const char* flag = kwl.find(prefix, KEEP_QUANTIZED_VALUE_FLAG_KW); + if(flag) + { + theKeepQuantizedValueFlag = ossimString(flag).toBool(); + } + return ossimImageSourceFilter::loadState(kwl, prefix); +} + +bool ossimNBandToIndexFilter::isSourceEnabled()const +{ + bool result = ossimSource::isSourceEnabled()&&theInputConnection; + + // only support 3 band integral values, no floating point for now. + // + if(result) + { + + ossimScalarType inputScalarType = theInputConnection->getOutputScalarType(); + if(!theLut.valid() || + (theLut->getNumberOfEntries()<1)|| + (inputScalarType==OSSIM_FLOAT32)|| + (inputScalarType==OSSIM_FLOAT64)|| + (theInputConnection->getNumberOfOutputBands()!=3)) + { + result = false; + } + } + + return result; +} + +ossim_uint32 ossimNBandToIndexFilter::getNumberOfOutputBands() const +{ + if(isSourceEnabled()) + { + if(theKeepQuantizedValueFlag) + { + if(theLut.valid()) + { + return theLut->getNumberOfBands(); + } + } + else + { + return 1; + } + } + + return ossimImageSourceFilter::getNumberOfOutputBands(); +} + +ossimScalarType ossimNBandToIndexFilter::getOutputScalarType() const +{ + if(isSourceEnabled()) + { + + ossim_uint32 numberOfEntries = theLut->getNumberOfEntries(); + + if(numberOfEntries < 257) + { + return OSSIM_UCHAR; + } + else if(numberOfEntries < 65537) + { + return OSSIM_UINT16; + } + else + { + return OSSIM_UINT32; + } + } + + return ossimImageSourceFilter::getOutputScalarType(); +} + +void ossimNBandToIndexFilter::setLut(ossimNBandLutDataObject& lut) +{ + theLut = new ossimNBandLutDataObject(lut); +} + +double ossimNBandToIndexFilter::getNullPixelValue(ossim_uint32 band)const +{ + if(isSourceEnabled()) + { + if(theLut->getNullPixelIndex() >= 0) + { + std::cout << "RETURNING NULL" << std::endl; + return theLut->getNullPixelIndex(); + } + } + + return ossimImageSourceFilter::getNullPixelValue(band); +} + +double ossimNBandToIndexFilter::getMinPixelValue(ossim_uint32 band)const +{ + if(isSourceEnabled()) + { + if(band < theMinValues.size()) + { + return (double)theMinValues[band]; + } + } +// if(isSourceEnabled()) +// { +// if(getNullPixelValue() != 0) +// { +// return 0; +// } +// else +// { +// return 1; +// } +// return 0; +// } + + return ossimImageSourceFilter::getMinPixelValue(); +} + +double ossimNBandToIndexFilter::getMaxPixelValue(ossim_uint32 band)const +{ + if(isSourceEnabled()) + { + if(band < theMaxValues.size()) + { + return (double)theMaxValues[band]; + } +// if(theLut->getNullPixelIndex() != ((ossim_int32)(theLut->getNumberOfEntries())-1)) +// { +// return theLut->getNumberOfEntries(); +// } +// else +// { +// return (theLut->getNumberOfEntries()-1); +// } + } + + return ossimImageSourceFilter::getMaxPixelValue(); +} + +void ossimNBandToIndexFilter::setProperty(ossimRefPtr<ossimProperty> property) +{ + if(property->getName() == ossimKeywordNames::FILENAME_KW) + { + ossimKeywordlist kwl; + if(kwl.addFile(ossimFilename(property->valueToString()))) + { + theLut = new ossimNBandLutDataObject; + theLut->loadState(kwl); + } + } + else if(property->getName() == KEEP_QUANTIZED_VALUE_FLAG_KW) + { + theKeepQuantizedValueFlag = property->valueToString().toBool(); + } + else + { + ossimImageSourceFilter::setProperty(property); + } +} + +ossimRefPtr<ossimProperty> ossimNBandToIndexFilter::getProperty(const ossimString& name)const +{ + if(name == ossimKeywordNames::FILENAME_KW) + { + ossimFilenameProperty* property = new ossimFilenameProperty(name, theLutFilename); + property->setIoType(ossimFilenameProperty::ossimFilenamePropertyIoType_INPUT); + property->setCacheRefreshBit(); + + return property; + } + else if(name == KEEP_QUANTIZED_VALUE_FLAG_KW) + { + ossimBooleanProperty* property = new ossimBooleanProperty(name, theKeepQuantizedValueFlag); + property->setCacheRefreshBit(); + + return property; + } + return ossimImageSourceFilter::getProperty(name); +} + +void ossimNBandToIndexFilter::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + ossimImageSourceFilter::getPropertyNames(propertyNames); + + propertyNames.push_back(ossimKeywordNames::FILENAME_KW); + propertyNames.push_back(KEEP_QUANTIZED_VALUE_FLAG_KW); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimNBandToIndexFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimNBandToIndexFilter.h new file mode 100644 index 0000000000..4581952afa --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimNBandToIndexFilter.h @@ -0,0 +1,129 @@ +//******************************************************************* +// Copyright (C) 2005 Garrett Potts +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimNBandToIndexFilter.h,v 1.3 2005/11/09 14:31:23 gpotts Exp $ +#ifndef ossimNBandToIndexFilter_HEADER +#define ossimNBandToIndexFilter_HEADER +#include <base/common/ossimNBandLutDataObject.h> +#include <base/data_types/ossimFilename.h> +#include <imaging/tile_sources/ossimImageSourceFilter.h> +#include <vector> + +class ossimImageData; + +/*! + * It will map the input data to an 8-bit index table. The table + * <pre> + * + * Example keyword list: + * + * type: ossimNBandToIndexFilter + * + * If you want to load from a file then just do: + * + * lut.filename: <full path to lut file> + * + * If you have the lut table in line then it must look like this: + * + * lut.entry0: 204 102 1 + * lut.entry1: 255 204 153 + * lut.entry2: 51 204 204 + * lut.number_of_entries: 3 + * lut.type: ossimNBandLutDataObject + * + * </pre> + */ +class OSSIM_DLL ossimNBandToIndexFilter : public ossimImageSourceFilter +{ +public: + /*! + * Initializes the min value to 0 and the max value to 4000. + */ + ossimNBandToIndexFilter(); + virtual ~ossimNBandToIndexFilter(); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& origin, + ossim_uint32 resLevel=0); + + virtual ossim_uint32 getNumberOfOutputBands() const; + + virtual ossimScalarType getOutputScalarType() const; + + void setLut(ossimNBandLutDataObject& lut); + + void setLut(const ossimFilename& file); + + virtual bool isSourceEnabled()const; + virtual void disableSource(); + + virtual double getNullPixelValue(ossim_uint32 band=0)const; + + virtual double getMinPixelValue(ossim_uint32 band=0)const; + + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + + virtual void initialize(); + + /*! + * Saves the state of this object. + */ + virtual bool saveState(ossimKeywordlist& kwl, const char* prefix=0)const; + + /*! + * Loads the state of this object. + */ + virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix=0); + + /** + * Will set the property whose name matches the argument + * "property->getName()". + * + * @param property Object containing property to set. + */ + virtual void setProperty(ossimRefPtr<ossimProperty> property); + + /** + * @param name Name of property to return. + * + * @returns A pointer to a property object which matches "name". Returns + * NULL if no match is found. + */ + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + + /** + * Pushes this's names onto the list of property names. + * + * @param propertyNames array to add this's property names to. + */ + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + +protected: + void allocate(); + + + virtual ossimRefPtr<ossimImageData> convertInputTile(ossimImageData* inputTile); + + template <class T> ossimRefPtr<ossimImageData> convertOutputTileTemplate(T inputDummy, + ossimImageData* inputTile); + template <class T1, class T2> ossimRefPtr<ossimImageData> convertInputTileToOutputTemplate(T1 inputDummy, + T2 outputDummy, + ossimImageData* inputTile); + + ossimRefPtr<ossimNBandLutDataObject> theLut; + ossimRefPtr<ossimImageData> theTile; + ossimFilename theLutFilename; + bool theKeepQuantizedValueFlag; + std::vector<ossimNBandLutDataObject::LUT_ENTRY_TYPE> theMinValues; + std::vector<ossimNBandLutDataObject::LUT_ENTRY_TYPE> theMaxValues; + std::vector<ossimNBandLutDataObject::LUT_ENTRY_TYPE> theNullValues; +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimOrthoImageMosaic.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimOrthoImageMosaic.cpp new file mode 100644 index 0000000000..1f36e5f70c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimOrthoImageMosaic.cpp @@ -0,0 +1,416 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimOrthoImageMosaic.cpp,v 1.26 2005/05/12 01:19:54 dburken Exp $ +#include <imaging/tile_sources/ossimOrthoImageMosaic.h> +#include <base/common/ossimKeywordNames.h> +#include <base/common/ossimTrace.h> +#include <projections/map_projections/ossimMapProjection.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> + + +static ossimTrace traceDebug ("ossimOrthoImageMosaic:debug"); + +RTTI_DEF1(ossimOrthoImageMosaic, "ossimOrthoImageMosaic", ossimImageMosaic); + +ossimOrthoImageMosaic::ossimOrthoImageMosaic() + :ossimImageMosaic() +{ + theDelta.makeNan(); + theUpperLeftTie.makeNan(); +} + +ossimOrthoImageMosaic::ossimOrthoImageMosaic(const std::vector<ossimImageSource*>& inputSources) + :ossimImageMosaic(inputSources) +{ + theDelta.makeNan(); + theUpperLeftTie.makeNan(); +} + +ossimOrthoImageMosaic::~ossimOrthoImageMosaic() +{ +} + +ossim_uint32 ossimOrthoImageMosaic::getNumberOfOverlappingImages(const ossimIrect& rect, + ossim_uint32 resLevel)const +{ + ossim_uint32 result = 0; + for(ossim_uint32 i = 0; i < theInputTiePoints.size(); ++i) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + getInput(i)); + if(interface&& + !theInputTiePoints[i].hasNans()) + { + ossimIrect tempRect = getRelativeRect(i, resLevel); + + if(!tempRect.hasNans()) + { + if(tempRect.intersects(rect)) + { + ++result; + } + } + } + } + + return 0; +} + +void ossimOrthoImageMosaic::getOverlappingImages(std::vector<ossim_uint32>& result, + const ossimIrect& rect, + ossim_uint32 resLevel)const +{ + result.clear(); + for(ossim_uint32 i = 0; i < theInputTiePoints.size(); ++i) + { + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + getInput(i)); + if(interface&& + !theInputTiePoints[i].hasNans()) + { + ossimIrect tempRect = getRelativeRect(i, resLevel); + + if(!tempRect.hasNans()) + { + if(tempRect.intersects(rect)) + { + result.push_back(i); + } + } + } + } +} + +bool ossimOrthoImageMosaic::getImageGeometry(ossimKeywordlist& kwl, + const char* prefix) +{ + bool result = true; + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(interface) + { + interface->getImageGeometry(kwl, prefix); + if(theUnits == "degrees") + { + kwl.add(prefix, + ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LAT, + theDelta.y, + true); + kwl.add(prefix, + ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LON, + theDelta.x, + true); + kwl.add(prefix, + ossimKeywordNames::TIE_POINT_LAT_KW, + theUpperLeftTie.y, + true); + kwl.add(prefix, + ossimKeywordNames::TIE_POINT_LON_KW, + theUpperLeftTie.x, + true); + kwl.remove(prefix, ossimKeywordNames::TIE_POINT_EASTING_KW); + kwl.remove(prefix, ossimKeywordNames::TIE_POINT_NORTHING_KW); + + } + else if(theUnits == "meters") + { + kwl.add(prefix, + ossimKeywordNames::METERS_PER_PIXEL_X_KW, + theDelta.x, + true); + kwl.add(prefix, + ossimKeywordNames::METERS_PER_PIXEL_Y_KW, + theDelta.x, + true); + kwl.add(prefix, + ossimKeywordNames::TIE_POINT_EASTING_KW, + theUpperLeftTie.x, + true); + kwl.add(prefix, + ossimKeywordNames::TIE_POINT_NORTHING_KW, + theUpperLeftTie.y, + true); + kwl.remove(prefix, ossimKeywordNames::TIE_POINT_LAT_KW); + kwl.remove(prefix, ossimKeywordNames::TIE_POINT_LON_KW); + } + else + { + result = false; + } + } + + return result; +} + +ossimIrect ossimOrthoImageMosaic::getBoundingRect(ossim_uint32 resLevel) const +{ + ossimDpt decimation; + + decimation.makeNan(); + + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(interface) + { + interface->getDecimationFactor(resLevel, + decimation); + } + if(decimation.hasNans()) + { + return theBoundingRect; + } + return theBoundingRect*decimation; +} + +void ossimOrthoImageMosaic::initialize() +{ + theInputTiePoints.clear(); + theDelta.makeNan(); + theUpperLeftTie.makeNan(); + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimOrthoImageMosaic::initialize() DEBUG: Entered..." + << "Number of inputs = " << getNumberOfInputs() + << std::endl; + } + if(getNumberOfInputs()) + { + theInputTiePoints.resize(getNumberOfInputs()); + for(ossim_uint32 i = 0; i < getNumberOfInputs(); ++i) + { + ossimImageSourceInterface *interface = + PTR_CAST(ossimImageSourceInterface, getInput(i)); + theInputTiePoints[i].makeNan(); + if(interface) + { + ossimKeywordlist kwl; + + bool status = interface->getImageGeometry(kwl); + if(status) + { + ossimProjection* prj = ossimProjectionFactoryRegistry::instance()->createProjection(kwl); + ossimMapProjection* mapPrj = PTR_CAST(ossimMapProjection, prj); + if(mapPrj) + { + if(!mapPrj->isGeographic()) + { + theUnits = "meters"; + theDelta = mapPrj->getMetersPerPixel(); + } + else + { + theUnits = "degrees"; + theDelta = mapPrj->getDecimalDegreesPerPixel(); + } + if(theUnits == "degrees") + { + theInputTiePoints[i].x = mapPrj->getUlGpt().lond(); + theInputTiePoints[i].y = mapPrj->getUlGpt().latd(); + } + else if(theUnits == "meters") + { + theInputTiePoints[i].x = mapPrj->getUlEastingNorthing().x;; + theInputTiePoints[i].y = mapPrj->getUlEastingNorthing().y; + } + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "tie points for input " << i << " = " + << theInputTiePoints[i] << std::endl; + } + + } + if(prj) + { + delete prj; + prj = NULL; + mapPrj = NULL; + } + } + if(!theInputTiePoints[i].hasNans()) + { + if(theUpperLeftTie.hasNans()) + { + theUpperLeftTie = theInputTiePoints[i]; + } + else if(!theInputTiePoints[i].hasNans()) + { + if(theUnits == "meters") + { + theUpperLeftTie.x = std::min(theUpperLeftTie.x, theInputTiePoints[i].x); + theUpperLeftTie.y = std::max(theUpperLeftTie.y, theInputTiePoints[i].y); + } + else + { + theUpperLeftTie.lon = std::min(theUpperLeftTie.lon, theInputTiePoints[i].lon); + theUpperLeftTie.lat = std::max(theUpperLeftTie.lat, theInputTiePoints[i].lat); + } + } + } + } + else + { + theInputTiePoints[i].makeNan(); +// CLOG << "Input " << i << " will not be used since no ortho information exists" << endl; + } + } + } + + computeBoundingRect(); + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "theUpperLeftTie = " << theUpperLeftTie << std::endl + << "delta per pixel = " << theDelta << std::endl + << "bounding rect = " << theBoundingRect << std::endl; + } + ossimImageMosaic::initialize(); + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimOrthoImageMosaic::initialize() DEBUG: Leaving..." << std::endl; + } +} + +ossimRefPtr<ossimImageData> ossimOrthoImageMosaic::getNextTile( + const ossimIrect& origin, + ossim_uint32 resLevel) +{ + const char *MODULE="ossimOrthoImageMosaic::getNextTile"; + + ossim_int32 size = getNumberOfInputs(); + + if((theCurrentIndex+1) >= size) + { + return ossimRefPtr<ossimImageData>(); + } + + ossimImageSourceInterface* temp = NULL; + ossimRefPtr<ossimImageData> result; + ossimDataObjectStatus status = OSSIM_NULL; + + do + { + ++theCurrentIndex; + temp = PTR_CAST(ossimImageSourceInterface, getInput(theCurrentIndex)); + if(temp) + { + ossimIrect relRect = getRelativeRect(theCurrentIndex, resLevel); + + if(traceDebug()) + { + CLOG << "Rel rect for input " << theCurrentIndex + << " = " << relRect + << "\nRes level: " << resLevel + << endl; + } + + if(origin.intersects(relRect)) + { + // get the rect relative to the input rect + // + ossimIrect shiftedRect = origin + (ossimIpt(-relRect.ul().x, + -relRect.ul().y)); + + // request that tile from the input space. + result = temp->getTile(shiftedRect, resLevel); + + // now change the origin to the output origin. + if (result.valid()) + { + result->setOrigin(origin.ul()); + + status = result->getDataObjectStatus(); + + if((status == OSSIM_NULL)||(status == OSSIM_EMPTY)) + { + result = NULL; + } + } + } + else + { + result = NULL; + } + } + + } while(!result.valid() && (theCurrentIndex<size)); + + return result; +} + +void ossimOrthoImageMosaic::computeBoundingRect(ossim_uint32 resLevel) +{ + const char* MODULE = "ossimOrthoImageMosaic::computeBoundingRect"; + + theBoundingRect.makeNan(); + + for(ossim_uint32 i = 0; i < theInputTiePoints.size(); ++ i) + { + ossimIrect shiftedRect = getRelativeRect(i, resLevel); + + if(traceDebug()) + { + CLOG << "bounding rect for input " << (i+1) + << ":" << shiftedRect << endl; + } + if(!shiftedRect.hasNans()) + { + if(theBoundingRect.hasNans()) + { + theBoundingRect = shiftedRect; + } + else + { + theBoundingRect = theBoundingRect.combine(shiftedRect); + } + } + } +} + +ossimIrect ossimOrthoImageMosaic::getRelativeRect(ossim_uint32 index, + ossim_uint32 resLevel)const +{ + ossimIrect result; + ossimImageSourceInterface* interface = PTR_CAST(ossimImageSourceInterface, + getInput(index)); + result.makeNan(); + if(interface&& + !theInputTiePoints[index].hasNans()) + { + ossimIrect inputRect = interface->getBoundingRect(); + result = inputRect; + + if(!inputRect.hasNans()) + { + ossimDpt shift = (theInputTiePoints[index] - theUpperLeftTie); + + shift.x/= theDelta.x; + shift.y/=-theDelta.y; + + result = result + shift; + if(!resLevel) + { + return result; + } + ossimDpt decimation; + interface->getDecimationFactor(resLevel, decimation); + if(!decimation.hasNans()) + { + result = result * decimation; + } + } + } + + return result; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimOrthoImageMosaic.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimOrthoImageMosaic.h new file mode 100644 index 0000000000..0e4f68e049 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimOrthoImageMosaic.h @@ -0,0 +1,65 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimOrthoImageMosaic.h,v 1.7 2005/02/11 15:07:33 dburken Exp $ +#ifndef ossimOrthoImageMosaic_HEADER +#define ossimOrthoImageMosaic_HEADER +#include <imaging/tile_sources/ossimImageMosaic.h> + +class OSSIMDLLEXPORT ossimOrthoImageMosaic : public ossimImageMosaic +{ +public: + ossimOrthoImageMosaic(); + ossimOrthoImageMosaic(const std::vector<ossimImageSource*>& inputSources); + virtual ~ossimOrthoImageMosaic(); + virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0) const; + virtual void initialize(); + virtual bool getImageGeometry(ossimKeywordlist& kwl, + const char* prefix=0); + /*! + * Used to retrieve the number of overlapping images withint the given + * rect. + */ + virtual ossim_uint32 getNumberOfOverlappingImages(const ossimIrect& rect, ossim_uint32 resLevel=0)const; + + /*! + * Used to populate the result with the index of the overlapping images. + */ + virtual void getOverlappingImages(std::vector<ossim_uint32>& result, + const ossimIrect& rect, + ossim_uint32 resLevel=0)const; + + virtual ossimRefPtr<ossimImageData> getNextTile(const ossimIrect& origin, + ossim_uint32 resLevel=0); + + ossimIrect getRelativeRect(ossim_uint32 index, + ossim_uint32 resLevel = 0)const; +protected: + std::vector<ossimDpt> theInputTiePoints; + + /*! + * Holds R0 delta and will be scaled for different r-level requests + * + */ + ossimDpt theDelta; + + /*! + * Will hold the upper left tie of the mosaic. + */ + ossimDpt theUpperLeftTie; + + ossimIrect theBoundingRect; + ossimString theUnits; + + void computeBoundingRect(ossim_uint32 resLevel=0); +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimPolyCutter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimPolyCutter.cpp new file mode 100644 index 0000000000..3b3a61bf5f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimPolyCutter.cpp @@ -0,0 +1,373 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimPolyCutter.cpp,v 1.28 2005/02/11 15:07:33 dburken Exp $ +#include <imaging/tile_sources/ossimPolyCutter.h> +#include <base/data_types/ossimPolyArea2d.h> +#include <imaging/ossimImageData.h> +#include <imaging/ossimImageDataHelper.h> +#include <base/common/ossimCommon.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <base/data_types/ossimActiveEdgeTable.h> + +static const char* NUMBER_POLYGONS_KW = "number_polygons"; + +RTTI_DEF1(ossimPolyCutter, "ossimPolyCutter", ossimImageSourceFilter) + +ossimPolyCutter::ossimPolyCutter() + : ossimImageSourceFilter(), + theTile(NULL), + theCutType(OSSIM_POLY_NULL_OUTSIDE) +{ + thePolygonList.push_back(ossimPolygon()); + theBoundingRect.makeNan(); +} + +// ossimPolyCutter::ossimPolyCutter(ossimImageSource* inputSource, +// ossimPolyArea2d* polygon) +ossimPolyCutter::ossimPolyCutter(ossimImageSource* inputSource, + const ossimPolygon& polygon) + : ossimImageSourceFilter(inputSource), + theTile(NULL), + theCutType(OSSIM_POLY_NULL_INSIDE) +{ + thePolygonList.push_back(polygon); + computeBoundingRect(); + initialize(); +} + +ossimPolyCutter::~ossimPolyCutter() +{ +} + +ossimRefPtr<ossimImageData> ossimPolyCutter::getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if(!theInputConnection) + { + return theTile; + } + ossimRefPtr<ossimImageData> input = theInputConnection->getTile(tileRect, + resLevel); + + if(!isSourceEnabled() || theBoundingRect.hasNans() || !input.valid()) + { + return input; + } + + if((input->getDataObjectStatus() == OSSIM_EMPTY) || + (input->getDataObjectStatus() == OSSIM_NULL)) + { + return input; + } + + if(!theTile.valid()) + { + allocate(); // First time through... + } + + if(!theTile.valid()) + { + return input; + } + + theTile->setImageRectangle(tileRect); + + theTile->loadTile(input.get()); + theTile->setDataObjectStatus(input->getDataObjectStatus()); + vector<ossimPolygon>* polyList = &thePolygonList; + vector<ossimPolygon> scaledPoly; + + ossimIrect boundingRect = getBoundingRect(resLevel); + if(resLevel) + { + ossimDpt decimation; + getDecimationFactor(resLevel, decimation); + + if(!decimation.hasNans()) + { + for(int polyIndex = 0; + polyIndex < (int)thePolygonList.size(); + ++polyIndex) + { + scaledPoly.push_back(thePolygonList[polyIndex]*decimation); + } + polyList = &scaledPoly; + } + } + + if(polyList->size()&& + theTile->getDataObjectStatus()!=OSSIM_NULL) + { + ossimActiveEdgeTable aet; + + + if((theCutType == OSSIM_POLY_NULL_OUTSIDE)) + { + if(boundingRect.intersects(tileRect)) + { + theTile->makeBlank(); + ossimImageDataHelper helper(theTile.get()); + for(int polyIndex = 0; polyIndex < (int)thePolygonList.size(); ++polyIndex) + { + helper.copyInputToThis(input->getBuf(), + (*polyList)[polyIndex]); + } + theTile->validate(); + } + else + { + theTile->makeBlank(); + } + } + else if(theCutType == OSSIM_POLY_NULL_INSIDE) + { + if(boundingRect.intersects(tileRect)) + { + ossimImageDataHelper helper(theTile.get()); + for(int polyIndex = 0; + polyIndex < (int)thePolygonList.size(); + ++polyIndex) + { + helper.fill(theTile->getNullPix(), + (*polyList)[polyIndex]); + } + } + theTile->validate(); + } + + } + + return theTile; +} + +ossimIrect ossimPolyCutter::getBoundingRect(ossim_uint32 resLevel)const +{ + ossimIrect result; + + result.makeNan(); + if(!theInputConnection) + { + return result; + } + if(!isSourceEnabled()) + { + return ossimImageSourceFilter::getBoundingRect(resLevel); + } + + result = theInputConnection->getBoundingRect(resLevel); + + if(isSourceEnabled()&&(!theBoundingRect.hasNans())) + { + if(theCutType == OSSIM_POLY_NULL_OUTSIDE) + { + ossimDpt decimation; + getDecimationFactor(resLevel, decimation); + if(decimation.hasNans()) + { + result = theBoundingRect; + } + else + { + result = theBoundingRect*decimation; + } + } + } + return result; +} + +void ossimPolyCutter::initialize() +{ + // Capture the input connection. + ossimImageSourceFilter::initialize(); + + // Force an allocate on next getTile. + theTile = NULL; +} + +void ossimPolyCutter::allocate() +{ + theTile=NULL; + if(theInputConnection) + { + theTile = ossimImageDataFactory::instance()->create(this, + theInputConnection); + theTile->initialize(); + + } +} + +bool ossimPolyCutter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimString newPrefix = prefix; + + for(int i = 0; i < (int)thePolygonList.size();++i) + { + newPrefix = ossimString(prefix) + "polygon" + ossimString::toString(i)+"."; + + thePolygonList[i].saveState(kwl, newPrefix.c_str()); + } + kwl.add(prefix, + NUMBER_POLYGONS_KW, + (int)thePolygonList.size(), + true); + + ossimString fillType = "null_inside"; + if(theCutType == OSSIM_POLY_NULL_OUTSIDE) + { + fillType = "null_outside"; + } + kwl.add(prefix, + "cut_type", + fillType.c_str(), + true); + + return ossimImageSourceFilter::saveState(kwl, prefix);; +} + +bool ossimPolyCutter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* numberPolygons = kwl.find(prefix, NUMBER_POLYGONS_KW); + + ossimString newPrefix; + if(numberPolygons) + { + thePolygonList.clear(); + int npolys = ossimString(numberPolygons).toLong(); + for(int i = 0; i < npolys;++i) + { + thePolygonList.push_back(ossimPolygon()); + + newPrefix = ossimString(prefix) + "polygon" + ossimString::toString(i)+"."; + + thePolygonList[i].loadState(kwl, newPrefix.c_str()); + } + } + + const char* lookup = kwl.find(prefix, + "cut_type"); + if(lookup) + { + theCutType = OSSIM_POLY_NULL_INSIDE; + ossimString test = lookup; + if(test == "null_outside") + { + theCutType = OSSIM_POLY_NULL_OUTSIDE; + } + } + else + { + theCutType = OSSIM_POLY_NULL_OUTSIDE; + } + + computeBoundingRect(); + + + return ossimImageSourceFilter::loadState(kwl, prefix); +} + + +void ossimPolyCutter::setPolygon(const vector<ossimDpt>& polygon, + ossim_uint32 index) +{ + if(index < polygon.size()) + { + thePolygonList[index] = polygon; + + computeBoundingRect(); + } + +} + +void ossimPolyCutter::setPolygon(const vector<ossimIpt>& polygon, + ossim_uint32 index) +{ + if(polygon.size()) + { + thePolygonList[index] = polygon; + computeBoundingRect(); + } +} + +void ossimPolyCutter::addPolygon(const vector<ossimIpt>& polygon) +{ + thePolygonList.push_back(ossimPolygon(polygon)); + computeBoundingRect(); +} + +void ossimPolyCutter::addPolygon(const vector<ossimDpt>& polygon) +{ + thePolygonList.push_back(ossimPolygon(polygon)); + computeBoundingRect(); +} + +void ossimPolyCutter::addPolygon(const ossimPolygon& polygon) +{ + thePolygonList.push_back(ossimPolygon(polygon)); + computeBoundingRect(); +} + + +void ossimPolyCutter::setCutType(ossimPolyCutterCutType cutType) +{ + theCutType = cutType; +} + +ossimPolyCutter::ossimPolyCutterCutType ossimPolyCutter::getCutType()const +{ + return theCutType; +} + +void ossimPolyCutter::computeBoundingRect() +{ + ossimIrect bounds; + theBoundingRect.makeNan(); + + for(int i = 0; i < (int)thePolygonList.size(); ++i) + { + thePolygonList[i].getBoundingRect(bounds); + + if(!bounds.hasNans()) + { + if(theBoundingRect.hasNans()) + { + theBoundingRect = bounds; + } + else + { + theBoundingRect = theBoundingRect.combine(bounds); + } + } + } +} +void ossimPolyCutter::setNumberOfPolygons(ossim_uint32 count) +{ + if(!count) + { + thePolygonList.clear(); + } + else + { + thePolygonList.resize(count); + } +} + +std::vector<ossimPolygon>& ossimPolyCutter::getPolygonList() +{ + return thePolygonList; +} + +const std::vector<ossimPolygon>& ossimPolyCutter::getPolygonList()const +{ + return thePolygonList; +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimPolyCutter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimPolyCutter.h new file mode 100644 index 0000000000..b7cd9a6801 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimPolyCutter.h @@ -0,0 +1,96 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimPolyCutter.h,v 1.15 2005/04/05 18:48:29 gpotts Exp $ +#ifndef ossimPolyCutter_HEADER +#define ossimPolyCutter_HEADER +#include <imaging/tile_sources/ossimImageSourceFilter.h> +#include <base/data_types/ossimPolygon.h> +#include <vector> + +//class ossimPolyArea2d; +class ossimImageData; + +class OSSIMDLLEXPORT ossimPolyCutter : public ossimImageSourceFilter +{ +public: + enum ossimPolyCutterCutType + { + OSSIM_POLY_NULL_INSIDE = 0, + OSSIM_POLY_NULL_OUTSIDE = 1 + }; + + ossimPolyCutter(); + ossimPolyCutter(ossimImageSource* inputSource, + const ossimPolygon& polygon); + virtual ~ossimPolyCutter(); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + + virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0)const; + + virtual void initialize(); + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual void setPolygon(const vector<ossimDpt>& polygon, + ossim_uint32 i = 0); + + virtual void setPolygon(const vector<ossimIpt>& polygon, + ossim_uint32 i = 0); + + virtual void addPolygon(const vector<ossimIpt>& polygon); + virtual void addPolygon(const vector<ossimDpt>& polygon); + virtual void addPolygon(const ossimPolygon& polygon); + + virtual void setNumberOfPolygons(ossim_uint32 count); + + virtual std::vector<ossimPolygon>& getPolygonList(); + + virtual const std::vector<ossimPolygon>& getPolygonList()const; + + void setCutType(ossimPolyCutterCutType cutType); + + ossimPolyCutterCutType getCutType()const; +protected: + + /** + * Called on first getTile, will initialize all data needed. + */ + void allocate(); + + ossimRefPtr<ossimImageData> theTile; + + /*! + * Will hold a pre-computed bounding rect of the + * polygon data. + */ + ossimIrect theBoundingRect; + + std::vector<ossimPolygon> thePolygonList; + + /*! + * theDefault fill will be outside. + */ + ossimPolyCutterCutType theCutType; + + void computeBoundingRect(); + +TYPE_DATA +}; +#endif /* #ifndef ossimPolyCutter_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRLevelFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRLevelFilter.cpp new file mode 100644 index 0000000000..ec5352a8ba --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRLevelFilter.cpp @@ -0,0 +1,265 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimRLevelFilter.cpp,v 1.14 2005/12/25 17:14:57 dburken Exp $ +#include <imaging/tile_sources/ossimRLevelFilter.h> +#include <projections/map_projections/ossimMapProjection.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <base/common/ossimTrace.h> + +static const char* CURRENT_RLEVEL_KW = "current_rlevel"; +static const char* OVERRIDE_GEOMETRY_KW = "override_geometry"; + +static ossimTrace traceDebug("ossimRLevelFilter:debug"); + +RTTI_DEF1(ossimRLevelFilter, "ossimRLevelFilter", ossimImageSourceFilter); + +ossimRLevelFilter::ossimRLevelFilter(ossimObject* owner, + ossimImageSource* inputSource, + ossim_uint32 resLevel, + bool overrideGeometry) + : ossimImageSourceFilter(owner), + theCurrentRLevel(resLevel), + theOverrideGeometryFlag(overrideGeometry) +{ +} + +ossimRLevelFilter::ossimRLevelFilter(ossimImageSource* inputSource, + ossim_uint32 resLevel, + bool overrideGeometry) + : ossimImageSourceFilter(NULL, inputSource), + theCurrentRLevel(resLevel), + theOverrideGeometryFlag(overrideGeometry) +{ +} + +ossimRLevelFilter::~ossimRLevelFilter() +{ +} + +void ossimRLevelFilter::getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result) const +{ + if(!theInputConnection) + { + result.makeNan(); + } + + theInputConnection->getDecimationFactor(resLevel, + result); +} + +bool ossimRLevelFilter::getOverrideGeometryFlag() const +{ + return theOverrideGeometryFlag; +} + +void ossimRLevelFilter::setOverrideGeometryFlag(bool override) +{ + theOverrideGeometryFlag = override; +} + +void ossimRLevelFilter::setCurrentRLevel(ossim_uint32 rlevel) +{ + theCurrentRLevel = rlevel; +} + +ossim_uint32 ossimRLevelFilter::getCurrentRLevel()const +{ + return theCurrentRLevel; +} + +bool ossimRLevelFilter::getImageGeometry(ossimKeywordlist& kwl, + const char* prefix) +{ + if (!theInputConnection) + { + return false; + } + + ossim_uint32 rlevel = getCurrentRLevel(); + bool status = theInputConnection->getImageGeometry(kwl, prefix); + + if (!theOverrideGeometryFlag || (status == false) || + (rlevel == 0) || (getEnableFlag() == false) ) + { + return status; + } + + ossimProjection* proj = ossimProjectionFactoryRegistry::instance()-> + createProjection(kwl); + ossimMapProjection* mapProj = PTR_CAST(ossimMapProjection, proj);; + if(mapProj) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimRLevelFilter::getImageGeometry DEBUG:" + << "\nOriginal projection:\n"; + mapProj->print(ossimNotify(ossimNotifyLevel_DEBUG)); + } + + //--- + // We must adjust both the scale and the tie point to account for + // decimation. + //--- + ossimDpt summed_decimation; + getSummedDecimation(summed_decimation); + if (!summed_decimation.hasNans()) + { + if (mapProj->isGeographic()) + { + // Adjust the upper left geographic tie point. + ossimDpt degPerPix = mapProj->getDecimalDegreesPerPixel(); + ossimGpt ulGpt = mapProj->getUlGpt(); + ulGpt.lat -= degPerPix.lat * summed_decimation.lat; + ulGpt.lon += degPerPix.lon * summed_decimation.lon; + mapProj->setUlGpt(ulGpt); + } + else + { + // Adjust the upper left easting northing tie point. + ossimDpt meterPerPix = mapProj->getMetersPerPixel(); + ossimDpt ulEnPt = mapProj->getUlEastingNorthing(); + ulEnPt.y -= meterPerPix.y * summed_decimation.y; + ulEnPt.x += meterPerPix.x * summed_decimation.x; + mapProj->setUlEastingNorthing(ulEnPt); + } + } + + // Apply the scale. + ossimDpt decimation; + getDecimationFactor(rlevel, decimation); + decimation.x = 1.0/decimation.x; + decimation.y = 1.0/decimation.y; + mapProj->applyScale(decimation, true); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimRLevelFilter::getImageGeometry DEBUG:" + << "\nUpdated projection:\n"; + mapProj->print(ossimNotify(ossimNotifyLevel_DEBUG)); + } + + // Save off the changes back to the keyword list. + mapProj->saveState(kwl, prefix); + + return true; + + } // End of "if(mapProj))" + + return status; +} + +void ossimRLevelFilter::getSummedDecimation(ossimDpt& result) const +{ + // Start with fresh values. + result.x = 0.0; + result.y = 0.0; + + ossim_uint32 rlevel = getCurrentRLevel(); + + if (rlevel == 0) + { + return; // no decimation. + } + + // Sum the decimations from rlevel one to the current rlevel. + for (ossim_uint32 i = 1; i <= rlevel; ++i) + { + ossimDpt dpt; + getDecimationFactor(i, dpt); + if (dpt.hasNans()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimRLevelFilter::getSummedDecimation WARNING:" + << "\nNans returned from getDecimationFactor!" + << std::endl; + result.makeNan(); + return; + } + result.x += dpt.x; + result.y += dpt.y; + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimRLevelFilter::getSummedDecimation result: " << result + << std::endl; + } +} + +ossimIrect ossimRLevelFilter::getBoundingRect(ossim_uint32 resLevel)const +{ + ossimIrect rect; + rect.makeNan(); + if(!theInputConnection) return rect; + + if (isSourceEnabled()) + { + return theInputConnection->getBoundingRect(theCurrentRLevel); + } + return theInputConnection->getBoundingRect(resLevel); +} + +ossimRefPtr<ossimImageData> ossimRLevelFilter::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if(!theInputConnection) + { + return NULL; + } + + if(!isSourceEnabled()) + { + return theInputConnection->getTile(tileRect, resLevel); + } + + // Ignoring resLevel as we're in charge of it here! + return theInputConnection->getTile(tileRect, theCurrentRLevel); +} + +bool ossimRLevelFilter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* current = kwl.find(prefix, CURRENT_RLEVEL_KW); + const char* override = kwl.find(prefix, OVERRIDE_GEOMETRY_KW); + + if(current) + { + theCurrentRLevel = ossimString(current).toULong(); + } + + if(override) + { + theOverrideGeometryFlag = ossimString(override).toBool(); + } + + return ossimImageSourceFilter::loadState(kwl, prefix); +} + +bool ossimRLevelFilter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + CURRENT_RLEVEL_KW, + theCurrentRLevel, + true); + + kwl.add(prefix, + OVERRIDE_GEOMETRY_KW, + (ossim_uint32)theOverrideGeometryFlag, + true); + + return ossimImageSourceFilter::saveState(kwl, prefix); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRLevelFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRLevelFilter.h new file mode 100644 index 0000000000..970d46b7b8 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRLevelFilter.h @@ -0,0 +1,84 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimRLevelFilter.h,v 1.9 2005/02/11 15:07:33 dburken Exp $ +#ifndef ossimRLevelFilter_HEADER +#define ossimRLevelFilter_HEADER +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +/*! + * This filter is used to adjust the RLevel. If you would like to + * continually change between RLevels or Reslolutions then you can use this + * filter to do so. You can also specify whether or not the rLevel + * passed in from the getTile request is added to this classes current + * Rlevel. This is so if you concatenate multiple filters that reduce + * the RLevels then it will keep reducing. For example if I have + * 2 filters that both go to RLevel 1 then it actually will go to + * 2 since there are 2 decimations happening. This can be turned off + * by specifying the Rlevel not to be additive. + */ +class OSSIMDLLEXPORT ossimRLevelFilter : public ossimImageSourceFilter +{ +public: + + ossimRLevelFilter(ossimObject* owner, + ossimImageSource* inputSource = NULL, + ossim_uint32 resLevel = 0, + bool overrideGeometry = false); + + ossimRLevelFilter(ossimImageSource* inputSource = NULL, + ossim_uint32 resLevel = 0, + bool overrideGeometry = false); + + virtual ~ossimRLevelFilter(); + + virtual void getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result)const; + + virtual bool getImageGeometry(ossimKeywordlist& kwl, + const char* prefix=NULL); + + virtual void setCurrentRLevel(ossim_uint32 rlevel); + + virtual ossim_uint32 getCurrentRLevel()const; + + /*! + * Get/set of the data member "theOverrideGeometryFlag". + * If set this will override the "getImageGeometry" method and adjust + * the getMetersPerPixel or the getDecimalDegreesPerPixel. + * Default behavior is to not override method. + */ + virtual bool getOverrideGeometryFlag() const; + virtual void setOverrideGeometryFlag(bool override); + + virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0) const; + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; +protected: + /*! + * Initializes result with the sum of decimations from rlevel one to + * theCurrentRLevel. + */ + void getSummedDecimation(ossimDpt& result) const; + + ossim_uint32 theCurrentRLevel; + bool theOverrideGeometryFlag; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRectangleCutFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRectangleCutFilter.cpp new file mode 100644 index 0000000000..1d018a6bfc --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRectangleCutFilter.cpp @@ -0,0 +1,295 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimRectangleCutFilter.cpp,v 1.21 2005/09/15 12:28:44 gpotts Exp $ +#include <imaging/tile_sources/ossimRectangleCutFilter.h> +#include <base/common/ossimTrace.h> +#include <base/context/ossimNotifyContext.h> + +static ossimTrace traceDebug("ossimRectangleCutFilter:debug"); + +RTTI_DEF1(ossimRectangleCutFilter, + "ossimRectangleCutFilter", + ossimImageSourceFilter); + +ossimRectangleCutFilter::ossimRectangleCutFilter(ossimObject* owner, + ossimImageSource* inputSource) + :ossimImageSourceFilter(owner, inputSource), + theCutType(OSSIM_RECTANGLE_NULL_OUTSIDE) +{ + theRectangle.makeNan(); +} + +ossimRectangleCutFilter::ossimRectangleCutFilter(ossimImageSource* inputSource) + :ossimImageSourceFilter(NULL, inputSource), + theCutType(OSSIM_RECTANGLE_NULL_OUTSIDE) +{ + theRectangle.makeNan(); +} + + +ossimRefPtr<ossimImageData> ossimRectangleCutFilter::getTile( + const ossimIrect& rect, + ossim_uint32 resLevel) +{ + if(!theInputConnection) + { + return NULL; + } + + ossimRefPtr<ossimImageData> tile = + theInputConnection->getTile(rect, resLevel); + if(!isSourceEnabled()||theRectangle.hasNans()||!tile.valid()) + { + return tile; + } + if(tile->getDataObjectStatus() == OSSIM_NULL || + tile->getDataObjectStatus() == OSSIM_EMPTY) + { + return tile; + } + ossim_int32 decimationIndex = min((ossim_int32)resLevel, + (ossim_int32)theDecimationList.size()-1); + + ossimIrect cutRect = theRectangle*theDecimationList[decimationIndex]; + + ossimIrect inputRectangle = tile->getImageRectangle(); + if(theCutType==OSSIM_RECTANGLE_NULL_INSIDE) + { + if(cutRect.intersects(inputRectangle)) + { + if(!inputRectangle.completely_within(cutRect)) + { + ossim_int32 ulx = inputRectangle.ul().x; + ossim_int32 uly = inputRectangle.ul().y; + ossim_int32 w = tile->getWidth(); + ossim_int32 h = tile->getHeight(); + ossim_int32 offset = 0; + ossimIpt tempPoint(ulx, uly); + + for(ossim_int32 y = 0; y < h; ++tempPoint.y,++y) + { + tempPoint.x = ulx; + for(ossim_int32 x = 0; x < w; ++tempPoint.x,++x) + { + if(cutRect.pointWithin(tempPoint)) + { + tile->setNull(offset); + } + ++offset; + } + } + tile->validate(); + } + else + { + tile->makeBlank(); + } + } + } + else // cut out the outide + { + if(cutRect.intersects(inputRectangle)) + { + if(!inputRectangle.completely_within(cutRect)) + { + ossim_int32 ulx = inputRectangle.ul().x; + ossim_int32 uly = inputRectangle.ul().y; + ossim_int32 w = tile->getWidth(); + ossim_int32 h = tile->getHeight(); + ossim_int32 offset = 0; + ossimIpt tempPoint(ulx, uly); + + for(ossim_int32 y = 0; y < h; ++tempPoint.y,++y) + { + tempPoint.x = ulx; + for(ossim_int32 x = 0; x < w; ++tempPoint.x,++x) + { + if(!cutRect.pointWithin(tempPoint)) + { + tile->setNull(offset); + } + ++offset; + } + } + tile->validate(); + } + } + else + { + tile->makeBlank(); + } + } + + return tile; +} + +void ossimRectangleCutFilter::setRectangle(const ossimIrect& rect) +{ + theRectangle = rect; + + if(theRectangle.hasNans()) + { + if(theInputConnection) + { + theRectangle = theInputConnection->getBoundingRect(); + } + } +} + +void ossimRectangleCutFilter::getValidImageVertices( + vector<ossimIpt>& validVertices, + ossimVertexOrdering ordering, + ossim_uint32 resLevel)const +{ + ossimIrect rect = getBoundingRect(); + + if(ordering == OSSIM_CLOCKWISE_ORDER) + { + validVertices.push_back(rect.ul()); + validVertices.push_back(rect.ur()); + validVertices.push_back(rect.lr()); + validVertices.push_back(rect.ll()); + } + else + { + validVertices.push_back(rect.ul()); + validVertices.push_back(rect.ll()); + validVertices.push_back(rect.lr()); + validVertices.push_back(rect.ur()); + } +} + +ossimIrect ossimRectangleCutFilter::getBoundingRect(ossim_uint32 resLevel)const +{ + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimRectangleCutFilter::getBoundingRect DEBUG: entered..." << std::endl; + } + ossimIrect result; + + result.makeNan(); + if(!theInputConnection) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimRectangleCutFilter::getBoundingRect DEBUG: Input connection was not valid so leaving" << std::endl; + } + return result; + } + + result = theInputConnection->getBoundingRect(resLevel); + if(isSourceEnabled()) + { + if(theCutType == OSSIM_RECTANGLE_NULL_OUTSIDE) + { + ossimDpt decimation; + getDecimationFactor(resLevel, decimation); + ossimIrect cutRect = theRectangle; + if(!decimation.hasNans()) + { + cutRect = theRectangle*decimation; + } + result = cutRect; + } + } + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimRectangleCutFilter::getBoundingRect DEBUG: cut rect = " << result << std::endl; + } + return result; +} + +void ossimRectangleCutFilter::initialize() +{ + theDecimationList.clear(); + if(theInputConnection) + { + getDecimationFactors(theDecimationList); + } + if(theDecimationList.empty()) + { + theDecimationList.push_back(ossimDpt(1,1)); + } + if(theRectangle.hasNans()) + { + setRectangle(theRectangle); + } +} + +bool ossimRectangleCutFilter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimString newPrefix = prefix; + newPrefix+="clip_rect."; + + theRectangle.saveState(kwl, newPrefix); + + if(theCutType == OSSIM_RECTANGLE_NULL_INSIDE) + { + kwl.add(prefix, + "cut_type", + "null_inside", + true); + } + else if(theCutType == OSSIM_RECTANGLE_NULL_OUTSIDE) + { + kwl.add(prefix, + "cut_type", + "null_outside", + true); + } + + return ossimImageSourceFilter::saveState(kwl, prefix); +} + +bool ossimRectangleCutFilter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimString newPrefix = prefix; + newPrefix+="clip_rect."; + + theRectangle.loadState(kwl, newPrefix.c_str()); + const char* cutType = kwl.find(prefix, "cut_type"); + if(cutType) + { + ossimString c = cutType; + if(c == "null_inside") + { + theCutType = OSSIM_RECTANGLE_NULL_INSIDE; + } + else if(c == "null_outside") + { + theCutType = OSSIM_RECTANGLE_NULL_OUTSIDE; + } + else + { + theCutType = static_cast<ossimRectangleCutType>(ossimString(cutType).toLong()); + } + } + + return ossimImageSourceFilter::loadState(kwl, prefix); +} + +const ossimIrect& ossimRectangleCutFilter::getRectangle()const +{ + return theRectangle; +} + +ossimRectangleCutFilter::ossimRectangleCutType ossimRectangleCutFilter::getCutType()const +{ + return theCutType; +} + +void ossimRectangleCutFilter::setCutType(ossimRectangleCutType cutType) +{ + theCutType = cutType; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRectangleCutFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRectangleCutFilter.h new file mode 100644 index 0000000000..65ce6341f0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRectangleCutFilter.h @@ -0,0 +1,57 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimRectangleCutFilter.h,v 1.12 2005/10/28 14:01:03 gpotts Exp $ +#ifndef ossimRectangleCutFilter_HEADER +#define ossimRectangleCutFilter_HEADER +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +class OSSIM_DLL ossimRectangleCutFilter : public ossimImageSourceFilter +{ +public: + enum ossimRectangleCutType + { + OSSIM_RECTANGLE_NULL_INSIDE = 0, + OSSIM_RECTANGLE_NULL_OUTSIDE = 1 + }; + + ossimRectangleCutFilter(ossimObject* owner, + ossimImageSource* inputSource=NULL); + ossimRectangleCutFilter(ossimImageSource* inputSource=NULL); + + void setRectangle(const ossimIrect& rect); + + const ossimIrect& getRectangle()const; + ossimRectangleCutType getCutType()const; + void setCutType(ossimRectangleCutType cutType); + + ossimIrect getBoundingRect(ossim_uint32 resLevel=0)const; + virtual void getValidImageVertices(vector<ossimIpt>& validVertices, + ossimVertexOrdering ordering=OSSIM_CLOCKWISE_ORDER, + ossim_uint32 resLevel=0)const; + + ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect, + ossim_uint32 resLevel=0); + + virtual void initialize(); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=NULL)const; + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=NULL); + +protected: + ossimIrect theRectangle; + ossimRectangleCutType theCutType; + vector<ossimDpt> theDecimationList; +TYPE_DATA +}; + +#endif /* #ifndef ossimRectangleCutFilter_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToGreyFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToGreyFilter.cpp new file mode 100644 index 0000000000..20085888b9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToGreyFilter.cpp @@ -0,0 +1,249 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimRgbToGreyFilter.cpp,v 1.21 2005/02/11 15:07:34 dburken Exp $ + +#include <imaging/tile_sources/ossimRgbToGreyFilter.h> +#include <imaging/ossimU8ImageData.h> +#include <base/common/ossimConstants.h> +#include <base/common/ossimCommon.h> +#include <base/data_types/ossimKeywordlist.h> + +RTTI_DEF1(ossimRgbToGreyFilter, "ossimRgbToGreyFilter", ossimImageSourceFilter) + +ossimRgbToGreyFilter::ossimRgbToGreyFilter(ossimObject* owner) + :ossimImageSourceFilter(owner), + theBlankTile(NULL), + theTile(NULL), + theC1(1.0/3.0), + theC2(1.0/3.0), + theC3(1.0/3.0) +{ +} + +ossimRgbToGreyFilter::ossimRgbToGreyFilter(ossimImageSource* inputSource, + double c1, + double c2, + double c3) + : ossimImageSourceFilter(NULL, inputSource), + theBlankTile(NULL), + theTile(NULL), + theC1(c1), + theC2(c2), + theC3(c3) +{ +} + +ossimRgbToGreyFilter::ossimRgbToGreyFilter(ossimObject* owner, + ossimImageSource* inputSource, + double c1, + double c2, + double c3) + : ossimImageSourceFilter(owner, inputSource), + theBlankTile(NULL), + theTile(NULL), + theC1(c1), + theC2(c2), + theC3(c3) +{ +} +ossimRgbToGreyFilter::~ossimRgbToGreyFilter() +{ +} + +ossimRefPtr<ossimImageData> ossimRgbToGreyFilter::getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if(!theInputConnection) + { + return NULL; // This filter requires an input. + } + + ossimRefPtr<ossimImageData> inputTile = theInputConnection->getTile(tileRect, + resLevel); + if(!isSourceEnabled() || !inputTile.valid()) + { + return inputTile; + } + + if(!theTile) + { + allocate(); // First time through... + } + + // if (!theTile) // throw exeption... + + if( inputTile->getDataObjectStatus() == OSSIM_NULL || + inputTile->getDataObjectStatus() == OSSIM_EMPTY ) + { + theBlankTile->setImageRectangle(tileRect); + return theBlankTile; + } + + // Set the origin, resize if needed of the output tile. + theTile->setImageRectangle(tileRect); + + // Filter the tile. + runUcharTransformation(inputTile); + + // Always validate to set the status. + theTile->validate(); + + return theTile; +} + + +void ossimRgbToGreyFilter::initialize() +{ + // Base class will recapture "theInputConnection". + ossimImageSourceFilter::initialize(); +} + +void ossimRgbToGreyFilter::allocate() +{ + if(theInputConnection) + { + theTile = NULL; + theBlankTile = NULL; + + if(isSourceEnabled()) + { + theBlankTile = new ossimU8ImageData(this, + 1, + theInputConnection->getTileWidth(), + theInputConnection->getTileHeight()); + + + theTile = (ossimImageData*)theBlankTile->dup(); + theTile->initialize(); + } + } +} + +ossim_uint32 ossimRgbToGreyFilter::getNumberOfOutputBands() const +{ + if(isSourceEnabled()) + { + return 1; + } + + return ossimImageSourceFilter::getNumberOfOutputBands(); +} + +bool ossimRgbToGreyFilter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimImageSourceFilter::saveState(kwl, prefix); + + kwl.add(prefix, + "c1", + theC1, + true); + kwl.add(prefix, + "c2", + theC2, + true); + kwl.add(prefix, + "c3", + theC2, + true); + + return true; +} + +bool ossimRgbToGreyFilter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimImageSourceFilter::loadState(kwl, prefix); + + const char* lookup = kwl.find(prefix, "c1"); + if(lookup) + { + theC1 = ossimString(lookup).toDouble(); + } + lookup = kwl.find(prefix, "c2"); + if(lookup) + { + theC2 = ossimString(lookup).toDouble(); + } + lookup = kwl.find(prefix, "c3"); + if(lookup) + { + theC3 = ossimString(lookup).toDouble(); + } + return true; +} + +void ossimRgbToGreyFilter::runUcharTransformation(ossimRefPtr<ossimImageData>& tile) +{ + unsigned char** bandSrc = new unsigned char*[tile->getNumberOfBands()]; + unsigned char* bandDest; + + if(tile->getNumberOfBands() == 1) + { + bandSrc[0] = static_cast<unsigned char*>(tile->getBuf(0)); + bandSrc[1] = static_cast<unsigned char*>(tile->getBuf(0)); + bandSrc[2] = static_cast<unsigned char*>(tile->getBuf(0)); + } + else if(tile->getNumberOfBands() == 2) + { + bandSrc[0] = static_cast<unsigned char*>(tile->getBuf(0)); + bandSrc[1] = static_cast<unsigned char*>(tile->getBuf(1)); + bandSrc[2] = static_cast<unsigned char*>(tile->getBuf(1)); + } + else if(tile->getNumberOfBands() == 3) + { + bandSrc[0] = static_cast<unsigned char*>(tile->getBuf(0)); + bandSrc[1] = static_cast<unsigned char*>(tile->getBuf(1)); + bandSrc[2] = static_cast<unsigned char*>(tile->getBuf(2)); + } + + bandDest = static_cast<unsigned char*>(theTile->getBuf()); + + long offset; + + long upperBound = tile->getWidth()*tile->getHeight(); + for(offset = 0; offset < upperBound; ++offset) + { + long value; + + value = irint(theC1*(bandSrc[0][offset]) + + theC2*(bandSrc[1][offset]) + + theC3*(bandSrc[2][offset])); + + value = value<255?value:255; + value = value>0?value:0; + + bandDest[offset] = value; + } + + + delete [] bandSrc; +} + +ossimString ossimRgbToGreyFilter::getShortName()const +{ + return ossimString("grey"); +} + +ossimString ossimRgbToGreyFilter::getLongName()const +{ + return ossimString("rgb to grey scale filter"); +} + +ossimScalarType ossimRgbToGreyFilter::getOutputScalarType() const +{ + if(isSourceEnabled()) + { + return OSSIM_UCHAR; + } + + return ossimImageSourceFilter::getOutputScalarType(); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToGreyFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToGreyFilter.h new file mode 100644 index 0000000000..fe3180f75d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToGreyFilter.h @@ -0,0 +1,70 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimRgbToGreyFilter.h,v 1.13 2005/02/11 15:07:34 dburken Exp $ +#ifndef ossimRgbToGreyFilter_HEADER +#define ossimRgbToGreyFilter_HEADER +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +class ossimRgbToGreyFilter : public ossimImageSourceFilter +{ +public: + ossimRgbToGreyFilter(ossimObject* owner=NULL); + ossimRgbToGreyFilter(ossimImageSource* inputSource, + double c1 = 1.0/3.0, + double c2 = 1.0/3.0, + double c3 = 1.0/3.0); + ossimRgbToGreyFilter(ossimObject* owner, + ossimImageSource* inputSource, + double c1 = 1.0/3.0, + double c2 = 1.0/3.0, + double c3 = 1.0/3.0); + virtual ~ossimRgbToGreyFilter(); + + virtual ossimString getShortName()const; + virtual ossimString getLongName()const; + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + + virtual void initialize(); + + virtual ossimScalarType getOutputScalarType() const; + + ossim_uint32 getNumberOfOutputBands() const; + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +protected: + + /** + * Called on first getTile, will initialize all data needed. + */ + void allocate(); + + ossimRefPtr<ossimImageData> theBlankTile; + ossimRefPtr<ossimImageData> theTile; + void runUcharTransformation(ossimRefPtr<ossimImageData>& tile); + double theC1; + double theC2; + double theC3; + +TYPE_DATA +}; + +#endif /* #ifndef ossimRgbToGreyFilter_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToHsiSource.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToHsiSource.cpp new file mode 100644 index 0000000000..f8ad925cd2 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToHsiSource.cpp @@ -0,0 +1,162 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimRgbToHsiSource.cpp,v 1.10 2005/02/11 15:07:34 dburken Exp $ + +#include <imaging/tile_sources/ossimRgbToHsiSource.h> +#include <imaging/ossimImageData.h> +#include <base/common/ossimConstants.h> +#include <base/common/ossimCommon.h> +#include <base/data_types/color_space/ossimHsiVector.h> +#include <base/data_types/color_space/ossimRgbVector.h> +#include <imaging/factory/ossimImageDataFactory.h> + +RTTI_DEF1(ossimRgbToHsiSource, "ossimRgbToHsiSource", ossimImageSourceFilter) + +ossimRgbToHsiSource::ossimRgbToHsiSource() + :ossimImageSourceFilter(), + theBlankTile(NULL), + theTile(NULL) +{ +} + +ossimRgbToHsiSource::ossimRgbToHsiSource(ossimImageSource* inputSource) + : ossimImageSourceFilter(inputSource), + theBlankTile(NULL), + theTile(NULL) +{ +} + +ossimRgbToHsiSource::~ossimRgbToHsiSource() +{ +} + +ossimRefPtr<ossimImageData> ossimRgbToHsiSource::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if(!theInputConnection) + { + return ossimRefPtr<ossimImageData>(); // This filter requires an input. + } + + ossimRefPtr<ossimImageData> inputTile = theInputConnection->getTile(tileRect, + resLevel); + if(!isSourceEnabled() || !inputTile.valid()) + { + return inputTile; + } + + if(!theTile) + { + allocate(); // First time through... + } + + if (!theTile.valid()) + { + return inputTile; + } + + if( inputTile->getDataObjectStatus() == OSSIM_NULL || + inputTile->getDataObjectStatus() == OSSIM_EMPTY ) + { + theBlankTile->setImageRectangle(tileRect); + return theBlankTile; + } + + if((inputTile->getNumberOfBands()==3)&& + (inputTile->getScalarType()==OSSIM_UCHAR)&& + (inputTile->getDataObjectStatus()!=OSSIM_NULL)) + { + // Set the origin, resize if needed of the output tile. + theTile->setImageRectangle(tileRect); + + float* outputBands[3]; + ossim_uint8* inputBands[3]; + outputBands[0] = static_cast<float*>(theTile->getBuf(0)); + outputBands[1] = static_cast<float*>(theTile->getBuf(1)); + outputBands[2] = static_cast<float*>(theTile->getBuf(2)); + inputBands[0] = static_cast<ossim_uint8*>(inputTile->getBuf(0)); + inputBands[1] = static_cast<ossim_uint8*>(inputTile->getBuf(1)); + inputBands[2] = static_cast<ossim_uint8*>(inputTile->getBuf(2)); + + long height = inputTile->getHeight(); + long width = inputTile->getWidth(); + long offset = 0; + for(long row = 0; row < height; ++row) + { + for(long col = 0; col < width; ++col) + { + ossimRgbVector rgb(inputBands[0][offset], + inputBands[1][offset], + inputBands[2][offset]); + + ossimHsiVector hsi(rgb); + + + outputBands[0][offset] = hsi.getH(); + outputBands[1][offset] = hsi.getS(); + outputBands[2][offset] = hsi.getI(); + + ++offset; + } + } + } + else // Input tile not of correct type to process... + { + return inputTile; + } + + theTile->validate(); + return theTile; +} + +ossimScalarType ossimRgbToHsiSource::getOutputScalarType() const +{ + return OSSIM_NORMALIZED_FLOAT; +} + +void ossimRgbToHsiSource::initialize() +{ + // Base class will recapture "theInputConnection". + ossimImageSourceFilter::initialize(); +} + +void ossimRgbToHsiSource::allocate() +{ + theBlankTile = NULL; + theTile = NULL; + + if(!theInputConnection) return; + + theBlankTile = ossimImageDataFactory::instance()->create(this, this); + theTile = (ossimImageData*)theBlankTile->dup(); + theTile->initialize(); +} + +ossim_uint32 ossimRgbToHsiSource::getNumberOfOutputBands()const +{ + return 3; +} + +double ossimRgbToHsiSource::getNullPixelValue()const +{ + return OSSIM_FLT_NAN; +} + +double ossimRgbToHsiSource::getMinPixelValue(ossim_uint32 band)const +{ + return 0.0; +} + +double ossimRgbToHsiSource::getMaxPixelValue(ossim_uint32 band)const +{ + return 1.0; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToHsiSource.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToHsiSource.h new file mode 100644 index 0000000000..1a2d77f905 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToHsiSource.h @@ -0,0 +1,47 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimRgbToHsiSource.h,v 1.10 2005/02/11 15:07:34 dburken Exp $ +#ifndef ossimRgbToHsiSource_HEADER +#define ossimRgbToHsiSource_HEADER +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +class ossimRgbToHsiSource : public ossimImageSourceFilter +{ +public: + ossimRgbToHsiSource(); + ossimRgbToHsiSource(ossimImageSource* inputSource); + virtual ~ossimRgbToHsiSource(); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + + virtual ossimScalarType getOutputScalarType() const; + virtual ossim_uint32 getNumberOfOutputBands()const; + virtual double getNullPixelValue()const; + virtual double getMinPixelValue(ossim_uint32 band=0)const; + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + + virtual void initialize(); + +protected: + + /** + * Called on first getTile, will initialize all data needed. + */ + void allocate(); + + ossimRefPtr<ossimImageData> theBlankTile; + ossimRefPtr<ossimImageData> theTile; + +TYPE_DATA +}; + +#endif /* #ifndef ossimRgbToHsiSource_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToHsvSource.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToHsvSource.cpp new file mode 100644 index 0000000000..9a16125242 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToHsvSource.cpp @@ -0,0 +1,155 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimRgbToHsvSource.cpp,v 1.8 2005/02/11 15:07:34 dburken Exp $ +#include "ossimRgbToHsvSource.h" +#include "imaging/ossimImageData.h" +#include "base/common/ossimConstants.h" +#include "base/common/ossimCommon.h" +#include "base/data_types/color_space/ossimHsvVector.h" +#include "base/data_types/color_space/ossimRgbVector.h" +#include "imaging/factory/ossimImageDataFactory.h" + +RTTI_DEF1(ossimRgbToHsvSource, "ossimRgbToHsvSource", ossimImageSourceFilter) + +ossimRgbToHsvSource::ossimRgbToHsvSource() + :ossimImageSourceFilter(), + theBlankTile(NULL), + theTile(NULL) +{ +} + + +ossimRgbToHsvSource::ossimRgbToHsvSource(ossimImageSource* inputSource) + : ossimImageSourceFilter(inputSource), + theBlankTile(NULL), + theTile(NULL) +{ +} + +ossimRgbToHsvSource::~ossimRgbToHsvSource() +{ +} + +ossimRefPtr<ossimImageData> ossimRgbToHsvSource::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if(!theInputConnection) + { + return ossimRefPtr<ossimImageData>(); // This filter requires an input. + } + + ossimRefPtr<ossimImageData> inputTile = + theInputConnection->getTile(tileRect, resLevel); + if(!isSourceEnabled() || !inputTile.valid()) + { + return inputTile; + } + + if(!theTile.valid()) + { + allocate(); // First time through... + } + + if (!theTile.valid()) // throw exeption... + { + return inputTile; + } + + if( inputTile->getDataObjectStatus() == OSSIM_NULL || + inputTile->getDataObjectStatus() == OSSIM_EMPTY ) + { + theBlankTile->setImageRectangle(tileRect); + return theBlankTile; + } + + if((inputTile->getNumberOfBands()==3)&& + (inputTile->getScalarType()==OSSIM_UCHAR)&& + (inputTile->getDataObjectStatus()!=OSSIM_NULL)) + { + // Set the origin, resize if needed of the output tile. + theTile->setImageRectangle(tileRect); + + float* outputBands[3]; + ossim_uint8* inputBands[3]; + outputBands[0] = static_cast<float*>(theTile->getBuf(0)); + outputBands[1] = static_cast<float*>(theTile->getBuf(1)); + outputBands[2] = static_cast<float*>(theTile->getBuf(2)); + inputBands[0] = static_cast<ossim_uint8*>(inputTile->getBuf(0)); + inputBands[1] = static_cast<ossim_uint8*>(inputTile->getBuf(1)); + inputBands[2] = static_cast<ossim_uint8*>(inputTile->getBuf(2)); + + long height = inputTile->getHeight(); + long width = inputTile->getWidth(); + long offset = 0; + for(long row = 0; row < height; ++row) + { + for(long col = 0; col < width; ++col) + { + ossimRgbVector rgb(inputBands[0][offset], + inputBands[1][offset], + inputBands[2][offset]); + + ossimHsvVector hsv(rgb); + + outputBands[0][offset] = hsv.getH(); + outputBands[1][offset] = hsv.getS(); + outputBands[2][offset] = hsv.getV(); + + ++offset; + } + } + } + else // Input tile not of correct type to process... + { + return inputTile; + } + theTile->validate(); + return theTile; +} + +void ossimRgbToHsvSource::initialize() +{ + // Base class will recapture "theInputConnection". + ossimImageSourceFilter::initialize(); +} + +void ossimRgbToHsvSource::allocate() +{ + theBlankTile = ossimImageDataFactory::instance()->create(this, this); + theTile = (ossimImageData*)theBlankTile->dup(); + theTile->initialize(); +} + +ossimScalarType ossimRgbToHsvSource::getOutputScalarType() const +{ + return OSSIM_NORMALIZED_FLOAT; +} + +ossim_uint32 ossimRgbToHsvSource::getNumberOfOutputBands()const +{ + return 3; +} + +double ossimRgbToHsvSource::getNullPixelValue()const +{ + return OSSIM_FLT_NAN; +} + +double ossimRgbToHsvSource::getMinPixelValue(ossim_uint32 band)const +{ + return 0.0; +} + +double ossimRgbToHsvSource::getMaxPixelValue(ossim_uint32 band)const +{ + return 1.0; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToHsvSource.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToHsvSource.h new file mode 100644 index 0000000000..67029d0b41 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToHsvSource.h @@ -0,0 +1,47 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimRgbToHsvSource.h,v 1.8 2005/02/11 15:07:34 dburken Exp $ +#ifndef ossimRgbToHsvSource_HEADER +#define ossimJpegRgbToYCbCrSource_HEADER +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +class ossimRgbToHsvSource : public ossimImageSourceFilter +{ +public: + ossimRgbToHsvSource(); + ossimRgbToHsvSource(ossimImageSource* inputSource); + virtual ~ossimRgbToHsvSource(); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + + virtual ossimScalarType getOutputScalarType() const; + virtual ossim_uint32 getNumberOfOutputBands()const; + virtual double getNullPixelValue()const; + virtual double getMinPixelValue(ossim_uint32 band=0)const; + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + + virtual void initialize(); + +protected: + + /** + * Called on first getTile, will initialize all data needed. + */ + void allocate(); + + ossimRefPtr<ossimImageData> theBlankTile; + ossimRefPtr<ossimImageData> theTile; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToIndexFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToIndexFilter.cpp new file mode 100644 index 0000000000..9133713d75 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToIndexFilter.cpp @@ -0,0 +1,227 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimRgbToIndexFilter.cpp,v 1.5 2005/07/16 14:28:03 dburken Exp $ + +#include <imaging/tile_sources/ossimRgbToIndexFilter.h> +#include <imaging/ossimImageData.h> +#include <imaging/factory/ossimImageDataFactory.h> + + +RTTI_DEF1(ossimRgbToIndexFilter, + "ossimRgbToIndexFilter", + ossimImageSourceFilter); + +ossimRgbToIndexFilter::ossimRgbToIndexFilter() + :ossimImageSourceFilter(), + theLut(0), + theTile(NULL) +{ +} + +ossimRgbToIndexFilter::ossimRgbToIndexFilter(ossimImageSource* inputSource, + const ossimRgbLutDataObject& rgbLut) + :ossimImageSourceFilter(inputSource), + theLut(rgbLut), + theTile(NULL) +{ +} + +ossimRgbToIndexFilter::~ossimRgbToIndexFilter() +{ +} + +void ossimRgbToIndexFilter::initialize() +{ + ossimImageSourceFilter::initialize(); + + // Force allocate on next getTile. + theTile = NULL; +} + +void ossimRgbToIndexFilter::allocate() +{ + theTile = NULL; + + if(isSourceEnabled()) + { + theTile = ossimImageDataFactory::instance()->create(this, this); + theTile->initialize(); + } +} + +void ossimRgbToIndexFilter::disableSource() +{ + ossimImageSourceFilter::disableSource(); + theTile = NULL; +} + +ossimRefPtr<ossimImageData> ossimRgbToIndexFilter::getTile( + const ossimIrect& origin, + ossim_uint32 resLevel) +{ + if(!theInputConnection) + { + return ossimRefPtr<ossimImageData>(); + } + + if(!theTile.valid()) + { + allocate(); + } + + ossimRefPtr<ossimImageData> input = theInputConnection->getTile(origin, + resLevel); + + if(!theTile.valid() || !input.valid()) + { + return input; + } + + theTile->setImageRectangle(origin); + + if(input->getScalarType() == OSSIM_UCHAR) + { + theTile->setDataObjectStatus(OSSIM_FULL); + return convertInputTile(input); + } + else + { + theTile->makeBlank(); + } + + theTile->setDataObjectStatus(OSSIM_FULL); + + return theTile; +} + +ossimRefPtr<ossimImageData> ossimRgbToIndexFilter::convertInputTile(ossimRefPtr<ossimImageData>& tile) +{ + if (!tile) + { + return theTile; + } + + const ossim_uint32 BANDS = tile->getNumberOfBands(); + + if (!BANDS) + { + return theTile; + } + + ossim_uint8* band[3]; + ossim_uint8* outBand = (ossim_uint8*)theTile->getBuf(); + + if(BANDS >= 3) + { + band[0] = (ossim_uint8*)(tile->getBuf(0)); + band[1] = (ossim_uint8*)(tile->getBuf(1)); + band[2] = (ossim_uint8*)(tile->getBuf(2)); + } + else + { + band[0] = (ossim_uint8*)(tile->getBuf(0)); + band[1] = (ossim_uint8*)(tile->getBuf(0)); + band[2] = (ossim_uint8*)(tile->getBuf(0)); + } + + if(band[0]) + { + ossim_uint32 upper = tile->getWidth()*tile->getHeight(); + + for(ossim_uint32 offset = 0; offset < upper; ++offset) + { + *outBand = theLut.findIndex(*band[0], *band[1], *band[2]); + + ++outBand; + ++band[0]; + ++band[1]; + ++band[2]; + } + } + + return theTile; +} + +bool ossimRgbToIndexFilter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimString newPrefix = prefix; + newPrefix = newPrefix + "lut."; + + theLut.saveState(kwl, newPrefix.c_str()); + + return ossimImageSourceFilter::saveState(kwl, prefix); +} + +bool ossimRgbToIndexFilter::loadState(const ossimKeywordlist& kwl, const char* prefix) +{ + ossimString newPrefix = prefix; + newPrefix = newPrefix + "lut."; + + theLut.loadState(kwl, newPrefix.c_str()); + + return ossimImageSourceFilter::loadState(kwl, prefix); +} + +ossim_uint32 ossimRgbToIndexFilter::getNumberOfOutputBands() const +{ + if(isSourceEnabled()) + { + return 1; + } + + return ossimImageSourceFilter::getNumberOfOutputBands(); +} + +ossimScalarType ossimRgbToIndexFilter::getOutputScalarType() const +{ + if(isSourceEnabled()) + { + return OSSIM_UCHAR; + } + + return ossimImageSourceFilter::getOutputScalarType(); +} + +void ossimRgbToIndexFilter::setLut(ossimRgbLutDataObject& lut) +{ + theLut = lut; +} + +double ossimRgbToIndexFilter::getNullPixelValue(ossim_uint32 band)const +{ + if(isSourceEnabled()) + { + return 0.0; + } + + return ossimImageSourceFilter::getNullPixelValue(band); +} + +double ossimRgbToIndexFilter::getMinPixelValue(ossim_uint32 band)const +{ + if(isSourceEnabled()) + { + return 1.0; + } + + return ossimImageSourceFilter::getMinPixelValue(); +} + +double ossimRgbToIndexFilter::getMaxPixelValue(ossim_uint32 band)const +{ + if(isSourceEnabled()) + { + return 255.0; + } + + return ossimImageSourceFilter::getMaxPixelValue(); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToIndexFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToIndexFilter.h new file mode 100644 index 0000000000..452b731ce7 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToIndexFilter.h @@ -0,0 +1,96 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimRgbToIndexFilter.h,v 1.4 2005/02/11 15:07:34 dburken Exp $ +#ifndef ossimRgbToIndexFilter_HEADER +#define ossimRgbToIndexFilter_HEADER +#include <base/data_types/color_space/ossimRgbVector.h> +#include <base/common/ossimRgbLutDataObject.h> +#include <base/data_types/ossimFilename.h> +#include <imaging/tile_sources/ossimImageSourceFilter.h> +#include <vector> + +class ossimImageData; + +/*! + * It will map the input data to an 8-bit index table. The table + * <pre> + * + * Example keyword list: + * + * type: ossimRgbToIndexFilter + * + * If you want to load from a file then just do: + * + * lut.filename: <full path to lut file> + * + * If you have the lut table in line then it must look like this: + * + * lut.entry0: 204 102 1 + * lut.entry1: 255 204 153 + * lut.entry2: 51 204 204 + * lut.number_of_entries: 3 + * lut.type: ossimRgbLutDataObject + * + * </pre> + */ +class ossimRgbToIndexFilter : public ossimImageSourceFilter +{ +public: + /*! + * Initializes the min value to 0 and the max value to 4000. + */ + ossimRgbToIndexFilter(); + ossimRgbToIndexFilter(ossimImageSource* inputSource, + const ossimRgbLutDataObject& rgbLut); + virtual ~ossimRgbToIndexFilter(); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& origin, + ossim_uint32 resLevel=0); + + virtual ossim_uint32 getNumberOfOutputBands() const; + + virtual ossimScalarType getOutputScalarType() const; + + void setLut(ossimRgbLutDataObject& lut); + + void setLut(const ossimFilename& file); + + virtual void disableSource(); + + virtual double getNullPixelValue(ossim_uint32 band=0)const; + + virtual double getMinPixelValue(ossim_uint32 band=0)const; + + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + + virtual void initialize(); + + /*! + * Saves the state of this object. + */ + virtual bool saveState(ossimKeywordlist& kwl, const char* prefix=0)const; + + /*! + * Loads the state of this object. + */ + virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix=0); +protected: + void allocate(); + + virtual ossimRefPtr<ossimImageData> convertInputTile(ossimRefPtr<ossimImageData>& tile); + + ossimRgbLutDataObject theLut; + ossimRefPtr<ossimImageData> theTile; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToJpegYCbCrSource.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToJpegYCbCrSource.cpp new file mode 100644 index 0000000000..da82a7002b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToJpegYCbCrSource.cpp @@ -0,0 +1,93 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimRgbToJpegYCbCrSource.cpp,v 1.6 2005/02/11 15:07:34 dburken Exp $ +#include <imaging/tile_sources/ossimRgbToJpegYCbCrSource.h> +#include <imaging/ossimImageData.h> +#include <base/common/ossimConstants.h> +#include <base/common/ossimCommon.h> +#include <base/data_types/color_space/ossimJpegYCbCrVector.h> +#include <base/data_types/color_space/ossimRgbVector.h> + +RTTI_DEF1(ossimRgbToJpegYCbCrSource, + "ossimRgbToJpegYCbCrSource", + ossimImageSourceFilter) + +ossimRgbToJpegYCbCrSource::ossimRgbToJpegYCbCrSource() + :ossimImageSourceFilter() +{ + theBlankTile = new ossimImageData(this, + OSSIM_UCHAR, + 3); +} + +ossimRgbToJpegYCbCrSource::ossimRgbToJpegYCbCrSource(ossimImageSource* inputSource) + : ossimImageSourceFilter(inputSource) +{ +} + +ossimRgbToJpegYCbCrSource::~ossimRgbToJpegYCbCrSource() +{ +} + +ossimRefPtr<ossimImageData> ossimRgbToJpegYCbCrSource::getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + theBlankTile->setOrigin(tileRect.ul()); + theBlankTile->setWidthHeight(tileRect.width(), tileRect.height()); + + if(theInputConnection) + { + ossimRefPtr<ossimImageData> imageData = theInputConnection->getTile(tileRect, + resLevel); + if(!imageData.valid()) + { + return theBlankTile; + } + if((isSourceEnabled())&& + (imageData->getNumberOfBands()==3)&& + (imageData->getScalarType()==OSSIM_UCHAR)&& + (imageData->getDataObjectStatus()!=OSSIM_NULL)&& + (imageData->getDataObjectStatus()!=OSSIM_EMPTY)) + { + ossim_uint8* bands[3]; + + bands[0] = static_cast<ossim_uint8*>(imageData->getBuf(0)); + bands[1] = static_cast<ossim_uint8*>(imageData->getBuf(1)); + bands[2] = static_cast<ossim_uint8*>(imageData->getBuf(2)); + + long height = imageData->getHeight(); + long width = imageData->getWidth(); + long offset = 0; + + for(long row = 0; row < height; ++row) + { + for(long col = 0; col < width; ++col) + { + ossimRgbVector rgb(bands[0][offset], + bands[1][offset], + bands[2][offset]); + + ossimJpegYCbCrVector ycbcr(rgb); + + + bands[0][offset] = ycbcr.getY(); + bands[1][offset] = ycbcr.getCb(); + bands[2][offset] = ycbcr.getCr(); + ++offset; + } + } + imageData->validate(); + } + return imageData; + } + + return theBlankTile; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToJpegYCbCrSource.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToJpegYCbCrSource.h new file mode 100644 index 0000000000..d4412ad064 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimRgbToJpegYCbCrSource.h @@ -0,0 +1,32 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimRgbToJpegYCbCrSource.h,v 1.6 2005/02/11 15:07:34 dburken Exp $ +#ifndef ossimRgbToJpegYCbCrSource_HEADER +#define ossimRgbToJpegYCbCrSource_HEADER +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +class ossimRgbToJpegYCbCrSource : public ossimImageSourceFilter +{ +public: + + ossimRgbToJpegYCbCrSource(); + ossimRgbToJpegYCbCrSource(ossimImageSource* inputSource); + virtual ~ossimRgbToJpegYCbCrSource(); + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + +protected: + ossimRefPtr<ossimImageData> theBlankTile; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimSFIMFusion.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimSFIMFusion.cpp new file mode 100644 index 0000000000..39050c914a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimSFIMFusion.cpp @@ -0,0 +1,285 @@ +//******************************************************************* +// Copyright (C) 2005 Garrett Potts +// +// LICENSE: See top level LICENSE.txt +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimSFIMFusion.cpp,v 1.2 2005/12/22 17:03:41 dburken Exp $ +#include "ossimSFIMFusion.h" +#include <matrix/newmat.h> +#include <matrix/newmatio.h> +#include <base/misc/ossim2dLinearRegression.h> +#include <base/data_types/color_space/ossimNormRgbVector.h> +#include <base/data_types/color_space/ossimHsiVector.h> +#include <imaging/factory/ossimImageDataFactory.h> + +RTTI_DEF2(ossimSFIMFusion, "ossimSFIMFusion", ossimFusionCombiner, ossimAdjustableParameterInterface); + + +static const ossim_uint32 HIGH_PASS_GAIN_OFFSET = 0; +static const ossim_uint32 PAN_BLURR_WIDTH_OFFSET = 1; +static const ossim_uint32 NUMBER_OF_ADJUSTABLE_PARAMETERS = 2; + +ossimSFIMFusion::ossimSFIMFusion() + :theBlurrKernelWidth(1.5), + theHighPassKernelWidth(3) +{ + theLowPassFilter = new ossimImageGaussianFilter; + theHighPassFilter = new ossimConvolutionSource; + + setFilters(); + + initAdjustableParameters(); +} + +ossimSFIMFusion::~ossimSFIMFusion() +{ +} + +ossimRefPtr<ossimImageData> ossimSFIMFusion::getTile(const ossimIrect& rect, + ossim_uint32 resLevel) +{ + if(!theInputConnection) + { + return ossimRefPtr<ossimImageData>(); + } + + if (!theIntensityConnection) + { + return theInputConnection->getTile(rect, resLevel); + } + + + + if(!theNormLowPassTile.valid()) + { + theNormLowPassTile = new ossimImageData(this, + OSSIM_NORMALIZED_FLOAT, + 1, + rect.width(), + rect.height()); + theNormHighPassTile = new ossimImageData(this, + OSSIM_NORMALIZED_FLOAT, + 1, + rect.width(), + rect.height()); + theNormLowPassTile->initialize(); + theNormHighPassTile->initialize(); + theNormLowPassTile->makeBlank(); + theNormHighPassTile->makeBlank(); + } + + theNormLowPassTile->setImageRectangle(rect); + theNormHighPassTile->setImageRectangle(rect); + theNormLowPassTile->makeBlank(); + theNormHighPassTile->makeBlank(); + + if(!theLowPassFilter->getInput() && getInput()) + { + initialize(); + } + + ossimRefPtr<ossimImageData> lowTile = theLowPassFilter->getTile(rect, resLevel); + ossimRefPtr<ossimImageData> highTile = theHighPassFilter->getTile(rect, resLevel); +// ossimRefPtr<ossimImageData> highTile = getNormIntensity(rect, resLevel); + + // if we don't have valid low and high pass then return the input color tile + // in its original format + // + if(!lowTile.valid()||!highTile.valid()) + { + return theInputConnection->getTile(rect, resLevel); + } + + if((lowTile->getDataObjectStatus() == OSSIM_EMPTY)|| + (!lowTile->getBuf()) || + (highTile->getDataObjectStatus() == OSSIM_EMPTY)|| + (!highTile->getBuf())) + { + return theInputConnection->getTile(rect, resLevel); + } + + ossimRefPtr<ossimImageData> normColorData = getNormTile(rect, resLevel); + + ossim_uint32 y = 0; + ossim_uint32 x = 0; + ossim_uint32 w = theTile->getWidth(); + ossim_uint32 h = theTile->getHeight(); + + theTile->makeBlank(); + theTile->setImageRectangle(rect); + + if(!normColorData.valid()) + { + return 0; +// return theTile; + } + + if((normColorData->getDataObjectStatus() == OSSIM_EMPTY)|| + !normColorData->getBuf()) + { + return theTile; + } + ossimRefPtr<ossimImageData> normColorOutputData = (ossimImageData*)normColorData->dup(); + normColorOutputData->setImageRectangle(rect); + normColorOutputData->loadTile(normColorData.get()); + + // ossim_float64 slopeResult = 0.0; + ossim_uint32 idx = 0; + std::vector<ossim_float32*> bands(normColorData->getNumberOfBands()); + + lowTile->copyTileToNormalizedBuffer((ossim_float32*)theNormLowPassTile->getBuf()); + + highTile->copyTileToNormalizedBuffer((ossim_float32*)theNormHighPassTile->getBuf()); + theNormLowPassTile->validate(); + theNormHighPassTile->validate(); + ossimRefPtr<ossimImageData> lowPan = (ossimImageData*)theNormLowPassTile->dup(); + lowPan->setImageRectangle(rect); + lowPan->loadTile(theNormLowPassTile.get()); + ossimRefPtr<ossimImageData> highPan = (ossimImageData*)theNormHighPassTile->dup(); + highPan->setImageRectangle(rect); + highPan->loadTile(theNormHighPassTile.get()); + + ossim_float32* panHigh = (ossim_float32*)highPan->getBuf(); + ossim_float32* panLow = (ossim_float32*)lowPan->getBuf(); + for(idx = 0; idx < bands.size(); ++idx) + { + bands[idx] = (ossim_float32*)normColorOutputData->getBuf(idx); + } + // double delta = 0.0; + ossim_uint32 bandsSize = bands.size(); + double normMinPix = 0.0; + for(y = 0; y < h; ++y) + { + for(x = 0; x < w; ++x) + { + for(idx = 0; idx < bandsSize; ++idx) + { + if((*bands[idx] != 0.0)&& + (*panLow > FLT_EPSILON) ) // if band is not null and not divide by 0 + { + normMinPix = (ossim_float32)normColorOutputData->getMinPix(idx); + *bands[idx] = ((*bands[idx])*(*panHigh))/ + (*panLow); + if(*bands[idx] > 1.0) *bands[idx] = 1.0; + if(*bands[idx] < normMinPix) *bands[idx] = normMinPix; + } + ++bands[idx]; + } + ++panHigh; + ++panLow; + } + } + + theTile->copyNormalizedBufferToTile((ossim_float32*)normColorOutputData->getBuf()); + theTile->validate(); + + return theTile; +} + +void ossimSFIMFusion::initialize() +{ + ossimFusionCombiner::initialize(); + if(!theIntensityConnection) + { + theLowPassFilter->disconnect(); + theHighPassFilter->disconnect(); + } + else + { + theLowPassFilter->connectMyInputTo(0, PTR_CAST(ossimConnectableObject, + theIntensityConnection->getObject())); + theHighPassFilter->connectMyInputTo(0, PTR_CAST(ossimConnectableObject, + theIntensityConnection->getObject())); + setFilters(); + theLowPassFilter->initialize(); + theHighPassFilter->initialize(); + } +} + +void ossimSFIMFusion::setFilters() +{ + theLowPassFilter->setGaussStd(theBlurrKernelWidth); + + theHighPassMatrix = NEWMAT::Matrix(theHighPassKernelWidth, theHighPassKernelWidth); + theHighPassMatrix = 0; + theHighPassMatrix[theHighPassKernelWidth>>1][theHighPassKernelWidth>>1] = 1; + + // adjust the gain for the high pass filter + // + NEWMAT::Matrix high = theHighPassMatrix; + + ossim_float64 kernelW2 = theHighPassKernelWidth*theHighPassKernelWidth; + double gain = computeParameterOffset(HIGH_PASS_GAIN_OFFSET)*(kernelW2); + double multiplier = gain/(kernelW2); + high = -multiplier; + ossim_int32 cx = theHighPassKernelWidth>>1; + ossim_int32 cy = theHighPassKernelWidth>>1; + + if(gain > FLT_EPSILON) + { + high[cy][cx] = multiplier* ( (kernelW2-1)+kernelW2/gain); + } + else + { + high = 0.0; + high[cy][cx] = 1.0; + } + + theHighPassFilter->setConvolution(high); +} + +void ossimSFIMFusion::initAdjustableParameters() +{ + resizeAdjustableParameterArray(NUMBER_OF_ADJUSTABLE_PARAMETERS); + + setAdjustableParameter(HIGH_PASS_GAIN_OFFSET, + -1.0); + setParameterDescription(HIGH_PASS_GAIN_OFFSET, + "High pass gain"); + setParameterSigma(HIGH_PASS_GAIN_OFFSET, + 1); + setParameterCenter(HIGH_PASS_GAIN_OFFSET, + 1.0); + + setAdjustableParameter(PAN_BLURR_WIDTH_OFFSET, + -1); + setParameterDescription(PAN_BLURR_WIDTH_OFFSET, + "Blurring kernel width"); + setParameterSigma(PAN_BLURR_WIDTH_OFFSET, + 7); + setParameterCenter(PAN_BLURR_WIDTH_OFFSET, + 7.5); + + + setParameterOffset(PAN_BLURR_WIDTH_OFFSET, + 1.5); +} + +void ossimSFIMFusion::adjustableParametersChanged() +{ +// std::cout << "Parameter offset = " << computeParameterOffset(2) << std::endl; + theBlurrKernelWidth = (ossim_uint32)(irint(computeParameterOffset(PAN_BLURR_WIDTH_OFFSET))); +} + + +bool ossimSFIMFusion::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + ossimFusionCombiner::saveState(kwl, prefix); + saveAdjustments(kwl, prefix); + + return true; +} + +bool ossimSFIMFusion::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimFusionCombiner::loadState(kwl, prefix); + loadAdjustments(kwl, prefix); + + + return true; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimSFIMFusion.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimSFIMFusion.h new file mode 100644 index 0000000000..4b4486597c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimSFIMFusion.h @@ -0,0 +1,76 @@ +//******************************************************************* +// Copyright (C) 2005 Garrett Potts +// +// LICENSE: See top level LICENSE.txt +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimSFIMFusion.h,v 1.3 2005/12/22 18:47:19 gpotts Exp $ +#ifndef ossimSFIMFusion_HEADER +#define ossimSFIMFusion_HEADER +#include "ossimFusionCombiner.h" +#include "ossimConvolutionSource.h" +#include "ossimImageGaussianFilter.h" +#include <base/misc/ossimAdjustableParameterInterface.h> + +/** + * This class imlements the fusion algorithm from the paper: + * + * "Smoothing Filter-based Intesity Modulation: a spectral preserve + * image fusion technique for improving spatial details" + * + * Pulished in INT. J. Remote Sensing, 2000, Vol. 21 NO. 18, 3461-3472 + * + * By J. G. LIU + */ +class OSSIM_DLL ossimSFIMFusion : public ossimFusionCombiner, + public ossimAdjustableParameterInterface +{ +public: + ossimSFIMFusion(); + virtual ~ossimSFIMFusion(); + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect, + ossim_uint32 resLevel=0); + virtual void initialize(); + + virtual ossimObject* getBaseObject() + { + return this; + } + virtual const ossimObject* getBaseObject()const + { + return this; + } + virtual void initAdjustableParameters(); + virtual void adjustableParametersChanged(); + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0) const; + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +protected: + void setFilters(); + bool computeRegression(ossim_float64& slopeResult, + const ossimIpt& origin, + ossimRefPtr<ossimImageData> panData, + ossimRefPtr<ossimImageData> colorData, + ossim_uint32 colorBandIdx); + + ossim_float64 theBlurrKernelWidth; + ossim_uint32 theHighPassKernelWidth; + // These are low and high pass filters for the single pan band + // + ossimRefPtr<ossimImageGaussianFilter> theLowPassFilter; + ossimRefPtr<ossimConvolutionSource> theHighPassFilter; + ossimRefPtr<ossimImageData> theNormLowPassTile; + ossimRefPtr<ossimImageData> theNormHighPassTile; + ossimRefPtr<ossimImageData> theNormColorData; + + NEWMAT::Matrix theHighPassMatrix; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimScalarRemapper.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimScalarRemapper.cpp new file mode 100644 index 0000000000..072573e56a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimScalarRemapper.cpp @@ -0,0 +1,554 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: David Burken +// +// Description: +// +// Contains class definition for ossimScalarRemapper. +// This class is used to remap image data from one scalar type to another. +// +//******************************************************************* +// $Id: ossimScalarRemapper.cpp,v 1.68 2005/12/20 17:55:56 dburken Exp $ + +#include <iostream> + +#include <imaging/tile_sources/ossimScalarRemapper.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/misc/lookup_tables/ossimScalarTypeLut.h> +#include <base/common/events/ossimPropertyEvent.h> +#include <base/common/events/ossimRefreshEvent.h> +#include <base/common/ossimTrace.h> +#include <base/property/ossimStringProperty.h> + +RTTI_DEF1(ossimScalarRemapper, + "ossimScalarRemapper", + ossimImageSourceFilter) + +static const ossimTrace traceDebug("ossimScalarRemapper:debug"); + +ossimScalarRemapper::ossimScalarRemapper() + : + ossimImageSourceFilter(), + theNormBuf(NULL), + theTile(NULL), + theOutputScalarType(OSSIM_UINT8), + theByPassFlag(false) +{ +} + +ossimScalarRemapper::ossimScalarRemapper(ossimImageSource* inputSource, + ossimScalarType outputScalarType) + : + ossimImageSourceFilter(inputSource), + theNormBuf(NULL), + theTile(NULL), + theOutputScalarType(outputScalarType), + theByPassFlag(false) +{ + if(inputSource) + { + if (inputSource->getOutputScalarType() == outputScalarType) + { + // Disable this filter simply return the inputSource's data. + theByPassFlag = true; + + // Nothing else to do. + } + else + { + theByPassFlag = false; + } + } + else + { + theByPassFlag = true; + } +} + +ossimScalarRemapper::~ossimScalarRemapper() +{ + destroy(); +} + +void ossimScalarRemapper::destroy() +{ + if (theNormBuf) + { + delete [] theNormBuf; + theNormBuf = NULL; + } + theTile = NULL; +} + +ossimRefPtr<ossimImageData> ossimScalarRemapper::getTile( + const ossimIrect& tileRect, ossim_uint32 resLevel) +{ + if(!theInputConnection) + { + return ossimRefPtr<ossimImageData>(); + } + + // Fetch tile from pointer from the input source. + ossimRefPtr<ossimImageData> inputTile = + theInputConnection->getTile(tileRect, resLevel); + + // Check for remap bypass: + if ( !isSourceEnabled()||theByPassFlag ) + { + return inputTile; + } + + // Check for first time through. + if ( !theTile.valid() ) + { + allocate(); + + if ( !theTile.valid() ) + { + // This can happen if input/output scalars are the same. + return inputTile; + } + } + + // Capture the size prior to a possible resize. + ossim_uint32 oldSize = theTile->getSize(); + + // Set the origin,bands of the output tile. + theTile->setImageRectangle(tileRect); + + ossim_uint32 newSize = theTile->getSize(); + + // Check for size change before possible return. + if(newSize != oldSize) + { + if(theNormBuf) + { + //--- + // Delete the current buffer since it is the wrong size. + // + // NOTE: + // We won't reallocate it yet since we could return without using it. + // It will be checked prior to using later. + //--- + delete [] theNormBuf; + theNormBuf = NULL; + } + } + + if ( !inputTile.valid() || + (inputTile->getDataObjectStatus() == OSSIM_NULL) || + (inputTile->getDataObjectStatus() == OSSIM_EMPTY) ) + { + //--- + // Since the filter is enabled, return theTile which is of the + // correct scalar type. + //--- + theTile->makeBlank(); + return theTile; + } + + if (!theNormBuf) // First time through or size changed and was deleted... + { + theNormBuf = new double[newSize]; + memset(theNormBuf, '\0', newSize); + } + + if (inputTile->getScalarType() == theOutputScalarType) + { + // Scalar types already the same. Nothing to do... + return inputTile; + } + + switch(inputTile->getScalarType()) + { + case OSSIM_NORMALIZED_DOUBLE: + { + // Un-normalize and copy the buffer to the destination tile. + theTile->copyNormalizedBufferToTile(static_cast<double*>( + inputTile->getBuf())); + break; + } + case OSSIM_NORMALIZED_FLOAT: + { + // Un-normalize and copy the buffer to the destination tile. + theTile->copyNormalizedBufferToTile(static_cast<float*>( + inputTile->getBuf())); + break; + } + default: + { + // Normalize and copy the source tile to a buffer. + inputTile->copyTileToNormalizedBuffer(theNormBuf); + + // Un-normalize and copy the buffer to the destination tile. + theTile->copyNormalizedBufferToTile(theNormBuf); + } + } + + theTile->validate(); + + return theTile; +} + +ossimScalarType ossimScalarRemapper::getOutputScalarType() const +{ + if(isSourceEnabled()&&!theByPassFlag) + { + return theOutputScalarType; + } + + return ossimImageSourceFilter::getOutputScalarType(); +} + +void ossimScalarRemapper::setOutputScalarType(ossimScalarType scalarType) +{ + if (scalarType == OSSIM_SCALAR_UNKNOWN) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimScalarRemapper::setOutputScalarType WARN:\n" + << "OSSIM_SCALAR_UNKNOWN passed to method. No action taken..." + << std::endl; + return; + } + + if (theInputConnection) + { + if ( scalarType == theInputConnection->getOutputScalarType() ) + { + // Input same as output, nothing for us to do... + theByPassFlag = true; + } + else // Types not equal... + { + theByPassFlag = false; + destroy(); + } + } + else // No input source, disable. + { + theByPassFlag = true; + } + + theOutputScalarType = scalarType; +} + +void ossimScalarRemapper::setOutputScalarType(ossimString scalarType) +{ + int scalar = + ossimScalarTypeLut::instance()->getEntryNumber(scalarType.c_str()); + + if (scalar != ossimLookUpTable::NOT_FOUND) + { + setOutputScalarType(static_cast<ossimScalarType>(scalar)); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimScalarRemapper ERROR:" + << "\nUnknown scalar type: " << scalarType.c_str() << std::endl; + } +} + +void ossimScalarRemapper::initialize() +{ + //--- + // Call the base class initialize. + // Note: This will reset "theInputConnection" if it changed... + //--- + ossimImageSourceFilter::initialize(); + + if (theInputConnection) + { + // Set the bypass flag accordingly... + if ( theInputConnection->getOutputScalarType() == + theOutputScalarType ) + { + theByPassFlag = true; + } + else + { + theByPassFlag = false; + } + + if (theTile.valid()) + { + //--- + // Check for: + // - bypass + // - disabled(!enabled) + // - scalar change + // - band count change + //--- + if ( theByPassFlag || + !theEnableFlag || + ( theInputConnection->getOutputScalarType() != + theOutputScalarType ) || + ( theInputConnection->getNumberOfOutputBands() != + theTile->getNumberOfBands() ) ) + { + destroy(); // Reallocated first unbypassed getTile. + } + } + } +} + +void ossimScalarRemapper::allocate() +{ + destroy(); + + if(!theInputConnection) // Nothing to do here. + { + setInitializedFlag(false); + theByPassFlag = true; + return; + } + + if (theOutputScalarType == OSSIM_SCALAR_UNKNOWN) + { + // default to OSSIM_UINT8 + theOutputScalarType = OSSIM_UINT8; + } + + if(theInputConnection && + (getOutputScalarType() != theInputConnection->getOutputScalarType())&& + (theInputConnection->getOutputScalarType() != OSSIM_SCALAR_UNKNOWN)&& + (getOutputScalarType() != OSSIM_SCALAR_UNKNOWN)) + { + theByPassFlag = false; + + theTile = ossimImageDataFactory::instance()->create(this, this); + + // Initialize the tile. + theTile->initialize(); + + // Set the base class flags to be initialized and enabled. + setInitializedFlag(true); + + } // End of "if(theInputConnection->isConnected()..." + else + { + // Set to not initialized and disabled. + setInitializedFlag(false); + theByPassFlag = true; + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimScalarRemapper::allocate() DEBUG" + << "\ninput scalar: " << theInputConnection->getOutputScalarType() + << "\noutput scalar: " << getOutputScalarType() + << "\nenabled: " << (isSourceEnabled()?"true":"false") + << std::endl; + } +} + +void ossimScalarRemapper::setProperty(ossimRefPtr<ossimProperty> property) +{ + if(!property) return; + + if(property->getName() == "Output scalar type") + { + theOutputScalarType = ossimScalarTypeLut::instance()-> + getScalarTypeFromString(property->valueToString()); + } + else + { + ossimImageSourceFilter::setProperty(property); + } +} + +ossimRefPtr<ossimProperty> ossimScalarRemapper::getProperty(const ossimString& name)const +{ + if(name == "Output scalar type") + { + std::vector<ossimString> scalarNames; + + ossim_int32 tableSize = (ossim_int32)ossimScalarTypeLut::instance()-> + getTableSize(); + ossim_int32 idx; + + for(idx = 0; idx < tableSize; ++idx) + { + scalarNames.push_back(ossimScalarTypeLut::instance()-> + getEntryString(idx)); + } + ossimStringProperty* stringProp = + new ossimStringProperty("Output scalar type", + ossimScalarTypeLut::instance()->getEntryString((ossim_int32)theOutputScalarType), + false, + scalarNames); + stringProp->clearChangeType(); + stringProp->setReadOnlyFlag(false); + stringProp->setCacheRefreshBit(); + + return stringProp; + } + + return ossimImageSourceFilter::getProperty(name); +} + +void ossimScalarRemapper::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + ossimImageSourceFilter::getPropertyNames(propertyNames); + propertyNames.push_back("Output scalar type"); +} + +bool ossimScalarRemapper::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + ossimImageSourceFilter::saveState(kwl, prefix); + + kwl.add(prefix, + ossimKeywordNames::SCALAR_TYPE_KW, + ossimScalarTypeLut::instance()->getEntryString(theOutputScalarType), + true); + + return true; +} + +bool ossimScalarRemapper::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimImageSourceFilter::loadState(kwl, prefix); + + if (kwl.getErrorStatus() == ossimErrorCodes::OSSIM_ERROR) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimScalarRemapper::loadState\n" + << " ERROR detected in keyword list! State not loaded." + << std::endl; + return false; + } + + int scalar = ossimScalarTypeLut::instance()->getEntryNumber(kwl, prefix); + + if (scalar != ossimLookUpTable::NOT_FOUND) + { + setOutputScalarType(static_cast<ossimScalarType>(scalar)); + } + + return true; +} + +ossimString ossimScalarRemapper::getOutputScalarTypeString() const +{ + return ossimScalarTypeLut::instance()->getEntryString(theOutputScalarType); +} + +void ossimScalarRemapper::propertyEvent(ossimPropertyEvent& event) +{ + // if my properties have changed then just initialize + // + if(event.getObject() == this) + { + initialize(); + } + else // if an input property has changed just check to see if the number + { // of bands has changed + + if(!theTile) + { + initialize(); + } + else + { + int b = theInputConnection->getNumberOfOutputBands(); + if((int)theTile->getNumberOfBands() != b) + { + initialize(); + } + } + } +} + +void ossimScalarRemapper::refreshEvent(ossimRefreshEvent& event) +{ + // if my properties have changed then just initialize + if(event.getObject() == this) + { + initialize(); + } + else // if an input property has changed just check to see if the number + { // of bands has changed + + if(!theTile) + { + initialize(); + } + else + { + int b = theInputConnection->getNumberOfOutputBands(); + if((int)theTile->getNumberOfBands() != b) + { + initialize(); + } + } + } +} + +double ossimScalarRemapper::getNullPixelValue(ossim_uint32 band) const +{ + if(!isSourceEnabled()||theByPassFlag) + { + if(theInputConnection) + { + return theInputConnection->getNullPixelValue(band); + } + } + else if(theTile.valid()) + { + theTile->getNullPix(band); + } + + return ossimGetDefaultNull(theOutputScalarType); +} + +double ossimScalarRemapper::getMinPixelValue(ossim_uint32 band) const +{ + if(!isSourceEnabled()||theByPassFlag) + { + if(theInputConnection) + { + return theInputConnection->getMinPixelValue(band); + } + } + else if(theTile.valid()) + { + theTile->getMinPix(band); + } + + return ossimGetDefaultMin(theOutputScalarType); +} + +double ossimScalarRemapper::getMaxPixelValue(ossim_uint32 band) const +{ + if(!isSourceEnabled()||theByPassFlag) + { + if(theInputConnection) + { + return theInputConnection->getMaxPixelValue(band); + } + } + else if(theTile.valid()) + { + theTile->getMaxPix(band); + } + + return ossimGetDefaultMax(theOutputScalarType); +} + +ossimString ossimScalarRemapper::getLongName()const +{ + return ossimString("Scalar Remapper, filters between different scalar types."); +} + +ossimString ossimScalarRemapper::getShortName()const +{ + return ossimString("Scalar Remapper"); +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimScalarRemapper.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimScalarRemapper.h new file mode 100644 index 0000000000..f3c3d1a96e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimScalarRemapper.h @@ -0,0 +1,108 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// License: See top level LICENSE.txt file. +// +// Author: David Burken +// +// Description: +// +// Contains class declartion for ossimScalarRemapper. +// This class is used to remap image data from one scalar type to another. +// +//******************************************************************* +// $Id: ossimScalarRemapper.h,v 1.22 2005/12/20 17:55:24 dburken Exp $ +#ifndef ossimScalarRemapper_HEADER +#define ossimScalarRemapper_HEADER + +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +class OSSIMDLLEXPORT ossimScalarRemapper : public ossimImageSourceFilter +{ +public: + ossimScalarRemapper(); + ossimScalarRemapper(ossimImageSource* inputSource, + ossimScalarType outputScalarType); + + virtual ~ossimScalarRemapper(); + + virtual void initialize(); + + virtual ossimString getLongName() const; + virtual ossimString getShortName() const; + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tile_rect, + ossim_uint32 resLevel=0); + + /** + * Returns the output pixel type of the tile source. This override the + * base class since it simply returns it's input scalar type which is + * not correct with this object. + */ + virtual ossimScalarType getOutputScalarType() const; + + /** + * Returns the output pixel type of the tile source as a string. + */ + virtual ossimString getOutputScalarTypeString() const; + + /** + * Sets the output scalar type. + */ + virtual void setOutputScalarType(ossimScalarType scalarType); + virtual void setOutputScalarType(ossimString scalarType); + + /** + * Sets the current resolution level. Returns true on success, false + * on error. + */ + virtual double getNullPixelValue(ossim_uint32 band) const; + virtual double getMinPixelValue(ossim_uint32 band=0) const; + virtual double getMaxPixelValue(ossim_uint32 band=0) const; + + /** + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=NULL)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=NULL); + + /** + * Override base class so that a disableSource event does not + * reinitialize the object and enable itself. + */ + virtual void propertyEvent(ossimPropertyEvent& event); + virtual void refreshEvent(ossimRefreshEvent& event); + + virtual void setProperty(ossimRefPtr<ossimProperty> property); + virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + +private: + + /** + * Called on first getTile, will initialize all data needed. + */ + void allocate(); + + /** + * Deletes allocated memory. Used by both allocate and destructor. + */ + void destroy(); + + double* theNormBuf; + ossimRefPtr<ossimImageData> theTile; + ossimScalarType theOutputScalarType; + + bool theByPassFlag; +TYPE_DATA +}; + +#endif /* #ifndef ossimScalarRemapper_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimScaleFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimScaleFilter.cpp new file mode 100644 index 0000000000..f35f2c3984 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimScaleFilter.cpp @@ -0,0 +1,908 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimScaleFilter.cpp,v 1.19 2005/12/25 17:14:57 dburken Exp $ +#include <imaging/tile_sources/ossimScaleFilter.h> +#include <imaging/filters/ossimFilter.h> +#include <imaging/filters/ossimDiscreteConvolutionKernel.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <projections/map_projections/ossimMapProjection.h> +#include <base/common/ossimKeywordNames.h> + +RTTI_DEF1(ossimScaleFilter, "ossimScaleFilter", ossimImageSourceFilter); + +ossimScaleFilter::ossimScaleFilter() + :ossimImageSourceFilter(), + theBlankTile(NULL), + theTile(NULL), + theMinifyFilter(NULL), + theMagnifyFilter(NULL), + theMinifyFilterType(ossimScaleFilter_NEAREST_NEIGHBOR), + theMagnifyFilterType(ossimScaleFilter_NEAREST_NEIGHBOR), + theScaleFactor(1.0, 1.0), + theInverseScaleFactor(1.0, 1.0), + theTileSize(64, 64), + theBlurFactor(1.0) +{ + theInputRect.makeNan(); + theMinifyFilter = new ossimNearestNeighborFilter(); + theMagnifyFilter = new ossimNearestNeighborFilter(); +} + +ossimScaleFilter::ossimScaleFilter(ossimImageSource* inputSource, + const ossimDpt& scaleFactor) + :ossimImageSourceFilter(inputSource), + theBlankTile(NULL), + theTile(NULL), + theMinifyFilter(NULL), + theMagnifyFilter(NULL), + theMinifyFilterType(ossimScaleFilter_NEAREST_NEIGHBOR), + theMagnifyFilterType(ossimScaleFilter_NEAREST_NEIGHBOR), + theScaleFactor(scaleFactor), + theTileSize(64, 64), + theBlurFactor(1.0) +{ + theInputRect.makeNan(); + theMinifyFilter = new ossimNearestNeighborFilter(); + theMagnifyFilter = new ossimNearestNeighborFilter(); +} + +ossimScaleFilter::~ossimScaleFilter() +{ + if(theMinifyFilter) + { + delete theMinifyFilter; + theMinifyFilter = NULL; + } + + if(theMagnifyFilter) + { + delete theMagnifyFilter; + theMagnifyFilter = NULL; + } +} + +ossimRefPtr<ossimImageData> ossimScaleFilter::getTile( + const ossimIrect& tileRect, ossim_uint32 resLevel) +{ + + if((!isSourceEnabled())|| + (!theInputConnection)|| + ((theScaleFactor.x == 1.0)&& + (theScaleFactor.y == 1.0)&& + (theBlurFactor == 1.0))) + { + return ossimImageSourceFilter::getTile(tileRect, resLevel); + } + if(!theTile.valid()) + { + allocate(); + } + + if(!theTile) + { + return ossimImageSourceFilter::getTile(tileRect, resLevel); + } + + theTile->makeBlank(); + + + ossimIrect imageRect = tileRect*theInverseScaleFactor; + + theTile->setImageRectangle(tileRect); + theBlankTile->setImageRectangle(tileRect); + + + double xSupport; + double ySupport; + + getSupport(xSupport, ySupport); + + ossimIpt deltaPt; + deltaPt.x = (ossim_int32)ceil(xSupport); + deltaPt.y = (ossim_int32)ceil(ySupport); + + imageRect = ossimIrect(imageRect.ul().x - (deltaPt.x), + imageRect.ul().y - (deltaPt.y), + imageRect.lr().x + (deltaPt.x), + imageRect.lr().y + (deltaPt.y)); + + + runFilter(imageRect, tileRect); + + theTile->validate(); + + return theTile; +} + +void ossimScaleFilter::runFilter(const ossimIrect& imageRect, + const ossimIrect& viewRect) +{ + switch(theTile->getScalarType()) + { + case OSSIM_UINT8: + { + runFilterTemplate((ossim_uint8)0, + imageRect, + viewRect); + break; + } + case OSSIM_USHORT11: + case OSSIM_UINT16: + { + runFilterTemplate((ossim_uint16)0, + imageRect, + viewRect); + break; + } + case OSSIM_SINT16: + { + runFilterTemplate((ossim_sint16)0, + imageRect, + viewRect); + break; + } + case OSSIM_UINT32: + { + runFilterTemplate((ossim_uint32)0, + imageRect, + viewRect); + break; + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + runFilterTemplate((ossim_float64)0, + imageRect, + viewRect); + break; + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + runFilterTemplate((ossim_float32)0, + imageRect, + viewRect); + break; + } + default: + break; + } +} + +template <class T> +void ossimScaleFilter::runFilterTemplate(T dummy, + const ossimIrect& imageRect, + const ossimIrect& viewRect) +{ + ossimRefPtr<ossimImageData> inputData = + theInputConnection->getTile(imageRect); + + if(!inputData.valid() || + !inputData->getBuf() || + (inputData->getDataObjectStatus() == OSSIM_EMPTY)) + { + return; + } + + ossim_int32 h = imageRect.height(); + ossimRefPtr<ossimImageData> tempData = + ossimImageDataFactory::instance()->create(NULL, + inputData->getScalarType(), + inputData->getNumberOfBands(), + viewRect.width(), + h); + tempData->setOrigin(ossimIpt(viewRect.ul().x, + imageRect.ul().y)); + + tempData->initialize(); + + if((theScaleFactor.x != 1.0)|| + (theBlurFactor != 1.0)) + { + runHorizontalFilterTemplate(dummy, + inputData, + tempData); + tempData->validate(); + } + else + { + tempData->loadTile(inputData.get()); + } + + if((theScaleFactor.y != 1.0)|| + (theBlurFactor != 1.0)) + { + runVerticalFilterTemplate(dummy, + tempData, + theTile); + } + else + { + theTile->loadTile(tempData.get()); + } + + theTile->validate(); +} + +ossimIrect ossimScaleFilter::getBoundingRect(ossim_uint32 resLevel)const +{ + ossimIrect result = ossimImageSourceFilter::getBoundingRect(resLevel); + + if(!result.hasNans()) + { + result = ossimIrect(result.ul().x, + result.ul().y, + result.lr().x+1, + result.lr().y+1); + result *= theScaleFactor; + } + + return result; +} + +void ossimScaleFilter::setFilterType(ossimScaleFilterType filterType) +{ + setFilterType(filterType, filterType); +} + + +void ossimScaleFilter::setFilterType(ossimScaleFilterType minifyFilterType, + ossimScaleFilterType magnifyFilterType) +{ + if(theMinifyFilter) + { + delete theMinifyFilter; + theMinifyFilter = NULL; + } + if(theMagnifyFilter) + { + delete theMagnifyFilter; + theMagnifyFilter = NULL; + } + + theMinifyFilterType = minifyFilterType; + theMagnifyFilterType = magnifyFilterType; + + theMinifyFilter = createNewFilter(minifyFilterType, theMinifyFilterType); + theMagnifyFilter = createNewFilter(magnifyFilterType, theMagnifyFilterType); +} + +ossimFilter* ossimScaleFilter::createNewFilter(ossimScaleFilterType filterType, + ossimScaleFilterType& result) +{ + switch(filterType) + { + case ossimScaleFilter_NEAREST_NEIGHBOR: + { + return new ossimNearestNeighborFilter(); + } + case ossimScaleFilter_BOX: + { + return new ossimBoxFilter(); + } + case ossimScaleFilter_GAUSSIAN: + { + return new ossimGaussianFilter(); + } + case ossimScaleFilter_CUBIC: + { + return new ossimCubicFilter(); + } + case ossimScaleFilter_HANNING: + { + return new ossimHanningFilter(); + } + case ossimScaleFilter_HAMMING: + { + return new ossimHammingFilter(); + } + case ossimScaleFilter_LANCZOS: + { + return new ossimLanczosFilter(); + } + case ossimScaleFilter_CATROM: + { + return new ossimCatromFilter(); + } + case ossimScaleFilter_MITCHELL: + { + return new ossimMitchellFilter(); + } + case ossimScaleFilter_BLACKMAN: + { + return new ossimBlackmanFilter(); + } + case ossimScaleFilter_BLACKMAN_SINC: + { + return new ossimBlackmanSincFilter(); + } + case ossimScaleFilter_BLACKMAN_BESSEL: + { + return new ossimBlackmanBesselFilter(); + } + case ossimScaleFilter_QUADRATIC: + { + return new ossimQuadraticFilter(); + } + case ossimScaleFilter_TRIANGLE: + { + return new ossimTriangleFilter(); + } + case ossimScaleFilter_HERMITE: + { + return new ossimHermiteFilter(); + } + + } + + result = ossimScaleFilter_NEAREST_NEIGHBOR; + return new ossimNearestNeighborFilter(); +} + +void ossimScaleFilter::setScaleFactor(const ossimDpt& scale) +{ + theScaleFactor = scale; + if(fabs(theScaleFactor.x) <= FLT_EPSILON) + { + theScaleFactor.x = 1.0; + } + if(fabs(theScaleFactor.y) <= FLT_EPSILON) + { + theScaleFactor.y = 1.0; + } + + theInverseScaleFactor.x = 1.0/theScaleFactor.x; + theInverseScaleFactor.y = 1.0/theScaleFactor.y; +} + + +template <class T> void ossimScaleFilter::runHorizontalFilterTemplate( + T dummy, + const ossimRefPtr<ossimImageData>& input, + ossimRefPtr<ossimImageData>& output) +{ + ossimIrect viewRect = output->getImageRectangle(); + ossimIrect imageRect = input->getImageRectangle(); + ossim_int32 vw = viewRect.width(); + ossim_int32 vh = viewRect.height(); + ossim_int32 iw = imageRect.width(); + ossimIpt origin(viewRect.ul()); + ossimIpt imageOrigin(imageRect.ul()); + ossimIpt inputUl = theInputRect.ul(); + ossimIpt inputLr = theInputRect.lr(); + + double scale = 0.0; + double support = 0.0; + ossim_int32 x = 0; + ossim_int32 y = 0; + ossim_int32 start = 0; + ossim_int32 stop = 0; + ossim_int32 kernelIdx = 0; + const ossimFilter* filter = getHorizontalFilter(); + ossim_float64 center = 0.0; + ossim_int32 bandIdx = 0; + ossim_int32 numberOfBands = theTile->getNumberOfBands(); + + scale = theBlurFactor*ossimMax(1.0/theScaleFactor.x, 1.0); + + support=scale*filter->getSupport(); + if (support <= 0.5) + { + support = 0.5 + FLT_EPSILON; + scale = 1.0; + } + scale=1.0/scale; + for(bandIdx = 0; bandIdx < numberOfBands; ++bandIdx) + { + T* imageBuf = (T*)input->getBuf(bandIdx); + T* viewBuf = (T*)output->getBuf(bandIdx); + T np = (T)input->getNullPix(bandIdx); + T outNp = (T)output->getNullPix(bandIdx); + T outMinPix = (T)output->getMinPix(bandIdx); + T outMaxPix = (T)output->getMaxPix(bandIdx); + + for(x = 0; x < vw; ++x) + { + center=(origin.x + x+ .5)/theScaleFactor.x; + start=ossimMax((ossim_int32)irint(center-support), (ossim_int32)inputUl.x); + stop=ossimMin((ossim_int32)irint(center+support), (ossim_int32)inputLr.x); + ossim_int32 delta = stop-start; + if (delta <= 0) + { + break; + } + vector<double> kernel(delta); + double density=0.0; + + for(kernelIdx = 0; kernelIdx < delta; ++kernelIdx) + { + double t = scale*(start + kernelIdx - + center + .5); + kernel[kernelIdx] = filter->filter(t, + filter->getSupport()); + density += kernel[kernelIdx]; + } + if ((density != 0.0) && (density != 1.0)) + { + /* + Normalize. + */ + density=1.0/density; + for (kernelIdx=0; kernelIdx < delta; kernelIdx++) + kernel[kernelIdx]*=density; + } + ossim_int32 offset = start - imageOrigin.x; + + T* xptr = imageBuf + offset; + T* xCenterptr = imageBuf + offset; + T* outptr = viewBuf + x; + + for(y = 0; y < vh; ++y) + { + double result = 0.0; + density = 0.0; + if((*xCenterptr) == np) + { + *outptr = outNp; + } + else + { + for(kernelIdx = 0; kernelIdx < (int)kernel.size(); ++kernelIdx) + { + if((*xptr != np)&& + (kernel[kernelIdx] != 0.0)) + { + result += ((double)(*(xptr+kernelIdx))*kernel[kernelIdx]); + density += kernel[kernelIdx]; + } + } + if(density != 0.0) + { + result /= density; + + if(result < outMinPix) result = outMinPix; + if(result > outMaxPix) result = outMaxPix; + + *outptr = (T)result; + } + else + { + *outptr = outNp; + } + } + xCenterptr += iw; + xptr += iw; + outptr += vw; + } + } + } +} + +template <class T> void ossimScaleFilter::runVerticalFilterTemplate( + T dummy, + const ossimRefPtr<ossimImageData>& input, + ossimRefPtr<ossimImageData>& output) +{ + ossimIrect viewRect = output->getImageRectangle(); + ossimIrect imageRect = input->getImageRectangle(); + ossim_int32 vw = viewRect.width(); + ossim_int32 vh = viewRect.height(); + ossim_int32 iw = imageRect.width(); + ossimIpt origin(viewRect.ul()); + ossimIpt imageOrigin(imageRect.ul()); + ossimIpt inputUl = theInputRect.ul(); + ossimIpt inputLr = theInputRect.lr(); + double scale = 0.0; + double support = 0.0; + ossim_int32 x = 0; + ossim_int32 y = 0; + ossim_int32 start = 0; + ossim_int32 stop = 0; + ossim_int32 kernelIdx = 0; + const ossimFilter* filter = getVerticalFilter(); + ossim_float64 center = 0.0; + ossim_int32 bandIdx = 0; + ossim_int32 numberOfBands = theTile->getNumberOfBands(); + + scale = theBlurFactor*ossimMax(1.0/theScaleFactor.y, 1.0); + + support=scale*filter->getSupport(); + if (support <= 0.5) + { + support = .5 + FLT_EPSILON; + scale = 1.0; + } + scale=1.0/scale; + + for(bandIdx = 0; bandIdx < numberOfBands; ++bandIdx) + { + T* imageBuf = (T*)input->getBuf(bandIdx); + T* viewBuf = (T*)output->getBuf(bandIdx); + T np = (T)input->getNullPix(bandIdx); + T outNp = (T)output->getNullPix(bandIdx); + T outMinPix = (T)output->getMinPix(bandIdx); + T outMaxPix = (T)output->getMaxPix(bandIdx); + + for(y = 0; y < vh; ++y) + { + center=(double) ((y + origin.y+0.5)/theScaleFactor.y); + start=ossimMax((ossim_int32)irint(center-support), (ossim_int32)inputUl.y); + stop=ossimMin((ossim_int32)irint(center+support), (ossim_int32)inputLr.y); + ossim_int32 delta = stop-start; + if (delta <= 0) + { + break; + } + vector<double> kernel(delta); + double density = 0.0; + for(kernelIdx = 0; kernelIdx < delta; ++kernelIdx) + { + kernel[kernelIdx] = filter->filter(scale*(start + kernelIdx - center + .5), + filter->getSupport()); + density += kernel[kernelIdx]; + } + if ((density != 0.0) && (density != 1.0)) + { + /* + Normalize. + */ + density=1.0/density; + for (kernelIdx=0; kernelIdx < delta; kernelIdx++) + kernel[kernelIdx]*=density; + } + + ossim_int32 offset = ((start - imageOrigin.y)*iw); + ossim_int32 offsetCenter = ((((ossim_int32)center) - imageOrigin.y)*iw); + + for(x = 0; x < vw; ++x) + { + T* yptr = imageBuf + offset + x; + T* yCenterptr = imageBuf + offsetCenter + x; + double result = 0.0; + density = 0.0; + + if((*yCenterptr) == np) + { + *viewBuf = outNp; + } + else + { + for(kernelIdx = 0; kernelIdx < delta; ++kernelIdx) + { + if((*yptr != np)&& + (kernel[kernelIdx] != 0.0)) + { + result += ((*yptr)*kernel[kernelIdx]); + density += kernel[kernelIdx]; + } + yptr += iw; + } + if(density != 0.0) + { + result /= density; + + if(result < outMinPix) result = outMinPix; + if(result > outMaxPix) result = outMaxPix; + + *viewBuf = (T)result; + } + else + { + *viewBuf = outNp; + } + } + ++viewBuf; + } + } + } +} + +void ossimScaleFilter::initialize() +{ + ossimImageSourceFilter::initialize(); + + // Force an allocate next getTile. + theTile = NULL; + theBlankTile = NULL; + theInputRect.makeNan(); +} + +void ossimScaleFilter::allocate() +{ + theTile = NULL; + theBlankTile = NULL; + theInputRect.makeNan(); + + if(theInputConnection&&isSourceEnabled()) + { + theTile = ossimImageDataFactory::instance()->create(this, this); + theBlankTile = ossimImageDataFactory::instance()->create(this, this); + + theTile->initialize(); + + theInputRect = theInputConnection->getBoundingRect(); + } +} + +bool ossimScaleFilter::getImageGeometry(ossimKeywordlist& kwl, + const char* prefix) +{ + if(theInputConnection) + { + theInputConnection->getImageGeometry(kwl, prefix); + + ossimProjection* proj = ossimProjectionFactoryRegistry::instance()->createProjection(kwl, + prefix); + + if(proj) + { + ossimMapProjection* mapProj = PTR_CAST(ossimMapProjection, + proj); + + if(mapProj) + { + mapProj->applyScale(theInverseScaleFactor, true); + + mapProj->saveState(kwl, prefix); + } + + delete proj; + + return true; + } + } + return false; +} + +ossimIrect ossimScaleFilter::scaleRect(const ossimIrect input, + const ossimDpt& scaleFactor)const +{ + ossimIpt origin(irint(input.ul().x*scaleFactor.x), + irint(input.ul().y*scaleFactor.y)); + ossim_int32 w = irint(input.width()*scaleFactor.x); + ossim_int32 h = irint(input.height()*scaleFactor.y); + + if(w < 1) w = 1; + if(h < 1) h = 1; + + return ossimIrect(origin.x, + origin.y, + origin.x + (w-1), + origin.y + (h-1)); +} + +ossimString ossimScaleFilter::getFilterTypeAsString(ossimScaleFilterType type)const +{ + switch(type) + { + case ossimScaleFilter_NEAREST_NEIGHBOR: + { + return "nearest_neighbor"; + } + case ossimScaleFilter_BOX: + { + return "box"; + } + case ossimScaleFilter_GAUSSIAN: + { + return "gaussian"; + } + case ossimScaleFilter_CUBIC: + { + return "cubic"; + } + case ossimScaleFilter_HANNING: + { + return "hanning"; + } + case ossimScaleFilter_HAMMING: + { + return "hamming"; + } + case ossimScaleFilter_LANCZOS: + { + return "lanczos"; + } + case ossimScaleFilter_MITCHELL: + { + return "mitchell"; + } + case ossimScaleFilter_CATROM: + { + return "catrom"; + } + case ossimScaleFilter_BLACKMAN: + { + return "blackman"; + } + case ossimScaleFilter_BLACKMAN_SINC: + { + return "blackman_sinc"; + } + case ossimScaleFilter_BLACKMAN_BESSEL: + { + return "blackman_bessel"; + } + case ossimScaleFilter_QUADRATIC: + { + return "quadratic"; + } + case ossimScaleFilter_TRIANGLE: + { + return "triangle"; + } + case ossimScaleFilter_HERMITE: + { + return "hermite"; + } + } + + return "nearest_neighbor"; +} + +ossimScaleFilter::ossimScaleFilterType ossimScaleFilter::getFilterType(const ossimString& type)const +{ + ossimString typeUpper = type; + typeUpper = typeUpper.upcase(); + + if(typeUpper.contains("BOX")) + { + return ossimScaleFilter_BOX; + } + else if(typeUpper.contains("NEAREST_NEIGHBOR")) + { + return ossimScaleFilter_NEAREST_NEIGHBOR; + } + else if(typeUpper.contains("GAUSSIAN")) + { + return ossimScaleFilter_GAUSSIAN; + } + else if(typeUpper.contains("HANNING")) + { + return ossimScaleFilter_HANNING; + } + else if(typeUpper.contains("HAMMING")) + { + return ossimScaleFilter_HAMMING; + } + else if(typeUpper.contains("LANCZOS")) + { + return ossimScaleFilter_LANCZOS; + } + else if(typeUpper.contains("MITCHELL")) + { + return ossimScaleFilter_MITCHELL; + } + else if(typeUpper.contains("CATROM")) + { + return ossimScaleFilter_CATROM; + } + else if(typeUpper.contains("CUBIC")) + { + return ossimScaleFilter_CUBIC; + } + else if(typeUpper.contains("BLACKMAN_BESSEL")) + { + return ossimScaleFilter_BLACKMAN_BESSEL; + } + else if(typeUpper.contains("BLACKMAN_SINC")) + { + return ossimScaleFilter_BLACKMAN_SINC; + } + else if(typeUpper.contains("BLACKMAN")) + { + return ossimScaleFilter_BLACKMAN; + } + else if(typeUpper.contains("QUADRATIC")) + { + return ossimScaleFilter_QUADRATIC; + } + else if(typeUpper.contains("TRIANGLE")) + { + return ossimScaleFilter_TRIANGLE; + } + else if(typeUpper.contains("HERMITE")) + { + return ossimScaleFilter_HERMITE; + } + + return ossimScaleFilter_NEAREST_NEIGHBOR; +} + +void ossimScaleFilter::getSupport(double& x, double& y) +{ + const ossimFilter* horizontalFilter = getHorizontalFilter(); + const ossimFilter* verticalFilter = getVerticalFilter(); + + x = theBlurFactor*ossimMax(1.0/theScaleFactor.x, 1.0)* + horizontalFilter->getSupport(); + y = theBlurFactor*ossimMax(1.0/theScaleFactor.y, 1.0)* + verticalFilter->getSupport(); +} + +const ossimFilter* ossimScaleFilter::getHorizontalFilter()const +{ + if(theScaleFactor.x < 1) + { + return theMinifyFilter; + } + + return theMagnifyFilter; +} + +const ossimFilter* ossimScaleFilter::getVerticalFilter()const +{ + if(theScaleFactor.y < 1) + { + return theMinifyFilter; + } + + return theMagnifyFilter; +} + + + +bool ossimScaleFilter::saveState(ossimKeywordlist& kwl, const char* prefix)const +{ + kwl.add(prefix, + ossimKeywordNames::SCALE_X_KW, + theScaleFactor.x, + true); + kwl.add(prefix, + ossimKeywordNames::SCALE_Y_KW, + theScaleFactor.y, + true); + kwl.add(prefix, + "minify_type", + getFilterTypeAsString(theMinifyFilterType), + true); + kwl.add(prefix, + "magnify_type", + getFilterTypeAsString(theMagnifyFilterType), + true); + + return ossimImageSourceFilter::saveState(kwl, prefix); +} + +bool ossimScaleFilter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimString scalex = kwl.find(prefix, + ossimKeywordNames::SCALE_X_KW); + ossimString scaley = kwl.find(prefix, + ossimKeywordNames::SCALE_Y_KW); + ossimString minify = kwl.find(prefix, + "minify_type"); + ossimString magnify = kwl.find(prefix, + "magnify_type"); + + theScaleFactor.x = scalex.toDouble(); + theScaleFactor.y = scaley.toDouble(); + + if(fabs(theScaleFactor.x) <= FLT_EPSILON) + { + theScaleFactor.x = 1.0; + } + if(fabs(theScaleFactor.y) <= FLT_EPSILON) + { + theScaleFactor.y = 1.0; + } + + theInverseScaleFactor.x = 1.0/theScaleFactor.x; + theInverseScaleFactor.y = 1.0/theScaleFactor.y; + + setFilterType(getFilterType(minify), + getFilterType(magnify)); + + return ossimImageSourceFilter::loadState(kwl, prefix); +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimScaleFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimScaleFilter.h new file mode 100644 index 0000000000..92dd9aeb21 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimScaleFilter.h @@ -0,0 +1,179 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimScaleFilter.h,v 1.12 2005/02/11 15:07:34 dburken Exp $ +#ifndef ossimScaleFilter_HEADER +#define ossimScaleFilter_HEADER +#include <vector> +#include <imaging/tile_sources/ossimImageSourceFilter.h> +#include <matrix/newmat.h> +#include <matrix/newmatio.h> +#include <imaging/filters/ossimFilter.h> + +/*! + */ +class ossimScaleFilter : public ossimImageSourceFilter +{ +public: + enum ossimScaleFilterType + { + ossimScaleFilter_NEAREST_NEIGHBOR = 0, + ossimScaleFilter_BOX = 1, + ossimScaleFilter_GAUSSIAN = 2, + ossimScaleFilter_CUBIC = 3, + ossimScaleFilter_HANNING = 4, + ossimScaleFilter_HAMMING = 5, + ossimScaleFilter_LANCZOS = 6, + ossimScaleFilter_MITCHELL = 7, + ossimScaleFilter_CATROM = 8, + ossimScaleFilter_BLACKMAN = 9, + ossimScaleFilter_BLACKMAN_SINC = 10, + ossimScaleFilter_BLACKMAN_BESSEL = 11, + ossimScaleFilter_QUADRATIC = 12, + ossimScaleFilter_TRIANGLE = 13, + ossimScaleFilter_HERMITE = 14 + }; + + ossimScaleFilter(); + ossimScaleFilter(ossimImageSource* inputSource, + const ossimDpt& scaleFactor); + virtual ~ossimScaleFilter(); + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + + virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0)const; + virtual bool getImageGeometry(ossimKeywordlist& kwl, + const char* prefix); + virtual void initialize(); + virtual void getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result)const + { + result.makeNan(); + + if(resLevel == 0) + { + result.x = 1.0; + result.y = 1.0; + } + } + virtual void getDecimationFactors(vector<ossimDpt>& decimations)const + { + decimations.push_back(ossimDpt(1.0, 1.0)); + } + virtual ossim_uint32 getNumberOfDecimationLevels()const + { + // only full res output since we are scaling + // + return 1; + } + void setFilterType(ossimScaleFilterType filterType); + void setFilterType(ossimScaleFilterType minifyFilterType, + ossimScaleFilterType magnifyFilterType); + + void setFilterType(const ossimString& minifyType, + const ossimString& magnifyType) + { + setFilterType(getFilterType(minifyType), + getFilterType(magnifyType)); + } + void setMinifyFilterType(const ossimString& minifyType) + { + setMinifyFilterType(getFilterType(minifyType)); + } + void setMagnifyFilterType(const ossimString& magnifyType) + { + setMagnifyFilterType(getFilterType(magnifyType)); + } + void setMinifyFilterType(ossimScaleFilterType filterType) + { + setFilterType(filterType, + theMagnifyFilterType); + } + void setMagnifyFilterType(ossimScaleFilterType filterType) + { + setFilterType(theMinifyFilterType,filterType); + } + ossimString getMinifyFilterTypeAsString()const + { + return getFilterTypeAsString(theMinifyFilterType); + } + ossimString getMagnifyFilterTypeAsString()const + { + return getFilterTypeAsString(theMagnifyFilterType); + } + void setScaleFactor(const ossimDpt& scale); + void setBlurFactor(ossim_float64 blur) + { + theBlurFactor = blur; + } + ossim_float64 getBlurFactor()const + { + return theBlurFactor; + } + const ossimDpt& getScaleFactor()const + { + return theScaleFactor; + } + /*! + * Saves the state of this object. + */ + virtual bool saveState(ossimKeywordlist& kwl, const char* prefix=0)const; + + /*! + * Loads the state of this object. + */ + virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix=0); + +protected: + void allocate(); + + ossimRefPtr<ossimImageData> theBlankTile; + ossimRefPtr<ossimImageData> theTile; + ossimFilter* theMinifyFilter; + ossimFilter* theMagnifyFilter; + ossimScaleFilterType theMinifyFilterType; + ossimScaleFilterType theMagnifyFilterType; + ossimDpt theScaleFactor; + ossimDpt theInverseScaleFactor; + ossimIpt theTileSize; + ossimIrect theInputRect; + ossim_float64 theBlurFactor; + + template <class T> + void runFilterTemplate(T dummy, + const ossimIrect& imageRect, + const ossimIrect& viewRect); + template <class T> + void runHorizontalFilterTemplate(T dummy, + const ossimRefPtr<ossimImageData>& input, + ossimRefPtr<ossimImageData>& output); + template <class T> + void runVerticalFilterTemplate(T dummy, + const ossimRefPtr<ossimImageData>& input, + ossimRefPtr<ossimImageData>& output); + void runFilter(const ossimIrect& imageRect, + const ossimIrect& viewRect); + + void getSupport(double& x, double& y); + const ossimFilter* getHorizontalFilter()const; + const ossimFilter* getVerticalFilter()const; + + ossimString getFilterTypeAsString(ossimScaleFilterType type)const; + ossimScaleFilterType getFilterType(const ossimString& type)const; + + ossimIrect scaleRect(const ossimIrect input, + const ossimDpt& scaleFactor)const; + ossimFilter* createNewFilter(ossimScaleFilterType filterType, + ossimScaleFilterType& result); +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimSubImageTileSource.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimSubImageTileSource.cpp new file mode 100644 index 0000000000..6b15916043 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimSubImageTileSource.cpp @@ -0,0 +1,224 @@ +//***************************************************************************** +// FILE: ossimSubImageTileSource.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// AUTHOR: Oscar Kramer +// +// DESCRIPTION: Contains implementation of class ossimSubImageTileSource. +// This tile source permits specifying an offset that is to be applied to the +// tile origin for all getTile() requests. It is intended for converting +// a full-image space coordinate to a sub-image coordinate. +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimSubImageTileSource.cpp,v 1.17 2005/09/15 12:28:44 gpotts Exp $ + +#include <imaging/tile_sources/ossimSubImageTileSource.h> +#include <base/data_types/ossimKeywordlist.h> +#include <imaging/ossimImageData.h> + +RTTI_DEF1(ossimSubImageTileSource, + "ossimSubImageTileSource", + ossimImageSourceFilter); + +static const char* SUBIMAGE_OFFSET_X = "offset_x"; +static const char* SUBIMAGE_OFFSET_Y = "offset_y"; + +ossimSubImageTileSource::ossimSubImageTileSource() + : ossimImageSourceFilter(), + theSubImageOffset(0, 0), + theTile(0) +{ +} + +ossimSubImageTileSource::ossimSubImageTileSource(ossimImageSource* inputSource) + : ossimImageSourceFilter(inputSource), theSubImageOffset(0, 0), + theTile(0) +{ +} + +ossimSubImageTileSource::ossimSubImageTileSource(ossimImageSource* inputSource, + const ossimIpt& offset) + : ossimImageSourceFilter(inputSource), theSubImageOffset(offset), + theTile(0) +{ +} + +ossimSubImageTileSource::~ossimSubImageTileSource() +{ +} + +//***************************************************************************** +// METHOD: ossimSubImageTileSource::getTile() +// +//***************************************************************************** +ossimRefPtr<ossimImageData> ossimSubImageTileSource::getTile( + const ossimIrect& rect, + ossim_uint32 res_level) +{ + ossimIpt offset = theSubImageOffset; + + if(res_level) + { + //*** + // Determine the offset for the particular rr level requested: + //*** + ossimDpt decimation_factor; + theInputConnection->getDecimationFactor(res_level, decimation_factor); + + if(!decimation_factor.hasNans()) + { + offset = ossimIpt((int)(theSubImageOffset.x*decimation_factor.x + 0.5), + (int)(theSubImageOffset.y*decimation_factor.y + 0.5)); + } + else + { + offset = theSubImageOffset; + } + } + // + // Apply the offset to the requested rect and fetch tile. The tile's origin + // needs to be adjusted to reflect the requested origin: + // + ossimIrect rect_prime (rect - offset); + + ossimRefPtr<ossimImageData> tile = + ossimImageSourceFilter::getTile(rect_prime, res_level); + + if(theTile.valid()) + { + theTile->setImageRectangle(rect_prime); + + if(tile.valid()) + { + theTile->loadTile(tile.get()); + } + else + { + theTile->makeBlank(); + } + } + else + { + if(tile.valid()) + { + theTile = (ossimImageData*)tile->dup(); + } + } + if(theTile.valid()) + { + theTile->setOrigin(rect.ul()); + theTile->validate(); + } + + return theTile; +} + +//***************************************************************************** +// METHOD: ossimSubImageTileSource::getBoundingRect() +// +//***************************************************************************** +ossimIrect ossimSubImageTileSource::getBoundingRect(ossim_uint32 resLevel) const +{ + ossimDrect result; + + result.makeNan(); + if(!theInputConnection) + return result; + ossimDpt offset = theSubImageOffset; + + ossimDrect rect (theInputConnection->getBoundingRect(resLevel)); + if(resLevel) + { + ossimDpt decimation_factor; + theInputConnection->getDecimationFactor(resLevel, decimation_factor); + + if(!decimation_factor.hasNans()) + { + rect*=decimation_factor; + offset= ossimDpt(theSubImageOffset.x*decimation_factor.x, + theSubImageOffset.y*decimation_factor.y); + } + } + ossimDrect rect_prime (rect + offset); + + return rect_prime; +} + +//***************************************************************************** +// METHOD: ossimSubImageTileSource::getValidImageVertices() +// +//***************************************************************************** +void ossimSubImageTileSource::getValidImageVertices(vector<ossimIpt>& vertices, + ossimVertexOrdering ordering, + ossim_uint32 resLevel) const +{ + if(!theInputConnection) + { + vertices.clear(); + return; + } + + ossimDpt offset (theSubImageOffset); + + theInputConnection->getValidImageVertices(vertices, ordering); + vector<ossimIpt>::iterator vertex = vertices.begin(); + + while (vertex != vertices.end()) + { + (*vertex) += offset; + vertex++; + } + + return; +} + +void ossimSubImageTileSource::initialize() +{ + ossimImageSourceFilter::initialize(); + + theTile = NULL; +} + +bool ossimSubImageTileSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* offset_x = kwl.find(prefix, SUBIMAGE_OFFSET_X); + const char* offset_y = kwl.find(prefix, SUBIMAGE_OFFSET_Y); + + if(offset_x) + { + theSubImageOffset.x = ossimString(offset_x).toLong(); + + } + if(offset_y) + { + theSubImageOffset.y = ossimString(offset_y).toLong(); + } + + return ossimImageSourceFilter::loadState(kwl, prefix); +} + +bool ossimSubImageTileSource::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + bool result = ossimImageSourceFilter::saveState(kwl, prefix); + + kwl.add(prefix, + SUBIMAGE_OFFSET_X, + theSubImageOffset.x, + true); + + kwl.add(prefix, + SUBIMAGE_OFFSET_Y, + theSubImageOffset.y, + true); + + return result; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimSubImageTileSource.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimSubImageTileSource.h new file mode 100644 index 0000000000..70c27df1f0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimSubImageTileSource.h @@ -0,0 +1,89 @@ +//***************************************************************************** +// FILE: ossimSubImageTileSource.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// AUTHOR: Oscar Kramer +// +// DESCRIPTION: Contains declaration of class ossimSubImageTileSource. +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimSubImageTileSource.h,v 1.11 2005/09/15 12:28:44 gpotts Exp $ + +#ifndef ossimSubImageTileSource_HEADER +#define ossimSubImageTileSource_HEADER + +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +/*!**************************************************************************** + * + * CLASS: ossimSubImageTileSource + * + * This tile source permits specifying an offset that is to be applied to the + * tile origin for all getTile() requests. It is intended for converting + * a full-image space coordinate to a sub-image coordinate. + * + *****************************************************************************/ +class ossimSubImageTileSource : public ossimImageSourceFilter +{ +public: + /*! + * Default constructor initializes the sub-image offset to zero. + */ + ossimSubImageTileSource(); + + /*! + * Constructor accepts an input source pointer. Offset is defaulted to (0,0). + */ + ossimSubImageTileSource(ossimImageSource* inputSource); + + /*! + * Constructs with specified input source and offset. + */ + ossimSubImageTileSource(ossimImageSource* inputSource, + const ossimIpt& offset); + + virtual ~ossimSubImageTileSource(); + /*! + * Permits setting the image's offset relative to the full image space. + */ + void setSubImageOffset(const ossimIpt& offset) { theSubImageOffset=offset; } + + ossimIpt getSubImageOffset()const{ return theSubImageOffset;} + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect, + ossim_uint32 rr_level=0); + + /*! + * Fetches the sub-image's bounding rect in FULL-IMAGE SPACE. + */ + virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0) const; + + /*! + * Fetches the sub-image's valid image vertices in FULL-IMAGE SPACE. + */ + virtual void getValidImageVertices(vector<ossimIpt>& validVertices, + ossimVertexOrdering ordering=OSSIM_CLOCKWISE_ORDER, + ossim_uint32 resLevel=0)const; + + virtual void initialize(); + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + +private: + ossimIpt theSubImageOffset; + ossimRefPtr<ossimImageData> theTile; + TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimTableRemapper.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimTableRemapper.cpp new file mode 100644 index 0000000000..9f724e7f01 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimTableRemapper.cpp @@ -0,0 +1,610 @@ +//******************************************************************* +// Copyright (C) 2003 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Table remapper class definition. +// +// Takes input tile, remaps it through a table, then output tile in the desired +// scalar type. +// +// Two modes one that works on native remap tables, that being of the same +// scalar type (like ossim_uint8) of the input connection, and another that +// uses a normalized remap table (more scalar independent). +// +//************************************************************************* +// $Id: ossimTableRemapper.cpp,v 1.20 2005/09/09 14:28:19 gpotts Exp $ + +#include <imaging/tile_sources/ossimTableRemapper.h> +#include <base/common/ossimTrace.h> +#include <base/misc/lookup_tables/ossimScalarTypeLut.h> +#include <base/context/ossimNotifyContext.h> +#include <imaging/factory/ossimImageDataFactory.h> + +RTTI_DEF1(ossimTableRemapper, "ossimTableRemapper", ossimImageSourceFilter) + +static ossimTrace traceDebug("ossimTableRemapper:debug"); + +static const char* TABLE_TYPE[] = { "UNKNOWN", "NATIVE", "NORMALIZED" }; + +ossimTableRemapper::ossimTableRemapper(ossimObject* owner) + : + ossimImageSourceFilter(owner), // base class + theTile(NULL), + theTmpTile(NULL), + theTable(NULL), + theNormBuf(NULL), + theTableBinCount(0), + theTableBandCount(0), + theTableType(ossimTableRemapper::UKNOWN), + theInputScalarType(OSSIM_SCALAR_UNKNOWN), + theOutputScalarType(OSSIM_SCALAR_UNKNOWN), + theTableOwnerFlag(true) +{ + //*** + // Set the base class "theEnableFlag" to off since no adjustments have been + // made yet. + //*** + disableSource(); +} + + +ossimTableRemapper::ossimTableRemapper(ossimImageSource* inputSource) + : + ossimImageSourceFilter (NULL, inputSource), // base class + theTile(NULL), + theTmpTile(NULL), + theTable(NULL), + theNormBuf(NULL), + theTableBinCount(0), + theTableBandCount(0), + theTableType(ossimTableRemapper::UKNOWN), + theInputScalarType(OSSIM_SCALAR_UNKNOWN), + theOutputScalarType(OSSIM_SCALAR_UNKNOWN), + theTableOwnerFlag(true) +{ + //*** + // Set the base class "theEnableFlag" to off since no adjustments have been + // made yet. + //*** + disableSource(); +} + + +ossimTableRemapper::ossimTableRemapper(ossimObject* owner, + ossimImageSource* inputSource) + : + ossimImageSourceFilter (owner, inputSource), // base class + theTile(NULL), + theTmpTile(NULL), + theTable(NULL), + theNormBuf(NULL), + theTableBinCount(0), + theTableBandCount(0), + theTableType(ossimTableRemapper::UKNOWN), + theInputScalarType(OSSIM_SCALAR_UNKNOWN), + theOutputScalarType(OSSIM_SCALAR_UNKNOWN), + theTableOwnerFlag(true) +{ + //*** + // Set the base class "theEnableFlag" to off since no adjustments have been + // made yet. + //*** + disableSource(); +} + +ossimTableRemapper::~ossimTableRemapper() +{ + destroy(); +} + +void ossimTableRemapper::destroy() +{ + if (theNormBuf) + { + delete [] theNormBuf; + theNormBuf = NULL; + } + if (theTableOwnerFlag && theTable) + { + delete [] theTable; + theTable = NULL; + } + theTmpTile = NULL; + theTile = NULL; +} + +void ossimTableRemapper::initialize() +{ + //--- + // Call the base class initialize. + // Note: This will reset "theInputConnection" if it changed... + //--- + ossimImageSourceFilter::initialize(); + if (theInputConnection) + { + // Since we override "getOutputScalarType" make sure something's set. + if (theOutputScalarType == OSSIM_SCALAR_UNKNOWN) + { + theOutputScalarType = theInputConnection->getOutputScalarType(); + } + + if (theTile.valid()) + { + if ( theTile->getNumberOfBands() != + theInputConnection->getNumberOfOutputBands() ) + { + // Wipe everything slick. The next getTile will call allocate. + destroy(); + } + } + } + + // Nothing else to do for this... +} + +void ossimTableRemapper::allocate(const ossimIrect& rect) +{ + //--- + // It's either first getTile or we've had either a resize, so allocate + // needed stuff... + //--- + destroy(); + + if (theInputConnection) + { + ossim_uint32 width = rect.width(); + ossim_uint32 height = rect.height(); + theInputScalarType = theInputConnection->getOutputScalarType(); + + theTile = + ossimImageDataFactory::instance()->create(this, + getOutputScalarType(), + getNumberOfOutputBands(), + width, + height); + + theTile->initialize(); + + if (theInputScalarType != getOutputScalarType() && + theTableType == ossimTableRemapper::NATIVE) + { + //--- + // We need a temp tile so we can do two remaps + // inputTile->remapTable->tmpTile then + // tmpTile->normalize->theTile(unnormalize to new scalar)... + //--- + theTmpTile + = ossimImageDataFactory::instance()->create(this, + theInputScalarType, + getNumberOfOutputBands(), + width, + height); + theTmpTile->initialize(); + } + + if (theTableType == ossimTableRemapper::NORMALIZED || + theInputScalarType != theOutputScalarType) + { + theNormBuf = new ossim_float64[theTile->getSize()]; + } + } +} + +ossimRefPtr<ossimImageData> ossimTableRemapper::getTile( + const ossimIrect& tile_rect, + ossim_uint32 resLevel) +{ + if(!theInputConnection) + { + return ossimRefPtr<ossimImageData>(); + } + + // Fetch tile from pointer from the input source. + ossimRefPtr<ossimImageData> inputTile = + theInputConnection->getTile(tile_rect, resLevel); + + if (!inputTile.valid()) // Just in case... + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimTableRemapper::getTile ERROR:" + << "\nReceived null pointer to tile from input source!" + << "\nReturning blank tile.\n"; + } + return inputTile; + } + + // Get its status. + ossimDataObjectStatus tile_status = inputTile->getDataObjectStatus(); + + // Check for remap bypass: + if ( !theEnableFlag || + tile_status == OSSIM_NULL || + tile_status == OSSIM_EMPTY ) + { + return inputTile; + } + + // OK we have an input tile... and it's not null or empty. + + // Check for first time through or size or band change. + if ( !theTile || + tile_rect.height() != theTile->getHeight() || + tile_rect.width() != theTile->getWidth() || + inputTile->getNumberOfBands() != theTile->getNumberOfBands()) + { + allocate(tile_rect); + } + + // Set the origin of the output tile. + theTile->setImageRectangle(tile_rect); + + // Think things are good. Do the real work... + if (theTableType == ossimTableRemapper::NATIVE) + { + // Most efficient case... + remapFromNativeTable(inputTile); + } + else + { + remapFromNormalizedTable(inputTile); + } + + theTile->validate(); + + return theTile; +} + +void ossimTableRemapper::remapFromNativeTable( + ossimRefPtr<ossimImageData>& inputTile) +{ + switch (theOutputScalarType) + { + case OSSIM_UCHAR: + { + remapFromNativeTable(ossim_uint8(0), inputTile); + break; + } + + case OSSIM_USHORT11: + case OSSIM_USHORT16: + { + remapFromNativeTable(ossim_uint16(0), inputTile); + break; + } + + case OSSIM_SSHORT16: + { + remapFromNativeTable(ossim_sint16(0), inputTile); + break; + } + + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT: + { + remapFromNativeTable(ossim_float32(0), inputTile); + break; + } + + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_DOUBLE: + { + remapFromNativeTable(ossim_float64(0), inputTile); + break; + } + + case OSSIM_SCALAR_UNKNOWN: + default: + { + // Shouldn't hit this. + ossimNotify(ossimNotifyLevel_WARN) + << "ossimTableRemapper::remapFromNativeTable" + << "\nOutput scalar type is OSSIM_SCALAR_UNKNOWN!\n"; + break; + } + + } // End of "switch (theTableType)" +} + +template <class T> void ossimTableRemapper::remapFromNativeTable( + T /* dummy */, + ossimRefPtr<ossimImageData>& inputTile) +{ + + const ossim_uint32 BANDS = theTile->getNumberOfBands(); + const ossim_uint32 PPB = theTile->getSizePerBand(); // pixels per band + + //--- + // NOTE: + // If (theTableBandCount == one) that means we only have one band; or, + // the user wanted to remap all bands using the same table... + //--- + const ossim_uint32 BAND_OFFSET = + (theTableBandCount != 1) ? theTableBinCount: 0; + + const T* rt = reinterpret_cast<T*>(theTable); // remap table (rt) + ossimRefPtr<ossimImageData> id = NULL; + if (theInputScalarType == theOutputScalarType) + { + id = theTile; + } + else + { + id = theTmpTile; + } + + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + const T NULL_PIX = static_cast<T>(id->getNullPix(band)); + const T MIN_PIX = static_cast<T>(id->getMinPix(band)); + + const T* s = static_cast<T*>(inputTile->getBuf(band)); // source (s) + T* d = static_cast<T*>(id->getBuf(band)); // destination (d) + + for (ossim_uint32 pixel = 0; pixel < PPB; ++pixel) + { + //--- + // Get the source pixel and use it as an index to the table. + // Note Null is always the "0" index, min always the "1". + //--- + T p = s[pixel]; + if (p == NULL_PIX) // Null is not always zero (dted). + { + p = 0; + } + else + { + p = (p+1-MIN_PIX); // If min == 1 we want that to map to index 1. + } + + ossim_uint32 table_index = static_cast<ossim_uint32>(p); + + //--- + // If within range use to index the remap table; else, null. + // Note: + // There is no min, max range checking on value retrieved from table. + // Range checking should be performed when the table is built. + //--- + d[pixel] =(table_index < theTableBinCount) ? rt[table_index] : NULL_PIX; + } + + rt += BAND_OFFSET; // Go to next band in the table. + } + + if (theInputScalarType != theOutputScalarType) + { + // Normalize and copy the temp tile to a buffer. + id->copyTileToNormalizedBuffer(theNormBuf); + + // Un-normalize and copy the buffer to the destination tile. + theTile->copyNormalizedBufferToTile(theNormBuf); + } +} + +void ossimTableRemapper::remapFromNormalizedTable( + ossimRefPtr<ossimImageData>& inputTile) +{ + if (!theNormBuf) // First time... + { + theNormBuf = new ossim_float64[theTile->getSize()]; + } + + // Normalize and copy the source tile to a buffer. + inputTile->copyTileToNormalizedBuffer(theNormBuf); + + const ossim_uint32 BANDS = theTile->getNumberOfBands(); + const ossim_uint32 PPB = theTile->getSizePerBand(); // pixels per band + + //--- + // NOTE: + // If (theTableBandCount == one) that means we only have one band; or, + // the user wanted to remap all bands using the same table... + //--- + const ossim_uint32 BAND_OFFSET = (theTableBandCount == 1) ? 0 : PPB; + + // remap table (rt) + ossim_float64* rt = reinterpret_cast<ossim_float64*>(theTable); + + ossim_float64* buf = theNormBuf; + + for (ossim_uint32 band = 0; band < BANDS; ++band) + { + for (ossim_uint32 pixel = 0; pixel < PPB; ++pixel) + { + // Get the source pixel... + ossim_uint32 index + = static_cast<ossim_uint32>(buf[pixel]*theTableBinCount+0.5); + + // If within range use to index the remap table; else, null. + ossim_float64 p = (index < theTableBinCount) ? rt[index] : 0.0; + + // Range check (in case table bad) and assign to destination pixel. + buf[pixel] + = (p >= 0.0) ? ( (p <=1.0) ? p : 1) : 0.0; + } + + // Go to next band. + rt += BAND_OFFSET; + buf += PPB; + } + + // Un-normalize and copy the buffer to the destination tile. + theTile->copyNormalizedBufferToTile(theNormBuf); +} + +ossimScalarType ossimTableRemapper::getOutputScalarType() const +{ + //--- + // Need to fix this as output scalar can be different from input. (drb) + //--- + return ossimImageSourceFilter::getOutputScalarType(); + +// if (theEnableFlag) +// { +// return theOutputScalarType; +// } +// else if (!theEnableFlag && theInputConnection) +// { +// // disabled return input scalar. +// theInputConnection->getOutputScalarType(); +// } + +// // No connection and disabled! +// return theOutputScalarType; +} + +void ossimTableRemapper::setTable(ossim_uint8* table, + ossim_uint32 table_bin_count, + ossim_uint32 table_band_count, + RemapTableType table_type, + ossimScalarType output_scalar_type, + bool own_table) +{ + // Start with a clean slate... + destroy(); + + theTable = table; + theTableBinCount = table_bin_count; + theTableBandCount = table_band_count; + theTableType = table_type; + theOutputScalarType = output_scalar_type; + + if (theInputConnection) + { + theEnableFlag = true; + } +} + +bool ossimTableRemapper::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + return ossimImageSourceFilter::loadState(kwl, prefix); +} + +bool ossimTableRemapper::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + return ossimImageSourceFilter::saveState(kwl, prefix); +} + +ostream& ossimTableRemapper::print(ostream& os) const +{ + ossimScalarTypeLut* sl = ossimScalarTypeLut::instance(); + + os << "\nossimTableRemapper::print:" + << "\ntheTableBinCount: " << theTableBinCount + << "\ntheTableBandCount: " << theTableBandCount + << "\ntheTableType: " << TABLE_TYPE[theTableType] + << "\ntheInputScalarType: " << (*sl)[theInputScalarType] + << "\ntheOutputScalarType: " << (*sl)[theOutputScalarType] + << "\ntheTableOwnerFlag: " << (theTableOwnerFlag ? "true" : "false") + << endl; + + if (theTile.valid()) + { + os << "theTile:\n" << *theTile << endl; + } + if (theTmpTile.valid()) + { + os << "theTmpTile:\n" << *theTmpTile << endl; + } + + switch (theOutputScalarType) + { + case OSSIM_UCHAR: + { + dumpTable(ossim_uint8(0), os); + break; + } + + case OSSIM_USHORT11: + case OSSIM_USHORT16: + { + dumpTable(ossim_uint16(0), os); + break; + } + + case OSSIM_SSHORT16: + { + dumpTable(ossim_sint16(0), os); + break; + } + + case OSSIM_NORMALIZED_FLOAT: + case OSSIM_FLOAT: + { + dumpTable(ossim_float32(0), os); + break; + } + + case OSSIM_NORMALIZED_DOUBLE: + case OSSIM_DOUBLE: + { + dumpTable(ossim_float64(0), os); + break; + } + + case OSSIM_SCALAR_UNKNOWN: + default: + { + // Shouldn't hit this. + ossimNotify(ossimNotifyLevel_WARN) + << "ossimTableRemapper::print OSSIM_SCALAR_UNKNOWN!\n"; + break; + } + + } // End of "switch (theTableType)" + + return os; +} + +template <class T> void ossimTableRemapper::dumpTable(T /*dummy*/, + ostream& os) const +{ + if (!theTable || !theTableBinCount || !theTableBandCount) + { + return; + } + + T* table = reinterpret_cast<T*>(theTable); + + ossim_uint32 table_index = 0; + for (ossim_uint32 band = 0; band < theTableBandCount; ++band) + { + for (ossim_uint32 index = 0; index < theTableBinCount; ++index) + { + os << "tabel[" << band << "][" << index << "]: " + << static_cast<int>(table[table_index]) << endl; + ++table_index; + } + } +} + +void ossimTableRemapper::setTableOwnership(bool flag) +{ + theTableOwnerFlag = flag; +} + +ostream& operator<<(ostream& os, const ossimTableRemapper& tr) +{ + return tr.print(os); +} + +// Private to disallow use... +ossimTableRemapper::ossimTableRemapper(const ossimTableRemapper&) +{ +} + +// Private to disallow use... +ossimTableRemapper& ossimTableRemapper::operator=(const ossimTableRemapper&) +{ + return *this; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimTableRemapper.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimTableRemapper.h new file mode 100644 index 0000000000..98b108cf12 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimTableRemapper.h @@ -0,0 +1,154 @@ +//******************************************************************* +// Copyright (C) 2003 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Table remapper class declaration. +// +// Takes input tile, remaps it through a table, then output tile in the desired +// scalar type. +// +// Two modes one that works on native remap tables, that being of the same +// scalar type (like ossim_uint8) of the input connection, and another that +// uses a normalized remap table (more scalar independent). +// +//************************************************************************* +// $Id: ossimTableRemapper.h,v 1.11 2005/02/11 15:07:34 dburken Exp $ +#ifndef ossimTableRemapper_HEADER +#define ossimTableRemapper_HEADER + +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +class OSSIMDLLEXPORT ossimTableRemapper : public ossimImageSourceFilter +{ +public: + enum RemapTableType + { + UKNOWN = 0, + NATIVE = 1, + NORMALIZED = 2 + }; + + + ossimTableRemapper(ossimObject* owner=NULL); + ossimTableRemapper(ossimImageSource* inputSource); + ossimTableRemapper(ossimObject* owner, ossimImageSource* inputSource); + + virtual ~ossimTableRemapper(); + + virtual ossimScalarType getOutputScalarType() const; + + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tile_rect, + ossim_uint32 resLevel=0); + + virtual void initialize(); + + + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + + virtual ostream& print(ostream& os) const; + + friend ostream& operator << (ostream& os, const ossimTableRemapper& tr); + +protected: + + /** + * Method: setTable + * + * @param table - ossim_uint8* to the table + * @param bin_count - number of bins in the table per band + * @param band_count - number of bands in the table + * @param table_type - Either ossimTableRemapper::NATIVE or + * ossimTableRemapper::NORMALIZED + * @param own_table - If true "this" object will destroy table on + * destruction. (default == true) + * + * Note on table: + * - It's alway passed in as an "ossim_uint8*" so that on destruction there + * are no complaints. You can do the math, if your table is really of + * double data type it's: + * "new ossim_uint8[bin_count * band_count * sizeof(double)]"... + * - For each band in the table: + * - Table index[0] should always be the null value. + * - Table index[1] should always be the min value. + * + * Note on band_count: + * - If the "band_count == 1", and the input source has more than one band, + * this implies that the same remap table will be used for all bands. + * + * Notes on RemapTableType: + * - If you want speed, use NATIVE, in which case the remap table scalar + * type should match input source. + * - If you want to be able to handle any scalar type with one table, use + * NORMALIZED, in which case, your table values should be + * between 0.0 and 1.0. + * + * Note on own_table flag: + * - If (own_table == true) this object will delete table on destruction. + * - If you want to use one table to remap many image chains you might + * build the table and manage the memory yourself; in which case, you + * would set the own_table false; else it will be de + */ + virtual void setTable(ossim_uint8* table, + ossim_uint32 table_bin_count, + ossim_uint32 table_band_count, + RemapTableType table_type, + ossimScalarType output_scalar_type, + bool own_table = true); + + /** + * @param flag Should be true if this object is owner of theTable, + * false if derived class or user is responsible for allocation, + * deletion of "theTable". + */ + virtual void setTableOwnership(bool flag); + + ossimRefPtr<ossimImageData> theTile; + ossimRefPtr<ossimImageData> theTmpTile; + ossim_uint8* theTable; + ossim_float64* theNormBuf; + ossim_uint32 theTableBinCount; + ossim_uint32 theTableBandCount; + RemapTableType theTableType; + ossimScalarType theInputScalarType; + ossimScalarType theOutputScalarType; + + bool theTableOwnerFlag; ///< True if "this" is responsible for memory. + + void allocate(const ossimIrect& rect); + void destroy(); + + void remapFromNativeTable(ossimRefPtr<ossimImageData>& inputTile); + + template <class T> void remapFromNativeTable( + T dummy, + ossimRefPtr<ossimImageData>& inputTile); + + void remapFromNormalizedTable(ossimRefPtr<ossimImageData>& inputTile); + + template <class T> void dumpTable(T dummy, ostream& os) const; + + // Do not allow copy constructor, operator=. + ossimTableRemapper(const ossimTableRemapper& tr); + ossimTableRemapper& operator=(const ossimTableRemapper& tr); + + TYPE_DATA +}; + +#endif /* #ifndef ossimTableRemapper_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimTopographicCorrectionFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimTopographicCorrectionFilter.cpp new file mode 100644 index 0000000000..e205f346ab --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimTopographicCorrectionFilter.cpp @@ -0,0 +1,1297 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimTopographicCorrectionFilter.cpp,v 1.31 2005/05/09 12:39:40 dburken Exp $ +#include <algorithm> +#include <sstream> +#include <imaging/tile_sources/ossimTopographicCorrectionFilter.h> +#include <imaging/tile_sources/ossimImageToPlaneNormalFilter.h> +//#include "ossimScalarRemapper.h" +#include <imaging/tile_sources/ossimScalarRemapper.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <matrix/newmat.h> +#include <base/data_types/ossimMatrix3x3.h> +#include <base/context/ossimNotifyContext.h> +#include <base/common/ossimKeywordNames.h> + +static const char* CORRECTION_TYPE_KW = "correction_type"; +static const char* C_COMPUTED_FLAG_KW = "c_computed_flag"; +static const char* NDVI_RANGE_KW = "ndvi_range"; + +RTTI_DEF1(ossimTopographicCorrectionFilter, "ossimTopographicCorrectionFilter", ossimImageCombiner); +ossimTopographicCorrectionFilter::ossimTopographicCorrectionFilter() + :ossimImageCombiner(NULL, 2, 0, true, false), + theTile(NULL), +// theScalarRemapper(NULL), + theLightSourceElevationAngle(45.0), + theLightSourceAzimuthAngle(45.0), + theJulianDay(0), + theCComputedFlag(false), + theTopoCorrectionType(TOPO_CORRECTION_COSINE), +// theTopoCorrectionType(TOPO_CORRECTION_MINNAERT), + theNdviLowTest(-0.1), + theNdviHighTest(0.1) +{ +// theScalarRemapper = new ossimScalarRemapper(); +// theScalarRemapper->setOutputScalarType(OSSIM_NORMALIZED_DOUBLE); +// theScalarRemapper->initialize(); +} + +ossimTopographicCorrectionFilter::ossimTopographicCorrectionFilter(ossimImageSource* colorSource, + ossimImageSource* elevSource) + :ossimImageCombiner(NULL, 2, 0, true, false), + theTile(NULL), + theLightSourceElevationAngle(45.0), + theLightSourceAzimuthAngle(45.0), + theJulianDay(0), + theCComputedFlag(false), + theTopoCorrectionType(TOPO_CORRECTION_COSINE), + theNdviLowTest(-0.1), + theNdviHighTest(0.1) +{ + connectMyInputTo(colorSource); + connectMyInputTo(elevSource); +} + +ossimTopographicCorrectionFilter::~ossimTopographicCorrectionFilter() +{ +} + +ossimRefPtr<ossimImageData> ossimTopographicCorrectionFilter::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + ossimImageSourceInterface* colorSource = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + ossimImageSourceInterface* normalSource = PTR_CAST(ossimImageSourceInterface, + getInput(1)); + + if(!isSourceEnabled()||!normalSource||!colorSource) + { + if(colorSource) + { + return colorSource->getTile(tileRect, resLevel); + } + } + + if(!theTile.valid()) + { + allocate(); + } + + if(!theTile) + { + return ossimRefPtr<ossimImageData>(); + } + + long w = tileRect.width(); + long h = tileRect.height(); + ossimIpt origin = tileRect.ul(); + + theTile->setOrigin(origin); + long tileW = theTile->getWidth(); + long tileH = theTile->getHeight(); + if((w != tileW)|| + (h != tileH)) + { + theTile->setWidth(w); + theTile->setHeight(h); + if((w*h)!=(tileW*tileH)) + { + theTile->initialize(); + } + else + { + theTile->makeBlank(); + } + } + else + { + theTile->makeBlank(); + } + + // ossimImageData* inputTile = NULL; + + ossimRefPtr<ossimImageData> normalData = normalSource->getTile(tileRect, + resLevel); + + ossimRefPtr<ossimImageData> colorData = colorSource->getTile(tileRect, + resLevel); + + if(!colorData.valid() || !normalData.valid()) + { + return theTile; + } + + if((normalData->getNumberOfBands() != 3)|| + (normalData->getScalarType() != OSSIM_DOUBLE)|| + !normalData->getBuf()|| + !colorData->getBuf()|| + (colorData->getDataObjectStatus() == OSSIM_EMPTY)|| + (normalData->getDataObjectStatus()==OSSIM_EMPTY)) + { + return colorData; + } + + executeTopographicCorrection(theTile, + colorData, + normalData); + theTile->validate(); + return theTile; +} + +void ossimTopographicCorrectionFilter::initialize() +{ + ossimImageCombiner::initialize(); + + // Force an "allocate()" on the first getTile. + theTile = NULL; +} + +void ossimTopographicCorrectionFilter::allocate() +{ + if(!getInput(0) || !getInput(1)) return; + theBandMapping.clear(); + if(isSourceEnabled()) + { + // ossimImageSourceInterface* colorSource = PTR_CAST(ossimImageSourceInterface, getInput(0)); + + theTile = ossimImageDataFactory::instance()->create(this, this); + theTile->initialize(); + + int arraySize = theTile->getNumberOfBands(); + if(theGain.size() > 0) + { + arraySize = theGain.size(); + } + // we will do a non destructive resize onf the arrays + // + resizeArrays(arraySize); + + ossimImageSourceInterface* input1 = PTR_CAST(ossimImageSourceInterface, + getInput(0)); + if(input1) + { + input1->getOutputBandList(theBandMapping); + for(ossim_uint32 idx = 0; idx < theBandMapping.size(); ++idx) + { + if(theBias.size()) + { + if(theBandMapping[idx] >= theBias.size()) + { + theBandMapping[idx] = theBias.size()-1; + } + } + else + { + theBandMapping[idx] = 0; + } + } + } + } + + computeLightDirection(); +} + +void ossimTopographicCorrectionFilter::computeLightDirection() +{ + NEWMAT::Matrix m = ossimMatrix3x3::createRotationMatrix(theLightSourceElevationAngle, + 0.0, + theLightSourceAzimuthAngle); + NEWMAT::ColumnVector v(3); + v[0] = 0; + v[1] = 1; + v[2] = 0; + v = m*v; + // reflect Z. We need the Z pointing up from the surface and not into it. + // + ossimColumnVector3d d(v[0], v[1], -v[2]); + d = d.unit(); + theLightDirection[0] = d[0]; + theLightDirection[1] = d[1]; + theLightDirection[2] = d[2]; +} + +void ossimTopographicCorrectionFilter::executeTopographicCorrection( + ossimRefPtr<ossimImageData>& outputData, + ossimRefPtr<ossimImageData>& colorData, + ossimRefPtr<ossimImageData>& normalData) +{ + switch(colorData->getScalarType()) + { + case OSSIM_UCHAR: + { + if(theTopoCorrectionType!=TOPO_CORRECTION_MINNAERT) + { + executeTopographicCorrectionTemplate((ossim_uint8)0, + outputData, + colorData, + normalData); + } + else + { + executeTopographicCorrectionMinnaertTemplate((ossim_uint8)0, + outputData, + colorData, + normalData); + } + break; + } + case OSSIM_USHORT11: + case OSSIM_USHORT16: + { + if(theTopoCorrectionType!=TOPO_CORRECTION_MINNAERT) + { + executeTopographicCorrectionTemplate((ossim_uint16)0, + outputData, + colorData, + normalData); + } + else + { + executeTopographicCorrectionMinnaertTemplate((ossim_uint16)0, + outputData, + colorData, + normalData); + } + break; + } + case OSSIM_SSHORT16: + { + if(theTopoCorrectionType!=TOPO_CORRECTION_MINNAERT) + { + executeTopographicCorrectionTemplate((ossim_sint16)0, + outputData, + colorData, + normalData); + } + else + { + executeTopographicCorrectionMinnaertTemplate((ossim_sint16)0, + outputData, + colorData, + normalData); + } + break; + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + if(theTopoCorrectionType!=TOPO_CORRECTION_MINNAERT) + { + executeTopographicCorrectionTemplate((ossim_float64)0, + outputData, + colorData, + normalData); + } + else + { + executeTopographicCorrectionMinnaertTemplate((ossim_float64)0, + outputData, + colorData, + normalData); + } + break; + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + if(theTopoCorrectionType!=TOPO_CORRECTION_MINNAERT) + { + executeTopographicCorrectionTemplate((ossim_float32)0, + outputData, + colorData, + normalData); + } + else + { + executeTopographicCorrectionMinnaertTemplate((ossim_float32)0, + outputData, + colorData, + normalData); + } + break; + } + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimTopographicCorrectionFilter::executeTopographicCorrection WARN: Not handling scalar type" + << endl; + } + } +} + +template <class T> +void ossimTopographicCorrectionFilter::executeTopographicCorrectionTemplate( + T dummy, + ossimRefPtr<ossimImageData>& outputData, + ossimRefPtr<ossimImageData>& colorData, + ossimRefPtr<ossimImageData>& normalData) +{ + ossim_int32 y = 0; + ossim_int32 x = 0; + ossim_int32 colorW = colorData->getWidth(); + ossim_int32 colorH = colorData->getHeight(); + + T* colorDataBand = 0; + T* outputDataBand = 0; + ossim_float64 colorNp = 0; + ossim_float64 colorMin = 0; + ossim_float64 colorMax = 0; + ossim_float64 outputDelta = 0;; + ossim_float64 outputMin = 0; + ossim_float64 outputMax = 0; + ossim_float64 outputNp; + double normalNp = normalData->getNullPix(0); + double LPrime = 0.0; + double LNew = 0.0; + double dn = 0.0; + double cosineZenith = cosd(90 - theLightSourceElevationAngle); + + if(!colorData->getBuf()|| + !normalData->getBuf()|| + (colorData->getDataObjectStatus() == OSSIM_EMPTY)) + { + return; + } + for(ossim_uint32 b = 0; b < outputData->getNumberOfBands();++b) + { + int mappedBand = theBandMapping[b]; + double* normalX = (double*)normalData->getBuf(0); + double* normalY = (double*)normalData->getBuf(1); + double* normalZ = (double*)normalData->getBuf(2); + double numerator = cosineZenith + theC[mappedBand]; + outputNp = (ossim_float64)outputData->getNullPix(b); + outputMin = (ossim_float64)outputData->getMinPix(b); + outputMax = (ossim_float64)outputData->getMaxPix(b); + outputDelta = outputMax - outputMin; + colorDataBand = (T*)(colorData->getBuf(b)); + colorNp = (ossim_float64)(colorData->getNullPix(b)); + colorMin = (ossim_float64)(colorData->getMinPix(b)); + colorMax = (ossim_float64)(colorData->getMaxPix(b)); + outputDataBand = (T*)(outputData->getBuf(b)); + bool theValuesAreGood = b < theC.size(); + double c = theC[mappedBand]; + if(theTopoCorrectionType != TOPO_CORRECTION_COSINE_C) + { + c = 0; + } + for(y = 0; y < colorH; ++y) + { + for(x = 0; x < colorW; ++x) + { + if((*colorDataBand) != colorNp) + { + if((*normalX != normalNp)&& + (*normalY != normalNp)&& + (*normalZ != normalNp)&& + theValuesAreGood) + { + + double cosineNewI = ((*normalX)*theLightDirection[0] + + (*normalY)*theLightDirection[1] + + (*normalZ)*theLightDirection[2]); + double cosineRatioDenom = (cosineNewI + c); + if((fabs(cosineRatioDenom) > FLT_EPSILON)&&(cosineNewI >= 0.0)) + { + double cosineRatio = numerator/cosineRatioDenom; + + LPrime = theGain[mappedBand]*((ossim_float64)(*colorDataBand)) + theBias[mappedBand]; + + LNew = LPrime*cosineRatio; + + dn = ((LNew-theBias[mappedBand])/theGain[mappedBand]); + + if(dn < colorMin) dn = colorMin; + if(dn > colorMax) dn = colorMax; + + *outputDataBand = (T)(dn); + } + else + { + *outputDataBand = (T)(*colorDataBand); + } + } + else + { + *outputDataBand = (T)(*colorDataBand); + } + } + else + { + *outputDataBand = (T)outputNp; + } + + ++outputDataBand; + ++colorDataBand; + ++normalX; + ++normalY; + ++normalZ; + } + } + } +} + +template <class T> +void ossimTopographicCorrectionFilter::executeTopographicCorrectionMinnaertTemplate( + T dummy, + ossimRefPtr<ossimImageData>& outputData, + ossimRefPtr<ossimImageData>& colorData, + ossimRefPtr<ossimImageData>& normalData) +{ + + ossim_int32 y = 0; + ossim_int32 x = 0; + ossim_int32 colorW = colorData->getWidth(); + ossim_int32 colorH = colorData->getHeight(); + + T* colorDataBand = 0; + T* outputDataBand = 0; + ossim_float64 colorNp = 0; + ossim_float64 colorMin = 0; + ossim_float64 colorMax = 0; + ossim_float64 outputDelta = 0;; + ossim_float64 outputMin = 0; + ossim_float64 outputMax = 0; + ossim_float64 outputNp; + double normalNp = normalData->getNullPix(0); + double LPrime = 0.0; + double LNew = 0.0; + double dn = 0.0; + + if(!colorData->getBuf()|| + !normalData->getBuf()|| + (colorData->getDataObjectStatus() == OSSIM_EMPTY)) + { + return; + } + int maxBands = ossimMin((int)theK.size(), (int)outputData->getNumberOfBands()); + for(int b = 0; b < maxBands;++b) + { + int mappedBand = theBandMapping[b]; + double* normalX = (double*)normalData->getBuf(0); + double* normalY = (double*)normalData->getBuf(1); + double* normalZ = (double*)normalData->getBuf(2); + outputNp = (ossim_float64)outputData->getNullPix(b); + outputMin = (ossim_float64)outputData->getMinPix(b); + outputMax = (ossim_float64)outputData->getMaxPix(b); + outputDelta = outputMax - outputMin; + colorDataBand = (T*)(colorData->getBuf(b)); + colorNp = (ossim_float64)(colorData->getNullPix(b)); + colorMin = (ossim_float64)(colorData->getMinPix(b)); + colorMax = (ossim_float64)(colorData->getMaxPix(b)); + outputDataBand = (T*)(outputData->getBuf(b)); + for(y = 0; y < colorH; ++y) + { + for(x = 0; x < colorW; ++x) + { + if((*colorDataBand) != colorNp) + { + if((*normalX != normalNp)&& + (*normalY != normalNp)&& + (*normalZ != normalNp)) + { + +// if(fabs(*normalZ) < FLT_EPSILON) +// { +// *normalZ = 0.0; +// } + double cosineNewI = (((*normalX)*theLightDirection[0] + + (*normalY)*theLightDirection[1] + + (*normalZ)*theLightDirection[2])); + double slopeAngle = acos(*normalZ); + double cosineSlope = cos(slopeAngle); + double k = theK[mappedBand]; + double cosineSlopeKPower = pow(cosineSlope, k); + double denom = pow((double)cosineNewI, k)*cosineSlopeKPower; + double numerator = cosineSlope; + +// double slopeAngle = asin(*normalZ); +// double tempK = theK[mappedBand]*cosineNewI; +// double denom = pow((double)cosineNewI*cosineSlope, theK[mappedBand]); +// double numerator = pow((double)cosineSlope, 1-tempK); +// if((fabs(denom) > .0001)&&(cosineNewI >= 0.0)) +// if((cosineNewI >= 0.0) &&fabs(denom) > .000001) + if(fabs(denom) > .00000001) + { +// double cosineRatio = cosineSlope/denom; + double cosineRatio = numerator/denom; + + LPrime = theGain[mappedBand]*((ossim_float64)(*colorDataBand)) + theBias[mappedBand]; + + LNew = LPrime*cosineRatio; + + dn = ((LNew-theBias[mappedBand])/theGain[mappedBand]); + + if(dn < colorMin) dn = colorMin; + if(dn > colorMax) dn = colorMax; + + *outputDataBand = (T)(dn); + } + else + { + *outputDataBand = (T)(*colorDataBand); + } + } + else + { + *outputDataBand = (T)(*colorDataBand); + } + } + else + { + *outputDataBand = (T)outputNp; + } + + ++outputDataBand; + ++colorDataBand; + ++normalX; + ++normalY; + ++normalZ; + } + } + } +} + + +#if 0 +void ossimTopographicCorrectionFilter::computeC() +{ + theCComputedFlag = false; + int b = 0; + int tileCount = 0; + bool done = false; + if(theC.size()<1) return; + + for(b = 0; b < (int) theC.size(); ++b) + { + theC[b] = 0.0; + } + + + theNdviLowTest = 0.1; + theNdviHighTest = 1; + + ossimImageSourceInterface* colorSource = PTR_CAST(ossimImageSourceInterface, getInput(0)); + ossimImageSourceInterface* normalSource = PTR_CAST(ossimImageSourceInterface, getInput(1)); + + if(!colorSource || !normalSource) + { + return; + } + std::vector<ossim2dLinearRegression> linearRegression(theC.size()); + ossimIrect normalRect = normalSource->getBoundingRect(); + ossimIrect colorRect = colorSource->getBoundingRect(); + ossimIrect clipRect = normalRect.clipToRect(colorRect); + ossimIpt ul = clipRect.ul(); + ossimIpt lr = clipRect.lr(); + ossimIpt tileSize(128,128); + ossim_int32 tilesHoriz = clipRect.width()/tileSize.x; + ossim_int32 tilesVert = clipRect.height()/tileSize.y; + + + if(!normalRect.intersects(colorRect)) + { + return; + } + ossim_int32 maxSize = tilesHoriz*tilesVert;//ossimMin(200, ); + + int idx = 0; + + idx = 0; + std::vector<int> cosineIBucketCount(10); + std::fill(cosineIBucketCount.begin(), cosineIBucketCount.end(), 0); + const int maxBucketCount = 1000; + bool goodCoefficients = false; + long numberOfRuns = 0; + while((!goodCoefficients)&&(numberOfRuns < 2)) + { + while((idx < maxSize)&& + (!done)) + { + ossim_int32 ty = idx/tilesHoriz; + ossim_int32 tx = idx%tilesHoriz; + + + ossim_int32 x = (ul.x + tx*tileSize.x); + ossim_int32 y = (ul.y + ty*tileSize.y); + + ossimIrect requestRect(x, + y, + x+tileSize.x-1, + y+tileSize.y-1); + + ossimRefPtr<ossimImageData> colorData = colorSource->getTile(requestRect); + ossimRefPtr<ossimImageData> normalData = normalSource->getTile(requestRect); + + switch(colorData->getScalarType()) + { + case OSSIM_UCHAR: + { + addRegressionPointsTemplate((ossim_uint8)0, + linearRegression, cosineIBucketCount, maxBucketCount, colorData, normalData); + break; + } + case OSSIM_USHORT11: + case OSSIM_USHORT16: + { + addRegressionPointsTemplate((ossim_uint16)0, + linearRegression, cosineIBucketCount, maxBucketCount, colorData, normalData); + break; + } + case OSSIM_SSHORT16: + { + addRegressionPointsTemplate((ossim_sint16)0, + linearRegression, cosineIBucketCount, maxBucketCount, colorData, normalData); + break; + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + addRegressionPointsTemplate((ossim_float32)0, + linearRegression, cosineIBucketCount, maxBucketCount, colorData, normalData); + break; + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + addRegressionPointsTemplate((ossim_float64)0, + linearRegression, cosineIBucketCount, maxBucketCount, colorData, normalData); + break; + } + } + if(((double)linearRegression[0].getNumberOfPoints()/(double)(maxBucketCount*10.0))>=.7) + { + done = true; + } + ++idx; + } + + double intercept, m; + long numberOfPositiveSlopes=0; + for(b=0;b<theC.size();++b) + { + if(linearRegression[b].getNumberOfPoints()>2) + { + linearRegression[b].solve(); + linearRegression[b].getEquation(m, intercept); + theC[b] = intercept/m; + + ossimNotify(ossimNotifyLevel_INFO) << "equation for b = " << b <<" is y = " << m << "*x + " << intercept << endl + << "with c = " << theC[b] << endl; + if(m >=0.0) + { + numberOfPositiveSlopes++; + } + } + } + for(idx = 0; idx < cosineIBucketCount.size(); ++idx) + { + ossimNotify(ossimNotifyLevel_INFO) << "bucket " << idx << " = " << cosineIBucketCount[idx] << endl; + } + if(numberOfPositiveSlopes > .5*theC.size()) + { + goodCoefficients = true; + } + else + { + ossimNotify(ossimNotifyLevel_WARN) << "ossimTopographicCorrectionFilter::computeC() WARN: not enough positive slopes" << endl + << "changing test to look for dirt areas" << endl; + theNdviLowTest = -1.0; + theNdviHighTest = .1; + for(b=0;b<theC.size();++b) + { + linearRegression[b].clear(); + } + } + ++numberOfRuns; + } + theCComputedFlag = true; +} + +template<class T> +void ossimTopographicCorrectionFilter::addRegressionPointsTemplate( + T, //dummy + std::vector<ossim2dLinearRegression>& regressionPoints, + std::vector<int>& cosineIBucketCount, + ossim_int32 maxCountPerBucket, + ossimRefPtr<ossimImageData>& colorData, + ossimRefPtr<ossimImageData>& normalData) +{ + if(!colorData||!normalData) + { + return; + } + if((colorData->getDataObjectStatus() == OSSIM_EMPTY)|| + (!colorData->getBuf())|| + (!normalData->getBuf())|| + (normalData->getDataObjectStatus()==OSSIM_EMPTY)) + { + return; + } + + ossim_float64* normalBands[3]; + ossim_float64 normalBandsNp[3]; + ossim_uint32 count=0; + ossim_uint32 b = 0; + std::vector<T*> colorBands(colorData->getNumberOfBands()); + std::vector<T> colorBandsNp(colorData->getNumberOfBands()); + + normalBands[0] = (ossim_float64*)normalData->getBuf(0); + normalBands[1] = (ossim_float64*)normalData->getBuf(1); + normalBands[2] = (ossim_float64*)normalData->getBuf(2); + normalBandsNp[0] = normalData->getNullPix(0); + normalBandsNp[1] = normalData->getNullPix(1); + normalBandsNp[2] = normalData->getNullPix(2); + + for(b=0;b<colorData->getNumberOfBands();++b) + { + colorBands[b] = (T*)colorData->getBuf(b); + colorBandsNp[b] = (T)colorData->getNullPix(b); + } + + ossim_uint32 maxOffset = colorData->getWidth()*colorData->getHeight(); + ossim_uint32 offset=0; + ossim_float64 ndviTest=0.0; + ossim_uint32 numberOfTests = 0; + if(maxOffset) + { + maxOffset-=1; + } + + ossim_int32 percent = (ossim_int32)(colorData->getWidth()*colorData->getHeight()*.2); + offset = 0; + ossim_uint32 countPixels = 0; + while(offset < maxOffset) + { + bool nullBandsExist = false; + for(b = 0; ((b < colorData->getNumberOfBands())&&(!nullBandsExist));++b) + { + if(*colorBands[b] == colorBandsNp[b]) + { + nullBandsExist = true; + } + } + + if((!nullBandsExist)&& + (*normalBands[0] != normalBandsNp[0])&& + (*normalBands[1] != normalBandsNp[1])&& + (*normalBands[2] != normalBandsNp[2])) + { + if(computeNdvi((T)0, + ndviTest, + offset, + colorBands)) + { + if((ndviTest >= theNdviLowTest) && (ndviTest <= theNdviHighTest)) + { + double cosineI = ((*(normalBands[0]+offset))*theLightDirection[0] + + (*(normalBands[1]+offset))*theLightDirection[1] + + (*(normalBands[2]+offset))*theLightDirection[2]); + if(cosineI >= 0.0) + { + long bucketIdx = (long)(cosineI*cosineIBucketCount.size()); + + // we will try to disperse the normals out and so we don't clump everything + // in one place + // + if(cosineIBucketCount[bucketIdx] < maxCountPerBucket) + { + for(b = 0; b < colorData->getNumberOfBands();++b) + { + regressionPoints[b].addPoint(ossimDpt(cosineI, *(colorBands[b]+offset))); + } + ++cosineIBucketCount[bucketIdx]; + ++count; + } + } + } + } + } + ++offset; + } +} +#endif + +template <class T> bool ossimTopographicCorrectionFilter::computeNdvi( + T, + ossim_float64& result, + ossim_uint32 offset, + const std::vector<T*>& bands)const +{ + if(bands.size() > 3) + { + result = (((double)*(bands[3]+offset) - (double)*(bands[2]+offset))/ + ((double)*(bands[3]+offset) + (double)*(bands[2]+offset))); + return true; + } + + return false; +} + +void ossimTopographicCorrectionFilter::resizeArrays(ossim_uint32 newSize) +{ + if(!getInput(0) || !getInput(1)) return; + + + vector<double> tempC = theC; + vector<double> tempK = theK; + vector<double> tempBias = theBias; + vector<double> tempGain = theGain; + + theC.resize(newSize); + theK.resize(newSize); + theBias.resize(newSize); + theGain.resize(newSize); + ossim_uint32 tempIdx = 0; + if(tempC.size() > 0 && (theC.size() > 0)) + { + int numberOfElements = ossimMin(tempC.size(), theC.size()); + + std::copy(tempC.begin(), tempC.begin()+numberOfElements, + theC.begin()); + std::copy(tempK.begin(), tempK.begin()+numberOfElements, + theK.begin()); + std::copy(tempBias.begin(), tempBias.begin()+numberOfElements, + theBias.begin()); + std::copy(tempGain.begin(), tempGain.begin()+numberOfElements, + theGain.begin()); + + if(theC.size() > tempC.size()) + { + std::fill(theC.begin()+numberOfElements, theC.end(), (double)0.0); + std::fill(theBias.begin()+numberOfElements, theBias.end(), (double)0.0); + std::fill(theGain.begin()+numberOfElements, theGain.end(), (double)1.0); + for(tempIdx = numberOfElements; tempIdx < theK.size(); ++tempIdx) + { + theK[tempIdx] = 0.3 + .4*(tempIdx/(double)(theK.size())); + } + } + } + else + { + std::fill(theC.begin(), theC.end(), (double)0.0); + std::fill(theBias.begin(), theBias.end(), (double)0.0); + std::fill(theGain.begin(), theGain.end(), (double)1.0); + for(tempIdx = 0; tempIdx < theK.size(); ++tempIdx) + { + theK[tempIdx] = 0.3 + .4*(tempIdx/(double)(theK.size())); + } + } +} + +bool ossimTopographicCorrectionFilter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + + ossimString elevAngle = kwl.find(prefix, ossimKeywordNames::ELEVATION_ANGLE_KW); + ossimString azimuthAngle = kwl.find(prefix, ossimKeywordNames::AZIMUTH_ANGLE_KW); + ossimString bands = kwl.find(prefix, ossimKeywordNames::NUMBER_BANDS_KW); + ossimString correctionType = kwl.find(prefix, CORRECTION_TYPE_KW); + ossimString julianDay = kwl.find(prefix, ossimKeywordNames::JULIAN_DAY_KW); + ossimString cComputedFlag = kwl.find(prefix, C_COMPUTED_FLAG_KW); + ossimString ndviRange = kwl.find(prefix, NDVI_RANGE_KW); + + theCComputedFlag = cComputedFlag.toBool(); + correctionType = correctionType.downcase(); + int numberOfBands = bands.toInt(); + theLightSourceElevationAngle = elevAngle.toDouble(); + theLightSourceAzimuthAngle = azimuthAngle.toDouble(); + theJulianDay = julianDay.toDouble(); + + if(ndviRange != "") + { + std::istringstream input(ndviRange.c_str()); + + input >> theNdviLowTest >> theNdviHighTest; + } + if(numberOfBands>0) + { + theGain.resize(numberOfBands); + theBias.resize(numberOfBands); + theC.resize(numberOfBands); + theK.resize(numberOfBands); + for(int b = 0; b < numberOfBands; ++b) + { + ossimString k = "k"+ossimString::toString(b); + ossimString c = "c"+ossimString::toString(b); + ossimString bias = "bias"+ossimString::toString(b); + ossimString gain = "gain"+ossimString::toString(b); + + const char* kValue = kwl.find(prefix, k); + const char* cValue = kwl.find(prefix, c); + const char* biasValue = kwl.find(prefix, bias); + const char* gainValue = kwl.find(prefix, gain); + if(kValue) + { + theK[b] = ossimString(kValue).toDouble(); + } + else + { + theK[b] = 1.0; + } + if(cValue) + { + theC[b] = ossimString(cValue).toDouble(); + } + else + { + theC[b] = 0.0;; + } + if(biasValue) + { + theBias[b] = ossimString(biasValue).toDouble(); + } + else + { + theBias[b] = 0.0; + } + if(gainValue) + { + theGain[b] = ossimString(gainValue).toDouble(); + } + else + { + theGain[b] = 1.0; + } + } + } + + if(correctionType.contains("cosine_c")) + { + theTopoCorrectionType = TOPO_CORRECTION_COSINE_C; + } + else if(correctionType.contains("minnaert")) + { + theTopoCorrectionType = TOPO_CORRECTION_MINNAERT; + } + else + { + theTopoCorrectionType = TOPO_CORRECTION_COSINE; + } + + + bool result = ossimImageCombiner::loadState(kwl, prefix); + + computeLightDirection(); + + return result; +} + +bool ossimTopographicCorrectionFilter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + // we can use any of the arrays theC, theBias, or theGain since + // they mirror the number of input bands + // + int numberOfBands = (int)theC.size(); + + kwl.add(prefix, + ossimKeywordNames::NUMBER_BANDS_KW, + numberOfBands, + true); + + kwl.add(prefix, + ossimKeywordNames::ELEVATION_ANGLE_KW, + theLightSourceElevationAngle, + true); + + kwl.add(prefix, + ossimKeywordNames::AZIMUTH_ANGLE_KW, + theLightSourceAzimuthAngle, + true); + + kwl.add(prefix, + C_COMPUTED_FLAG_KW, + (ossim_uint32)theCComputedFlag, + true); + kwl.add(prefix, + NDVI_RANGE_KW, + ossimString::toString(theNdviLowTest) + + " " + ossimString::toString(theNdviHighTest), + true); + + if(theTopoCorrectionType == TOPO_CORRECTION_COSINE_C) + { + kwl.add(prefix, + CORRECTION_TYPE_KW, + "cosine_c", + true); + } + else if(theTopoCorrectionType == TOPO_CORRECTION_MINNAERT) + { + kwl.add(prefix, + CORRECTION_TYPE_KW, + "minnaert", + true); + } + else + { + kwl.add(prefix, + CORRECTION_TYPE_KW, + "cosine", + true); + } + + for(int b = 0; b < numberOfBands; ++b) + { + ossimString k = "k"+ossimString::toString(b); + ossimString c = "c"+ossimString::toString(b); + ossimString bias = "bias"+ossimString::toString(b); + ossimString gain = "gain"+ossimString::toString(b); + kwl.add(prefix, + k, + theK[b], + true); + kwl.add(prefix, + c, + theC[b], + true); + kwl.add(prefix, + bias, + theBias[b], + true); + kwl.add(prefix, + gain, + theGain[b], + true); + } + + return ossimImageCombiner::saveState(kwl, prefix); +} + +ossim_uint32 ossimTopographicCorrectionFilter::getNumberOfOutputBands() const +{ + ossimImageSourceInterface* colorSource = PTR_CAST(ossimImageSourceInterface, getInput(0)); + if(colorSource) + { + return colorSource->getNumberOfOutputBands(); + } + return ossimImageCombiner::getNumberOfOutputBands(); +} + +ossimScalarType ossimTopographicCorrectionFilter::getOutputScalarType() const +{ + ossimImageSourceInterface* colorSource = PTR_CAST(ossimImageSourceInterface, getInput(0)); + if(colorSource) + { + return colorSource->getOutputScalarType(); + } + return ossimImageCombiner::getOutputScalarType(); +} + +double ossimTopographicCorrectionFilter::getNullPixelValue(ossim_uint32 band)const +{ + ossimImageSourceInterface* colorSource = PTR_CAST(ossimImageSourceInterface, getInput(0)); + if(colorSource) + { + return colorSource->getNullPixelValue(band); + } + return ossimImageCombiner::getNullPixelValue(band); +} + +double ossimTopographicCorrectionFilter::getMinPixelValue(ossim_uint32 band)const +{ + ossimImageSourceInterface* colorSource = PTR_CAST(ossimImageSourceInterface, getInput(0)); + if(colorSource) + { + return colorSource->getMinPixelValue(band); + } + return ossimImageCombiner::getMinPixelValue(band); +} + +double ossimTopographicCorrectionFilter::getMaxPixelValue(ossim_uint32 band)const +{ + ossimImageSourceInterface* colorSource = PTR_CAST(ossimImageSourceInterface, getInput(0)); + if(colorSource) + { + return colorSource->getMaxPixelValue(band); + } + return ossimImageCombiner::getMaxPixelValue(band); +} + +ossimIrect ossimTopographicCorrectionFilter::getBoundingRect(ossim_uint32 resLevel)const +{ + ossimIrect result; + result.makeNan(); + ossimImageSourceInterface* colorSource = PTR_CAST(ossimImageSourceInterface, getInput(0)); + + if(colorSource) + { + result = colorSource->getBoundingRect(resLevel); + } + + return result; +} + +void ossimTopographicCorrectionFilter::getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result) const +{ + result.makeNan(); + ossimImageSourceInterface* colorSource = PTR_CAST(ossimImageSourceInterface, getInput(0)); + + if(colorSource) + { + colorSource->getDecimationFactor(resLevel, + result); + } +} + +void ossimTopographicCorrectionFilter::getDecimationFactors(vector<ossimDpt>& decimations) const +{ + ossimImageSourceInterface* colorSource = PTR_CAST(ossimImageSourceInterface, getInput(0)); + if(colorSource) + { + colorSource->getDecimationFactors(decimations); + } +} + +ossim_uint32 ossimTopographicCorrectionFilter::getNumberOfDecimationLevels()const +{ + ossimImageSourceInterface* colorSource = PTR_CAST(ossimImageSourceInterface, getInput(0)); + if(colorSource) + { + return colorSource->getNumberOfDecimationLevels(); + } + return 0; +} + +double ossimTopographicCorrectionFilter::getAzimuthAngle()const +{ + return theLightSourceAzimuthAngle; +} + +double ossimTopographicCorrectionFilter::getElevationAngle()const +{ + return theLightSourceElevationAngle; +} + +void ossimTopographicCorrectionFilter::setAzimuthAngle(double angle) +{ + theLightSourceAzimuthAngle = angle; +} + +void ossimTopographicCorrectionFilter::setElevationAngle(double angle) +{ + theLightSourceElevationAngle = angle; +} +bool ossimTopographicCorrectionFilter::canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const +{ + return (object&& + ( (inputIndex>=0) && inputIndex < 2)&& + PTR_CAST(ossimImageSourceInterface, object)); + +} + +void ossimTopographicCorrectionFilter::connectInputEvent(ossimConnectionEvent& event) +{ + initialize(); +} + +void ossimTopographicCorrectionFilter::disconnectInputEvent(ossimConnectionEvent& event) +{ + initialize(); +} + +void ossimTopographicCorrectionFilter::propertyEvent(ossimPropertyEvent& event) +{ + initialize(); +} + +void ossimTopographicCorrectionFilter::refreshEvent(ossimRefreshEvent& event) +{ + initialize(); +} + +ossimTopographicCorrectionFilter::ossimTopoCorrectionType ossimTopographicCorrectionFilter::getTopoCorrectionType()const +{ + return theTopoCorrectionType; +} + +void ossimTopographicCorrectionFilter::setTopoCorrectionType(ossimTopoCorrectionType topoType) +{ + theTopoCorrectionType = topoType; +} + +const std::vector<double>& ossimTopographicCorrectionFilter::getGainValues()const +{ + return theGain; +} + +void ossimTopographicCorrectionFilter::setGainValues(const std::vector<double>& gainValues) +{ + theGain = gainValues; +} + +const vector<double>& ossimTopographicCorrectionFilter::getBiasValues()const +{ + return theBias; +} + +void ossimTopographicCorrectionFilter::setBiasValues(const std::vector<double>& biasValues) +{ + theBias = biasValues; +} + +const vector<double>& ossimTopographicCorrectionFilter::getKValues()const +{ + return theK; +} + +double ossimTopographicCorrectionFilter::getK(int idx)const +{ + if(idx < (int)theK.size()) + { + return theK[idx]; + } + else + { + return 1.0; + } +} + +void ossimTopographicCorrectionFilter::setK(int idx, double value) +{ + if(idx < (int)theK.size()) + { + theK[idx] = value; + } +} + +void ossimTopographicCorrectionFilter::setKValues(const vector<double>& kValues) +{ + theK = kValues; +} + +double ossimTopographicCorrectionFilter::getC(int idx)const +{ + if(idx < (int)theC.size()) + { + return theC[idx]; + } + else + { + return 0.0; + } +} + +void ossimTopographicCorrectionFilter::setC(int idx, double value) +{ + if(idx < (int)theC.size()) + { + theC[idx] = value; + } +} + +void ossimTopographicCorrectionFilter::setCValues(const vector<double>& cValues) +{ + theC = cValues; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimTopographicCorrectionFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimTopographicCorrectionFilter.h new file mode 100644 index 0000000000..83fff7fe30 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimTopographicCorrectionFilter.h @@ -0,0 +1,225 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimTopographicCorrectionFilter.h,v 1.19 2005/02/11 15:07:34 dburken Exp $ +#ifndef ossimTopographicCorrectionFilter_HEADER +#define ossimTopographicCorrectionFilter_HEADER +#include <imaging/tile_sources/ossimImageCombiner.h> +#include <matrix/newmat.h> +#include <base/data_types/ossimColumnVector3d.h> +#include <base/common/events/ossimConnectableObjectListener.h> +#include <base/common/events/ossimPropertyEvent.h> +#include <base/misc/ossim2dLinearRegression.h> + +class ossimImageData; + +class ossimImageSourceConnection; +class ossimImageToPlaneNormalFilter; +/*! + * + * class ossimTopographicCorrectionFilter + * + * This clas is used to execute terrain correction. I t requires 2 inputs + * where the first input is a multi band data source to correct and the + * second is elevation normals used in light incident calculations. + * + * A sample chain might look like: + * + * landsatHandler ---> Cache ---> renderer ---> cache --------------------------------------- + * |--> Topo correction filter ---> Output + * ortho mosaic of elevation data----> imageToPlaneNormals --> Cache ---> Renderer -->Cache -- + * + * the ossimImageToPlaneNormalsFilter is used to take a single band elevation source and compute normals at each post. I suggest that you + * set the renderer to use a higher order convolution than just nearest neighbor, maybe Cubic. This way you have smoother interpolation + * as you change zoom levels. + * + * + * Correction Types: + * + * Cosine correction: In order for this to run it does not need any additional informat but the multi band source and + * an normal calculation input. + * + * Cosine-C correction: In order for this to run it will need theC array populated for each band. It defaults + * to 0 forcing a default Cosine correction to take place. + * + * Minnaert correction: In order for this to run it will need theK array populated for each band. The defaults should work pretty good + * + */ +class OSSIMDLLEXPORT ossimTopographicCorrectionFilter : public ossimImageCombiner +{ +public: + enum ossimTopoCorrectionType + { + TOPO_CORRECTION_COSINE = 0, + TOPO_CORRECTION_COSINE_C = 1, + TOPO_CORRECTION_MINNAERT = 2 + }; + ossimTopographicCorrectionFilter(); + + ossimTopographicCorrectionFilter(ossimImageSource* colorSource, + ossimImageSource* elevSource); + + virtual ~ossimTopographicCorrectionFilter(); + + ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + + virtual ossim_uint32 getNumberOfOutputBands() const; + + virtual ossimScalarType getOutputScalarType() const; + + virtual double getNullPixelValue(ossim_uint32 band=0)const; + + virtual double getMinPixelValue(ossim_uint32 band=0)const; + + virtual double getMaxPixelValue(ossim_uint32 band=0)const; + + virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0)const; + + virtual void getDecimationFactor(ossim_uint32 resLevel, + ossimDpt& result) const; + + virtual void getDecimationFactors(vector<ossimDpt>& decimations) const; + + virtual ossim_uint32 getNumberOfDecimationLevels()const; + + virtual double getAzimuthAngle()const; + + virtual double getElevationAngle()const; + + virtual void setAzimuthAngle(double angle); + + virtual void setElevationAngle(double angle); + + virtual void initialize(); + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + bool canConnectMyInputTo(ossim_int32 inputIndex, + const ossimConnectableObject* object)const; + + virtual void connectInputEvent(ossimConnectionEvent& event); + + virtual void disconnectInputEvent(ossimConnectionEvent& event); + + virtual void propertyEvent(ossimPropertyEvent& event); + + virtual void refreshEvent(ossimRefreshEvent& event); + + virtual ossimTopoCorrectionType getTopoCorrectionType()const; + + virtual void setTopoCorrectionType(ossimTopoCorrectionType topoType); + + const std::vector<double>& getGainValues()const; + + void setGainValues(const std::vector<double>& gainValues); + + const vector<double>& getBiasValues()const; + + void setBiasValues(const std::vector<double>& biasValues); + + const vector<double>& getKValues()const; + + double getK(int idx)const; + + void setK(int idx, double value); + + void setKValues(const vector<double>& kValues); + + double getC(int idx)const; + + void setC(int idx, double value); + + void setCValues(const vector<double>& cValues); + + void computeLightDirection(); + +protected: + virtual void allocate(); + + /*! + * The result of the illumination equation is stored in + * here. This is populated on each call to getTile. + */ + ossimRefPtr<ossimImageData> theTile; + + std::vector<ossim_uint32> theBandMapping; + +// ossimImageToPlaneNormalFilter* theNormalFilter; +// ossimScalarRemapper* theScalarRemapper; + std::vector<double> theC; + std::vector<double> theK; + std::vector<double> theBias; + std::vector<double> theGain; + + /*! + * Used for the light vector computation. + */ + double theLightSourceElevationAngle; + + /*! + * Used for the light vector computation. + */ + double theLightSourceAzimuthAngle; + + /*! + * This is computed from the elevation and + * azimuth angles of the light source. + */ + double theLightDirection[3]; + + double theJulianDay; + mutable bool theCComputedFlag; + ossimTopoCorrectionType theTopoCorrectionType; + double theNdviLowTest; + double theNdviHighTest; + + virtual void executeTopographicCorrection( + ossimRefPtr<ossimImageData>& outputData, + ossimRefPtr<ossimImageData>& colorData, + ossimRefPtr<ossimImageData>& normalData); + + template <class T> void executeTopographicCorrectionTemplate( + T dummy, + ossimRefPtr<ossimImageData>& outputData, + ossimRefPtr<ossimImageData>& colorData, + ossimRefPtr<ossimImageData>& normalData); + + template <class T> void executeTopographicCorrectionMinnaertTemplate( + T dummy, + ossimRefPtr<ossimImageData>& outputData, + ossimRefPtr<ossimImageData>& colorData, + ossimRefPtr<ossimImageData>& normalData); + +// virtual void computeC(); + +// template<class T> +// void addRegressionPointsTemplate(T, //dummy +// std::vector<ossim2dLinearRegression>& regressionPoints, +// std::vector<int>& cosineIBucketCount, +// ossim_int32 maxCountPerBucket, +// ossimImageData* colorData, +// ossimImageData* normalData); + template <class T> bool computeNdvi(T dummy, + ossim_float64& result, + ossim_uint32 offset, + const std::vector<T*>& bands)const; + + void resizeArrays(ossim_uint32 newSize); + + bool setCCmputedFlag(); +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimTrimFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimTrimFilter.cpp new file mode 100644 index 0000000000..6f0fbdc3dd --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimTrimFilter.cpp @@ -0,0 +1,352 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimTrimFilter.cpp,v 1.3 2005/09/17 19:51:11 dburken Exp $ +#include <imaging/tile_sources/ossimTrimFilter.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <base/common/ossimTrace.h> +#include <base/context/ossimNotifyContext.h> +#include <base/property/ossimNumericProperty.h> +#include <base/data_types/ossimDpt.h> + +static ossimTrace traceDebug("ossimTrimFilter:debug"); + +RTTI_DEF1(ossimTrimFilter, + "ossimTrimFilter", + ossimImageSourceFilter); + +ossimTrimFilter::ossimTrimFilter() + :ossimImageSourceFilter(), + theLeftPercent(0.0), + theRightPercent(0.0), + theTopPercent(0.0), + theBottomPercent(0.0) +{ + theCutter = new ossimPolyCutter; +} + +ossimRefPtr<ossimImageData> ossimTrimFilter::getTile( + const ossimIrect& rect, + ossim_uint32 resLevel) +{ + if(!theInputConnection) + { + return NULL; + } + + if(!theValidVertices.size()) + { + return ossimImageSourceFilter::getTile(rect, resLevel); + } + + ossimRefPtr<ossimImageData> tile = + theCutter->getTile(rect, resLevel); + + if(!isSourceEnabled()||!tile.valid()) + { + return tile; + } + if(tile->getDataObjectStatus() == OSSIM_NULL || + tile->getDataObjectStatus() == OSSIM_EMPTY) + { + return tile; + } + + return theCutter->getTile(rect, resLevel); +// theTile->setImageRectangle(rect); +// theTile->setDataObjectStatus(OSSIM_FULL); + +// theTile->makeBlank(); +// ossimIrect boundingRect = getBoundingRect(resLevel); +// ossimIrect tileRect = tile->getImageRectangle(); +// ossimIrect clipRect = boundingRect.clipToRect(tileRect); + +// theTile->loadTile(tile->getBuf(), +// tile->getImageRectangle(), +// clipRect, +// OSSIM_BSQ); + +// theTile->validate(); + +} + +void ossimTrimFilter::getValidImageVertices( + vector<ossimIpt>& validVertices, + ossimVertexOrdering ordering, + ossim_uint32 resLevel)const +{ + ossimImageSource::getValidImageVertices(validVertices, + ordering, + resLevel); + if(validVertices.size()==4) + { + ossimDpt averagePt((ossimDpt(validVertices[0])+ + ossimDpt(validVertices[1])+ + ossimDpt(validVertices[2])+ + ossimDpt(validVertices[3]))*.25); + ossimDpt averageTop( ( ossimDpt(validVertices[0]+ + validVertices[1])*.5) ); + ossimDpt averageBottom( ( ossimDpt(validVertices[2]+ + validVertices[3])*.5 ) ); + ossimDpt averageLeft( (ossimDpt(validVertices[0]+ + validVertices[3])*.5) ); + ossimDpt averageRight( (ossimDpt(validVertices[1]+ + validVertices[2])*.5) ); + + ossimDpt topAxis = (averageTop-averagePt); + ossimDpt rightAxis = (averageRight-averagePt); + ossimDpt leftAxis = (averageLeft-averagePt); + ossimDpt bottomAxis = (averageBottom-averagePt); + + double topLen = topAxis.length(); + double bottomLen = bottomAxis.length(); + double rightLen = rightAxis.length(); + double leftLen = leftAxis.length(); + + if((topLen > FLT_EPSILON)&& + (bottomLen > FLT_EPSILON)&& + (leftLen > FLT_EPSILON)&& + (rightLen > FLT_EPSILON)) + { + topAxis = topAxis*(1.0/topLen); + bottomAxis = bottomAxis*(1.0/bottomLen); + leftAxis = leftAxis*(1.0/leftLen); + rightAxis = rightAxis*(1.0/rightLen); + + ossim_uint32 idx = 0; + ossim_uint32 count = 0; + for(idx = 0; idx < validVertices.size(); ++idx) + { + ossimDpt axis[2]; + double axisLen[2]; + ossimDpt diff = validVertices[idx]-averagePt; + double testLen = (topAxis.x*diff.x+ + topAxis.y*diff.y); + count = 0; + if(testLen >= -FLT_EPSILON) + { + axis[count] = topAxis; + axisLen[count] = testLen*(1.0-theTopPercent); + ++count; + } + + if(count < 2) + { + testLen = (bottomAxis.x*diff.x+ + bottomAxis.y*diff.y); + if(testLen >= -FLT_EPSILON) + { + axis[count] = bottomAxis; + axisLen[count] = testLen*(1.0-theBottomPercent); + ++count; + } + } + if(count < 2) + { + testLen = (leftAxis.x*diff.x+ + leftAxis.y*diff.y); + if(testLen >= -FLT_EPSILON) + { + axis[count] = leftAxis; + axisLen[count] = testLen*(1.0-theLeftPercent); + ++count; + } + } + if(count < 2) + { + testLen = (rightAxis.x*diff.x+ + rightAxis.y*diff.y); + if(testLen >= -FLT_EPSILON) + { + axis[count] = rightAxis; + axisLen[count] = testLen*(1.0-theRightPercent); + ++count; + } + } + if(count == 2) + { + validVertices[idx] = (averagePt + (axis[0]*axisLen[0] + + axis[1]*axisLen[1])); + } + } + } + } +// ossimIrect rect = getBoundingRect(); + +// if(ordering == OSSIM_CLOCKWISE_ORDER) +// { +// validVertices.push_back(rect.ul()); +// validVertices.push_back(rect.ur()); +// validVertices.push_back(rect.lr()); +// validVertices.push_back(rect.ll()); +// } +// else +// { +// validVertices.push_back(rect.ul()); +// validVertices.push_back(rect.ll()); +// validVertices.push_back(rect.lr()); +// validVertices.push_back(rect.ur()); +// } +} + +ossimIrect ossimTrimFilter::getBoundingRect(ossim_uint32 resLevel)const +{ + + vector<ossimIpt> validVertices; + ossimIrect result; + result.makeNan(); + getValidImageVertices(validVertices, OSSIM_CLOCKWISE_ORDER, resLevel); + + if(validVertices.size()) + { + result = ossimIrect(validVertices); + } + + return result; +} + +void ossimTrimFilter::initialize() +{ + if(theInputConnection) + { + theCutter->disconnectMyInput(0, false, false); + if(getInput()) + { + theCutter->connectMyInputTo(0, getInput()); + } + theCutter->initialize(); + getValidImageVertices(theValidVertices); + theCutter->setNumberOfPolygons(1); + theCutter->setPolygon(theValidVertices); + } +} + +bool ossimTrimFilter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + "left_percent", + theLeftPercent, + true); + kwl.add(prefix, + "right_percent", + theRightPercent, + true); + kwl.add(prefix, + "top_percent", + theTopPercent, + true); + kwl.add(prefix, + "bottom_percent", + theBottomPercent, + true); + + return ossimImageSourceFilter::saveState(kwl, prefix); +} + +bool ossimTrimFilter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* leftPerc = kwl.find(prefix, "left_percent"); + const char* rightPerc = kwl.find(prefix, "right_percent"); + const char* topPerc = kwl.find(prefix, "top_percent"); + const char* bottomPerc = kwl.find(prefix, "bottom_percent"); + + if(leftPerc) + { + theLeftPercent = ossimString(leftPerc).toDouble(); + } + if(rightPerc) + { + theRightPercent = ossimString(rightPerc).toDouble(); + } + if(topPerc) + { + theTopPercent = ossimString(topPerc).toDouble(); + } + if(bottomPerc) + { + theBottomPercent = ossimString(bottomPerc).toDouble(); + } + + return ossimImageSourceFilter::loadState(kwl, prefix); +} + +ossimRefPtr<ossimProperty> ossimTrimFilter::getProperty(const ossimString& name)const +{ + ossimProperty* prop = 0; + if(name == "left_percent") + { + prop = new ossimNumericProperty(name, + ossimString::toString(theLeftPercent), + 0.0, 1.0); + prop->setFullRefreshBit(); + } + else if(name == "right_percent") + { + prop = new ossimNumericProperty(name, + ossimString::toString(theRightPercent), + 0.0, 1.0); + prop->setFullRefreshBit(); + } + else if(name == "top_percent") + { + prop = new ossimNumericProperty(name, + ossimString::toString(theTopPercent), + 0.0, 1.0); + prop->setFullRefreshBit(); + } + else if(name == "bottom_percent") + { + prop = new ossimNumericProperty(name, + ossimString::toString(theBottomPercent), + 0.0, 1.0); + prop->setFullRefreshBit(); + } + + if(prop) return prop; + + return ossimImageSourceFilter::getProperty(name); +} + +void ossimTrimFilter::setProperty(ossimRefPtr<ossimProperty> property) +{ + if(!property.valid())return; + ossimString name = property->getName(); + + if(name == "left_percent") + { + theLeftPercent = property->valueToString().toDouble(); + } + else if(name == "right_percent") + { + theRightPercent = property->valueToString().toDouble(); + } + else if(name == "top_percent") + { + theTopPercent = property->valueToString().toDouble(); + } + else if(name == "bottom_percent") + { + theBottomPercent = property->valueToString().toDouble(); + } + else + { + return ossimImageSourceFilter::setProperty(property); + } +} + +void ossimTrimFilter::getPropertyNames(std::vector<ossimString>& propertyNames)const +{ + propertyNames.push_back("left_percent"); + propertyNames.push_back("right_percent"); + propertyNames.push_back("top_percent"); + propertyNames.push_back("bottom_percent"); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimTrimFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimTrimFilter.h new file mode 100644 index 0000000000..46ef8a091f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimTrimFilter.h @@ -0,0 +1,70 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimTrimFilter.h,v 1.2 2005/09/15 12:28:44 gpotts Exp $ +#ifndef ossimTrimFilter_HEADER +#define ossimTrimFilter_HEADER +#include <imaging/tile_sources/ossimImageSourceFilter.h> +#include "ossimPolyCutter.h" + +class ossimTrimFilter : public ossimImageSourceFilter +{ +public: + ossimTrimFilter(); + + virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0)const; + virtual void getValidImageVertices(vector<ossimIpt>& validVertices, + ossimVertexOrdering ordering=OSSIM_CLOCKWISE_ORDER, + ossim_uint32 resLevel=0)const; + + ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect, + ossim_uint32 resLevel=0); + + virtual void initialize(); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=NULL)const; + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=NULL); + + + virtual ossimRefPtr<ossimProperty> getProperty( + const ossimString& name)const; + + /** + * Set property. + * + * @param property Property to set if property->getName() matches a + * property name of this object. + */ + virtual void setProperty(ossimRefPtr<ossimProperty> property); + + /** + * Adds this objects properties to the list. + * + * @param propertyNames Array to add to. + * + * @note This method does not clear propertyNames prior to adding it's + * names. + */ + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + +protected: + double theLeftPercent; + double theRightPercent; + double theTopPercent; + double theBottomPercent; + std::vector<ossimIpt> theValidVertices; + ossimRefPtr<ossimPolyCutter> theCutter; + +TYPE_DATA +}; + +#endif /* #ifndef ossimTrimFilter_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimValueAssignImageSourceFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimValueAssignImageSourceFilter.cpp new file mode 100644 index 0000000000..8db7307535 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimValueAssignImageSourceFilter.cpp @@ -0,0 +1,377 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimValueAssignImageSourceFilter.cpp,v 1.6 2005/02/11 15:07:34 dburken Exp $ +#include <imaging/tile_sources/ossimValueAssignImageSourceFilter.h> +#include <imaging/ossimImageData.h> +#include <imaging/factory/ossimImageDataFactory.h> + +RTTI_DEF1(ossimValueAssignImageSourceFilter, + "ossimValueAssignImageSourceFilter", + ossimImageSourceFilter); + +ossimValueAssignImageSourceFilter::ossimValueAssignImageSourceFilter(ossimObject* owner) + :ossimImageSourceFilter(owner), + theAssignType(ossimValueAssignType_GROUP), + theTile(NULL) +{ +} + +ossimValueAssignImageSourceFilter::~ossimValueAssignImageSourceFilter() +{ +} + +ossimRefPtr<ossimImageData> ossimValueAssignImageSourceFilter::getTile( + const ossimIrect& tileRect, + ossim_uint32 resLevel) +{ + if(!theInputConnection) + { + return NULL; // This filter requires an input. + } + + ossimRefPtr<ossimImageData> inputTile = + theInputConnection->getTile(tileRect, resLevel); + + if(!isSourceEnabled() || !inputTile.valid()) + { + return inputTile; + } + + if(!theTile.valid()) + { + allocate(); // First time through... + } + + if (!theTile.valid()) // throw exeption... + { + return inputTile; + } + + // Set the origin, resize if needed of the output tile. + theTile->setImageRectangle(tileRect); + + if( inputTile->getDataObjectStatus() == OSSIM_NULL || + inputTile->getDataObjectStatus() == OSSIM_EMPTY ) + { + theTile->makeBlank(); + return theTile; + } + + if(!inputTile->getBuf()) + { + theTile->makeBlank(); + } + else + { + theTile->loadTile(inputTile.get()); + } + + switch(inputTile->getScalarType()) + { + case OSSIM_UCHAR: + { + executeAssign(static_cast<ossim_uint8>(0), + theTile); + break; + } + case OSSIM_FLOAT: + case OSSIM_NORMALIZED_FLOAT: + { + executeAssign(static_cast<float>(0), + theTile); + break; + } + case OSSIM_USHORT16: + case OSSIM_USHORT11: + { + executeAssign(static_cast<ossim_uint16>(0), + theTile); + break; + } + case OSSIM_SSHORT16: + { + executeAssign(static_cast<ossim_sint16>(0), + theTile); + break; + } + case OSSIM_DOUBLE: + case OSSIM_NORMALIZED_DOUBLE: + { + executeAssign(static_cast<double>(0), + theTile); + break; + } + default: + { + ossimNotify(ossimNotifyLevel_WARN) << "ossimValueAssignImageSourceFilter::getTile WARN: Scalar type = " << theTile->getScalarType() + << " Not supported!" << std::endl; + break; + } + } + + theTile->validate(); + + return theTile; +} + +void ossimValueAssignImageSourceFilter::setInputOutputValues(const vector<double>& inputValues, + const vector<double>& outputValues) +{ + theInputValueArray = inputValues; + theOutputValueArray = outputValues; + + validateArrays(); +} + +void ossimValueAssignImageSourceFilter::validateArrays() +{ + if(theOutputValueArray.size() != theInputValueArray.size()) + { + ossim_uint32 index = std::min(theOutputValueArray.size(), + theInputValueArray.size()); + + vector<double> copyVector(theOutputValueArray.begin(), + theOutputValueArray.begin() + index); + + theOutputValueArray = copyVector; + + for(ossim_uint32 index2 = index; index < theInputValueArray.size(); ++index) + { + theOutputValueArray.push_back(theInputValueArray[index2]); + } + } +} + +template <class T> void ossimValueAssignImageSourceFilter::executeAssign( + T, + ossimRefPtr<ossimImageData>& data) +{ + if(!theInputValueArray.size()) return; + + if(theAssignType == ossimValueAssignType_SEPARATE) + { + executeAssignSeparate(static_cast<T>(0), data); + } + else + { + executeAssignGroup(static_cast<T>(0), data); + } +} + +template <class T> void ossimValueAssignImageSourceFilter::executeAssignSeparate( + T, + ossimRefPtr<ossimImageData>& data) +{ + ossim_uint32 numberOfBands = std::min((ossim_uint32)data->getNumberOfBands(), + (ossim_uint32)theInputValueArray.size()); + ossim_uint32 maxOffset = data->getWidth()*data->getHeight(); + + for(ossim_uint32 band = 0; band<numberOfBands; ++band) + { + T* buf = static_cast<T*>(data->getBuf(band)); + T inValue = static_cast<T>(theInputValueArray[band]); + T outValue = static_cast<T>(theOutputValueArray[band]); + for(ossim_uint32 count = 0; count < maxOffset; ++count) + { + if(*buf == inValue) + { + *buf = outValue; + } + ++buf; + } + } +} + +template <class T> void ossimValueAssignImageSourceFilter::executeAssignGroup( + T, + ossimRefPtr<ossimImageData>& data) +{ + ossim_uint32 numberOfBands = std::min((ossim_uint32)data->getNumberOfBands(), + (ossim_uint32)theInputValueArray.size()); + ossim_uint32 maxOffset = data->getWidth()*data->getHeight(); + ossim_uint32 band = 0; + bool equalFlag = false; + + T** bufArray = new T*[data->getNumberOfBands()]; + for(band = 0; band < data->getNumberOfBands(); ++band) + { + bufArray[band] = static_cast<T*>(data->getBuf(band)); + } + + for(ossim_uint32 offset = 0; offset < maxOffset; ++offset) + { + equalFlag = true; + + for(band = 0; band<numberOfBands; ++band) + { + if(bufArray[band][offset] != theInputValueArray[band]) + { + equalFlag = false; + } + } + if(equalFlag) + { + for(band = 0; band<numberOfBands; ++band) + { + bufArray[band][offset] = static_cast<T>(theOutputValueArray[band]); + } + } + } + + delete [] bufArray; +} + +void ossimValueAssignImageSourceFilter::initialize() +{ + // Base class will recapture "theInputConnection". + ossimImageSourceFilter::initialize(); +} + +void ossimValueAssignImageSourceFilter::allocate() +{ + theTile = NULL; + + if(theInputConnection) + { + ossimImageDataFactory* idf = ossimImageDataFactory::instance(); + + theTile = idf->create(this, + this); + + theTile->initialize(); + } +} + +bool ossimValueAssignImageSourceFilter::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + ossim_uint32 index = 0; + for(index =0; index < theInputValueArray.size(); ++index) + { + ossimString in = ("input_band" + ossimString::toString(index)); + ossimString out = ("output_band" + ossimString::toString(index)); + + kwl.add(prefix, + in.c_str(), + theInputValueArray[index], + true); + kwl.add(prefix, + out.c_str(), + theOutputValueArray[index], + true); + } + if(theAssignType == ossimValueAssignType_SEPARATE) + { + kwl.add(prefix, + "assign_type", + "separate", + true); + } + else + { + kwl.add(prefix, + "assign_type", + "group", + true); + } + + return ossimImageSourceFilter::saveState(kwl, prefix); +} + +/*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ +bool ossimValueAssignImageSourceFilter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + + ossimString inRegExpression = ossimString("^(") + + ossimString(prefix) + + "input_band[0-9]+)"; + ossimString outRegExpression = ossimString("^(") + + ossimString(prefix) + + "output_band[0-9]+)"; + ossim_uint32 numberOfInputs = kwl.getNumberOfSubstringKeys(inRegExpression); + ossim_uint32 numberOfOutputs = kwl.getNumberOfSubstringKeys(outRegExpression); + ossim_uint32 index = 0; + ossim_uint32 currentIndex = 0; + + theInputValueArray.clear(); + theOutputValueArray.clear(); + + while(index < numberOfInputs) + { + const char* value = kwl.find(prefix, + (ossimString("input_band") + + ossimString::toString(currentIndex)).c_str() + ); + if(value) + { + theInputValueArray.push_back(ossimString(value).toDouble()); + ++index; + } + ++currentIndex; + } + index = 0; + currentIndex = 0; + while(index < numberOfOutputs) + { + const char* value = kwl.find(prefix, + (ossimString("output_band") + + ossimString::toString(currentIndex)).c_str() + ); + if(value) + { + theOutputValueArray.push_back(ossimString(value).toDouble()); + ++index; + } + ++currentIndex; + } + validateArrays(); + + const char* assignType = kwl.find(prefix, "assign_type"); + if(assignType) + { + if(ossimString(assignType).trim().downcase() == "separate") + { + theAssignType = ossimValueAssignType_SEPARATE; + } + else + { + theAssignType = ossimValueAssignType_GROUP; + } + } + else + { + theAssignType = ossimValueAssignType_GROUP; + } + + return ossimImageSourceFilter::loadState(kwl, prefix); +} + +const vector<double>& ossimValueAssignImageSourceFilter::getInputValues()const +{ + return theInputValueArray; +} +const vector<double>& ossimValueAssignImageSourceFilter::getOutputValues()const +{ + return theOutputValueArray; +} + +ossimValueAssignImageSourceFilter::ossimValueAssignType ossimValueAssignImageSourceFilter::getValueAssignType()const +{ + return theAssignType; +} +void ossimValueAssignImageSourceFilter::setValueAssignType(ossimValueAssignType type) +{ + theAssignType = type; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimValueAssignImageSourceFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimValueAssignImageSourceFilter.h new file mode 100644 index 0000000000..0e8fe92a09 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimValueAssignImageSourceFilter.h @@ -0,0 +1,102 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimValueAssignImageSourceFilter.h,v 1.5 2005/02/11 15:07:34 dburken Exp $ +#ifndef ossimValueAssignImageSourceFilter_HEADER +#define ossimValueAssignImageSourceFilter_HEADER + +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +/** + * This allows one to assign a value to a group of bands. It will test + * for equality band separate or as group. For example: + * + * if we are testing as a group then the assign will not happen unless + * all values equal theInputValue array + * + * inputValue = <1, 2, 3> + * outputValue = <100, 100, 100> + * + * then it will only convert to 100, 100, 100 if the input equals all + * values of the output. + * + * input <1, 55, 3> would become <1, 55, 3> + * input <1, 2, 3> would become <100, 100, 100> + * + * Now for band separate it means you want to change on a per band and + * not as a group. For example: + * + * inputValue = <1, 2, 3> + * outputValue = <100, 100, 100> + * + * input <1, 55, 3> would become <100, 55, 100> + * + */ +class OSSIMDLLEXPORT ossimValueAssignImageSourceFilter : public ossimImageSourceFilter +{ +public: + enum ossimValueAssignType + { + ossimValueAssignType_SEPARATE = 1, + ossimValueAssignType_GROUP = 2 + }; + + ossimValueAssignImageSourceFilter(ossimObject* owner=NULL); + virtual ~ossimValueAssignImageSourceFilter(); + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, + ossim_uint32 resLevel=0); + + void setInputOutputValues(const vector<double>& inputValues, + const vector<double>& outputValues); + + const vector<double>& getInputValues()const; + const vector<double>& getOutputValues()const; + ossimValueAssignType getValueAssignType()const; + void setValueAssignType(ossimValueAssignType type); + + virtual void initialize(); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=NULL)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=NULL); + +protected: + + /** + * Called on first getTile, will initialize all data needed. + */ + void allocate(); + + vector<double> theInputValueArray; + vector<double> theOutputValueArray; + ossimValueAssignType theAssignType; + ossimRefPtr<ossimImageData> theTile; + + void validateArrays(); + + template <class T> + void executeAssign(T, ossimRefPtr<ossimImageData>& data); + + template <class T> + void executeAssignSeparate(T, ossimRefPtr<ossimImageData>& data); + + template <class T> + void executeAssignGroup(T, ossimRefPtr<ossimImageData>& data); + +TYPE_DATA +}; + +#endif /* #ifndef ossimValueAssignImageSourceFilter_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimVectorRenderer.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimVectorRenderer.cpp new file mode 100644 index 0000000000..ffe87ffaeb --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimVectorRenderer.cpp @@ -0,0 +1,148 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken (dburken@imagelinks.com) +// +// Description: +// +// Abstract class for rendering vector data. Derived classes should implement +// the "rasterizeVectorData" data method. +// +//******************************************************************* +// $Id: ossimVectorRenderer.cpp,v 1.7 2003/05/13 11:31:09 dburken Exp $ + +#include <iostream> +using namespace std; + +#include "ossimVectorRenderer.h" +#include "base/common/ossimCommon.h" +#include "base/data_types/ossimKeywordlist.h" +#include "base/common/ossimKeywordNames.h" +#include "imaging/filters/ossimFilter.h" +#include "projections/ossimImageViewTransform.h" +#include "projections/factory/ossimImageViewTransformFactory.h" + +RTTI_DEF1(ossimVectorRenderer, "ossimVectorRenderer", ossimImageSourceFilter) + + +ossimVectorRenderer::ossimVectorRenderer() + : + ossimImageSourceFilter(), + theImageViewTransform(NULL), + theBoundingRect(), + theAreaOfInterest(), + theNumberOfAoiObjects(0), + theNumberOfObjects(0) +{ +} + +ossimVectorRenderer::ossimVectorRenderer(ossimImageSource* inputSource, + ossimImageViewTransform* transform) + : ossimImageSourceFilter(inputSource), + theImageViewTransform(transform), + theBoundingRect(), + theAreaOfInterest(), + theNumberOfAoiObjects(0), + theNumberOfObjects(0) +{ + +} + + +ossimVectorRenderer::~ossimVectorRenderer() +{ + if (theImageViewTransform) + { + delete theImageViewTransform; + theImageViewTransform = NULL; + } +} + +bool ossimVectorRenderer::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + return false; +} + +bool ossimVectorRenderer::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimString newPrefix = prefix + ossimString("image_view_trans."); + + if(theImageViewTransform) + { + delete theImageViewTransform; + theImageViewTransform = NULL; + } + + theImageViewTransform + = ossimImageViewTransformFactory::instance()-> + createTransform(kwl, newPrefix.c_str()); + + return ossimImageSource::loadState(kwl, prefix); +} + +void +ossimVectorRenderer::setImageViewTransform(ossimImageViewTransform* transform) +{ + if(theImageViewTransform) + { + delete theImageViewTransform; + } + theImageViewTransform = transform; +} + +void ossimVectorRenderer::setAreaOfInterest(const ossimDrect& aoi) +{ + theAreaOfInterest = aoi; +} + +ossimDrect ossimVectorRenderer::getAreaOfInterest() const +{ + return theAreaOfInterest; +} + +ossimDrect ossimVectorRenderer::getBoundingRect(long resLevel)const +{ + return theBoundingRect; +} + +ossim_int32 ossimVectorRenderer::getNumberOfAoiObjects() const +{ + return theNumberOfAoiObjects; +} + +ossim_int32 ossimVectorRenderer::getNumberOfObjects() const +{ + return theNumberOfObjects; +} + +void ossimVectorRenderer::setBoundingRect(ossimDrect& rect) +{ + theBoundingRect = rect; +} + +void ossimVectorRenderer::setNumberOfAoiObjects(ossim_int32 number_of_objects) +{ + theNumberOfAoiObjects = number_of_objects; +} + +void ossimVectorRenderer::setNumberOfObjects(ossim_int32 number_of_objects) +{ + theNumberOfObjects = number_of_objects; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimVectorRenderer.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimVectorRenderer.h new file mode 100644 index 0000000000..92ac7bcc30 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimVectorRenderer.h @@ -0,0 +1,133 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken +// +// Description: +// +// Abstract class for rendering vector data. Derived classes should implement +// the "rasterizeVectorData" data method. +// +//******************************************************************* +// $Id: ossimVectorRenderer.h,v 1.7 2004/04/03 20:53:18 dburken Exp $ +#ifndef ossimVectorRenderer_HEADER +#define ossimVectorRenderer_HEADER + +#include "ossimImageSourceFilter.h" +#include "base/data_types/ossimDrect.h" +#include "base/data_types/ossimDpt3d.h" + +class ossimImageViewTransform; +class ossimImageData; + +class ossimVectorRenderer : public ossimImageSourceFilter +{ +public: + ossimVectorRenderer(); + ossimVectorRenderer(ossimImageSource* inputSource, + ossimImageViewTransform *transform = NULL); + virtual ~ossimVectorRenderer(); + + /** + * Renders the vector data to a data object. The area which is + * imaged is the area of interest. The scale is determined by the output + * view projection of the ImageViewTransform. + */ + virtual ossimImageData* renderVectorData() const = 0; + + /** + * Returns vector of ossimDpt3d points representing the data object at + * the index passed in. Implementors should set an error and return an + * empty vector if the index is out of range. + */ + virtual vector<ossimDpt3d> getObject(ossim_uint32 index) const = 0; + + /** + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * Sets the ImageViewTransform to be used for converting vector data. + */ + virtual void setImageViewTransform(ossimImageViewTransform* transform); + + /** + * Sets the area of interest. This will be used by the renderVectorData. + */ + virtual void setAreaOfInterest(const ossimDrect& aoi); + + /** + * Returns the current area of interest as an ossimDrect. + */ + virtual ossimDrect getAreaOfInterest() const; + + /** + * Returns the full bounding rectangle of current vector data loaded. + */ + virtual ossimDrect getBoundingRect(long resLevel=0)const; + + /** + * Returns the number of vector objects in the area of interest. + */ + virtual ossim_int32 getNumberOfAoiObjects() const; + + /** + * Returns the total number of vector objects in the full bounding + * rectangle. + */ + virtual ossim_int32 getNumberOfObjects() const; + +protected: + + /** + * Sets the bounding rectangle of current vector data loaded. + */ + virtual void setBoundingRect(ossimDrect& rect); + + /** + * Sets the number of vector objects in the area of interest. + */ + virtual void setNumberOfAoiObjects(ossim_int32 number_of_objects); + + /** + * Sets the number of vector objects in the full bounding rectangle. + */ + virtual void setNumberOfObjects(ossim_int32 number_of_objects); + +private: + + ossimImageViewTransform* theImageViewTransform; + ossimDrect theBoundingRect; + ossimDrect theAreaOfInterest; + ossim_int32 theNumberOfAoiObjects; + ossim_int32 theNumberOfObjects; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimWatermarkFilter.cpp b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimWatermarkFilter.cpp new file mode 100644 index 0000000000..63353c24a9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimWatermarkFilter.cpp @@ -0,0 +1,1167 @@ +//---------------------------------------------------------------------------- +// Copyright (c) 2005, David Burken, all rights reserved. +// +// License: See top level LICENSE.txt file. +// +// Author: David Burken +// +// Description: Class definition of ossimWatermarkFilter. +// Applies an image or watermark to image. Positioning is based on mode. +// Density is base on alpha weight. +// +//---------------------------------------------------------------------------- +// $Id: ossimWatermarkFilter.cpp,v 1.8 2005/12/21 15:43:36 dburken Exp $ + +#include <vector> + +#include <imaging/tile_sources/ossimWatermarkFilter.h> +#include <base/common/ossimTrace.h> +#include <base/common/ossimScopedLock.h> +#include <base/common/ossimKeywordNames.h> +#include <base/context/ossimNotifyContext.h> +#include <base/property/ossimFilenameProperty.h> +#include <base/property/ossimNumericProperty.h> +#include <base/property/ossimStringProperty.h> +#include <imaging/formats/ossimImageHandler.h> +#include <imaging/factory/ossimImageHandlerRegistry.h> +#include <imaging/factory/ossimImageDataFactory.h> + +#include <imaging/tile_sources/ossimScalarRemapper.h> + + +RTTI_DEF1(ossimWatermarkFilter, "ossimWatermarkFilter", ossimImageSourceFilter) + +static ossimTrace traceDebug(ossimString("ossimWatermarkFilter:debug")); + +// Keywords: +static const char WATERMARK_MODE_KW[] = "watermark_mode"; +static const char WEIGHT_KW[] = "weight"; + +#ifdef OSSIM_ID_ENABLED +static const char OSSIM_ID[] = "$Id: ossimWatermarkFilter.cpp,v 1.8 2005/12/21 15:43:36 dburken Exp $"; +#endif + +const ossim_float64 DEFAULT_WEIGHT = 0.20; + +ossimWatermarkFilter::ossimWatermarkFilter() + : + theFilename(ossimFilename::NIL), + theWatermarkWeight(DEFAULT_WEIGHT), + theTile(NULL), + theWatermark(NULL), + theMode(ossimWatermarkFilter::UPPER_LEFT), + theInputBoundingRect(), + theDirtyFlag(true), + theMutex() +{ + theEnableFlag = true; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimPixelFlipper::ossimPixelFlipper" << std::endl; +#ifdef OSSIM_ID_ENABLED + ossimNotify(ossimNotifyLevel_DEBUG) + << "OSSIM_ID: " << OSSIM_ID << std::endl; +#endif + } +} + +ossimWatermarkFilter::~ossimWatermarkFilter() +{ + // Dereference tiles and force a delete if last reference. + theWatermark = NULL; + theTile = NULL; +} + +ossimString ossimWatermarkFilter::getShortName() const +{ + return ossimString("Watermark Filter"); +} + +ossimString ossimWatermarkFilter::getLongName() const +{ + return ossimString("Watermark Filter - Applies watermark image onto getTile Request."); +} + +ossimString ossimWatermarkFilter::getDescription() const +{ + ossimString description; + description = getLongName(); + description += "\n"; + description += "Valid modes:\n"; + + vector<ossimString> list; + getModeList(list); + + vector<ossimString>::const_iterator i = list.begin(); + while (i != list.end()) + { + description +=(*i); + description += "\n"; + ++i; + } + + return description; +} + +ossimRefPtr<ossimImageData> ossimWatermarkFilter::getTile( + const ossimIrect& tile_rect, ossim_uint32 resLevel) +{ + // Lock for the length of this method. + ossimScopedLock<ossimMutex> scopeLock(theMutex); + + // Check for input. + if (!theInputConnection) + { + if (theTile.valid()) + { + theTile->setImageRectangle(tile_rect); + theTile->makeBlank(); + } + return theTile; + } + + // Fetch a tile from from the input source. + ossimRefPtr<ossimImageData> inputTile = + theInputConnection->getTile(tile_rect, resLevel); + + // Check for bypass. + if (theEnableFlag == false) return inputTile; + + // Check for weight being 0.0. + if (theWatermarkWeight == 0.0) return inputTile; + + //--- + // Check for dirty state. + // Note: This is set in initialize if something changes. + //--- + if (theDirtyFlag == true) + { + if (allocate() == false) // Something not right if false. + { + return inputTile; + } + } + + // We will only watermark (process) within the input bounding rectangle. + if (tile_rect.intersects(theInputBoundingRect) == false) + { + return inputTile; + } + + // Capture the rectangle and blank out theTile. + theTile->setImageRectangle(tile_rect); + + if (inputTile.valid() && + (inputTile->getDataObjectStatus() != OSSIM_NULL)) + { + // Copy the inputTile to theTile. + theTile->loadTile(inputTile.get()); + } + else + { + theTile->makeBlank(); + } + + // Write the watermarks... + switch(theTile->getScalarType()) + { + case OSSIM_UINT8: + { + fill(ossim_uint8(0)); + break; + } + case OSSIM_SINT8: + { + fill(ossim_sint8(0)); + break; + } + case OSSIM_USHORT11: + case OSSIM_UINT16: + { + fill(ossim_uint16(0)); + break; + } + case OSSIM_SINT16: + { + fill(ossim_sint16(0)); + break; + } + case OSSIM_UINT32: + { + fill(ossim_uint32(0)); + break; + } + case OSSIM_SINT32: + { + fill(ossim_sint32(0)); + break; + } + case OSSIM_FLOAT32: + case OSSIM_NORMALIZED_FLOAT: + { + fill(ossim_float32(0)); + break; + } + case OSSIM_FLOAT64: + case OSSIM_NORMALIZED_DOUBLE: + { + fill(ossim_float32(0)); + break; + } + case OSSIM_SCALAR_UNKNOWN: + default: + { + ossimNotify(ossimNotifyLevel_WARN) + << "Scalar type = " << theTile->getScalarType() + << " Not supported by ossimWatermarkFilter" << std::endl; + return inputTile; + } + } + + return theTile; +} + +template <class T> void ossimWatermarkFilter::fill(T /* dummy */) +{ + const ossimIrect TILE_RECT = theTile->getImageRectangle(); + + // We will only fill data within the input bounding rect. + const ossimIrect CLIPPED_TILE_RECT = + TILE_RECT.clipToRect(theInputBoundingRect); + + // Get the bounding rectangles. + vector<ossimIrect> rects(0); + getIntersectingRects(rects); + + if (rects.size() == 0) + { + return; + } + + //--- + // Have watermark rectangles that intersect this tile so we need to process. + //--- + ossim_uint32 band = 0; + ossim_float64 inputPixWeight = 1.0 - theWatermarkWeight; + + // Get a pointers to the watermark buffers (wmBuf) and nulls wn. + T** wmBuf = new T*[theWatermarkNumberOfBands]; + for (band = 0; band < theWatermarkNumberOfBands; ++band) + { + wmBuf[band] = static_cast<T*>(theWatermark->getBuf(band)); + } + + // Get a pointers to the output tile buffers and nulls in. + T** otBuf = new T*[theInputNumberOfBands]; + for (band = 0; band < theInputNumberOfBands; ++band) + { + otBuf[band] = static_cast<T*>(theTile->getBuf(band)); + } + + // Get the width of the buffers for indexing. + ossim_int32 wmWidth = static_cast<ossim_int32>(theWatermark->getWidth()); + ossim_int32 otWidth = static_cast<ossim_int32>(theTile->getWidth()); + + const ossim_float64* wmNull = theWatermark->getNullPix(); + const ossim_float64* otMin = theTile->getMinPix(); + const ossim_float64* otMax = theTile->getMaxPix(); + const ossim_float64* otNull = theTile->getNullPix(); + + + // Control loop through intersecting rectangles. + vector<ossimIrect>::const_iterator i = rects.begin(); + while (i != rects.end()) + { + if ( (*i).intersects(CLIPPED_TILE_RECT) ) + { + //--- + // This is the rectangle we want to fill relative to requesting + // image space. + //--- + const ossimIrect CLIPPED_WATERMARRK_RECT = + (*i).clipToRect(CLIPPED_TILE_RECT); + + ossim_int32 clipHeight = CLIPPED_WATERMARRK_RECT.height(); + ossim_int32 clipWidth = CLIPPED_WATERMARRK_RECT.width(); + + // Compute the starting offset into the wmBuf and otBuf. + ossim_int32 wmOffset = + (CLIPPED_WATERMARRK_RECT.ul().y - (*i).ul().y) * wmWidth + + CLIPPED_WATERMARRK_RECT.ul().x - (*i).ul().x; + ossim_int32 otOffset = + (CLIPPED_WATERMARRK_RECT.ul().y - TILE_RECT.ul().y)* otWidth + + CLIPPED_WATERMARRK_RECT.ul().x - TILE_RECT.ul().x; + + // Line loop... + for (ossim_int32 line = 0; line < clipHeight; ++line) + { + // Sample loop... + for (ossim_int32 sample = 0; sample < clipWidth; ++sample) + { + // Output band control loop until all output bands are filled. + ossim_uint32 otBand = 0; + while (otBand < theInputNumberOfBands) + { + // Band loop through the watermark. + for (ossim_uint32 wmBand = 0; + wmBand < theWatermarkNumberOfBands; + ++wmBand) + { + if (wmBuf[wmBand][wmOffset+sample] != wmNull[wmBand]) + { + // Apply the weight to the input pixel. + ossim_float64 p1 = + (otBuf[otBand][otOffset+sample] != otNull[otBand]) ? + otBuf[otBand][otOffset+sample] * inputPixWeight : + 0.0; + + // Apply the Weight to the watermark pixel. + ossim_float64 p2 = + wmBuf[wmBand][wmOffset+sample]*theWatermarkWeight; + + // Add them up. + ossim_float64 p3 = p1 + p2; + + // Cast to output type with range checking. + otBuf[otBand][otOffset+sample] = static_cast<T>( + ( (p3 >= otMin[otBand]) ? + (p3 < otMax[otBand] ? p3 : otMax[otBand]) : + otNull[otBand]) ); + } + ++otBand; + + // We stop when we reach here. All output bands filled. + if (otBand == theInputNumberOfBands) + { + break; + } + + } // End of band through watermark. + + } // End of outer band loop. + + } // End of sample loop. + + wmOffset += wmWidth; + otOffset += otWidth; + + } // End of line loop. + + } // End "if ( (*i).intersects(TILE_RECT) )" + + ++i; // Go to next rectangle to fill if any. + + } // End of "while (i != rects.end())" + + // Clean up. + delete [] wmBuf; + delete [] otBuf; + + theTile->validate(); +} + +void ossimWatermarkFilter::getIntersectingRects(vector<ossimIrect>& rects) +{ + switch(theMode) + { + case UPPER_LEFT: + getUpperLeftRect(rects); + break; + case UPPER_CENTER: + getUpperCenterRect(rects); + break; + case UPPER_RIGHT: + getUpperRightRect(rects); + break; + case CENTER: + getCenterRect(rects); + break; + case LOWER_LEFT: + getLowerLeftRect(rects); + break; + case LOWER_CENTER: + getLowerCenterRect(rects); + break; + case LOWER_RIGHT: + getLowerRightRect(rects); + break; + case UNIFORM_DENSE: + getUniformDenseRects(rects); + break; + case UNIFORM_SPARSE: + getUniformSparceRects(rects); + break; + default: + break; + } +} + +void ossimWatermarkFilter::getUpperLeftRect(vector<ossimIrect>& rects) +{ + // First clip the rect to the bounding image rectangle. + const ossimIrect CLIP_RECT = + theTile->getImageRectangle().clipToRect(theInputBoundingRect); + theWatermark->setOrigin(theInputBoundingRect.ul()); + ossimIrect r = theWatermark->getImageRectangle(); + if (r.intersects(CLIP_RECT)) + { + rects.push_back(r); + } +} + +void ossimWatermarkFilter::getUpperCenterRect(vector<ossimIrect>& rects) +{ + // First clip the rect to the bounding image rectangle. + const ossimIrect CLIP_RECT = + theTile->getImageRectangle().clipToRect(theInputBoundingRect); + ossim_uint32 watermarkWidth = theWatermark->getImageRectangle().width(); + ossim_uint32 inputWidth = theInputBoundingRect.width(); + ossimIpt origin = theInputBoundingRect.ul(); + + // Input wider than watermark so center. + if (inputWidth > watermarkWidth) + { + ossim_int32 offset = + static_cast<ossim_int32>((inputWidth - watermarkWidth) / 2); + origin.x = origin.x + offset; + } + + theWatermark->setOrigin(origin); + + ossimIrect r = theWatermark->getImageRectangle(); + if (r.intersects(CLIP_RECT)) + { + rects.push_back(r); + } +} + +void ossimWatermarkFilter::getUpperRightRect(vector<ossimIrect>& rects) +{ + // First clip the rect to the bounding image rectangle. + const ossimIrect CLIP_RECT = + theTile->getImageRectangle().clipToRect(theInputBoundingRect); + ossim_uint32 watermarkWidth = + theWatermark->getImageRectangle().width(); + ossim_uint32 inputWidth = theInputBoundingRect.width(); + + ossimIpt origin = theInputBoundingRect.ul(); + + // Input wider than watermark so center. + if (inputWidth > watermarkWidth) + { + ossim_int32 offset = + static_cast<ossim_int32>(inputWidth - watermarkWidth); + origin.x = origin.x + offset; + } + + theWatermark->setOrigin(origin); + + ossimIrect r = theWatermark->getImageRectangle(); + if (r.intersects(CLIP_RECT)) + { + rects.push_back(r); + } +} + +void ossimWatermarkFilter::getCenterRect(vector<ossimIrect>& rects) +{ + // First clip the rect to the bounding image rectangle. + const ossimIrect CLIP_RECT = + theTile->getImageRectangle().clipToRect(theInputBoundingRect); + ossim_uint32 watermarkWidth = theWatermark->getImageRectangle().width(); + ossim_uint32 watermarkHeight = theWatermark->getImageRectangle().height(); + ossim_uint32 inputWidth = theInputBoundingRect.width(); + ossim_uint32 inputHeight = theInputBoundingRect.height(); + ossimIpt origin = theInputBoundingRect.ul(); + + // Input wider than watermark so center. + if (inputWidth > watermarkWidth) + { + ossim_int32 offset = + static_cast<ossim_int32>((inputWidth - watermarkWidth) / 2); + origin.x = origin.x + offset; + } + // Input higher than watermark so center. + if (inputHeight > watermarkHeight) + { + ossim_int32 offset = + static_cast<ossim_int32>((inputHeight - watermarkHeight) / 2); + origin.y = origin.y + offset; + } + + theWatermark->setOrigin(origin); + + ossimIrect r = theWatermark->getImageRectangle(); + if (r.intersects(CLIP_RECT)) + { + rects.push_back(r); + } +} + +void ossimWatermarkFilter::getLowerLeftRect(vector<ossimIrect>& rects) +{ + // First clip the rect to the bounding image rectangle. + const ossimIrect CLIP_RECT = + theTile->getImageRectangle().clipToRect(theInputBoundingRect); + ossim_uint32 watermarkHeight = theWatermark->getImageRectangle().height(); + ossim_uint32 inputHeight = theInputBoundingRect.height(); + ossimIpt origin = theInputBoundingRect.ul(); + + // Input higher than watermark so apply offset. + if (inputHeight > watermarkHeight) + { + ossim_int32 offset = + static_cast<ossim_int32>(inputHeight - watermarkHeight); + origin.y = origin.y + offset; + } + + theWatermark->setOrigin(origin); + + ossimIrect r = theWatermark->getImageRectangle(); + if (r.intersects(CLIP_RECT)) + { + rects.push_back(r); + } +} + +void ossimWatermarkFilter::getLowerCenterRect(vector<ossimIrect>& rects) +{ + // First clip the rect to the bounding image rectangle. + const ossimIrect CLIP_RECT = + theTile->getImageRectangle().clipToRect(theInputBoundingRect); + ossim_uint32 watermarkWidth = theWatermark->getImageRectangle().width(); + ossim_uint32 watermarkHeight = theWatermark->getImageRectangle().height(); + ossim_uint32 inputWidth = theInputBoundingRect.width(); + ossim_uint32 inputHeight = theInputBoundingRect.height(); + ossimIpt origin = theInputBoundingRect.ul(); + + // Input wider than watermark so center. + if (inputWidth > watermarkWidth) + { + ossim_int32 offset = + static_cast<ossim_int32>((inputWidth - watermarkWidth) / 2); + origin.x = origin.x + offset; + } + // Input higher than watermark so apply offset. + if (inputHeight > watermarkHeight) + { + ossim_int32 offset = + static_cast<ossim_int32>(inputHeight - watermarkHeight); + origin.y = origin.y + offset; + } + + theWatermark->setOrigin(origin); + ossimIrect r = theWatermark->getImageRectangle(); + if (r.intersects(CLIP_RECT)) + { + rects.push_back(r); + } +} + +void ossimWatermarkFilter::getLowerRightRect(vector<ossimIrect>& rects) +{ + // First clip the rect to the bounding image rectangle. + const ossimIrect CLIP_RECT = + theTile->getImageRectangle().clipToRect(theInputBoundingRect); + ossim_uint32 watermarkWidth = theWatermark->getImageRectangle().width(); + ossim_uint32 watermarkHeight = theWatermark->getImageRectangle().height(); + ossim_uint32 inputWidth = theInputBoundingRect.width(); + ossim_uint32 inputHeight = theInputBoundingRect.height(); + ossimIpt origin = theInputBoundingRect.ul(); + + // Input wider than watermark so center. + if (inputWidth > watermarkWidth) + { + ossim_int32 offset = + static_cast<ossim_int32>(inputWidth - watermarkWidth); + origin.x = origin.x + offset; + } + // Input higher than watermark so apply offset. + if (inputHeight > watermarkHeight) + { + ossim_int32 offset = + static_cast<ossim_int32>(inputHeight - watermarkHeight); + origin.y = origin.y + offset; + } + + theWatermark->setOrigin(origin); + ossimIrect r = theWatermark->getImageRectangle(); + if (r.intersects(CLIP_RECT)) + { + rects.push_back(r); + } + +} + +void ossimWatermarkFilter::getUniformDenseRects(vector<ossimIrect>& rects) +{ + // First clip the rect to the bounding image rectangle. + const ossimIrect CLIP_RECT = + theTile->getImageRectangle().clipToRect(theInputBoundingRect); + ossim_uint32 watermarkWidth = theWatermark->getImageRectangle().width(); + ossim_uint32 watermarkHeight = theWatermark->getImageRectangle().height(); + ossim_uint32 inputWidth = theInputBoundingRect.width(); + ossim_uint32 inputHeight = theInputBoundingRect.height(); + + ossim_uint32 watermarksHigh = inputHeight / watermarkHeight; + if (inputHeight % watermarkHeight) ++watermarksHigh; + + ossim_uint32 watermarksWide = inputWidth / watermarkWidth; + if (inputWidth % watermarkWidth) ++watermarksWide; + + ossim_int32 xOffset = static_cast<ossim_int32>(watermarkWidth); + ossim_int32 yOffset = static_cast<ossim_int32>(watermarkHeight); + + ossimIpt origin = theInputBoundingRect.ul(); + + for (ossim_uint32 y = 0; y < watermarksHigh; ++y) + { + for (ossim_uint32 x = 0; x < watermarksWide; ++x) + { + theWatermark->setOrigin(origin); + ossimIrect r = theWatermark->getImageRectangle(); + if (r.intersects(CLIP_RECT)) + { + rects.push_back(r); + } + origin.x = origin.x + xOffset; + } + origin.y = origin.y + yOffset; + origin.x = theInputBoundingRect.ul().x; + } +} + +void ossimWatermarkFilter::getUniformSparceRects(vector<ossimIrect>& rects) +{ + // First clip the rect to the bounding image rectangle. + const ossimIrect CLIP_RECT = + theTile->getImageRectangle().clipToRect(theInputBoundingRect); + ossim_uint32 watermarkWidth = theWatermark->getImageRectangle().width(); + ossim_uint32 watermarkHeight = theWatermark->getImageRectangle().height(); + ossim_uint32 inputWidth = theInputBoundingRect.width(); + ossim_uint32 inputHeight = theInputBoundingRect.height(); + ossim_uint32 gapWidth = watermarkWidth/2; + ossim_uint32 gapHeight = watermarkHeight/2; + + ossim_uint32 watermarksHigh = inputHeight/(watermarkHeight+gapHeight); + if (inputHeight % watermarkHeight) ++watermarksHigh; + + ossim_uint32 watermarksWide = inputWidth/(watermarkWidth+gapWidth); + if (inputWidth % watermarkWidth) ++watermarksWide; + + ossim_int32 xOffset = static_cast<ossim_int32>(watermarkWidth + gapWidth); + ossim_int32 yOffset = static_cast<ossim_int32>(watermarkHeight + gapHeight); + + ossimIpt origin = theInputBoundingRect.ul(); + + for (ossim_uint32 y = 0; y < watermarksHigh; ++y) + { + for (ossim_uint32 x = 0; x < watermarksWide; ++x) + { + theWatermark->setOrigin(origin); + ossimIrect r = theWatermark->getImageRectangle(); + if (r.intersects(CLIP_RECT)) + { + rects.push_back(r); + } + origin.x = origin.x + xOffset; + } + origin.y = origin.y + yOffset; + origin.x = theInputBoundingRect.ul().x; + } +} + +void ossimWatermarkFilter::initialize() +{ + //--- + // If state is not already dirty and there is an input connection + // check for: + // + // 1) Scalar change + // 2) band number change + // 3) bounding box change + // + // Set state to dirty on a change. + // + // NOTE: This method intentionally only sets the dirty state and doesn't do + // anything else as it is called repetitively during chain setup or chain + // state changes. + // + // The first getTile call will do the real work, call allocate(), + // if the state is dirty. + //--- + + // Lock for the length of this method. + ossimScopedLock<ossimMutex> scopeLock(theMutex); + + // Set the input connection. + ossimImageSourceFilter::initialize(); + + // Once dirty flag is set no need to do it again. + if (theDirtyFlag == false) + { + if (theInputConnection) + { + // Check for scalar type change. + if (theInputScalarType != theInputConnection->getOutputScalarType()) + { + theDirtyFlag = true; + return; + } + + // Check for band change. + if (theInputNumberOfBands != + theInputConnection->getNumberOfOutputBands()) + { + theDirtyFlag = true; + return; + } + + // Check for bounding rectangle change. + if ( theInputBoundingRect != theInputConnection->getBoundingRect() ) + { + theDirtyFlag = true; + return; + } + } + } +} + +bool ossimWatermarkFilter::allocate() +{ + // Capture the bounding rect: + theInputBoundingRect = theInputConnection->getBoundingRect(); + + // Capture the scalar type: + theInputScalarType = theInputConnection->getOutputScalarType(); + + // Capture the number of bands: + theInputNumberOfBands = theInputConnection->getNumberOfOutputBands(); + + //--- + // Check the watermark scalar type. + //--- + if (theWatermark.valid()) + { + if (theWatermark->getScalarType() != theInputScalarType) + { + //--- + // We'll need to make a new one with a scalar remapper after it. + //--- + theWatermark = NULL; // We'll need to make a new one. + } + } + + //--- + // Make a new watermark tile. This will do a scalar remap if needed. + // If we don't have a watermark no point in going on... + //--- + if (!theWatermark) + { + if (openWatermarkFile() == false) + { + return false; + } + } + + if (theTile.valid()) + { + if ( (theTile->getScalarType() != theInputScalarType) || + (theTile->getNumberOfBands() != theInputNumberOfBands) ) + { + theTile = NULL; // We'll need to make a new one. + } + } + + // Make a new output tile if we need to. + if (!theTile) + { + theTile = ossimImageDataFactory::instance()->create(this, + theInputConnection); + if (theTile.valid()) + { + theTile->initialize(); + } + else + { + return false; + } + } + + //--- + // If we get here things are good so clear the dirty flag so we don't + // get called again needlessly. + //--- + theDirtyFlag = false; + + return true; +} + +bool ossimWatermarkFilter::openWatermarkFile() +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimWatermarkFilter::openWatermarkFile DEBUG: entered..." + << std::endl; + } + + if (!theInputConnection || (theFilename == ossimFilename::NIL)) + { + return false; + } + + theWatermark = NULL; // This will destroy any previous tiles. + + // Open the watermark image. + ossimImageHandler* ih = + ossimImageHandlerRegistry::instance()->open(theFilename); + if (!ih) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimWatermarkFilter::openWatermarkFile" + << "\nCould not open: " << theFilename + << std::endl; + } + + return false; + } + if (ih->getErrorStatus() == ossimErrorCodes::OSSIM_ERROR) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimWatermarkFilter::openWatermarkFile" + << "\nError reading image: " << theFilename + << std::endl; + return false; + } + } + + ih->initialize(); + ossimImageSource* imageSource = ih; + ossimScalarRemapper* remapper = NULL; + + if (ih->getOutputScalarType() != theInputConnection->getOutputScalarType()) + { + // Remap the watemark to the same scalar type as the input. + remapper = new ossimScalarRemapper(imageSource, + theInputConnection-> + getOutputScalarType()); + remapper->initialize(); + imageSource = remapper; + } + + // Get the full image rectangle. + theWatermark = imageSource->getTile(ih->getImageRectangle(), 0); + + // Cleanup... + if (remapper) + { + delete remapper; + remapper = NULL; + } + if (ih) + { + delete ih; + ih = NULL; + } + imageSource = NULL; + + if (theWatermark.valid() == false) + { + return false; + } + + // Capture the bands as we will need this repetitively. + theWatermarkNumberOfBands = theWatermark->getNumberOfBands(); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimWatermarkFilter::openWatermarkFile DEBUG:" + << *(theWatermark.get()) + << endl; + } + + return true; +} + +bool ossimWatermarkFilter::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + kwl.add(prefix, + ossimKeywordNames::FILENAME_KW, + theFilename.c_str()); + kwl.add(prefix, + WATERMARK_MODE_KW, + getModeString().c_str()); + kwl.add(prefix, + WEIGHT_KW, + theWatermarkWeight); + + return ossimImageSourceFilter::saveState(kwl, prefix); +} + +bool ossimWatermarkFilter::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + // Do this first so connections get set up. + if (ossimImageSourceFilter::loadState(kwl, prefix) == false) + { + return false; + } + + const char* lookupReturn; + + lookupReturn = kwl.find(prefix, WEIGHT_KW); + if(lookupReturn) + { + setWeight(ossimString(lookupReturn).toDouble()); + } + + lookupReturn = kwl.find(prefix, WATERMARK_MODE_KW); + if(lookupReturn) + { + setMode(ossimString(lookupReturn)); + } + + lookupReturn = kwl.find(prefix, ossimKeywordNames::FILENAME_KW); + if(lookupReturn) + { + setFilename(lookupReturn); + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimWatermarkFilter::loadState DEBUG:" + << std::endl; + print(ossimNotify(ossimNotifyLevel_DEBUG)); + } + + return true; +} + +ossimRefPtr<ossimProperty> ossimWatermarkFilter::getProperty( + const ossimString& name) const +{ + // Lock for the length of this method. + ossimScopedLock<ossimMutex> scopeLock(theMutex); + + if (name == ossimKeywordNames::FILENAME_KW) + { + ossimFilenameProperty* ofp = + new ossimFilenameProperty(name, theFilename); + ofp->setIoType(ossimFilenameProperty::ossimFilenamePropertyIoType_INPUT); + ofp->setCacheRefreshBit(); + return ossimRefPtr<ossimProperty>((ossimProperty*)ofp); + } + else if (name == WATERMARK_MODE_KW) + { + vector<ossimString> constraintList; + getModeList(constraintList); + + ossimStringProperty* p = + new ossimStringProperty(name, + getModeString(), + false, + constraintList); + p->setCacheRefreshBit(); + return ossimRefPtr<ossimProperty>(p); + } + else if (name == WEIGHT_KW) + { + ossimProperty* p = + new ossimNumericProperty(name, + ossimString::toString(theWatermarkWeight)); + p->setCacheRefreshBit(); + return ossimRefPtr<ossimProperty>(p); + } + + return ossimImageSourceFilter::getProperty(name); +} + +void ossimWatermarkFilter::setProperty(ossimRefPtr<ossimProperty> property) +{ + if (!property) return; + + ossimString os = property->valueToString(); + + ossimString name = property->getName(); + if (name == ossimKeywordNames::FILENAME_KW) + { + setFilename(os); + } + else if (name == WATERMARK_MODE_KW) + { + setMode(os); + } + else if (name == WEIGHT_KW) + { + setWeight(os.toDouble()); + } + else + { + ossimImageSourceFilter::setProperty(property); + } +} + +void ossimWatermarkFilter::getPropertyNames( + std::vector<ossimString>& propertyNames) const +{ + propertyNames.push_back(ossimKeywordNames::FILENAME_KW); + propertyNames.push_back(WATERMARK_MODE_KW); + propertyNames.push_back(WEIGHT_KW); + ossimImageSourceFilter::getPropertyNames(propertyNames); +} + +void ossimWatermarkFilter::getModeList(vector<ossimString>& list) const +{ + list.clear(); + list.resize(ossimWatermarkFilter::END); + list[0] = ossimString("upper_left"); + list[1] = ossimString("upper_center"); + list[2] = ossimString("upper_right"); + list[3] = ossimString("center"); + list[4] = ossimString("lower_left"); + list[5] = ossimString("lower_center"); + list[6] = ossimString("lower_right"); + list[7] = ossimString("uniform_dense"); + list[8] = ossimString("uniform_sparse"); +} + +ossimWatermarkFilter::WatermarkMode ossimWatermarkFilter::getMode() const +{ + return theMode; +} + +ossimString ossimWatermarkFilter::getModeString() const +{ + switch(theMode) + { + case UPPER_LEFT: + return ossimString("upper_left"); + case UPPER_CENTER: + return ossimString("upper_center"); + case UPPER_RIGHT: + return ossimString("upper_right"); + case CENTER: + return ossimString("center"); + case LOWER_LEFT: + return ossimString("lower_left"); + case LOWER_CENTER: + return ossimString("lower_center"); + case LOWER_RIGHT: + return ossimString("lower_right"); + case UNIFORM_DENSE: + return ossimString("uniform_dense"); + case UNIFORM_SPARSE: + return ossimString("uniform_sparse"); + default: + break; + } + + return ossimString("UNKNOWN_MODE"); +} + +void ossimWatermarkFilter::setFilename(const ossimFilename& file) +{ + if (file != theFilename) + { + theFilename = file; + theWatermark = NULL; // Will be reallocated next getTile. + theDirtyFlag = true; + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimWatermarkFilter::setFilename DEBUG:" << std::endl; + print(ossimNotify(ossimNotifyLevel_DEBUG)); + } +} + +void ossimWatermarkFilter::setMode(const ossimString& mode) +{ + ossimString os = mode; + os.downcase(); + + if (os == "upper_left") + { + theMode = UPPER_LEFT; + } + else if (os == "upper_center") + { + theMode = UPPER_CENTER; + } + else if (os == "upper_right") + { + theMode = UPPER_RIGHT; + } + else if (os == "center") + { + theMode = CENTER; + } + else if (os == "lower_left") + { + theMode = LOWER_LEFT; + } + else if (os == "lower_center") + { + theMode = LOWER_CENTER; + } + else if (os == "lower_right") + { + theMode = LOWER_RIGHT; + } + else if (os == "uniform_dense") + { + theMode = UNIFORM_DENSE; + } + else if (os == "uniform_sparse") + { + theMode = UNIFORM_SPARSE; + } + else + { + // Invalid mode... + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimWatermarkFilter::setMode DEBUG:" + << "\nInvalid mode! " << mode + << std::endl; + } + } +} + +void ossimWatermarkFilter::setWeight(ossim_float64 weight) +{ + if ( (weight >= 0.0) && (weight <= 1.0) ) + { + theWatermarkWeight = weight; + } + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimWatermarkFilter::setWeight DEBUG:" << std::endl; + print(ossimNotify(ossimNotifyLevel_DEBUG)); + } + +} + +std::ostream& ossimWatermarkFilter::print(std::ostream& out) const +{ + out << "ossimWatermarkFilter::print" + << "\ntheFilename: " << theFilename + << "\ntheWatermarkWeight: " << theWatermarkWeight + << "\ntheMode: " << getModeString() + << std::endl; + return ossimImageSourceFilter::print(out); +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimWatermarkFilter.h b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimWatermarkFilter.h new file mode 100644 index 0000000000..c668a99226 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tile_sources/ossimWatermarkFilter.h @@ -0,0 +1,351 @@ +//---------------------------------------------------------------------------- +// Copyright (c) 2005, David Burken, all rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: Class declaration of ossimWatermarkFilter. +// Applies an image or watermark to image. Positioning is based on mode. +// Density is base on alpha weight. +// +//---------------------------------------------------------------------------- +// $Id: ossimWatermarkFilter.h,v 1.4 2005/08/31 21:07:05 dburken Exp $ +#ifndef ossimWatermarkFilter_HEADER +#define ossimWatermarkFilter_HEADER + +#include <base/common/ossimConstants.h> +#include <base/common/ossimMutex.h> +#include <base/data_types/ossimString.h> +#include <base/data_types/ossimFilename.h> +#include <base/data_types/ossimIrect.h> +#include <imaging/tile_sources/ossimImageSourceFilter.h> + +/** + * class ossimWatermarkFilter + * Applies an image or watermark to image. + * Positioning is based on mode. + * Density is base on alpha weight. + */ +class OSSIMDLLEXPORT ossimWatermarkFilter : public ossimImageSourceFilter +{ +public: + + enum WatermarkMode + { + UPPER_LEFT = 0, + UPPER_CENTER = 1, + UPPER_RIGHT = 2, + CENTER = 3, + LOWER_LEFT = 4, + LOWER_CENTER = 5, + LOWER_RIGHT = 6, + UNIFORM_DENSE = 7, + UNIFORM_SPARSE = 8, + END = 9 //< Number of modes. + }; + + /** contructor */ + ossimWatermarkFilter(); + + /** destructor */ + virtual ~ossimWatermarkFilter(); + + /** @return Short name of filter. */ + virtual ossimString getShortName() const; + + /** @return Long name of filter. */ + virtual ossimString getLongName() const; + + /** @return Descriptive name of filter. */ + virtual ossimString getDescription() const; + + /** + * @param tile_rect Rectangle to fill tile with. + * + * @param resLevel Reduced resolution level to grab from. + * + * @return ossimRefPtr<ossimImageData> This is tile that was filled with + * tile_rect. + * + * @note Callers should check the ossimRefPtr::valid method. + * The internal pointer of the ossimRefPtr<ossimImageData> can be + * null if the tile_rect did not intersect the input connection's + * bounding rectangle. + */ + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tile_rect, + ossim_uint32 resLevel=0); + + /** + * Initializes state of the object from the input connection. + */ + virtual void initialize(); + + /** + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + * + * Keywords picked saved by saveState + * + * filename: my_colormap_file.jpg + * + * weight: .25 + * + * watermark_mode: upper_left + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of the object from a keyword + * list. + * + * @param kwl Keyword list to initialize from. + * + * @param prefix Usually something like: "object1." + * + * @return This method will alway return true as it is intended to be + * used in conjuction with the set methods. + * + * Keywords picked up by loadState: + * + * filename: my_colormap_file.jpg + * + * weight: .25 + * + * watermark_mode: upper_left + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * @param The property to get as a string like "watermark_mode". + * + * @return ossimRefPt<ossimProperty> holding pointer to ossimProperty + * matching string or null pointer if string does not match. + * + * @note Internal pointer can be null so callers should check prior to + * accessing like: + * ossimRefPtr<ossimProperty> p = myFilter->getProperty(ossimString("foo")); + * if (p.valid() == NULL) + * { + * some_error; + * } + */ + virtual ossimRefPtr<ossimProperty> getProperty( + const ossimString& name)const; + + /** + * Set property. + * + * @param property Property to set if property->getName() matches a + * property name of this object. + */ + virtual void setProperty(ossimRefPtr<ossimProperty> property); + + /** + * Adds this objects properties to the list. + * + * @param propertyNames Array to add to. + * + * @note This method does not clear propertyNames prior to adding it's + * names. + */ + virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const; + + /** + * @param list List initialized with watermark mode strings. + * + * @note This method clears the "list" prior to stuffing. + */ + void getModeList(vector<ossimString>& list) const; + + /** @return theMode */ + ossimWatermarkFilter::WatermarkMode getMode() const; + + /** @return theMode as a string like "upper_left". */ + ossimString getModeString() const; + + /** + * Sets theFilename to file. + * + * @param file The watermark image file. + */ + void setFilename(const ossimFilename& file); + + /** + * Sets the filter mode. + * + * @param mode String representing mode. + */ + void setMode(const ossimString& mode); + + /** + * Sets the weight. + * + * @param weight Weight to use for watermark pixels normalize between + * 0.0 and 1.0. + */ + void setWeight(ossim_float64 weight); + + /** + * Print method. Called by: friend operator<< + * + * @return std::ostream& + */ + virtual std::ostream& print(std::ostream& out) const; + +private: + + /** + * Allocates / recomputes things that are needed. Clears theDirtyFlag + * by setting it to false on success. + * + * @return true on success, false on error. + */ + bool allocate(); + + /** + * Attempts to open "theFilename". This will load "theWatermark" with + * the image converting it to the scalar type of the input connection. + * + * @return true on success, false if no image handler is found for the + * image or theInputConnection has not been established. + */ + bool openWatermarkFile(); + + // void verifyEnable(); + + /** + * Writes watermark(s) to theTile. + * Performs theTile->validate() at the end if theTile was touched. + */ + template <class T> void fill(T dummy); + + /** + * Computes the bounding rectangles. These are the rectangles in image + * space of the input connection to paint the watermark(s) on. The start of + * each rectangle will be the start of where "theWatermark" is painted. + */ + void getIntersectingRects(vector<ossimIrect>& rects); + + /** + * Addes upper left watermark rectangle to rects if it intersects + * theTile rect clipped to input bounding rect. + * + * @param rects Array to add rect to. + */ + void getUpperLeftRect(vector<ossimIrect>& rects); + + /** + * Addes upper center watermark rectangle to rects if it intersects + * theTile rect clipped to input bounding rect. + * + * @param rects Array to add rect to. + */ + void getUpperCenterRect(vector<ossimIrect>& rects); + + /** + * Addes upper right watermark rectangle to rects if it intersects + * theTile rect clipped to input bounding rect. + * + * @param rects Array to add rect to. + */ + void getUpperRightRect(vector<ossimIrect>& rects); + + /** + * Addes center watermark rectangle to rects if it intersects + * theTile rect clipped to input bounding rect. + * + * @param rects Array to add rect to. + */ + void getCenterRect(vector<ossimIrect>& rects); + + /** + * Addes lower left watermark rectangle to rects if it intersects + * theTile rect clipped to input bounding rect. + * + * @param rects Array to add rect to. + */ + void getLowerLeftRect(vector<ossimIrect>& rects); + + /** + * Addes lower center watermark rectangle to rects if it intersects + * theTile rect clipped to input bounding rect. + * + * @param rects Array to add rect to. + */ + void getLowerCenterRect(vector<ossimIrect>& rects); + + /** + * Addes lower right watermark rectangle to rects if it intersects + * theTile rect clipped to input bounding rect. + * + * @param rects Array to add rect to. + */ + void getLowerRightRect(vector<ossimIrect>& rects); + + /** + * Addes rectangles to rects if it intersects + * theTile rect clipped to input bounding rect. + * + * This will repeat the watermark throughout the input bounding rect. + * + * @param rects Array to add rect to. + */ + void getUniformDenseRects(vector<ossimIrect>& rects); + + /** + * Addes rectangles to rects if it intersects + * theTile rect clipped to input bounding rect. + * + * This will repeat the watermark sparsly throughout the input bounding + * rect. + * + * @param rects Array to add rect to. + */ + void getUniformSparceRects(vector<ossimIrect>& rects); + + /** File name of watermark image. */ + ossimFilename theFilename; + + /** Normalized between 0.0 and 1.0. */ + ossim_float64 theWatermarkWeight; + + /** The returned tile. */ + ossimRefPtr<ossimImageData> theTile; + + /** Tile storage for watermark image. */ + ossimRefPtr<ossimImageData> theWatermark; + + /** The number of watermark bands. */ + ossim_uint32 theWatermarkNumberOfBands; + + /** The filter mode. */ + WatermarkMode theMode; + + /** The bounding rectangle of the input connection. */ + ossimIrect theInputBoundingRect; + + /** The number of input bands. */ + ossim_uint32 theInputNumberOfBands; + + /** The input scalar type. */ + ossimScalarType theInputScalarType; + + /** + * Set in the initialize method this instructs the getTile that something + * has changes and it need to call initialize. + */ + bool theDirtyFlag; + + /** For locking for threads. */ + mutable ossimMutex theMutex; + +TYPE_DATA + +}; // End of class ossimWatermarkFilter. + +#endif /* #ifndef ossimWatermarkFilter_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/imaging/tonal_balance/.cvsignore b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimAtbController.cpp b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimAtbController.cpp new file mode 100644 index 0000000000..fec899a13a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimAtbController.cpp @@ -0,0 +1,594 @@ +//***************************************************************************** +// File: ossimAtbController.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// AUTHOR: Oscar Kramer (okramer@imagelinks.com) +// +// DESCRIPTION: Contains implementation of class ossimAtbController. This is the +// controller managing the tonal balancing process. It's product is the +// initialization of specialized remappers in each of the mosaic's member +// images that results in a tonally balanced mosaic. +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimAtbController.cpp,v 1.12 2005/09/09 19:23:58 gpotts Exp $ + +#include "ossimAtbController.h" + +RTTI_DEF2(ossimAtbController, "ossimAtbController", ossimProcessInterface, ossimConnectableObject ); + +#include <stdio.h> +#include "ossimGridRemapEngineFactory.h" +#include "base/data_types/ossimKeywordlist.h" +#include "ossimAtbMatchPoint.h" +#include "ossimGridRemapSource.h" +#include "base/common/ossimConnectableContainer.h" +#include "imaging/tile_sources/ossimImageCombiner.h" + +//*** +// Define Trace flags for use within this file: +//*** +#include "base/common/ossimTrace.h" +static ossimTrace traceExec ("ossimAtbController:exec"); +static ossimTrace traceDebug ("ossimAtbController:debug"); + +static const ossimIpt DEFAULT_GRID_SPACING (64,64); +static const char* DEFAULT_ATB_REMAP_ENGINE = "ossimHsvGridRemapEngine"; + +//***************************************************************************** +// CONSTRUCTOR: ossimAtbController() +// +//***************************************************************************** +ossimAtbController::ossimAtbController() + : + ossimConnectableObject(NULL, 0, 0, false, true), + theContainer (0), + theGridRemapEngine (0), + theGridSpacing (DEFAULT_GRID_SPACING) +{ + static const char MODULE[] = "ossimAtbController Default Constructor"; + if (traceExec()) CLOG << "entering..." << endl; + + //*** + // Instantiate a default remap engine: + //*** + theGridRemapEngine + = ossimGridRemapEngineFactory::create(DEFAULT_ATB_REMAP_ENGINE); + + if (traceExec()) CLOG << "returning..." << endl; +} + +//***************************************************************************** +// CONSTRUCTOR: ossimAtbController() +// +//***************************************************************************** +ossimAtbController::ossimAtbController(ossimImageCombiner* combiner, + ossimGridRemapEngine* engine) + : + ossimConnectableObject(NULL, 0, 0, false, true), + theContainer (0), + theGridRemapEngine (0), + theGridSpacing (DEFAULT_GRID_SPACING) +{ + static const char MODULE[] = "ossimAtbController Constructor #1"; + if (traceExec()) CLOG << "entering..." << endl; + + initializeWithCombiner(combiner, engine); + + if (traceExec()) CLOG << "returning..." << endl; +} + +//***************************************************************************** +// CONSTRUCTOR: ossimAtbController() +// +//***************************************************************************** +ossimAtbController::ossimAtbController(ossimGridRemapEngine* engine) + : + theContainer (0), + theGridRemapEngine (0), + theGridSpacing (DEFAULT_GRID_SPACING) +{ + static const char MODULE[] = "ossimAtbController Constructor #1"; + if (traceExec()) CLOG << "entering..." << endl; + + //*** + // Assign default engine if non provided: + //*** + delete theGridRemapEngine; + if (engine) + theGridRemapEngine = (ossimGridRemapEngine*)engine->dup(); + else + theGridRemapEngine + = ossimGridRemapEngineFactory::create(DEFAULT_ATB_REMAP_ENGINE); + + if (traceExec()) CLOG << "returning..." << endl; +} + +//***************************************************************************** +// DESTRUCTOR: ~ossimAtbController() +// +// The remappers are left behind, owned by the combiner's container. If the +// combiner was owned by something other than a container (see initialize()), +// then this controller will assume ownership of the allocated remappers and +// delete them here. +// +//***************************************************************************** +ossimAtbController::~ossimAtbController() +{ + if (!theContainer) + { + //*** + // No container exists that assumed ownership of the remappers, so delete + // them here: + //*** + for (unsigned int i=0; i<getNumberOfInputs(); i++) + delete getInput(i); + } + + delete theGridRemapEngine; +} + +//***************************************************************************** +// METHOD: ossimAtbController::initializeWithCombiner() +// +//***************************************************************************** +void ossimAtbController::initializeWithCombiner(ossimImageCombiner* combiner, + ossimGridRemapEngine* engine) +{ + static const char MODULE[] = "ossimAtbController::initializeWithCombiner()"; + if (traceExec()) CLOG << "entering..." << endl; + + //*** + // Assign default engine if non provided: + //*** + delete theGridRemapEngine; + if (engine) + theGridRemapEngine = (ossimGridRemapEngine*)engine->dup(); + else + theGridRemapEngine + = ossimGridRemapEngineFactory::create(DEFAULT_ATB_REMAP_ENGINE); + + //*** + // This is the first combiner initializing the controller. The combiner + // will have all of the input sources connected already. We attach to + // these: + //*** + theContainer = PTR_CAST(ossimConnectableContainer, combiner->getOwner()); + + //*** + // Need to scan the input connections of the combiner and insert a + // remapper if there is not one already at the end of the input chain: + //*** + vector<ossimConnectableObject*> del_list; + vector<ossimConnectableObject*> add_list; + int numInputs = combiner->getNumberOfInputs(); + for(int i=0; i<numInputs; i++) + { + ossimImageSource* input_image = PTR_CAST(ossimImageSource, + combiner->getInput(i)); + + if (input_image) + { + ossimGridRemapSource* remapper = PTR_CAST(ossimGridRemapSource, + input_image); + if (remapper) + { + //*** + // Remapper already present, set its remap engine to this + // controller's remap engine: + //*** + remapper->setRemapEngine(theGridRemapEngine); + } + + else + { + //*** + // Need to instantiate remapper: + //*** + remapper = new ossimGridRemapSource(input_image, + theGridRemapEngine); + if (theContainer) + theContainer->addChild(remapper); + + add_list.push_back(remapper); + del_list.push_back(input_image); + } + + connectMyInputTo(remapper); + } + } + + //*** + // Need to delete the old inputs and add the new remappers to the + // combiner's input list: + //*** + vector<ossimConnectableObject*>::iterator add_iter = add_list.begin(); + vector<ossimConnectableObject*>::iterator del_iter = del_list.begin(); + while (add_iter != add_list.end()) + { + (*add_iter)->connectMyInputTo(*del_iter); + combiner->disconnect(*del_iter); + combiner->connectMyInputTo(*add_iter); + add_iter++; + del_iter++; + } + combiner->initialize(); + + if (traceExec()) CLOG << "returning..." << endl; +} + +//***************************************************************************** +// METHOD: ossimAtbController::enableImage() +// +// Enable an image in the mosaic to be included the tonal balancing process. +// +//***************************************************************************** +bool ossimAtbController::enableImage(unsigned int index) +{ + if (index >= getNumberOfInputs()) + return false; + + ossimSource* remapper = PTR_CAST(ossimSource, + getInput(index)); + if (remapper) + remapper->enableSource(); + + return true; +} + +//***************************************************************************** +// METHOD: ossimAtbController::disableImage() +// +// Disable an image in the mosaic from the tonal balancing process. +// +//***************************************************************************** +bool ossimAtbController::disableImage(unsigned int index) +{ + if (index >= getNumberOfInputs()) + return false; + + ossimSource* remapper = PTR_CAST(ossimSource, + getInput(index)); + if (remapper) + remapper->disableSource(); + + return true; +} + +//***************************************************************************** +// METHOD: ossimAtbController::lockImage() +// +// Locks a particular source for adjustment. A locked image +// effectively defines the target values for all overlapping imagery. +// +//***************************************************************************** +bool ossimAtbController::lockImage(unsigned int index) +{ + if (index >= getNumberOfInputs()) + return false; + + ossimGridRemapSource* remapper = PTR_CAST(ossimGridRemapSource, + getInput(index)); + if (remapper) + remapper->lock(); + + return true; +} + + +//***************************************************************************** +// METHOD: ossimAtbController::unlockImage() +// +// Unlocks a particular source for allowing its adjustment. +// +//***************************************************************************** +bool ossimAtbController::unlockImage(unsigned int index) +{ + if (index >= getNumberOfInputs()) + return false; + + ossimGridRemapSource* remapper = PTR_CAST(ossimGridRemapSource, + getInput(index)); + if (remapper) + remapper->lock(); + + return true; +} + + +//***************************************************************************** +// METHOD: ossimAtbController::execute() +// +//***************************************************************************** +bool ossimAtbController::execute() +{ + static const char MODULE[] = "ossimAtbController::execute()"; + if (traceExec()) CLOG << "entering..." << endl; + + setPercentComplete(0.0); + + ossimGridRemapSource* source; + + //*** + // First verify that all objects needed are initialized: + //*** + int num_images = getNumberOfInputs(); + if ((!theGridRemapEngine) || (num_images < 2)) + { + CLOG << "WARNING: execute method was called but the controller has not " + << "been properly initialized. Ignoring request..." << endl; + if (traceExec()) CLOG << "returning..." << endl; + return false; + } + + //*** + // establish the remap grids: + //*** + initializeRemappers(); + setPercentComplete(10.0); + + //*** + // Establish grid of matchpoints: + //*** + int numPoints = 0; + ossimDpt mp_view_pt; + theMatchPoints.clear(); + for (mp_view_pt.line = theBoundingRect.ul().line; + mp_view_pt.line <= theBoundingRect.lr().line; + mp_view_pt.line += theGridSpacing.line) + { + for (mp_view_pt.samp = theBoundingRect.ul().samp; + mp_view_pt.samp <= theBoundingRect.lr().samp; + mp_view_pt.samp += theGridSpacing.samp) + { + ossimAtbMatchPoint* mp = new ossimAtbMatchPoint(mp_view_pt, + theGridRemapEngine); + theMatchPoints.push_back(mp); + numPoints++; + } + } + + //*** + // Loop over each matchpoint to determine which images contribute statistics: + //*** + setPercentComplete(20.0); + for (int mp=0; mp<numPoints; mp++) + { + ossimDpt view_point (theMatchPoints[mp]->viewPoint()); + + //*** + // Loop over each image source to check if point lies inside its bounding + // rectangle, and add its contribution to the matchpoint's collection: + //*** + for (int src=0; src<num_images; src++) + { + source = PTR_CAST(ossimGridRemapSource, getInput(src)); + if (source) + { + ossimDrect image_rect (source->getBoundingRect()); + if (image_rect.pointWithin(view_point)) + theMatchPoints[mp]->addImage(source); + } + } + + setPercentComplete(20.0 + 50.0*(mp/numPoints)); + } + + //*** + // All contributors have been included in all matchpoints' collections. + // Compute the target pixel value for each matchpoint and communicate it + // to the corresponding remappers: + //*** + for (int mp=0; mp<numPoints; mp++) + { + setPercentComplete(70.0 + 30.0*(mp/numPoints)); + theMatchPoints[mp]->assignRemapValues(); + } + + //*** + // Finally, enable the remappers: + //*** + for (int src=0; src<num_images; src++) + { + source = PTR_CAST(ossimGridRemapSource, getInput(src)); + if (source) + source->enableSource(); + } + setPercentComplete(100.0); + + if (traceExec()) CLOG << "returning..." << endl; + return true; +} + +//***************************************************************************** +// METHOD: ossimAtbController::abort() +// +//***************************************************************************** +void ossimAtbController::abort() +{ + static const char MODULE[] = "ossimAtbController::abort()"; + if (traceExec()) CLOG << "entering..." << endl; + + CLOG << "NOTICE: this method not yet implemented." << endl; + + if (traceExec()) CLOG << "returning..." << endl; +} + +//***************************************************************************** +// METHOD: ossimAtbController::saveState() +// +//***************************************************************************** +bool ossimAtbController::saveState(ossimKeywordlist& kwl) const +{ + static const char MODULE[] = "ossimAtbController::saveState()"; + if (traceExec()) CLOG << "entering..." << endl; + + CLOG << "NOTICE: this method not yet implemented." << endl; + + if (traceExec()) CLOG << "returning..." << endl; + return true; +} + +//***************************************************************************** +// METHOD: ossimAtbController::loadState() +// +//***************************************************************************** +bool ossimAtbController::loadState(const ossimKeywordlist& kwl) +{ + static const char MODULE[] = "ossimAtbController::loadState()"; + if (traceExec()) CLOG << "entering..." << endl; + + CLOG << "NOTICE: this method not yet implemented." << endl; + + if (traceExec()) CLOG << "returning..." << endl; + return true; +} + + +//***************************************************************************** +// METHOD: ossimAtbController::setKernelSize(N) +// +// Hook to set the size of the kernel used by all point sources in computing +// their mean pixel value. The kernels will be resized to NxN. +// +//***************************************************************************** +void ossimAtbController::setKernelSize(int side_size) +{ + static const char MODULE[] = "ossimAtbController::setKernelSize(N)"; + if (traceExec()) CLOG << "entering..." << endl; + + vector<ossimAtbMatchPoint*>::iterator mpi = theMatchPoints.begin(); + while (mpi != theMatchPoints.end()) + (*mpi)->setKernelSize(side_size); + + if (traceExec()) CLOG << "returning..." << endl; + return; +} + + +//***************************************************************************** +// PRIVATE METHOD: ossimAtbController::initializeRemappers() +// +//***************************************************************************** +void ossimAtbController::initializeRemappers() +{ + static const char MODULE[] = "ossimAtbController::initializeRemappers()"; + if (traceExec()) CLOG << "entering..." << endl; + + int num_images = getNumberOfInputs(); + + //*** + // Fetch the overall mosaic bounding rect: + //*** + ossimGridRemapSource* remapper = PTR_CAST(ossimGridRemapSource, + getInput(0)); + theBoundingRect = remapper->getBoundingRect(); + for (int src=1; src<num_images; src++) + { + theBoundingRect = theBoundingRect.combine(remapper->getBoundingRect()); + } + + //*** + // Loop over each contribution image source chain to fetch each image + // bounding rect: + //*** + double dx_ul, dy_ul, dx_lr, dy_lr; + double grid_ul_x, grid_ul_y, grid_lr_x, grid_lr_y; + for (int src=0; src<num_images; src++) + { + remapper = PTR_CAST(ossimGridRemapSource, getInput(src)); + ossimDrect image_rect (remapper->getBoundingRect()); + + //*** + // Arrive at the number of grid posts from mosaic origin to image's grid + // UL and LR corners: + //*** + dx_ul = (image_rect.ul().x - theBoundingRect.ul().x)/theGridSpacing.x; + dy_ul = (image_rect.ul().y - theBoundingRect.ul().y)/theGridSpacing.y; + dx_lr = (image_rect.lr().x - theBoundingRect.lr().x)/theGridSpacing.x; + dy_lr = (image_rect.lr().y - theBoundingRect.lr().y)/theGridSpacing.y; + + //*** + // Establish the view coordinates for the adjusted image grid: + //*** + grid_ul_x = theBoundingRect.ul().x + ceil(dx_ul)*theGridSpacing.x; + grid_ul_y = theBoundingRect.ul().y + ceil(dy_ul)*theGridSpacing.y; + grid_lr_x = theBoundingRect.lr().x + floor(dx_lr)*theGridSpacing.x; + grid_lr_y = theBoundingRect.lr().y + floor(dy_lr)*theGridSpacing.y; + + //*** + // Have the remapper initialize a new grid with the given rectangle and + // spacing: + //*** + ossimDrect grid_rect (grid_ul_x, grid_ul_y, grid_lr_x, grid_lr_y); + remapper->initialize(grid_rect, theGridSpacing); + } + + if (traceExec()) CLOG << "returning..." << endl; + return; +} + +//***************************************************************************** +// METHOD: ossimAtbController::setGridRemapEngine() +// +//***************************************************************************** +void ossimAtbController::setGridRemapEngine(ossimGridRemapEngine* engine) +{ + static const char MODULE[] = "ossimAtbController::setGridRemapEngine()"; + if (traceExec()) CLOG << "entering..." << endl; + + if (theGridRemapEngine) + delete theGridRemapEngine; + + theGridRemapEngine = engine; + + //*** + // Communicate the new engine to all member's interested: + //*** + ossimGridRemapSource* remapper; + vector<ossimConnectableObject*>::iterator iter=theInputObjectList.begin(); + while (iter != theInputObjectList.end()) + { + remapper = PTR_CAST(ossimGridRemapSource, *iter); + remapper->setRemapEngine(engine); + iter++; + } + + vector<ossimAtbMatchPoint*>::iterator match_point = theMatchPoints.begin(); + while (match_point != theMatchPoints.end()) + { + (*match_point)->setGridRemapEngine(engine); + match_point++; + } + + if (traceExec()) CLOG << "returning..." << endl; + return; +} + + +//***************************************************************************** +// METHOD: ossimAtbController::canConnectMyInputTo() +// +//***************************************************************************** +bool ossimAtbController::canConnectMyInputTo(ossim_int32 myInputIndex, + const ossimConnectableObject* object) const +{ + return (object&& PTR_CAST(ossimGridRemapSource, object)); +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimAtbController.h b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimAtbController.h new file mode 100644 index 0000000000..29fe9e829d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimAtbController.h @@ -0,0 +1,162 @@ +//***************************************************************************** +// FILE: ossimAtbController.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// AUTHOR: Oscar Kramer (okramer@imagelinks.com) +// +// DESCRIPTION: Contains declaration of class ossimAtbController. +// This is the class for the top-level object controlling the automated +// tonal balancing (ATB) function. The controller accepts a mosaic. +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimAtbController.h,v 1.6 2005/09/12 13:15:52 gpotts Exp $ + +#ifndef ossimAtbController_HEADER +#define ossimAtbController_HEADER + +#include "base/data_types/ossimIpt.h" +#include "base/data_types/ossimDrect.h" +#include "base/common/ossimConnectableObject.h" +#include "base/common/ossimProcessInterface.h" +#include <vector> + +class ossimImageCombiner; +class ossimKeywordlist; +class ossimAtbMatchPoint; +class ossimGridRemapSource; +class ossimGridRemapEngine; +class ossimConnectableContainer; + +/***************************************************************************** + * + * CLASS: ossimAtbController + * + *****************************************************************************/ +class ossimAtbController : + public ossimConnectableObject, + public ossimProcessInterface +{ +public: + /*! + * default Constructor initializes the member combiner pointer to NULL. + */ + ossimAtbController(); + + /*! + * Constructor with Combiner reference. This combiner is used for the ATB. + */ + ossimAtbController(ossimImageCombiner* combiner, + ossimGridRemapEngine* engine=0); + + /*! + * Constructor with a specified remap engine. + */ + ossimAtbController(ossimGridRemapEngine* engine); + + ~ossimAtbController(); + + virtual ossimObject* getObject() + { + return this; + } + virtual const ossimObject* getObject()const + { + return this; + } + /*! + * Provide alternate means of initialization in case default constructor + * used. + */ + void initializeWithCombiner(ossimImageCombiner* combiner, + ossimGridRemapEngine* engine=0); + + /*! + * Enable an image in the mosaic for the tonal balancing process + */ + bool enableImage (unsigned int index); + + /*! + * Disnable an image in the mosaic from the tonal balancing process + */ + bool disableImage(unsigned int index); + + /*! + * Locks a particular source for adjustment. A locked image + * effectively defines the target values for all overlapping imagery. + */ + bool lockImage (unsigned int index); + + /*! + * Unlock a particular source for adjustment. + */ + bool unlockImage (unsigned int index); + + /*! + * Implementation of ossimProcessInterface pure virtual method. + */ + virtual bool execute(); + virtual void abort(); + + /*! + * Hook to set the size of the kernel used by all point sources in computing + * their mean pixel value. The kernels will be resized to NxN. + */ + void setKernelSize(int side_size); + + /*! + * Sets the grid spacing used in gridding the mosaic's bounding rectangle. + */ + void setGridSpacing(const ossimIpt& spacing); + + /*! + * Sets the ATB remap engine. This object implements the specific tonal + * balancing algorithm. The dependency on number of bands and color space, + * is limited only to this engine. This facilitates the implementation of + * various grid-based image matching schemes. + */ + void setGridRemapEngine(ossimGridRemapEngine* engine); + + /*! + * Implementations of ossimStateInterface pure virtuals + */ + virtual bool saveState(ossimKeywordlist& kwl) const; + virtual bool loadState(const ossimKeywordlist& kwl); + + /*! + * Implementation of ossimConnectableObject pure virtual. + */ + virtual bool canConnectMyInputTo(ossim_int32 myInputIndex, + const ossimConnectableObject* object)const; + + +protected: + void initializeRemappers(); + + ossimDrect theBoundingRect; + ossimConnectableContainer* theContainer; + ossimGridRemapEngine* theGridRemapEngine; + vector<ossimAtbMatchPoint*> theMatchPoints; + ossimIpt theGridSpacing; + + TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimAtbMatchPoint.cpp b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimAtbMatchPoint.cpp new file mode 100644 index 0000000000..c4bc9e21df --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimAtbMatchPoint.cpp @@ -0,0 +1,169 @@ +//***************************************************************************** +// FILE: ossimAtbMatchPoint.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// AUTHOR: Oscar Kramer (okramer@imagelinks.com) +// +// DESCRIPTION: Contains implementation of class +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimAtbMatchPoint.cpp,v 1.3 2001/12/14 19:45:57 okramer Exp $ + +#include "ossimAtbMatchPoint.h" +#include "ossimAtbPointSource.h" +#include "ossimGridRemapEngine.h" +#include "ossimGridRemapSource.h" + +//*** +// Define Trace flags for use within this file: +//*** +#include "base/common/ossimTrace.h" +static ossimTrace traceExec ("ossimAtbMatchPoint:exec"); +static ossimTrace traceDebug ("ossimAtbMatchPoint:debug"); + +//***************************************************************************** +// DESTRUCTOR: ~ossimAtbMatchPoint() +// +// Need to delete each instance of an ossimAtbPointSource in thePointSourceList +// +//***************************************************************************** +ossimAtbMatchPoint::~ossimAtbMatchPoint() +{ + vector<ossimAtbPointSource*>::iterator source = thePointSourceList.begin(); + while (source != thePointSourceList.end()) + { + delete *source; + source++; + } +} + +//***************************************************************************** +// METHOD: ossimAtbMatchPoint::addImage() +// +// Adds a new contribution to the sample set. +// +//***************************************************************************** +void ossimAtbMatchPoint::addImage(ossimGridRemapSource* remapper) +{ + static const char MODULE[] = "ossimAtbMatchPoint::addImage()"; + if (traceExec()) CLOG << "entering..." << endl; + + //*** + // Assure that this image contains the view point corresponding to this + // matchpoint: + //*** + if (!remapper->getBoundingRect().pointWithin(theViewPoint)) + { + if (traceExec()) CLOG << "returning..." << endl; + return; + } + + //*** + // Instantiate a point source for this image at this view point and + // save it in the list: + //*** + ossimAtbPointSource* point_source = new ossimAtbPointSource(remapper, + theViewPoint); + thePointSourceList.push_back(point_source); + + if (traceExec()) CLOG << "returning..." << endl; + return; +} + + +//***************************************************************************** +// METHOD: ossimAtbMatchPoint::assignRemapValues() +// +// The target parameter value computed given all contributions. The target +// value is then used to establish the remap parameters for each image at this +// points location. +// +//***************************************************************************** +bool ossimAtbMatchPoint::assignRemapValues() +{ + static const char MODULE[] = "ossimAtbMatchPoint::assignRemapValues()"; + if (traceExec()) CLOG << "entering..." << endl; + + //*** + // Determine the number of contributors. We require minimum of two: + //*** + int num_contributors = thePointSourceList.size(); + if (num_contributors < 2) + return false; + + //*** + // Hand off the computation of the target pixel to the ATB engine being + // used. The engine implements the methods for computing targets, as these + // will vary according to algorithm being used: + //*** + theGridRemapEngine->assignRemapValues(thePointSourceList); + + if (traceExec()) CLOG << "returning..." << endl; + return true; +} + + +//***************************************************************************** +// METHOD: ossimAtbMatchPoint::setKernelSize(N) +// +// Hook to set the size of the kernel used by all point sources in computing +// their mean pixel value. The kernels will be resized to NxN. +// +//***************************************************************************** +void ossimAtbMatchPoint::setKernelSize(int side_size) +{ + static const char MODULE[] = "ossimAtbController::setKernelSize(N)"; + if (traceExec()) CLOG << "entering..." << endl; + + vector<ossimAtbPointSource*>::iterator psi = thePointSourceList.begin(); + while (psi != thePointSourceList.end()) + (*psi)->setKernelSize(side_size); + + if (traceExec()) CLOG << "returning..." << endl; + return; +} + + +//***************************************************************************** +// METHOD: ossimAtbMatchPoint::setAtbRemapEngine +// +//***************************************************************************** +void ossimAtbMatchPoint::setGridRemapEngine(ossimGridRemapEngine* engine) +{ + static const char MODULE[] = "ossimAtbMatchPoint::setAtbRemapEngine"; + if (traceExec()) CLOG << "entering..." << endl; + + theGridRemapEngine = engine; + + //*** + // Need to communicate this change of engine to the point sources that use + // it to arrive at a "source value": + //*** + vector<ossimAtbPointSource*>::iterator source = thePointSourceList.begin(); + while (source != thePointSourceList.end()) + { + (*source)->setGridRemapEngine(engine); + source++; + } + + if (traceExec()) CLOG << "returning..." << endl; + return; +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimAtbMatchPoint.h b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimAtbMatchPoint.h new file mode 100644 index 0000000000..7a987218ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimAtbMatchPoint.h @@ -0,0 +1,104 @@ +//***************************************************************************** +// FILE: ossimAtbMatchPoint.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// AUTHOR: Oscar Kramer (okramer@imagelinks.com) +// +// DESCRIPTION: Contains declaration of class ossimAtbMatchPoint. This class +// is used by the automated tonal balancing code for bookkeeping and +// statistics associated with match-points. Match points are points shared in +// common between two or more images being adjusted. +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimAtbMatchPoint.h,v 1.4 2001/12/14 20:16:25 okramer Exp $ + +#ifndef ossimAtbMatchPoint_HEADER +#define ossimAtbMatchPoint_HEADER + +#include "base/data_types/ossimDpt.h" +#include <vector> +using namespace std; + +class ossimAtbPointSource; +class ossimGridRemapEngine; +class ossimGridRemapSource; + +/*!**************************************************************************** + * + * CLASS: ossimAtbMatchPoint + * + *****************************************************************************/ +class ossimAtbMatchPoint +{ +public: + ossimAtbMatchPoint() + : theGridRemapEngine(0) {} + + ossimAtbMatchPoint(const ossimDpt& view_point, + ossimGridRemapEngine* engine) + : theViewPoint(view_point), theGridRemapEngine(engine) {} + + ~ossimAtbMatchPoint(); + + /*! + * Returns the point in view coordinates associated with this object. + */ + const ossimDpt& viewPoint() const { return theViewPoint; } + + /*! + * Adds a new contribution to the sample set. + */ + void addImage(ossimGridRemapSource* image_source); + + /*! + * The target parameter value computed given all contributions. Returns true + * if a valid quantity is returned. + */ + bool assignRemapValues(); + + /*! + * Hook to set the size of the kernel used by all point sources in computing + * their mean pixel value. The kernels will be resized to NxN. + */ + void setKernelSize(int side_size); + + /*! + * Sets the ATB remap engine reference owned by the controller. This engine + * is the only object that understands how to compute remap parameters from + * pixel data. This permits easily modifying the ATB algorithm without + * the support classes such as this one. + */ + void setGridRemapEngine(ossimGridRemapEngine* engine); + + /*! + * Dumps the contents of the object to the stream in human readable format. + */ +// void print(ostream& os) const; + +// friend ostream& operator << (ostream& os); + +private: + ossimDpt theViewPoint; + vector<ossimAtbPointSource*> thePointSourceList; + ossimGridRemapEngine* theGridRemapEngine; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimAtbPointSource.cpp b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimAtbPointSource.cpp new file mode 100644 index 0000000000..147b3d5355 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimAtbPointSource.cpp @@ -0,0 +1,206 @@ +//***************************************************************************** +// FILE: ossimAtbPointSource.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// AUTHOR: Oscar Kramer (okramer@imagelinks.com) +// +// DESCRIPTION: Contains implementation of class ossimAtbPointSource. +// This object provides the statistics associated with a given point on a +// given image corresponding to a matchpoint. A matchpoint contains a +// collection of these point sources, one for each contributing image. +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimAtbPointSource.cpp,v 1.5 2005/02/11 15:07:34 dburken Exp $ + +#include "imaging/ossimImageSource.h" +#include "imaging/ossimImageData.h" +#include "imaging/factory/ossimImageDataFactory.h" +#include "ossimGridRemapSource.h" +#include "ossimGridRemapEngine.h" +#include "ossimAtbPointSource.h" + +//*** +// Define Trace flags for use within this file: +//*** +#include "base/common/ossimTrace.h" +static ossimTrace traceExec ("ossimImageSource:exec"); +static ossimTrace traceDebug ("ossimImageSource:debug"); + +static const int DEFAULT_KERNEL_SIZE = 18; // recommend odd number + +//***************************************************************************** +// DEFAULT CONSTRUCTOR: ossimAtbPointSource +// +//***************************************************************************** +ossimAtbPointSource::ossimAtbPointSource() + : theRemapSource (0), + theGridRemapEngine (0), + theKernelSize (DEFAULT_KERNEL_SIZE), + theViewPointIsValid (false) +{ + static const char MODULE[] = "ossimAtbPointSource Default Constructor"; + if (traceExec()) CLOG << "entering..." << endl; + + if (traceExec()) CLOG << "returning..." << endl; +} + + +//***************************************************************************** +// CONSTRUCTOR: ossimAtbPointSource(image_source) +// +//***************************************************************************** +ossimAtbPointSource::ossimAtbPointSource(ossimGridRemapSource* source, + const ossimDpt& view_point) + : theRemapSource (source), + theGridRemapEngine (source->getRemapEngine()), + theKernelSize (DEFAULT_KERNEL_SIZE), + theViewPointIsValid (false) +{ + static const char MODULE[] = "ossimAtbPointSource Default Constructor"; + if (traceExec()) CLOG << "entering..." << endl; + + setViewPoint(view_point); + + if (traceExec()) CLOG << "returning..." << endl; +} + + +//***************************************************************************** +// DESTRUCTOR: ~ossimAtbPointSource() +// +//***************************************************************************** +ossimAtbPointSource::~ossimAtbPointSource() +{ +} + +//***************************************************************************** +// METHOD: ossimAtbPointSource::setRemapSource() +// +// Sets the pointer to the source of pixels used to compute the stats. +// +//***************************************************************************** +void ossimAtbPointSource::setRemapSource(ossimGridRemapSource* source) +{ + static const char MODULE[] = "ossimAtbPointSource::setRemapSource()"; + if (traceExec()) CLOG << "entering..." << endl; + + theRemapSource = source; + + //*** + // Also fetch the remap engine which should be a derived ossimAtbRemapEngine: + //*** + theGridRemapEngine = theRemapSource->getRemapEngine(); + + if (traceExec()) CLOG << "returning..." << endl; + return; +} + + +//***************************************************************************** +// METHOD: ossimAtbPointSource::setViewPoint() +// +// Sets the view coordinates corresponding to this point. +// +//***************************************************************************** +void ossimAtbPointSource::setViewPoint(const ossimDpt& view_point) +{ + static const char MODULE[] = "ossimAtbPointSource::setViewPoint()"; + if (traceExec()) CLOG << "entering..." << endl; + + theViewPoint = view_point; + + if ((theRemapSource) && + (theRemapSource->getBoundingRect().pointWithin(theViewPoint))) + theViewPointIsValid = true; + else + theViewPointIsValid = false; + + if (traceExec()) CLOG << "returning..." << endl; + return; +} + + +//***************************************************************************** +// METHOD: ossimAtbPointSource::getSourceValue() +// +// Returns the computed value vector corresponding to the region about the +// view point. The definition of "value" is implemented by theGridRemapEngine. +// +//***************************************************************************** +void ossimAtbPointSource::getSourceValue(void* value_vector) +{ + static const char MODULE[] = "ossimAtbPointSource::getSourceValue()"; + if (traceExec()) CLOG << "entering..." << endl; + + //*** + // Verify that members are initialized before processing: + //*** + if ((!theViewPointIsValid) || (!theRemapSource) || (!theGridRemapEngine)) + { + CLOG <<"ERROR: This object was not properly initialized before attempting" + <<" to compute target value! Returning usassigned vector..."<<endl; + return; + } + + //*** + // Extract the data kernel from the image chain: + //*** + ossimIpt kernel_2d_size (theKernelSize, theKernelSize); + ossimIpt kernel_ul (theViewPoint - kernel_2d_size/2.0); + ossimIpt kernel_lr (kernel_ul.x + kernel_2d_size.x - 1, + kernel_ul.y + kernel_2d_size.y - 1); + ossimIrect kernel_rect (kernel_ul, kernel_lr); + ossimRefPtr<ossimImageData> kernel_data = + theRemapSource->getTile(kernel_rect); + + //*** + // Fetch the value of the data kernel. Note: this is not necessarily in + // the same color space as the pixels. It depends on which engine is being + // utilized: + //*** + theGridRemapEngine->computeSourceValue(kernel_data, value_vector); + +// delete kernel_data; + + if (traceExec()) CLOG << "returning..." << endl; + return; +} + + +//***************************************************************************** +// METHOD: ossimAtbPointSource:: setKernelSize(N) +// +// Method to set the kernel size used in computing statistics. The kernel +// will be resized to NxN. +// +//***************************************************************************** +void ossimAtbPointSource::setKernelSize(int side_size) +{ + static const char MODULE[] = "ossimAtbPointSource::setKernelSize()"; + if (traceExec()) CLOG << "entering..." << endl; + + theKernelSize = side_size; + + if (traceExec()) CLOG << "returning..." << endl; + return; +} + + diff --git a/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimAtbPointSource.h b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimAtbPointSource.h new file mode 100644 index 0000000000..f79d1fce9b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimAtbPointSource.h @@ -0,0 +1,108 @@ +//***************************************************************************** +// FILE: ossimAtbPointSource.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// AUTHOR: Oscar Kramer (okramer@imagelinks.com) +// +// DESCRIPTION: Contains declaration of class ossimAtbPointSource. +// This object provides the statistics associated with a given point on a +// given image corresponding to a matchpoint. A matchpoint contains a +// collection of these point sources, one for each contributing image. +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimAtbPointSource.h,v 1.2 2001/12/14 20:10:39 okramer Exp $ + +#ifndef ossimAtbPointSource_HEADER +#define ossimAtbPointSource_HEADER + +#include "base/data_types/ossimDpt.h" + +class ossimImageSource; +class ossimImageData; +class ossimGridRemapSource; +class ossimGridRemapEngine; + +/*!**************************************************************************** + * + * CLASS: ossimAtbPointSource + * + *****************************************************************************/ +class ossimAtbPointSource +{ +public: + ossimAtbPointSource(); + ossimAtbPointSource(ossimGridRemapSource* remap_source, + const ossimDpt& view_point); + + ~ossimAtbPointSource(); + + /*! + * Sets the pointer of the source of pixels used to compute the stats. + */ + void setRemapSource(ossimGridRemapSource* image_source); + + /*! + * Returns the reference to the remapper feeding this source. + */ + ossimGridRemapSource* getRemapSource() { return theRemapSource; } + + /*! + * Sets the view coordinates corresponding to this point. + */ + void setViewPoint(const ossimDpt& view_point); + + /*! + * Returns the view point corresponding to this point source. + */ + const ossimDpt& getViewPoint() const { return theViewPoint; } + + /*! + * Returns the computed value vector corresponding to the region about the + * view point. The ATB Remap engine performs the actual computation, since + * the definition of "value" is algorithm dependent (the value may be in a + * different color space). + */ + void getSourceValue(void* value); + + /*! + * Method to set the kernel size used in computing statistics. The kernel + * will be resized to NxN. + */ + void setKernelSize(int side_size); + + /*! + * Sets the ATB remap engine reference owned by the controller. This engine + * is the only object that understands how to compute remap parameters from + * pixel data. This permits easily modifying the ATB algorithm without + * the support classes such as this one. + */ + void setGridRemapEngine(ossimGridRemapEngine* engine) + { theGridRemapEngine = engine; } + +private: + ossimGridRemapSource* theRemapSource; + ossimDpt theViewPoint; + ossimGridRemapEngine* theGridRemapEngine; + int theKernelSize; + bool theViewPointIsValid; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimGridRemapEngine.cpp b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimGridRemapEngine.cpp new file mode 100644 index 0000000000..37c646d179 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimGridRemapEngine.cpp @@ -0,0 +1,32 @@ +//***************************************************************************** +// FILE: ossimGridRemapEngine.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// AUTHOR: Oscar Kramer (okramer@imagelinks.com) +// +// DESCRIPTION: Contains declaration of class +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimGridRemapEngine.cpp,v 1.1 2001/12/03 21:52:09 gpotts Exp $ + +#include "ossimGridRemapEngine.h" + +RTTI_DEF1(ossimGridRemapEngine, "ossimGridRemapEngine", ossimObject); diff --git a/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimGridRemapEngine.h b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimGridRemapEngine.h new file mode 100644 index 0000000000..dffba663b5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimGridRemapEngine.h @@ -0,0 +1,69 @@ +//***************************************************************************** +// FILE: ossimGridRemapEngine.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// AUTHOR: Oscar Kramer +// +// DESCRIPTION: Contains declaration of class +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimGridRemapEngine.h,v 1.5 2005/10/17 18:42:27 gpotts Exp $ + +#ifndef ossimGridRemapEngine_HEADER +#define ossimGridRemapEngine_HEADER + +#include <vector> +#include <base/common/ossimObject.h> +#include <base/common/ossimRefPtr.h> + +class ossimDpt; +class ossimGridRemapSource; +class ossimImageData; +class ossimAtbPointSource; + +/*!**************************************************************************** + * + * CLASS: ossimGridRemapEngine + * + *****************************************************************************/ +class ossimGridRemapEngine : public ossimObject +{ +public: + virtual ossimObject* dup() const = 0; + + virtual void remapTile(const ossimDpt& origin_point, + ossimGridRemapSource* remapper, + ossimRefPtr<ossimImageData>& tile) = 0; + + virtual void assignRemapValues(std::vector<ossimAtbPointSource*>& sources)=0; + + virtual void computeSourceValue(ossimRefPtr<ossimImageData>& source, + void* result) = 0; + + int getNumberOfParams() const { return theNumberOfParams; } + + int getNumberOfBands() const { return theNumberOfBands; } + +protected: + ossimGridRemapEngine(int numParams, int numBands) + : theNumberOfParams(numParams), theNumberOfBands(numBands) {} + + ossimGridRemapEngine() {} + + virtual void computeRemapNode(ossimAtbPointSource* point_source, + void* source_value, + void* target_value) = 0; + int theNumberOfParams; + int theNumberOfBands; + + TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimGridRemapEngineFactory.cpp b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimGridRemapEngineFactory.cpp new file mode 100644 index 0000000000..0c772cb000 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimGridRemapEngineFactory.cpp @@ -0,0 +1,44 @@ +//***************************************************************************** +// FILE: ossimGridRemapEngineFactory.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// AUTHOR: Oscar Kramer +// +// DESCRIPTION: Contains implementation of class ossimGridRemapEngineFactory +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimGridRemapEngineFactory.cpp,v 1.2 2005/02/11 15:07:35 dburken Exp $ + +#include <imaging/tonal_balance/ossimGridRemapEngineFactory.h> +#include <imaging/tonal_balance/ossimHsvGridRemapEngine.h> +#include <imaging/tonal_balance/ossimRgbGridRemapEngine.h> +#include <imaging/tonal_balance/ossimMonoGridRemapEngine.h> + +//***************************************************************************** +// STATIC METHOD: ossimGridRemapEngineFactory::create() +// +//***************************************************************************** +ossimGridRemapEngine* ossimGridRemapEngineFactory::create(const char* s) +{ + if (!s) + return 0; + + if (strcmp(s, "ossimHsvGridRemapEngine") == 0) + return new ossimHsvGridRemapEngine; + + else if (strcmp(s, "ossimRgbGridRemapEngine") == 0) + return new ossimRgbGridRemapEngine; + + else if (strcmp(s, "ossimMonoGridRemapEngine") == 0) + return new ossimMonoGridRemapEngine; + + return 0; +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimGridRemapEngineFactory.h b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimGridRemapEngineFactory.h new file mode 100644 index 0000000000..d987b09194 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimGridRemapEngineFactory.h @@ -0,0 +1,53 @@ +//***************************************************************************** +// FILE: ossimGridRemapEngineFactory.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// AUTHOR: Oscar Kramer (okramer@imagelinks.com) +// +// DESCRIPTION: Contains declaration of class ossimGridRemapEngineFactory +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimGridRemapEngineFactory.h,v 1.2 2001/12/05 00:04:31 okramer Exp $ + +#ifndef ossimGridRemapEngineFactory_HEADER +#define ossimGridRemapEngineFactory_HEADER + +class ossimGridRemapEngine; + +/*!**************************************************************************** + * + * CLASS: ossimGridRemapEngineFactory (SIMPLETON) + * + *****************************************************************************/ +class ossimGridRemapEngineFactory +{ +public: + /*! + * Attempts to create an instance of the Product given a Specifier. Returns + * successfully constructed product or NULL. + */ + static ossimGridRemapEngine* create(const char* spec); + +protected: + ossimGridRemapEngineFactory() {} +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimGridRemapSource.cpp b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimGridRemapSource.cpp new file mode 100644 index 0000000000..39d271b53d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimGridRemapSource.cpp @@ -0,0 +1,368 @@ +//***************************************************************************** +// FILE: ossimGridRemapper.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// AUTHOR: Oscar Kramer +// +// DESCRIPTION: Contains implementation of class ossimGridRemapper. This is +// a spacially variant remapper that utilizes a grid for interpolating the +// remap value given an image x, y. +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimGridRemapSource.cpp,v 1.10 2005/09/09 19:23:58 gpotts Exp $ + +#include "ossimGridRemapSource.h" + +RTTI_DEF1(ossimGridRemapSource, "ossimGridRemapSource", ossimImageSourceFilter); + +#include <stdio.h> +#include <fstream> +#include "imaging/ossimImageData.h" +#include "base/data_types/ossimDrect.h" +#include "base/data_types/ossimDpt.h" +#include "base/data_types/ossimDblGrid.h" +#include "base/data_types/ossimKeywordlist.h" +#include "ossimGridRemapEngineFactory.h" + +//*** +// Define Trace flags for use within this file: +//*** +#include "base/common/ossimTrace.h" +static ossimTrace traceExec ("ossimGridRemapSource:exec"); +static ossimTrace traceDebug ("ossimGridRemapSource:debug"); + +static const char* GRID_FILENAME_KW = "grid_remap_file"; +static const char* REMAP_ENGINE_KW = "remap_engine"; + +//***************************************************************************** +// DEFAULT CONSTRUCTOR #1: ossimGridRemapper() +// +//***************************************************************************** +ossimGridRemapSource::ossimGridRemapSource() + : + ossimImageSourceFilter(), + theGridFilename (0), + theRemapEngine (0), + theRemapIsLockedFlag(true), + theGridIsFilled(false) +{ + disableSource(); +} + +//***************************************************************************** +// CONSTRUCTOR #2: ossimGridRemapper(inputSource) +// +//***************************************************************************** +ossimGridRemapSource::ossimGridRemapSource(ossimImageSource* inputSource, + ossimGridRemapEngine* engine) + : + ossimImageSourceFilter(inputSource), + theGridFilename (0), + theRemapEngine ((ossimGridRemapEngine*)engine->dup()), + theRemapIsLockedFlag(true), + theGridIsFilled(false) +{ + disableSource(); +} + +//***************************************************************************** +// DESTRUCTOR: ~ossimGridRemapSource +// +//***************************************************************************** +ossimGridRemapSource::~ossimGridRemapSource() +{ + deallocateGrids(); + delete theRemapEngine; +} + +//***************************************************************************** +// METHOD: ossimGridRemapSource::initialize +// +//***************************************************************************** +void ossimGridRemapSource::initialize(const ossimDrect& uv_rect, + const ossimDpt& grid_spacing) +{ + deallocateGrids(); + int num_params; + + if (theRemapEngine) + { + num_params = theRemapEngine->getNumberOfParams(); + + for (int p=0; p<num_params; p++) + { + ossimDblGrid* grid = new ossimDblGrid(uv_rect, grid_spacing); + theGrids.push_back(grid); + } + + theGridFilename = ossimFilename(ossimString("ogrs") + + ossimString::toString((int)this) + + ossimString(".org")); + + theGridIsFilled = false; + } +} + +//***************************************************************************** +// METHOD: ossimGridRemapSource::getTile() +// +// Implementation of virtual method to return remapped tile. +// +//***************************************************************************** +ossimRefPtr<ossimImageData> ossimGridRemapSource::getTile( + const ossimIrect& rect, ossim_uint32 resLevel) +{ + if(!theInputConnection) + return NULL; + + //*** + // Fetch tile from input source: + //*** + ossimRefPtr<ossimImageData> tile = theInputConnection->getTile(rect, + resLevel); + + //--- + // Bypass this filter if it is not initialized, or if input tile is bogus: + //--- + if ((!isSourceEnabled()) || (!tile.valid()) || (!theRemapEngine) || + (tile->getDataObjectStatus()==OSSIM_NULL) || + (tile->getDataObjectStatus()==OSSIM_EMPTY)) + { + return tile; + } + + //*** + // Insure that the grid has been filled in case nodes were being randomly set + //*** + if (!theGridIsFilled) + { + vector<ossimDblGrid*>::iterator grid = theGrids.begin(); + while (grid != theGrids.end()) + { +// (*grid)->setInterpolationType(ossimDblGrid::BILINEAR); + (*grid)->interpolateNullValuedNodes(); + grid++; + } + theGridIsFilled = true; + } + + //*** + // hand off the actual remap to the ATB engine. This object knows how to + // interpret the grids for the particular remap algorithm selected: + //*** + theRemapEngine->remapTile(rect.ul(), this, tile); + + tile->validate(); + return tile; +} + +//***************************************************************************** +// METHOD: ossimGridRemapSource::loadState() +// +//***************************************************************************** +bool ossimGridRemapSource::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + static const char MODULE[] = "ossimGridRemapSource::loadState()"; + if (traceExec()) CLOG << "entering..." << endl; + + bool successful = false; + const char* value; + + //*** + // Reset object in preparation for reassignment: + //*** + deallocateGrids(); + delete theRemapEngine; + + //*** + // Read the remap engine type: + //*** + value = kwl.find(prefix, REMAP_ENGINE_KW); + theRemapEngine = ossimGridRemapEngineFactory::create(value); + if (!theRemapEngine) + { +// CLOG << "ERROR: could not instantiate remap engine. Aborting..." << endl; +// if (traceExec()) CLOG << "returning..." << endl; +// return false; + } + + //*** + // Read the grid filename and open input stream: + //*** + theGridIsFilled = false; + value = kwl.find(prefix, GRID_FILENAME_KW); + if (value) + { + theGridFilename = value; + ifstream is (theGridFilename.chars()); + + //*** + // Create an input stream from the grid file to pass to the + // corresponding grid: + //*** + int num_grids = theRemapEngine->getNumberOfParams(); + for (int i=0; (i<num_grids) && successful; i++) + { + ossimDblGrid* grid = new ossimDblGrid; + successful = grid->load(is); + if (successful) + theGrids.push_back(grid); + } + if (!successful) + { + CLOG << "ERROR: Encountered errorloading remap grids at file: " + << theGridFilename << ". Remapper disabled." << endl; + if (traceExec()) CLOG << "returning..." << endl; + return false; + } + theGridIsFilled = true; + } + + //*** + // Allow base class to parse list: + //*** + bool rtn_stat = ossimImageSourceFilter::loadState(kwl, prefix); + + //*** + // Enable source only if KWL read was successful: + //*** + if (theRemapEngine && successful && rtn_stat) + enableSource(); + + if (traceExec()) CLOG << "returning..." << endl; + return rtn_stat; +} + +//***************************************************************************** +// METHOD: ossimGridRemapSource::saveState() +// +//***************************************************************************** +bool ossimGridRemapSource::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + static const char MODULE[] = "ossimGridRemapSource::saveState()"; + + //*** + // No filename indicates that this remapper has not been initialized: + //*** + if (!theGridFilename) + return false; + + //*** + // Write the remap engine type: + //*** + if (theRemapEngine) + kwl.add(prefix, REMAP_ENGINE_KW, theRemapEngine->getClassName()); + + //*** + // Write the filename to the KWL: + //*** + if (!theGridFilename.empty()) + { + kwl.add(prefix, GRID_FILENAME_KW, theGridFilename); + + //*** + // Loop over each remap component to write out the grid: + //*** + ofstream os (theGridFilename); + bool successful = true; + int num_components = theRemapEngine->getNumberOfParams(); + for (int p=0; (p<num_components)&&successful; p++) + successful = theGrids[p]->save(os, "Remap-Grid"); + + if (!successful) + { + CLOG << "ERROR: Encountered saving remap grids to file: " + << theGridFilename << ". State not properly saved." + << endl; + return false; + } + } + + return ossimImageSourceFilter::saveState(kwl, prefix); +} + +//***************************************************************************** +// METHOD: ossimGridRemapSource::setGridNode() +// +// Sets a node of the member grid to the value specified. +// +//***************************************************************************** +void ossimGridRemapSource::setGridNode(const ossimDpt& view_pt, + const double* value) +{ + int numGrids = theGrids.size(); + for (int i=0; i<numGrids; i++) + theGrids[i]->setNearestNode(view_pt, value[i]); + + theGridIsFilled = false; + + return; +} + +//***************************************************************************** +// METHOD: ossimGridRemapSource::getGrid() +// +//***************************************************************************** +ossimDblGrid* ossimGridRemapSource::getGrid(unsigned int index) +{ + if (index >= theGrids.size()) + return 0; + + return theGrids[index]; +} + +//***************************************************************************** +// METHOD: ossimGridRemapSource::deallocateGrids() +// +//***************************************************************************** +void ossimGridRemapSource::deallocateGrids() +{ + static const char MODULE[] = "ossimGridRemapSource::deallocateMemory()"; + if (traceExec()) CLOG << "entering..." << endl; + + vector<ossimDblGrid*>::iterator grid = theGrids.begin(); + while (grid != theGrids.end()) + { + delete *grid; + grid++; + } + theGrids.clear(); + + if (traceExec()) CLOG << "returning..." << endl; + return; +} + + +//***************************************************************************** +// METHOD: ossimGridRemapSource::setRemapEngine() +// +//***************************************************************************** +void ossimGridRemapSource::setRemapEngine(ossimGridRemapEngine* engine) +{ + if (theRemapEngine) + delete theRemapEngine; + + theRemapEngine = (ossimGridRemapEngine*)engine->dup(); + theGridIsFilled = false; +} + +//***************************************************************************** +// METHOD: ossimGridRemapSource::setGridFilename() +// +//***************************************************************************** +void ossimGridRemapSource::setGridFilename(const ossimFilename& grid_filename) +{ + theGridFilename = grid_filename; + //*** + // NOT COMPLETE### + //*** +} diff --git a/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimGridRemapSource.h b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimGridRemapSource.h new file mode 100644 index 0000000000..e8eb8a6dc0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimGridRemapSource.h @@ -0,0 +1,144 @@ +//***************************************************************************** +// FILE: ossimGridRemapSource.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// AUTHOR: Oscar Kramer +// +// DESCRIPTION: Contains declaration of class ossimGridRemapSource. This is +// a spacially variant remapper that utilizes a grid for interpolating the +// remap value given an image x, y. +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimGridRemapSource.h,v 1.8 2005/02/11 15:07:35 dburken Exp $ + +#ifndef ossimGridRemapSource_HEADER +#define ossimGridRemapSource_HEADER + +#include "imaging/tile_sources/ossimImageSourceFilter.h" +#include <vector> +#include "ossimGridRemapEngine.h" +#include "base/data_types/ossimFilename.h" + +class ossimDblGrid; +class ossimDrect; +class ossimDpt; +class ossimImageData; + +/*!**************************************************************************** + * + * CLASS: ossimGridRemapSource + * + *****************************************************************************/ +class ossimGridRemapSource : public ossimImageSourceFilter +{ +public: + /*! + * Constructors: + */ + ossimGridRemapSource(); + ossimGridRemapSource(ossimImageSource* inputSource, + ossimGridRemapEngine* engine); + + virtual ~ossimGridRemapSource(); + + /*!ossimAtbPointSource + * Initializes the remap engine. This object implements specific algorithms + * for interpreting the grids owned by this remapper. It actually performs + * the remapping. + */ + void setRemapEngine(ossimGridRemapEngine* engine); + + /*! + * Provides access to the remap engine: + */ + ossimGridRemapEngine* getRemapEngine() { return theRemapEngine; } + + /*! + * Permits initializing the remap grid after construction. + */ + virtual void initialize(const ossimDrect& uv_rect, + const ossimDpt& grid_spacing); + + /*! + * Sets a node of the member grid to the value specified. The grid is flagged + * as unfilled. + */ + void setGridNode(const ossimDpt& view_pt, + const double* value); + + /*! + * Implementation of virtual method to return remapped tile. + */ + virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& origin, + ossim_uint32 resLevel=0); + + /*! + * Restore the state of the object from a keywordlist. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /*! + * Save the state of the object to a keywordlist. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Locks the image to prevent grid adjustment. The remapper continues to + * remap given the current grid (if enabled), but all target values computed + * are such that no change in the grids will occur in an adjsutment. If more + * than one overlapping image is locked, the target will may be influenced + * by all locked images, but the remap grids will not be updated. + */ + void lock() { theRemapIsLockedFlag = true; } + + /*! + * Unlocks the grids for adjustment. + */ + void unlock() { theRemapIsLockedFlag = false; } + + /*! + * Returns the status of the lock flag. + */ + bool isLocked() const { return theRemapIsLockedFlag; } + + /*! + * Provides access to individual grids (pointer) given an index. Null pointer + * returned if index out of range. + */ + ossimDblGrid* getGrid(unsigned int index); + + /*! + * Returns grid filename (may be empty) + */ + const ossimFilename& getGridFilename() const { return theGridFilename; } + + /*! + * Sets the grid filename and initiates read. + */ + void setGridFilename(const ossimFilename& grid_filename); + +protected: + /*! + * Deallocates grid memory. + */ + void deallocateGrids(); + + vector<ossimDblGrid*> theGrids; + ossimFilename theGridFilename; + ossimGridRemapEngine* theRemapEngine; + bool theRemapIsLockedFlag; + bool theGridIsFilled; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimHsvGridRemapEngine.cpp b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimHsvGridRemapEngine.cpp new file mode 100644 index 0000000000..9d2995772a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimHsvGridRemapEngine.cpp @@ -0,0 +1,276 @@ +//***************************************************************************** +// FILE: ossimHsvGridRemapEngine.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// AUTHOR: Oscar Kramer +// +// DESCRIPTION: Contains implementation of class +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimHsvGridRemapEngine.cpp,v 1.7 2005/09/09 19:23:58 gpotts Exp $ + +#include "ossimHsvGridRemapEngine.h" + +RTTI_DEF1(ossimHsvGridRemapEngine, "ossimHsvGridRemapEngine", + ossimGridRemapEngine); + +#include <imaging/tonal_balance/ossimGridRemapSource.h> +#include <imaging/tonal_balance/ossimAtbPointSource.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimDblGrid.h> +#include <imaging/ossimImageData.h> +#include <base/data_types/color_space/ossimRgbVector.h> +#include <base/data_types/color_space/ossimHsvVector.h> + +//*** +// Define Trace flags for use within this file: +//*** +#include <base/common/ossimTrace.h> +static ossimTrace traceExec ("ossimHsvGridRemapEngine:exec"); +static ossimTrace traceDebug ("ossimHsvGridRemapEngine:debug"); + +//***************************************************************************** +// METHOD: ossimHsvGridRemapEngine::remapTile +// +//***************************************************************************** +ossimObject* ossimHsvGridRemapEngine::dup() const +{ + return new ossimHsvGridRemapEngine; +} + +//***************************************************************************** +// METHOD: ossimHsvGridRemapEngine::remapTile +// +//***************************************************************************** +void ossimHsvGridRemapEngine::remapTile(const ossimDpt& origin, + ossimGridRemapSource* remapper, + ossimRefPtr<ossimImageData>& tile) +{ + static const char MODULE[] = "ossimHsvGridRemapEngine::remapTile"; + if (traceExec()) CLOG << "entering..." << endl; + + //*** + // Fetch tile size and NULL pixel value: + //*** + int width = tile->getWidth(); + int height = tile->getHeight(); + int offset = 0; + + void* red_buf = tile->getBuf(0); + void* grn_buf = tile->getBuf(1); + void* blu_buf = tile->getBuf(2); + + ossimDblGrid& gridH = *(remapper->getGrid(0)); + ossimDblGrid& gridS = *(remapper->getGrid(1)); + ossimDblGrid& gridV = *(remapper->getGrid(2)); + + //--- + // Remap according to pixel type: + //--- + switch(tile->getScalarType()) + { + case OSSIM_UINT8: + { + for (double line=origin.line; line<origin.line+height; line+=1.0) + { + for (double samp=origin.samp; samp<origin.samp+width; samp+=1.0) + { + //--- + // Fetch pixel from the input tile band buffers and convert + // to HSV: + //--- + ossimRgbVector rgb_pixel (((ossim_uint8*)red_buf)[offset], + ((ossim_uint8*)grn_buf)[offset], + ((ossim_uint8*)blu_buf)[offset]); + ossimHsvVector hsv_pixel (rgb_pixel); + + //--- + // Remap pixel HSV with spatially variant bias value: + //--- + hsv_pixel.setH(hsv_pixel.getH() + gridH(samp,line)); + hsv_pixel.setS(hsv_pixel.getS() + gridS(samp,line)); + hsv_pixel.setV(hsv_pixel.getV() + gridV(samp,line)); + + //--- + // Convert back to RGB and write to the tile: + //--- + rgb_pixel = hsv_pixel; // auto-clamped + ((ossim_uint8*)red_buf)[offset] = rgb_pixel.getR(); + ((ossim_uint8*)grn_buf)[offset] = rgb_pixel.getG(); + ((ossim_uint8*)blu_buf)[offset] = rgb_pixel.getB(); + + offset++; + } + } + break; + } + + case OSSIM_USHORT11: + break; + + case OSSIM_UINT16: + break; + + case OSSIM_SINT16: + break; + + case OSSIM_FLOAT64: + break; + + case OSSIM_NORMALIZED_DOUBLE: + break; + + case OSSIM_FLOAT32: + break; + + case OSSIM_NORMALIZED_FLOAT: + break; + + case OSSIM_SCALAR_UNKNOWN: + default: + break; + + } // end switch statement + + if (traceExec()) CLOG << "returning..." << endl; + return; +}; + +//***************************************************************************** +// METHOD: ossimHsvGridRemapEngine::assignRemapValues +// +// This engine defines the target value as an HSV vector of doubles, computed +// as the mean of all contributor HSV values. +// +//***************************************************************************** +void ossimHsvGridRemapEngine::assignRemapValues ( + vector<ossimAtbPointSource*>& sources_list) +{ + static const char MODULE[] = "ossimHsvGridRemapEngine::assignRemapValues"; + if (traceExec()) CLOG << "entering..." << endl; + + int i; // index to individual sources + + //*** + // Declare a 2D array that will contain all of the contributing sources' + // HSV mean values. Also declare the accumulator target vector. + //*** + int num_contributors = sources_list.size(); + double** contributor_pixel = new double* [num_contributors]; + for (i=0; i<num_contributors; i++) + contributor_pixel[i] = new double[3]; + double target_pixel[3] = {0.0, 0.0, 0.0}; + + //*** + // Now loop over each remaining contributor and sum in its contribution: + //*** + vector<ossimAtbPointSource*>::iterator source; + i = 0; + for(source = sources_list.begin(); + source != sources_list.end(); + source++) + { + (*source)->getSourceValue(contributor_pixel[i]); + + target_pixel[0] += contributor_pixel[i][0]/(double)num_contributors; + target_pixel[1] += contributor_pixel[i][1]/(double)num_contributors; + target_pixel[2] += contributor_pixel[i][2]/(double)num_contributors; + + i++; + } + + //*** + // The target pixel has been established. Now need to compute the actual + // remap quantities that will be written to the appropriate remap grids: + //*** + i = 0; + for(source = sources_list.begin(); + source != sources_list.end(); + source++) + { + computeRemapNode(*source, contributor_pixel[i], target_pixel); + i++; + } + + //*** + // Delete locally allocated memory: + //*** + for (i=0; i<num_contributors; i++) + delete [] contributor_pixel[i]; + delete [] contributor_pixel; + + if (traceExec()) CLOG << "returning..." << endl; + return; +} + +//***************************************************************************** +// METHOD: ossimHsvGridRemapEngine::computeSourceValue +// +//***************************************************************************** +void ossimHsvGridRemapEngine::computeSourceValue( + ossimRefPtr<ossimImageData>& source, void* result) +{ + static const char MODULE[]="ossimHsvGridRemapEngine::computeSourceValue"; + if (traceExec()) CLOG << "entering..." << endl; + + //*** + // This engine defines "value" as the HSV vector corresponding to the mean + // RGB pixel value of the source data: + //*** + ossimRgbVector rgb_vector; + rgb_vector.setR((unsigned char) source->computeAverageBandValue(0)); + rgb_vector.setG((unsigned char) source->computeAverageBandValue(1)); + rgb_vector.setB((unsigned char) source->computeAverageBandValue(2)); + + //*** + // Assign the HSV components to the result vector: + //*** + ossimHsvVector hsv_vector (rgb_vector); + ((double*)result)[0] = (double) hsv_vector.getH(); + ((double*)result)[1] = (double) hsv_vector.getS(); + ((double*)result)[2] = (double) hsv_vector.getV(); + + if (traceExec()) CLOG << "returning..." << endl; + return; +} + +//***************************************************************************** +// METHOD: ossimHsvGridRemapEngine::computeRemapNode +// +// This engine defines the remap value as the difference between the target +// HSV vector and the individual point source's value vector. +// +//***************************************************************************** +void ossimHsvGridRemapEngine::computeRemapNode(ossimAtbPointSource* ps, + void* source_value, + void* target_value) +{ + static const char MODULE[] = "ossimHsvGridRemapEngine::computeRemapNode"; + if (traceExec()) CLOG << "entering..." << endl; + + //*** + // Compute the remap grid node value specific to this HSV implementation: + //*** + double node[3]; + node[0] = ((double*)target_value)[0] - ((double*)source_value)[0]; + node[1] = ((double*)target_value)[1] - ((double*)source_value)[1]; + node[2] = ((double*)target_value)[2] - ((double*)source_value)[2]; + + //*** + // Fetch a pointer to the remapper feeding this point source in order to + // pass it the node value: + //*** + ossimGridRemapSource* remapper = ps->getRemapSource(); + remapper->setGridNode(ps->getViewPoint(), node); + + if (traceExec()) CLOG << "returning..." << endl; + return; +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimHsvGridRemapEngine.h b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimHsvGridRemapEngine.h new file mode 100644 index 0000000000..eb9b2311d3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimHsvGridRemapEngine.h @@ -0,0 +1,54 @@ +//***************************************************************************** +// FILE: ossimHsvGridRemapEngine.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// AUTHOR: Oscar Kramer +// +// DESCRIPTION: Contains declaration of class ossimHsvGridRemapEngine +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimHsvGridRemapEngine.h,v 1.5 2005/10/17 18:42:27 gpotts Exp $ + +#ifndef ossimHsvGridRemapEngine_HEADER +#define ossimHsvGridRemapEngine_HEADER + +#include <imaging/tonal_balance/ossimGridRemapEngine.h> + +/*!**************************************************************************** + * + * CLASS: ossimHsvGridRemapEngine + * + *****************************************************************************/ +class ossimHsvGridRemapEngine : public ossimGridRemapEngine +{ +public: + ossimHsvGridRemapEngine() + : ossimGridRemapEngine(3, 3) {} + + virtual ossimObject* dup() const; + + virtual void remapTile(const ossimDpt& origin_point, + ossimGridRemapSource* remapper, + ossimRefPtr<ossimImageData>& tile); + + virtual void assignRemapValues(std::vector<ossimAtbPointSource*>& sources); + + virtual void computeSourceValue(ossimRefPtr<ossimImageData>& source, + void* result); + +protected: + virtual void computeRemapNode(ossimAtbPointSource* point_source, + void* source_value, + void* target_value); + + TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimMonoGridRemapEngine.cpp b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimMonoGridRemapEngine.cpp new file mode 100644 index 0000000000..0d4729cffe --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimMonoGridRemapEngine.cpp @@ -0,0 +1,368 @@ +//***************************************************************************** +// FILE: ossimMonoGridRemapEngine.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// See the GPL in the COPYING.GPL file for more details. +// +// AUTHOR: Oscar Kramer +// +// DESCRIPTION: Contains implementation of class +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimMonoGridRemapEngine.cpp,v 1.8 2005/09/09 19:23:58 gpotts Exp $ + +#include <imaging/tonal_balance/ossimMonoGridRemapEngine.h> + +RTTI_DEF1(ossimMonoGridRemapEngine, "ossimMonoGridRemapEngine", + ossimGridRemapEngine); + +#include <imaging/tonal_balance/ossimGridRemapSource.h> +#include <imaging/tonal_balance/ossimAtbPointSource.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimDblGrid.h> +#include <imaging/ossimImageData.h> + +//*** +// Define Trace flags for use within this file: +//*** +#include <base/common/ossimTrace.h> +static ossimTrace traceExec ("ossimMonoGridRemapEngine:exec"); +static ossimTrace traceDebug ("ossimMonoGridRemapEngine:debug"); +static bool TRACE_FLAG = true; + +//***************************************************************************** +// METHOD: ossimMonoGridRemapEngine::dup +// +//***************************************************************************** +ossimObject* ossimMonoGridRemapEngine::dup() const +{ + return new ossimMonoGridRemapEngine; +} + +//***************************************************************************** +// METHOD: ossimMonoGridRemapEngine::remapTile +// +//***************************************************************************** +void ossimMonoGridRemapEngine::remapTile(const ossimDpt& origin, + ossimGridRemapSource* remapper, + ossimRefPtr<ossimImageData>& tile) +{ + static const char MODULE[] = "ossimMonoGridRemapEngine::remapTile"; + if (traceExec()) CLOG << "entering..." << endl; + + //*** + // Fetch tile size and NULL pixel value: + //*** + int width = tile->getWidth(); + int height = tile->getHeight(); + int offset = 0; + double null; + + //*** + // Determine null pixel values so that we can recognize a null coming in and + // not remap it: + //*** + null = tile->getNullPix(0); + ossimDblGrid& grid = *(remapper->getGrid(0)); + + //*** + // Remap according to pixel type: + //*** + switch(tile->getScalarType()) + { + case OSSIM_UCHAR: + { + ossim_uint8* tile_buf = (ossim_uint8*)tile->getBuf(0); + short pixel; + + for (double line=origin.line; line<origin.line+height; line+=1.0) + { + for (double samp=origin.samp; samp<origin.samp+width; samp+=1.0) + { + //*** + // Scan for null pixel before adding remap delta: + //*** + if (tile_buf[offset] != (ossim_uint8) null) + { + //*** + // Remap MONO pixel with spatially variant bias value: + //*** + pixel = tile_buf[offset] + (short) grid(samp,line); + + //*** + // Clamp: + //*** + if (pixel<0) tile_buf[offset] = 0; + else if (pixel>255) tile_buf[offset] = 255; + else tile_buf[offset] = pixel; + + //*** + // Avoid NULLS: + //*** + if (tile_buf[offset] == (ossim_uint8) null) tile_buf[offset]++; + } + + offset++; + } + } + break; + } + + case OSSIM_USHORT11: + { + ossim_uint16* tile_buf = (ossim_uint16*)tile->getBuf(0); + int pixel; + + for (double line=origin.line; line<origin.line+height; line+=1.0) + { + for (double samp=origin.samp; samp<origin.samp+width; samp+=1.0) + { + //*** + // Scan for null pixel before adding remap delta: + //*** + if (tile_buf[offset] != (ossim_uint16) null) + { + //*** + // Remap MONO pixel with spatially variant bias value: + //*** + pixel = tile_buf[offset] + (int) grid(samp,line); + + //*** + // Clamp: + //*** + if (pixel<0) tile_buf[offset] = 0; + else if (pixel>2047) tile_buf[offset] = 2047; + else tile_buf[offset] = pixel; + + //*** + // Avoid NULLS: + //*** + if (tile_buf[offset] == (ossim_uint16) null) tile_buf[offset]++; + } + + offset++; + } + } + break; + } + + case OSSIM_USHORT16: + { + ossim_uint16* tile_buf = (ossim_uint16*)tile->getBuf(0); + int pixel; + + for (double line=origin.line; line<origin.line+height; line+=1.0) + { + for (double samp=origin.samp; samp<origin.samp+width; samp+=1.0) + { + //*** + // Scan for null pixel before adding remap delta: + //*** + if (tile_buf[offset] != (ossim_uint16) null) + { + //*** + // Remap MONO pixel with spatially variant bias value: + //*** + pixel = tile_buf[offset] + (int) grid(samp,line); + + //*** + // Clamp: + //*** + if (pixel<0) tile_buf[offset] = 0; + else if (pixel>65535) tile_buf[offset] = 65535; + else tile_buf[offset] = pixel; + + //*** + // Avoid NULLS: + //*** + if (tile_buf[offset] == (ossim_uint16) null) tile_buf[offset]++; + } + + offset++; + } + } + break; + } + + case OSSIM_SSHORT16: + { + short* tile_buf = (short*)tile->getBuf(0); + int pixel; + + for (double line=origin.line; line<origin.line+height; line+=1.0) + { + for (double samp=origin.samp; samp<origin.samp+width; samp+=1.0) + { + //*** + // Scan for null pixel before adding remap delta: + //*** + if (tile_buf[offset] != (short) null) + { + //*** + // Remap MONO pixel with spatially variant bias value: + //*** + pixel = tile_buf[offset] + (short) grid(samp,line); + + //*** + // Clamp: + //*** + if (pixel<-32766) tile_buf[offset] = -32766; + else if (pixel> 32767) tile_buf[offset] = 32767; + else tile_buf[offset] = pixel; + + //*** + // Avoid NULLS: + //*** + if (tile_buf[offset] == (short) null) tile_buf[offset]++; + } + + offset++; + } + } + break; + } + default: + { + ossimNotify(ossimNotifyLevel_WARN) << "WARNING ossimMonoGridRemapEngine::remapTile: Scalar type not handled" << std::endl; + break; + } + + } // end switch statement + + if (traceExec()) CLOG << "returning..." << endl; + return; +}; + +//***************************************************************************** +// METHOD: ossimMonoGridRemapEngine::assignRemapValues +// +// This engine defines the target value as an MONO vector of doubles, computed +// as the mean of all contributor MONO values. +// +//***************************************************************************** +void ossimMonoGridRemapEngine::assignRemapValues ( + vector<ossimAtbPointSource*>& sources_list) +{ + static const char MODULE[] = "ossimMonoGridRemapEngine::assignRemapValues"; + if (traceExec()) CLOG << "entering..." << endl; + + int i; // index to individual sources + + //*** + // Declare a 2D array that will contain all of the contributing sources' + // MONO mean values. Also declare the accumulator target vector. + //*** + int num_contributors = sources_list.size(); + double** contributor_pixel = new double* [num_contributors]; + for (i=0; i<num_contributors; i++) + contributor_pixel[i] = new double[1]; + double target_pixel = 0.0; + + //*** + // Now loop over each remaining contributor and sum in its contribution: + //*** + vector<ossimAtbPointSource*>::iterator source; + i = 0; + for(source=sources_list.begin(); + source!=sources_list.end(); + source++) + { + (*source)->getSourceValue(contributor_pixel[i]); + target_pixel += contributor_pixel[i][0]/(double)num_contributors; + ++i; + } + + //*** + // The target pixel has been established. Now need to compute the actual + // remap quantities that will be written to the appropriate remap grids: + //*** + i = 0; + for(source=sources_list.begin(); + source!=sources_list.end(); + source++) + { + computeRemapNode(*source, contributor_pixel[i], &target_pixel); + ++i; + } + + // *** + // Delete locally allocated memory: + // *** + for (i=0; i<num_contributors; ++i) + { + delete [] contributor_pixel[i]; + } + delete [] contributor_pixel; + + if (traceExec()) CLOG << "returning..." << endl; + return; +} + +//***************************************************************************** +// METHOD: ossimMonoGridRemapEngine::computeSourceValue +// +//***************************************************************************** +void ossimMonoGridRemapEngine::computeSourceValue( + ossimRefPtr<ossimImageData>& source, void* result) +{ + static const char MODULE[]="ossimMonoGridRemapEngine::computeSourceValue"; + if (traceExec()) CLOG << "entering..." << endl; + + //*** + // This engine defines "value" as the MONO vector corresponding to the mean + // MONO pixel value of the source data: + //*** + ((double*)result)[0] = source->computeAverageBandValue(0); + + if (traceExec()) CLOG << "returning..." << endl; + return; +} + +//***************************************************************************** +// METHOD: ossimMonoGridRemapEngine::computeRemapNode +// +// This engine defines the remap value as the difference between the target +// MONO vector and the individual point source's value vector. +// +//***************************************************************************** +void ossimMonoGridRemapEngine::computeRemapNode(ossimAtbPointSource* ps, + void* source_value, + void* target_value) +{ + static const char MODULE[] = "ossimMonoGridRemapEngine::computeRemapNode"; + if (traceExec()) CLOG << "entering..." << endl; + + //*** + // Compute the remap grid node value specific to this MONO implementation: + //*** + double node; + node = ((double*)target_value)[0] - ((double*)source_value)[0]; + + //*** + // Fetch a pointer to the remapper feeding this point source in order to + // pass it the node value: + //*** + ossimGridRemapSource* remapper = ps->getRemapSource(); + remapper->setGridNode(ps->getViewPoint(), &node); + + if (traceDebug() || TRACE_FLAG) + { + CLOG << "DEBUG -- " + << "\n\t ps->getViewPoint() = "<<ps->getViewPoint() + << "\n\t source_value = "<<((double*)source_value)[0] + << "\n\t target_value = "<<((double*)target_value)[0] + << "\n\t node = "<<node + << "\n\t remapper at "<<remapper<<endl; + } + + if (traceExec()) CLOG << "returning..." << endl; + return; +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimMonoGridRemapEngine.h b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimMonoGridRemapEngine.h new file mode 100644 index 0000000000..273bfe856f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimMonoGridRemapEngine.h @@ -0,0 +1,54 @@ +//***************************************************************************** +// FILE: ossimMonoGridRemapEngine.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// AUTHOR: Oscar Kramer +// +// DESCRIPTION: Contains declaration of class ossimMonoGridRemapEngine +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimMonoGridRemapEngine.h,v 1.5 2005/10/17 18:42:27 gpotts Exp $ + +#ifndef ossimMonoGridRemapEngine_HEADER +#define ossimMonoGridRemapEngine_HEADER + +#include <imaging/tonal_balance/ossimGridRemapEngine.h> + +/*!**************************************************************************** + * + * CLASS: ossimMonoGridRemapEngine + * + *****************************************************************************/ +class ossimMonoGridRemapEngine : public ossimGridRemapEngine +{ +public: + ossimMonoGridRemapEngine() + : ossimGridRemapEngine(1, 1) {} + + virtual ossimObject* dup() const; + + virtual void remapTile(const ossimDpt& origin_point, + ossimGridRemapSource* remapper, + ossimRefPtr<ossimImageData>& tile); + + virtual void assignRemapValues(std::vector<ossimAtbPointSource*>& sources); + + virtual void computeSourceValue(ossimRefPtr<ossimImageData>& source, + void* result); + +protected: + virtual void computeRemapNode(ossimAtbPointSource* point_source, + void* source_value, + void* target_value); + + TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimRgbGridRemapEngine.cpp b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimRgbGridRemapEngine.cpp new file mode 100644 index 0000000000..6b757da4b2 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimRgbGridRemapEngine.cpp @@ -0,0 +1,271 @@ +//***************************************************************************** +// FILE: ossimRgbGridRemapEngine.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// AUTHOR: Oscar Kramer +// +// DESCRIPTION: Contains implementation of class +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimRgbGridRemapEngine.cpp,v 1.6 2005/09/09 19:23:58 gpotts Exp $ + +#include <imaging/tonal_balance/ossimRgbGridRemapEngine.h> + +RTTI_DEF1(ossimRgbGridRemapEngine, "ossimRgbGridRemapEngine", + ossimGridRemapEngine); + +#include <imaging/tonal_balance/ossimGridRemapSource.h> +#include <imaging/tonal_balance/ossimAtbPointSource.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimDblGrid.h> +#include <imaging/ossimImageData.h> + +//*** +// Define Trace flags for use within this file: +//*** +#include <base/common/ossimTrace.h> +static ossimTrace traceExec ("ossimRgbGridRemapEngine:exec"); +static ossimTrace traceDebug ("ossimRgbGridRemapEngine:debug"); + +//***************************************************************************** +// METHOD: ossimRgbGridRemapEngine::dup +// +//***************************************************************************** +ossimObject* ossimRgbGridRemapEngine::dup() const +{ + return new ossimRgbGridRemapEngine; +} + +//***************************************************************************** +// METHOD: ossimRgbGridRemapEngine::remapTile +// +//***************************************************************************** +void ossimRgbGridRemapEngine::remapTile(const ossimDpt& origin, + ossimGridRemapSource* remapper, + ossimRefPtr<ossimImageData>& tile) +{ + static const char MODULE[] = "ossimRgbGridRemapEngine::remapTile"; + if (traceExec()) CLOG << "entering..." << endl; + + //*** + // Fetch tile size and NULL pixel value: + //*** + int width = tile->getWidth(); + int height = tile->getHeight(); + int offset = 0; + double null[3]; + + //*** + // Determine null pixel values so that we can recognize a null coming in and + // not remap it: + //*** + null[0] = tile->getNullPix(0); + null[1] = tile->getNullPix(1); + null[2] = tile->getNullPix(2); + + ossimDblGrid& gridR = *(remapper->getGrid(0)); + ossimDblGrid& gridG = *(remapper->getGrid(1)); + ossimDblGrid& gridB = *(remapper->getGrid(2)); + + //*** + // Remap according to pixel type: + //*** + switch(tile->getScalarType()) + { + case OSSIM_UCHAR: + { + ossim_uint8* red_buf = (ossim_uint8*)tile->getBuf(0); + ossim_uint8* grn_buf = (ossim_uint8*)tile->getBuf(1); + ossim_uint8* blu_buf = (ossim_uint8*)tile->getBuf(2); + short pixel_buffer[3]; + + for (double line=origin.line; line<origin.line+height; line+=1.0) + { + for (double samp=origin.samp; samp<origin.samp+width; samp+=1.0) + { + //*** + // Scan for null pixel before adding remap delta: + //*** + if ((red_buf[offset] != (ossim_uint8) null[0]) && + (grn_buf[offset] != (ossim_uint8) null[1]) && + (blu_buf[offset] != (ossim_uint8) null[2])) + { + //*** + // Remap RGB pixel with spatially variant bias value: + //*** + pixel_buffer[0] = red_buf[offset] + (short) gridR(samp,line); + pixel_buffer[1] = grn_buf[offset] + (short) gridG(samp,line); + pixel_buffer[2] = blu_buf[offset] + (short) gridB(samp,line); + + //*** + // Clamp: + //*** + if (pixel_buffer[0]<0) red_buf[offset] = 0; + else if (pixel_buffer[0]>255) red_buf[offset] = 255; + else red_buf[offset] = pixel_buffer[0]; + + + if (pixel_buffer[1]<0) grn_buf[offset] = 0; + else if (pixel_buffer[1]>255) grn_buf[offset] = 255; + else grn_buf[offset] = pixel_buffer[1]; + + + if (pixel_buffer[2]<0) blu_buf[offset] = 0; + else if (pixel_buffer[2]>255) blu_buf[offset] = 255; + else blu_buf[offset] = pixel_buffer[2]; + + //*** + // Avoid NULLS: + //*** + if (red_buf[offset] == (ossim_uint8) null[0]) red_buf[offset]++; + if (grn_buf[offset] == (ossim_uint8) null[1]) grn_buf[offset]++; + if (blu_buf[offset] == (ossim_uint8) null[2]) blu_buf[offset]++; + } + + offset++; + } + } + break; + } + + default: + { + ossimNotify(ossimNotifyLevel_WARN) << "WARNING ossimRgbGridRemapEngine::remapTile: Scalar type not handled" << std::endl; + break; + } + + } // end switch statement + + if (traceExec()) CLOG << "returning..." << endl; + return; +}; + +//***************************************************************************** +// METHOD: ossimRgbGridRemapEngine::assignRemapValues +// +// This engine defines the target value as an RGB vector of doubles, computed +// as the mean of all contributor RGB values. +// +//***************************************************************************** +void ossimRgbGridRemapEngine::assignRemapValues ( + vector<ossimAtbPointSource*>& sources_list) +{ + static const char MODULE[] = "ossimRgbGridRemapEngine::assignRemapValues"; + if (traceExec()) CLOG << "entering..." << endl; + + int i; // index to individual sources + + //*** + // Declare a 2D array that will contain all of the contributing sources' + // RGB mean values. Also declare the accumulator target vector. + //*** + int num_contributors = sources_list.size(); + double** contributor_pixel = new double* [num_contributors]; + for (i=0; i<num_contributors; i++) + contributor_pixel[i] = new double[3]; + double target_pixel[3] = {0.0, 0.0, 0.0}; + + //*** + // Now loop over each remaining contributor and sum in its contribution: + //*** + vector<ossimAtbPointSource*>::iterator source; + i = 0; + for(source=sources_list.begin(); + source!=sources_list.end(); + source++) + { + (*source)->getSourceValue(contributor_pixel[i]); + + target_pixel[0] += contributor_pixel[i][0]/(double)num_contributors; + target_pixel[1] += contributor_pixel[i][1]/(double)num_contributors; + target_pixel[2] += contributor_pixel[i][2]/(double)num_contributors; + + i++; + } + + //*** + // The target pixel has been established. Now need to compute the actual + // remap quantities that will be written to the appropriate remap grids: + //*** + i = 0; + for(source=sources_list.begin(); + source!=sources_list.end(); + source++) + { + computeRemapNode(*source, contributor_pixel[i], target_pixel); + i++; + } + + //*** + // Delete locally allocated memory: + //*** + for (i=0; i<num_contributors; i++) + delete [] contributor_pixel[i]; + delete [] contributor_pixel; + + if (traceExec()) CLOG << "returning..." << endl; + return; +} + +//***************************************************************************** +// METHOD: ossimRgbGridRemapEngine::computeSourceValue +// +//***************************************************************************** +void ossimRgbGridRemapEngine::computeSourceValue( + ossimRefPtr<ossimImageData>& source, void* result) +{ + static const char MODULE[]="ossimRgbGridRemapEngine::computeSourceValue"; + if (traceExec()) CLOG << "entering..." << endl; + + //*** + // This engine defines "value" as the RGB vector corresponding to the mean + // RGB pixel value of the source data: + //*** + ((double*)result)[0] = source->computeAverageBandValue(0); + ((double*)result)[1] = source->computeAverageBandValue(1); + ((double*)result)[2] = source->computeAverageBandValue(2); + + if (traceExec()) CLOG << "returning..." << endl; + return; +} + +//***************************************************************************** +// METHOD: ossimRgbGridRemapEngine::computeRemapNode +// +// This engine defines the remap value as the difference between the target +// RGB vector and the individual point source's value vector. +// +//***************************************************************************** +void ossimRgbGridRemapEngine::computeRemapNode(ossimAtbPointSource* ps, + void* source_value, + void* target_value) +{ + static const char MODULE[] = "ossimRgbGridRemapEngine::computeRemapNode"; + if (traceExec()) CLOG << "entering..." << endl; + + //*** + // Compute the remap grid node value specific to this RGB implementation: + //*** + double node[3]; + node[0] = ((double*)target_value)[0] - ((double*)source_value)[0]; + node[1] = ((double*)target_value)[1] - ((double*)source_value)[1]; + node[2] = ((double*)target_value)[2] - ((double*)source_value)[2]; + + //*** + // Fetch a pointer to the remapper feeding this point source in order to + // pass it the node value: + //*** + ossimGridRemapSource* remapper = ps->getRemapSource(); + remapper->setGridNode(ps->getViewPoint(), node); + + if (traceExec()) CLOG << "returning..." << endl; + return; +} + diff --git a/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimRgbGridRemapEngine.h b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimRgbGridRemapEngine.h new file mode 100644 index 0000000000..29c2ad81e9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/imaging/tonal_balance/ossimRgbGridRemapEngine.h @@ -0,0 +1,54 @@ +//***************************************************************************** +// FILE: ossimRgbGridRemapEngine.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// AUTHOR: Oscar Kramer +// +// DESCRIPTION: Contains declaration of class ossimRgbGridRemapEngine +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimRgbGridRemapEngine.h,v 1.5 2005/10/17 18:42:27 gpotts Exp $ + +#ifndef ossimRgbGridRemapEngine_HEADER +#define ossimRgbGridRemapEngine_HEADER + +#include <imaging/tonal_balance/ossimGridRemapEngine.h> + +/*!**************************************************************************** + * + * CLASS: ossimRgbGridRemapEngine + * + *****************************************************************************/ +class ossimRgbGridRemapEngine : public ossimGridRemapEngine +{ +public: + ossimRgbGridRemapEngine() + : ossimGridRemapEngine(3, 3) {} + + virtual ossimObject* dup() const; + + virtual void remapTile(const ossimDpt& origin_point, + ossimGridRemapSource* remapper, + ossimRefPtr<ossimImageData>& tile); + + virtual void assignRemapValues(std::vector<ossimAtbPointSource*>& sources); + + virtual void computeSourceValue(ossimRefPtr<ossimImageData>& source, + void* result); + +protected: + virtual void computeRemapNode(ossimAtbPointSource* point_source, + void* source_value, + void* target_value); + + TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/init/.cvsignore b/Utilities/OSSIM/ossim_core/init/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/init/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/init/CMakeLists.txt b/Utilities/OSSIM/ossim_core/init/CMakeLists.txt new file mode 100644 index 0000000000..14ea75c04c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/init/CMakeLists.txt @@ -0,0 +1,6 @@ +FILE(GLOB_RECURSE ossim_init_SRCS "*.cpp") +FILE(GLOB_RECURSE ossim_init_HDRS "*.h") +ADD_LIBRARY(ossim_init ${ossim_init_SRCS}) + +INSTALL_TARGETS(/lib/otb/ ossim_init) +INSTALL_FILES(/include/otb/Utilities/OSSIM/ossim_core/ "\\.h$" ${ossim_init_HRDS}) diff --git a/Utilities/OSSIM/ossim_core/init/ossimInit.cpp b/Utilities/OSSIM/ossim_core/init/ossimInit.cpp new file mode 100644 index 0000000000..a97414ea24 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/init/ossimInit.cpp @@ -0,0 +1,551 @@ +//***************************************************************************** +// FILE: ossimInit.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// DESCRIPTION: +// Contains implementation of class ossimInit. This object handles all +// aspects of initialization for OSSIM applications. These tasks include: +// +// 1. Parsing the command line. +// 2. Instantiating all class factories. +// 3. Initializing the "trace" code execution tracing functionality. +// 4. Scanning the preferences file for relevant values. +// +// SOFTWARE HISTORY: +// 24Apr2001 Oscar Kramer +// Initial coding. +//***************************************************************************** +// $Id: ossimInit.cpp,v 1.66 2006/01/10 21:07:15 gpotts Exp $ + +#include <iostream> +using namespace std; +#include <init/ossimInit.h> +#include <base/common/ossimPreferences.h> +#include <base/common/ossimKeywordNames.h> +#include <base/common/ossimArgumentParser.h> +#include <base/common/ossimApplicationUsage.h> +#include <base/common/ossimTraceManager.h> +#include <algorithm> + +//*** +// Define Trace flags for use within this file: +//*** +#include <base/common/ossimTrace.h> + +// include the image file formats +#include <base/factory/ossimObjectFactoryRegistry.h> +#include <imaging/factory/ossimImageSourceFactoryRegistry.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <elevation/ossimElevManager.h> +#include <base/data_types/geoid/ossimGeoidManager.h> +#include <imaging/factory/ossimImageHandlerRegistry.h> +#include <imaging/factory/ossimImageWriterFactoryRegistry.h> +#include <imaging/factory/ossimImageMetaDataWriterRegistry.h> +#include <projections/factory/ossimProjectionViewControllerFactory.h> +#include <base/factory/ossimBaseObjectFactory.h> +#include <base/factory/ossimCustomEditorWindowRegistry.h> +#include <base/data_types/ossimDirectory.h> +#include <base/data_types/ossimKeywordlist.h> +#include <plugin/ossimSharedPluginRegistry.h> +#include <plugin/ossimDynamicLibrary.h> +#include <fonts/factory/ossimFontFactoryRegistry.h> +#include <base/context/ossimNotifyContext.h> + + +static ossimTrace traceExec = ossimTrace("ossimInit:exec"); +static ossimTrace traceDebug = ossimTrace("ossimInit:debug"); + +ossimInit* ossimInit::theInstance = NULL; + +ossimInit::~ossimInit() +{ + theInstance = NULL; +} + +ossimInit::ossimInit() + : + theAppName(), + thePreferences(ossimPreferences::instance()), + theElevEnabledFlag(true), + thePluginLoaderEnabledFlag(true) +{ +} + +ossimInit* ossimInit::instance() +{ + if (!theInstance) + { + theInstance = new ossimInit(); + } + return theInstance; +} + +void ossimInit::addOptions(ossimArgumentParser& parser) +{ + parser.getApplicationUsage()->addCommandLineOption("-P", "specify a preference file to load"); + parser.getApplicationUsage()->addCommandLineOption("-K", "specify individual keywords to add to the preferences keyword list: name=value"); + parser.getApplicationUsage()->addCommandLineOption("-T", "specify the classes to trace, ex: ossimInit|ossimImage.* \nwill trace ossimInit and all ossimImage classes"); + parser.getApplicationUsage()->addCommandLineOption("--disable-elev", "Will disable the elevation"); + parser.getApplicationUsage()->addCommandLineOption("--disable-plugin", "Will disable the plugin loader"); + + parser.getApplicationUsage()->addCommandLineOption("--ossim-logfile", "takes a logfile as an argument. All output messages are redirected to the specified log file. By default there is no log file and all messages are enabled."); + parser.getApplicationUsage()->addCommandLineOption("--disable-notify", "Takes an argument. Arguments are ALL, WARN, NOTICE, INFO, FATAL, DEBUG. If you want multiple disables then just do multiple --disable-notify on the command line. All argument are case insensitive. Default is all are enabled."); + +} + +/*!**************************************************************************** + * METHOD: ossimInit::initialize() + * + * Method called from the OSSIM application main. + * + *****************************************************************************/ +void ossimInit::initialize(int& argc, char** argv) +{ + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimInit::initialize(argc, argv): entering..." << std::endl; + + theInstance->theAppName = argv[0]; + + theInstance->thePreferences = ossimPreferences::instance(); + + // Parse the command line: + theInstance->parseOptions(argc, argv); + + theInstance->initializeDefaultFactories(); + theInstance->initializeElevation(); + if(thePluginLoaderEnabledFlag) + { + theInstance->initializePlugins(); + } + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimInit::initialize(argc, argv): leaving..." << std::endl; + return; +} + +void ossimInit::initialize(ossimArgumentParser& parser) +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimInit::initialize(parser): entering..." << endl; + } + + theInstance->theAppName = parser.getApplicationUsage()->getApplicationName(); + theInstance->thePreferences = ossimPreferences::instance(); + + //Parse the command line: + theInstance->parseOptions(parser); + + theInstance->initializeDefaultFactories(); + theInstance->initializeElevation(); + if(thePluginLoaderEnabledFlag) + { + theInstance->initializePlugins(); + } + + if(!theElevEnabledFlag) + { + ossimElevManager::instance()->disableSource(); + ossimElevManager::instance()->disableAutoLoad(); + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimInit::initialize(parser): leaving..." << endl; + } + return; +} + +void ossimInit::initialize() +{ + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimInit::initialize(): entering..." << std::endl; + + theInstance->theAppName = ""; + theInstance->thePreferences = ossimPreferences::instance(); + theInstance->initializeDefaultFactories(); + theInstance->initializeElevation(); + + //--- + // To do: + // We need a mechanism to register factories to the "front" or the + // "back" of factory list so that plugins can override things. For + // now we will initialize the plugins last... + //--- + if(thePluginLoaderEnabledFlag) + { + theInstance->initializePlugins(); + } + + return; +} + +void ossimInit::finalize() +{ + +} +/*!**************************************************************************** + * Prints to stdout the list of command line options that this object parses. + *****************************************************************************/ +void ossimInit::usage() +{ + ossimNotify(ossimNotifyLevel_INFO) + << "INFORMATION ossimInit::usage():\n" + << "Additional command-line options available are as follows: " + << "\n" + << "\n -P<pref_filename> -- Allows the user to override the loading " + << "\n of the default preferences with their own pref file." + << "\n" + << "\n -K<keyword>[=<value>] -- Allows the user to specify additional" + << "\n keyword/value pairs that are added onto the preferences " + << "\n previously loaded. Keywords specified here override those in" + << "\n the preferences file." + << "\n" + << "\n -T<trace_tag> -- Lets user turn on specific trace flags." + << "\n" + << "\n -S<session_filename> -- Allows user to specify a session file" + << "\n to load." + << std::endl; + return; +} + +void ossimInit::setPluginLoaderEnabledFlag(bool flag) +{ + thePluginLoaderEnabledFlag = flag; +} + + +void ossimInit::parseOptions(ossimArgumentParser& parser) +{ + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimInit::parseOptions: entering..." << endl; + + std::string tempString; + ossimArgumentParser::ossimParameter stringParameter(tempString); + while(parser.read("-P", stringParameter)); + + if(tempString != "") + { + thePreferences->loadPreferences(ossimFilename(tempString)); + } + while(parser.read("-K", stringParameter)) + { + ossimString option = tempString; + if (option.contains("=") ) + { + ossimString delimiter = "="; + ossimString key (option.before(delimiter)); + ossimString value = option.after(delimiter); + thePreferences->addPreference(key.c_str(), value.c_str()); + } + else + { + ossimString key (option); + thePreferences->addPreference(key, ""); + } + } + + while(parser.read("-T", stringParameter)) + { + ossimTraceManager::instance()->setTracePattern(ossimString(tempString)); + } + + while(parser.read("--ossim-logfile", stringParameter)) + { + ossimSetLogFilename(ossimFilename(tempString)); + } + while(parser.read("--disable-notify", stringParameter)) + { + ossimString tempDownCase = tempString; + tempDownCase = tempDownCase.downcase(); + + if(tempDownCase == "warn") + { + ossimDisableNotify(ossimNotifyFlags_WARN); + } + else if(tempDownCase == "fatal") + { + ossimDisableNotify(ossimNotifyFlags_FATAL); + } + else if(tempDownCase == "debug") + { + ossimDisableNotify(ossimNotifyFlags_DEBUG); + } + else if(tempDownCase == "info") + { + ossimDisableNotify(ossimNotifyFlags_INFO); + } + else if(tempDownCase == "notice") + { + ossimDisableNotify(ossimNotifyFlags_NOTICE); + } + else if(tempDownCase == "all") + { + ossimDisableNotify(ossimNotifyFlags_ALL); + } + } + if(parser.read("--disable-elev")) + { + theElevEnabledFlag = false; + } + if(parser.read("--disable-plugin")) + { + thePluginLoaderEnabledFlag = false; + } +} + + +/*!**************************************************************************** + * METHOD: ossimInit::parseOptions() + * + * Parses the command line options. + * + *****************************************************************************/ +void ossimInit::parseOptions(int& argc, char** argv) +{ + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimInit::parseOptions(argc, argv): entering..." << std::endl; + + int currArgc = 1; + while (currArgc < argc) + { + if(argv[currArgc][0] == '-') + { + switch (argv[currArgc][1]) + { + case 'P': + { + /*! + * OPTION_SYNTAX: -P<pref_filename> + * This option permits replacing the default preferences file + * with a different, user-specified keyword preference file: + */ + ossimFilename pref_file = (&argv[currArgc][2]); + thePreferences->loadPreferences(pref_file); + removeOption (argc, argv, currArgc--); + break; + } + + case 'K': + { + /*! + * OPTION SYNTAX: -K<keyword>[=<value>] + * This option used to add a keyword to the already loaded + * preferences KWL: + */ + ossimString option = (&argv[currArgc][2]); + if (option.contains("=") ) + { + ossimString delimiter = "="; + ossimString key (option.before(delimiter)); + ossimString value = option.after(delimiter); + thePreferences->addPreference(key.c_str(), value.c_str()); + } + else + { + ossimString key (option); + thePreferences->addPreference(key, ""); + + } + removeOption (argc, argv, currArgc--); + break; + } + + case 'T': + { + /*! + * OPTION SYNTAX: -T<trace_tag> + * Turns on the trace flag for all trace objects matching + * the trace_tag: + */ + ossimString tag = (&argv[currArgc][2]); + if (tag.empty()) + { + // Someone did -T "some_tag" instead of -T"some_tag" + removeOption (argc, argv, currArgc); + tag = argv[currArgc]; + } + ossimTraceManager::instance()->setTracePattern(tag); + removeOption (argc, argv, currArgc--); + break; + } + + case 'S': + { + /*! + * OPTION SYNTAX: -S<sesion_filename> + * This option is specified for autoloading session KWL files: + */ + ossimFilename session_file = (&argv[currArgc][2]); + thePreferences->loadPreferences(session_file); + removeOption (argc, argv, currArgc--); + break; + } + + default: + // option unrecognized, skip + break; + } + } + + currArgc++; + } + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimInit::parseOptions(argc, argv): leaving..." << std::endl; +} + + +/*!**************************************************************************** + * METHOD: ossimInit::removeOption() + * + * Removes all characters associated with the indicated option from the + * command line string. + * + *****************************************************************************/ +void ossimInit::removeOption(int& argc, + char** argv, + int argToRemove) +{ + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimInit::removeOption(argc, argv, argToRemove): entering..." + << std::endl; + + // Shift the args up by one position, overwriting the arg being removed: + for (int i=argToRemove+1; i<argc; i++) + { + argv[i - 1] = argv[i]; + } + + argc--; + argv[argc] = 0; + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimInit::removeOption(argc, argv, argToRemove): leaving..." + << std::endl; + return; +} + +void ossimInit::initializeDefaultFactories() +{ + ossimObjectFactoryRegistry::instance()->registerFactory(ossimImageSourceFactoryRegistry::instance()); + + //--- + // Because of how the imagehandlers work off a magic number make sure + // we place the writer first if we don't then the imagehandler will + // be false and will then try to open the filename and go through a + // magic number and if the file already + // existed it will open and create a handler instead of a writer. + //--- + ossimImageWriterFactoryRegistry::instance(); + ossimImageMetaDataWriterRegistry::instance(); + ossimImageHandlerRegistry::instance(); + ossimObjectFactoryRegistry::instance()->addFactory(ossimBaseObjectFactory::instance()); + + // initialize. projection factory. + ossimProjectionFactoryRegistry::instance(); + + // add the view controllers + ossimObjectFactoryRegistry::instance()->registerFactory(ossimProjectionViewControllerFactory::instance()); + + ossimFontFactoryRegistry::instance(); +} + +void ossimInit::initializePlugins() +{ + ossimString regExpressionDir = ossimString("^(") + "plugin.dir[0-9]+)"; + ossimString regExpressionFile = ossimString("^(") + "plugin.file[0-9]+)"; + + const ossimKeywordlist& kwl = thePreferences->preferencesKWL(); + + vector<ossimString> keys = kwl.getSubstringKeyList( regExpressionDir ); + + ossim_uint32 numberOfDirs = keys.size(); + ossim_uint32 offset = ossimString("plugin.dir").size(); + int idx = 0; + + std::vector<int> numberList(numberOfDirs); + if(numberList.size()>0) + { + for(idx = 0; idx < (int)numberList.size();++idx) + { + ossimString numberStr(keys[idx].begin() + offset, + keys[idx].end()); + numberList[idx] = numberStr.toInt(); + } + + std::sort(numberList.begin(), numberList.end()); + for(idx=0;idx < (int)numberList.size();++idx) + { + ossimString newPrefix = "plugin.dir"; + newPrefix += ossimString::toString(numberList[idx]); + const char* directory = kwl.find(newPrefix.c_str()); + + if(directory) + { + ossimDirectory d; + + if(d.open(ossimFilename(directory))) + { + ossimFilename file; + + if(d.getFirst(file, ossimDirectory::OSSIM_DIR_FILES)) + { + do + { + ossimSharedPluginRegistry::instance()->registerPlugin(file); + }while(d.getNext(file)); + } + } + } + } + } + keys = kwl.getSubstringKeyList( regExpressionFile ); + + ossim_uint32 numberOfFiles = keys.size(); + offset = ossimString("plugin.file").size(); + numberList.resize(numberOfFiles); + if(numberList.size()>0) + { + for(idx = 0; idx < (int)numberList.size();++idx) + { + ossimString numberStr(keys[idx].begin() + offset, + keys[idx].end()); + numberList[idx] = numberStr.toInt(); + } + + std::sort(numberList.begin(), numberList.end()); + for(idx=0;idx < (int)numberList.size();++idx) + { + ossimString newPrefix="plugin.file"; + newPrefix += ossimString::toString(numberList[idx]); + const char* file = kwl.find(newPrefix.c_str()); + + if(file&&ossimFilename(file).exists()) + { + ossimSharedPluginRegistry::instance()->registerPlugin(file); + } + } + } +} + +void ossimInit::initializeElevation() +{ + if (traceDebug()) ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimInit::initializeElevation(): Entered..." << std::endl; + + const ossimKeywordlist& KWL = thePreferences->preferencesKWL(); + + ossimGeoidManager::instance()->loadState(KWL); + ossimElevManager::instance()->loadState(KWL); + + if (traceDebug()) ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimInit::initializeElevation(): leaving..." << std::endl; +} diff --git a/Utilities/OSSIM/ossim_core/init/ossimInit.h b/Utilities/OSSIM/ossim_core/init/ossimInit.h new file mode 100644 index 0000000000..8d865264bc --- /dev/null +++ b/Utilities/OSSIM/ossim_core/init/ossimInit.h @@ -0,0 +1,125 @@ +//***************************************************************************** +// FILE: ossimInit.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// DESCRIPTION: +// Contains declaration of class ossimInit. This object handles all aspects +// of initialization for OSSIM applications. These tasks include: +// +// 1. Parsing the command line. +// 2. Instantiating all class factories as declared in ossimFactories.h +// 3. Initializing the "trace" code execution tracing functionality. +// 4. Scanning the preferences file for relevant values. +// +// SOFTWARE HISTORY: +//> +// 24Apr2001 Oscar Kramer (okramer@imagelinks.com) +// Initial coding. +//< +//***************************************************************************** + +#ifndef ossimInit_HEADER +#define ossimInit_HEADER + +#include <base/data_types/ossimString.h> + +class ossimPreferences; +class ossimArgumentParser; + +class OSSIMDLLEXPORT ossimInit +{ +public: + + ~ossimInit(); + /*! + * Returns the static instance of an ossimInit object. This is of no use + * until non-static methods are implemented. + */ + static ossimInit* instance(); + + void addOptions(ossimArgumentParser& parser); + /*! + * METHOD: initialize() + * This method shall be called from the application's main module with + * the command-line arguments. Every OSSIM application should have the + * following line early in the main module: + * + * ossimInit::initialize(argc, argv); + * + * OR + * + * ossimInit::instance()->initialize(argc, argv); + * + * The two forms are functionally identical. Pick the latter form if you + * like to type. The argv command line options are parsed and may be + * stripped. the value of argc will be adjusted to account for stripped + * options. + */ + void initialize(int& argc, char** argv); + + void initialize(ossimArgumentParser& parser); + + void initialize(); + + void finalize(); + + /*! + * METHOD: usage() + * Prints to stdout the list of command line options that this object parses + */ + void usage(); + + void setPluginLoaderEnabledFlag(bool flag); + +protected: + ossimInit(); + ossimInit(const ossimInit&) {} + + /*! + * METHOD: parseOptions() + * Parses the command line as passed in initialize. The options string is + * modified: + */ + void parseOptions(int& argc, char** argv); + + void parseOptions(ossimArgumentParser& parser); + + /*! + * METHOD: removeOptions() + * Utility for stripping from argv all characters associated with a + * particular option: + */ + void removeOption(int& argc, + char** argv, + int argToRemove); + + void initializeDefaultFactories(); + + void initializePlugins(); + + void initializeElevation(); + + static ossimInit* theInstance; + ossimString theAppName; + ossimPreferences* thePreferences; + bool theElevEnabledFlag; + bool thePluginLoaderEnabledFlag; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/libpolyclip/.cvsignore b/Utilities/OSSIM/ossim_core/libpolyclip/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/libpolyclip/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/libpolyclip/CMakeLists.txt b/Utilities/OSSIM/ossim_core/libpolyclip/CMakeLists.txt new file mode 100644 index 0000000000..7b7aec3a35 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/libpolyclip/CMakeLists.txt @@ -0,0 +1,6 @@ +FILE(GLOB_RECURSE ossim_polyclip_SRCS "*.c") +FILE(GLOB_RECURSE ossim_polyclip_HDRS "*.h") +ADD_LIBRARY(ossim_polyclip ${ossim_polyclip_SRCS}) + +INSTALL_TARGETS(/lib/otb/ ossim_polyclip) +INSTALL_FILES(/include/otb/Utilities/OSSIM/ossim_core/ "\\.h$" ${ossim_polyclip_HRDS}) diff --git a/Utilities/OSSIM/ossim_core/libpolyclip/polyarea.h b/Utilities/OSSIM/ossim_core/libpolyclip/polyarea.h new file mode 100644 index 0000000000..29c4c36868 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/libpolyclip/polyarea.h @@ -0,0 +1,336 @@ +/* + + poly_Boolean: a polygon clip library + + Copyright (C) 1997 Alexey Nikitin, Michael Leonov + + leonov@propro.iis.nsk.su + + + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + + + polyarea.h + + (C) 1997 Alexey Nikitin, Michael Leonov + + (C) 1997 Klamer Schutte (minor patches) + +*/ + + + +#ifndef POLY_H + +#define POLY_H + + + +#include "vectmatr.h" + + + +#ifdef __cplusplus + +extern "C" { + +#endif + + + +enum + +{ + + err_no_memory = 2, + + err_bad_parm = 3, + + err_ok = 0 + +}; + + + +#define PLF_STATUS 0x0003 + +#define PLF_CYCLINK 0x0004 + +#define PLF_MARK 0x0008 + +#define PLF_RESERVED 0x00FF + + + +#define PLF_ORIENT 0x0100 + +#define PLF_DIR 0x0100 + +#define PLF_INV 0x0000 + + + +typedef struct VNODE VNODE; + +struct VNODE + +{ + + VNODE *next, *prev; + + unsigned int Flags; + + Vector point; + + union + + { + + VNODE *link; + + void *v; + + int i; + + } t; + +}; + + + +typedef struct PLINE PLINE; + +struct PLINE + +{ + + PLINE *next; + + VNODE head; + + unsigned int Count; + + unsigned int Flags; + + double xmin, ymin, xmax, ymax; + +}; + + + +PLINE *poly_NewContour(Vector v); + + + +void poly_IniContour(PLINE * c); + +void poly_ClrContour(PLINE * c); /* clears list of vertices */ + +void poly_DelContour(PLINE ** c); + + + +BOOL poly_CopyContour(PLINE ** dst, PLINE * src); + + + +void poly_PreContour(PLINE * c, BOOL optimize); /* prepare contour */ + +void poly_InvContour(PLINE * c); /* invert contour */ + + + +VNODE *poly_CreateNode(Vector v); + + + +void poly_InclVertex(VNODE * after, VNODE * node); + +void poly_ExclVertex(VNODE * node); + + + +/**********************************************************************/ + + + +typedef struct POLYAREA POLYAREA; + +struct POLYAREA + +{ + + POLYAREA *f, *b; + + PLINE *contours; + +}; + + + +/************** POLYMAP ****************/ + + + +#define MAXLABEL 128 + + + +typedef struct POLYMAP POLYMAP; + +struct POLYMAP + +{ + + POLYMAP *next; + + POLYAREA *area; + + char *label; + +}; + + + +BOOL LoadPOLYMAP(POLYMAP **m, char *fname); + +void SavePOLYMAP(POLYMAP *m, char *fname); + +BOOL poly_Overlay(POLYMAP *R, POLYMAP *B, POLYMAP **r, POLYMAP **b, POLYMAP **p); + +/* R and B are input maps, the output maps are: + +r = R - B, + +b = B - R, + +p = R & B */ + + + +BOOL poly_AddMap(POLYMAP **m, POLYAREA *area, char *label); + +void poly_DelMap(POLYMAP **m); + + + +/***************************************/ + + + +BOOL poly_M_Copy0(POLYAREA ** dst, const POLYAREA * srcfst); + +void poly_M_Incl(POLYAREA **list, POLYAREA *a); + + + +BOOL poly_Copy0(POLYAREA **dst, const POLYAREA *src); + +BOOL poly_Copy1(POLYAREA *dst, const POLYAREA *src); + + + +BOOL poly_InclContour(POLYAREA * p, PLINE * c); + +BOOL poly_ExclContour(POLYAREA * p, PLINE * c); + + + + + +BOOL poly_ChkContour(PLINE * a); + + + +BOOL poly_CheckInside(POLYAREA * c, Vector v0); + + + +/**********************************************************************/ + + + +/* tools for clipping */ + + + +/* checks whether point lies within contour + +independently of its orientation */ + + + +int poly_InsideContour(PLINE *c, Vector v); + +int poly_ContourInContour(PLINE * poly, PLINE * inner); + +POLYAREA *poly_Create(void); + + + +void poly_Free(POLYAREA **p); + +void poly_Init(POLYAREA *p); + +void poly_Clear(POLYAREA *p); + +BOOL poly_Valid(POLYAREA *p); + + + +enum PolygonBooleanOperation { + + PBO_UNITE, + + PBO_ISECT, + + PBO_SUB, + + PBO_XOR + +}; + + + +int poly_Boolean(const POLYAREA * a, const POLYAREA * b, POLYAREA ** res, int action); + + + +#ifdef __cplusplus + +} + +#endif + + + + + +#endif /* POLY_H */ + diff --git a/Utilities/OSSIM/ossim_core/libpolyclip/polygon0.c b/Utilities/OSSIM/ossim_core/libpolyclip/polygon0.c new file mode 100644 index 0000000000..ab0f01335c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/libpolyclip/polygon0.c @@ -0,0 +1,1234 @@ +/* + + poly_Boolean: a polygon clip library + + Copyright (C) 1997 Alexey Nikitin, Michael Leonov + + leonov@propro.ru + + + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + + + polygon0.c + + (C) 1997 Alexey Nikitin, Michael Leonov + +*/ + + + +#include <assert.h> + +#include <math.h> + +#include <string.h> + +#include <stdlib.h> +#include <string.h> + + +#include "vectmatr.h" + +#include "polyarea.h" + + + +#define SETBITS(n,mask,s) (((n)->Flags & ~(mask)) | ((s) & mask)) + +#define GETBITS(n, mask) ((n)->Flags & mask) + + + +static + +void cntrbox_adjust(PLINE * c, Vector p) + +{ + + c->xmin = min(c->xmin, p[0]); + + c->xmax = max(c->xmax, p[0]); + + c->ymin = min(c->ymin, p[1]); + + c->ymax = max(c->ymax, p[1]); + +} + + + +static + +int cntrbox_pointin(PLINE * c, Vector p) + +{ + + return (p[0] >= c->xmin && p[1] >= c->ymin && + + p[0] <= c->xmax && p[1] <= c->ymax); + + + +} + + + +static + +int cntrbox_inside(PLINE * c1, PLINE * c2) + +{ + + assert(c1 != NULL && c2 != NULL); + + return ((c1->xmin >= c2->xmin) && + + (c1->ymin >= c2->ymin) && + + (c1->xmax <= c2->xmax) && + + (c1->ymax <= c2->ymax)); + +} + + + +static + +int node_neighbours(VNODE * a, VNODE * b) + +{ + + return (a == b) || (a->next == b) || (b->next == a) || + + (a->next == b->next); + +} + + + +VNODE *poly_CreateNode(Vector v) + +{ + + VNODE *res; + + + + if (v == NULL) + + return NULL; + + res = (VNODE *) malloc(sizeof(VNODE)); + + if (res == NULL) + + return NULL; + + res->Flags = 0; + + res->t.link = NULL; + + vect_copy(res->point, v); + + res->prev = res->next = res; + + return res; + +} + + + +void poly_IniContour(PLINE * c) + +{ + + if (c == NULL) + + return; + + c->next = NULL; + + c->Flags = 0; + + c->Count = 0; + + vect_copy(c->head.point, vect_zero); + + c->head.next = c->head.prev = &c->head; + + c->xmin = c->ymin = +1.0e+30f; + + c->xmax = c->ymax = -1.0e+30f; + +} + + + +PLINE *poly_NewContour(Vector v) + +{ + + PLINE *res; + + + + res = (PLINE *)calloc(1, sizeof(PLINE)); + + if (res == NULL) + + return NULL; + + + + poly_IniContour(res); + + + + if (v != NULL) + + { + + vect_copy(res->head.point, v); + + cntrbox_adjust(res, v); + + } + + + + return res; + +} + + + +void poly_ClrContour(PLINE * c) + +{ + + VNODE *cur; + + + + assert(c != NULL); + + while ( ( cur = c->head.next ) != &c->head ) + + { + + poly_ExclVertex(cur); + + free(cur); + + } + + poly_IniContour(c); + +} + + + +void poly_DelContour(PLINE ** c) + +{ + + if (*c == NULL) + + return; + + poly_ClrContour(*c); + + free(*c), *c = NULL; + +} + + + +#define IsZero(a, b) (fabs((a) - (b)) < EPSILON) + + + +void poly_PreContour(PLINE *C, BOOL optimize) + +{ + + double area = 0; + + VNODE *p, *c; + + + + assert(C != NULL); + + + + if (optimize) + + { + + for (c = (p = &C->head)->next; c != &C->head; c = (p = c)->next) + + { + + if (IsZero(p->point[0], c->point[0]) && + + IsZero(p->point[1], c->point[1])) + + { + + poly_ExclVertex(c); + + free(c); + + c = p; + + } + + } + + } + + C->Count = 0; + + C->xmin = C->xmax = C->head.point[0]; + + C->ymin = C->ymax = C->head.point[1]; + + + + p = (c = &C->head)->prev; + + if (c != p) + + { + + do { + + /* calculate area for orientation */ + + area += (p->point[0] - c->point[0]) * (p->point[1] + c->point[1]); + + cntrbox_adjust(C, c->point); + + C->Count++; + + } while ((c = (p = c)->next) != &C->head); + + } + + if (C->Count > 2) + + C->Flags = SETBITS(c, PLF_ORIENT, area < 0 ? PLF_INV : PLF_DIR); + +} /* poly_PreContour */ + + + +void poly_InvContour(PLINE * c) + +{ + + VNODE *cur, *next; + + + + assert(c != NULL); + + cur = &c->head; + + do + + { + + next = cur->next; + + cur->next = cur->prev; + + cur->prev = next; + + } while ((cur = next) != &c->head); + + c->Flags ^= PLF_ORIENT; + +} + + + +void poly_InclVertex(VNODE * after, VNODE * node) + +{ + + assert(after != NULL); + + assert(node != NULL); + + + + node->prev = after; + + node->next = after->next; + + after->next = after->next->prev = node; + +} + + + +void poly_ExclVertex(VNODE * node) + +{ + + assert (node != NULL); + + + + node->prev->next = node->next; + + node->next->prev = node->prev; + +} + + + +BOOL poly_CopyContour(PLINE ** dst, PLINE * src) + +{ + + VNODE *cur, *newnode; + + + + assert(src != NULL); + + *dst = NULL; + + *dst = poly_NewContour(src->head.point); + + if (*dst == NULL) + + return FALSE; + + + + (*dst)->Count = src->Count; + + (*dst)->Flags = src->Flags; + + (*dst)->xmin = src->xmin, (*dst)->xmax = src->xmax; + + (*dst)->ymin = src->ymin, (*dst)->ymax = src->ymax; + + + + for (cur = src->head.next; cur != &src->head; cur = cur->next) + + { + + if ( (newnode = poly_CreateNode(cur->point) ) == NULL) + + return FALSE; + + newnode->Flags = cur->Flags; + + poly_InclVertex((*dst)->head.prev, newnode); + + } + + return TRUE; + +} + + + +/**********************************************************************/ + +/* polygon routines */ + + + +BOOL poly_Copy0(POLYAREA ** dst, const POLYAREA * src) + +{ + + *dst = NULL; + + if (src != NULL) + + *dst = (POLYAREA*)calloc(1, sizeof(POLYAREA)); + + if (*dst == NULL) + + return FALSE; + + + + return poly_Copy1(*dst, src); + +} + + + +BOOL poly_Copy1(POLYAREA * dst, const POLYAREA * src) + +{ + + PLINE *cur, **last = &dst->contours; + + + + *last = NULL; + + dst->f = dst->b = dst; + + + + for (cur = src->contours; cur != NULL; cur = cur->next) + + { + + if (!poly_CopyContour(last, cur)) + + return FALSE; + + last = &(*last)->next; + + } + + return TRUE; + +} + + + +void poly_M_Incl(POLYAREA **list, POLYAREA *a) + +{ + + if (*list == NULL) + + a->f = a->b = a, *list = a; + + else + + { + + a->f = *list; + + a->b = (*list)->b; + + (*list)->b = (*list)->b->f = a; + + } + +} + + + +BOOL poly_M_Copy0(POLYAREA ** dst, const POLYAREA * srcfst) + +{ + + const POLYAREA *src = srcfst; + + POLYAREA *di; + + + + *dst = NULL; + + if (src == NULL) + + return FALSE; + + do { + + if ((di = poly_Create()) == NULL || + + !poly_Copy1(di, src)) + + return FALSE; + + poly_M_Incl(dst, di); + + } while ((src = src->f) != srcfst); + + return TRUE; + +} + + + +BOOL poly_InclContour(POLYAREA * p, PLINE * c) + +{ + + PLINE *tmp; + + + + if ((c == NULL) || (p == NULL)) + + return FALSE; + + if (GETBITS(c, PLF_ORIENT) == PLF_DIR) + + { + + if (p->contours != NULL) + + return FALSE; + + p->contours = c; + + } + + else + + { + + if (p->contours == NULL) + + return FALSE; + + for (tmp = p->contours; tmp->next != NULL; tmp = tmp->next); + + tmp->next = c; + + c->next = NULL; + + } + + return TRUE; + +} + + + +BOOL poly_M_InclContour(POLYAREA ** p, PLINE * c) + +{ + + POLYAREA *a, *t; + + + + if (c == NULL) + + return FALSE; + + if (GETBITS(c, PLF_ORIENT) == PLF_DIR) + + { + + t = poly_Create(); + + if (*p != NULL) + + { + + a = (*p)->b; + + (((t->f = a->f)->b = t)->b = a)->f = t; + + } + + else + + *p = t; + + return poly_InclContour(t, c); + + } + + else + + { + + if (*p == NULL) + + return FALSE; + + a = *p; + + t = NULL; + + do { + + /* find the smallest container for the hole */ + + if (poly_ContourInContour(a->contours, c) && + + (t == NULL || + + poly_ContourInContour(t->contours, a->contours))) + + t = a; + + } while ((a = a->f) != *p); + + if (t == NULL) + + return FALSE; + + else + + return poly_InclContour(t, c); + + } + +} + + + +BOOL poly_ExclContour(POLYAREA * p, PLINE * c) + +{ + + PLINE *tmp; + + + + if ((c == NULL) || (p == NULL) || (p->contours == NULL)) + + return FALSE; + + if (GETBITS(c, PLF_ORIENT) == PLF_DIR) + + { + + if (c != p->contours) + + return FALSE; + + assert(c->next == NULL); + + p->contours = NULL; + + } + + else + + { + + for (tmp = p->contours; (tmp->next != c) && (tmp->next != NULL); + + tmp = tmp->next) {} + + if (tmp->next == NULL) + + return FALSE; + + tmp->next = c->next; + + } + + return TRUE; + +} + + + + + +BOOL poly_M_ExclContour(POLYAREA * p, PLINE * c) + +{ + + POLYAREA *a = p; + + + + if (p == NULL || c == NULL) + + return FALSE; + + do { + + if (poly_ExclContour(a, c)) + + return TRUE; + + } while ((a = a->f) != p); + + return FALSE; + +} + + + +int poly_InsideContour(PLINE * c, Vector p) + +{ + + int f = 0; + + VNODE *cur; + + + + if (!cntrbox_pointin(c, p)) + + return FALSE; + + + + cur = &c->head; + + do + + { + + if (( + + ((cur->point[1] <= p[1]) && (p[1] < cur->prev->point[1])) || + + ((cur->prev->point[1] <= p[1]) && (p[1] < cur->point[1])) + + ) && (p[0] < + + (cur->prev->point[0] - cur->point[0]) * (p[1] - cur->point[1]) + + / (cur->prev->point[1] - cur->point[1]) + cur->point[0]) + + ) + + f = !f; + + } while ((cur = cur->next) != &c->head); + + return f; + +} + + + + + +BOOL poly_CheckInside(POLYAREA * p, Vector v0) + +{ + + PLINE *cur; + + + + if ((p == NULL) || (v0 == NULL) || (p->contours == NULL)) + + return FALSE; + + cur = p->contours; + + if (poly_InsideContour(cur, v0)) + + { + + for (cur = cur->next; cur != NULL; cur = cur->next) + + if (poly_InsideContour(cur, v0)) + + return FALSE; + + return TRUE; + + } + + return FALSE; + +} + + + +BOOL poly_M_CheckInside(POLYAREA * p, Vector v0) + +{ + + POLYAREA *cur; + + + + if ((p == NULL) || (v0 == NULL)) + + return FALSE; + + cur = p; + + do { + + if (poly_CheckInside(cur, v0)) + + return TRUE; + + } while ((cur = cur->f) != p); + + return FALSE; + +} + + + +int poly_ContourInContour(PLINE * poly, PLINE * inner) + +{ + + assert(poly != NULL); + + assert(inner != NULL); + + if (!cntrbox_inside(inner, poly)) + + return FALSE; + + return poly_InsideContour(poly, inner->head.point); + +} + + + +void poly_Init(POLYAREA *p) + +{ + + p->f = p->b = p; + + p->contours = NULL; + +} + + + +POLYAREA *poly_Create(void) + +{ + + POLYAREA *res; + + + + if ((res = (POLYAREA*)malloc(sizeof(POLYAREA))) != NULL) + + poly_Init(res); + + return res; + +} + + + +void poly_Clear(POLYAREA *P) + +{ + + PLINE *p; + + + + assert(P != NULL); + + while ((p = P->contours) != NULL) + + { + + P->contours = p->next; + + poly_DelContour(&p); + + } + +} + + + +void poly_Free(POLYAREA ** p) + +{ + + POLYAREA *cur; + + + + if (*p == NULL) + + return; + + for (cur = (*p)->f; cur != *p; cur = (*p)->f) + + { + + poly_Clear(cur); + + cur->f->b = cur->b; + + cur->b->f = cur->f; + + free(cur); + + } + + poly_Clear(cur); + + free(*p), *p = NULL; + +} + + + +static + +BOOL inside_sector(VNODE * pn, Vector p2) + +{ + + Vector cdir, ndir, pdir; + + int p_c, n_c, p_n; + + + + assert(pn != NULL); + + vect_sub(cdir, p2, pn->point); + + vect_sub(pdir, pn->point, pn->prev->point); + + vect_sub(ndir, pn->next->point, pn->point); + + + + p_c = vect_det2(pdir, cdir) >= 0; + + n_c = vect_det2(ndir, cdir) >= 0; + + p_n = vect_det2(pdir, ndir) >= 0; + + + + if ((p_n && p_c && n_c) || ((!p_n) && (p_c || n_c))) + + return TRUE; + + else + + return FALSE; + +} /* inside_sector */ + + + +/* returns TRUE if bad contour */ + +BOOL poly_ChkContour(PLINE * a) + +{ + + VNODE *a1, *a2, *hit1, *hit2; + + Vector i1, i2; + + int icnt; + + + + assert(a != NULL); + + a1 = &a->head; + + do + + { + + a2 = a1; + + do + + { + + if (!node_neighbours(a1, a2) && + + (icnt = vect_inters2(a1->point, a1->next->point, + + a2->point, a2->next->point, i1, i2)) > 0) + + { + + if (icnt > 1) + + return TRUE; + + + + if (vect_dist2(i1, a1->point) < EPSILON) + + hit1 = a1; + + else if (vect_dist2(i1, a1->next->point) < EPSILON) + + hit1 = a1->next; + + else + + return TRUE; + + + + if (vect_dist2(i1, a2->point) < EPSILON) + + hit2 = a2; + + else if (vect_dist2(i1, a2->next->point) < EPSILON) + + hit2 = a2->next; + + else + + return TRUE; + + + + /* now check if they are inside each other */ + + if (inside_sector(hit1, hit2->prev->point) || + + inside_sector(hit1, hit2->next->point) || + + inside_sector(hit2, hit1->prev->point) || + + inside_sector(hit2, hit1->next->point)) + + return TRUE; + + } + + } + + while ((a2 = a2->next) != &a->head); + + } + + while ((a1 = a1->next) != &a->head); + + return FALSE; + +} + + + + + +BOOL poly_Valid(POLYAREA * p) + +{ + + PLINE *c; + + + + if ((p == NULL) || (p->contours == NULL)) + + return FALSE; + + + + if (GETBITS(p->contours, PLF_ORIENT) == PLF_INV || + + poly_ChkContour(p->contours)) + + return FALSE; + + for (c = p->contours->next; c != NULL; c = c->next) + + { + + if (GETBITS(c, PLF_ORIENT) == PLF_DIR || + + poly_ChkContour(c) || + + !poly_ContourInContour(p->contours, c) ) + + return FALSE; + + } + + return TRUE; + +} + + + +/******************* POLYMAP ************************/ + + + +BOOL poly_AddMap(POLYMAP **m, POLYAREA *area, char *label) + +{ + + POLYMAP *n; + + if (area == NULL) return 0; + + if ((n = (POLYMAP*)calloc(1, sizeof(POLYMAP))) == NULL) + + return 1; + + n->area = area; + + n->label = strdup(label); + + n->next = *m, *m = n; + + return 0; + +} /* poly_AddMap */ + + + +void poly_DelMap(POLYMAP **m) + +{ + + assert(m != NULL); + + while (*m != NULL) + + { + + poly_Free(&(*m)->area); + + free((*m)->label); + + *m = (*m)->next; + + } + +} /* poly_DelMap */ + + + diff --git a/Utilities/OSSIM/ossim_core/libpolyclip/polygon1.c b/Utilities/OSSIM/ossim_core/libpolyclip/polygon1.c new file mode 100644 index 0000000000..7e09e38320 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/libpolyclip/polygon1.c @@ -0,0 +1,1482 @@ +/* + + poly_Boolean: a polygon clip library + + Copyright (C) 1997 Alexey Nikitin, Michael Leonov + + leonov@propro.ru + + + + based on: + + nclip: a polygon clip library + + Copyright (C) 1993 Klamer Schutte + + + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + + + polygon1.c + + (C) 1997 Alexey Nikitin, Michael Leonov + + (C) 1993 Klamer Schutte + + + + all cases where original (Klamer Schutte) code is present + + are marked + +*/ + + + +#include <assert.h> + +#include <stdlib.h> + +#include <string.h> + +#include <setjmp.h> + +#include <math.h> + + + +#include "polyarea.h" + +#include "vectmatr.h" + + + +#define ISECTED 0 + +#define SHARED ISECTED + +#define INSIDE 1 + +#define OUTSIDE 2 + +#define UNKNOWN 3 + + + +/* this means that current polygon is B and operation is A - B */ + +#define PBO_SUBSLAVE (-PBO_SUB) + + + +#define SETBITS(n,mask,s) (((n)->Flags & ~(mask)) | ((s) & mask)) + +#define GETBITS(n, mask) ((n)->Flags & mask) + +#define PLF_ESTATE(n) GETBITS(n, PLF_STATUS) + + + +#define error(code) longjmp(*(e), code) + + + +#define MemGet(ptr, type) \ +if (((ptr) = (type*)malloc(sizeof(type))) == NULL) \ + error(err_no_memory); + + + +/***************************************************************/ + +/* routines for processing intersections */ + + + +/* + +node_add + + (C) 1993 Klamer Schutte + + (C) 1997 Alexey Nikitin, Michael Leonov + +*/ + +static + +VNODE *node_add(VNODE * dest, Vector po, int *new_point) + +{ + + VNODE *chk = dest, *last, *p; + + double d; + + + + do + + if (vect_equal(po, chk->point)) + + return chk; + + while ((chk = chk->next) != dest); + + + + d = vect_dist2(dest->point, po); + + for (p = (last = dest)->next; d > vect_dist2(dest->point, p->point); + + p = (last = p)->next) ; + + /* Go to next node, as next node is on same side as current node */ + + p = poly_CreateNode(po); + + if ( p == NULL ) return NULL; + +/* *new_point++; */ + + p->prev = last; + + p->next = last->next; + + p->t.link = NULL; + + p->Flags = UNKNOWN; + + return ( last->next = last->next->prev = p ); + +} /* node_add */ + + + +#define ISECT_BAD_PARAM (-1) + +#define ISECT_NO_MEMORY (-2) + + + +/* + +node_add_point + + (C) 1993 Klamer Schutte + + (C) 1997 Alexey Nikitin, Michael Leonov + +*/ + + + +static + +int node_add_point(VNODE * a, VNODE * b, Vector p) + +{ + + int res = 0; + + + + VNODE *node_a = node_add(a, p, &res); + + VNODE *node_b = node_add(b, p, &res); + + + + if ( node_a == NULL || node_b == NULL ) + + return ISECT_NO_MEMORY; + + if (node_a->t.link != 0 && node_a->t.link != node_b) + + return ISECT_BAD_PARAM; + + if (node_b->t.link != 0 && node_b->t.link != node_a) + + return ISECT_BAD_PARAM; + + + + node_a->t.link = node_b; + + node_b->t.link = node_a; + + return res; + +} /* node_add_point */ + + + +/* + + + +intersect + + (C) 1993 Klamer Schutte + + (C) 1997 Alexey Nikitin, Michael Leonov + + + + calculate all the intersections between a and b. Add the intersection points + + to a and b. + + returns total number of intersections found.*/ + +static + +int intersect(PLINE * a, PLINE * b) + +{ + + VNODE *a_iter, *b_iter; + + int res = 0, res2 = 0, cnt, errc; + + Vector intersect1, intersect2; + + + + assert(a != NULL); + + assert(b != NULL); + + + + /* if their boxes do not isect return 0 intersections */ + + if ( ( a->xmin > b->xmax ) || ( a->xmax < b->xmin ) || + + ( a->ymin > b->ymax ) || ( a->ymax < b->ymin ) ) + + return 0; + + + + a_iter = &a->head; + + do { + + b_iter = &b->head; + + do { + + cnt = vect_inters2(a_iter->point, a_iter->next->point, + + b_iter->point, b_iter->next->point, + + intersect1, intersect2); + + res += cnt; + + if (cnt > 0) + + { + + res2 += ( errc = node_add_point(a_iter, b_iter, intersect1) ); + + if ( errc < 0 ) return errc; + + if (cnt >= 2) + + { + + res2 += ( errc = node_add_point(a_iter, b_iter, intersect2) ); + + if ( errc < 0 ) return errc; + + } + + } + + } while ((b_iter = b_iter->next) != &b->head); + + } while ((a_iter = a_iter->next) != &a->head); + + + + if (res2 != 0) + + { + + if ( (errc = intersect(a, b)) < 0 ) + + return errc; + + else + + return res + errc; + + } + + + + return res; + +} /* intersect */ + + + +static + +void M_POLYAREA_intersect(jmp_buf *e, POLYAREA * afst, POLYAREA * bfst) + +{ + + POLYAREA *a = afst, *b = bfst; + + PLINE *curcA, *curcB; + + int locisect; + + + + if ( a == NULL || b == NULL ) + + error(err_bad_parm); + + do { + + do { + + for (curcA = a->contours; curcA != NULL; curcA = curcA->next) + + for (curcB = b->contours; curcB != NULL; curcB = curcB->next) + + if ((locisect = intersect(curcA, curcB)) > 0) + + { + + curcA->Flags = SETBITS(curcA, PLF_STATUS, ISECTED); + + curcB->Flags = SETBITS(curcB, PLF_STATUS, ISECTED); + + } + + else if ( locisect == ISECT_BAD_PARAM ) + + error(err_bad_parm); + + else if ( locisect == ISECT_NO_MEMORY ) + + error(err_no_memory); + + } while ((a = a->f) != afst); + + } while ((b = b->f) != bfst); + +} /* M_POLYAREA_intersect */ + + + +/*****************************************************************/ + +/* Routines for making labels */ + + + +/* cntr_in_M_POLYAREA + +returns poly is inside outfst ? TRUE : FALSE */ + +static + +int cntr_in_M_POLYAREA(PLINE * poly, POLYAREA * outfst) + +{ + + PLINE *curc; + + POLYAREA *outer = outfst; + + + + assert(poly != NULL); + + assert(outer != NULL); + + + + do { + + if (poly_ContourInContour(outer->contours, poly)) + + { + + for (curc = outer->contours->next; curc != NULL; curc = curc->next) + + if (poly_ContourInContour(curc, poly)) + + continue; + + return TRUE; + + } + + } while ((outer = outer->f) != outfst); + + return FALSE; + +} /* cntr_in_M_POLYAREA */ + + + +/* + +node_label + + (C) 1993 Klamer Schutte + + (C) 1997 Alexey Nikitin, Michael Leonov + +*/ + + + +static + +unsigned int node_label(Vector p2, VNODE * pn) + +{ + + Vector + + cdir, ndir, pdir; + + int p_c, n_c, p_n; + + + + assert(pn != NULL); + + vect_sub(cdir, p2, pn->point); + + vect_sub(pdir, pn->point, pn->prev->point); + + vect_sub(ndir, pn->next->point, pn->point); + + + + p_c = vect_det2(pdir, cdir) >= 0; + + n_c = vect_det2(ndir, cdir) >= 0; + + p_n = vect_det2(pdir, ndir) >= 0; + + + + if ((p_n && p_c && n_c) || ((!p_n) && (p_c || n_c))) + + return INSIDE; + + else + + return OUTSIDE; + + + +} /* node_label */ + + + +/* + +label_contour + + (C) 1993 Klamer Schutte + + (C) 1997 Alexey Nikitin, Michael Leonov + +*/ + + + +static + +void label_contour(PLINE * a) + +{ + + VNODE *cur = &a->head, *b1, *b2; + + + + do { + + if ( PLF_ESTATE(cur) != OUTSIDE && PLF_ESTATE(cur) != UNKNOWN ) + + continue; + + + + b1 = cur->t.link; + + b2 = cur->next->t.link; + + + + if ( b1 != NULL && b2 != NULL && + + /* Seems SHARED -- but check + + that b1 and b2 are also connected! */ + + ( b1->next == b2 || b2->next == b1 ) ) + + { + + cur->Flags = SETBITS(cur, PLF_STATUS, SHARED); + + continue; + + } + + /* else isected by different contours */ + + if (b1 != NULL) + + cur->Flags = SETBITS(cur, PLF_STATUS, node_label(cur->next->point, b1)); + + else if (b2 != NULL) + + cur->Flags = SETBITS(cur, PLF_STATUS, node_label(cur->point, b2)); + + } while ((cur = cur->next) != &a->head); + +} /* label_contour */ + + + +static + +void cntr_label_POLYAREA(PLINE * poly, POLYAREA * ppl) + +{ + + assert(ppl != NULL && ppl->contours != NULL); + + if (GETBITS(poly, PLF_STATUS) == ISECTED) + + label_contour(poly); + + else if ( cntr_in_M_POLYAREA( poly, ppl ) ) + + poly->Flags = SETBITS( poly, PLF_STATUS, INSIDE); + + else + + poly->Flags = SETBITS( poly, PLF_STATUS, OUTSIDE); + +} /* cntr_label_POLYAREA */ + + + +static + +void M_POLYAREA_label(POLYAREA * afst, POLYAREA * b) + +{ + + POLYAREA *a = afst; + + PLINE *curc; + + + + assert(a != NULL); + + do { + + for (curc = a->contours; curc != NULL; curc = curc->next) + + cntr_label_POLYAREA(curc, b); + + } while ((a = a->f) != afst); + +} + + + +/****************************************************************/ + + + +/* routines for temporary storing resulting contours */ + +static + +void InsCntr(jmp_buf *e, PLINE * c, POLYAREA ** dst) + +{ + + POLYAREA *newp; + + + + if (*dst == NULL) + + { + + MemGet(*dst, POLYAREA); + + (*dst)->f = (*dst)->b = *dst; + + newp = *dst; + + } + + else + + { + + MemGet(newp, POLYAREA); + + newp->f = *dst; + + newp->b = (*dst)->b; + + newp->f->b = newp->b->f = newp; + + } + + newp->contours = c; + + c->next = NULL; + +} /* InsCntr */ + + + +static + +void PutContour(jmp_buf *e, PLINE * cntr, POLYAREA ** contours, PLINE ** holes) + +{ + + PLINE *cur; + + + + assert(cntr != NULL); + + cntr->next = NULL; + + if (GETBITS(cntr, PLF_ORIENT) == PLF_DIR) + + InsCntr(e, cntr, contours); + + + + /* put hole into temporary list */ + + else if (*holes == NULL) + + *holes = cntr; /* let cntr be 1st hole in list */ + + else + + { + + for (cur = *holes; cur->next != NULL; cur = cur->next); + + cur->next = cntr; + + } + +} /* PutContour */ + + + +static + +void InsertHoles(jmp_buf *e, POLYAREA * dest, PLINE **src) + +{ + + POLYAREA *curc, *container; + + PLINE *curh, *nexth; + + + + if (*src == NULL) return; /* empty hole list */ + + if (dest == NULL) error(err_bad_parm); /* empty contour list */ + + + + while ((curh = *src) != NULL) + + { + + *src = curh->next; + + + + container = NULL; + + curc = dest; + + do + + { + + /* find the smallest container for the hole */ + + if (poly_ContourInContour(curc->contours, curh) && + + (container == NULL || + + poly_ContourInContour(container->contours, curc->contours))) + + container = curc; + + } while ((curc = curc->f) != dest); + + nexth = curh->next; + + curh->next = NULL; + + if (container == NULL) + + { + + /* bad input polygons were given */ + + poly_DelContour(&curh); + + error(err_bad_parm); + + } + + else + + poly_InclContour(container, curh); + + } + +} /* InsertHoles */ + + + + + +/****************************************************************/ + +/* routines for collecting result */ + + + +typedef enum + +{ + + FORW, BACKW + +} DIRECTION; + + + +/* Start Rule */ + +typedef int (*S_Rule) (VNODE *, DIRECTION *); + + + +/* Jump Rule */ + +typedef int (*J_Rule) (VNODE *, DIRECTION *); + + + +static + +int UniteS_Rule(VNODE * cur, DIRECTION * initdir) + +{ + + *initdir = FORW; + + return (PLF_ESTATE(cur) == OUTSIDE) || + + (PLF_ESTATE(cur) == SHARED && cur->next->t.link == cur->t.link->next); + +} + + + +static + +int IsectS_Rule(VNODE * cur, DIRECTION * initdir) + +{ + + *initdir = FORW; + + return (PLF_ESTATE(cur) == INSIDE) || + + (PLF_ESTATE(cur) == SHARED && cur->next->t.link == cur->t.link->next); + +} + + + + + +static + +int SubS_Rule(VNODE * cur, DIRECTION * initdir) + +{ + + *initdir = FORW; + + return (PLF_ESTATE(cur) == OUTSIDE) || + + (PLF_ESTATE(cur) == SHARED && cur->next->t.link == cur->t.link->prev); + +} + + + +static + +int SubSlaveS_Rule(VNODE * cur, DIRECTION * initdir) + +{ + + *initdir = BACKW; + + return (PLF_ESTATE(cur) == INSIDE); + +} + + + +static + +int IsectJ_Rule(VNODE * cur, DIRECTION * cdir) + +{ + + assert(*cdir == FORW); + + return (PLF_ESTATE(cur->t.link) == INSIDE); + +} + + + +static + +int UniteJ_Rule(VNODE * cur, DIRECTION * cdir) + +{ + + assert(*cdir == FORW); + + return (PLF_ESTATE(cur) != OUTSIDE && PLF_ESTATE(cur->t.link) == OUTSIDE); + +} + + + +static + +int SubJ_Rule(VNODE * cur, DIRECTION * cdir) + +{ + + if (*cdir == FORW) + + { + + if (PLF_ESTATE(cur->t.link->prev) == INSIDE) + + { + + *cdir = BACKW; + + return TRUE; + + } + + } + + else if (PLF_ESTATE(cur->t.link) == OUTSIDE || + + PLF_ESTATE(cur->t.link) == SHARED) + + { + + *cdir = FORW; + + return TRUE; + + } + + return FALSE; + +} + + + +static + +int Gather(VNODE * start, PLINE ** result, J_Rule j_rule, DIRECTION initdir) + +{ + + VNODE *cur = start, *newn, *cn; + + DIRECTION dir = initdir; + + *result = poly_NewContour(start->point); + + if ( *result == NULL ) return err_no_memory; + + do + + { + + cn = (dir == FORW ? cur : cur->prev); + + cn->Flags = SETBITS( cn, PLF_MARK, PLF_MARK); + + + + /* for SHARED edge mark its neighbour, if the direction + + is the same */ + + if (PLF_ESTATE(cn) == SHARED && cn->t.link->next == cn->next->t.link) + + cn->t.link->Flags |= PLF_MARK; + + + + cur = (dir == FORW ? cur->next : cur->prev); + + + + if (cur->t.link != NULL && j_rule(cur, &dir)) + + cur = cur->t.link; /* jump */ + + if (!vect_equal(cur->point, start->point)) + + { + + if ( (newn = poly_CreateNode(cur->point)) == NULL) + + return err_no_memory; + + poly_InclVertex((*result)->head.prev, newn); + + } + + } while (!vect_equal(cur->point, start->point)); + + return err_ok; + +} /* Gather */ + + + +static + +void Collect(jmp_buf *e, PLINE * a, POLYAREA ** contours, PLINE ** holes, + + S_Rule c_rule, J_Rule j_rule) + +{ + + VNODE *cur; + + PLINE *p = NULL; + + int errc = err_ok; + + DIRECTION dir; + + + + cur = &a->head; + + do + + if ((cur->Flags & PLF_MARK) == 0 && c_rule(cur, &dir)) + + { + + p = NULL; /* start making contour */ + + if ( (errc = Gather(dir == FORW ? cur : cur->next, &p, j_rule, dir)) != err_ok) + + { + + if (p != NULL) poly_DelContour(&p); + + error(errc); + + } + + poly_PreContour(p, TRUE); + + PutContour(e, p, contours, holes); + + } + + while ((cur = cur->next) != &a->head); + +} /* Collect */ + + + +static + +void cntr_Collect(jmp_buf *e, PLINE * A, POLYAREA ** contours, PLINE ** holes, + + int action) + +{ + + PLINE *tmprev; + + + + if (GETBITS(A, PLF_STATUS) == ISECTED) + + { + + switch (action) + + { + + case PBO_UNITE: + + Collect(e, A, contours, holes, UniteS_Rule, UniteJ_Rule); + + break; + + case PBO_ISECT: + + Collect(e, A, contours, holes, IsectS_Rule, IsectJ_Rule); + + break; + + case PBO_XOR: + + case PBO_SUBSLAVE: + + Collect(e, A, contours, holes, SubSlaveS_Rule, SubJ_Rule); + + if (action == PBO_SUBSLAVE) + + break; + + case PBO_SUB: + + Collect(e, A, contours, holes, SubS_Rule, SubJ_Rule); + + break; + + }; + + } + + else + + { + + switch (action) + + { + + case PBO_ISECT: + + if (GETBITS(A, PLF_STATUS) == INSIDE) + + { + + if (!poly_CopyContour(&tmprev, A) ) + + error(err_no_memory); + + poly_PreContour(tmprev, TRUE); + + PutContour(e, tmprev, contours, holes); + + } + + break; + + case PBO_XOR: + + case PBO_SUBSLAVE: + + if (GETBITS(A, PLF_STATUS) == INSIDE) + + { + + if ( !poly_CopyContour(&tmprev, A) ) + + error(err_no_memory); + + poly_PreContour(tmprev, TRUE); + + poly_InvContour(tmprev); + + PutContour(e, tmprev, contours, holes); + + } + + if (action == PBO_SUBSLAVE) + + break; + + case PBO_UNITE: + + case PBO_SUB: + + if (GETBITS(A, PLF_STATUS) == OUTSIDE) + + { + + if ( !poly_CopyContour(&tmprev, A) ) + + error(err_no_memory); + + poly_PreContour(tmprev, TRUE); + + PutContour(e, tmprev, contours, holes); + + } + + break; + + } + + } + +} /* cntr_Collect */ + + + + + +static + +void M_POLYAREA_Collect(jmp_buf *e, POLYAREA * afst, POLYAREA ** contours, PLINE ** holes, + + int action) + +{ + + POLYAREA *a = afst; + + PLINE *cur; + + + + assert(a != NULL); + + do { + + for (cur = a->contours; cur != NULL; cur = cur->next) + + cntr_Collect(e, cur, contours, holes, action); + + } while ((a = a->f) != afst); + +} + + + +/************************************************************************/ + +/* prepares polygon for algorithm, sets UNKNOWN labels and clears MARK bits */ + +static + +void M_InitPolygon(POLYAREA * afst) + +{ + + PLINE *curc; + + VNODE *curn; + + POLYAREA *a = afst; + + + + assert(a != NULL); + + do { + + for (curc = a->contours; curc != NULL; curc = curc->next) + + { + + poly_PreContour(curc, TRUE); + + curc->Flags = SETBITS( curc, PLF_STATUS, UNKNOWN ); + + curn = &curc->head; + + do { + + /* + + PLF_CYCLINK = 0, PLF_MARK = 0, PLF_STATUS = UNKNOWN + + */ + + curn->Flags = SETBITS(curn, PLF_RESERVED, UNKNOWN); + + curn->t.link = NULL; + + } while ((curn = curn->next) != &curc->head); + + } + + } while ((a = a->f) != afst); + +} /* M_InitPolygon */ + + + +/* the main clipping routine */ + +int poly_Boolean(const POLYAREA * a_org, const POLYAREA * b_org, POLYAREA ** res, int action) + +{ + + POLYAREA *a = NULL, *b = NULL; + + PLINE *p, *holes = NULL; + + jmp_buf e; + + int code; + + + + *res = NULL; + + + + if ((code = setjmp(e)) == 0) + + { + + if (!poly_M_Copy0(&a, a_org) || !poly_M_Copy0(&b, b_org)) + + longjmp(e, err_no_memory); + + + + /* prepare polygons */ + + M_InitPolygon(a); + + M_InitPolygon(b); + + + + /*M_POLYAREA_cyclink(a); + + M_POLYAREA_cyclink(b);*/ + + + + M_POLYAREA_intersect(&e, a, b); + + + + M_POLYAREA_label(a, b); + + M_POLYAREA_label(b, a); + + + + M_POLYAREA_Collect(&e, a, res, &holes, action); + + + + if (action == PBO_SUB) + + action = PBO_SUBSLAVE; + + M_POLYAREA_Collect(&e, b, res, &holes, action); + + + + InsertHoles(&e, *res, &holes); + + } + + /* delete holes */ + + while ((p = holes) != NULL) + + { + + holes = p->next; + + poly_DelContour(&p); + + } + + poly_Free(&a); + + poly_Free(&b); + + + + if (code) + + poly_Free(res); + + return code; + +} /* poly_Boolean */ + + + +/********************* MAP OVERLAY **********************/ + + + +static + +BOOL SubMap(POLYMAP *R, POLYMAP *B, POLYMAP **r) + +{ + + POLYMAP *ri; + + for (ri = R; ri != NULL; ri = ri->next) + + { + + POLYAREA *sub = NULL; + + POLYMAP *bi; + + if (!poly_M_Copy0(&sub, ri->area)) + + return 1; + + for (bi = B; bi != NULL; bi = bi->next) + + { + + POLYAREA *t = NULL; + + if (poly_Boolean(sub, bi->area, &t, PBO_SUB)) + + return 1; + + poly_Free(&sub), sub = t; + + } + + if (poly_AddMap(r, sub, ri->label)) + + return 1; + + } + + return 0; + +} /* SubMap */ + + + +BOOL poly_Overlay(POLYMAP *R, POLYMAP *B, + + POLYMAP **r, POLYMAP **b, POLYMAP **p) + +{ + + char res[MAXLABEL + 1]; + + POLYMAP *ri; + + if (R == NULL || B == NULL) return 1; + + + + /* first, find the purple polygons */ + + for (ri = R; ri != NULL; ri = ri->next) + + { + + POLYMAP *bi; + + for (bi = B; bi != NULL; bi = bi->next) + + { + + POLYAREA *rp = NULL; + + if (poly_Boolean(ri->area, bi->area, &rp, PBO_ISECT)) + + return 1; + + + + strcat(strcat(strcpy(res, ri->label), " & "), bi->label); + + if (poly_AddMap(p, rp, res)) + + return 1; + + } + + } + + + + /* find pure red and blue polygons */ + + return SubMap(R, B, r) || SubMap(B, R, b); + +} /* poly_Overlay */ + diff --git a/Utilities/OSSIM/ossim_core/libpolyclip/polyio.c b/Utilities/OSSIM/ossim_core/libpolyclip/polyio.c new file mode 100644 index 0000000000..4b0f5612fa --- /dev/null +++ b/Utilities/OSSIM/ossim_core/libpolyclip/polyio.c @@ -0,0 +1,306 @@ +/* + + poly_Boolean: a polygon clip library + + Copyright (C) 1997 Alexey Nikitin, Michael Leonov + + leonov@propro.ru + + + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + + + polyio.c + + (C) 1997 Michael Leonov + +*/ + + + +#include <stdio.h> + +#include <string.h> + + + +#include "polyarea.h" + +#include "vectmatr.h" + + + +static + +PLINE *LoadPLINE(FILE * f) + +{ + + int cnt, i; + + PLINE *res = NULL; + + Vector v; + + + + fscanf(f, "%d", &cnt); + + if (cnt < 3) return NULL; + + for ( i = 0; i < cnt; i++ ) + + { + + fscanf(f, "%lf %lf", v, v + 1); + + v[2] = 0.0f; + + if ( res == NULL ) + + { + + if ((res = poly_NewContour(v)) == NULL) + + return NULL; + + } + + else + + poly_InclVertex(res->head.prev, poly_CreateNode(v)); + + } + + poly_PreContour(res, TRUE); + + return res; + +} /* LoadPLINE */ + + + +static + +size_t til_eol(const char *str) + +{ + + char *eoln; + + eoln = strchr(str, '\n'); + + return eoln != NULL ? (size_t)(eoln - str) : MAXLABEL; + +} /* til_eol */ + + + +BOOL LoadPOLYMAP(POLYMAP **m, char *fname) + +{ + + int nMaps, k; + + char label[MAXLABEL + 1]; + + FILE *f = fopen( fname, "r" ); + + if (f == NULL) return 1; + + fscanf(f, "%d", &nMaps); + + if (nMaps < 1) return 1; + + for (k = 0; k < nMaps; k++) + + { + + int cnt, pcnt, i, j; + + PLINE *cntr; + + POLYAREA *p; + + POLYAREA *area = NULL; + + + + fgets(label, MAXLABEL, f); + + fgets(label, MAXLABEL, f); + + label[til_eol(label)] = 0; + + fscanf(f, "%d", &pcnt); + + if (pcnt < 1) return 1; + + for (j = 0; j < pcnt; j++) + + { + + fscanf(f, "%d", &cnt); + + if (cnt < 1) return err_bad_parm; + + p = NULL; + + for (i = 0; i < cnt; i++) + + { + + if ( (cntr = LoadPLINE(f)) == NULL) + + return err_bad_parm; + + if ( (cntr->Flags & PLF_ORIENT) != (unsigned int)(i ? PLF_INV : PLF_DIR) ) + + poly_InvContour(cntr); + + if (p == NULL) p = poly_Create(); + + if (p == NULL) return 1; + + poly_InclContour(p, cntr); + + cntr = NULL; + + if (!poly_Valid(p)) return err_bad_parm; + + } + + poly_M_Incl(&area, p); + + } + + if (poly_AddMap(m, area, label)) + + return 1; + + } + + fclose(f); + + return 0; + +} /* LoadPOLYMAP */ + + + +static + +void SavePLINE(FILE * f, PLINE * res) + +{ + + VNODE *cur; + + + + fprintf(f, "%d\n", res->Count); + + cur = &res->head; + + do { + + fprintf(f, "%f %f\n", cur->point[0], cur->point[1] ); + + } while ( ( cur = cur->next ) != &res->head ); + +} /* SavePLINE */ + + + + + +void SavePOLYMAP(POLYMAP *m, char *fname) + +{ + + POLYMAP *mi; + + int i; + + FILE *f = fopen(fname, "w"); + + if (f == NULL) return; + + for (mi = m, i = 0; mi != NULL; mi = mi->next) + + i++; + + fprintf(f, "%d\n", i); + + for (mi = m; mi != NULL; mi = mi->next) + + { + + PLINE *cntr; + + POLYAREA * curpa; + + + + i = 0, curpa = mi->area; + + do { + + i++; + + } while ( (curpa = curpa->f) != mi->area); + + + + fprintf(f, "%s\n", mi->label); + + fprintf(f, "%d\n", i); + + curpa = mi->area; + + do { + + for (cntr = curpa->contours, i = 0; cntr != NULL; cntr = cntr->next) + + i++; + + fprintf(f, "%d\n", i); + + for (cntr = curpa->contours; cntr != NULL; cntr = cntr->next) + + SavePLINE(f, cntr); + + } while ((curpa = curpa->f) != mi->area); + + } + +} /* SavePOLYMAP */ + + + diff --git a/Utilities/OSSIM/ossim_core/libpolyclip/polyio.h b/Utilities/OSSIM/ossim_core/libpolyclip/polyio.h new file mode 100644 index 0000000000..88c40c6117 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/libpolyclip/polyio.h @@ -0,0 +1,40 @@ +/* + poly_Boolean: a polygon clip library + Copyright (C) 1997 Alexey Nikitin, Michael Leonov + leonov@propro.iis.nsk.su + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + polyio.h + (C) 1997 Michael Leonov + +*/ +#ifndef _POLYIO_H +#define _POLYIO_H + +#include "polyarea.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int LoadPOLYAREA( POLYAREA **PA, char * fname); +int SavePOLYAREA( POLYAREA * PA, char * fname); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Utilities/OSSIM/ossim_core/libpolyclip/vectmatr.c b/Utilities/OSSIM/ossim_core/libpolyclip/vectmatr.c new file mode 100644 index 0000000000..72ad959969 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/libpolyclip/vectmatr.c @@ -0,0 +1,823 @@ +/* + + poly_Boolean: a polygon clip library + + Copyright (C) 1997 Alexey Nikitin, Michael Leonov + + leonov@propro.iis.nsk.su + + + + based on: + + graphadd.cc: a polygon clip library + + Copyright (C) 1993 Klamer Schutte + + + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + + + vectmatr.c + + (C) 1997 Alexey Nikitin, Michael Leonov + + (C) 1993,1997 Klamer Schutte + + + + all cases where original (Klamer Schutte) code is present + + are marked + +*/ + + + +#include <stdlib.h> + +#include <math.h> + +#include <assert.h> + + + +#include "vectmatr.h" + + + +#ifndef min + +double + +min(double x, double y) + +{ + + if (x > y) + + return y; + + return x; + +} + +#endif + + + +#ifndef max + +double + +max(double x, double y) + +{ + + if (y > x) + + return y; + + return x; + +} + +#endif + + + +Vector vect_zero = { (double)0, (double)0, (double)0 }; + + + +/*********************************************************************/ + +/* F l o a t V e c t o r S t u f f */ + +/*********************************************************************/ + + + +void vect_init ( Vector v, double x, double y, double z ) + +{ + + v[0] = (double)x; + + v[1] = (double)y; + + v[2] = (double)z; + +} /* vect_init */ + + + +#define Vcopy(a,b) {(a)[0]=(b)[0];(a)[1]=(b)[1];(a)[2]=(b)[2];} + +#define Vzero(a) ((a)[0] == 0. && (a)[1] == 0. && (a)[2] == 0.) + + + +#define Vsub(a,b,c) {(a)[0]=(b)[0]-(c)[0];(a)[1]=(b)[1]-(c)[1];(a)[2]=(b)[2]-(c)[2];} + + + +void vect_copy ( Vector des, Vector sou ) { Vcopy( des, sou ) } /* vect_copy */ + +int vect_equal ( Vector v1, Vector v2 ) + +{ + + return ( v1[0] == v2[0] && v1[1] == v2[1] && v1[2] == v2[2] ); + +} /* vect_equal */ + + + + + +void vect_sub ( Vector res, Vector v1, Vector v2 ) { Vsub( res, v1, v2 ) } /* vect_sub */ + + + +void vect_min ( Vector v1, Vector v2, Vector v3 ) + +{ + + v1[0] = (v2[0] < v3[0]) ? v2[0] : v3[0]; + + v1[1] = (v2[1] < v3[1]) ? v2[1] : v3[1]; + + v1[2] = (v2[2] < v3[2]) ? v2[2] : v3[2]; + +} /* vect_min */ + + + +void vect_max ( Vector v1, Vector v2, Vector v3 ) + +{ + + v1[0] = (v2[0] > v3[0]) ? v2[0] : v3[0]; + + v1[1] = (v2[1] > v3[1]) ? v2[1] : v3[1]; + + v1[2] = (v2[2] > v3[2]) ? v2[2] : v3[2]; + +} /* vect_max */ + + + +/* ///////////////////////////////////////////////////////////////////////////// * / + +/ * 2-Dimentional stuff + +/ * ///////////////////////////////////////////////////////////////////////////// */ + + + + + +#define Vsub2(r,a,b) {(r)[0] = (a)[0] - (b)[0]; (r)[1] = (a)[1] - (b)[1];} + +#define Vadd2(r,a,b) {(r)[0] = (a)[0] + (b)[0]; (r)[1] = (a)[1] + (b)[1];} + +#define Vsca2(r,a,s) {(r)[0] = (a)[0] * (s); (r)[1] = (a)[1] * (s);} + +#define Vcpy2(r,a) {(r)[0] = (a)[0]; (r)[1] = (a)[1];} + +#define Vequ2(a,b) ((a)[0] == (b)[0] && (a)[1] == (b)[1]) + + + +#define Vadds(r,a,b,s) {(r)[0] = ((a)[0] + (b)[0]) * (s); (r)[1] = ((a)[1] + (b)[1]) * (s);} + + + +#define Vswp2(a,b) { double t; \ +t = (a)[0], (a)[0] = (b)[0], (b)[0] = t; \ +t = (a)[1], (a)[1] = (b)[1], (b)[1] = t; \ +} + + + +double vect_len2(Vector v) + +{ + + return sqrt(v[0] * v[0] + v[1] * v[1]); + +} + + + +double vect_dist2(Vector v1, Vector v2) + +{ + + double dx = v1[0] - v2[0]; + + double dy = v1[1] - v2[1]; + + + + return sqrt(dx * dx + dy * dy); + +} + + + +double vect_det2(Vector v1, Vector v2) + +{ + + return ((v1[0] * v2[1]) - (v2[0] * v1[1])); + +} + + + +static + +double vect_m_dist(Vector v1, Vector v2) + +{ + + double dx = v1[0] - v2[0]; + + double dy = v1[1] - v2[1]; + + double dd = sqrt(dx * dx + dy * dy); + + + + if (dx > 0) + + return +dd; + + if (dx < 0) + + return -dd; + + if (dy > 0) + + return +dd; + + return -dd; + +} /* vect_m_dist */ + + + +/* + +RecursiveIsect + + (C) 1993 Klamer Schutte + + (C) 1997 Michael Leonov, Alexey Nikitin + +*/ + + + + + +static + +void RecursiveIsect(Vector p1, Vector p2, Vector q1, Vector q2, Vector ret) + +{ + + /* Find intersection point of p1-p2 and q1-q2 by iteratively taking + + the middle of p1-p2 */ + + + + Vector q, s1, s2, m, tmp; + + double inp; + + + + Vsub2(q, q2, q1); + + + + if (vect_len2(q) < vect_dist2(p2, p1)) + + { + + RecursiveIsect(q1, q2, p1, p2, ret); + + return; + + } + + + + Vsub2(s1, p1, q1); + + Vsub2(s2, p2, q1); + + Vadds(m, s1, s2, 0.5f); + + + + inp = vect_det2(q, s1); + + + + if (inp > 0) + + { + + Vcpy2(tmp, s1); + + Vcpy2(s1, s2); + + Vcpy2(s2, tmp); + + } + + + + while (!Vequ2(m, s1) && !Vequ2(m, s2)) + + { + +/* assert(vect_det2(q, s1) <= 0); */ + +/* assert(vect_det2(q, s2) >= 0); */ + +/* if(vect_det2(q, s1) > 0) */ +/* { */ +/* break; */ +/* } */ + +/* if(vect_det2(q, s2) > 0) */ +/* { */ +/* break; */ +/* } */ + + + + if (vect_det2(q, m) <= 0) + + Vcpy2(s1, m) + + else + + Vcpy2(s2, m) + + + + Vadds(m, s1, s2, 0.5f); + + } + +/* assert(vect_len2(m) <= vect_dist2(q2, q1)); */ + + + + Vadd2(ret, m, q1); + +} /* RecursiveIsect */ + + + +/* + +vect_inters2 + + (C) 1993 Klamer Schutte + + (C) 1997 Michael Leonov, Alexey Nikitin + +*/ + + + +int vect_inters2(Vector p1, Vector p2, Vector q1, Vector q2, + + Vector S1, Vector S2) + +{ + + double rpx, rpy, rqx, rqy, t, deel; + + Vector p, pq1, pq2, q, qp1, qp2, s, qs; + + int c1, c2, c1s, c2s; + + + + if (max(p1[0], p2[0]) < min(q1[0], q2[0]) || + + max(q1[0], q2[0]) < min(p1[0], p2[0])) + + return 0; + + + + S1[2] = S2[2] = 0.0F; + + rpx = p2[0] - p1[0]; + + rpy = p2[1] - p1[1]; + + rqx = q2[0] - q1[0]; + + rqy = q2[1] - q1[1]; + + + + deel = rpx * rqy - rpy * rqx; /* vect_det(rp,rq); */ + + + + /* every value below EPSILON is considered as being 0. + + * Hence, we do not introduce numerical inaccuracies + + */ + + + + if (fabs(deel) < EPSILON) /* parallel */ + + { + + double inpr, dc1, dc2, d1, d2, h; /* Check too see whether p1-p2 and q1-q2 are on the same line */ + + Vector hp1, hq1, hp2, hq2, q1p1, q1q2; + + + + Vsub2(q1p1, q1, p1); + + Vsub2(q1q2, q1, q2); + + + + inpr = vect_det2(q1p1, q1q2); + + + + /* If this product is not zero then p1 is not on q1-q2! */ + + if (fabs(inpr) > EPSILON) + + return 0; + + dc1 = 0; /* m_len(p1 - p1) */ + + + + dc2 = vect_m_dist(p1, p2); + + d1 = vect_m_dist(p1, q1); + + d2 = vect_m_dist(p1, q2); + + + +/* Sorting the independent points from small to large: */ + + Vcpy2(hp1, p1); + + Vcpy2(hp2, p2); + + Vcpy2(hq1, q1); + + Vcpy2(hq2, q2); + + if (dc1 > dc2) + + { /* hv and h are used as help-variable. */ + + Vswp2(hp1, hp2); + + h = dc1, dc1 = dc2, dc2 = h; + + } + + if (d1 > d2) + + { + + Vswp2(hq1, hq2); + + h = d1, d1 = d2, d2 = h; + + } + + + +/* Now the line-pieces are compared: */ + + + + if (dc1 < d1) + + { + + if (dc2 < d1) + + return 0; + + if (dc2 < d2) { Vcpy2(S1, hp2); Vcpy2(S2, hq1); } + + else { Vcpy2(S1, hq1); Vcpy2(S2, hq2); }; + + } + + else + + { + + if (dc1 > d2) + + return 0; + + if (dc2 < d2) { Vcpy2(S1, hp1); Vcpy2(S2, hp2); } + + else { Vcpy2(S1, hp1); Vcpy2(S2, hq2); }; + + } + + return (Vequ2(S1, S2) ? 1 : 2); + + } + + else + + { /* not parallel */ + + /* + + * We have the lines: + + * l1: p1 + s(p2 - p1) + + * l2: q1 + t(q2 - q1) + + * And we want to know the intersection point. + + * Calculate t: + + * p1 + s(p2-p1) = q1 + t(q2-q1) + + * which is similar to the two equations: + + * p1x + s * rpx = q1x + t * rqx + + * p1y + s * rpy = q1y + t * rqy + + * Multiplying these by rpy resp. rpx gives: + + * rpy * p1x + s * rpx * rpy = rpy * q1x + t * rpy * rqx + + * rpx * p1y + s * rpx * rpy = rpx * q1y + t * rpx * rqy + + * Subtracting these gives: + + * rpy * p1x - rpx * p1y = rpy * q1x - rpx * q1y + t * ( rpy * rqx - rpx * rqy ) + + * So t can be isolated: + + * t = (rpy * ( p1x - q1x ) + rpx * ( - p1y + q1y )) / ( rpy * rqx - rpx * rqy ) + + * and deel = rpx * rqy - rpy * rqx + + */ + + double inp1, inp2, inp3, inp4, inp1s, inp2s, inp3s, inp4s; + + + + + + if (Vequ2(q1, p1) || Vequ2(q1, p2)) Vcpy2(S1, q1) else + + if (Vequ2(q2, p1) || Vequ2(q2, p2)) Vcpy2(S1, q2) else + + { + + t = -(rpy * (-q1[0] + p1[0]) + rpx * (q1[1] - p1[1])) / deel; + + S1[0] = (double) (q1[0] + t * rqx); + + S1[1] = (double) (q1[1] + t * rqy); + + } + +/* + + * The intersection point is valid if it is + + * 1) on q1-q2 --> t >= 0 && t <= 1 + + * 2) on p1-p2 --> p1 must be on the other side of q1-q2 as p2 + + * This is so if the difference of the x coordinate of p1-s1 has the + + * opposite sign as the x coordinate of p2-s2. So the multiplication of + + * these two must be negative. This might fail if p1-p2 is a vertical line; + + * this can be solved by adding the same product for the y coordinates + + */ + + Vsub2(p, p2, p1); + + Vsub2(pq1, q1, p1); + + Vsub2(pq2, q2, p1); + + inp1 = vect_det2(p, pq1); + + inp2 = vect_det2(p, pq2); + + c1 = inp1 * inp2 <= 0; + + + + Vsub2(q, q2, q1); + + Vsub2(qp1, p1, q1); + + Vsub2(qp2, p2, q1); + + + + inp3 = vect_det2(q, qp1); + + inp4 = vect_det2(q, qp2); + + c2 = inp3 * inp4 <= 0; + + + + { + + double l_q, l_p; + + /* Say that *S1 equals one of the points if the relative + + distance is smaller than EPSILON */ + + l_q = vect_dist2(q1, q2); + + l_p = vect_dist2(p1, p2); + + if (EPSILON > vect_dist2(S1, p2) / l_p) + + { + + *S1 = *p2; + + c2 = 2; + + } + + else if (EPSILON > vect_dist2(S1, p1) / l_p) + + { + + *S1 = *p1; + + c2 = 2; + + } + + else + + { + + if (EPSILON > vect_dist2(S1, q2) / l_q) + + { + + *S1 = *q2; + + c1 = 2; + + } + + else if (EPSILON > vect_dist2(S1, q1) / l_q) + + { + + *S1 = *q1; + + c1 = 2; + + } + + } + + } + + Vsub2(s, S1, p1); + + inp1s = vect_det2(s, pq1); + + inp2s = vect_det2(s, pq2); + + c1s = Vequ2(S1, p1) ? -1 : inp1s * inp2s <= 0; + + + + Vsub2(qs, S1, q1); + + inp3s = vect_det2(qs, qp1); + + inp4s = vect_det2(qs, qp2); + + c2s = Vequ2(S1, q1) ? -1 : inp3s * inp4s <= 0; + + { + + int failed = 0; /* Roundig errors might make the statements below untrue */ + + + + if (!((c1 == 0) || (c2 == 0) || (c1s == (c1 != 0)) || (c1s == -1))) + + failed = 1; + + else if (!((c1 == 0) || (c2 == 0) || (c2s == (c2 != 0)) || (c2s == -1))) + + failed = 2; + + else if (c1 && c2 && (vect_dist2(S1, q1) > vect_dist2(q2, q1))) + + failed = 3; + + else if (c1 && c2 && (vect_dist2(S1, q2) > vect_dist2(q2, q1))) + + failed = 4; + + else if (c1 && c2 && (vect_dist2(S1, p1) > vect_dist2(p2, p1))) + + failed = 5; + + else if (c1 && c2 && (vect_dist2(S1, p2) > vect_dist2(p2, p1))) + + failed = 6; + + if ((failed >= 3) && (c1 == 2 || c2 == 2)) + + { + + failed = -1; + + c1 = c2 = 0; + + } + + if (failed > 0) + + RecursiveIsect(p1, p2, q1, q2, S1); + + return (c1 && c2); + + } + + } + +} /* vect_inters2 */ + + + +/* end of VECTMATR.C */ + diff --git a/Utilities/OSSIM/ossim_core/libpolyclip/vectmatr.h b/Utilities/OSSIM/ossim_core/libpolyclip/vectmatr.h new file mode 100644 index 0000000000..2a44356da2 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/libpolyclip/vectmatr.h @@ -0,0 +1,190 @@ +/* + + poly_Boolean: a polygon clip library + + Copyright (C) 1997 Alexey Nikitin, Michael Leonov + + leonov@propro.iis.nsk.su + + + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + + + vectmatr.h + + (C) 1997 Alexey Nikitin, Michael Leonov + + (C) 1993,1997 Klamer Schutte + + + +*/ + + + +#ifndef VECTOR_MATRIX_H + +#define VECTOR_MATRIX_H + + + + + +#ifdef __cplusplus + +extern "C" { + +#endif + + + +typedef int BOOL; + + + +#ifndef FALSE + +enum { + + FALSE = 0, + + TRUE = 1 + +}; + +#endif + + + +#ifndef min + +double min(double x, double y); + +#endif + + + +#ifndef max + +double max(double x, double y); + +#endif + + + + + +typedef double vertex[3]; /* floating point representation of + + coordinates */ + +typedef vertex Vector; + + + +#define VertexEqu(a,b) (memcmp((a),(b),sizeof(Vector))==0) + +#define VertexCpy(a,b) memcpy((a),(b),sizeof(Vector)) + + + + + +extern Vector vect_zero; + + + +/*********************************************************************/ + +/* F l o a t V e c t o r S t u f f */ + +/*********************************************************************/ + + + +int vect_equal ( Vector v1, Vector v2 ); + +void vect_copy ( Vector des, Vector sou ); + +void vect_init ( Vector v, double x, double y, double z); + +void vect_sub( Vector res, Vector v2, Vector v3 ); + + + +void vect_min( Vector res, Vector v2, Vector v3 ); + +void vect_max( Vector res, Vector v2, Vector v3 ); + + + +#define TNY 1e-6 + + + +#ifndef EPSILON + +#define EPSILON TNY + +#endif + + + +double vect_dist2(Vector v1, Vector v2); + +double vect_det2(Vector v1, Vector v2); + +double vect_len2(Vector v1); + + + +int vect_inters2(Vector A, Vector B, Vector C, Vector D, Vector S1, Vector S2); + + + +/**************************************************************************** + +* Calcs the intersection point of AB and BC. Returns if they hit each other + +* and the position of the hit(s) (S1 (and S2)) + +*****************************************************************************/ + + + +#ifdef __cplusplus + +} + +#endif + + + +#endif /* VECTOR_MATRIX_H */ + diff --git a/Utilities/OSSIM/ossim_core/matrix/.cvsignore b/Utilities/OSSIM/ossim_core/matrix/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/matrix/CMakeLists.txt b/Utilities/OSSIM/ossim_core/matrix/CMakeLists.txt new file mode 100644 index 0000000000..4291125170 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/CMakeLists.txt @@ -0,0 +1,6 @@ +FILE(GLOB_RECURSE ossim_matrix_SRCS "*.cpp") +FILE(GLOB_RECURSE ossim_matrix_HDRS "*.h") +ADD_LIBRARY(ossim_matrix ${ossim_matrix_SRCS}) + +INSTALL_TARGETS(/lib/otb/ ossim_matrix) +INSTALL_FILES(/include/otb/Utilities/OSSIM/ossim_core/ "\\.h$" ${ossim_matrix_HRDS}) diff --git a/Utilities/OSSIM/ossim_core/matrix/bandmat.cpp b/Utilities/OSSIM/ossim_core/matrix/bandmat.cpp new file mode 100644 index 0000000000..22ef71395d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/bandmat.cpp @@ -0,0 +1,569 @@ +//$$ bandmat.cpp Band matrix definitions + +// Copyright (C) 1991,2,3,4,9: R B Davies + +#define WANT_MATH // include.h will get math fns + +//#define WANT_STREAM + +#include "include.h" + +#include "newmat.h" +#include "newmatrc.h" + +#ifdef use_namespace +namespace NEWMAT { +#endif + + + +#ifdef DO_REPORT +#define REPORT { static ExeCounter ExeCount(__LINE__,10); ++ExeCount; } +#else +#define REPORT {} +#endif + +static inline int my_min(int x, int y) { return x < y ? x : y; } +static inline int my_max(int x, int y) { return x > y ? x : y; } + + +BandMatrix::BandMatrix(const BaseMatrix& M) +{ + REPORT // CheckConversion(M); + // MatrixConversionCheck mcc; + GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::BM); + GetMatrix(gmx); CornerClear(); +} + +void BandMatrix::SetParameters(const GeneralMatrix* gmx) +{ + REPORT + MatrixBandWidth bw = gmx->BandWidth(); + lower = bw.lower; upper = bw.upper; +} + +void BandMatrix::ReSize(int n, int lb, int ub) +{ + REPORT + Tracer tr("BandMatrix::ReSize"); + if (lb<0 || ub<0) Throw(ProgramException("Undefined bandwidth")); + lower = (lb<=n) ? lb : n-1; upper = (ub<=n) ? ub : n-1; + GeneralMatrix::ReSize(n,n,n*(lower+1+upper)); CornerClear(); +} + +// SimpleAddOK shows when we can add etc two matrices by a simple vector add +// and when we can add one matrix into another +// *gm must be the same type as *this +// return 0 if simple add is OK +// return 1 if we can add into *gm only +// return 2 if we can add into *this only +// return 3 if we can't add either way +// For SP this will still be valid if we swap 1 and 2 + +short BandMatrix::SimpleAddOK(const GeneralMatrix* gm) +{ + const BandMatrix* bm = (const BandMatrix*)gm; + if (bm->lower == lower && bm->upper == upper) { REPORT return 0; } + else if (bm->lower >= lower && bm->upper >= upper) { REPORT return 1; } + else if (bm->lower <= lower && bm->upper <= upper) { REPORT return 2; } + else { REPORT return 3; } +} + +short SymmetricBandMatrix::SimpleAddOK(const GeneralMatrix* gm) +{ + const SymmetricBandMatrix* bm = (const SymmetricBandMatrix*)gm; + if (bm->lower == lower) { REPORT return 0; } + else if (bm->lower > lower) { REPORT return 1; } + else { REPORT return 2; } +} + +void UpperBandMatrix::ReSize(int n, int lb, int ub) +{ + REPORT + if (lb != 0) + { + Tracer tr("UpperBandMatrix::ReSize"); + Throw(ProgramException("UpperBandMatrix with non-zero lower band" )); + } + BandMatrix::ReSize(n, lb, ub); +} + +void LowerBandMatrix::ReSize(int n, int lb, int ub) +{ + REPORT + if (ub != 0) + { + Tracer tr("LowerBandMatrix::ReSize"); + Throw(ProgramException("LowerBandMatrix with non-zero upper band" )); + } + BandMatrix::ReSize(n, lb, ub); +} + +void BandMatrix::ReSize(const GeneralMatrix& A) +{ + REPORT + int n = A.Nrows(); + if (n != A.Ncols()) + { + Tracer tr("BandMatrix::ReSize(GM)"); + Throw(NotSquareException(*this)); + } + MatrixBandWidth mbw = A.BandWidth(); + ReSize(n, mbw.Lower(), mbw.Upper()); +} + +bool BandMatrix::SameStorageType(const GeneralMatrix& A) const +{ + if (Type() != A.Type()) { REPORT return false; } + REPORT + return BandWidth() == A.BandWidth(); +} + +void BandMatrix::ReSizeForAdd(const GeneralMatrix& A, const GeneralMatrix& B) +{ + REPORT + Tracer tr("BandMatrix::ReSizeForAdd"); + MatrixBandWidth A_BW = A.BandWidth(); MatrixBandWidth B_BW = B.BandWidth(); + if ((A_BW.Lower() < 0) | (A_BW.Upper() < 0) | (B_BW.Lower() < 0) + | (A_BW.Upper() < 0)) + Throw(ProgramException("Can't ReSize to BandMatrix" )); + // already know A and B are square + ReSize(A.Nrows(), my_max(A_BW.Lower(), B_BW.Lower()), + my_max(A_BW.Upper(), B_BW.Upper())); +} + +void BandMatrix::ReSizeForSP(const GeneralMatrix& A, const GeneralMatrix& B) +{ + REPORT + Tracer tr("BandMatrix::ReSizeForSP"); + MatrixBandWidth A_BW = A.BandWidth(); MatrixBandWidth B_BW = B.BandWidth(); + if ((A_BW.Lower() < 0) | (A_BW.Upper() < 0) | (B_BW.Lower() < 0) + | (A_BW.Upper() < 0)) + Throw(ProgramException("Can't ReSize to BandMatrix" )); + // already know A and B are square + ReSize(A.Nrows(), my_min(A_BW.Lower(), B_BW.Lower()), + my_min(A_BW.Upper(), B_BW.Upper())); +} + + +void BandMatrix::operator=(const BaseMatrix& X) +{ + REPORT // CheckConversion(X); + // MatrixConversionCheck mcc; + Eq(X,MatrixType::BM); CornerClear(); +} + +void BandMatrix::CornerClear() const +{ + // set unused parts of BandMatrix to zero + REPORT + int i = lower; Real* s = store; int bw = lower + 1 + upper; + while (i) + { int j = i--; Real* sj = s; s += bw; while (j--) *sj++ = 0.0; } + i = upper; s = store + storage; + while (i) + { int j = i--; Real* sj = s; s -= bw; while (j--) *(--sj) = 0.0; } +} + +MatrixBandWidth MatrixBandWidth::operator+(const MatrixBandWidth& bw) const +{ + REPORT + int l = bw.lower; int u = bw.upper; + l = (lower < 0 || l < 0) ? -1 : (lower > l) ? lower : l; + u = (upper < 0 || u < 0) ? -1 : (upper > u) ? upper : u; + return MatrixBandWidth(l,u); +} + +MatrixBandWidth MatrixBandWidth::operator*(const MatrixBandWidth& bw) const +{ + REPORT + int l = bw.lower; int u = bw.upper; + l = (lower < 0 || l < 0) ? -1 : lower+l; + u = (upper < 0 || u < 0) ? -1 : upper+u; + return MatrixBandWidth(l,u); +} + +MatrixBandWidth MatrixBandWidth::minimum(const MatrixBandWidth& bw) const +{ + REPORT + int l = bw.lower; int u = bw.upper; + if ((lower >= 0) && ( (l < 0) || (l > lower) )) l = lower; + if ((upper >= 0) && ( (u < 0) || (u > upper) )) u = upper; + return MatrixBandWidth(l,u); +} + +UpperBandMatrix::UpperBandMatrix(const BaseMatrix& M) +{ + REPORT // CheckConversion(M); + // MatrixConversionCheck mcc; + GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::UB); + GetMatrix(gmx); CornerClear(); +} + +void UpperBandMatrix::operator=(const BaseMatrix& X) +{ + REPORT // CheckConversion(X); + // MatrixConversionCheck mcc; + Eq(X,MatrixType::UB); CornerClear(); +} + +LowerBandMatrix::LowerBandMatrix(const BaseMatrix& M) +{ + REPORT // CheckConversion(M); + // MatrixConversionCheck mcc; + GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::LB); + GetMatrix(gmx); CornerClear(); +} + +void LowerBandMatrix::operator=(const BaseMatrix& X) +{ + REPORT // CheckConversion(X); + // MatrixConversionCheck mcc; + Eq(X,MatrixType::LB); CornerClear(); +} + +BandLUMatrix::BandLUMatrix(const BaseMatrix& m) +{ + REPORT + Tracer tr("BandLUMatrix"); + storage2 = 0; store2 = 0; // in event of exception during build + GeneralMatrix* gm = ((BaseMatrix&)m).Evaluate(MatrixType::BM); + m1 = ((BandMatrix*)gm)->lower; m2 = ((BandMatrix*)gm)->upper; + GetMatrix(gm); + if (nrows!=ncols) Throw(NotSquareException(*this)); + d = true; sing = false; + indx = new int [nrows]; MatrixErrorNoSpace(indx); + MONITOR_INT_NEW("Index (BndLUMat)",nrows,indx) + storage2 = nrows * m1; + store2 = new Real [storage2]; MatrixErrorNoSpace(store2); + MONITOR_REAL_NEW("Make (BandLUMat)",storage2,store2) + ludcmp(); +} + +BandLUMatrix::~BandLUMatrix() +{ + REPORT + MONITOR_INT_DELETE("Index (BndLUMat)",nrows,indx) + MONITOR_REAL_DELETE("Delete (BndLUMt)",storage2,store2) + delete [] indx; delete [] store2; +} + +MatrixType BandLUMatrix::Type() const { REPORT return MatrixType::BC; } + + +LogAndSign BandLUMatrix::LogDeterminant() const +{ + REPORT + if (sing) return 0.0; + Real* a = store; int w = m1+1+m2; LogAndSign sum; int i = nrows; + // while (i--) { sum *= *a; a += w; } + if (i) for (;;) { sum *= *a; if (!(--i)) break; a += w; } + if (!d) sum.ChangeSign(); return sum; +} + +GeneralMatrix* BandMatrix::MakeSolver() +{ + REPORT + GeneralMatrix* gm = new BandLUMatrix(*this); + MatrixErrorNoSpace(gm); gm->ReleaseAndDelete(); return gm; +} + + +void BandLUMatrix::ludcmp() +{ + REPORT + Real* a = store2; int i = storage2; + // clear store2 - so unused locations are always zero - + // required by operator== + while (i--) *a++ = 0.0; + a = store; + i = m1; int j = m2; int k; int n = nrows; int w = m1 + 1 + m2; + while (i) + { + Real* ai = a + i; + k = ++j; while (k--) *a++ = *ai++; + k = i--; while (k--) *a++ = 0.0; + } + + a = store; int l = m1; + for (k=0; k<n; k++) + { + Real x = *a; i = k; Real* aj = a; + if (l < n) l++; + for (j=k+1; j<l; j++) + { aj += w; if (fabs(x) < fabs(*aj)) { x = *aj; i = j; } } + indx[k] = i; + if (x==0) { sing = true; return; } + if (i!=k) + { + d = !d; Real* ak = a; Real* ai = store + i * w; j = w; + while (j--) { x = *ak; *ak++ = *ai; *ai++ = x; } + } + aj = a + w; Real* m = store2 + m1 * k; + for (j=k+1; j<l; j++) + { + *m++ = x = *aj / *a; i = w; Real* ak = a; + while (--i) { Real* aj1 = aj++; *aj1 = *aj - x * *(++ak); } + *aj++ = 0.0; + } + a += w; + } +} + +void BandLUMatrix::lubksb(Real* B, int mini) +{ + REPORT + Tracer tr("BandLUMatrix::lubksb"); + if (sing) Throw(SingularException(*this)); + int n = nrows; int l = m1; int w = m1 + 1 + m2; + + for (int k=0; k<n; k++) + { + int i = indx[k]; + if (i!=k) { Real x=B[k]; B[k]=B[i]; B[i]=x; } + if (l<n) l++; + Real* m = store2 + k*m1; Real* b = B+k; Real* bi = b; + for (i=k+1; i<l; i++) *(++bi) -= *m++ * *b; + } + + l = -m1; + for (int i = n-1; i>=mini; i--) + { + Real* b = B + i; Real* bk = b; Real x = *bk; + Real* a = store + w*i; Real y = *a; + int k = l+m1; while (k--) x -= *(++a) * *(++bk); + *b = x / y; + if (l < m2) l++; + } +} + +void BandLUMatrix::Solver(MatrixColX& mcout, const MatrixColX& mcin) +{ + REPORT + int i = mcin.skip; Real* el = mcin.data-i; Real* el1=el; + while (i--) *el++ = 0.0; + el += mcin.storage; i = nrows - mcin.skip - mcin.storage; + while (i--) *el++ = 0.0; + lubksb(el1, mcout.skip); +} + +// Do we need check for entirely zero output? + + +void UpperBandMatrix::Solver(MatrixColX& mcout, + const MatrixColX& mcin) +{ + REPORT + int i = mcin.skip-mcout.skip; Real* elx = mcin.data-i; + while (i-- > 0) *elx++ = 0.0; + int nr = mcin.skip+mcin.storage; + elx = mcin.data+mcin.storage; Real* el = elx; + int j = mcout.skip+mcout.storage-nr; i = nr-mcout.skip; + while (j-- > 0) *elx++ = 0.0; + + Real* Ael = store + (upper+1)*(i-1)+1; j = 0; + if (i > 0) for(;;) + { + elx = el; Real sum = 0.0; int jx = j; + while (jx--) sum += *(--Ael) * *(--elx); + elx--; *elx = (*elx - sum) / *(--Ael); + if (--i <= 0) break; + if (j<upper) Ael -= upper - (++j); else el--; + } +} + +void LowerBandMatrix::Solver(MatrixColX& mcout, + const MatrixColX& mcin) +{ + REPORT + int i = mcin.skip-mcout.skip; Real* elx = mcin.data-i; + while (i-- > 0) *elx++ = 0.0; + int nc = mcin.skip; i = nc+mcin.storage; elx = mcin.data+mcin.storage; + int nr = mcout.skip+mcout.storage; int j = nr-i; i = nr-nc; + while (j-- > 0) *elx++ = 0.0; + + Real* el = mcin.data; Real* Ael = store + (lower+1)*nc + lower; j = 0; + if (i > 0) for(;;) + { + elx = el; Real sum = 0.0; int jx = j; + while (jx--) sum += *Ael++ * *elx++; + *elx = (*elx - sum) / *Ael++; + if (--i <= 0) break; + if (j<lower) Ael += lower - (++j); else el++; + } +} + + +LogAndSign BandMatrix::LogDeterminant() const +{ + REPORT + BandLUMatrix C(*this); return C.LogDeterminant(); +} + +LogAndSign LowerBandMatrix::LogDeterminant() const +{ + REPORT + int i = nrows; LogAndSign sum; Real* s = store + lower; int j = lower + 1; +// while (i--) { sum *= *s; s += j; } + if (i) for (;;) { sum *= *s; if (!(--i)) break; s += j; } + ((GeneralMatrix&)*this).tDelete(); return sum; +} + +LogAndSign UpperBandMatrix::LogDeterminant() const +{ + REPORT + int i = nrows; LogAndSign sum; Real* s = store; int j = upper + 1; +// while (i--) { sum *= *s; s += j; } + if (i) for (;;) { sum *= *s; if (!(--i)) break; s += j; } + ((GeneralMatrix&)*this).tDelete(); return sum; +} + +GeneralMatrix* SymmetricBandMatrix::MakeSolver() +{ + REPORT + GeneralMatrix* gm = new BandLUMatrix(*this); + MatrixErrorNoSpace(gm); gm->ReleaseAndDelete(); return gm; +} + +SymmetricBandMatrix::SymmetricBandMatrix(const BaseMatrix& M) +{ + REPORT // CheckConversion(M); + // MatrixConversionCheck mcc; + GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::SB); + GetMatrix(gmx); +} + +GeneralMatrix* SymmetricBandMatrix::Transpose(TransposedMatrix*, MatrixType mt) +{ REPORT return Evaluate(mt); } + +LogAndSign SymmetricBandMatrix::LogDeterminant() const +{ + REPORT + BandLUMatrix C(*this); return C.LogDeterminant(); +} + +void SymmetricBandMatrix::SetParameters(const GeneralMatrix* gmx) +{ REPORT lower = gmx->BandWidth().lower; } + +void SymmetricBandMatrix::ReSize(int n, int lb) +{ + REPORT + Tracer tr("SymmetricBandMatrix::ReSize"); + if (lb<0) Throw(ProgramException("Undefined bandwidth")); + lower = (lb<=n) ? lb : n-1; + GeneralMatrix::ReSize(n,n,n*(lower+1)); +} + +void SymmetricBandMatrix::ReSize(const GeneralMatrix& A) +{ + REPORT + int n = A.Nrows(); + if (n != A.Ncols()) + { + Tracer tr("SymmetricBandMatrix::ReSize(GM)"); + Throw(NotSquareException(*this)); + } + MatrixBandWidth mbw = A.BandWidth(); int b = mbw.Lower(); + if (b != mbw.Upper()) + { + Tracer tr("SymmetricBandMatrix::ReSize(GM)"); + Throw(ProgramException("Upper and lower band-widths not equal")); + } + ReSize(n, b); +} + +bool SymmetricBandMatrix::SameStorageType(const GeneralMatrix& A) const +{ + if (Type() != A.Type()) { REPORT return false; } + REPORT + return BandWidth() == A.BandWidth(); +} + +void SymmetricBandMatrix::ReSizeForAdd(const GeneralMatrix& A, + const GeneralMatrix& B) +{ + REPORT + Tracer tr("SymmetricBandMatrix::ReSizeForAdd"); + MatrixBandWidth A_BW = A.BandWidth(); MatrixBandWidth B_BW = B.BandWidth(); + if ((A_BW.Lower() < 0) | (B_BW.Lower() < 0)) + Throw(ProgramException("Can't ReSize to SymmetricBandMatrix" )); + // already know A and B are square + ReSize(A.Nrows(), my_max(A_BW.Lower(), B_BW.Lower())); +} + +void SymmetricBandMatrix::ReSizeForSP(const GeneralMatrix& A, + const GeneralMatrix& B) +{ + REPORT + Tracer tr("SymmetricBandMatrix::ReSizeForSP"); + MatrixBandWidth A_BW = A.BandWidth(); MatrixBandWidth B_BW = B.BandWidth(); + if ((A_BW.Lower() < 0) | (B_BW.Lower() < 0)) + Throw(ProgramException("Can't ReSize to SymmetricBandMatrix" )); + // already know A and B are square + ReSize(A.Nrows(), my_min(A_BW.Lower(), B_BW.Lower())); +} + + +void SymmetricBandMatrix::operator=(const BaseMatrix& X) +{ + REPORT // CheckConversion(X); + // MatrixConversionCheck mcc; + Eq(X,MatrixType::SB); +} + +void SymmetricBandMatrix::CornerClear() const +{ + // set unused parts of BandMatrix to zero + REPORT + int i = lower; Real* s = store; int bw = lower + 1; + if (i) for(;;) + { + int j = i; + Real* sj = s; + while (j--) *sj++ = 0.0; + if (!(--i)) break; + s += bw; + } +} + +MatrixBandWidth SymmetricBandMatrix::BandWidth() const + { REPORT return MatrixBandWidth(lower,lower); } + +inline Real square(Real x) { return x*x; } + + +Real SymmetricBandMatrix::SumSquare() const +{ + REPORT + CornerClear(); + Real sum1=0.0; Real sum2=0.0; Real* s=store; int i=nrows; int l=lower; + while (i--) + { int j = l; while (j--) sum2 += square(*s++); sum1 += square(*s++); } + ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2; +} + +Real SymmetricBandMatrix::SumAbsoluteValue() const +{ + REPORT + CornerClear(); + Real sum1=0.0; Real sum2=0.0; Real* s=store; int i=nrows; int l=lower; + while (i--) + { int j = l; while (j--) sum2 += fabs(*s++); sum1 += fabs(*s++); } + ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2; +} + +Real SymmetricBandMatrix::Sum() const +{ + REPORT + CornerClear(); + Real sum1=0.0; Real sum2=0.0; Real* s=store; int i=nrows; int l=lower; + while (i--) + { int j = l; while (j--) sum2 += *s++; sum1 += *s++; } + ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2; +} + + +#ifdef use_namespace +} +#endif + diff --git a/Utilities/OSSIM/ossim_core/matrix/bc.mak b/Utilities/OSSIM/ossim_core/matrix/bc.mak new file mode 100644 index 0000000000..84cf701b3b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/bc.mak @@ -0,0 +1,202 @@ +.AUTODEPEND + +BORLANDPATH = F:\BC5 + +TASM = TASM +TLIB = tlib +TLINK = tlink +LIBPATH = $(BORLANDPATH)\LIB +INCLUDEPATH = $(BORLANDPATH)\INCLUDE + +CCX = bcc -ml -wpro -weas -wpre -I$(INCLUDEPATH) -D + +CC = bcc -W- -v- -H- -x- -3 -N -Og -Oi -Ov -vGd- -vGt- -ml -f -I$(INCLUDEPATH) + +everything: tmt.exe example.exe nl_ex.exe sl_ex.exe garch.exe test_exc.exe + + +.cpp.obj: + $(CC) -c {$< } + +OBJ_LIB = bandmat.obj cholesky.obj evalue.obj fft.obj hholder.obj \ + jacobi.obj myexcept.obj newmat1.obj newmat2.obj newmat3.obj \ + newmat4.obj newmat5.obj newmat6.obj newmat7.obj newmat8.obj \ + newmat9.obj newmatex.obj newmatnl.obj newmatrm.obj solution.obj \ + sort.obj submat.obj svd.obj newfft.obj + +newmat.lib: $(OBJ_LIB) + erase newmat.lib + $(TLIB) newmat.lib /P32 +newmat1 +newmat2 +newmat3 +newmat4 +newmat5 +newmat6 + $(TLIB) newmat.lib /P32+newmat7 +newmat8 +newmat9 +svd +fft +hholder +sort + $(TLIB) newmat.lib /P32+cholesky +submat +jacobi +evalue +bandmat +myexcept + $(TLIB) newmat.lib /P32+solution +newmatnl +newmatrm +newmatex +newfft + +OBJ_T = tmt.obj tmt1.obj tmt2.obj tmt3.obj tmt4.obj tmt5.obj tmt6.obj \ + tmt7.obj tmt8.obj tmt9.obj tmta.obj tmtb.obj tmtc.obj tmtd.obj tmte.obj \ + tmtf.obj tmtg.obj tmth.obj tmti.obj tmtj.obj tmtk.obj tmtl.obj + + +tmt.exe: newmat.lib $(OBJ_T) + $(TLINK) /x/L$(LIBPATH) -Tde @&&| +c0l.obj+tmt.obj+tmt1.obj+tmt2.obj+tmt3.obj+tmt4.obj+tmt5.obj+tmt6.obj+ + tmt7.obj+tmt8.obj+tmt9.obj+tmta.obj+tmtb.obj+tmtc.obj+tmtd.obj+tmte.obj+ + tmtf.obj+tmtg.obj+tmth.obj+tmti.obj+tmtj.obj+tmtk.obj+tmtl.obj+newmat.lib + tmt + # no map file + bidsl.lib+emu.lib+mathl.lib+cl.lib + +| + + +example.exe: newmat.lib example.obj + $(TLINK) /x/L$(LIBPATH) -Tde @&&| +c0l.obj+example.obj+newmat.lib + example + # no map file + bidsl.lib+emu.lib+mathl.lib+cl.lib + +| + + +nl_ex.exe: newmat.lib nl_ex.obj + $(TLINK) /x/L$(LIBPATH) -Tde @&&| +c0l.obj+nl_ex.obj+newmat.lib + nl_ex + # no map file + bidsl.lib+emu.lib+mathl.lib+cl.lib + +| + + +sl_ex.exe: newmat.lib sl_ex.obj + $(TLINK) /x/L$(LIBPATH) -Tde @&&| +c0l.obj+sl_ex.obj+newmat.lib + sl_ex + # no map file + bidsl.lib+emu.lib+mathl.lib+cl.lib + +| + + +garch.exe: newmat.lib garch.obj + $(TLINK) /x/L$(LIBPATH) -Tde @&&| +c0l.obj+garch.obj+newmat.lib + garch + # no map file + bidsl.lib+emu.lib+mathl.lib+cl.lib + +| + +test_exc.exe: newmat.lib test_exc.obj + $(TLINK) /x/L$(LIBPATH) -Tde @&&| +c0l.obj+test_exc.obj+newmat.lib + test_exc + # no map file + bidsl.lib+emu.lib+mathl.lib+cl.lib + +| + + +bandmat.obj: bandmat.cpp + +cholesky.obj: cholesky.cpp + +evalue.obj: evalue.cpp + +myexcept.obj: myexcept.cpp + +fft.obj: fft.cpp + +newfft.obj: newfft.cpp + +hholder.obj: hholder.cpp + +jacobi.obj: jacobi.cpp + +newmat1.obj: newmat1.cpp + +newmat2.obj: newmat2.cpp + +newmat3.obj: newmat3.cpp + +newmat4.obj: newmat4.cpp + +newmat5.obj: newmat5.cpp + +newmat6.obj: newmat6.cpp + +newmat7.obj: newmat7.cpp + +newmat8.obj: newmat8.cpp + +newmat9.obj: newmat9.cpp + +newmatex.obj: newmatex.cpp + +newmatrm.obj: newmatrm.cpp + +newmatnl.obj: newmatnl.cpp + +sort.obj: sort.cpp + +submat.obj: submat.cpp + +svd.obj: svd.cpp + +example.obj: example.cpp + +tmt.obj: tmt.cpp + +tmt1.obj: tmt1.cpp + +tmt2.obj: tmt2.cpp + +tmt3.obj: tmt3.cpp + +tmt4.obj: tmt4.cpp + +tmt5.obj: tmt5.cpp + +tmt6.obj: tmt6.cpp + +tmt7.obj: tmt7.cpp + +tmt8.obj: tmt8.cpp + +tmt9.obj: tmt9.cpp + +tmta.obj: tmta.cpp + +tmtb.obj: tmtb.cpp + +tmtc.obj: tmtc.cpp + +tmtd.obj: tmtd.cpp + +tmte.obj: tmte.cpp + +tmtf.obj: tmtf.cpp + +tmtg.obj: tmtg.cpp + +tmth.obj: tmth.cpp + +tmti.obj: tmti.cpp + +tmtj.obj: tmtj.cpp + +tmtk.obj: tmtk.cpp + +tmtl.obj: tmtl.cpp + +nl_ex.obj: nl_ex.cpp + +sl_ex.obj: sl_ex.cpp + +solution.obj: solution.cpp + +garch.obj: garch.cpp + +test_exc.obj: test_exc.cpp + + diff --git a/Utilities/OSSIM/ossim_core/matrix/bc32.mak b/Utilities/OSSIM/ossim_core/matrix/bc32.mak new file mode 100644 index 0000000000..08251d2ba7 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/bc32.mak @@ -0,0 +1,200 @@ +.AUTODEPEND + +BORLANDPATH = F:\BC5 + +TASM = TASM32 +TLIB = tlib +TLINK = tlink32 +LIBPATH = $(BORLANDPATH)\LIB +INCLUDEPATH = $(BORLANDPATH)\INCLUDE + +CC = bcc32 -W- -v- -H- -x- -3 -N -Og -Oi -Ov -f -I$(INCLUDEPATH) + +everything: tmt.exe example.exe nl_ex.exe sl_ex.exe garch.exe test_exc.exe + + +.cpp.obj: + $(CC) -c {$< } + +OBJ_LIB = bandmat.obj cholesky.obj evalue.obj fft.obj hholder.obj \ + jacobi.obj myexcept.obj newmat1.obj newmat2.obj newmat3.obj \ + newmat4.obj newmat5.obj newmat6.obj newmat7.obj newmat8.obj \ + newmat9.obj newmatex.obj newmatnl.obj newmatrm.obj solution.obj \ + sort.obj submat.obj svd.obj newfft.obj + +newmat.lib: $(OBJ_LIB) + erase newmat.lib + $(TLIB) newmat.lib /P32 +newmat1 +newmat2 +newmat3 +newmat4 +newmat5 +newmat6 + $(TLIB) newmat.lib /P32+newmat7 +newmat8 +newmat9 +svd +fft +hholder +sort + $(TLIB) newmat.lib /P32+cholesky +submat +jacobi +evalue +bandmat +myexcept + $(TLIB) newmat.lib /P32+solution +newmatnl +newmatrm +newmatex +newfft + +OBJ_T = tmt.obj tmt1.obj tmt2.obj tmt3.obj tmt4.obj tmt5.obj tmt6.obj \ + tmt7.obj tmt8.obj tmt9.obj tmta.obj tmtb.obj tmtc.obj tmtd.obj tmte.obj \ + tmtf.obj tmtg.obj tmth.obj tmti.obj tmtj.obj tmtk.obj tmtl.obj + + +tmt.exe: newmat.lib $(OBJ_T) + $(TLINK) /x/L$(LIBPATH) -Tpe -ap -c @&&| +c0x32.obj+tmt.obj+tmt1.obj+tmt2.obj+tmt3.obj+tmt4.obj+tmt5.obj+tmt6.obj+ + tmt7.obj+tmt8.obj+tmt9.obj+tmta.obj+tmtb.obj+tmtc.obj+tmtd.obj+tmte.obj+ + tmtf.obj+tmtg.obj+tmth.obj+tmti.obj+tmtj.obj+tmtk.obj+tmtl.obj+newmat.lib + tmt + # no map file + bidsf.lib+import32.lib+cw32.lib + +| + + +example.exe: newmat.lib example.obj + $(TLINK) /x/L$(LIBPATH) -Tpe -ap -c @&&| +c0x32.obj+example.obj+newmat.lib + example + # no map file + bidsf.lib+import32.lib+cw32.lib + +| + + +nl_ex.exe: newmat.lib nl_ex.obj + $(TLINK) /x/L$(LIBPATH) -Tpe -ap -c @&&| +c0x32.obj+nl_ex.obj+newmat.lib + nl_ex + # no map file + bidsf.lib+import32.lib+cw32.lib + +| + + +sl_ex.exe: newmat.lib sl_ex.obj + $(TLINK) /x/L$(LIBPATH) -Tpe -ap -c @&&| +c0x32.obj+sl_ex.obj+newmat.lib + sl_ex + # no map file + bidsf.lib+import32.lib+cw32.lib + +| + + +garch.exe: newmat.lib garch.obj + $(TLINK) /x/L$(LIBPATH) -Tpe -ap -c @&&| +c0x32.obj+garch.obj+newmat.lib + garch + # no map file + bidsf.lib+import32.lib+cw32.lib + +| + +test_exc.exe: newmat.lib test_exc.obj + $(TLINK) /x/L$(LIBPATH) -Tpe -ap -c @&&| +c0x32.obj+test_exc.obj+newmat.lib + test_exc + # no map file + bidsf.lib+import32.lib+cw32.lib + +| + + +bandmat.obj: bandmat.cpp + +cholesky.obj: cholesky.cpp + +evalue.obj: evalue.cpp + +myexcept.obj: myexcept.cpp + +fft.obj: fft.cpp + +newfft.obj: newfft.cpp + +hholder.obj: hholder.cpp + +jacobi.obj: jacobi.cpp + +newmat1.obj: newmat1.cpp + +newmat2.obj: newmat2.cpp + +newmat3.obj: newmat3.cpp + +newmat4.obj: newmat4.cpp + +newmat5.obj: newmat5.cpp + +newmat6.obj: newmat6.cpp + +newmat7.obj: newmat7.cpp + +newmat8.obj: newmat8.cpp + +newmat9.obj: newmat9.cpp + +newmatex.obj: newmatex.cpp + +newmatrm.obj: newmatrm.cpp + +newmatnl.obj: newmatnl.cpp + +sort.obj: sort.cpp + +submat.obj: submat.cpp + +svd.obj: svd.cpp + +example.obj: example.cpp + +tmt.obj: tmt.cpp + +tmt1.obj: tmt1.cpp + +tmt2.obj: tmt2.cpp + +tmt3.obj: tmt3.cpp + +tmt4.obj: tmt4.cpp + +tmt5.obj: tmt5.cpp + +tmt6.obj: tmt6.cpp + +tmt7.obj: tmt7.cpp + +tmt8.obj: tmt8.cpp + +tmt9.obj: tmt9.cpp + +tmta.obj: tmta.cpp + +tmtb.obj: tmtb.cpp + +tmtc.obj: tmtc.cpp + +tmtd.obj: tmtd.cpp + +tmte.obj: tmte.cpp + +tmtf.obj: tmtf.cpp + +tmtg.obj: tmtg.cpp + +tmth.obj: tmth.cpp + +tmti.obj: tmti.cpp + +tmtj.obj: tmtj.cpp + +tmtk.obj: tmtk.cpp + +tmtl.obj: tmtl.cpp + +nl_ex.obj: nl_ex.cpp + +sl_ex.obj: sl_ex.cpp + +solution.obj: solution.cpp + +garch.obj: garch.cpp + +test_exc.obj: test_exc.cpp + + diff --git a/Utilities/OSSIM/ossim_core/matrix/boolean.h b/Utilities/OSSIM/ossim_core/matrix/boolean.h new file mode 100644 index 0000000000..1d7b4c8589 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/boolean.h @@ -0,0 +1,40 @@ +//$$ boolean.h bool class + +// This is for compilers that do not have bool automatically defined + +#ifndef bool_LIB +#define bool_LIB 0 + +#ifdef use_namespace +namespace RBD_COMMON { +#endif + + +class bool +{ + int value; +public: + bool(const int b) { value = b ? 1 : 0; } + bool(const void* b) { value = b ? 1 : 0; } + bool() {} + operator int() const { return value; } + int operator!() const { return !value; } +}; + + +const bool true = 1; +const bool false = 0; + + + +// version for some older versions of gnu g++ +//#define false 0 +//#define true 1 + +#ifdef use_namespace +} +#endif + + + +#endif diff --git a/Utilities/OSSIM/ossim_core/matrix/cc.mak b/Utilities/OSSIM/ossim_core/matrix/cc.mak new file mode 100644 index 0000000000..2c3ad5c1d3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/cc.mak @@ -0,0 +1,160 @@ +CXX = CC +CXXFLAGS = -O2 + +.SUFFIXES: +.SUFFIXES: .a .o .c .cpp + +everything: libnewmat.a tmt example nl_ex sl_ex garch test_exc + + +.cpp.o: + rm -f $*.cxx + ln $*.cpp $*.cxx + $(CXX) $(CXXFLAGS) -c $*.cxx + rm $*.cxx + +OBJ_LIB = bandmat.o cholesky.o evalue.o fft.o hholder.o \ + jacobi.o myexcept.o newmat1.o newmat2.o newmat3.o \ + newmat4.o newmat5.o newmat6.o newmat7.o newmat8.o \ + newmat9.o newmatex.o newmatnl.o newmatrm.o solution.o \ + sort.o submat.o svd.o newfft.o + +libnewmat.a: $(OBJ_LIB) + $(AR) cr $@ $(OBJ_LIB) + ranlib $@ + +OBJ_T = tmt.o tmt1.o tmt2.o tmt3.o tmt4.o tmt5.o tmt6.o \ + tmt7.o tmt8.o tmt9.o tmta.o tmtb.o tmtc.o tmtd.o tmte.o \ + tmtf.o tmtg.o tmth.o tmti.o tmtj.o tmtk.o tmtl.o + +tmt: $(OBJ_T) libnewmat.a + $(CXX) -o $@ $(OBJ_T) -L. -lnewmat -lm + +OBJ_E = example.o + +example: $(OBJ_E) libnewmat.a + $(CXX) -o $@ $(OBJ_E) -L. -lnewmat -lm + +OBJ_N = nl_ex.o + +nl_ex: $(OBJ_N) libnewmat.a + $(CXX) -o $@ $(OBJ_N) -L. -lnewmat -lm + +OBJ_S = sl_ex.o + +sl_ex: $(OBJ_S) libnewmat.a + $(CXX) -o $@ $(OBJ_S) -L. -lnewmat -lm + +OBJ_G = garch.o + +garch: $(OBJ_G) libnewmat.a + $(CXX) -o $@ $(OBJ_G) -L. -lnewmat -lm + +OBJ_X = test_exc.o + +test_exc: $(OBJ_X) libnewmat.a + $(CXX) -o $@ $(OBJ_X) -L. -lnewmat -lm + +newmatxx = include.h newmat.h boolean.h myexcept.h + +myexcept.o: include.h boolean.h myexcept.h myexcept.cpp + +newmatex.o: $(newmatxx) newmatex.cpp + +newmatnl.o: $(newmatxx) newmatnl.h newmatap.h + +example.o: $(newmatxx) newmatap.h example.cpp + +cholesky.o: $(newmatxx) cholesky.cpp + +evalue.o: $(newmatxx) newmatrm.h precisio.h evalue.cpp + +fft.o: $(newmatxx) newmatap.h fft.cpp + +newfft.o: $(newmatxx) newmatap.h newfft.cpp + +hholder.o: $(newmatxx) newmatap.h hholder.cpp + +jacobi.o: $(newmatxx) precisio.h newmatrm.h jacobi.cpp + +bandmat.o: $(newmatxx) newmatrc.h controlw.h bandmat.cpp + +newmat1.o: $(newmatxx) newmat1.cpp + +newmat2.o: $(newmatxx) newmatrc.h controlw.h newmat2.cpp + +newmat3.o: $(newmatxx) newmatrc.h controlw.h newmat3.cpp + +newmat4.o: $(newmatxx) newmatrc.h controlw.h newmat4.cpp + +newmat5.o: $(newmatxx) newmatrc.h controlw.h newmat5.cpp + +newmat6.o: $(newmatxx) newmatrc.h controlw.h newmat6.cpp + +newmat7.o: $(newmatxx) newmatrc.h controlw.h newmat7.cpp + +newmat8.o: $(newmatxx) newmatap.h newmat8.cpp + +newmat9.o: $(newmatxx) newmatrc.h controlw.h newmatio.h newmat9.cpp + +newmatrm.o: $(newmatxx) newmatrm.h newmatrm.cpp + +sort.o: $(newmatxx) newmatap.h sort.cpp + +submat.o: $(newmatxx) newmatrc.h controlw.h submat.cpp + +svd.o: $(newmatxx) newmatrm.h precisio.h svd.cpp + +tmt.o: $(newmatxx) newmatap.h tmt.cpp + +tmt1.o: $(newmatxx) newmatap.h tmt1.cpp + +tmt2.o: $(newmatxx) newmatap.h tmt2.cpp + +tmt3.o: $(newmatxx) newmatap.h tmt3.cpp + +tmt4.o: $(newmatxx) newmatap.h tmt4.cpp + +tmt5.o: $(newmatxx) newmatap.h tmt5.cpp + +tmt6.o: $(newmatxx) newmatap.h tmt6.cpp + +tmt7.o: $(newmatxx) newmatap.h tmt7.cpp + +tmt8.o: $(newmatxx) newmatap.h tmt8.cpp + +tmt9.o: $(newmatxx) newmatap.h tmt9.cpp + +tmta.o: $(newmatxx) newmatap.h tmta.cpp + +tmtb.o: $(newmatxx) newmatap.h tmtb.cpp + +tmtc.o: $(newmatxx) newmatap.h tmtc.cpp + +tmtd.o: $(newmatxx) newmatap.h tmtd.cpp + +tmte.o: $(newmatxx) newmatap.h tmte.cpp + +tmtf.o: $(newmatxx) newmatap.h tmtf.cpp + +tmtg.o: $(newmatxx) newmatap.h tmtg.cpp + +tmth.o: $(newmatxx) newmatap.h tmth.cpp + +tmti.o: $(newmatxx) newmatap.h tmti.cpp + +tmtj.o: $(newmatxx) newmatap.h tmtj.cpp + +tmtk.o: $(newmatxx) newmatap.h tmtk.cpp + +tmtl.o: $(newmatxx) newmatap.h tmtl.cpp + +nl_ex.o: $(newmatxx) newmatap.h newmatnl.h nl_ex.cpp + +sl_ex.o: include.h boolean.h myexcept.h sl_ex.cpp + +solution.o: include.h boolean.h myexcept.h solution.cpp + +garch.o: $(newmatxx) newmatap.h newmatnl.h garch.cpp + +test_exc.o: $(newmatxx) test_exc.cpp diff --git a/Utilities/OSSIM/ossim_core/matrix/cholesky.cpp b/Utilities/OSSIM/ossim_core/matrix/cholesky.cpp new file mode 100644 index 0000000000..00faf069a8 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/cholesky.cpp @@ -0,0 +1,280 @@ +//$$ cholesky.cpp cholesky decomposition + +// Copyright (C) 1991,2,3,4: R B Davies + +#define WANT_MATH +//#define WANT_STREAM + +#include "include.h" + +#include "newmat.h" +#include "newmatrm.h" + +#ifdef use_namespace +namespace NEWMAT { +#endif + +#ifdef DO_REPORT +#define REPORT { static ExeCounter ExeCount(__LINE__,14); ++ExeCount; } +#else +#define REPORT {} +#endif + +/********* Cholesky decomposition of a positive definite matrix *************/ + +// Suppose S is symmetrix and positive definite. Then there exists a unique +// lower triangular matrix L such that L L.t() = S; + + +ReturnMatrix Cholesky(const SymmetricMatrix& S) +{ + REPORT + Tracer trace("Cholesky"); + int nr = S.Nrows(); + LowerTriangularMatrix T(nr); + Real* s = S.Store(); Real* t = T.Store(); Real* ti = t; + for (int i=0; i<nr; i++) + { + Real* tj = t; Real sum; int k; + for (int j=0; j<i; j++) + { + Real* tk = ti; sum = 0.0; k = j; + while (k--) { sum += *tj++ * *tk++; } + *tk = (*s++ - sum) / *tj++; + } + sum = 0.0; k = i; + while (k--) { sum += square(*ti++); } + Real d = *s++ - sum; + if (d<=0.0) Throw(NPDException(S)); + *ti++ = sqrt(d); + } + T.Release(); return T.ForReturn(); +} + +ReturnMatrix Cholesky(const SymmetricBandMatrix& S) +{ + REPORT + Tracer trace("Band-Cholesky"); + int nr = S.Nrows(); int m = S.lower; + LowerBandMatrix T(nr,m); + Real* s = S.Store(); Real* t = T.Store(); Real* ti = t; + + for (int i=0; i<nr; i++) + { + Real* tj = t; Real sum; int l; + if (i<m) { REPORT l = m-i; s += l; ti += l; l = i; } + else { REPORT t += (m+1); l = m; } + + for (int j=0; j<l; j++) + { + Real* tk = ti; sum = 0.0; int k = j; tj += (m-j); + while (k--) { sum += *tj++ * *tk++; } + *tk = (*s++ - sum) / *tj++; + } + sum = 0.0; + while (l--) { sum += square(*ti++); } + Real d = *s++ - sum; + if (d<=0.0) Throw(NPDException(S)); + *ti++ = sqrt(d); + } + + T.Release(); return T.ForReturn(); +} + + + + +// Contributed by Nick Bennett of Schlumberger-Doll Research; modified by RBD + +// The enclosed routines can be used to update the Cholesky decomposition of +// a positive definite symmetric matrix. A good reference for this routines +// can be found in +// LINPACK User's Guide, Chapter 10, Dongarra et. al., SIAM, Philadelphia, 1979 + +// produces the Cholesky decomposition of A + x.t() * x where A = chol.t() * chol +void UpdateCholesky(UpperTriangularMatrix &chol, RowVector r1Modification) +{ + int ncols = chol.Nrows(); + ColumnVector cGivens(ncols); cGivens = 0.0; + ColumnVector sGivens(ncols); sGivens = 0.0; + + for(int j = 1; j <= ncols; ++j) // process the jth column of chol + { + // apply the previous Givens rotations k = 1,...,j-1 to column j + for(int k = 1; k < j; ++k) + GivensRotation(cGivens(k), sGivens(k), chol(k,j), r1Modification(j)); + + // determine the jth Given's rotation + pythag(chol(j,j), r1Modification(j), cGivens(j), sGivens(j)); + + // apply the jth Given's rotation + { + Real tmp0 = cGivens(j) * chol(j,j) + sGivens(j) * r1Modification(j); + chol(j,j) = tmp0; r1Modification(j) = 0.0; + } + + } + +} + + +// produces the Cholesky decomposition of A - x.t() * x where A = chol.t() * chol +void DowndateCholesky(UpperTriangularMatrix &chol, RowVector x) +{ + int nRC = chol.Nrows(); + + // solve R^T a = x + LowerTriangularMatrix L = chol.t(); + ColumnVector a(nRC); a = 0.0; + int i, j; + + for (i = 1; i <= nRC; ++i) + { + // accumulate subtr sum + Real subtrsum = 0.0; + for(int k = 1; k < i; ++k) subtrsum += a(k) * L(i,k); + + a(i) = (x(i) - subtrsum) / L(i,i); + } + + // test that l2 norm of a is < 1 + Real squareNormA = a.SumSquare(); + if (squareNormA >= 1.0) + Throw(ProgramException("DowndateCholesky() fails", chol)); + + Real alpha = sqrt(1.0 - squareNormA); + + // compute and apply Givens rotations to the vector a + ColumnVector cGivens(nRC); cGivens = 0.0; + ColumnVector sGivens(nRC); sGivens = 0.0; + for(i = nRC; i >= 1; i--) + alpha = pythag(alpha, a(i), cGivens(i), sGivens(i)); + + // apply Givens rotations to the jth column of chol + ColumnVector xtilde(nRC); xtilde = 0.0; + for(j = nRC; j >= 1; j--) + { + // only the first j rotations have an affect on chol,0 + for(int k = j; k >= 1; k--) + GivensRotation(cGivens(k), -sGivens(k), chol(k,j), xtilde(j)); + } +} + + + +// produces the Cholesky decomposition of EAE where A = chol.t() * chol +// and E produces a RIGHT circular shift of the rows and columns from +// 1,...,k-1,k,k+1,...l,l+1,...,p to +// 1,...,k-1,l,k,k+1,...l-1,l+1,...p +void RightCircularUpdateCholesky(UpperTriangularMatrix &chol, int k, int l) +{ + int nRC = chol.Nrows(); + int i, j; + + // I. compute shift of column l to the kth position + Matrix cholCopy = chol; + // a. grab column l + ColumnVector columnL = cholCopy.Column(l); + // b. shift columns k,...l-1 to the RIGHT + for(j = l-1; j >= k; --j) + cholCopy.Column(j+1) = cholCopy.Column(j); + // c. copy the top k-1 elements of columnL into the kth column of cholCopy + cholCopy.Column(k) = 0.0; + for(i = 1; i < k; ++i) cholCopy(i,k) = columnL(i); + + // II. determine the l-k Given's rotations + int nGivens = l-k; + ColumnVector cGivens(nGivens); cGivens = 0.0; + ColumnVector sGivens(nGivens); sGivens = 0.0; + for(i = l; i > k; i--) + { + int givensIndex = l-i+1; + columnL(i-1) = pythag(columnL(i-1), columnL(i), + cGivens(givensIndex), sGivens(givensIndex)); + columnL(i) = 0.0; + } + // the kth entry of columnL is the new diagonal element in column k of cholCopy + cholCopy(k,k) = columnL(k); + + // III. apply these Given's rotations to subsequent columns + // for columns k+1,...,l-1 we only need to apply the last nGivens-(j-k) rotations + for(j = k+1; j <= nRC; ++j) + { + ColumnVector columnJ = cholCopy.Column(j); + int imin = nGivens - (j-k) + 1; if (imin < 1) imin = 1; + for(int gIndex = imin; gIndex <= nGivens; ++gIndex) + { + // apply gIndex Given's rotation + int topRowIndex = k + nGivens - gIndex; + GivensRotationR(cGivens(gIndex), sGivens(gIndex), + columnJ(topRowIndex), columnJ(topRowIndex+1)); + } + cholCopy.Column(j) = columnJ; + } + + chol << cholCopy; +} + + + +// produces the Cholesky decomposition of EAE where A = chol.t() * chol +// and E produces a LEFT circular shift of the rows and columns from +// 1,...,k-1,k,k+1,...l,l+1,...,p to +// 1,...,k-1,k+1,...l,k,l+1,...,p to +void LeftCircularUpdateCholesky(UpperTriangularMatrix &chol, int k, int l) +{ + int nRC = chol.Nrows(); + int i, j; + + // I. compute shift of column k to the lth position + Matrix cholCopy = chol; + // a. grab column k + ColumnVector columnK = cholCopy.Column(k); + // b. shift columns k+1,...l to the LEFT + for(j = k+1; j <= l; ++j) + cholCopy.Column(j-1) = cholCopy.Column(j); + // c. copy the elements of columnK into the lth column of cholCopy + cholCopy.Column(l) = 0.0; + for(i = 1; i <= k; ++i) + cholCopy(i,l) = columnK(i); + + // II. apply and compute Given's rotations + int nGivens = l-k; + ColumnVector cGivens(nGivens); cGivens = 0.0; + ColumnVector sGivens(nGivens); sGivens = 0.0; + for(j = k; j <= nRC; ++j) + { + ColumnVector columnJ = cholCopy.Column(j); + + // apply the previous Givens rotations to columnJ + int imax = j - k; if (imax > nGivens) imax = nGivens; + for(int i = 1; i <= imax; ++i) + { + int gIndex = i; + int topRowIndex = k + i - 1; + GivensRotationR(cGivens(gIndex), sGivens(gIndex), + columnJ(topRowIndex), columnJ(topRowIndex+1)); + } + + // compute a new Given's rotation when j < l + if(j < l) + { + int gIndex = j-k+1; + columnJ(j) = pythag(columnJ(j), columnJ(j+1), cGivens(gIndex), sGivens(gIndex)); + columnJ(j+1) = 0.0; + } + + cholCopy.Column(j) = columnJ; + } + + chol << cholCopy; + +} + + + + +#ifdef use_namespace +} +#endif + diff --git a/Utilities/OSSIM/ossim_core/matrix/controlw.h b/Utilities/OSSIM/ossim_core/matrix/controlw.h new file mode 100644 index 0000000000..76faa98549 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/controlw.h @@ -0,0 +1,48 @@ +//$$ controlw.h Control word class + +#ifndef CONTROL_WORD_LIB +#define CONTROL_WORD_LIB 0 + +// for organising an int as a series of bits which indicate whether an +// option is on or off. + +class ControlWord +{ +protected: + int cw; // the control word +public: + ControlWord() : cw(0) {} // do nothing + ControlWord(int i) : cw(i) {} // load an integer + + // select specific bits (for testing at least one set) + ControlWord operator*(ControlWord i) const + { return ControlWord(cw & i.cw); } + void operator*=(ControlWord i) { cw &= i.cw; } + + // set bits + ControlWord operator+(ControlWord i) const + { return ControlWord(cw | i.cw); } + void operator+=(ControlWord i) { cw |= i.cw; } + + // reset bits + ControlWord operator-(ControlWord i) const + { return ControlWord(cw - (cw & i.cw)); } + void operator-=(ControlWord i) { cw -= (cw & i.cw); } + + // check if all of selected bits set or reset + bool operator>=(ControlWord i) const { return (cw & i.cw) == i.cw; } + bool operator<=(ControlWord i) const { return (cw & i.cw) == cw; } + + // flip selected bits + ControlWord operator^(ControlWord i) const + { return ControlWord(cw ^ i.cw); } + ControlWord operator~() const { return ControlWord(~cw); } + + // convert to integer + int operator+() const { return cw; } + int operator!() const { return cw==0; } + FREE_CHECK(ControlWord) +}; + + +#endif diff --git a/Utilities/OSSIM/ossim_core/matrix/evalue.cpp b/Utilities/OSSIM/ossim_core/matrix/evalue.cpp new file mode 100644 index 0000000000..ccb9c8d14a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/evalue.cpp @@ -0,0 +1,297 @@ +//$$evalue.cpp eigen-value decomposition + +// Copyright (C) 1991,2,3,4: R B Davies + +#define WANT_MATH + +#include "include.h" +#include "newmatap.h" +#include "newmatrm.h" +#include "precisio.h" + +#ifdef use_namespace +namespace NEWMAT { +#endif + +#ifdef DO_REPORT +#define REPORT { static ExeCounter ExeCount(__LINE__,17); ++ExeCount; } +#else +#define REPORT {} +#endif + + + +static void tred2(const SymmetricMatrix& A, DiagonalMatrix& D, + DiagonalMatrix& E, Matrix& Z) +{ + Tracer et("Evalue(tred2)"); + REPORT + Real tol = + FloatingPointPrecision::Minimum()/FloatingPointPrecision::Epsilon(); + int n = A.Nrows(); Z.ReSize(n,n); Z.Inject(A); + D.ReSize(n); E.ReSize(n); + Real* z = Z.Store(); int i; + + for (i=n-1; i > 0; i--) // i=0 is excluded + { + Real f = Z.element(i,i-1); Real g = 0.0; + int k = i-1; Real* zik = z + i*n; + while (k--) g += square(*zik++); + Real h = g + square(f); + if (g <= tol) { REPORT E.element(i) = f; h = 0.0; } + else + { + REPORT + g = sign(-sqrt(h), f); E.element(i) = g; h -= f*g; + Z.element(i,i-1) = f-g; f = 0.0; + Real* zji = z + i; Real* zij = z + i*n; Real* ej = E.Store(); + int j; + for (j=0; j<i; j++) + { + *zji = (*zij++)/h; g = 0.0; + Real* zjk = z + j*n; zik = z + i*n; + k = j; while (k--) g += *zjk++ * (*zik++); + k = i-j; + if (k) for(;;) + { g += *zjk * (*zik++); if (!(--k)) break; zjk += n; } + *ej++ = g/h; f += g * (*zji); zji += n; + } + Real hh = f / (h + h); zij = z + i*n; ej = E.Store(); + for (j=0; j<i; j++) + { + f = *zij++; g = *ej - hh * f; *ej++ = g; + Real* zjk = z + j*n; Real* zik = z + i*n; + Real* ek = E.Store(); k = j+1; + while (k--) *zjk++ -= ( f*(*ek++) + g*(*zik++) ); + } + } + D.element(i) = h; + } + + D.element(0) = 0.0; E.element(0) = 0.0; + for (i=0; i<n; i++) + { + if (D.element(i) != 0.0) + { + REPORT + for (int j=0; j<i; j++) + { + Real g = 0.0; + Real* zik = z + i*n; Real* zkj = z + j; + int k = i; + if (k) for (;;) + { g += *zik++ * (*zkj); if (!(--k)) break; zkj += n; } + Real* zki = z + i; zkj = z + j; + k = i; + if (k) for (;;) + { *zkj -= g * (*zki); if (!(--k)) break; zkj += n; zki += n; } + } + } + Real* zij = z + i*n; Real* zji = z + i; + int j = i; + if (j) for (;;) + { *zij++ = 0.0; *zji = 0.0; if (!(--j)) break; zji += n; } + D.element(i) = *zij; *zij = 1.0; + } +} + +static void tql2(DiagonalMatrix& D, DiagonalMatrix& E, Matrix& Z) +{ + Tracer et("Evalue(tql2)"); + REPORT + Real eps = FloatingPointPrecision::Epsilon(); + int n = D.Nrows(); Real* z = Z.Store(); int l; + for (l=1; l<n; l++) E.element(l-1) = E.element(l); + Real b = 0.0; Real f = 0.0; E.element(n-1) = 0.0; + for (l=0; l<n; l++) + { + int i,j; + Real& dl = D.element(l); Real& el = E.element(l); + Real h = eps * ( fabs(dl) + fabs(el) ); + if (b < h) { REPORT b = h; } + int m; + for (m=l; m<n; m++) if (fabs(E.element(m)) <= b) break; + bool test = false; + for (j=0; j<30; j++) + { + if (m==l) { REPORT test = true; break; } + Real& dl1 = D.element(l+1); + Real g = dl; Real p = (dl1-g) / (2.0*el); Real r = sqrt(p*p + 1.0); + dl = el / (p < 0.0 ? p-r : p+r); Real h = g - dl; f += h; + Real* dlx = &dl1; i = n-l-1; while (i--) *dlx++ -= h; + + p = D.element(m); Real c = 1.0; Real s = 0.0; + for (i=m-1; i>=l; i--) + { + Real ei = E.element(i); Real di = D.element(i); + Real& ei1 = E.element(i+1); + g = c * ei; h = c * p; + if ( fabs(p) >= fabs(ei)) + { + REPORT + c = ei / p; r = sqrt(c*c + 1.0); + ei1 = s*p*r; s = c/r; c = 1.0/r; + } + else + { + REPORT + c = p / ei; r = sqrt(c*c + 1.0); + ei1 = s * ei * r; s = 1.0/r; c /= r; + } + p = c * di - s*g; D.element(i+1) = h + s * (c*g + s*di); + + Real* zki = z + i; Real* zki1 = zki + 1; int k = n; + if (k) for (;;) + { + REPORT + h = *zki1; *zki1 = s*(*zki) + c*h; *zki = c*(*zki) - s*h; + if (!(--k)) break; + zki += n; zki1 += n; + } + } + el = s*p; dl = c*p; + if (fabs(el) <= b) { REPORT; test = true; break; } + } + if (!test) Throw ( ConvergenceException(D) ); + dl += f; + } +/* + for (int i=0; i<n; i++) + { + int k = i; Real p = D.element(i); + for (int j=i+1; j<n; j++) + { if (D.element(j) < p) { k = j; p = D.element(j); } } + if (k != i) + { + D.element(k) = D.element(i); D.element(i) = p; int j = n; + Real* zji = z + i; Real* zjk = z + k; + if (j) for(;;) + { + p = *zji; *zji = *zjk; *zjk = p; + if (!(--j)) break; + zji += n; zjk += n; + } + } + } +*/ +} + +static void tred3(const SymmetricMatrix& X, DiagonalMatrix& D, + DiagonalMatrix& E, SymmetricMatrix& A) +{ + Tracer et("Evalue(tred3)"); + REPORT + Real tol = + FloatingPointPrecision::Minimum()/FloatingPointPrecision::Epsilon(); + int n = X.Nrows(); A = X; D.ReSize(n); E.ReSize(n); + Real* ei = E.Store() + n; + for (int i = n-1; i >= 0; i--) + { + Real h = 0.0; Real f = - FloatingPointPrecision::Maximum(); + Real* d = D.Store(); Real* a = A.Store() + (i*(i+1))/2; int k = i; + while (k--) { f = *a++; *d++ = f; h += square(f); } + if (h <= tol) { REPORT *(--ei) = 0.0; h = 0.0; } + else + { + REPORT + Real g = sign(-sqrt(h), f); *(--ei) = g; h -= f*g; + f -= g; *(d-1) = f; *(a-1) = f; f = 0.0; + Real* dj = D.Store(); Real* ej = E.Store(); int j; + for (j = 0; j < i; j++) + { + Real* dk = D.Store(); Real* ak = A.Store()+(j*(j+1))/2; + Real g = 0.0; k = j; + while (k--) g += *ak++ * *dk++; + k = i-j; int l = j; + if (k) for (;;) { g += *ak * *dk++; if (!(--k)) break; ak += ++l; } + g /= h; *ej++ = g; f += g * *dj++; + } + Real hh = f / (2 * h); Real* ak = A.Store(); + dj = D.Store(); ej = E.Store(); + for (j = 0; j < i; j++) + { + f = *dj++; g = *ej - hh * f; *ej++ = g; + Real* dk = D.Store(); Real* ek = E.Store(); k = j+1; + while (k--) { *ak++ -= (f * *ek++ + g * *dk++); } + } + } + *d = *a; *a = h; + } +} + +static void tql1(DiagonalMatrix& D, DiagonalMatrix& E) +{ + Tracer et("Evalue(tql1)"); + REPORT + Real eps = FloatingPointPrecision::Epsilon(); + int n = D.Nrows(); int l; + for (l=1; l<n; l++) E.element(l-1) = E.element(l); + Real b = 0.0; Real f = 0.0; E.element(n-1) = 0.0; + for (l=0; l<n; l++) + { + int i,j; + Real& dl = D.element(l); Real& el = E.element(l); + Real h = eps * ( fabs(dl) + fabs(el) ); + if (b < h) b = h; + int m; + for (m=l; m<n; m++) if (fabs(E.element(m)) <= b) break; + bool test = false; + for (j=0; j<30; j++) + { + if (m==l) { REPORT test = true; break; } + Real& dl1 = D.element(l+1); + Real g = dl; Real p = (dl1-g) / (2.0*el); Real r = sqrt(p*p + 1.0); + dl = el / (p < 0.0 ? p-r : p+r); Real h = g - dl; f += h; + Real* dlx = &dl1; i = n-l-1; while (i--) *dlx++ -= h; + + p = D.element(m); Real c = 1.0; Real s = 0.0; + for (i=m-1; i>=l; i--) + { + Real ei = E.element(i); Real di = D.element(i); + Real& ei1 = E.element(i+1); + g = c * ei; h = c * p; + if ( fabs(p) >= fabs(ei)) + { + REPORT + c = ei / p; r = sqrt(c*c + 1.0); + ei1 = s*p*r; s = c/r; c = 1.0/r; + } + else + { + REPORT + c = p / ei; r = sqrt(c*c + 1.0); + ei1 = s * ei * r; s = 1.0/r; c /= r; + } + p = c * di - s*g; D.element(i+1) = h + s * (c*g + s*di); + } + el = s*p; dl = c*p; + if (fabs(el) <= b) { REPORT test = true; break; } + } + if (!test) Throw ( ConvergenceException(D) ); + Real p = dl + f; + test = false; + for (i=l; i>0; i--) + { + if (p < D.element(i-1)) { REPORT D.element(i) = D.element(i-1); } + else { REPORT test = true; break; } + } + if (!test) i=0; + D.element(i) = p; + } +} + +void EigenValues(const SymmetricMatrix& A, DiagonalMatrix& D, Matrix& Z) +{ REPORT DiagonalMatrix E; tred2(A, D, E, Z); tql2(D, E, Z); SortSV(D,Z,true); } + +void EigenValues(const SymmetricMatrix& X, DiagonalMatrix& D) +{ REPORT DiagonalMatrix E; SymmetricMatrix A; tred3(X,D,E,A); tql1(D,E); } + +void EigenValues(const SymmetricMatrix& X, DiagonalMatrix& D, + SymmetricMatrix& A) +{ REPORT DiagonalMatrix E; tred3(X,D,E,A); tql1(D,E); } + + +#ifdef use_namespace +} +#endif + diff --git a/Utilities/OSSIM/ossim_core/matrix/example.txt b/Utilities/OSSIM/ossim_core/matrix/example.txt new file mode 100644 index 0000000000..b3b733490b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/example.txt @@ -0,0 +1,123 @@ + +Demonstration of Matrix package + +Print a real number (may help lost memory test): 3.14159 + + +Test 1 - traditional, bad + +Estimates and their standard errors + + 1.39166 0.53188 + 1.98310 0.20932 + 0.95221 0.27731 + + +Observations, fitted value, residual value, hat value + 2.400 1.700 8.300 7.770 0.530 0.280 + 1.800 0.900 5.500 5.818 -0.318 0.190 + 2.400 1.600 8.000 7.675 0.325 0.229 + 3.000 1.900 8.500 9.150 -0.650 0.446 + 2.000 0.500 5.700 5.834 -0.134 0.271 + 1.200 0.600 4.400 4.343 0.057 0.480 + 2.000 1.100 6.300 6.405 -0.105 0.143 + 2.700 1.000 7.900 7.698 0.202 0.153 + 3.600 0.500 9.100 9.007 0.093 0.808 + + + + +Test 2 - traditional, OK + +Estimates and their standard errors + + 1.39166 0.53188 + 1.98310 0.20932 + 0.95221 0.27731 + + +Observations, fitted value, residual value, hat value + 2.400 1.700 8.300 7.770 0.530 0.280 + 1.800 0.900 5.500 5.818 -0.318 0.190 + 2.400 1.600 8.000 7.675 0.325 0.229 + 3.000 1.900 8.500 9.150 -0.650 0.446 + 2.000 0.500 5.700 5.834 -0.134 0.271 + 1.200 0.600 4.400 4.343 0.057 0.480 + 2.000 1.100 6.300 6.405 -0.105 0.143 + 2.700 1.000 7.900 7.698 0.202 0.153 + 3.600 0.500 9.100 9.007 0.093 0.808 + + + + +Test 3 - Cholesky + +Estimates and their standard errors + + 1.39166 0.53188 + 1.98310 0.20932 + 0.95221 0.27731 + + +Observations, fitted value, residual value, hat value + 2.400 1.700 8.300 7.770 0.530 0.280 + 1.800 0.900 5.500 5.818 -0.318 0.190 + 2.400 1.600 8.000 7.675 0.325 0.229 + 3.000 1.900 8.500 9.150 -0.650 0.446 + 2.000 0.500 5.700 5.834 -0.134 0.271 + 1.200 0.600 4.400 4.343 0.057 0.480 + 2.000 1.100 6.300 6.405 -0.105 0.143 + 2.700 1.000 7.900 7.698 0.202 0.153 + 3.600 0.500 9.100 9.007 0.093 0.808 + + + + +Test 4 - QR triangularisation + +Estimates and their standard errors + + 1.39166 0.53188 + 1.98310 0.20932 + 0.95221 0.27731 + + +Observations, fitted value, residual value, hat value + 2.400 1.700 8.300 7.770 0.530 0.280 + 1.800 0.900 5.500 5.818 -0.318 0.190 + 2.400 1.600 8.000 7.675 0.325 0.229 + 3.000 1.900 8.500 9.150 -0.650 0.446 + 2.000 0.500 5.700 5.834 -0.134 0.271 + 1.200 0.600 4.400 4.343 0.057 0.480 + 2.000 1.100 6.300 6.405 -0.105 0.143 + 2.700 1.000 7.900 7.698 0.202 0.153 + 3.600 0.500 9.100 9.007 0.093 0.808 + + + + +Test 5 - singular value + +Estimates and their standard errors + + 1.39166 0.53188 + 1.98310 0.20932 + 0.95221 0.27731 + + +Observations, fitted value, residual value, hat value + 2.400 1.700 8.300 7.770 0.530 0.280 + 1.800 0.900 5.500 5.818 -0.318 0.190 + 2.400 1.600 8.000 7.675 0.325 0.229 + 3.000 1.900 8.500 9.150 -0.650 0.446 + 2.000 0.500 5.700 5.834 -0.134 0.271 + 1.200 0.600 4.400 4.343 0.057 0.480 + 2.000 1.100 6.300 6.405 -0.105 0.143 + 2.700 1.000 7.900 7.698 0.202 0.153 + 3.600 0.500 9.100 9.007 0.093 0.808 + + + + +The following test does not work with all compilers - see documentation +Checking for lost memory: 8206652 8206652 - ok diff --git a/Utilities/OSSIM/ossim_core/matrix/fft.cpp b/Utilities/OSSIM/ossim_core/matrix/fft.cpp new file mode 100644 index 0000000000..08a2deb2f5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/fft.cpp @@ -0,0 +1,474 @@ +//$$ fft.cpp Fast fourier transform + +// Copyright (C) 1991,2,3,4,8: R B Davies + + +#define WANT_MATH +// #define WANT_STREAM + +#include "include.h" + +#include "newmatap.h" + +// #include "newmatio.h" + +#ifdef use_namespace +namespace NEWMAT { +#endif + +#ifdef DO_REPORT +#define REPORT { static ExeCounter ExeCount(__LINE__,19); ++ExeCount; } +#else +#define REPORT {} +#endif + +static void cossin(int n, int d, Real& c, Real& s) +// calculate cos(twopi*n/d) and sin(twopi*n/d) +// minimise roundoff error +{ + REPORT + long n4 = n * 4; int sector = (int)floor( (Real)n4 / (Real)d + 0.5 ); + n4 -= sector * d; + if (sector < 0) { REPORT sector = 3 - (3 - sector) % 4; } + else { REPORT sector %= 4; } + Real ratio = 1.5707963267948966192 * (Real)n4 / (Real)d; + + switch (sector) + { + case 0: REPORT c = cos(ratio); s = sin(ratio); break; + case 1: REPORT c = -sin(ratio); s = cos(ratio); break; + case 2: REPORT c = -cos(ratio); s = -sin(ratio); break; + case 3: REPORT c = sin(ratio); s = -cos(ratio); break; + } +} + +static void fftstep(ColumnVector& A, ColumnVector& B, ColumnVector& X, + ColumnVector& Y, int after, int now, int before) +{ + REPORT + Tracer trace("FFT(step)"); + // const Real twopi = 6.2831853071795864769; + const int gamma = after * before; const int delta = now * after; + // const Real angle = twopi / delta; Real temp; + // Real r_omega = cos(angle); Real i_omega = -sin(angle); + Real r_arg = 1.0; Real i_arg = 0.0; + Real* x = X.Store(); Real* y = Y.Store(); // pointers to array storage + const int m = A.Nrows() - gamma; + + for (int j = 0; j < now; j++) + { + Real* a = A.Store(); Real* b = B.Store(); // pointers to array storage + Real* x1 = x; Real* y1 = y; x += after; y += after; + for (int ia = 0; ia < after; ia++) + { + // generate sins & cosines explicitly rather than iteratively + // for more accuracy; but slower + cossin(-(j*after+ia), delta, r_arg, i_arg); + + Real* a1 = a++; Real* b1 = b++; Real* x2 = x1++; Real* y2 = y1++; + if (now==2) + { + REPORT int ib = before; + if (ib) for (;;) + { + REPORT + Real* a2 = m + a1; Real* b2 = m + b1; a1 += after; b1 += after; + Real r_value = *a2; Real i_value = *b2; + *x2 = r_value * r_arg - i_value * i_arg + *(a2-gamma); + *y2 = r_value * i_arg + i_value * r_arg + *(b2-gamma); + if (!(--ib)) break; + x2 += delta; y2 += delta; + } + } + else + { + REPORT int ib = before; + if (ib) for (;;) + { + REPORT + Real* a2 = m + a1; Real* b2 = m + b1; a1 += after; b1 += after; + Real r_value = *a2; Real i_value = *b2; + int in = now-1; while (in--) + { + // it should be possible to make this faster + // hand code for now = 2,3,4,5,8 + // use symmetry to halve number of operations + a2 -= gamma; b2 -= gamma; Real temp = r_value; + r_value = r_value * r_arg - i_value * i_arg + *a2; + i_value = temp * i_arg + i_value * r_arg + *b2; + } + *x2 = r_value; *y2 = i_value; + if (!(--ib)) break; + x2 += delta; y2 += delta; + } + } + + // temp = r_arg; + // r_arg = r_arg * r_omega - i_arg * i_omega; + // i_arg = temp * i_omega + i_arg * r_omega; + + } + } +} + + +void FFTI(const ColumnVector& U, const ColumnVector& V, + ColumnVector& X, ColumnVector& Y) +{ + // Inverse transform + Tracer trace("FFTI"); + REPORT + FFT(U,-V,X,Y); + const Real n = X.Nrows(); X /= n; Y /= (-n); +} + +void RealFFT(const ColumnVector& U, ColumnVector& X, ColumnVector& Y) +{ + // Fourier transform of a real series + Tracer trace("RealFFT"); + REPORT + const int n = U.Nrows(); // length of arrays + const int n2 = n / 2; + if (n != 2 * n2) + Throw(ProgramException("Vector length not multiple of 2", U)); + ColumnVector A(n2), B(n2); + Real* a = A.Store(); Real* b = B.Store(); Real* u = U.Store(); int i = n2; + while (i--) { *a++ = *u++; *b++ = *u++; } + FFT(A,B,A,B); + int n21 = n2 + 1; + X.ReSize(n21); Y.ReSize(n21); + i = n2 - 1; + a = A.Store(); b = B.Store(); // first els of A and B + Real* an = a + i; Real* bn = b + i; // last els of A and B + Real* x = X.Store(); Real* y = Y.Store(); // first els of X and Y + Real* xn = x + n2; Real* yn = y + n2; // last els of X and Y + + *x++ = *a + *b; *y++ = 0.0; // first complex element + *xn-- = *a++ - *b++; *yn-- = 0.0; // last complex element + + int j = -1; i = n2/2; + while (i--) + { + Real c,s; cossin(j--,n,c,s); + Real am = *a - *an; Real ap = *a++ + *an--; + Real bm = *b - *bn; Real bp = *b++ + *bn--; + Real samcbp = s * am + c * bp; Real sbpcam = s * bp - c * am; + *x++ = 0.5 * ( ap + samcbp); *y++ = 0.5 * ( bm + sbpcam); + *xn-- = 0.5 * ( ap - samcbp); *yn-- = 0.5 * (-bm + sbpcam); + } +} + +void RealFFTI(const ColumnVector& A, const ColumnVector& B, ColumnVector& U) +{ + // inverse of a Fourier transform of a real series + Tracer trace("RealFFTI"); + REPORT + const int n21 = A.Nrows(); // length of arrays + if (n21 != B.Nrows() || n21 == 0) + Throw(ProgramException("Vector lengths unequal or zero", A, B)); + const int n2 = n21 - 1; const int n = 2 * n2; int i = n2 - 1; + + ColumnVector X(n2), Y(n2); + Real* a = A.Store(); Real* b = B.Store(); // first els of A and B + Real* an = a + n2; Real* bn = b + n2; // last els of A and B + Real* x = X.Store(); Real* y = Y.Store(); // first els of X and Y + Real* xn = x + i; Real* yn = y + i; // last els of X and Y + + Real hn = 0.5 / n2; + *x++ = hn * (*a + *an); *y++ = - hn * (*a - *an); + a++; an--; b++; bn--; + int j = -1; i = n2/2; + while (i--) + { + Real c,s; cossin(j--,n,c,s); + Real am = *a - *an; Real ap = *a++ + *an--; + Real bm = *b - *bn; Real bp = *b++ + *bn--; + Real samcbp = s * am - c * bp; Real sbpcam = s * bp + c * am; + *x++ = hn * ( ap + samcbp); *y++ = - hn * ( bm + sbpcam); + *xn-- = hn * ( ap - samcbp); *yn-- = - hn * (-bm + sbpcam); + } + FFT(X,Y,X,Y); // have done inverting elsewhere + U.ReSize(n); i = n2; + x = X.Store(); y = Y.Store(); Real* u = U.Store(); + while (i--) { *u++ = *x++; *u++ = - *y++; } +} + +void FFT(const ColumnVector& U, const ColumnVector& V, + ColumnVector& X, ColumnVector& Y) +{ + // from Carl de Boor (1980), Siam J Sci Stat Comput, 1 173-8 + // but first try Sande and Gentleman + Tracer trace("FFT"); + REPORT + const int n = U.Nrows(); // length of arrays + if (n != V.Nrows() || n == 0) + Throw(ProgramException("Vector lengths unequal or zero", U, V)); + if (n == 1) { REPORT X = U; Y = V; return; } + + // see if we can use the newfft routine + if (!FFT_Controller::OnlyOldFFT && FFT_Controller::CanFactor(n)) + { + REPORT + X = U; Y = V; + if ( FFT_Controller::ar_1d_ft(n,X.Store(),Y.Store()) ) return; + } + + ColumnVector B = V; + ColumnVector A = U; + X.ReSize(n); Y.ReSize(n); + const int nextmx = 8; + int prime[8] = { 2,3,5,7,11,13,17,19 }; + int after = 1; int before = n; int next = 0; bool inzee = true; + int now = 0; int b1; // initialised to keep gnu happy + + do + { + for (;;) + { + if (next < nextmx) { REPORT now = prime[next]; } + b1 = before / now; if (b1 * now == before) { REPORT break; } + next++; now += 2; + } + before = b1; + + if (inzee) { REPORT fftstep(A, B, X, Y, after, now, before); } + else { REPORT fftstep(X, Y, A, B, after, now, before); } + + inzee = !inzee; after *= now; + } + while (before != 1); + + if (inzee) { REPORT A.Release(); X = A; B.Release(); Y = B; } +} + +// Trigonometric transforms +// see Charles Van Loan (1992) "Computational frameworks for the fast +// Fourier transform" published by SIAM; section 4.4. + +void DCT_II(const ColumnVector& U, ColumnVector& V) +{ + // Discrete cosine transform, type II, of a real series + Tracer trace("DCT_II"); + REPORT + const int n = U.Nrows(); // length of arrays + const int n2 = n / 2; const int n4 = n * 4; + if (n != 2 * n2) + Throw(ProgramException("Vector length not multiple of 2", U)); + ColumnVector A(n); + Real* a = A.Store(); Real* b = a + n; Real* u = U.Store(); + int i = n2; + while (i--) { *a++ = *u++; *(--b) = *u++; } + ColumnVector X, Y; + RealFFT(A, X, Y); A.CleanUp(); + V.ReSize(n); + Real* x = X.Store(); Real* y = Y.Store(); + Real* v = V.Store(); Real* w = v + n; + *v = *x; + int k = 0; i = n2; + while (i--) + { + Real c, s; cossin(++k, n4, c, s); + Real xi = *(++x); Real yi = *(++y); + *(++v) = xi * c + yi * s; *(--w) = xi * s - yi * c; + } +} + +void DCT_II_inverse(const ColumnVector& V, ColumnVector& U) +{ + // Inverse of discrete cosine transform, type II + Tracer trace("DCT_II_inverse"); + REPORT + const int n = V.Nrows(); // length of array + const int n2 = n / 2; const int n4 = n * 4; const int n21 = n2 + 1; + if (n != 2 * n2) + Throw(ProgramException("Vector length not multiple of 2", V)); + ColumnVector X(n21), Y(n21); + Real* x = X.Store(); Real* y = Y.Store(); + Real* v = V.Store(); Real* w = v + n; + *x = *v; *y = 0.0; + int i = n2; int k = 0; + while (i--) + { + Real c, s; cossin(++k, n4, c, s); + Real vi = *(++v); Real wi = *(--w); + *(++x) = vi * c + wi * s; *(++y) = vi * s - wi * c; + } + ColumnVector A; RealFFTI(X, Y, A); + X.CleanUp(); Y.CleanUp(); U.ReSize(n); + Real* a = A.Store(); Real* b = a + n; Real* u = U.Store(); + i = n2; + while (i--) { *u++ = *a++; *u++ = *(--b); } +} + +void DST_II(const ColumnVector& U, ColumnVector& V) +{ + // Discrete sine transform, type II, of a real series + Tracer trace("DST_II"); + REPORT + const int n = U.Nrows(); // length of arrays + const int n2 = n / 2; const int n4 = n * 4; + if (n != 2 * n2) + Throw(ProgramException("Vector length not multiple of 2", U)); + ColumnVector A(n); + Real* a = A.Store(); Real* b = a + n; Real* u = U.Store(); + int i = n2; + while (i--) { *a++ = *u++; *(--b) = -(*u++); } + ColumnVector X, Y; + RealFFT(A, X, Y); A.CleanUp(); + V.ReSize(n); + Real* x = X.Store(); Real* y = Y.Store(); + Real* v = V.Store(); Real* w = v + n; + *(--w) = *x; + int k = 0; i = n2; + while (i--) + { + Real c, s; cossin(++k, n4, c, s); + Real xi = *(++x); Real yi = *(++y); + *v++ = xi * s - yi * c; *(--w) = xi * c + yi * s; + } +} + +void DST_II_inverse(const ColumnVector& V, ColumnVector& U) +{ + // Inverse of discrete sine transform, type II + Tracer trace("DST_II_inverse"); + REPORT + const int n = V.Nrows(); // length of array + const int n2 = n / 2; const int n4 = n * 4; const int n21 = n2 + 1; + if (n != 2 * n2) + Throw(ProgramException("Vector length not multiple of 2", V)); + ColumnVector X(n21), Y(n21); + Real* x = X.Store(); Real* y = Y.Store(); + Real* v = V.Store(); Real* w = v + n; + *x = *(--w); *y = 0.0; + int i = n2; int k = 0; + while (i--) + { + Real c, s; cossin(++k, n4, c, s); + Real vi = *v++; Real wi = *(--w); + *(++x) = vi * s + wi * c; *(++y) = - vi * c + wi * s; + } + ColumnVector A; RealFFTI(X, Y, A); + X.CleanUp(); Y.CleanUp(); U.ReSize(n); + Real* a = A.Store(); Real* b = a + n; Real* u = U.Store(); + i = n2; + while (i--) { *u++ = *a++; *u++ = -(*(--b)); } +} + +void DCT_inverse(const ColumnVector& V, ColumnVector& U) +{ + // Inverse of discrete cosine transform, type I + Tracer trace("DCT_inverse"); + REPORT + const int n = V.Nrows()-1; // length of transform + const int n2 = n / 2; const int n21 = n2 + 1; + if (n != 2 * n2) + Throw(ProgramException("Vector length not multiple of 2", V)); + ColumnVector X(n21), Y(n21); + Real* x = X.Store(); Real* y = Y.Store(); Real* v = V.Store(); + Real vi = *v++; *x++ = vi; *y++ = 0.0; + Real sum1 = vi / 2.0; Real sum2 = sum1; vi = *v++; + int i = n2-1; + while (i--) + { + Real vi2 = *v++; sum1 += vi2 + vi; sum2 += vi2 - vi; + *x++ = vi2; vi2 = *v++; *y++ = vi - vi2; vi = vi2; + } + sum1 += vi; sum2 -= vi; + vi = *v; *x = vi; *y = 0.0; vi /= 2.0; sum1 += vi; sum2 += vi; + ColumnVector A; RealFFTI(X, Y, A); + X.CleanUp(); Y.CleanUp(); U.ReSize(n+1); + Real* a = A.Store(); Real* b = a + n; Real* u = U.Store(); v = u + n; + i = n2; int k = 0; *u++ = sum1 / n2; *v-- = sum2 / n2; + while (i--) + { + Real s = sin(1.5707963267948966192 * (++k) / n2); + Real ai = *(++a); Real bi = *(--b); + Real bz = (ai - bi) / 4 / s; Real az = (ai + bi) / 2; + *u++ = az - bz; *v-- = az + bz; + } +} + +void DCT(const ColumnVector& U, ColumnVector& V) +{ + // Discrete cosine transform, type I + Tracer trace("DCT"); + REPORT + DCT_inverse(U, V); + V *= (V.Nrows()-1)/2; +} + +void DST_inverse(const ColumnVector& V, ColumnVector& U) +{ + // Inverse of discrete sine transform, type I + Tracer trace("DST_inverse"); + REPORT + const int n = V.Nrows()-1; // length of transform + const int n2 = n / 2; const int n21 = n2 + 1; + if (n != 2 * n2) + Throw(ProgramException("Vector length not multiple of 2", V)); + ColumnVector X(n21), Y(n21); + Real* x = X.Store(); Real* y = Y.Store(); Real* v = V.Store(); + Real vi = *(++v); *x++ = 2 * vi; *y++ = 0.0; + int i = n2-1; + while (i--) { *y++ = *(++v); Real vi2 = *(++v); *x++ = vi2 - vi; vi = vi2; } + *x = -2 * vi; *y = 0.0; + ColumnVector A; RealFFTI(X, Y, A); + X.CleanUp(); Y.CleanUp(); U.ReSize(n+1); + Real* a = A.Store(); Real* b = a + n; Real* u = U.Store(); v = u + n; + i = n2; int k = 0; *u++ = 0.0; *v-- = 0.0; + while (i--) + { + Real s = sin(1.5707963267948966192 * (++k) / n2); + Real ai = *(++a); Real bi = *(--b); + Real az = (ai + bi) / 4 / s; Real bz = (ai - bi) / 2; + *u++ = az - bz; *v-- = az + bz; + } +} + +void DST(const ColumnVector& U, ColumnVector& V) +{ + // Discrete sine transform, type I + Tracer trace("DST"); + REPORT + DST_inverse(U, V); + V *= (V.Nrows()-1)/2; +} + +// Two dimensional FFT +void FFT2(const Matrix& U, const Matrix& V, Matrix& X, Matrix& Y) +{ + Tracer trace("FFT2"); + REPORT + int m = U.Nrows(); int n = U.Ncols(); + if (m != V.Nrows() || n != V.Ncols() || m == 0 || n == 0) + Throw(ProgramException("Matrix dimensions unequal or zero", U, V)); + X = U; Y = V; + int i; ColumnVector CVR; ColumnVector CVI; + for (i = 1; i <= m; ++i) + { + FFT(X.Row(i).t(), Y.Row(i).t(), CVR, CVI); + X.Row(i) = CVR.t(); Y.Row(i) = CVI.t(); + } + for (i = 1; i <= n; ++i) + { + FFT(X.Column(i), Y.Column(i), CVR, CVI); + X.Column(i) = CVR; Y.Column(i) = CVI; + } +} + +void FFT2I(const Matrix& U, const Matrix& V, Matrix& X, Matrix& Y) +{ + // Inverse transform + Tracer trace("FFT2I"); + REPORT + FFT2(U,-V,X,Y); + const Real n = X.Nrows() * X.Ncols(); X /= n; Y /= (-n); +} + + +#ifdef use_namespace +} +#endif + + diff --git a/Utilities/OSSIM/ossim_core/matrix/gnu.mak b/Utilities/OSSIM/ossim_core/matrix/gnu.mak new file mode 100644 index 0000000000..e1cbb19e7f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/gnu.mak @@ -0,0 +1,154 @@ +CXX = g++ +CXXFLAGS = -O2 -Wall + +everything: libnewmat.a tmt example nl_ex sl_ex garch test_exc + + +%.o: %.cpp + $(CXX) $(CXXFLAGS) -c $*.cpp + +OBJ_LIB = bandmat.o cholesky.o evalue.o fft.o hholder.o \ + jacobi.o myexcept.o newmat1.o newmat2.o newmat3.o \ + newmat4.o newmat5.o newmat6.o newmat7.o newmat8.o \ + newmat9.o newmatex.o newmatnl.o newmatrm.o solution.o \ + sort.o submat.o svd.o newfft.o + +libnewmat.a: $(OBJ_LIB) + $(AR) cr $@ $(OBJ_LIB) + ranlib $@ + +OBJ_T = tmt.o tmt1.o tmt2.o tmt3.o tmt4.o tmt5.o tmt6.o \ + tmt7.o tmt8.o tmt9.o tmta.o tmtb.o tmtc.o tmtd.o tmte.o \ + tmtf.o tmtg.o tmth.o tmti.o tmtj.o tmtk.o tmtl.o + +tmt: $(OBJ_T) libnewmat.a + $(CXX) -o $@ $(OBJ_T) -L. -lnewmat -lm + +OBJ_E = example.o + +example: $(OBJ_E) libnewmat.a + $(CXX) -o $@ $(OBJ_E) -L. -lnewmat -lm + +OBJ_N = nl_ex.o + +nl_ex: $(OBJ_N) libnewmat.a + $(CXX) -o $@ $(OBJ_N) -L. -lnewmat -lm + +OBJ_S = sl_ex.o + +sl_ex: $(OBJ_S) libnewmat.a + $(CXX) -o $@ $(OBJ_S) -L. -lnewmat -lm + +OBJ_G = garch.o + +garch: $(OBJ_G) libnewmat.a + $(CXX) -o $@ $(OBJ_G) -L. -lnewmat -lm + +OBJ_X = test_exc.o + +test_exc: $(OBJ_X) libnewmat.a + $(CXX) -o $@ $(OBJ_X) -L. -lnewmat -lm + +newmatxx = include.h newmat.h boolean.h myexcept.h + +myexcept.o: include.h boolean.h myexcept.h myexcept.cpp + +newmatex.o: $(newmatxx) newmatex.cpp + +newmatnl.o: $(newmatxx) newmatnl.h newmatap.h + +example.o: $(newmatxx) newmatap.h example.cpp + +cholesky.o: $(newmatxx) cholesky.cpp + +evalue.o: $(newmatxx) newmatrm.h precisio.h evalue.cpp + +fft.o: $(newmatxx) newmatap.h fft.cpp + +hholder.o: $(newmatxx) newmatap.h hholder.cpp + +jacobi.o: $(newmatxx) precisio.h newmatrm.h jacobi.cpp + +bandmat.o: $(newmatxx) newmatrc.h controlw.h bandmat.cpp + +newfft.o: $(newmatxx) newmatap.h newfft.cpp + +newmat1.o: $(newmatxx) newmat1.cpp + +newmat2.o: $(newmatxx) newmatrc.h controlw.h newmat2.cpp + +newmat3.o: $(newmatxx) newmatrc.h controlw.h newmat3.cpp + +newmat4.o: $(newmatxx) newmatrc.h controlw.h newmat4.cpp + +newmat5.o: $(newmatxx) newmatrc.h controlw.h newmat5.cpp + +newmat6.o: $(newmatxx) newmatrc.h controlw.h newmat6.cpp + +newmat7.o: $(newmatxx) newmatrc.h controlw.h newmat7.cpp + +newmat8.o: $(newmatxx) newmatap.h newmat8.cpp + +newmat9.o: $(newmatxx) newmatrc.h controlw.h newmatio.h newmat9.cpp + +newmatrm.o: $(newmatxx) newmatrm.h newmatrm.cpp + +sort.o: $(newmatxx) newmatap.h sort.cpp + +submat.o: $(newmatxx) newmatrc.h controlw.h submat.cpp + +svd.o: $(newmatxx) newmatrm.h precisio.h svd.cpp + +tmt.o: $(newmatxx) newmatap.h tmt.cpp + +tmt1.o: $(newmatxx) newmatap.h tmt1.cpp + +tmt2.o: $(newmatxx) newmatap.h tmt2.cpp + +tmt3.o: $(newmatxx) newmatap.h tmt3.cpp + +tmt4.o: $(newmatxx) newmatap.h tmt4.cpp + +tmt5.o: $(newmatxx) newmatap.h tmt5.cpp + +tmt6.o: $(newmatxx) newmatap.h tmt6.cpp + +tmt7.o: $(newmatxx) newmatap.h tmt7.cpp + +tmt8.o: $(newmatxx) newmatap.h tmt8.cpp + +tmt9.o: $(newmatxx) newmatap.h tmt9.cpp + +tmta.o: $(newmatxx) newmatap.h tmta.cpp + +tmtb.o: $(newmatxx) newmatap.h tmtb.cpp + +tmtc.o: $(newmatxx) newmatap.h tmtc.cpp + +tmtd.o: $(newmatxx) newmatap.h tmtd.cpp + +tmte.o: $(newmatxx) newmatap.h tmte.cpp + +tmtf.o: $(newmatxx) newmatap.h tmtf.cpp + +tmtg.o: $(newmatxx) newmatap.h tmtg.cpp + +tmth.o: $(newmatxx) newmatap.h tmth.cpp + +tmti.o: $(newmatxx) newmatap.h tmti.cpp + +tmtj.o: $(newmatxx) newmatap.h tmtj.cpp + +tmtk.o: $(newmatxx) newmatap.h tmtk.cpp + +tmtl.o: $(newmatxx) newmatap.h tmtl.cpp + +nl_ex.o: $(newmatxx) newmatap.h newmatnl.h nl_ex.cpp + +sl_ex.o: include.h boolean.h myexcept.h sl_ex.cpp + +solution.o: include.h boolean.h myexcept.h solution.cpp + +garch.o: $(newmatxx) newmatap.h newmatnl.h garch.cpp + +test_exc.o: $(newmatxx) test_exc.cpp diff --git a/Utilities/OSSIM/ossim_core/matrix/hholder.cpp b/Utilities/OSSIM/ossim_core/matrix/hholder.cpp new file mode 100644 index 0000000000..1e8a2ac01a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/hholder.cpp @@ -0,0 +1,331 @@ +//$$ hholder.cpp QR decomposition + +// Copyright (C) 1991,2,3,4: R B Davies + +#define WANT_MATH +//#define WANT_STREAM + +#include "include.h" + +#include "newmatap.h" + +#ifdef use_namespace +namespace NEWMAT { +#endif + +#ifdef DO_REPORT +#define REPORT { static ExeCounter ExeCount(__LINE__,16); ++ExeCount; } +#else +#define REPORT {} +#endif + + +/*************************** QR decompositions ***************************/ + +inline Real square(Real x) { return x*x; } + +void QRZT(Matrix& X, LowerTriangularMatrix& L) +{ + REPORT + Tracer et("QRZT(1)"); + int n = X.Ncols(); int s = X.Nrows(); L.ReSize(s); + Real* xi = X.Store(); int k; + for (int i=0; i<s; i++) + { + Real sum = 0.0; + Real* xi0=xi; k=n; while(k--) { sum += square(*xi++); } + sum = sqrt(sum); + if (sum == 0.0) + { + REPORT + k=n; while(k--) { *xi0++ = 0.0; } + for (int j=i; j<s; j++) L.element(j,i) = 0.0; + } + else + { + L.element(i,i) = sum; + Real* xj0=xi0; k=n; while(k--) { *xj0++ /= sum; } + for (int j=i+1; j<s; j++) + { + sum=0.0; + xi=xi0; Real* xj=xj0; k=n; while(k--) { sum += *xi++ * *xj++; } + xi=xi0; k=n; while(k--) { *xj0++ -= sum * *xi++; } + L.element(j,i) = sum; + } + } + } +} + +void QRZT(const Matrix& X, Matrix& Y, Matrix& M) +{ + REPORT + Tracer et("QRZT(2)"); + int n = X.Ncols(); int s = X.Nrows(); int t = Y.Nrows(); + if (Y.Ncols() != n) + { Throw(ProgramException("Unequal row lengths",X,Y)); } + M.ReSize(t,s); + Real* xi = X.Store(); int k; + for (int i=0; i<s; i++) + { + Real* xj0 = Y.Store(); Real* xi0 = xi; + for (int j=0; j<t; j++) + { + Real sum=0.0; + xi=xi0; Real* xj=xj0; k=n; while(k--) { sum += *xi++ * *xj++; } + xi=xi0; k=n; while(k--) { *xj0++ -= sum * *xi++; } + M.element(j,i) = sum; + } + } +} + +/* +void QRZ(Matrix& X, UpperTriangularMatrix& U) +{ + Tracer et("QRZ(1)"); + int n = X.Nrows(); int s = X.Ncols(); U.ReSize(s); + Real* xi0 = X.Store(); int k; + for (int i=0; i<s; i++) + { + Real sum = 0.0; + Real* xi = xi0; k=n; while(k--) { sum += square(*xi); xi+=s; } + sum = sqrt(sum); + U.element(i,i) = sum; + if (sum==0.0) Throw(SingularException(U)); + Real* xj0=xi0; k=n; while(k--) { *xj0 /= sum; xj0+=s; } + xj0 = xi0; + for (int j=i+1; j<s; j++) + { + sum=0.0; + xi=xi0; k=n; xj0++; Real* xj=xj0; + while(k--) { sum += *xi * *xj; xi+=s; xj+=s; } + xi=xi0; k=n; xj=xj0; + while(k--) { *xj -= sum * *xi; xj+=s; xi+=s; } + U.element(i,j) = sum; + } + xi0++; + } +} +*/ + +void QRZ(Matrix& X, UpperTriangularMatrix& U) +{ + REPORT + Tracer et("QRZ(1)"); + int n = X.Nrows(); int s = X.Ncols(); U.ReSize(s); U = 0.0; + Real* xi0 = X.Store(); Real* u0 = U.Store(); Real* u; + int j, k; int J = s; int i = s; + while (i--) + { + Real* xj0 = xi0; Real* xi = xi0; k = n; + if (k) for (;;) + { + u = u0; Real Xi = *xi; Real* xj = xj0; + j = J; while(j--) *u++ += Xi * *xj++; + if (!(--k)) break; + xi += s; xj0 += s; + } + + Real sum = sqrt(*u0); *u0 = sum; u = u0+1; + if (sum == 0.0) + { + REPORT + j = J - 1; while(j--) *u++ = 0.0; + + xj0 = xi0++; k = n; + if (k) for (;;) + { + *xj0 = 0.0; + if (!(--k)) break; + xj0 += s; + } + u0 += J--; + } + else + { + int J1 = J-1; j = J1; while(j--) *u++ /= sum; + + xj0 = xi0; xi = xi0++; k = n; + if (k) for (;;) + { + u = u0+1; Real Xi = *xi; Real* xj = xj0; + Xi /= sum; *xj++ = Xi; + j = J1; while(j--) *xj++ -= *u++ * Xi; + if (!(--k)) break; + xi += s; xj0 += s; + } + u0 += J--; + } + } +} + +void QRZ(const Matrix& X, Matrix& Y, Matrix& M) +{ + REPORT + Tracer et("QRZ(2)"); + int n = X.Nrows(); int s = X.Ncols(); int t = Y.Ncols(); + if (Y.Nrows() != n) + { Throw(ProgramException("Unequal column lengths",X,Y)); } + M.ReSize(s,t); M = 0;Real* m0 = M.Store(); Real* m; + Real* xi0 = X.Store(); + int j, k; int i = s; + while (i--) + { + Real* xj0 = Y.Store(); Real* xi = xi0; k = n; + if (k) for (;;) + { + m = m0; Real Xi = *xi; Real* xj = xj0; + j = t; while(j--) *m++ += Xi * *xj++; + if (!(--k)) break; + xi += s; xj0 += t; + } + + xj0 = Y.Store(); xi = xi0++; k = n; + if (k) for (;;) + { + m = m0; Real Xi = *xi; Real* xj = xj0; + j = t; while(j--) *xj++ -= *m++ * Xi; + if (!(--k)) break; + xi += s; xj0 += t; + } + m0 += t; + } +} + +/* + +void QRZ(const Matrix& X, Matrix& Y, Matrix& M) +{ + Tracer et("QRZ(2)"); + int n = X.Nrows(); int s = X.Ncols(); int t = Y.Ncols(); + if (Y.Nrows() != n) + { Throw(ProgramException("Unequal column lengths",X,Y)); } + M.ReSize(s,t); + Real* xi0 = X.Store(); int k; + for (int i=0; i<s; i++) + { + Real* xj0 = Y.Store(); + for (int j=0; j<t; j++) + { + Real sum=0.0; + Real* xi=xi0; Real* xj=xj0; k=n; + while(k--) { sum += *xi * *xj; xi+=s; xj+=t; } + xi=xi0; k=n; xj=xj0++; + while(k--) { *xj -= sum * *xi; xj+=t; xi+=s; } + M.element(i,j) = sum; + } + xi0++; + } +} +*/ + +void UpdateQRZT(Matrix& X, LowerTriangularMatrix& L) +{ + REPORT + Tracer et("UpdateQRZT"); + int n = X.Ncols(); int s = X.Nrows(); + if (s != L.Nrows()) + Throw(ProgramException("Incompatible dimensions",X,L)); + Real* xi = X.Store(); int k; + for (int i=0; i<s; i++) + { + Real r = L.element(i,i); + Real sum = 0.0; + Real* xi0=xi; k=n; while(k--) { sum += square(*xi++); } + sum = sqrt(sum + square(r)); + if (sum == 0.0) + { + REPORT + k=n; while(k--) { *xi0++ = 0.0; } + for (int j=i; j<s; j++) L.element(j,i) = 0.0; + } + else + { + Real frs = fabs(r) + sum; + Real a0 = sqrt(frs / sum); Real alpha = a0 / frs; + if (r <= 0) { REPORT L.element(i,i) = sum; alpha = -alpha; } + else { REPORT L.element(i,i) = -sum; } + Real* xj0=xi0; k=n; while(k--) { *xj0++ *= alpha; } + for (int j=i+1; j<s; j++) + { + sum = 0.0; + xi=xi0; Real* xj=xj0; k=n; while(k--) { sum += *xi++ * *xj++; } + sum += a0 * L.element(j,i); + xi=xi0; k=n; while(k--) { *xj0++ -= sum * *xi++; } + L.element(j,i) -= sum * a0; + } + } + } +} + +void UpdateQRZ(Matrix& X, UpperTriangularMatrix& U) +{ + REPORT + Tracer et("UpdateQRZ"); + int n = X.Nrows(); int s = X.Ncols(); + if (s != U.Ncols()) + Throw(ProgramException("Incompatible dimensions",X,U)); + Real* xi0 = X.Store(); Real* u0 = U.Store(); Real* u; + RowVector V(s); Real* v0 = V.Store(); Real* v; V = 0.0; + int j, k; int J = s; int i = s; + while (i--) + { + Real* xj0 = xi0; Real* xi = xi0; k = n; + if (k) for (;;) + { + v = v0; Real Xi = *xi; Real* xj = xj0; + j = J; while(j--) *v++ += Xi * *xj++; + if (!(--k)) break; + xi += s; xj0 += s; + } + + Real r = *u0; + Real sum = sqrt(*v0 + square(r)); + + if (sum == 0.0) + { + REPORT + u = u0; v = v0; + j = J; while(j--) { *u++ = 0.0; *v++ = 0.0; } + xj0 = xi0++; k = n; + if (k) for (;;) + { + *xj0 = 0.0; + if (!(--k)) break; + xj0 += s; + } + u0 += J--; + } + else + { + Real frs = fabs(r) + sum; + Real a0 = sqrt(frs / sum); Real alpha = a0 / frs; + if (r <= 0) { REPORT alpha = -alpha; *u0 = sum; } + else { REPORT *u0 = -sum; } + + j = J - 1; v = v0 + 1; u = u0 + 1; + while (j--) + { *v = a0 * *u + alpha * *v; *u -= a0 * *v; ++v; ++u; } + + xj0 = xi0; xi = xi0++; k = n; + if (k) for (;;) + { + v = v0 + 1; Real Xi = *xi; Real* xj = xj0; + Xi *= alpha; *xj++ = Xi; + j = J - 1; while(j--) *xj++ -= *v++ * Xi; + if (!(--k)) break; + xi += s; xj0 += s; + } + + j = J; v = v0; + while (j--) *v++ = 0.0; + + u0 += J--; + } + } +} + + +#ifdef use_namespace +} +#endif + diff --git a/Utilities/OSSIM/ossim_core/matrix/include.h b/Utilities/OSSIM/ossim_core/matrix/include.h new file mode 100644 index 0000000000..5b71e266e3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/include.h @@ -0,0 +1,313 @@ +//$$ include.h include files required by various versions of C++ + +#ifndef INCLUDE_LIB +#define INCLUDE_LIB +#define use_namespace // define name spaces +#include <base/common/ossimConstants.h> +#define SETUP_C_SUBSCRIPTS // allow element access via A[i][j] + +// Activate just one of the following 3 statements + +//#define SimulateExceptions // use simulated exceptions +//#define UseExceptions // use C++ exceptions +#define DisableExceptions // do not use exceptions + + +//#define TEMPS_DESTROYED_QUICKLY // for compilers that delete + // temporaries too quickly + +//#define TEMPS_DESTROYED_QUICKLY_R // the same thing but applied + // to return from functions only + +//#define DO_FREE_CHECK // check news and deletes balance + +#define USING_DOUBLE // elements of type double +//#define USING_FLOAT // elements of type float + +#define bool_LIB 0 // for compatibility with my older libraries + +//#define ios_format_flags ios::fmtflags // for Gnu 3 and Intel for Linux + + +//#define _STANDARD_ // using standard library + +//#define use_float_h // use float.h for precision data + + +//#define HAS_INT64 // if unsigned _int64 is recognised + // used by newran03 + +// comment out next line if Exception causes a problem +#define TypeDefException + +//*********************** end of options set by user ******************** + + +// for Gnu C++ version 3 +#if defined __GNUG__ && __GNUG__ >= 3 + #define _STANDARD_ // use standard library + #define ios_format_flags ios::fmtflags +#endif + +// for Intel C++ for Linux +#if defined __ICC + #define _STANDARD_ // use standard library + #define ios_format_flags ios::fmtflags +#endif + +#ifdef __BORLANDC__ +#define _STANDARD_ +#endif + +#ifdef _STANDARD_ // using standard library + #include <cstdlib> + #ifdef _MSC_VER + #include <limits> // for VC++6 + #endif + #ifdef WANT_STREAM + #include <iostream> + #include <iomanip> + #endif + #ifdef WANT_MATH + #include <cmath> + #endif + #ifdef WANT_STRING + #include <cstring> + #endif + #ifdef WANT_TIME + #include <ctime> + #endif + #ifdef WANT_FSTREAM + #include <fstream> + #endif + using namespace std; +#else + +#define DEFAULT_HEADER // use AT&T style header + // if no other compiler is recognised + +#ifdef _MSC_VER // Microsoft + #include <stdlib.h> + + // reactivate these statements to run under MSC version 7.0 +// typedef int jmp_buf[9]; +// extern "C" +// { +// int __cdecl setjmp(jmp_buf); +// void __cdecl longjmp(jmp_buf, int); +// } + + #ifdef WANT_STREAM + #include <iostream> + #include <iomanip> + #endif + #ifdef WANT_MATH + #include <math.h> + #include <float.h> + #endif + #ifdef WANT_STRING + #include <string.h> + #endif + #ifdef WANT_TIME + #include <time.h> + #endif + #ifdef WANT_FSTREAM + #include <fstream.h> + #endif + #undef DEFAULT_HEADER +#endif + +#ifdef __ZTC__ // Zortech + #include <stdlib.h> + #ifdef WANT_STREAM + #include <iostream.hpp> + #include <iomanip.hpp> + #define flush "" // not defined in iomanip? + #endif + #ifdef WANT_MATH + #include <math.h> + #include <float.h> + #endif + #ifdef WANT_STRING + #include <string.h> + #endif + #ifdef WANT_TIME + #include <time.h> + #endif + #ifdef WANT_FSTREAM + #include <fstream.h> + #endif + #undef DEFAULT_HEADER +#endif + +#if defined __BCPLUSPLUS__ || defined __TURBOC__ // Borland or Turbo + #include <stdlib.h> + #ifdef WANT_STREAM + #include <iostream.h> + #include <iomanip.h> + #endif + #ifdef WANT_MATH + #include <math.h> + #include <float.h> // Borland has both float and values + // but values.h returns +INF for + // MAXDOUBLE in BC5 + #endif + #ifdef WANT_STRING + #include <string.h> + #endif + #ifdef WANT_TIME + #include <time.h> + #endif + #ifdef WANT_FSTREAM + #include <fstream.h> + #endif + #undef DEFAULT_HEADER +#endif + +#ifdef __GNUG__ // Gnu C++ + #include <stdlib.h> + #ifdef WANT_STREAM + #include <iostream.h> + #include <iomanip.h> + #endif + #ifdef WANT_MATH + #include <math.h> + #include <float.h> + #endif + #ifdef WANT_STRING + #include <string.h> + #endif + #ifdef WANT_TIME + #include <time.h> + #endif + #ifdef WANT_FSTREAM + #include <fstream.h> + #endif + #undef DEFAULT_HEADER +#endif + +#ifdef __WATCOMC__ // Watcom C/C++ + #include <stdlib.h> + #ifdef WANT_STREAM + #include <iostream.h> + #include <iomanip.h> + #endif + #ifdef WANT_MATH + #include <math.h> + #include <float.h> + #endif + #ifdef WANT_STRING + #include <string.h> + #endif + #ifdef WANT_TIME + #include <time.h> + #endif + #ifdef WANT_FSTREAM + #include <fstream.h> + #endif + #undef DEFAULT_HEADER +#endif + + +#ifdef macintosh // MPW C++ on the Mac +#include <stdlib.h> +#ifdef WANT_STREAM +#include <iostream.h> +#include <iomanip.h> +#endif +#ifdef WANT_MATH +#include <float.h> +#include <math.h> +#endif +#ifdef WANT_STRING +#include <string.h> +#endif +#ifdef WANT_TIME +#include <time.h> +#endif +#ifdef WANT_FSTREAM +#include <fstream.h> +#endif +#undef DEFAULT_HEADER +#endif + +#ifdef use_float_h // use float.h for precision values +#include <stdlib.h> +#ifdef WANT_STREAM +#include <iostream.h> +#include <iomanip.h> +#endif +#ifdef WANT_MATH +#include <float.h> +#include <math.h> +#endif +#ifdef WANT_STRING +#include <string.h> +#endif +#ifdef WANT_TIME +#include <time.h> +#endif +#ifdef WANT_FSTREAM +#include <fstream.h> +#endif +#undef DEFAULT_HEADER +#endif + + +#ifdef DEFAULT_HEADER // for example AT&T +#define ATandT +#include <stdlib.h> +#ifdef WANT_STREAM +#include <iostream.h> +#include <iomanip.h> +#endif +#ifdef WANT_MATH +#include <math.h> +#define SystemV // use System V +#include <values.h> +#endif +#ifdef WANT_STRING +#include <string.h> +#endif +#ifdef WANT_TIME +#include <time.h> +#endif +#ifdef WANT_FSTREAM +#include <fstream.h> +#endif +#endif // DEFAULT_HEADER + +#endif // _STANDARD_ + +#ifdef use_namespace +namespace RBD_COMMON { +#endif + + +#ifdef USING_FLOAT // set precision type to float +typedef float Real; +typedef double long_Real; +#endif + +#ifdef USING_DOUBLE // set precision type to double +typedef double Real; +//typedef long double long_Real; +typedef double long_Real; +#endif + + +#ifdef use_namespace +} +#endif + + +#ifdef use_namespace +namespace RBD_COMMON {} +namespace RBD_LIBRARIES // access all my libraries +{ + using namespace RBD_COMMON; +} +#endif + + +#endif diff --git a/Utilities/OSSIM/ossim_core/matrix/jacobi.cpp b/Utilities/OSSIM/ossim_core/matrix/jacobi.cpp new file mode 100644 index 0000000000..fc4b7661ff --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/jacobi.cpp @@ -0,0 +1,123 @@ +//$$jacobi.cpp jacobi eigenvalue analysis + +// Copyright (C) 1991,2,3,4: R B Davies + + +//#define WANT_STREAM + + +#define WANT_MATH + +#include "include.h" +#include "newmatap.h" +#include "precisio.h" +#include "newmatrm.h" + +#ifdef use_namespace +namespace NEWMAT { +#endif + +#ifdef DO_REPORT +#define REPORT { static ExeCounter ExeCount(__LINE__,18); ++ExeCount; } +#else +#define REPORT {} +#endif + + +void Jacobi(const SymmetricMatrix& X, DiagonalMatrix& D, SymmetricMatrix& A, + Matrix& V, bool eivec) +{ + Real epsilon = FloatingPointPrecision::Epsilon(); + Tracer et("Jacobi"); + REPORT + int n = X.Nrows(); DiagonalMatrix B(n), Z(n); D.ReSize(n); A = X; + if (eivec) { REPORT V.ReSize(n,n); D = 1.0; V = D; } + B << A; D = B; Z = 0.0; A.Inject(Z); + bool converged = false; + for (int i=1; i<=50; i++) + { + Real sm=0.0; Real* a = A.Store(); int p = A.Storage(); + while (p--) sm += fabs(*a++); // have previously zeroed diags + if (sm==0.0) { REPORT converged = true; break; } + Real tresh = (i<4) ? 0.2 * sm / square(n) : 0.0; a = A.Store(); + for (p = 0; p < n; p++) + { + Real* ap1 = a + (p*(p+1))/2; + Real& zp = Z.element(p); Real& dp = D.element(p); + for (int q = p+1; q < n; q++) + { + Real* ap = ap1; Real* aq = a + (q*(q+1))/2; + Real& zq = Z.element(q); Real& dq = D.element(q); + Real& apq = A.element(q,p); + Real g = 100 * fabs(apq); Real adp = fabs(dp); Real adq = fabs(dq); + + if (i>4 && g < epsilon*adp && g < epsilon*adq) { REPORT apq = 0.0; } + else if (fabs(apq) > tresh) + { + REPORT + Real t; Real h = dq - dp; Real ah = fabs(h); + if (g < epsilon*ah) { REPORT t = apq / h; } + else + { + REPORT + Real theta = 0.5 * h / apq; + t = 1.0 / ( fabs(theta) + sqrt(1.0 + square(theta)) ); + if (theta<0.0) { REPORT t = -t; } + } + Real c = 1.0 / sqrt(1.0 + square(t)); Real s = t * c; + Real tau = s / (1.0 + c); h = t * apq; + zp -= h; zq += h; dp -= h; dq += h; apq = 0.0; + int j = p; + while (j--) + { + g = *ap; h = *aq; + *ap++ = g-s*(h+g*tau); *aq++ = h+s*(g-h*tau); + } + int ip = p+1; j = q-ip; ap += ip++; aq++; + while (j--) + { + g = *ap; h = *aq; + *ap = g-s*(h+g*tau); *aq++ = h+s*(g-h*tau); + ap += ip++; + } + if (q < n-1) // last loop is non-empty + { + int iq = q+1; j = n-iq; ap += ip++; aq += iq++; + for (;;) + { + g = *ap; h = *aq; + *ap = g-s*(h+g*tau); *aq = h+s*(g-h*tau); + if (!(--j)) break; + ap += ip++; aq += iq++; + } + } + if (eivec) + { + REPORT + RectMatrixCol VP(V,p); RectMatrixCol VQ(V,q); + Rotate(VP, VQ, tau, s); + } + } + } + } + B = B + Z; D = B; Z = 0.0; + } + if (!converged) Throw(ConvergenceException(X)); + if (eivec) SortSV(D, V, true); + else SortAscending(D); +} + +void Jacobi(const SymmetricMatrix& X, DiagonalMatrix& D) +{ REPORT SymmetricMatrix A; Matrix V; Jacobi(X,D,A,V,false); } + +void Jacobi(const SymmetricMatrix& X, DiagonalMatrix& D, SymmetricMatrix& A) +{ REPORT Matrix V; Jacobi(X,D,A,V,false); } + +void Jacobi(const SymmetricMatrix& X, DiagonalMatrix& D, Matrix& V) +{ REPORT SymmetricMatrix A; Jacobi(X,D,A,V,true); } + + +#ifdef use_namespace +} +#endif + diff --git a/Utilities/OSSIM/ossim_core/matrix/ms.mak b/Utilities/OSSIM/ossim_core/matrix/ms.mak new file mode 100644 index 0000000000..398e95ddba --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/ms.mak @@ -0,0 +1,201 @@ +.SUFFIXES: .cpp + + +everything: tmt.exe example.exe nl_ex.exe sl_ex.exe garch.exe test_exc.exe + +.cpp.obj: + cl -AL -c $*.cpp + +OBJ_LIB = bandmat.obj cholesky.obj evalue.obj fft.obj hholder.obj \ + jacobi.obj myexcept.obj newmat1.obj newmat2.obj newmat3.obj \ + newmat4.obj newmat5.obj newmat6.obj newmat7.obj newmat8.obj \ + newmat9.obj newmatex.obj newmatnl.obj newmatrm.obj solution.obj \ + sort.obj submat.obj svd.obj newfft.obj + +OBJ_T = tmt.obj tmt1.obj tmt2.obj tmt3.obj tmt4.obj tmt5.obj tmt6.obj \ + tmt7.obj tmt8.obj tmt9.obj tmta.obj tmtb.obj tmtc.obj tmtd.obj tmte.obj \ + tmtf.obj tmtg.obj tmth.obj tmti.obj tmtj.obj tmtk.obj tmtl.obj + +tmt.exe: $(OBJ_T) $(OBJ_LIB) + echo newmat1.obj+newmat2.obj+newmat3.obj+ > link.lnk + echo newmat4.obj+svd.obj+newmat5.obj+ >> link.lnk + echo newmat6.obj+newmat7.obj+newmat8.obj+ >> link.lnk + echo tmt.obj+tmt1.obj+tmt2.obj+tmt3.obj+ >> link.lnk + echo tmt4.obj+tmt5.obj+tmt6.obj+tmt7.obj+ >> link.lnk + echo tmt8.obj+tmt9.obj+tmta.obj+tmti.obj+ >> link.lnk + echo tmtb.obj+tmtc.obj+tmtd.obj+tmte.obj+ >> link.lnk + echo tmtf.obj+tmtg.obj+tmth.obj+tmtj.obj+ >> link.lnk + echo tmtk.obj+tmtl.obj+ >> link.lnk + echo cholesky.obj+hholder.obj+sort.obj+ >> link.lnk + echo submat.obj+jacobi.obj+newmatrm.obj+ >> link.lnk + echo fft.obj+evalue.obj+bandmat.obj+ >> link.lnk + echo newmatex.obj+myexcept.obj+newfft.obj, >> link.lnk + echo tmt.exe; >> link.lnk + link @link.lnk + +OBJ_E = example.obj + +example.exe: $(OBJ_E) $(OBJ_LIB) + echo newmat1.obj+newmat2.obj+newmat3.obj+ > link.lnk + echo newmat4.obj+svd.obj+newmat5.obj+ >> link.lnk + echo newmat6.obj+newmat7.obj+newmat8.obj+ >> link.lnk + echo cholesky.obj+hholder.obj+sort.obj+ >> link.lnk + echo submat.obj+jacobi.obj+newmatrm.obj+ >> link.lnk + echo fft.obj+evalue.obj+bandmat.obj+ >> link.lnk + echo newmatex.obj+myexcept.obj+newmat9+ >> link.lnk + echo newfft.obj+example.obj, >> link.lnk + echo example.exe; >> link.lnk + link @link.lnk + +OBJ_N = nl_ex.obj + +nl_ex.exe: $(OBJ_N) $(OBJ_LIB) + echo newmat1.obj+newmat2.obj+newmat3.obj+ > link.lnk + echo newmat4.obj+svd.obj+newmat5.obj+ >> link.lnk + echo newmat6.obj+newmat7.obj+newmat8.obj+ >> link.lnk + echo cholesky.obj+hholder.obj+sort.obj+ >> link.lnk + echo submat.obj+jacobi.obj+newmatrm.obj+ >> link.lnk + echo fft.obj+evalue.obj+bandmat.obj+ >> link.lnk + echo newmatex.obj+myexcept.obj+newmat9.obj+ >> link.lnk + echo newmatnl.obj+nl_ex.obj+newfft.obj, >> link.lnk + echo nl_ex.exe; >> link.lnk + link @link.lnk + +OBJ_S = sl_ex.obj + +sl_ex.exe: $(OBJ_S) $(OBJ_LIB) + echo solution.obj+myexcept.obj+sl_ex.obj, > link.lnk + echo sl_ex.exe; >> link.lnk + link @link.lnk + +OBJ_G = garch.obj + +garch.exe: $(OBJ_G) $(OBJ_LIB) + echo newmat1.obj+newmat2.obj+newmat3.obj+ > link.lnk + echo newmat4.obj+svd.obj+newmat5.obj+ >> link.lnk + echo newmat6.obj+newmat7.obj+newmat8.obj+ >> link.lnk + echo cholesky.obj+hholder.obj+sort.obj+ >> link.lnk + echo submat.obj+jacobi.obj+newmatrm.obj+ >> link.lnk + echo fft.obj+evalue.obj+bandmat.obj+ >> link.lnk + echo newmatex.obj+myexcept.obj+newmat9.obj+ >> link.lnk + echo newmatnl.obj+garch.obj+newfft.obj, >> link.lnk + echo garch.exe; >> link.lnk + link @link.lnk + +OBJ_X = test_exc.obj + +test_exc.exe: $(OBJ_X) $(OBJ_LIB) + echo newmat1.obj+newmat2.obj+newmat3.obj+ > link.lnk + echo newmat4.obj+svd.obj+newmat5.obj+ >> link.lnk + echo newmat6.obj+newmat7.obj+newmat8.obj+ >> link.lnk + echo cholesky.obj+hholder.obj+sort.obj+ >> link.lnk + echo submat.obj+jacobi.obj+newmatrm.obj+ >> link.lnk + echo fft.obj+evalue.obj+bandmat.obj+ >> link.lnk + echo newmatex.obj+myexcept.obj+newmat9.obj+ >> link.lnk + echo test_exc.obj+newfft.obj, >> link.lnk + echo test_exc.exe; >> link.lnk + link @link.lnk + +newmatxx = include.h newmat.h boolean.h myexcept.h + +myexcept.obj: include.h boolean.h myexcept.h myexcept.cpp + +newmatex.obj: $(newmatxx) newmatex.cpp + +newmatnl.obj: $(newmatxx) newmatnl.h newmatap.h + +example.obj: $(newmatxx) newmatap.h example.cpp + +cholesky.obj: $(newmatxx) cholesky.cpp + +evalue.obj: $(newmatxx) newmatrm.h precisio.h evalue.cpp + +fft.obj: $(newmatxx) newmatap.h fft.cpp + +newfft.obj: $(newmatxx) newmatap.h newfft.cpp + +hholder.obj: $(newmatxx) newmatap.h hholder.cpp + +jacobi.obj: $(newmatxx) precisio.h newmatrm.h jacobi.cpp + +bandmat.obj: $(newmatxx) newmatrc.h controlw.h bandmat.cpp + +newmat1.obj: $(newmatxx) newmat1.cpp + +newmat2.obj: $(newmatxx) newmatrc.h controlw.h newmat2.cpp + +newmat3.obj: $(newmatxx) newmatrc.h controlw.h newmat3.cpp + +newmat4.obj: $(newmatxx) newmatrc.h controlw.h newmat4.cpp + +newmat5.obj: $(newmatxx) newmatrc.h controlw.h newmat5.cpp + +newmat6.obj: $(newmatxx) newmatrc.h controlw.h newmat6.cpp + +newmat7.obj: $(newmatxx) newmatrc.h controlw.h newmat7.cpp + +newmat8.obj: $(newmatxx) newmatap.h newmat8.cpp + +newmat9.obj: $(newmatxx) newmatrc.h controlw.h newmatio.h newmat9.cpp + +newmatrm.obj: $(newmatxx) newmatrm.h newmatrm.cpp + +sort.obj: $(newmatxx) newmatap.h sort.cpp + +submat.obj: $(newmatxx) newmatrc.h controlw.h submat.cpp + +svd.obj: $(newmatxx) newmatrm.h precisio.h svd.cpp + +tmt.obj: $(newmatxx) newmatap.h tmt.cpp + +tmt1.obj: $(newmatxx) newmatap.h tmt1.cpp + +tmt2.obj: $(newmatxx) newmatap.h tmt2.cpp + +tmt3.obj: $(newmatxx) newmatap.h tmt3.cpp + +tmt4.obj: $(newmatxx) newmatap.h tmt4.cpp + +tmt5.obj: $(newmatxx) newmatap.h tmt5.cpp + +tmt6.obj: $(newmatxx) newmatap.h tmt6.cpp + +tmt7.obj: $(newmatxx) newmatap.h tmt7.cpp + +tmt8.obj: $(newmatxx) newmatap.h tmt8.cpp + +tmt9.obj: $(newmatxx) newmatap.h tmt9.cpp + +tmta.obj: $(newmatxx) newmatap.h tmta.cpp + +tmtb.obj: $(newmatxx) newmatap.h tmtb.cpp + +tmtc.obj: $(newmatxx) newmatap.h tmtc.cpp + +tmtd.obj: $(newmatxx) newmatap.h tmtd.cpp + +tmte.obj: $(newmatxx) newmatap.h tmte.cpp + +tmtf.obj: $(newmatxx) newmatap.h tmtf.cpp + +tmtg.obj: $(newmatxx) newmatap.h tmtg.cpp + +tmth.obj: $(newmatxx) newmatap.h tmth.cpp + +tmti.obj: $(newmatxx) newmatap.h tmti.cpp + +tmtj.obj: $(newmatxx) newmatap.h tmtj.cpp + +tmtk.obj: $(newmatxx) newmatap.h tmtk.cpp + +tmtl.obj: $(newmatxx) newmatap.h tmtl.cpp + +nl_ex.obj: $(newmatxx) newmatap.h newmatnl.h nl_ex.cpp + +sl_ex.obj: include.h boolean.h myexcept.h sl_ex.cpp + +solution.obj: include.h boolean.h myexcept.h solution.cpp + +garch.obj: $(newmatxx) newmatap.h newmatnl.h garch.cpp + +test_exc.obj: $(newmatxx) test_exc.cpp diff --git a/Utilities/OSSIM/ossim_core/matrix/ms_nt.mak b/Utilities/OSSIM/ossim_core/matrix/ms_nt.mak new file mode 100644 index 0000000000..1976a761af --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/ms_nt.mak @@ -0,0 +1,151 @@ +!include <ntwin32.mak> + +.SUFFIXES: .cpp + + +everything: tmt.exe example.exe nl_ex.exe sl_ex.exe garch.exe test_exc.exe + +.cpp.obj: + cl -c -W3 -Ox $*.cpp + +OBJ_LIB = bandmat.obj cholesky.obj evalue.obj fft.obj hholder.obj \ + jacobi.obj myexcept.obj newmat1.obj newmat2.obj newmat3.obj \ + newmat4.obj newmat5.obj newmat6.obj newmat7.obj newmat8.obj \ + newmat9.obj newmatex.obj newmatnl.obj newmatrm.obj solution.obj \ + sort.obj submat.obj svd.obj newfft.obj + +OBJ_T = tmt.obj tmt1.obj tmt2.obj tmt3.obj tmt4.obj tmt5.obj tmt6.obj \ + tmt7.obj tmt8.obj tmt9.obj tmta.obj tmtb.obj tmtc.obj tmtd.obj tmte.obj \ + tmtf.obj tmtg.obj tmth.obj tmti.obj tmtj.obj tmtk.obj tmtl.obj + +tmt.exe: $(OBJ_T) $(OBJ_LIB) + link -OUT:tmt.exe $(conlflags) $(conlibs) $(OBJ_T) $(OBJ_LIB) + +OBJ_E = example.obj + +example.exe: $(OBJ_E) $(OBJ_LIB) + link -OUT:example.exe $(conlflags) $(conlibs) $(OBJ_E) $(OBJ_LIB) + +OBJ_N = nl_ex.obj + +nl_ex.exe: $(OBJ_N) $(OBJ_LIB) + link -OUT:nl_ex.exe $(conlflags) $(conlibs) $(OBJ_N) $(OBJ_LIB) + +OBJ_S = sl_ex.obj + +sl_ex.exe: $(OBJ_S) $(OBJ_LIB) + link -OUT:sl_ex.exe $(conlflags) $(conlibs) $(OBJ_S) $(OBJ_LIB) + +OBJ_G = garch.obj + +garch.exe: $(OBJ_G) $(OBJ_LIB) + link -OUT:garch.exe $(conlflags) $(conlibs) $(OBJ_G) $(OBJ_LIB) + +OBJ_X = test_exc.obj + +test_exc.exe: $(OBJ_X) $(OBJ_LIB) + link -OUT:test_exc.exe $(conlflags) $(conlibs) $(OBJ_X) $(OBJ_LIB) + +newmatxx = include.h newmat.h boolean.h myexcept.h + +myexcept.obj: include.h boolean.h myexcept.h myexcept.cpp + +newmatex.obj: $(newmatxx) newmatex.cpp + +newmatnl.obj: $(newmatxx) newmatnl.h newmatap.h + +example.obj: $(newmatxx) newmatap.h example.cpp + +cholesky.obj: $(newmatxx) cholesky.cpp + +evalue.obj: $(newmatxx) newmatrm.h precisio.h evalue.cpp + +fft.obj: $(newmatxx) newmatap.h fft.cpp + +newfft.obj: $(newmatxx) newmatap.h newfft.cpp + +hholder.obj: $(newmatxx) newmatap.h hholder.cpp + +jacobi.obj: $(newmatxx) precisio.h newmatrm.h jacobi.cpp + +bandmat.obj: $(newmatxx) newmatrc.h controlw.h bandmat.cpp + +newmat1.obj: $(newmatxx) newmat1.cpp + +newmat2.obj: $(newmatxx) newmatrc.h controlw.h newmat2.cpp + +newmat3.obj: $(newmatxx) newmatrc.h controlw.h newmat3.cpp + +newmat4.obj: $(newmatxx) newmatrc.h controlw.h newmat4.cpp + +newmat5.obj: $(newmatxx) newmatrc.h controlw.h newmat5.cpp + +newmat6.obj: $(newmatxx) newmatrc.h controlw.h newmat6.cpp + +newmat7.obj: $(newmatxx) newmatrc.h controlw.h newmat7.cpp + +newmat8.obj: $(newmatxx) newmatap.h newmat8.cpp + +newmat9.obj: $(newmatxx) newmatrc.h controlw.h newmatio.h newmat9.cpp + +newmatrm.obj: $(newmatxx) newmatrm.h newmatrm.cpp + +sort.obj: $(newmatxx) newmatap.h sort.cpp + +submat.obj: $(newmatxx) newmatrc.h controlw.h submat.cpp + +svd.obj: $(newmatxx) newmatrm.h precisio.h svd.cpp + +tmt.obj: $(newmatxx) newmatap.h tmt.cpp + +tmt1.obj: $(newmatxx) newmatap.h tmt1.cpp + +tmt2.obj: $(newmatxx) newmatap.h tmt2.cpp + +tmt3.obj: $(newmatxx) newmatap.h tmt3.cpp + +tmt4.obj: $(newmatxx) newmatap.h tmt4.cpp + +tmt5.obj: $(newmatxx) newmatap.h tmt5.cpp + +tmt6.obj: $(newmatxx) newmatap.h tmt6.cpp + +tmt7.obj: $(newmatxx) newmatap.h tmt7.cpp + +tmt8.obj: $(newmatxx) newmatap.h tmt8.cpp + +tmt9.obj: $(newmatxx) newmatap.h tmt9.cpp + +tmta.obj: $(newmatxx) newmatap.h tmta.cpp + +tmtb.obj: $(newmatxx) newmatap.h tmtb.cpp + +tmtc.obj: $(newmatxx) newmatap.h tmtc.cpp + +tmtd.obj: $(newmatxx) newmatap.h tmtd.cpp + +tmte.obj: $(newmatxx) newmatap.h tmte.cpp + +tmtf.obj: $(newmatxx) newmatap.h tmtf.cpp + +tmtg.obj: $(newmatxx) newmatap.h tmtg.cpp + +tmth.obj: $(newmatxx) newmatap.h tmth.cpp + +tmti.obj: $(newmatxx) newmatap.h tmti.cpp + +tmtj.obj: $(newmatxx) newmatap.h tmtj.cpp + +tmtk.obj: $(newmatxx) newmatap.h tmtk.cpp + +tmtl.obj: $(newmatxx) newmatap.h tmtl.cpp + +nl_ex.obj: $(newmatxx) newmatap.h newmatnl.h nl_ex.cpp + +sl_ex.obj: include.h boolean.h myexcept.h sl_ex.cpp + +solution.obj: include.h boolean.h myexcept.h solution.cpp + +garch.obj: $(newmatxx) newmatap.h newmatnl.h garch.cpp + +test_exc.obj: $(newmatxx) test_exc.cpp diff --git a/Utilities/OSSIM/ossim_core/matrix/myexcept.cpp b/Utilities/OSSIM/ossim_core/matrix/myexcept.cpp new file mode 100644 index 0000000000..8af60a6712 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/myexcept.cpp @@ -0,0 +1,485 @@ +//$$myexcept.cpp Exception handler + +// Copyright (C) 1993,4,6: R B Davies + + +#define WANT_STREAM // include.h will get stream fns +#define WANT_STRING + +#include "include.h" // include standard files + +using namespace std; + +#include "myexcept.h" // for exception handling + +#ifdef use_namespace +namespace RBD_COMMON { +#endif + + +//#define REG_DEREG // for print out uses of new/delete +//#define CLEAN_LIST // to print entries being added to + // or deleted from cleanup list + +#ifdef SimulateExceptions + +void Throw() +{ + for (Janitor* jan = JumpBase::jl->janitor; jan; jan = jan->NextJanitor) + jan->CleanUp(); + JumpItem* jx = JumpBase::jl->ji; // previous jumpbase; + if ( !jx ) { Terminate(); } // jl was initial JumpItem + JumpBase::jl = jx; // drop down a level; cannot be in front + // of previous line + Tracer::last = JumpBase::jl->trace; + longjmp(JumpBase::jl->env, 1); +} + +#endif // end of simulate exceptions + + +unsigned long BaseException::Select; +char* BaseException::what_error; +int BaseException::SoFar; +int BaseException::LastOne; + +BaseException::BaseException(const char* a_what) +{ + Select++; SoFar = 0; + if (!what_error) // make space for exception message + { + LastOne = 511; + what_error = new char[512]; + if (!what_error) // fail to make space + { + LastOne = 0; + what_error = (char *)"No heap space for exception message\n"; + } + } + AddMessage("\n\nAn exception has been thrown\n"); + AddMessage(a_what); + if (a_what) Tracer::AddTrace(); +} + +void BaseException::AddMessage(const char* a_what) +{ + if (a_what) + { + int l = strlen(a_what); int r = LastOne - SoFar; + if (l < r) { strcpy(what_error+SoFar, a_what); SoFar += l; } + else if (r > 0) + { + strncpy(what_error+SoFar, a_what, r); + what_error[LastOne] = 0; + SoFar = LastOne; + } + } +} + +void BaseException::AddInt(int value) +{ + bool negative; + if (value == 0) { AddMessage("0"); return; } + else if (value < 0) { value = -value; negative = true; } + else negative = false; + int n = 0; int v = value; // how many digits will we need? + while (v > 0) { v /= 10; n++; } + if (negative) n++; + if (LastOne-SoFar < n) { AddMessage("***"); return; } + + SoFar += n; n = SoFar; what_error[n] = 0; + while (value > 0) + { + int nv = value / 10; int rm = value - nv * 10; value = nv; + what_error[--n] = (char)(rm + '0'); + } + if (negative) what_error[--n] = '-'; + return; +} + +void Tracer::PrintTrace() +{ + cout << "\n"; + for (Tracer* et = last; et; et=et->previous) + cout << " * " << et->entry << "\n"; +} + +void Tracer::AddTrace() +{ + if (last) + { + BaseException::AddMessage("Trace: "); + BaseException::AddMessage(last->entry); + for (Tracer* et = last->previous; et; et=et->previous) + { + BaseException::AddMessage("; "); + BaseException::AddMessage(et->entry); + } + BaseException::AddMessage(".\n"); + } +} + +#ifdef SimulateExceptions + + +Janitor::Janitor() +{ + if (do_not_link) + { + do_not_link = false; NextJanitor = 0; OnStack = false; +#ifdef CLEAN_LIST + cout << "Not added to clean-list " << (unsigned long)this << "\n"; +#endif + } + else + { + OnStack = true; +#ifdef CLEAN_LIST + cout << "Add to clean-list " << (unsigned long)this << "\n"; +#endif + NextJanitor = JumpBase::jl->janitor; JumpBase::jl->janitor=this; + } +} + +Janitor::~Janitor() +{ + // expect the item to be deleted to be first on list + // but must be prepared to search list + if (OnStack) + { +#ifdef CLEAN_LIST + cout << "Delete from clean-list " << (unsigned long)this << "\n"; +#endif + Janitor* lastjan = JumpBase::jl->janitor; + if (this == lastjan) JumpBase::jl->janitor = NextJanitor; + else + { + for (Janitor* jan = lastjan->NextJanitor; jan; + jan = lastjan->NextJanitor) + { + if (jan==this) + { lastjan->NextJanitor = jan->NextJanitor; return; } + lastjan=jan; + } + + Throw(BaseException( +"Cannot resolve memory linked list\nSee notes in myexcept.cpp for details\n" + )); + + +// This message occurs when a call to ~Janitor() occurs, apparently +// without a corresponding call to Janitor(). This could happen if my +// way of deciding whether a constructor is being called by new +// fails. + +// It may happen if you are using my simulated exceptions and also have +// your compiler s exceptions turned on. + +// It can also happen if you have a class derived from Janitor +// which does not include a copy constructor [ eg X(const &X) ]. +// Possibly also if delete is applied an object on the stack (ie not +// called by new). Otherwise, it is a bug in myexcept or your compiler. +// If you do not #define TEMPS_DESTROYED_QUICKLY you will get this +// error with Microsoft C 7.0. There are probably situations where +// you will get this when you do define TEMPS_DESTROYED_QUICKLY. This +// is a bug in MSC. Beware of "operator" statements for defining +// conversions; particularly for converting from a Base class to a +// Derived class. + +// You may get away with simply deleting this error message and Throw +// statement if you can not find a better way of overcoming the +// problem. In any case please tell me if you get this error message, +// particularly for compilers apart from Microsoft C 7.0. + + + } + } +} + +JumpItem* JumpBase::jl; // will be set to zero +jmp_buf JumpBase::env; +bool Janitor::do_not_link; // will be set to false + + +int JanitorInitializer::ref_count; + +JanitorInitializer::JanitorInitializer() +{ + if (ref_count++ == 0) new JumpItem; + // need JumpItem at head of list +} + +#endif // end of SimulateExceptions + +Tracer* Tracer::last; // will be set to zero + + +void Terminate() +{ + cout << "\n\nThere has been an exception with no handler - exiting"; + const char* what = BaseException::what(); + if (what) cout << what << "\n"; + exit(1); +} + + + +#ifdef DO_FREE_CHECK +// Routines for tracing whether new and delete calls are balanced + +FreeCheckLink::FreeCheckLink() : next(FreeCheck::next) + { FreeCheck::next = this; } + +FCLClass::FCLClass(void* t, char* name) : ClassName(name) { ClassStore=t; } + +FCLRealArray::FCLRealArray(void* t, char* o, int s) + : Operation(o), size(s) { ClassStore=t; } + +FCLIntArray::FCLIntArray(void* t, char* o, int s) + : Operation(o), size(s) { ClassStore=t; } + +FreeCheckLink* FreeCheck::next; +int FreeCheck::BadDelete; + +void FCLClass::Report() +{ cout << " " << ClassName << " " << (unsigned long)ClassStore << "\n"; } + +void FCLRealArray::Report() +{ + cout << " " << Operation << " " << (unsigned long)ClassStore << + " " << size << "\n"; +} + +void FCLIntArray::Report() +{ + cout << " " << Operation << " " << (unsigned long)ClassStore << + " " << size << "\n"; +} + +void FreeCheck::Register(void* t, char* name) +{ + FCLClass* f = new FCLClass(t,name); + if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); } +#ifdef REG_DEREG + cout << "Registering " << name << " " << (unsigned long)t << "\n"; +#endif +} + +void FreeCheck::RegisterR(void* t, char* o, int s) +{ + FCLRealArray* f = new FCLRealArray(t,o,s); + if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); } +#ifdef REG_DEREG + cout << o << " " << s << " " << (unsigned long)t << "\n"; +#endif +} + +void FreeCheck::RegisterI(void* t, char* o, int s) +{ + FCLIntArray* f = new FCLIntArray(t,o,s); + if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); } +#ifdef REG_DEREG + cout << o << " " << s << " " << (unsigned long)t << "\n"; +#endif +} + +void FreeCheck::DeRegister(void* t, char* name) +{ + FreeCheckLink* last = 0; +#ifdef REG_DEREG + cout << "Deregistering " << name << " " << (unsigned long)t << "\n"; +#endif + for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next) + { + if (fcl->ClassStore==t) + { + if (last) last->next = fcl->next; else next = fcl->next; + delete fcl; return; + } + last = fcl; + } + cout << "\nRequest to delete non-existent object of class and location:\n"; + cout << " " << name << " " << (unsigned long)t << "\n"; + BadDelete++; + Tracer::PrintTrace(); + cout << "\n"; +} + +void FreeCheck::DeRegisterR(void* t, char* o, int s) +{ + FreeCheckLink* last = 0; +#ifdef REG_DEREG + cout << o << " " << s << " " << (unsigned long)t << "\n"; +#endif + for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next) + { + if (fcl->ClassStore==t) + { + if (last) last->next = fcl->next; else next = fcl->next; + if (s >= 0 && ((FCLRealArray*)fcl)->size != s) + { + cout << "\nArray sizes do not agree:\n"; + cout << " " << o << " " << (unsigned long)t + << " " << ((FCLRealArray*)fcl)->size << " " << s << "\n"; + Tracer::PrintTrace(); + cout << "\n"; + } + delete fcl; return; + } + last = fcl; + } + cout << "\nRequest to delete non-existent real array:\n"; + cout << " " << o << " " << (unsigned long)t << " " << s << "\n"; + BadDelete++; + Tracer::PrintTrace(); + cout << "\n"; +} + +void FreeCheck::DeRegisterI(void* t, char* o, int s) +{ + FreeCheckLink* last = 0; +#ifdef REG_DEREG + cout << o << " " << s << " " << (unsigned long)t << "\n"; +#endif + for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next) + { + if (fcl->ClassStore==t) + { + if (last) last->next = fcl->next; else next = fcl->next; + if (s >= 0 && ((FCLIntArray*)fcl)->size != s) + { + cout << "\nArray sizes do not agree:\n"; + cout << " " << o << " " << (unsigned long)t + << " " << ((FCLIntArray*)fcl)->size << " " << s << "\n"; + Tracer::PrintTrace(); + cout << "\n"; + } + delete fcl; return; + } + last = fcl; + } + cout << "\nRequest to delete non-existent int array:\n"; + cout << " " << o << " " << (unsigned long)t << " " << s << "\n"; + BadDelete++; + Tracer::PrintTrace(); + cout << "\n"; +} + +void FreeCheck::Status() +{ + if (next) + { + cout << "\nObjects of the following classes remain undeleted:\n"; + for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next) fcl->Report(); + cout << "\n"; + } + else cout << "\nNo objects remain undeleted\n\n"; + if (BadDelete) + { + cout << "\nThere were " << BadDelete << + " requests to delete non-existent items\n\n"; + } +} + +#endif // end of DO_FREE_CHECK + +// derived exception bodies + +Logic_error::Logic_error(const char* a_what) : BaseException() +{ + Select = BaseException::Select; + AddMessage("Logic error:- "); AddMessage(a_what); + if (a_what) Tracer::AddTrace(); +} + +Runtime_error::Runtime_error(const char* a_what) + : BaseException() +{ + Select = BaseException::Select; + AddMessage("Runtime error:- "); AddMessage(a_what); + if (a_what) Tracer::AddTrace(); +} + +Domain_error::Domain_error(const char* a_what) : Logic_error() +{ + Select = BaseException::Select; + AddMessage("domain error\n"); AddMessage(a_what); + if (a_what) Tracer::AddTrace(); +} + +Invalid_argument::Invalid_argument(const char* a_what) : Logic_error() +{ + Select = BaseException::Select; + AddMessage("invalid argument\n"); AddMessage(a_what); + if (a_what) Tracer::AddTrace(); +} + +Length_error::Length_error(const char* a_what) : Logic_error() +{ + Select = BaseException::Select; + AddMessage("length error\n"); AddMessage(a_what); + if (a_what) Tracer::AddTrace(); +} + +Out_of_range::Out_of_range(const char* a_what) : Logic_error() +{ + Select = BaseException::Select; + AddMessage("out of range\n"); AddMessage(a_what); + if (a_what) Tracer::AddTrace(); +} + +//Bad_cast::Bad_cast(const char* a_what) : Logic_error() +//{ +// Select = BaseException::Select; +// AddMessage("bad cast\n"); AddMessage(a_what); +// if (a_what) Tracer::AddTrace(); +//} + +//Bad_typeid::Bad_typeid(const char* a_what) : Logic_error() +//{ +// Select = BaseException::Select; +// AddMessage("bad type id.\n"); AddMessage(a_what); +// if (a_what) Tracer::AddTrace(); +//} + +Range_error::Range_error(const char* a_what) : Runtime_error() +{ + Select = BaseException::Select; + AddMessage("range error\n"); AddMessage(a_what); + if (a_what) Tracer::AddTrace(); +} + +Overflow_error::Overflow_error(const char* a_what) : Runtime_error() +{ + Select = BaseException::Select; + AddMessage("overflow error\n"); AddMessage(a_what); + if (a_what) Tracer::AddTrace(); +} + +Bad_alloc::Bad_alloc(const char* a_what) : BaseException() +{ + Select = BaseException::Select; + AddMessage("bad allocation\n"); AddMessage(a_what); + if (a_what) Tracer::AddTrace(); +} + + + + +unsigned long Logic_error::Select; +unsigned long Runtime_error::Select; +unsigned long Domain_error::Select; +unsigned long Invalid_argument::Select; +unsigned long Length_error::Select; +unsigned long Out_of_range::Select; +//unsigned long Bad_cast::Select; +//unsigned long Bad_typeid::Select; +unsigned long Range_error::Select; +unsigned long Overflow_error::Select; +unsigned long Bad_alloc::Select; + +#ifdef use_namespace +} +#endif + + diff --git a/Utilities/OSSIM/ossim_core/matrix/myexcept.h b/Utilities/OSSIM/ossim_core/matrix/myexcept.h new file mode 100644 index 0000000000..1351ccbfb4 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/myexcept.h @@ -0,0 +1,433 @@ +//$$ myexcept.h Exception handling classes + + +// A set of classes to simulate exceptions in C++ +// +// Partially copied from Carlos Vidal s article in the C users journal +// September 1992, pp 19-28 +// +// Operations defined +// Try { } +// Throw ( exception object ) +// ReThrow +// Catch ( exception class ) { } +// CatchAll { } +// CatchAndThrow +// +// All catch lists must end with a CatchAll or CatchAndThrow statement +// but not both. +// +// When exceptions are finally implemented replace Try, Throw(E), Rethrow, +// Catch, CatchAll, CatchAndThrow by try, throw E, throw, catch, +// catch(...), and {}. +// +// All exception classes must be derived from BaseException, have no +// non-static variables and must include the statement +// +// static unsigned long Select; +// +// Any constructor in one of these exception classes must include +// +// Select = BaseException::Select; +// +// For each exceptions class, EX_1, some .cpp file must include +// +// unsigned long EX_1::Select; +// + + +#ifndef EXCEPTION_LIB +#define EXCEPTION_LIB + +#ifdef use_namespace +namespace RBD_COMMON { +#endif + + +void Terminate(); + + +//********** classes for setting up exceptions and reporting ************// + +class BaseException; + +class Tracer // linked list showing how +{ // we got here + const char* entry; + Tracer* previous; +public: + Tracer(const char*); + ~Tracer(); + void ReName(const char*); + static void PrintTrace(); // for printing trace + static void AddTrace(); // insert trace in exception record + static Tracer* last; // points to Tracer list + friend class BaseException; +}; + + +class BaseException // The base exception class +{ +protected: + static char* what_error; // error message + static int SoFar; // no. characters already entered + static int LastOne; // last location in error buffer +public: + static void AddMessage(const char* a_what); + // messages about exception + static void AddInt(int value); // integer to error message + static unsigned long Select; // for identifying exception + BaseException(const char* a_what = 0); + static const char* what() { return what_error; } + // for getting error message +}; + +#ifdef TypeDefException +typedef BaseException Exception; // for compatibility with my older libraries +#endif + +inline Tracer::Tracer(const char* e) + : entry(e), previous(last) { last = this; } + +inline Tracer::~Tracer() { last = previous; } + +inline void Tracer::ReName(const char* e) { entry=e; } + +#ifdef SimulateExceptions // SimulateExceptions + +#include <setjmp.h> + + +//************* the definitions of Try, Throw and Catch *****************// + + +class JumpItem; +class Janitor; + +class JumpBase // pointer to a linked list of jmp_buf s +{ +public: + static JumpItem *jl; + static jmp_buf env; +}; + +class JumpItem // an item in a linked list of jmp_buf s +{ +public: + JumpItem *ji; + jmp_buf env; + Tracer* trace; // to keep check on Tracer items + Janitor* janitor; // list of items for cleanup + JumpItem() : ji(JumpBase::jl), trace(0), janitor(0) + { JumpBase::jl = this; } + ~JumpItem() { JumpBase::jl = ji; } +}; + +void Throw(); + +inline void Throw(const BaseException&) { Throw(); } + +#define Try \ + if (!setjmp( JumpBase::jl->env )) { \ + JumpBase::jl->trace = Tracer::last; \ + JumpItem JI387256156; + +#define ReThrow Throw() + +#define Catch(EXCEPTION) \ + } else if (BaseException::Select == EXCEPTION::Select) { + +#define CatchAll } else + +#define CatchAndThrow } else Throw(); + + +//****************** cleanup heap following Throw ***********************// + +class Janitor +{ +protected: + static bool do_not_link; // set when new is called + bool OnStack; // false if created by new +public: + Janitor* NextJanitor; + virtual void CleanUp() {} + Janitor(); + virtual ~Janitor(); +}; + + +// The tiresome old trick for initializing the Janitor class +// this is needed for classes derived from Janitor which have objects +// declared globally + +class JanitorInitializer +{ +public: + JanitorInitializer(); +private: + static int ref_count; +}; + +static JanitorInitializer JanInit; + +#endif // end of SimulateExceptions + +#ifdef UseExceptions + +#define Try try +#define Throw(E) throw E +#define ReThrow throw +#define Catch catch +#define CatchAll catch(...) +#define CatchAndThrow {} + +#endif // end of UseExceptions + + +#ifdef DisableExceptions // Disable exceptions + +#define Try { +#define ReThrow Throw() +#define Catch(EXCEPTION) } if (false) { +#define CatchAll } if (false) +#define CatchAndThrow } + +inline void Throw() { Terminate(); } +inline void Throw(const BaseException&) { Terminate(); } + + +#endif // end of DisableExceptions + +#ifndef SimulateExceptions // ! SimulateExceptions + +class Janitor // a dummy version +{ +public: + virtual void CleanUp() {} + Janitor() {} + virtual ~Janitor() {} +}; + +#endif // end of ! SimulateExceptions + + +//******************** FREE_CHECK and NEW_DELETE ***********************// + +#ifdef DO_FREE_CHECK // DO_FREE_CHECK +// Routines for tracing whether new and delete calls are balanced + +class FreeCheck; + +class FreeCheckLink +{ +protected: + FreeCheckLink* next; + void* ClassStore; + FreeCheckLink(); + virtual void Report()=0; // print details of link + friend class FreeCheck; +}; + +class FCLClass : public FreeCheckLink // for registering objects +{ + char* ClassName; + FCLClass(void* t, char* name); + void Report(); + friend class FreeCheck; +}; + +class FCLRealArray : public FreeCheckLink // for registering real arrays +{ + char* Operation; + int size; + FCLRealArray(void* t, char* o, int s); + void Report(); + friend class FreeCheck; +}; + +class FCLIntArray : public FreeCheckLink // for registering int arrays +{ + char* Operation; + int size; + FCLIntArray(void* t, char* o, int s); + void Report(); + friend class FreeCheck; +}; + + +class FreeCheck +{ + static FreeCheckLink* next; + static int BadDelete; +public: + static void Register(void*, char*); + static void DeRegister(void*, char*); + static void RegisterR(void*, char*, int); + static void DeRegisterR(void*, char*, int); + static void RegisterI(void*, char*, int); + static void DeRegisterI(void*, char*, int); + static void Status(); + friend class FreeCheckLink; + friend class FCLClass; + friend class FCLRealArray; + friend class FCLIntArray; +}; + +#define FREE_CHECK(Class) \ +public: \ + void* operator new(size_t size) \ + { \ + void* t = ::operator new(size); FreeCheck::Register(t,#Class); \ + return t; \ + } \ + void operator delete(void* t) \ + { FreeCheck::DeRegister(t,#Class); ::operator delete(t); } + + +#ifdef SimulateExceptions // SimulateExceptions + +#define NEW_DELETE(Class) \ +public: \ + void* operator new(size_t size) \ + { \ + do_not_link=true; \ + void* t = ::operator new(size); FreeCheck::Register(t,#Class); \ + return t; \ + } \ + void operator delete(void* t) \ + { FreeCheck::DeRegister(t,#Class); ::operator delete(t); } + + +#endif // end of SimulateExceptions + + +#define MONITOR_REAL_NEW(Operation, Size, Pointer) \ + FreeCheck::RegisterR(Pointer, Operation, Size); +#define MONITOR_INT_NEW(Operation, Size, Pointer) \ + FreeCheck::RegisterI(Pointer, Operation, Size); +#define MONITOR_REAL_DELETE(Operation, Size, Pointer) \ + FreeCheck::DeRegisterR(Pointer, Operation, Size); +#define MONITOR_INT_DELETE(Operation, Size, Pointer) \ + FreeCheck::DeRegisterI(Pointer, Operation, Size); + +#else // DO_FREE_CHECK not defined + +#define FREE_CHECK(Class) public: +#define MONITOR_REAL_NEW(Operation, Size, Pointer) {} +#define MONITOR_INT_NEW(Operation, Size, Pointer) {} +#define MONITOR_REAL_DELETE(Operation, Size, Pointer) {} +#define MONITOR_INT_DELETE(Operation, Size, Pointer) {} + + +#ifdef SimulateExceptions // SimulateExceptions + + +#define NEW_DELETE(Class) \ +public: \ + void* operator new(size_t size) \ + { do_not_link=true; void* t = ::operator new(size); return t; } \ + void operator delete(void* t) { ::operator delete(t); } + +#endif // end of SimulateExceptions + +#endif // end of ! DO_FREE_CHECK + +#ifndef SimulateExceptions // ! SimulateExceptions + +#define NEW_DELETE(Class) FREE_CHECK(Class) + +#endif // end of ! SimulateExceptions + + +//********************* derived exceptions ******************************// + +class Logic_error : public BaseException +{ +public: + static unsigned long Select; + Logic_error(const char* a_what = 0); +}; + +class Runtime_error : public BaseException +{ +public: + static unsigned long Select; + Runtime_error(const char* a_what = 0); +}; + +class Domain_error : public Logic_error +{ +public: + static unsigned long Select; + Domain_error(const char* a_what = 0); +}; + +class Invalid_argument : public Logic_error +{ +public: + static unsigned long Select; + Invalid_argument(const char* a_what = 0); +}; + +class Length_error : public Logic_error +{ +public: + static unsigned long Select; + Length_error(const char* a_what = 0); +}; + +class Out_of_range : public Logic_error +{ +public: + static unsigned long Select; + Out_of_range(const char* a_what = 0); +}; + +//class Bad_cast : public Logic_error +//{ +//public: +// static unsigned long Select; +// Bad_cast(const char* a_what = 0); +//}; + +//class Bad_typeid : public Logic_error +//{ +//public: +// static unsigned long Select; +// Bad_typeid(const char* a_what = 0); +//}; + +class Range_error : public Runtime_error +{ +public: + static unsigned long Select; + Range_error(const char* a_what = 0); +}; + +class Overflow_error : public Runtime_error +{ +public: + static unsigned long Select; + Overflow_error(const char* a_what = 0); +}; + +class Bad_alloc : public BaseException +{ +public: + static unsigned long Select; + Bad_alloc(const char* a_what = 0); +}; + +#ifdef use_namespace +} +#endif + + +#endif // end of EXCEPTION_LIB + + +// body file: myexcept.cpp + + + diff --git a/Utilities/OSSIM/ossim_core/matrix/newfft.cpp b/Utilities/OSSIM/ossim_core/matrix/newfft.cpp new file mode 100644 index 0000000000..5d0136fa63 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/newfft.cpp @@ -0,0 +1,1059 @@ +//$ newfft.cpp + +// This is originally by Sande and Gentleman in 1967! I have translated from +// Fortran into C and a little bit of C++. + +// It takes about twice as long as fftw +// (http://theory.lcs.mit.edu/~fftw/homepage.html) +// but is much shorter than fftw and so despite its age +// might represent a reasonable +// compromise between speed and complexity. +// If you really need the speed get fftw. + + +// THIS SUBROUTINE WAS WRITTEN BY G.SANDE OF PRINCETON UNIVERSITY AND +// W.M.GENTLMAN OF THE BELL TELEPHONE LAB. IT WAS BROUGHT TO LONDON +// BY DR. M.D. GODFREY AT THE IMPERIAL COLLEGE AND WAS ADAPTED FOR +// BURROUGHS 6700 BY D. R. BRILLINGER AND J. PEMBERTON +// IT REPRESENTS THE STATE OF THE ART OF COMPUTING COMPLETE FINITE +// DISCRETE FOURIER TRANSFORMS AS OF NOV.1967. +// OTHER PROGRAMS REQUIRED. +// ONLY THOSE SUBROUTINES INCLUDED HERE. +// USAGE. +// CALL AR1DFT(N,X,Y) +// WHERE N IS THE NUMBER OF POINTS IN THE SEQUENCE . +// X - IS A ONE-DIMENSIONAL ARRAY CONTAINING THE REAL +// PART OF THE SEQUENCE. +// Y - IS A ONE-DIMENSIONAL ARRAY CONTAINING THE +// IMAGINARY PART OF THE SEQUENCE. +// THE TRANSFORM IS RETURNED IN X AND Y. +// METHOD +// FOR A GENERAL DISCUSSION OF THESE TRANSFORMS AND OF +// THE FAST METHOD FOR COMPUTING THEM, SEE GENTLEMAN AND SANDE, +// @FAST FOURIER TRANSFORMS - FOR FUN AND PROFIT,@ 1966 FALL JOINT +// COMPUTER CONFERENCE. +// THIS PROGRAM COMPUTES THIS FOR A COMPLEX SEQUENCE Z(T) OF LENGTH +// N WHOSE ELEMENTS ARE STORED AT(X(I) , Y(I)) AND RETURNS THE +// TRANSFORM COEFFICIENTS AT (X(I), Y(I)). +// DESCRIPTION +// AR1DFT IS A HIGHLY MODULAR ROUTINE CAPABLE OF COMPUTING IN PLACE +// THE COMPLETE FINITE DISCRETE FOURIER TRANSFORM OF A ONE- +// DIMENSIONAL SEQUENCE OF RATHER GENERAL LENGTH N. +// THE MAIN ROUTINE , AR1DFT ITSELF, FACTORS N. IT THEN CALLS ON +// ON GR 1D FT TO COMPUTE THE ACTUAL TRANSFORMS, USING THESE FACTORS. +// THIS GR 1D FT DOES, CALLING AT EACH STAGE ON THE APPROPRIATE KERN +// EL R2FTK, R4FTK, R8FTK, R16FTK, R3FTK, R5FTK, OR RPFTK TO PERFORM +// THE COMPUTATIONS FOR THIS PASS OVER THE SEQUENCE, DEPENDING ON +// WHETHER THE CORRESPONDING FACTOR IS 2, 4, 8, 16, 3, 5, OR SOME +// MORE GENERAL PRIME P. WHEN GR1DFT IS FINISHED THE TRANSFORM IS +// COMPUTED, HOWEVER, THE RESULTS ARE STORED IN "DIGITS REVERSED" +// ORDER. AR1DFT THEREFORE, CALLS UPON GR 1S FS TO SORT THEM OUT. +// TO RETURN TO THE FACTORIZATION, SINGLETON HAS POINTED OUT THAT +// THE TRANSFORMS ARE MORE EFFICIENT IF THE SAMPLE SIZE N, IS OF THE +// FORM B*A**2 AND B CONSISTS OF A SINGLE FACTOR. IN SUCH A CASE +// IF WE PROCESS THE FACTORS IN THE ORDER ABA THEN +// THE REORDERING CAN BE DONE AS FAST IN PLACE, AS WITH SCRATCH +// STORAGE. BUT AS B BECOMES MORE COMPLICATED, THE COST OF THE DIGIT +// REVERSING DUE TO B PART BECOMES VERY EXPENSIVE IF WE TRY TO DO IT +// IN PLACE. IN SUCH A CASE IT MIGHT BE BETTER TO USE EXTRA STORAGE +// A ROUTINE TO DO THIS IS, HOWEVER, NOT INCLUDED HERE. +// ANOTHER FEATURE INFLUENCING THE FACTORIZATION IS THAT FOR ANY FIXED +// FACTOR N WE CAN PREPARE A SPECIAL KERNEL WHICH WILL COMPUTE +// THAT STAGE OF THE TRANSFORM MORE EFFICIENTLY THAN WOULD A KERNEL +// FOR GENERAL FACTORS, ESPECIALLY IF THE GENERAL KERNEL HAD TO BE +// APPLIED SEVERAL TIMES. FOR EXAMPLE, FACTORS OF 4 ARE MORE +// EFFICIENT THAN FACTORS OF 2, FACTORS OF 8 MORE EFFICIENT THAN 4,ETC +// ON THE OTHER HAND DIMINISHING RETURNS RAPIDLY SET IN, ESPECIALLY +// SINCE THE LENGTH OF THE KERNEL FOR A SPECIAL CASE IS ROUGHLY +// PROPORTIONAL TO THE FACTOR IT DEALS WITH. HENCE THESE PROBABLY ARE +// ALL THE KERNELS WE WISH TO HAVE. +// RESTRICTIONS. +// AN UNFORTUNATE FEATURE OF THE SORTING PROBLEM IS THAT THE MOST +// EFFICIENT WAY TO DO IT IS WITH NESTED DO LOOPS, ONE FOR EACH +// FACTOR. THIS PUTS A RESTRICTION ON N AS TO HOW MANY FACTORS IT +// CAN HAVE. CURRENTLY THE LIMIT IS 16, BUT THE LIMIT CAN BE READILY +// RAISED IF NECESSARY. +// A SECOND RESTRICTION OF THE PROGRAM IS THAT LOCAL STORAGE OF THE +// THE ORDER P**2 IS REQUIRED BY THE GENERAL KERNEL RPFTK, SO SOME +// LIMIT MUST BE SET ON P. CURRENTLY THIS IS 19, BUT IT CAN BE INCRE +// INCREASED BY TRIVIAL CHANGES. +// OTHER COMMENTS. +//(1) THE ROUTINE IS ADAPTED TO CHECK WHETHER A GIVEN N WILL MEET THE +// ABOVE FACTORING REQUIREMENTS AN, IF NOT, TO RETURN THE NEXT HIGHER +// NUMBER, NX, SAY, WHICH WILL MEET THESE REQUIREMENTS. +// THIS CAN BE ACCHIEVED BY A STATEMENT OF THE FORM +// CALL FACTR(N,X,Y). +// IF A DIFFERENT N, SAY NX, IS RETURNED THEN THE TRANSFORMS COULD BE +// OBTAINED BY EXTENDING THE SIZE OF THE X-ARRAY AND Y-ARRAY TO NX, +// AND SETTING X(I) = Y(I) = 0., FOR I = N+1, NX. +//(2) IF THE SEQUENCE Z IS ONLY A REAL SEQUENCE, THEN THE IMAGINARY PART +// Y(I)=0., THIS WILL RETURN THE COSINE TRANSFORM OF THE REAL SEQUENCE +// IN X, AND THE SINE TRANSFORM IN Y. + + +#define WANT_STREAM + +#define WANT_MATH + +#include "newmatap.h" + +#ifdef use_namespace +namespace NEWMAT { +#endif + +#ifdef DO_REPORT +#define REPORT { static ExeCounter ExeCount(__LINE__,20); ++ExeCount; } +#else +#define REPORT {} +#endif + +inline Real square(Real x) { return x*x; } +inline int square(int x) { return x*x; } + +static void GR_1D_FS (int PTS, int N_SYM, int N_UN_SYM, + const SimpleIntArray& SYM, int P_SYM, const SimpleIntArray& UN_SYM, + Real* X, Real* Y); +static void GR_1D_FT (int N, int N_FACTOR, const SimpleIntArray& FACTOR, + Real* X, Real* Y); +static void R_P_FTK (int N, int M, int P, Real* X, Real* Y); +static void R_2_FTK (int N, int M, Real* X0, Real* Y0, Real* X1, Real* Y1); +static void R_3_FTK (int N, int M, Real* X0, Real* Y0, Real* X1, Real* Y1, + Real* X2, Real* Y2); +static void R_4_FTK (int N, int M, + Real* X0, Real* Y0, Real* X1, Real* Y1, + Real* X2, Real* Y2, Real* X3, Real* Y3); +static void R_5_FTK (int N, int M, + Real* X0, Real* Y0, Real* X1, Real* Y1, Real* X2, Real* Y2, + Real* X3, Real* Y3, Real* X4, Real* Y4); +static void R_8_FTK (int N, int M, + Real* X0, Real* Y0, Real* X1, Real* Y1, + Real* X2, Real* Y2, Real* X3, Real* Y3, + Real* X4, Real* Y4, Real* X5, Real* Y5, + Real* X6, Real* Y6, Real* X7, Real* Y7); +static void R_16_FTK (int N, int M, + Real* X0, Real* Y0, Real* X1, Real* Y1, + Real* X2, Real* Y2, Real* X3, Real* Y3, + Real* X4, Real* Y4, Real* X5, Real* Y5, + Real* X6, Real* Y6, Real* X7, Real* Y7, + Real* X8, Real* Y8, Real* X9, Real* Y9, + Real* X10, Real* Y10, Real* X11, Real* Y11, + Real* X12, Real* Y12, Real* X13, Real* Y13, + Real* X14, Real* Y14, Real* X15, Real* Y15); +static int BitReverse(int x, int prod, int n, const SimpleIntArray& f); + + +bool FFT_Controller::ar_1d_ft (int PTS, Real* X, Real *Y) +{ +// ARBITRARY RADIX ONE DIMENSIONAL FOURIER TRANSFORM + + REPORT + + int F,J,N,NF,P,PMAX,P_SYM,P_TWO,Q,R,TWO_GRP; + + // NP is maximum number of squared factors allows PTS up to 2**32 at least + // NQ is number of not-squared factors - increase if we increase PMAX + const int NP = 16, NQ = 10; + SimpleIntArray PP(NP), QQ(NQ); + + TWO_GRP=16; PMAX=19; + + // PMAX is the maximum factor size + // TWO_GRP is the maximum power of 2 handled as a single factor + // Doesn't take advantage of combining powers of 2 when calculating + // number of factors + + if (PTS<=1) return true; + N=PTS; P_SYM=1; F=2; P=0; Q=0; + + // P counts the number of squared factors + // Q counts the number of the rest + // R = 0 for no non-squared factors; 1 otherwise + + // FACTOR holds all the factors - non-squared ones in the middle + // - length is 2*P+Q + // SYM also holds all the factors but with the non-squared ones + // multiplied together - length is 2*P+R + // PP holds the values of the squared factors - length is P + // QQ holds the values of the rest - length is Q + + // P_SYM holds the product of the squared factors + + // find the factors - load into PP and QQ + while (N > 1) + { + bool fail = true; + for (J=F; J<=PMAX; J++) + if (N % J == 0) { fail = false; F=J; break; } + if (fail || P >= NP || Q >= NQ) return false; // can't factor + N /= F; + if (N % F != 0) QQ[Q++] = F; + else { N /= F; PP[P++] = F; P_SYM *= F; } + } + + R = (Q == 0) ? 0 : 1; // R = 0 if no not-squared factors, 1 otherwise + + NF = 2*P + Q; + SimpleIntArray FACTOR(NF + 1), SYM(2*P + R); + FACTOR[NF] = 0; // we need this in the "combine powers of 2" + + // load into SYM and FACTOR + for (J=0; J<P; J++) + { SYM[J]=FACTOR[J]=PP[P-1-J]; FACTOR[P+Q+J]=SYM[P+R+J]=PP[J]; } + + if (Q>0) + { + REPORT + for (J=0; J<Q; J++) FACTOR[P+J]=QQ[J]; + SYM[P]=PTS/square(P_SYM); + } + + // combine powers of 2 + P_TWO = 1; + for (J=0; J < NF; J++) + { + if (FACTOR[J]!=2) continue; + P_TWO=P_TWO*2; FACTOR[J]=1; + if (P_TWO<TWO_GRP && FACTOR[J+1]==2) continue; + FACTOR[J]=P_TWO; P_TWO=1; + } + + if (P==0) R=0; + if (Q<=1) Q=0; + + // do the analysis + GR_1D_FT(PTS,NF,FACTOR,X,Y); // the transform + GR_1D_FS(PTS,2*P+R,Q,SYM,P_SYM,QQ,X,Y); // the reshuffling + + return true; + +} + +static void GR_1D_FS (int PTS, int N_SYM, int N_UN_SYM, + const SimpleIntArray& SYM, int P_SYM, const SimpleIntArray& UN_SYM, + Real* X, Real* Y) +{ +// GENERAL RADIX ONE DIMENSIONAL FOURIER SORT + +// PTS = number of points +// N_SYM = length of SYM +// N_UN_SYM = length of UN_SYM +// SYM: squared factors + product of non-squared factors + squared factors +// P_SYM = product of squared factors (each included only once) +// UN_SYM: not-squared factors + + REPORT + + Real T; + int JJ,KK,P_UN_SYM; + + // I have replaced the multiple for-loop used by Sande-Gentleman code + // by the following code which does not limit the number of factors + + if (N_SYM > 0) + { + REPORT + SimpleIntArray U(N_SYM); + for(MultiRadixCounter MRC(N_SYM, SYM, U); !MRC.Finish(); ++MRC) + { + if (MRC.Swap()) + { + int P = MRC.Reverse(); int JJ = MRC.Counter(); Real T; + T=X[JJ]; X[JJ]=X[P]; X[P]=T; T=Y[JJ]; Y[JJ]=Y[P]; Y[P]=T; + } + } + } + + int J,JL,K,L,M,MS; + + // UN_SYM contains the non-squared factors + // I have replaced the Sande-Gentleman code as it runs into + // integer overflow problems + // My code (and theirs) would be improved by using a bit array + // as suggested by Van Loan + + if (N_UN_SYM==0) { REPORT return; } + P_UN_SYM=PTS/square(P_SYM); JL=(P_UN_SYM-3)*P_SYM; MS=P_UN_SYM*P_SYM; + + for (J = P_SYM; J<=JL; J+=P_SYM) + { + K=J; + do K = P_SYM * BitReverse(K / P_SYM, P_UN_SYM, N_UN_SYM, UN_SYM); + while (K<J); + + if (K!=J) + { + REPORT + for (L=0; L<P_SYM; L++) for (M=L; M<PTS; M+=MS) + { + JJ=M+J; KK=M+K; + T=X[JJ]; X[JJ]=X[KK]; X[KK]=T; T=Y[JJ]; Y[JJ]=Y[KK]; Y[KK]=T; + } + } + } + + return; +} + +static void GR_1D_FT (int N, int N_FACTOR, const SimpleIntArray& FACTOR, + Real* X, Real* Y) +{ +// GENERAL RADIX ONE DIMENSIONAL FOURIER TRANSFORM; + + REPORT + + int M = N; + + for (int i = 0; i < N_FACTOR; i++) + { + int P = FACTOR[i]; M /= P; + + switch(P) + { + case 1: REPORT break; + case 2: REPORT R_2_FTK (N,M,X,Y,X+M,Y+M); break; + case 3: REPORT R_3_FTK (N,M,X,Y,X+M,Y+M,X+2*M,Y+2*M); break; + case 4: REPORT R_4_FTK (N,M,X,Y,X+M,Y+M,X+2*M,Y+2*M,X+3*M,Y+3*M); break; + case 5: + REPORT + R_5_FTK (N,M,X,Y,X+M,Y+M,X+2*M,Y+2*M,X+3*M,Y+3*M,X+4*M,Y+4*M); + break; + case 8: + REPORT + R_8_FTK (N,M,X,Y,X+M,Y+M,X+2*M,Y+2*M, + X+3*M,Y+3*M,X+4*M,Y+4*M,X+5*M,Y+5*M, + X+6*M,Y+6*M,X+7*M,Y+7*M); + break; + case 16: + REPORT + R_16_FTK (N,M,X,Y,X+M,Y+M,X+2*M,Y+2*M, + X+3*M,Y+3*M,X+4*M,Y+4*M,X+5*M,Y+5*M, + X+6*M,Y+6*M,X+7*M,Y+7*M,X+8*M,Y+8*M, + X+9*M,Y+9*M,X+10*M,Y+10*M,X+11*M,Y+11*M, + X+12*M,Y+12*M,X+13*M,Y+13*M,X+14*M,Y+14*M, + X+15*M,Y+15*M); + break; + default: REPORT R_P_FTK (N,M,P,X,Y); break; + } + } + +} + +static void R_P_FTK (int N, int M, int P, Real* X, Real* Y) +// RADIX PRIME FOURIER TRANSFORM KERNEL; +// X and Y are treated as M * P matrices with Fortran storage +{ + REPORT + bool NO_FOLD,ZERO; + Real ANGLE,IS,IU,RS,RU,T,TWOPI,XT,YT; + int J,JJ,K0,K,M_OVER_2,MP,PM,PP,U,V; + + Real AA [9][9], BB [9][9]; + Real A [18], B [18], C [18], S [18]; + Real IA [9], IB [9], RA [9], RB [9]; + + TWOPI=8.0*atan(1.0); + M_OVER_2=M/2+1; MP=M*P; PP=P/2; PM=P-1; + + for (U=0; U<PP; U++) + { + ANGLE=TWOPI*Real(U+1)/Real(P); + JJ=P-U-2; + A[U]=cos(ANGLE); B[U]=sin(ANGLE); + A[JJ]=A[U]; B[JJ]= -B[U]; + } + + for (U=1; U<=PP; U++) + { + for (V=1; V<=PP; V++) + { JJ=U*V-U*V/P*P; AA[V-1][U-1]=A[JJ-1]; BB[V-1][U-1]=B[JJ-1]; } + } + + for (J=0; J<M_OVER_2; J++) + { + NO_FOLD = (J==0 || 2*J==M); + K0=J; + ANGLE=TWOPI*Real(J)/Real(MP); ZERO=ANGLE==0.0; + C[0]=cos(ANGLE); S[0]=sin(ANGLE); + for (U=1; U<PM; U++) + { + C[U]=C[U-1]*C[0]-S[U-1]*S[0]; + S[U]=S[U-1]*C[0]+C[U-1]*S[0]; + } + goto L700; + L500: + REPORT + if (NO_FOLD) { REPORT goto L1500; } + REPORT + NO_FOLD=true; K0=M-J; + for (U=0; U<PM; U++) + { T=C[U]*A[U]+S[U]*B[U]; S[U]= -S[U]*A[U]+C[U]*B[U]; C[U]=T; } + L700: + REPORT + for (K=K0; K<N; K+=MP) + { + XT=X[K]; YT=Y[K]; + for (U=1; U<=PP; U++) + { + RA[U-1]=XT; IA[U-1]=YT; + RB[U-1]=0.0; IB[U-1]=0.0; + } + for (U=1; U<=PP; U++) + { + JJ=P-U; + RS=X[K+M*U]+X[K+M*JJ]; IS=Y[K+M*U]+Y[K+M*JJ]; + RU=X[K+M*U]-X[K+M*JJ]; IU=Y[K+M*U]-Y[K+M*JJ]; + XT=XT+RS; YT=YT+IS; + for (V=0; V<PP; V++) + { + RA[V]=RA[V]+RS*AA[V][U-1]; IA[V]=IA[V]+IS*AA[V][U-1]; + RB[V]=RB[V]+RU*BB[V][U-1]; IB[V]=IB[V]+IU*BB[V][U-1]; + } + } + X[K]=XT; Y[K]=YT; + for (U=1; U<=PP; U++) + { + if (!ZERO) + { + REPORT + XT=RA[U-1]+IB[U-1]; YT=IA[U-1]-RB[U-1]; + X[K+M*U]=XT*C[U-1]+YT*S[U-1]; Y[K+M*U]=YT*C[U-1]-XT*S[U-1]; + JJ=P-U; + XT=RA[U-1]-IB[U-1]; YT=IA[U-1]+RB[U-1]; + X[K+M*JJ]=XT*C[JJ-1]+YT*S[JJ-1]; + Y[K+M*JJ]=YT*C[JJ-1]-XT*S[JJ-1]; + } + else + { + REPORT + X[K+M*U]=RA[U-1]+IB[U-1]; Y[K+M*U]=IA[U-1]-RB[U-1]; + JJ=P-U; + X[K+M*JJ]=RA[U-1]-IB[U-1]; Y[K+M*JJ]=IA[U-1]+RB[U-1]; + } + } + } + goto L500; +L1500: ; + } + return; +} + +static void R_2_FTK (int N, int M, Real* X0, Real* Y0, Real* X1, Real* Y1) +// RADIX TWO FOURIER TRANSFORM KERNEL; +{ + REPORT + bool NO_FOLD,ZERO; + int J,K,K0,M2,M_OVER_2; + Real ANGLE,C,IS,IU,RS,RU,S,TWOPI; + + M2=M*2; M_OVER_2=M/2+1; + TWOPI=8.0*atan(1.0); + + for (J=0; J<M_OVER_2; J++) + { + NO_FOLD = (J==0 || 2*J==M); + K0=J; + ANGLE=TWOPI*Real(J)/Real(M2); ZERO=ANGLE==0.0; + C=cos(ANGLE); S=sin(ANGLE); + goto L200; + L100: + REPORT + if (NO_FOLD) { REPORT goto L600; } + REPORT + NO_FOLD=true; K0=M-J; C= -C; + L200: + REPORT + for (K=K0; K<N; K+=M2) + { + RS=X0[K]+X1[K]; IS=Y0[K]+Y1[K]; + RU=X0[K]-X1[K]; IU=Y0[K]-Y1[K]; + X0[K]=RS; Y0[K]=IS; + if (!ZERO) { X1[K]=RU*C+IU*S; Y1[K]=IU*C-RU*S; } + else { X1[K]=RU; Y1[K]=IU; } + } + goto L100; + L600: ; + } + + return; +} + +static void R_3_FTK (int N, int M, Real* X0, Real* Y0, Real* X1, Real* Y1, + Real* X2, Real* Y2) +// RADIX THREE FOURIER TRANSFORM KERNEL +{ + REPORT + bool NO_FOLD,ZERO; + int J,K,K0,M3,M_OVER_2; + Real ANGLE,A,B,C1,C2,S1,S2,T,TWOPI; + Real I0,I1,I2,IA,IB,IS,R0,R1,R2,RA,RB,RS; + + M3=M*3; M_OVER_2=M/2+1; TWOPI=8.0*atan(1.0); + A=cos(TWOPI/3.0); B=sin(TWOPI/3.0); + + for (J=0; J<M_OVER_2; J++) + { + NO_FOLD = (J==0 || 2*J==M); + K0=J; + ANGLE=TWOPI*Real(J)/Real(M3); ZERO=ANGLE==0.0; + C1=cos(ANGLE); S1=sin(ANGLE); + C2=C1*C1-S1*S1; S2=S1*C1+C1*S1; + goto L200; + L100: + REPORT + if (NO_FOLD) { REPORT goto L600; } + REPORT + NO_FOLD=true; K0=M-J; + T=C1*A+S1*B; S1=C1*B-S1*A; C1=T; + T=C2*A-S2*B; S2= -C2*B-S2*A; C2=T; + L200: + REPORT + for (K=K0; K<N; K+=M3) + { + R0 = X0[K]; I0 = Y0[K]; + RS=X1[K]+X2[K]; IS=Y1[K]+Y2[K]; + X0[K]=R0+RS; Y0[K]=I0+IS; + RA=R0+RS*A; IA=I0+IS*A; + RB=(X1[K]-X2[K])*B; IB=(Y1[K]-Y2[K])*B; + if (!ZERO) + { + REPORT + R1=RA+IB; I1=IA-RB; R2=RA-IB; I2=IA+RB; + X1[K]=R1*C1+I1*S1; Y1[K]=I1*C1-R1*S1; + X2[K]=R2*C2+I2*S2; Y2[K]=I2*C2-R2*S2; + } + else { REPORT X1[K]=RA+IB; Y1[K]=IA-RB; X2[K]=RA-IB; Y2[K]=IA+RB; } + } + goto L100; + L600: ; + } + + return; +} + +static void R_4_FTK (int N, int M, + Real* X0, Real* Y0, Real* X1, Real* Y1, + Real* X2, Real* Y2, Real* X3, Real* Y3) +// RADIX FOUR FOURIER TRANSFORM KERNEL +{ + REPORT + bool NO_FOLD,ZERO; + int J,K,K0,M4,M_OVER_2; + Real ANGLE,C1,C2,C3,S1,S2,S3,T,TWOPI; + Real I1,I2,I3,IS0,IS1,IU0,IU1,R1,R2,R3,RS0,RS1,RU0,RU1; + + M4=M*4; M_OVER_2=M/2+1; + TWOPI=8.0*atan(1.0); + + for (J=0; J<M_OVER_2; J++) + { + NO_FOLD = (J==0 || 2*J==M); + K0=J; + ANGLE=TWOPI*Real(J)/Real(M4); ZERO=ANGLE==0.0; + C1=cos(ANGLE); S1=sin(ANGLE); + C2=C1*C1-S1*S1; S2=S1*C1+C1*S1; + C3=C2*C1-S2*S1; S3=S2*C1+C2*S1; + goto L200; + L100: + REPORT + if (NO_FOLD) { REPORT goto L600; } + REPORT + NO_FOLD=true; K0=M-J; + T=C1; C1=S1; S1=T; + C2= -C2; + T=C3; C3= -S3; S3= -T; + L200: + REPORT + for (K=K0; K<N; K+=M4) + { + RS0=X0[K]+X2[K]; IS0=Y0[K]+Y2[K]; + RU0=X0[K]-X2[K]; IU0=Y0[K]-Y2[K]; + RS1=X1[K]+X3[K]; IS1=Y1[K]+Y3[K]; + RU1=X1[K]-X3[K]; IU1=Y1[K]-Y3[K]; + X0[K]=RS0+RS1; Y0[K]=IS0+IS1; + if (!ZERO) + { + REPORT + R1=RU0+IU1; I1=IU0-RU1; + R2=RS0-RS1; I2=IS0-IS1; + R3=RU0-IU1; I3=IU0+RU1; + X2[K]=R1*C1+I1*S1; Y2[K]=I1*C1-R1*S1; + X1[K]=R2*C2+I2*S2; Y1[K]=I2*C2-R2*S2; + X3[K]=R3*C3+I3*S3; Y3[K]=I3*C3-R3*S3; + } + else + { + REPORT + X2[K]=RU0+IU1; Y2[K]=IU0-RU1; + X1[K]=RS0-RS1; Y1[K]=IS0-IS1; + X3[K]=RU0-IU1; Y3[K]=IU0+RU1; + } + } + goto L100; + L600: ; + } + + return; +} + +static void R_5_FTK (int N, int M, + Real* X0, Real* Y0, Real* X1, Real* Y1, Real* X2, Real* Y2, + Real* X3, Real* Y3, Real* X4, Real* Y4) +// RADIX FIVE FOURIER TRANSFORM KERNEL + +{ + REPORT + bool NO_FOLD,ZERO; + int J,K,K0,M5,M_OVER_2; + Real ANGLE,A1,A2,B1,B2,C1,C2,C3,C4,S1,S2,S3,S4,T,TWOPI; + Real R0,R1,R2,R3,R4,RA1,RA2,RB1,RB2,RS1,RS2,RU1,RU2; + Real I0,I1,I2,I3,I4,IA1,IA2,IB1,IB2,IS1,IS2,IU1,IU2; + + M5=M*5; M_OVER_2=M/2+1; + TWOPI=8.0*atan(1.0); + A1=cos(TWOPI/5.0); B1=sin(TWOPI/5.0); + A2=cos(2.0*TWOPI/5.0); B2=sin(2.0*TWOPI/5.0); + + for (J=0; J<M_OVER_2; J++) + { + NO_FOLD = (J==0 || 2*J==M); + K0=J; + ANGLE=TWOPI*Real(J)/Real(M5); ZERO=ANGLE==0.0; + C1=cos(ANGLE); S1=sin(ANGLE); + C2=C1*C1-S1*S1; S2=S1*C1+C1*S1; + C3=C2*C1-S2*S1; S3=S2*C1+C2*S1; + C4=C2*C2-S2*S2; S4=S2*C2+C2*S2; + goto L200; + L100: + REPORT + if (NO_FOLD) { REPORT goto L600; } + REPORT + NO_FOLD=true; K0=M-J; + T=C1*A1+S1*B1; S1=C1*B1-S1*A1; C1=T; + T=C2*A2+S2*B2; S2=C2*B2-S2*A2; C2=T; + T=C3*A2-S3*B2; S3= -C3*B2-S3*A2; C3=T; + T=C4*A1-S4*B1; S4= -C4*B1-S4*A1; C4=T; + L200: + REPORT + for (K=K0; K<N; K+=M5) + { + R0=X0[K]; I0=Y0[K]; + RS1=X1[K]+X4[K]; IS1=Y1[K]+Y4[K]; + RU1=X1[K]-X4[K]; IU1=Y1[K]-Y4[K]; + RS2=X2[K]+X3[K]; IS2=Y2[K]+Y3[K]; + RU2=X2[K]-X3[K]; IU2=Y2[K]-Y3[K]; + X0[K]=R0+RS1+RS2; Y0[K]=I0+IS1+IS2; + RA1=R0+RS1*A1+RS2*A2; IA1=I0+IS1*A1+IS2*A2; + RA2=R0+RS1*A2+RS2*A1; IA2=I0+IS1*A2+IS2*A1; + RB1=RU1*B1+RU2*B2; IB1=IU1*B1+IU2*B2; + RB2=RU1*B2-RU2*B1; IB2=IU1*B2-IU2*B1; + if (!ZERO) + { + REPORT + R1=RA1+IB1; I1=IA1-RB1; + R2=RA2+IB2; I2=IA2-RB2; + R3=RA2-IB2; I3=IA2+RB2; + R4=RA1-IB1; I4=IA1+RB1; + X1[K]=R1*C1+I1*S1; Y1[K]=I1*C1-R1*S1; + X2[K]=R2*C2+I2*S2; Y2[K]=I2*C2-R2*S2; + X3[K]=R3*C3+I3*S3; Y3[K]=I3*C3-R3*S3; + X4[K]=R4*C4+I4*S4; Y4[K]=I4*C4-R4*S4; + } + else + { + REPORT + X1[K]=RA1+IB1; Y1[K]=IA1-RB1; + X2[K]=RA2+IB2; Y2[K]=IA2-RB2; + X3[K]=RA2-IB2; Y3[K]=IA2+RB2; + X4[K]=RA1-IB1; Y4[K]=IA1+RB1; + } + } + goto L100; + L600: ; + } + + return; +} + +static void R_8_FTK (int N, int M, + Real* X0, Real* Y0, Real* X1, Real* Y1, + Real* X2, Real* Y2, Real* X3, Real* Y3, + Real* X4, Real* Y4, Real* X5, Real* Y5, + Real* X6, Real* Y6, Real* X7, Real* Y7) +// RADIX EIGHT FOURIER TRANSFORM KERNEL +{ + REPORT + bool NO_FOLD,ZERO; + int J,K,K0,M8,M_OVER_2; + Real ANGLE,C1,C2,C3,C4,C5,C6,C7,E,S1,S2,S3,S4,S5,S6,S7,T,TWOPI; + Real R1,R2,R3,R4,R5,R6,R7,RS0,RS1,RS2,RS3,RU0,RU1,RU2,RU3; + Real I1,I2,I3,I4,I5,I6,I7,IS0,IS1,IS2,IS3,IU0,IU1,IU2,IU3; + Real RSS0,RSS1,RSU0,RSU1,RUS0,RUS1,RUU0,RUU1; + Real ISS0,ISS1,ISU0,ISU1,IUS0,IUS1,IUU0,IUU1; + + M8=M*8; M_OVER_2=M/2+1; + TWOPI=8.0*atan(1.0); E=cos(TWOPI/8.0); + + for (J=0;J<M_OVER_2;J++) + { + NO_FOLD= (J==0 || 2*J==M); + K0=J; + ANGLE=TWOPI*Real(J)/Real(M8); ZERO=ANGLE==0.0; + C1=cos(ANGLE); S1=sin(ANGLE); + C2=C1*C1-S1*S1; S2=C1*S1+S1*C1; + C3=C2*C1-S2*S1; S3=S2*C1+C2*S1; + C4=C2*C2-S2*S2; S4=S2*C2+C2*S2; + C5=C4*C1-S4*S1; S5=S4*C1+C4*S1; + C6=C4*C2-S4*S2; S6=S4*C2+C4*S2; + C7=C4*C3-S4*S3; S7=S4*C3+C4*S3; + goto L200; + L100: + REPORT + if (NO_FOLD) { REPORT goto L600; } + REPORT + NO_FOLD=true; K0=M-J; + T=(C1+S1)*E; S1=(C1-S1)*E; C1=T; + T=S2; S2=C2; C2=T; + T=(-C3+S3)*E; S3=(C3+S3)*E; C3=T; + C4= -C4; + T= -(C5+S5)*E; S5=(-C5+S5)*E; C5=T; + T= -S6; S6= -C6; C6=T; + T=(C7-S7)*E; S7= -(C7+S7)*E; C7=T; + L200: + REPORT + for (K=K0; K<N; K+=M8) + { + RS0=X0[K]+X4[K]; IS0=Y0[K]+Y4[K]; + RU0=X0[K]-X4[K]; IU0=Y0[K]-Y4[K]; + RS1=X1[K]+X5[K]; IS1=Y1[K]+Y5[K]; + RU1=X1[K]-X5[K]; IU1=Y1[K]-Y5[K]; + RS2=X2[K]+X6[K]; IS2=Y2[K]+Y6[K]; + RU2=X2[K]-X6[K]; IU2=Y2[K]-Y6[K]; + RS3=X3[K]+X7[K]; IS3=Y3[K]+Y7[K]; + RU3=X3[K]-X7[K]; IU3=Y3[K]-Y7[K]; + RSS0=RS0+RS2; ISS0=IS0+IS2; + RSU0=RS0-RS2; ISU0=IS0-IS2; + RSS1=RS1+RS3; ISS1=IS1+IS3; + RSU1=RS1-RS3; ISU1=IS1-IS3; + RUS0=RU0-IU2; IUS0=IU0+RU2; + RUU0=RU0+IU2; IUU0=IU0-RU2; + RUS1=RU1-IU3; IUS1=IU1+RU3; + RUU1=RU1+IU3; IUU1=IU1-RU3; + T=(RUS1+IUS1)*E; IUS1=(IUS1-RUS1)*E; RUS1=T; + T=(RUU1+IUU1)*E; IUU1=(IUU1-RUU1)*E; RUU1=T; + X0[K]=RSS0+RSS1; Y0[K]=ISS0+ISS1; + if (!ZERO) + { + REPORT + R1=RUU0+RUU1; I1=IUU0+IUU1; + R2=RSU0+ISU1; I2=ISU0-RSU1; + R3=RUS0+IUS1; I3=IUS0-RUS1; + R4=RSS0-RSS1; I4=ISS0-ISS1; + R5=RUU0-RUU1; I5=IUU0-IUU1; + R6=RSU0-ISU1; I6=ISU0+RSU1; + R7=RUS0-IUS1; I7=IUS0+RUS1; + X4[K]=R1*C1+I1*S1; Y4[K]=I1*C1-R1*S1; + X2[K]=R2*C2+I2*S2; Y2[K]=I2*C2-R2*S2; + X6[K]=R3*C3+I3*S3; Y6[K]=I3*C3-R3*S3; + X1[K]=R4*C4+I4*S4; Y1[K]=I4*C4-R4*S4; + X5[K]=R5*C5+I5*S5; Y5[K]=I5*C5-R5*S5; + X3[K]=R6*C6+I6*S6; Y3[K]=I6*C6-R6*S6; + X7[K]=R7*C7+I7*S7; Y7[K]=I7*C7-R7*S7; + } + else + { + REPORT + X4[K]=RUU0+RUU1; Y4[K]=IUU0+IUU1; + X2[K]=RSU0+ISU1; Y2[K]=ISU0-RSU1; + X6[K]=RUS0+IUS1; Y6[K]=IUS0-RUS1; + X1[K]=RSS0-RSS1; Y1[K]=ISS0-ISS1; + X5[K]=RUU0-RUU1; Y5[K]=IUU0-IUU1; + X3[K]=RSU0-ISU1; Y3[K]=ISU0+RSU1; + X7[K]=RUS0-IUS1; Y7[K]=IUS0+RUS1; + } + } + goto L100; + L600: ; + } + + return; +} + +static void R_16_FTK (int N, int M, + Real* X0, Real* Y0, Real* X1, Real* Y1, + Real* X2, Real* Y2, Real* X3, Real* Y3, + Real* X4, Real* Y4, Real* X5, Real* Y5, + Real* X6, Real* Y6, Real* X7, Real* Y7, + Real* X8, Real* Y8, Real* X9, Real* Y9, + Real* X10, Real* Y10, Real* X11, Real* Y11, + Real* X12, Real* Y12, Real* X13, Real* Y13, + Real* X14, Real* Y14, Real* X15, Real* Y15) +// RADIX SIXTEEN FOURIER TRANSFORM KERNEL +{ + REPORT + bool NO_FOLD,ZERO; + int J,K,K0,M16,M_OVER_2; + Real ANGLE,EI1,ER1,E2,EI3,ER3,EI5,ER5,T,TWOPI; + Real RS0,RS1,RS2,RS3,RS4,RS5,RS6,RS7; + Real IS0,IS1,IS2,IS3,IS4,IS5,IS6,IS7; + Real RU0,RU1,RU2,RU3,RU4,RU5,RU6,RU7; + Real IU0,IU1,IU2,IU3,IU4,IU5,IU6,IU7; + Real RUS0,RUS1,RUS2,RUS3,RUU0,RUU1,RUU2,RUU3; + Real ISS0,ISS1,ISS2,ISS3,ISU0,ISU1,ISU2,ISU3; + Real RSS0,RSS1,RSS2,RSS3,RSU0,RSU1,RSU2,RSU3; + Real IUS0,IUS1,IUS2,IUS3,IUU0,IUU1,IUU2,IUU3; + Real RSSS0,RSSS1,RSSU0,RSSU1,RSUS0,RSUS1,RSUU0,RSUU1; + Real ISSS0,ISSS1,ISSU0,ISSU1,ISUS0,ISUS1,ISUU0,ISUU1; + Real RUSS0,RUSS1,RUSU0,RUSU1,RUUS0,RUUS1,RUUU0,RUUU1; + Real IUSS0,IUSS1,IUSU0,IUSU1,IUUS0,IUUS1,IUUU0,IUUU1; + Real R1,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,R12,R13,R14,R15; + Real I1,I2,I3,I4,I5,I6,I7,I8,I9,I10,I11,I12,I13,I14,I15; + Real C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15; + Real S1,S2,S3,S4,S5,S6,S7,S8,S9,S10,S11,S12,S13,S14,S15; + + M16=M*16; M_OVER_2=M/2+1; + TWOPI=8.0*atan(1.0); + ER1=cos(TWOPI/16.0); EI1=sin(TWOPI/16.0); + E2=cos(TWOPI/8.0); + ER3=cos(3.0*TWOPI/16.0); EI3=sin(3.0*TWOPI/16.0); + ER5=cos(5.0*TWOPI/16.0); EI5=sin(5.0*TWOPI/16.0); + + for (J=0; J<M_OVER_2; J++) + { + NO_FOLD = (J==0 || 2*J==M); + K0=J; + ANGLE=TWOPI*Real(J)/Real(M16); + ZERO=ANGLE==0.0; + C1=cos(ANGLE); S1=sin(ANGLE); + C2=C1*C1-S1*S1; S2=C1*S1+S1*C1; + C3=C2*C1-S2*S1; S3=S2*C1+C2*S1; + C4=C2*C2-S2*S2; S4=S2*C2+C2*S2; + C5=C4*C1-S4*S1; S5=S4*C1+C4*S1; + C6=C4*C2-S4*S2; S6=S4*C2+C4*S2; + C7=C4*C3-S4*S3; S7=S4*C3+C4*S3; + C8=C4*C4-S4*S4; S8=C4*S4+S4*C4; + C9=C8*C1-S8*S1; S9=S8*C1+C8*S1; + C10=C8*C2-S8*S2; S10=S8*C2+C8*S2; + C11=C8*C3-S8*S3; S11=S8*C3+C8*S3; + C12=C8*C4-S8*S4; S12=S8*C4+C8*S4; + C13=C8*C5-S8*S5; S13=S8*C5+C8*S5; + C14=C8*C6-S8*S6; S14=S8*C6+C8*S6; + C15=C8*C7-S8*S7; S15=S8*C7+C8*S7; + goto L200; + L100: + REPORT + if (NO_FOLD) { REPORT goto L600; } + REPORT + NO_FOLD=true; K0=M-J; + T=C1*ER1+S1*EI1; S1= -S1*ER1+C1*EI1; C1=T; + T=(C2+S2)*E2; S2=(C2-S2)*E2; C2=T; + T=C3*ER3+S3*EI3; S3= -S3*ER3+C3*EI3; C3=T; + T=S4; S4=C4; C4=T; + T=S5*ER1-C5*EI1; S5=C5*ER1+S5*EI1; C5=T; + T=(-C6+S6)*E2; S6=(C6+S6)*E2; C6=T; + T=S7*ER3-C7*EI3; S7=C7*ER3+S7*EI3; C7=T; + C8= -C8; + T= -(C9*ER1+S9*EI1); S9=S9*ER1-C9*EI1; C9=T; + T= -(C10+S10)*E2; S10=(-C10+S10)*E2; C10=T; + T= -(C11*ER3+S11*EI3); S11=S11*ER3-C11*EI3; C11=T; + T= -S12; S12= -C12; C12=T; + T= -S13*ER1+C13*EI1; S13= -(C13*ER1+S13*EI1); C13=T; + T=(C14-S14)*E2; S14= -(C14+S14)*E2; C14=T; + T= -S15*ER3+C15*EI3; S15= -(C15*ER3+S15*EI3); C15=T; + L200: + REPORT + for (K=K0; K<N; K+=M16) + { + RS0=X0[K]+X8[K]; IS0=Y0[K]+Y8[K]; + RU0=X0[K]-X8[K]; IU0=Y0[K]-Y8[K]; + RS1=X1[K]+X9[K]; IS1=Y1[K]+Y9[K]; + RU1=X1[K]-X9[K]; IU1=Y1[K]-Y9[K]; + RS2=X2[K]+X10[K]; IS2=Y2[K]+Y10[K]; + RU2=X2[K]-X10[K]; IU2=Y2[K]-Y10[K]; + RS3=X3[K]+X11[K]; IS3=Y3[K]+Y11[K]; + RU3=X3[K]-X11[K]; IU3=Y3[K]-Y11[K]; + RS4=X4[K]+X12[K]; IS4=Y4[K]+Y12[K]; + RU4=X4[K]-X12[K]; IU4=Y4[K]-Y12[K]; + RS5=X5[K]+X13[K]; IS5=Y5[K]+Y13[K]; + RU5=X5[K]-X13[K]; IU5=Y5[K]-Y13[K]; + RS6=X6[K]+X14[K]; IS6=Y6[K]+Y14[K]; + RU6=X6[K]-X14[K]; IU6=Y6[K]-Y14[K]; + RS7=X7[K]+X15[K]; IS7=Y7[K]+Y15[K]; + RU7=X7[K]-X15[K]; IU7=Y7[K]-Y15[K]; + RSS0=RS0+RS4; ISS0=IS0+IS4; + RSS1=RS1+RS5; ISS1=IS1+IS5; + RSS2=RS2+RS6; ISS2=IS2+IS6; + RSS3=RS3+RS7; ISS3=IS3+IS7; + RSU0=RS0-RS4; ISU0=IS0-IS4; + RSU1=RS1-RS5; ISU1=IS1-IS5; + RSU2=RS2-RS6; ISU2=IS2-IS6; + RSU3=RS3-RS7; ISU3=IS3-IS7; + RUS0=RU0-IU4; IUS0=IU0+RU4; + RUS1=RU1-IU5; IUS1=IU1+RU5; + RUS2=RU2-IU6; IUS2=IU2+RU6; + RUS3=RU3-IU7; IUS3=IU3+RU7; + RUU0=RU0+IU4; IUU0=IU0-RU4; + RUU1=RU1+IU5; IUU1=IU1-RU5; + RUU2=RU2+IU6; IUU2=IU2-RU6; + RUU3=RU3+IU7; IUU3=IU3-RU7; + T=(RSU1+ISU1)*E2; ISU1=(ISU1-RSU1)*E2; RSU1=T; + T=(RSU3+ISU3)*E2; ISU3=(ISU3-RSU3)*E2; RSU3=T; + T=RUS1*ER3+IUS1*EI3; IUS1=IUS1*ER3-RUS1*EI3; RUS1=T; + T=(RUS2+IUS2)*E2; IUS2=(IUS2-RUS2)*E2; RUS2=T; + T=RUS3*ER5+IUS3*EI5; IUS3=IUS3*ER5-RUS3*EI5; RUS3=T; + T=RUU1*ER1+IUU1*EI1; IUU1=IUU1*ER1-RUU1*EI1; RUU1=T; + T=(RUU2+IUU2)*E2; IUU2=(IUU2-RUU2)*E2; RUU2=T; + T=RUU3*ER3+IUU3*EI3; IUU3=IUU3*ER3-RUU3*EI3; RUU3=T; + RSSS0=RSS0+RSS2; ISSS0=ISS0+ISS2; + RSSS1=RSS1+RSS3; ISSS1=ISS1+ISS3; + RSSU0=RSS0-RSS2; ISSU0=ISS0-ISS2; + RSSU1=RSS1-RSS3; ISSU1=ISS1-ISS3; + RSUS0=RSU0-ISU2; ISUS0=ISU0+RSU2; + RSUS1=RSU1-ISU3; ISUS1=ISU1+RSU3; + RSUU0=RSU0+ISU2; ISUU0=ISU0-RSU2; + RSUU1=RSU1+ISU3; ISUU1=ISU1-RSU3; + RUSS0=RUS0-IUS2; IUSS0=IUS0+RUS2; + RUSS1=RUS1-IUS3; IUSS1=IUS1+RUS3; + RUSU0=RUS0+IUS2; IUSU0=IUS0-RUS2; + RUSU1=RUS1+IUS3; IUSU1=IUS1-RUS3; + RUUS0=RUU0+RUU2; IUUS0=IUU0+IUU2; + RUUS1=RUU1+RUU3; IUUS1=IUU1+IUU3; + RUUU0=RUU0-RUU2; IUUU0=IUU0-IUU2; + RUUU1=RUU1-RUU3; IUUU1=IUU1-IUU3; + X0[K]=RSSS0+RSSS1; Y0[K]=ISSS0+ISSS1; + if (!ZERO) + { + REPORT + R1=RUUS0+RUUS1; I1=IUUS0+IUUS1; + R2=RSUU0+RSUU1; I2=ISUU0+ISUU1; + R3=RUSU0+RUSU1; I3=IUSU0+IUSU1; + R4=RSSU0+ISSU1; I4=ISSU0-RSSU1; + R5=RUUU0+IUUU1; I5=IUUU0-RUUU1; + R6=RSUS0+ISUS1; I6=ISUS0-RSUS1; + R7=RUSS0+IUSS1; I7=IUSS0-RUSS1; + R8=RSSS0-RSSS1; I8=ISSS0-ISSS1; + R9=RUUS0-RUUS1; I9=IUUS0-IUUS1; + R10=RSUU0-RSUU1; I10=ISUU0-ISUU1; + R11=RUSU0-RUSU1; I11=IUSU0-IUSU1; + R12=RSSU0-ISSU1; I12=ISSU0+RSSU1; + R13=RUUU0-IUUU1; I13=IUUU0+RUUU1; + R14=RSUS0-ISUS1; I14=ISUS0+RSUS1; + R15=RUSS0-IUSS1; I15=IUSS0+RUSS1; + X8[K]=R1*C1+I1*S1; Y8[K]=I1*C1-R1*S1; + X4[K]=R2*C2+I2*S2; Y4[K]=I2*C2-R2*S2; + X12[K]=R3*C3+I3*S3; Y12[K]=I3*C3-R3*S3; + X2[K]=R4*C4+I4*S4; Y2[K]=I4*C4-R4*S4; + X10[K]=R5*C5+I5*S5; Y10[K]=I5*C5-R5*S5; + X6[K]=R6*C6+I6*S6; Y6[K]=I6*C6-R6*S6; + X14[K]=R7*C7+I7*S7; Y14[K]=I7*C7-R7*S7; + X1[K]=R8*C8+I8*S8; Y1[K]=I8*C8-R8*S8; + X9[K]=R9*C9+I9*S9; Y9[K]=I9*C9-R9*S9; + X5[K]=R10*C10+I10*S10; Y5[K]=I10*C10-R10*S10; + X13[K]=R11*C11+I11*S11; Y13[K]=I11*C11-R11*S11; + X3[K]=R12*C12+I12*S12; Y3[K]=I12*C12-R12*S12; + X11[K]=R13*C13+I13*S13; Y11[K]=I13*C13-R13*S13; + X7[K]=R14*C14+I14*S14; Y7[K]=I14*C14-R14*S14; + X15[K]=R15*C15+I15*S15; Y15[K]=I15*C15-R15*S15; + } + else + { + REPORT + X8[K]=RUUS0+RUUS1; Y8[K]=IUUS0+IUUS1; + X4[K]=RSUU0+RSUU1; Y4[K]=ISUU0+ISUU1; + X12[K]=RUSU0+RUSU1; Y12[K]=IUSU0+IUSU1; + X2[K]=RSSU0+ISSU1; Y2[K]=ISSU0-RSSU1; + X10[K]=RUUU0+IUUU1; Y10[K]=IUUU0-RUUU1; + X6[K]=RSUS0+ISUS1; Y6[K]=ISUS0-RSUS1; + X14[K]=RUSS0+IUSS1; Y14[K]=IUSS0-RUSS1; + X1[K]=RSSS0-RSSS1; Y1[K]=ISSS0-ISSS1; + X9[K]=RUUS0-RUUS1; Y9[K]=IUUS0-IUUS1; + X5[K]=RSUU0-RSUU1; Y5[K]=ISUU0-ISUU1; + X13[K]=RUSU0-RUSU1; Y13[K]=IUSU0-IUSU1; + X3[K]=RSSU0-ISSU1; Y3[K]=ISSU0+RSSU1; + X11[K]=RUUU0-IUUU1; Y11[K]=IUUU0+RUUU1; + X7[K]=RSUS0-ISUS1; Y7[K]=ISUS0+RSUS1; + X15[K]=RUSS0-IUSS1; Y15[K]=IUSS0+RUSS1; + } + } + goto L100; + L600: ; + } + + return; +} + +// can the number of points be factorised sufficiently +// for the fft to run + +bool FFT_Controller::CanFactor(int PTS) +{ + REPORT + const int NP = 16, NQ = 10, PMAX=19; + + if (PTS<=1) { REPORT return true; } + + int N = PTS, F = 2, P = 0, Q = 0; + + while (N > 1) + { + bool fail = true; + for (int J = F; J <= PMAX; J++) + if (N % J == 0) { fail = false; F=J; break; } + if (fail || P >= NP || Q >= NQ) { REPORT return false; } + N /= F; + if (N % F != 0) Q++; else { N /= F; P++; } + } + + return true; // can factorise + +} + +bool FFT_Controller::OnlyOldFFT; // static variable + +// **************************** multi radix counter ********************** + +MultiRadixCounter::MultiRadixCounter(int nx, const SimpleIntArray& rx, + SimpleIntArray& vx) + : Radix(rx), Value(vx), n(nx), reverse(0), + product(1), counter(0), finish(false) +{ + REPORT for (int k = 0; k < n; k++) { Value[k] = 0; product *= Radix[k]; } +} + +void MultiRadixCounter::operator++() +{ + REPORT + counter++; int p = product; + for (int k = 0; k < n; k++) + { + Value[k]++; int p1 = p / Radix[k]; reverse += p1; + if (Value[k] == Radix[k]) { REPORT Value[k] = 0; reverse -= p; p = p1; } + else { REPORT return; } + } + finish = true; +} + + +static int BitReverse(int x, int prod, int n, const SimpleIntArray& f) +{ + // x = c[0]+f[0]*(c[1]+f[1]*(c[2]+... + // return c[n-1]+f[n-1]*(c[n-2]+f[n-2]*(c[n-3]+... + // prod is the product of the f[i] + // n is the number of f[i] (don't assume f has the correct length) + + REPORT + const int* d = f.Data() + n; int sum = 0; int q = 1; + while (n--) + { + prod /= *(--d); + int c = x / prod; x-= c * prod; + sum += q * c; q *= *d; + } + return sum; +} + + +#ifdef use_namespace +} +#endif + + diff --git a/Utilities/OSSIM/ossim_core/matrix/newmat.h b/Utilities/OSSIM/ossim_core/matrix/newmat.h new file mode 100644 index 0000000000..3bc64194b6 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/newmat.h @@ -0,0 +1,1805 @@ +//$$ newmat.h definition file for new version of matrix package + +// Copyright (C) 1991,2,3,4,7,2000,2,3: R B Davies + +#ifndef NEWMAT_LIB +#define NEWMAT_LIB 0 + +#include "include.h" + +#include "myexcept.h" + + +#ifdef use_namespace +namespace NEWMAT { using namespace RBD_COMMON; } +namespace RBD_LIBRARIES { using namespace NEWMAT; } +namespace NEWMAT { +#endif + +//#define DO_REPORT // to activate REPORT + +#ifdef NO_LONG_NAMES +#define UpperTriangularMatrix UTMatrix +#define LowerTriangularMatrix LTMatrix +#define SymmetricMatrix SMatrix +#define DiagonalMatrix DMatrix +#define BandMatrix BMatrix +#define UpperBandMatrix UBMatrix +#define LowerBandMatrix LBMatrix +#define SymmetricBandMatrix SBMatrix +#define BandLUMatrix BLUMatrix +#endif + +// ************************** general utilities ****************************/ + +class GeneralMatrix; + +void MatrixErrorNoSpace(const void*); // no space handler + +class LogAndSign +// Return from LogDeterminant function +// - value of the log plus the sign (+, - or 0) +{ + Real log_value; + int sign; +public: + LogAndSign() { log_value=0.0; sign=1; } + LogAndSign(Real); + void operator*=(Real); + void PowEq(int k); // raise to power of k + void ChangeSign() { sign = -sign; } + Real LogValue() const { return log_value; } + int Sign() const { return sign; } + Real Value() const; + FREE_CHECK(LogAndSign) +}; + +// the following class is for counting the number of times a piece of code +// is executed. It is used for locating any code not executed by test +// routines. Use turbo GREP locate all places this code is called and +// check which ones are not accessed. +// Somewhat implementation dependent as it relies on "cout" still being +// present when ExeCounter objects are destructed. + +#ifdef DO_REPORT + +class ExeCounter +{ + int line; // code line number + int fileid; // file identifier + long nexe; // number of executions + static int nreports; // number of reports +public: + ExeCounter(int,int); + void operator++() { nexe++; } + ~ExeCounter(); // prints out reports +}; + +#endif + + +// ************************** class MatrixType *****************************/ + +// Is used for finding the type of a matrix resulting from the binary operations +// +, -, * and identifying what conversions are permissible. +// This class must be updated when new matrix types are added. + +class GeneralMatrix; // defined later +class BaseMatrix; // defined later +class MatrixInput; // defined later + +class OSSIM_DLL MatrixType +{ +public: + enum Attribute { Valid = 1, + Diagonal = 2, // order of these is important + Symmetric = 4, + Band = 8, + Lower = 16, + Upper = 32, + Square = 64, + Skew = 128, + LUDeco = 256, + Ones = 512 }; + + enum { US = 0, + UT = Valid + Upper + Square, + LT = Valid + Lower + Square, + Rt = Valid, + Sq = Valid + Square, + Sm = Valid + Symmetric + Square, + Sk = Valid + Skew + Square, + Dg = Valid + Diagonal + Band + Lower + Upper + Symmetric + + Square, + Id = Valid + Diagonal + Band + Lower + Upper + Symmetric + + Square + Ones, + RV = Valid, // do not separate out + CV = Valid, // vectors + BM = Valid + Band + Square, + UB = Valid + Band + Upper + Square, + LB = Valid + Band + Lower + Square, + SB = Valid + Band + Symmetric + Square, + Ct = Valid + LUDeco + Square, + BC = Valid + Band + LUDeco + Square, + Mask = ~Square + }; + + + static int nTypes() { return 12; } // number of different types + // exclude Ct, US, BC +public: + int attribute; + bool DataLossOK; // true if data loss is OK when + // this represents a destination +public: + MatrixType () : DataLossOK(false) {} + MatrixType (int i) : attribute(i), DataLossOK(false) {} + MatrixType (int i, bool dlok) : attribute(i), DataLossOK(dlok) {} + MatrixType (const MatrixType& mt) + : attribute(mt.attribute), DataLossOK(mt.DataLossOK) {} + void operator=(const MatrixType& mt) + { attribute = mt.attribute; DataLossOK = mt.DataLossOK; } + void SetDataLossOK() { DataLossOK = true; } + int operator+() const { return attribute; } + MatrixType operator+(MatrixType mt) const + { return MatrixType(attribute & mt.attribute); } + MatrixType operator*(const MatrixType&) const; + MatrixType SP(const MatrixType&) const; + MatrixType KP(const MatrixType&) const; + MatrixType operator|(const MatrixType& mt) const + { return MatrixType(attribute & mt.attribute & Valid); } + MatrixType operator&(const MatrixType& mt) const + { return MatrixType(attribute & mt.attribute & Valid); } + bool operator>=(MatrixType mt) const + { return ( attribute & ~mt.attribute & Mask ) == 0; } + bool operator<(MatrixType mt) const // for MS Visual C++ 4 + { return ( attribute & ~mt.attribute & Mask ) != 0; } + bool operator==(MatrixType t) const + { return (attribute == t.attribute); } + bool operator!=(MatrixType t) const + { return (attribute != t.attribute); } + bool operator!() const { return (attribute & Valid) == 0; } + MatrixType i() const; // type of inverse + MatrixType t() const; // type of transpose + MatrixType AddEqualEl() const // Add constant to matrix + { return MatrixType(attribute & (Valid + Symmetric + Square)); } + MatrixType MultRHS() const; // type for rhs of multiply + MatrixType sub() const // type of submatrix + { return MatrixType(attribute & Valid); } + MatrixType ssub() const // type of sym submatrix + { return MatrixType(attribute); } // not for selection matrix + GeneralMatrix* New() const; // new matrix of given type + GeneralMatrix* New(int,int,BaseMatrix*) const; + // new matrix of given type + const char* Value() const; // to print type + friend bool Rectangular(MatrixType a, MatrixType b, MatrixType c); + friend bool Compare(const MatrixType&, MatrixType&); + // compare and check conv. + bool IsBand() const { return (attribute & Band) != 0; } + bool IsDiagonal() const { return (attribute & Diagonal) != 0; } + bool IsSymmetric() const { return (attribute & Symmetric) != 0; } + bool CannotConvert() const { return (attribute & LUDeco) != 0; } + // used by operator== + FREE_CHECK(MatrixType) +}; + + +// *********************** class MatrixBandWidth ***********************/ + +class OSSIM_DLL MatrixBandWidth +{ +public: + int lower; + int upper; + MatrixBandWidth(const int l, const int u) : lower(l), upper (u) {} + MatrixBandWidth(const int i) : lower(i), upper(i) {} + MatrixBandWidth operator+(const MatrixBandWidth&) const; + MatrixBandWidth operator*(const MatrixBandWidth&) const; + MatrixBandWidth minimum(const MatrixBandWidth&) const; + MatrixBandWidth t() const { return MatrixBandWidth(upper,lower); } + bool operator==(const MatrixBandWidth& bw) const + { return (lower == bw.lower) && (upper == bw.upper); } + bool operator!=(const MatrixBandWidth& bw) const { return !operator==(bw); } + int Upper() const { return upper; } + int Lower() const { return lower; } + FREE_CHECK(MatrixBandWidth) +}; + + +// ********************* Array length specifier ************************/ + +// This class is introduced to avoid constructors such as +// ColumnVector(int) +// being used for conversions + +class OSSIM_DLL ArrayLengthSpecifier +{ + int value; +public: + int Value() const { return value; } + ArrayLengthSpecifier(int l) : value(l) {} +}; + +// ************************* Matrix routines ***************************/ + + +class MatrixRowCol; // defined later +class MatrixRow; +class MatrixCol; +class MatrixColX; + +class GeneralMatrix; // defined later +class AddedMatrix; +class MultipliedMatrix; +class SubtractedMatrix; +class SPMatrix; +class KPMatrix; +class ConcatenatedMatrix; +class StackedMatrix; +class SolvedMatrix; +class ShiftedMatrix; +class NegShiftedMatrix; +class ScaledMatrix; +class TransposedMatrix; +class ReversedMatrix; +class NegatedMatrix; +class InvertedMatrix; +class RowedMatrix; +class ColedMatrix; +class DiagedMatrix; +class MatedMatrix; +class GetSubMatrix; +class ReturnMatrix; +class Matrix; +class SquareMatrix; +class nricMatrix; +class RowVector; +class ColumnVector; +class SymmetricMatrix; +class UpperTriangularMatrix; +class LowerTriangularMatrix; +class DiagonalMatrix; +class CroutMatrix; +class BandMatrix; +class LowerBandMatrix; +class UpperBandMatrix; +class SymmetricBandMatrix; +class LinearEquationSolver; +class GenericMatrix; + + +#define MatrixTypeUnSp 0 +//static MatrixType MatrixTypeUnSp(MatrixType::US); +// // AT&T needs this + +class OSSIM_DLL BaseMatrix : public Janitor // base of all matrix classes +{ +protected: + virtual int search(const BaseMatrix*) const = 0; + // count number of times matrix + // is referred to + +public: + virtual GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp) = 0; + // evaluate temporary + // for old version of G++ + // virtual GeneralMatrix* Evaluate(MatrixType mt) = 0; + // GeneralMatrix* Evaluate() { return Evaluate(MatrixTypeUnSp); } + AddedMatrix operator+(const BaseMatrix&) const; // results of operations + MultipliedMatrix operator*(const BaseMatrix&) const; + SubtractedMatrix operator-(const BaseMatrix&) const; + ConcatenatedMatrix operator|(const BaseMatrix&) const; + StackedMatrix operator&(const BaseMatrix&) const; + ShiftedMatrix operator+(Real) const; + ScaledMatrix operator*(Real) const; + ScaledMatrix operator/(Real) const; + ShiftedMatrix operator-(Real) const; + TransposedMatrix t() const; +// TransposedMatrix t; + NegatedMatrix operator-() const; // change sign of elements + ReversedMatrix Reverse() const; + InvertedMatrix i() const; +// InvertedMatrix i; + RowedMatrix AsRow() const; + ColedMatrix AsColumn() const; + DiagedMatrix AsDiagonal() const; + MatedMatrix AsMatrix(int,int) const; + GetSubMatrix SubMatrix(int,int,int,int) const; + GetSubMatrix SymSubMatrix(int,int) const; + GetSubMatrix Row(int) const; + GetSubMatrix Rows(int,int) const; + GetSubMatrix Column(int) const; + GetSubMatrix Columns(int,int) const; + Real AsScalar() const; // conversion of 1 x 1 matrix + virtual LogAndSign LogDeterminant() const; + Real Determinant() const; + virtual Real SumSquare() const; + Real NormFrobenius() const; + virtual Real SumAbsoluteValue() const; + virtual Real Sum() const; + virtual Real MaximumAbsoluteValue() const; + virtual Real MaximumAbsoluteValue1(int& i) const; + virtual Real MaximumAbsoluteValue2(int& i, int& j) const; + virtual Real MinimumAbsoluteValue() const; + virtual Real MinimumAbsoluteValue1(int& i) const; + virtual Real MinimumAbsoluteValue2(int& i, int& j) const; + virtual Real Maximum() const; + virtual Real Maximum1(int& i) const; + virtual Real Maximum2(int& i, int& j) const; + virtual Real Minimum() const; + virtual Real Minimum1(int& i) const; + virtual Real Minimum2(int& i, int& j) const; + virtual Real Trace() const; + Real Norm1() const; + Real NormInfinity() const; + virtual MatrixBandWidth BandWidth() const; // bandwidths of band matrix + virtual void CleanUp() {} // to clear store + void IEQND() const; // called by ineq. ops +// virtual ReturnMatrix Reverse() const; // reverse order of elements +//protected: +// BaseMatrix() : t(this), i(this) {} + + friend class GeneralMatrix; + friend class Matrix; + friend class SquareMatrix; + friend class nricMatrix; + friend class RowVector; + friend class ColumnVector; + friend class SymmetricMatrix; + friend class UpperTriangularMatrix; + friend class LowerTriangularMatrix; + friend class DiagonalMatrix; + friend class CroutMatrix; + friend class BandMatrix; + friend class LowerBandMatrix; + friend class UpperBandMatrix; + friend class SymmetricBandMatrix; + friend class AddedMatrix; + friend class MultipliedMatrix; + friend class SubtractedMatrix; + friend class SPMatrix; + friend class KPMatrix; + friend class ConcatenatedMatrix; + friend class StackedMatrix; + friend class SolvedMatrix; + friend class ShiftedMatrix; + friend class NegShiftedMatrix; + friend class ScaledMatrix; + friend class TransposedMatrix; + friend class ReversedMatrix; + friend class NegatedMatrix; + friend class InvertedMatrix; + friend class RowedMatrix; + friend class ColedMatrix; + friend class DiagedMatrix; + friend class MatedMatrix; + friend class GetSubMatrix; + friend class ReturnMatrix; + friend class LinearEquationSolver; + friend class GenericMatrix; + NEW_DELETE(BaseMatrix) +}; + + +// ***************************** working classes **************************/ + +class OSSIM_DLL GeneralMatrix : public BaseMatrix // declarable matrix types +{ + virtual GeneralMatrix* Image() const; // copy of matrix +protected: + int tag; // shows whether can reuse + int nrows, ncols; // dimensions + int storage; // total store required + Real* store; // point to store (0=not set) + GeneralMatrix(); // initialise with no store + GeneralMatrix(ArrayLengthSpecifier); // constructor getting store + void Add(GeneralMatrix*, Real); // sum of GM and Real + void Add(Real); // add Real to this + void NegAdd(GeneralMatrix*, Real); // Real - GM + void NegAdd(Real); // this = this - Real + void Multiply(GeneralMatrix*, Real); // product of GM and Real + void Multiply(Real); // multiply this by Real + void Negate(GeneralMatrix*); // change sign + void Negate(); // change sign + void ReverseElements(); // internal reverse of elements + void ReverseElements(GeneralMatrix*); // reverse order of elements + void operator=(Real); // set matrix to constant + Real* GetStore(); // get store or copy + GeneralMatrix* BorrowStore(GeneralMatrix*, MatrixType); + // temporarily access store + void GetMatrix(const GeneralMatrix*); // used by = and initialise + void Eq(const BaseMatrix&, MatrixType); // used by = + void Eq(const GeneralMatrix&); // version with no conversion + void Eq(const BaseMatrix&, MatrixType, bool);// used by << + void Eq2(const BaseMatrix&, MatrixType); // cut down version of Eq + int search(const BaseMatrix*) const; + virtual GeneralMatrix* Transpose(TransposedMatrix*, MatrixType); + void CheckConversion(const BaseMatrix&); // check conversion OK + void ReSize(int, int, int); // change dimensions + virtual short SimpleAddOK(const GeneralMatrix* /* gm */ ) { return 0; } + // see bandmat.cpp for explanation + virtual void MiniCleanUp() { store = 0; storage = 0; nrows = 0; ncols = 0; tag = -1;} + // CleanUp when the data array has already been deleted + void PlusEqual(const GeneralMatrix& gm); + void MinusEqual(const GeneralMatrix& gm); + void PlusEqual(Real f); + void MinusEqual(Real f); +public: + GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp); + virtual MatrixType Type() const = 0; // type of a matrix + int Nrows() const { return nrows; } // get dimensions + int Ncols() const { return ncols; } + int Storage() const { return storage; } + Real* Store() const { return store; } + virtual ~GeneralMatrix(); // delete store if set + void tDelete(); // delete if tag permits + bool reuse(); // true if tag allows reuse + void Protect() { tag=-1; } // cannot delete or reuse + int Tag() const { return tag; } + bool IsZero() const; // test matrix has all zeros + void Release() { tag=1; } // del store after next use + void Release(int t) { tag=t; } // del store after t accesses + void ReleaseAndDelete() { tag=0; } // delete matrix after use + void operator<<(const Real*); // assignment from an array + void operator<<(const int*); // assignment from an array + void operator<<(const BaseMatrix& X) + { Eq(X,this->Type(),true); } // = without checking type + void Inject(const GeneralMatrix&); // copy stored els only + void operator+=(const BaseMatrix&); + void operator-=(const BaseMatrix&); + void operator*=(const BaseMatrix&); + void operator|=(const BaseMatrix&); + void operator&=(const BaseMatrix&); + void operator+=(Real); + void operator-=(Real r) { operator+=(-r); } + void operator*=(Real); + void operator/=(Real r) { operator*=(1.0/r); } + virtual GeneralMatrix* MakeSolver(); // for solving + virtual void Solver(MatrixColX&, const MatrixColX&) {} + virtual void GetRow(MatrixRowCol&) = 0; // Get matrix row + virtual void RestoreRow(MatrixRowCol&) {} // Restore matrix row + virtual void NextRow(MatrixRowCol&); // Go to next row + virtual void GetCol(MatrixRowCol&) = 0; // Get matrix col + virtual void GetCol(MatrixColX&) = 0; // Get matrix col + virtual void RestoreCol(MatrixRowCol&) {} // Restore matrix col + virtual void RestoreCol(MatrixColX&) {} // Restore matrix col + virtual void NextCol(MatrixRowCol&); // Go to next col + virtual void NextCol(MatrixColX&); // Go to next col + Real SumSquare() const; + Real SumAbsoluteValue() const; + Real Sum() const; + Real MaximumAbsoluteValue1(int& i) const; + Real MinimumAbsoluteValue1(int& i) const; + Real Maximum1(int& i) const; + Real Minimum1(int& i) const; + Real MaximumAbsoluteValue() const; + Real MaximumAbsoluteValue2(int& i, int& j) const; + Real MinimumAbsoluteValue() const; + Real MinimumAbsoluteValue2(int& i, int& j) const; + Real Maximum() const; + Real Maximum2(int& i, int& j) const; + Real Minimum() const; + Real Minimum2(int& i, int& j) const; + LogAndSign LogDeterminant() const; + virtual bool IsEqual(const GeneralMatrix&) const; + // same type, same values + void CheckStore() const; // check store is non-zero + virtual void SetParameters(const GeneralMatrix*) {} + // set parameters in GetMatrix + operator ReturnMatrix() const; // for building a ReturnMatrix + ReturnMatrix ForReturn() const; + virtual bool SameStorageType(const GeneralMatrix& A) const; + virtual void ReSizeForAdd(const GeneralMatrix& A, const GeneralMatrix& B); + virtual void ReSizeForSP(const GeneralMatrix& A, const GeneralMatrix& B); + virtual void ReSize(const GeneralMatrix& A); + MatrixInput operator<<(Real); // for loading a list + MatrixInput operator<<(int f); +// ReturnMatrix Reverse() const; // reverse order of elements + void CleanUp(); // to clear store + + friend class Matrix; + friend class SquareMatrix; + friend class nricMatrix; + friend class SymmetricMatrix; + friend class UpperTriangularMatrix; + friend class LowerTriangularMatrix; + friend class DiagonalMatrix; + friend class CroutMatrix; + friend class RowVector; + friend class ColumnVector; + friend class BandMatrix; + friend class LowerBandMatrix; + friend class UpperBandMatrix; + friend class SymmetricBandMatrix; + friend class BaseMatrix; + friend class AddedMatrix; + friend class MultipliedMatrix; + friend class SubtractedMatrix; + friend class SPMatrix; + friend class KPMatrix; + friend class ConcatenatedMatrix; + friend class StackedMatrix; + friend class SolvedMatrix; + friend class ShiftedMatrix; + friend class NegShiftedMatrix; + friend class ScaledMatrix; + friend class TransposedMatrix; + friend class ReversedMatrix; + friend class NegatedMatrix; + friend class InvertedMatrix; + friend class RowedMatrix; + friend class ColedMatrix; + friend class DiagedMatrix; + friend class MatedMatrix; + friend class GetSubMatrix; + friend class ReturnMatrix; + friend class LinearEquationSolver; + friend class GenericMatrix; + NEW_DELETE(GeneralMatrix) +}; + + + +class OSSIM_DLL Matrix : public GeneralMatrix // usual rectangular matrix +{ + GeneralMatrix* Image() const; // copy of matrix +public: + Matrix():GeneralMatrix() {} + ~Matrix() {} + Matrix(int, int); // standard declaration + Matrix(const BaseMatrix&); // evaluate BaseMatrix + void operator=(const BaseMatrix&); + void operator=(Real f) { GeneralMatrix::operator=(f); } + void operator=(const Matrix& m) { Eq(m); } + MatrixType Type() const; + Real& operator()(int, int); // access element + Real& element(int, int); // access element + Real operator()(int, int) const; // access element + Real element(int, int) const; // access element +#ifdef SETUP_C_SUBSCRIPTS + Real* operator[](int m) { return store+m*ncols; } + const Real* operator[](int m) const { return store+m*ncols; } +#endif + Matrix(const Matrix& gm):GeneralMatrix(gm) { GetMatrix(&gm); } + GeneralMatrix* MakeSolver(); + Real Trace() const; + void GetRow(MatrixRowCol&); + void GetCol(MatrixRowCol&); + void GetCol(MatrixColX&); + void RestoreCol(MatrixRowCol&); + void RestoreCol(MatrixColX&); + void NextRow(MatrixRowCol&); + void NextCol(MatrixRowCol&); + void NextCol(MatrixColX&); + virtual void ReSize(int,int); // change dimensions + // virtual so we will catch it being used in a vector called as a matrix + void ReSize(const GeneralMatrix& A); + Real MaximumAbsoluteValue2(int& i, int& j) const; + Real MinimumAbsoluteValue2(int& i, int& j) const; + Real Maximum2(int& i, int& j) const; + Real Minimum2(int& i, int& j) const; + void operator+=(const Matrix& M) { PlusEqual(M); } + void operator-=(const Matrix& M) { MinusEqual(M); } + void operator+=(Real f) { GeneralMatrix::Add(f); } + void operator-=(Real f) { GeneralMatrix::Add(-f); } + friend Real DotProduct(const Matrix& A, const Matrix& B); + NEW_DELETE(Matrix) +}; + +class OSSIM_DLL SquareMatrix : public Matrix // square matrix +{ + GeneralMatrix* Image() const; // copy of matrix +public: + SquareMatrix() {} + ~SquareMatrix() {} + SquareMatrix(ArrayLengthSpecifier); // standard declaration + SquareMatrix(const BaseMatrix&); // evaluate BaseMatrix + void operator=(const BaseMatrix&); + void operator=(Real f) { GeneralMatrix::operator=(f); } + void operator=(const SquareMatrix& m) { Eq(m); } + void operator=(const Matrix& m); + MatrixType Type() const; + SquareMatrix(const SquareMatrix& gm):Matrix(gm) { GetMatrix(&gm); } + SquareMatrix(const Matrix& gm); + void ReSize(int); // change dimensions + virtual void ReSize(int,int); // change dimensions + // virtual so we will catch it being used in a vector called as a matrix + void ReSize(const GeneralMatrix& A); + void operator+=(const Matrix& M) { PlusEqual(M); } + void operator-=(const Matrix& M) { MinusEqual(M); } + void operator+=(Real f) { GeneralMatrix::Add(f); } + void operator-=(Real f) { GeneralMatrix::Add(-f); } + NEW_DELETE(SquareMatrix) +}; + +class OSSIM_DLL nricMatrix : public Matrix // for use with Numerical + // Recipes in C +{ + GeneralMatrix* Image() const; // copy of matrix + Real** row_pointer; // points to rows + void MakeRowPointer(); // build rowpointer + void DeleteRowPointer(); +public: + nricMatrix():Matrix() {} + nricMatrix(int m, int n) // standard declaration + : Matrix(m,n) { MakeRowPointer(); } + nricMatrix(const BaseMatrix& bm) // evaluate BaseMatrix + : Matrix(bm) { MakeRowPointer(); } + void operator=(const BaseMatrix& bm) + { DeleteRowPointer(); Matrix::operator=(bm); MakeRowPointer(); } + void operator=(Real f) { GeneralMatrix::operator=(f); } + void operator=(const nricMatrix& m) + { DeleteRowPointer(); Eq(m); MakeRowPointer(); } + void operator<<(const BaseMatrix& X) + { DeleteRowPointer(); Eq(X,this->Type(),true); MakeRowPointer(); } + nricMatrix(const nricMatrix& gm):Matrix(gm) { GetMatrix(&gm); MakeRowPointer(); } + void ReSize(int m, int n) // change dimensions + { DeleteRowPointer(); Matrix::ReSize(m,n); MakeRowPointer(); } + void ReSize(const GeneralMatrix& A); + ~nricMatrix() { DeleteRowPointer(); } + Real** nric() const { CheckStore(); return row_pointer-1; } + void CleanUp(); // to clear store + void MiniCleanUp(); + void operator+=(const Matrix& M) { PlusEqual(M); } + void operator-=(const Matrix& M) { MinusEqual(M); } + void operator+=(Real f) { GeneralMatrix::Add(f); } + void operator-=(Real f) { GeneralMatrix::Add(-f); } + NEW_DELETE(nricMatrix) +}; + +class OSSIM_DLL SymmetricMatrix : public GeneralMatrix +{ + GeneralMatrix* Image() const; // copy of matrix +public: + SymmetricMatrix():GeneralMatrix() {} + ~SymmetricMatrix() {} + SymmetricMatrix(ArrayLengthSpecifier); + SymmetricMatrix(const BaseMatrix&); + void operator=(const BaseMatrix&); + void operator=(Real f) { GeneralMatrix::operator=(f); } + void operator=(const SymmetricMatrix& m) { Eq(m); } + Real& operator()(int, int); // access element + Real& element(int, int); // access element + Real operator()(int, int) const; // access element + Real element(int, int) const; // access element +#ifdef SETUP_C_SUBSCRIPTS + Real* operator[](int m) { return store+(m*(m+1))/2; } + const Real* operator[](int m) const { return store+(m*(m+1))/2; } +#endif + MatrixType Type() const; + SymmetricMatrix(const SymmetricMatrix& gm):GeneralMatrix(gm) { GetMatrix(&gm); } + Real SumSquare() const; + Real SumAbsoluteValue() const; + Real Sum() const; + Real Trace() const; + void GetRow(MatrixRowCol&); + void GetCol(MatrixRowCol&); + void GetCol(MatrixColX&); + void RestoreCol(MatrixRowCol&) {} + void RestoreCol(MatrixColX&); + GeneralMatrix* Transpose(TransposedMatrix*, MatrixType); + void ReSize(int); // change dimensions + void ReSize(const GeneralMatrix& A); + void operator+=(const SymmetricMatrix& M) { PlusEqual(M); } + void operator-=(const SymmetricMatrix& M) { MinusEqual(M); } + void operator+=(Real f) { GeneralMatrix::Add(f); } + void operator-=(Real f) { GeneralMatrix::Add(-f); } + NEW_DELETE(SymmetricMatrix) +}; + +class OSSIM_DLL UpperTriangularMatrix : public GeneralMatrix +{ + GeneralMatrix* Image() const; // copy of matrix +public: + UpperTriangularMatrix():GeneralMatrix() {} + ~UpperTriangularMatrix() {} + UpperTriangularMatrix(ArrayLengthSpecifier); + void operator=(const BaseMatrix&); + void operator=(const UpperTriangularMatrix& m) { Eq(m); } + UpperTriangularMatrix(const BaseMatrix&); + UpperTriangularMatrix(const UpperTriangularMatrix& gm):GeneralMatrix(gm) { GetMatrix(&gm); } + void operator=(Real f) { GeneralMatrix::operator=(f); } + Real& operator()(int, int); // access element + Real& element(int, int); // access element + Real operator()(int, int) const; // access element + Real element(int, int) const; // access element +#ifdef SETUP_C_SUBSCRIPTS + Real* operator[](int m) { return store+m*ncols-(m*(m+1))/2; } + const Real* operator[](int m) const { return store+m*ncols-(m*(m+1))/2; } +#endif + MatrixType Type() const; + GeneralMatrix* MakeSolver() { return this; } // for solving + void Solver(MatrixColX&, const MatrixColX&); + LogAndSign LogDeterminant() const; + Real Trace() const; + void GetRow(MatrixRowCol&); + void GetCol(MatrixRowCol&); + void GetCol(MatrixColX&); + void RestoreCol(MatrixRowCol&); + void RestoreCol(MatrixColX& c) { RestoreCol((MatrixRowCol&)c); } + void NextRow(MatrixRowCol&); + void ReSize(int); // change dimensions + void ReSize(const GeneralMatrix& A); + MatrixBandWidth BandWidth() const; + void operator+=(const UpperTriangularMatrix& M) { PlusEqual(M); } + void operator-=(const UpperTriangularMatrix& M) { MinusEqual(M); } + void operator+=(Real f) { GeneralMatrix::operator+=(f); } + void operator-=(Real f) { GeneralMatrix::operator-=(f); } + NEW_DELETE(UpperTriangularMatrix) +}; + +class OSSIM_DLL LowerTriangularMatrix : public GeneralMatrix +{ + GeneralMatrix* Image() const; // copy of matrix +public: + LowerTriangularMatrix():GeneralMatrix() {} + ~LowerTriangularMatrix() {} + LowerTriangularMatrix(ArrayLengthSpecifier); + LowerTriangularMatrix(const LowerTriangularMatrix& gm):GeneralMatrix(gm) { GetMatrix(&gm); } + LowerTriangularMatrix(const BaseMatrix& M); + void operator=(const BaseMatrix&); + void operator=(Real f) { GeneralMatrix::operator=(f); } + void operator=(const LowerTriangularMatrix& m) { Eq(m); } + Real& operator()(int, int); // access element + Real& element(int, int); // access element + Real operator()(int, int) const; // access element + Real element(int, int) const; // access element +#ifdef SETUP_C_SUBSCRIPTS + Real* operator[](int m) { return store+(m*(m+1))/2; } + const Real* operator[](int m) const { return store+(m*(m+1))/2; } +#endif + MatrixType Type() const; + GeneralMatrix* MakeSolver() { return this; } // for solving + void Solver(MatrixColX&, const MatrixColX&); + LogAndSign LogDeterminant() const; + Real Trace() const; + void GetRow(MatrixRowCol&); + void GetCol(MatrixRowCol&); + void GetCol(MatrixColX&); + void RestoreCol(MatrixRowCol&); + void RestoreCol(MatrixColX& c) { RestoreCol((MatrixRowCol&)c); } + void NextRow(MatrixRowCol&); + void ReSize(int); // change dimensions + void ReSize(const GeneralMatrix& A); + MatrixBandWidth BandWidth() const; + void operator+=(const LowerTriangularMatrix& M) { PlusEqual(M); } + void operator-=(const LowerTriangularMatrix& M) { MinusEqual(M); } + void operator+=(Real f) { GeneralMatrix::operator+=(f); } + void operator-=(Real f) { GeneralMatrix::operator-=(f); } + NEW_DELETE(LowerTriangularMatrix) +}; + +class OSSIM_DLL DiagonalMatrix : public GeneralMatrix +{ + GeneralMatrix* Image() const; // copy of matrix +public: + DiagonalMatrix():GeneralMatrix() {} + ~DiagonalMatrix() {} + DiagonalMatrix(ArrayLengthSpecifier); + DiagonalMatrix(const BaseMatrix&); + DiagonalMatrix(const DiagonalMatrix& gm):GeneralMatrix(gm) { GetMatrix(&gm); } + void operator=(const BaseMatrix&); + void operator=(Real f) { GeneralMatrix::operator=(f); } + void operator=(const DiagonalMatrix& m) { Eq(m); } + Real& operator()(int, int); // access element + Real& operator()(int); // access element + Real operator()(int, int) const; // access element + Real operator()(int) const; + Real& element(int, int); // access element + Real& element(int); // access element + Real element(int, int) const; // access element + Real element(int) const; // access element +#ifdef SETUP_C_SUBSCRIPTS + Real& operator[](int m) { return store[m]; } + const Real& operator[](int m) const { return store[m]; } +#endif + MatrixType Type() const; + + LogAndSign LogDeterminant() const; + Real Trace() const; + void GetRow(MatrixRowCol&); + void GetCol(MatrixRowCol&); + void GetCol(MatrixColX&); + void NextRow(MatrixRowCol&); + void NextCol(MatrixRowCol&); + void NextCol(MatrixColX&); + GeneralMatrix* MakeSolver() { return this; } // for solving + void Solver(MatrixColX&, const MatrixColX&); + GeneralMatrix* Transpose(TransposedMatrix*, MatrixType); + void ReSize(int); // change dimensions + void ReSize(const GeneralMatrix& A); + Real* nric() const + { CheckStore(); return store-1; } // for use by NRIC + MatrixBandWidth BandWidth() const; +// ReturnMatrix Reverse() const; // reverse order of elements + void operator+=(const DiagonalMatrix& M) { PlusEqual(M); } + void operator-=(const DiagonalMatrix& M) { MinusEqual(M); } + void operator+=(Real f) { GeneralMatrix::operator+=(f); } + void operator-=(Real f) { GeneralMatrix::operator-=(f); } + NEW_DELETE(DiagonalMatrix) +}; + +class OSSIM_DLL RowVector : public Matrix +{ + GeneralMatrix* Image() const; // copy of matrix +public: + RowVector():Matrix() { nrows = 1; } + ~RowVector() {} + RowVector(ArrayLengthSpecifier n) : Matrix(1,n.Value()) {} + RowVector(const BaseMatrix&); + RowVector(const RowVector& gm):Matrix(gm) { GetMatrix(&gm); } + void operator=(const BaseMatrix&); + void operator=(Real f) { GeneralMatrix::operator=(f); } + void operator=(const RowVector& m) { Eq(m); } + Real& operator()(int); // access element + Real& element(int); // access element + Real operator()(int) const; // access element + Real element(int) const; // access element +#ifdef SETUP_C_SUBSCRIPTS + Real& operator[](int m) { return store[m]; } + const Real& operator[](int m) const { return store[m]; } +#endif + MatrixType Type() const; + void GetCol(MatrixRowCol&); + void GetCol(MatrixColX&); + void NextCol(MatrixRowCol&); + void NextCol(MatrixColX&); + void RestoreCol(MatrixRowCol&) {} + void RestoreCol(MatrixColX& c); + GeneralMatrix* Transpose(TransposedMatrix*, MatrixType); + void ReSize(int); // change dimensions + void ReSize(int,int); // in case access is matrix + void ReSize(const GeneralMatrix& A); + Real* nric() const + { CheckStore(); return store-1; } // for use by NRIC + void CleanUp(); // to clear store + void MiniCleanUp() { store = 0; storage = 0; nrows = 1; ncols = 0; tag = -1; } + // friend ReturnMatrix GetMatrixRow(Matrix& A, int row); + void operator+=(const Matrix& M) { PlusEqual(M); } + void operator-=(const Matrix& M) { MinusEqual(M); } + void operator+=(Real f) { GeneralMatrix::Add(f); } + void operator-=(Real f) { GeneralMatrix::Add(-f); } + NEW_DELETE(RowVector) +}; + +class OSSIM_DLL ColumnVector : public Matrix +{ + GeneralMatrix* Image() const; // copy of matrix +public: + ColumnVector():Matrix() { ncols = 1; } + ~ColumnVector() {} + ColumnVector(ArrayLengthSpecifier n) : Matrix(n.Value(),1) {} + ColumnVector(const BaseMatrix&); + ColumnVector(const ColumnVector& gm):Matrix(gm) { GetMatrix(&gm); } + void operator=(const BaseMatrix&); + void operator=(Real f) { GeneralMatrix::operator=(f); } + void operator=(const ColumnVector& m) { Eq(m); } + Real& operator()(int); // access element + Real& element(int); // access element + Real operator()(int) const; // access element + Real element(int) const; // access element +#ifdef SETUP_C_SUBSCRIPTS + Real& operator[](int m) { return store[m]; } + const Real& operator[](int m) const { return store[m]; } +#endif + MatrixType Type() const; + GeneralMatrix* Transpose(TransposedMatrix*, MatrixType); + void ReSize(int); // change dimensions + void ReSize(int,int); // in case access is matrix + void ReSize(const GeneralMatrix& A); + Real* nric() const + { CheckStore(); return store-1; } // for use by NRIC + void CleanUp(); // to clear store + void MiniCleanUp() { store = 0; storage = 0; nrows = 0; ncols = 1; tag = -1; } +// ReturnMatrix Reverse() const; // reverse order of elements + void operator+=(const Matrix& M) { PlusEqual(M); } + void operator-=(const Matrix& M) { MinusEqual(M); } + void operator+=(Real f) { GeneralMatrix::Add(f); } + void operator-=(Real f) { GeneralMatrix::Add(-f); } + NEW_DELETE(ColumnVector) +}; + +class OSSIM_DLL CroutMatrix : public GeneralMatrix // for LU decomposition +{ + int* indx; + bool d; + bool sing; + void ludcmp(); + void operator=(const CroutMatrix& /* m */) {} // not allowed +public: + CroutMatrix(const BaseMatrix&); + MatrixType Type() const; + void lubksb(Real*, int=0); + ~CroutMatrix(); + GeneralMatrix* MakeSolver() { return this; } // for solving + LogAndSign LogDeterminant() const; + void Solver(MatrixColX&, const MatrixColX&); + void GetRow(MatrixRowCol&); + void GetCol(MatrixRowCol&); + void GetCol(MatrixColX& c) { GetCol((MatrixRowCol&)c); } + void CleanUp(); // to clear store + void MiniCleanUp(); + bool IsEqual(const GeneralMatrix&) const; + bool IsSingular() const { return sing; } + NEW_DELETE(CroutMatrix) +}; + +// ***************************** band matrices ***************************/ + +class OSSIM_DLL BandMatrix : public GeneralMatrix // band matrix +{ + GeneralMatrix* Image() const; // copy of matrix +protected: + void CornerClear() const; // set unused elements to zero + short SimpleAddOK(const GeneralMatrix* gm); +public: + int lower, upper; // band widths + BandMatrix():GeneralMatrix() { lower=0; upper=0; CornerClear(); } + ~BandMatrix() {} + BandMatrix(int n,int lb,int ub) { ReSize(n,lb,ub); CornerClear(); } + // standard declaration + BandMatrix(const BaseMatrix&); // evaluate BaseMatrix + void operator=(const BaseMatrix&); + void operator=(Real f) { GeneralMatrix::operator=(f); } + void operator=(const BandMatrix& m) { Eq(m); } + MatrixType Type() const; + Real& operator()(int, int); // access element + Real& element(int, int); // access element + Real operator()(int, int) const; // access element + Real element(int, int) const; // access element +#ifdef SETUP_C_SUBSCRIPTS + Real* operator[](int m) { return store+(upper+lower)*m+lower; } + const Real* operator[](int m) const { return store+(upper+lower)*m+lower; } +#endif + BandMatrix(const BandMatrix& gm):GeneralMatrix(gm) { GetMatrix(&gm); } + LogAndSign LogDeterminant() const; + GeneralMatrix* MakeSolver(); + Real Trace() const; + Real SumSquare() const { CornerClear(); return GeneralMatrix::SumSquare(); } + Real SumAbsoluteValue() const + { CornerClear(); return GeneralMatrix::SumAbsoluteValue(); } + Real Sum() const + { CornerClear(); return GeneralMatrix::Sum(); } + Real MaximumAbsoluteValue() const + { CornerClear(); return GeneralMatrix::MaximumAbsoluteValue(); } + Real MinimumAbsoluteValue() const + { int i, j; return GeneralMatrix::MinimumAbsoluteValue2(i, j); } + Real Maximum() const { int i, j; return GeneralMatrix::Maximum2(i, j); } + Real Minimum() const { int i, j; return GeneralMatrix::Minimum2(i, j); } + void GetRow(MatrixRowCol&); + void GetCol(MatrixRowCol&); + void GetCol(MatrixColX&); + void RestoreCol(MatrixRowCol&); + void RestoreCol(MatrixColX& c) { RestoreCol((MatrixRowCol&)c); } + void NextRow(MatrixRowCol&); + virtual void ReSize(int, int, int); // change dimensions + void ReSize(const GeneralMatrix& A); + bool SameStorageType(const GeneralMatrix& A) const; + void ReSizeForAdd(const GeneralMatrix& A, const GeneralMatrix& B); + void ReSizeForSP(const GeneralMatrix& A, const GeneralMatrix& B); + MatrixBandWidth BandWidth() const; + void SetParameters(const GeneralMatrix*); + MatrixInput operator<<(Real); // will give error + MatrixInput operator<<(int f); + void operator<<(const Real* r); // will give error + void operator<<(const int* r); // will give error + // the next is included because Zortech and Borland + // cannot find the copy in GeneralMatrix + void operator<<(const BaseMatrix& X) { GeneralMatrix::operator<<(X); } + NEW_DELETE(BandMatrix) +}; + +class OSSIM_DLL UpperBandMatrix : public BandMatrix // upper band matrix +{ + GeneralMatrix* Image() const; // copy of matrix +public: + UpperBandMatrix():BandMatrix() {} + ~UpperBandMatrix() {} + UpperBandMatrix(int n, int ubw) // standard declaration + : BandMatrix(n, 0, ubw) {} + UpperBandMatrix(const BaseMatrix&); // evaluate BaseMatrix + void operator=(const BaseMatrix&); + void operator=(Real f) { GeneralMatrix::operator=(f); } + void operator=(const UpperBandMatrix& m) { Eq(m); } + MatrixType Type() const; + UpperBandMatrix(const UpperBandMatrix& gm):BandMatrix(gm) { GetMatrix(&gm); } + GeneralMatrix* MakeSolver() { return this; } + void Solver(MatrixColX&, const MatrixColX&); + LogAndSign LogDeterminant() const; + void ReSize(int, int, int); // change dimensions + void ReSize(int n,int ubw) // change dimensions + { BandMatrix::ReSize(n,0,ubw); } + void ReSize(const GeneralMatrix& A) { BandMatrix::ReSize(A); } + Real& operator()(int, int); + Real operator()(int, int) const; + Real& element(int, int); + Real element(int, int) const; +#ifdef SETUP_C_SUBSCRIPTS + Real* operator[](int m) { return store+upper*m; } + const Real* operator[](int m) const { return store+upper*m; } +#endif + NEW_DELETE(UpperBandMatrix) +}; + +class OSSIM_DLL LowerBandMatrix : public BandMatrix // upper band matrix +{ + GeneralMatrix* Image() const; // copy of matrix +public: + LowerBandMatrix():BandMatrix() {} + ~LowerBandMatrix() {} + LowerBandMatrix(int n, int lbw) // standard declaration + : BandMatrix(n, lbw, 0) {} + LowerBandMatrix(const BaseMatrix&); // evaluate BaseMatrix + void operator=(const BaseMatrix&); + void operator=(Real f) { GeneralMatrix::operator=(f); } + void operator=(const LowerBandMatrix& m) { Eq(m); } + MatrixType Type() const; + LowerBandMatrix(const LowerBandMatrix& gm):BandMatrix(gm) { GetMatrix(&gm); } + GeneralMatrix* MakeSolver() { return this; } + void Solver(MatrixColX&, const MatrixColX&); + LogAndSign LogDeterminant() const; + void ReSize(int, int, int); // change dimensions + void ReSize(int n,int lbw) // change dimensions + { BandMatrix::ReSize(n,lbw,0); } + void ReSize(const GeneralMatrix& A) { BandMatrix::ReSize(A); } + Real& operator()(int, int); + Real operator()(int, int) const; + Real& element(int, int); + Real element(int, int) const; +#ifdef SETUP_C_SUBSCRIPTS + Real* operator[](int m) { return store+lower*(m+1); } + const Real* operator[](int m) const { return store+lower*(m+1); } +#endif + NEW_DELETE(LowerBandMatrix) +}; + +class OSSIM_DLL SymmetricBandMatrix : public GeneralMatrix +{ + GeneralMatrix* Image() const; // copy of matrix + void CornerClear() const; // set unused elements to zero + short SimpleAddOK(const GeneralMatrix* gm); +public: + int lower; // lower band width + SymmetricBandMatrix():GeneralMatrix() { lower=0; CornerClear(); } + ~SymmetricBandMatrix() {} + SymmetricBandMatrix(int n, int lb) { ReSize(n,lb); CornerClear(); } + SymmetricBandMatrix(const BaseMatrix&); + void operator=(const BaseMatrix&); + void operator=(Real f) { GeneralMatrix::operator=(f); } + void operator=(const SymmetricBandMatrix& m) { Eq(m); } + Real& operator()(int, int); // access element + Real& element(int, int); // access element + Real operator()(int, int) const; // access element + Real element(int, int) const; // access element +#ifdef SETUP_C_SUBSCRIPTS + Real* operator[](int m) { return store+lower*(m+1); } + const Real* operator[](int m) const { return store+lower*(m+1); } +#endif + MatrixType Type() const; + SymmetricBandMatrix(const SymmetricBandMatrix& gm):GeneralMatrix(gm) { GetMatrix(&gm); } + GeneralMatrix* MakeSolver(); + Real SumSquare() const; + Real SumAbsoluteValue() const; + Real Sum() const; + Real MaximumAbsoluteValue() const + { CornerClear(); return GeneralMatrix::MaximumAbsoluteValue(); } + Real MinimumAbsoluteValue() const + { int i, j; return GeneralMatrix::MinimumAbsoluteValue2(i, j); } + Real Maximum() const { int i, j; return GeneralMatrix::Maximum2(i, j); } + Real Minimum() const { int i, j; return GeneralMatrix::Minimum2(i, j); } + Real Trace() const; + LogAndSign LogDeterminant() const; + void GetRow(MatrixRowCol&); + void GetCol(MatrixRowCol&); + void GetCol(MatrixColX&); + void RestoreCol(MatrixRowCol&) {} + void RestoreCol(MatrixColX&); + GeneralMatrix* Transpose(TransposedMatrix*, MatrixType); + void ReSize(int,int); // change dimensions + void ReSize(const GeneralMatrix& A); + bool SameStorageType(const GeneralMatrix& A) const; + void ReSizeForAdd(const GeneralMatrix& A, const GeneralMatrix& B); + void ReSizeForSP(const GeneralMatrix& A, const GeneralMatrix& B); + MatrixBandWidth BandWidth() const; + void SetParameters(const GeneralMatrix*); + void operator<<(const Real* r); // will give error + void operator<<(const int* r); // will give error + void operator<<(const BaseMatrix& X) { GeneralMatrix::operator<<(X); } + NEW_DELETE(SymmetricBandMatrix) +}; + +class OSSIM_DLL BandLUMatrix : public GeneralMatrix +// for LU decomposition of band matrix +{ + int* indx; + bool d; + bool sing; // true if singular + Real* store2; + int storage2; + void ludcmp(); + int m1,m2; // lower and upper + void operator=(const BandLUMatrix& /* m */) {} // no allowed +public: + BandLUMatrix(const BaseMatrix&); + MatrixType Type() const; + void lubksb(Real*, int=0); + ~BandLUMatrix(); + GeneralMatrix* MakeSolver() { return this; } // for solving + LogAndSign LogDeterminant() const; + void Solver(MatrixColX&, const MatrixColX&); + void GetRow(MatrixRowCol&); + void GetCol(MatrixRowCol&); + void GetCol(MatrixColX& c) { GetCol((MatrixRowCol&)c); } + void CleanUp(); // to clear store + void MiniCleanUp(); + bool IsEqual(const GeneralMatrix&) const; + bool IsSingular() const { return sing; } + NEW_DELETE(BandLUMatrix) +}; + +// ************************** special matrices **************************** + +class OSSIM_DLL IdentityMatrix : public GeneralMatrix +{ + GeneralMatrix* Image() const; // copy of matrix +public: + IdentityMatrix():GeneralMatrix() {} + ~IdentityMatrix() {} + IdentityMatrix(ArrayLengthSpecifier n) : GeneralMatrix(1) + { nrows = ncols = n.Value(); *store = 1; } + IdentityMatrix(const IdentityMatrix& gm):GeneralMatrix(gm) { GetMatrix(&gm); } + IdentityMatrix(const BaseMatrix&); + void operator=(const BaseMatrix&); + void operator=(const IdentityMatrix& m) { Eq(m); } + void operator=(Real f) { GeneralMatrix::operator=(f); } + MatrixType Type() const; + + LogAndSign LogDeterminant() const; + Real Trace() const; + Real SumSquare() const; + Real SumAbsoluteValue() const; + Real Sum() const { return Trace(); } + void GetRow(MatrixRowCol&); + void GetCol(MatrixRowCol&); + void GetCol(MatrixColX&); + void NextRow(MatrixRowCol&); + void NextCol(MatrixRowCol&); + void NextCol(MatrixColX&); + GeneralMatrix* MakeSolver() { return this; } // for solving + void Solver(MatrixColX&, const MatrixColX&); + GeneralMatrix* Transpose(TransposedMatrix*, MatrixType); + void ReSize(int n); + void ReSize(const GeneralMatrix& A); + MatrixBandWidth BandWidth() const; +// ReturnMatrix Reverse() const; // reverse order of elements + NEW_DELETE(IdentityMatrix) +}; + + + + +// ************************** GenericMatrix class ************************/ + +class OSSIM_DLL GenericMatrix : public BaseMatrix +{ + GeneralMatrix* gm; + int search(const BaseMatrix* bm) const; + friend class BaseMatrix; +public: + GenericMatrix() : gm(0) {} + GenericMatrix(const BaseMatrix& bm) + { gm = ((BaseMatrix&)bm).Evaluate(); gm = gm->Image(); } + GenericMatrix(const GenericMatrix& bm) : BaseMatrix(bm) + { gm = bm.gm->Image(); } + void operator=(const GenericMatrix&); + void operator=(const BaseMatrix&); + void operator+=(const BaseMatrix&); + void operator-=(const BaseMatrix&); + void operator*=(const BaseMatrix&); + void operator|=(const BaseMatrix&); + void operator&=(const BaseMatrix&); + void operator+=(Real); + void operator-=(Real r) { operator+=(-r); } + void operator*=(Real); + void operator/=(Real r) { operator*=(1.0/r); } + ~GenericMatrix() { delete gm; } + void CleanUp() { delete gm; gm = 0; } + void Release() { gm->Release(); } + GeneralMatrix* Evaluate(MatrixType = MatrixTypeUnSp); + MatrixBandWidth BandWidth() const; + NEW_DELETE(GenericMatrix) +}; + +// *************************** temporary classes *************************/ + +class OSSIM_DLL MultipliedMatrix : public BaseMatrix +{ +protected: + // if these union statements cause problems, simply remove them + // and declare the items individually + union { const BaseMatrix* bm1; GeneralMatrix* gm1; }; + // pointers to summands + union { const BaseMatrix* bm2; GeneralMatrix* gm2; }; + MultipliedMatrix(const BaseMatrix* bm1x, const BaseMatrix* bm2x) + : bm1(bm1x),bm2(bm2x) {} + int search(const BaseMatrix*) const; + friend class BaseMatrix; + friend class GeneralMatrix; + friend class GenericMatrix; +public: + ~MultipliedMatrix() {} + GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp); + MatrixBandWidth BandWidth() const; + NEW_DELETE(MultipliedMatrix) +}; + +class OSSIM_DLL AddedMatrix : public MultipliedMatrix +{ +protected: + AddedMatrix(const BaseMatrix* bm1x, const BaseMatrix* bm2x) + : MultipliedMatrix(bm1x,bm2x) {} + + friend class BaseMatrix; + friend class GeneralMatrix; + friend class GenericMatrix; +public: + ~AddedMatrix() {} + GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp); + MatrixBandWidth BandWidth() const; + NEW_DELETE(AddedMatrix) +}; + +class OSSIM_DLL SPMatrix : public AddedMatrix +{ +protected: + SPMatrix(const BaseMatrix* bm1x, const BaseMatrix* bm2x) + : AddedMatrix(bm1x,bm2x) {} + + friend class BaseMatrix; + friend class GeneralMatrix; + friend class GenericMatrix; +public: + ~SPMatrix() {} + GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp); + MatrixBandWidth BandWidth() const; + + friend SPMatrix SP(const BaseMatrix&, const BaseMatrix&); + + NEW_DELETE(SPMatrix) +}; + +class OSSIM_DLL KPMatrix : public MultipliedMatrix +{ +protected: + KPMatrix(const BaseMatrix* bm1x, const BaseMatrix* bm2x) + : MultipliedMatrix(bm1x,bm2x) {} + + friend class BaseMatrix; + friend class GeneralMatrix; + friend class GenericMatrix; +public: + ~KPMatrix() {} + MatrixBandWidth BandWidth() const; + GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp); + friend KPMatrix KP(const BaseMatrix&, const BaseMatrix&); + NEW_DELETE(KPMatrix) +}; + +class OSSIM_DLL ConcatenatedMatrix : public MultipliedMatrix +{ +protected: + ConcatenatedMatrix(const BaseMatrix* bm1x, const BaseMatrix* bm2x) + : MultipliedMatrix(bm1x,bm2x) {} + + friend class BaseMatrix; + friend class GeneralMatrix; + friend class GenericMatrix; +public: + ~ConcatenatedMatrix() {} + MatrixBandWidth BandWidth() const; + GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp); + NEW_DELETE(ConcatenatedMatrix) +}; + +class OSSIM_DLL StackedMatrix : public ConcatenatedMatrix +{ +protected: + StackedMatrix(const BaseMatrix* bm1x, const BaseMatrix* bm2x) + : ConcatenatedMatrix(bm1x,bm2x) {} + + friend class BaseMatrix; + friend class GeneralMatrix; + friend class GenericMatrix; +public: + ~StackedMatrix() {} + GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp); + NEW_DELETE(StackedMatrix) +}; + +class OSSIM_DLL SolvedMatrix : public MultipliedMatrix +{ + SolvedMatrix(const BaseMatrix* bm1x, const BaseMatrix* bm2x) + : MultipliedMatrix(bm1x,bm2x) {} + friend class BaseMatrix; + friend class InvertedMatrix; // for operator* +public: + ~SolvedMatrix() {} + GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp); + MatrixBandWidth BandWidth() const; + NEW_DELETE(SolvedMatrix) +}; + +class OSSIM_DLL SubtractedMatrix : public AddedMatrix +{ + SubtractedMatrix(const BaseMatrix* bm1x, const BaseMatrix* bm2x) + : AddedMatrix(bm1x,bm2x) {} + friend class BaseMatrix; + friend class GeneralMatrix; + friend class GenericMatrix; +public: + ~SubtractedMatrix() {} + GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp); + NEW_DELETE(SubtractedMatrix) +}; + +class OSSIM_DLL ShiftedMatrix : public BaseMatrix +{ +protected: + union { const BaseMatrix* bm; GeneralMatrix* gm; }; + Real f; + ShiftedMatrix(const BaseMatrix* bmx, Real fx) : bm(bmx),f(fx) {} + int search(const BaseMatrix*) const; + friend class BaseMatrix; + friend class GeneralMatrix; + friend class GenericMatrix; +public: + ~ShiftedMatrix() {} + GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp); + friend ShiftedMatrix operator+(Real f, const BaseMatrix& BM); + NEW_DELETE(ShiftedMatrix) +}; + +class OSSIM_DLL NegShiftedMatrix : public ShiftedMatrix +{ +protected: + NegShiftedMatrix(Real fx, const BaseMatrix* bmx) : ShiftedMatrix(bmx,fx) {} + friend class BaseMatrix; + friend class GeneralMatrix; + friend class GenericMatrix; +public: + ~NegShiftedMatrix() {} + GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp); + friend NegShiftedMatrix operator-(Real, const BaseMatrix&); + NEW_DELETE(NegShiftedMatrix) +}; + +class OSSIM_DLL ScaledMatrix : public ShiftedMatrix +{ + ScaledMatrix(const BaseMatrix* bmx, Real fx) : ShiftedMatrix(bmx,fx) {} + friend class BaseMatrix; + friend class GeneralMatrix; + friend class GenericMatrix; +public: + ~ScaledMatrix() {} + GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp); + MatrixBandWidth BandWidth() const; + friend ScaledMatrix operator*(Real f, const BaseMatrix& BM); + NEW_DELETE(ScaledMatrix) +}; + +class OSSIM_DLL NegatedMatrix : public BaseMatrix +{ +protected: + union { const BaseMatrix* bm; GeneralMatrix* gm; }; + NegatedMatrix(const BaseMatrix* bmx) : bm(bmx) {} + int search(const BaseMatrix*) const; +private: + friend class BaseMatrix; +public: + ~NegatedMatrix() {} + GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp); + MatrixBandWidth BandWidth() const; + NEW_DELETE(NegatedMatrix) +}; + +class OSSIM_DLL TransposedMatrix : public NegatedMatrix +{ + TransposedMatrix(const BaseMatrix* bmx) : NegatedMatrix(bmx) {} + friend class BaseMatrix; +public: + ~TransposedMatrix() {} + GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp); + MatrixBandWidth BandWidth() const; + NEW_DELETE(TransposedMatrix) +}; + +class OSSIM_DLL ReversedMatrix : public NegatedMatrix +{ + ReversedMatrix(const BaseMatrix* bmx) : NegatedMatrix(bmx) {} + friend class BaseMatrix; +public: + ~ReversedMatrix() {} + GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp); + NEW_DELETE(ReversedMatrix) +}; + +class OSSIM_DLL InvertedMatrix : public NegatedMatrix +{ + InvertedMatrix(const BaseMatrix* bmx) : NegatedMatrix(bmx) {} +public: + ~InvertedMatrix() {} + SolvedMatrix operator*(const BaseMatrix&) const; // inverse(A) * B + ScaledMatrix operator*(Real t) const { return BaseMatrix::operator*(t); } + friend class BaseMatrix; + GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp); + MatrixBandWidth BandWidth() const; + NEW_DELETE(InvertedMatrix) +}; + +class OSSIM_DLL RowedMatrix : public NegatedMatrix +{ + RowedMatrix(const BaseMatrix* bmx) : NegatedMatrix(bmx) {} + friend class BaseMatrix; +public: + ~RowedMatrix() {} + GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp); + MatrixBandWidth BandWidth() const; + NEW_DELETE(RowedMatrix) +}; + +class OSSIM_DLL ColedMatrix : public NegatedMatrix +{ + ColedMatrix(const BaseMatrix* bmx) : NegatedMatrix(bmx) {} + friend class BaseMatrix; +public: + ~ColedMatrix() {} + GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp); + MatrixBandWidth BandWidth() const; + NEW_DELETE(ColedMatrix) +}; + +class OSSIM_DLL DiagedMatrix : public NegatedMatrix +{ + DiagedMatrix(const BaseMatrix* bmx) : NegatedMatrix(bmx) {} + friend class BaseMatrix; +public: + ~DiagedMatrix() {} + GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp); + MatrixBandWidth BandWidth() const; + NEW_DELETE(DiagedMatrix) +}; + +class OSSIM_DLL MatedMatrix : public NegatedMatrix +{ + int nr, nc; + MatedMatrix(const BaseMatrix* bmx, int nrx, int ncx) + : NegatedMatrix(bmx), nr(nrx), nc(ncx) {} + friend class BaseMatrix; +public: + ~MatedMatrix() {} + GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp); + MatrixBandWidth BandWidth() const; + NEW_DELETE(MatedMatrix) +}; + +class OSSIM_DLL ReturnMatrix : public BaseMatrix // for matrix return +{ + GeneralMatrix* gm; + int search(const BaseMatrix*) const; +public: + ~ReturnMatrix() {} + GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp); + friend class BaseMatrix; + ReturnMatrix(const ReturnMatrix& tm) :BaseMatrix(tm), gm(tm.gm) {} + ReturnMatrix(const GeneralMatrix* gmx) : gm((GeneralMatrix*&)gmx) {} +// ReturnMatrix(GeneralMatrix&); + MatrixBandWidth BandWidth() const; + NEW_DELETE(ReturnMatrix) +}; + + +// ************************** submatrices ******************************/ + +class OSSIM_DLL GetSubMatrix : public NegatedMatrix +{ + int row_skip; + int row_number; + int col_skip; + int col_number; + bool IsSym; + + GetSubMatrix + (const BaseMatrix* bmx, int rs, int rn, int cs, int cn, bool is) + : NegatedMatrix(bmx), + row_skip(rs), row_number(rn), col_skip(cs), col_number(cn), IsSym(is) {} + void SetUpLHS(); + friend class BaseMatrix; + +public: + + GetSubMatrix(const GetSubMatrix& g) + : NegatedMatrix(g.bm), row_skip(g.row_skip), row_number(g.row_number), + col_skip(g.col_skip), col_number(g.col_number), IsSym(g.IsSym) {} + + ~GetSubMatrix() {} + GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp); + void operator=(const BaseMatrix&); + void operator+=(const BaseMatrix&); + void operator-=(const BaseMatrix&); + void operator=(const GetSubMatrix& m) { operator=((const BaseMatrix&)m); } + void operator<<(const BaseMatrix&); + void operator<<(const Real*); // copy from array + void operator<<(const int*); // copy from array + MatrixInput operator<<(Real); // for loading a list + MatrixInput operator<<(int f); + void operator=(Real); // copy from constant + void operator+=(Real); // add constant + void operator-=(Real r) { operator+=(-r); } // subtract constant + void operator*=(Real); // multiply by constant + void operator/=(Real r) { operator*=(1.0/r); } // divide by constant + void Inject(const GeneralMatrix&); // copy stored els only + MatrixBandWidth BandWidth() const; + NEW_DELETE(GetSubMatrix) +}; + +// ******************** linear equation solving ****************************/ + +class OSSIM_DLL LinearEquationSolver : public BaseMatrix +{ + GeneralMatrix* gm; + int search(const BaseMatrix*) const { return 0; } + friend class BaseMatrix; +public: + LinearEquationSolver(const BaseMatrix& bm); + ~LinearEquationSolver() { delete gm; } + void CleanUp() { delete gm; } + GeneralMatrix* Evaluate(MatrixType) { return gm; } + // probably should have an error message if MatrixType != UnSp + NEW_DELETE(LinearEquationSolver) +}; + +// ************************** matrix input *******************************/ + +class MatrixInput // for reading a list of values into a matrix + // the difficult part is detecting a mismatch + // in the number of elements +{ + int n; // number values still to be read + Real* r; // pointer to next location to be read to +public: + MatrixInput(const MatrixInput& mi) : n(mi.n), r(mi.r) {} + MatrixInput(int nx, Real* rx) : n(nx), r(rx) {} + ~MatrixInput(); + MatrixInput operator<<(Real); + MatrixInput operator<<(int f); + friend class GeneralMatrix; +}; + + + +// **************** a very simple integer array class ********************/ + +// A minimal array class to imitate a C style array but giving dynamic storage +// mostly intended for internal use by newmat + +class OSSIM_DLL SimpleIntArray : public Janitor +{ +protected: + int* a; // pointer to the array + int n; // length of the array +public: + SimpleIntArray(int xn); // build an array length xn + ~SimpleIntArray(); // return the space to memory + int& operator[](int i); // access element of the array - start at 0 + int operator[](int i) const; + // access element of constant array + void operator=(int ai); // set the array equal to a constant + void operator=(const SimpleIntArray& b); + // copy the elements of an array + SimpleIntArray(const SimpleIntArray& b); + // make a new array equal to an existing one + int Size() const { return n; } + // return the size of the array + int* Data() { return a; } // pointer to the data + const int* Data() const { return a; } + // pointer to the data + void ReSize(int i, bool keep = false); + // change length, keep data if keep = true + void CleanUp() { ReSize(0); } + NEW_DELETE(SimpleIntArray) +}; + +// *************************** exceptions ********************************/ + +class OSSIM_DLL NPDException : public Runtime_error // Not positive definite +{ +public: + static unsigned long Select; // for identifying exception + NPDException(const GeneralMatrix&); +}; + +class OSSIM_DLL ConvergenceException : public Runtime_error +{ +public: + static unsigned long Select; // for identifying exception + ConvergenceException(const GeneralMatrix& A); + ConvergenceException(const char* c); +}; + +class OSSIM_DLL SingularException : public Runtime_error +{ +public: + static unsigned long Select; // for identifying exception + SingularException(const GeneralMatrix& A); +}; + +class OSSIM_DLL OverflowException : public Runtime_error +{ +public: + static unsigned long Select; // for identifying exception + OverflowException(const char* c); +}; + +class OSSIM_DLL ProgramException : public Logic_error +{ +protected: + ProgramException(); +public: + static unsigned long Select; // for identifying exception + ProgramException(const char* c); + ProgramException(const char* c, const GeneralMatrix&); + ProgramException(const char* c, const GeneralMatrix&, const GeneralMatrix&); + ProgramException(const char* c, MatrixType, MatrixType); +}; + +class OSSIM_DLL IndexException : public Logic_error +{ +public: + static unsigned long Select; // for identifying exception + IndexException(int i, const GeneralMatrix& A); + IndexException(int i, int j, const GeneralMatrix& A); + // next two are for access via element function + IndexException(int i, const GeneralMatrix& A, bool); + IndexException(int i, int j, const GeneralMatrix& A, bool); +}; + +class OSSIM_DLL VectorException : public Logic_error // cannot convert to vector +{ +public: + static unsigned long Select; // for identifying exception + VectorException(); + VectorException(const GeneralMatrix& A); +}; + +class OSSIM_DLL NotSquareException : public Logic_error +{ +public: + static unsigned long Select; // for identifying exception + NotSquareException(const GeneralMatrix& A); + NotSquareException(); +}; + +class OSSIM_DLL SubMatrixDimensionException : public Logic_error +{ +public: + static unsigned long Select; // for identifying exception + SubMatrixDimensionException(); +}; + +class OSSIM_DLL IncompatibleDimensionsException : public Logic_error +{ +public: + static unsigned long Select; // for identifying exception + IncompatibleDimensionsException(); + IncompatibleDimensionsException(const GeneralMatrix&, const GeneralMatrix&); +}; + +class OSSIM_DLL NotDefinedException : public Logic_error +{ +public: + static unsigned long Select; // for identifying exception + NotDefinedException(const char* op, const char* matrix); +}; + +class OSSIM_DLL CannotBuildException : public Logic_error +{ +public: + static unsigned long Select; // for identifying exception + CannotBuildException(const char* matrix); +}; + + +class OSSIM_DLL InternalException : public Logic_error +{ +public: + static unsigned long Select; // for identifying exception + InternalException(const char* c); +}; + +// ************************ functions ************************************ // + +bool operator==(const GeneralMatrix& A, const GeneralMatrix& B); +bool operator==(const BaseMatrix& A, const BaseMatrix& B); +inline bool operator!=(const GeneralMatrix& A, const GeneralMatrix& B) + { return ! (A==B); } +inline bool operator!=(const BaseMatrix& A, const BaseMatrix& B) + { return ! (A==B); } + + // inequality operators are dummies included for compatibility + // with STL. They throw an exception if actually called. +inline bool operator<=(const BaseMatrix& A, const BaseMatrix&) + { A.IEQND(); return true; } +inline bool operator>=(const BaseMatrix& A, const BaseMatrix&) + { A.IEQND(); return true; } +inline bool operator<(const BaseMatrix& A, const BaseMatrix&) + { A.IEQND(); return true; } +inline bool operator>(const BaseMatrix& A, const BaseMatrix&) + { A.IEQND(); return true; } + +bool IsZero(const BaseMatrix& A); + +Matrix CrossProduct(const Matrix& A, const Matrix& B); +ReturnMatrix CrossProductRows(const Matrix& A, const Matrix& B); +ReturnMatrix CrossProductColumns(const Matrix& A, const Matrix& B); + + +// ********************* inline functions ******************************** // + + +inline LogAndSign LogDeterminant(const BaseMatrix& B) + { return B.LogDeterminant(); } +inline Real Determinant(const BaseMatrix& B) + { return B.Determinant(); } +inline Real SumSquare(const BaseMatrix& B) { return B.SumSquare(); } +inline Real NormFrobenius(const BaseMatrix& B) { return B.NormFrobenius(); } +inline Real Trace(const BaseMatrix& B) { return B.Trace(); } +inline Real SumAbsoluteValue(const BaseMatrix& B) + { return B.SumAbsoluteValue(); } +inline Real Sum(const BaseMatrix& B) + { return B.Sum(); } +inline Real MaximumAbsoluteValue(const BaseMatrix& B) + { return B.MaximumAbsoluteValue(); } +inline Real MinimumAbsoluteValue(const BaseMatrix& B) + { return B.MinimumAbsoluteValue(); } +inline Real Maximum(const BaseMatrix& B) { return B.Maximum(); } +inline Real Minimum(const BaseMatrix& B) { return B.Minimum(); } +inline Real Norm1(const BaseMatrix& B) { return B.Norm1(); } +inline Real Norm1(RowVector& RV) { return RV.MaximumAbsoluteValue(); } +inline Real NormInfinity(const BaseMatrix& B) { return B.NormInfinity(); } +inline Real NormInfinity(ColumnVector& CV) + { return CV.MaximumAbsoluteValue(); } +inline bool IsZero(const GeneralMatrix& A) { return A.IsZero(); } + + +inline MatrixInput MatrixInput::operator<<(int f) { return *this << (Real)f; } +inline MatrixInput GeneralMatrix::operator<<(int f) { return *this << (Real)f; } +inline MatrixInput BandMatrix::operator<<(int f) { return *this << (Real)f; } +inline MatrixInput GetSubMatrix::operator<<(int f) { return *this << (Real)f; } + + + +#ifdef use_namespace +} +#endif + + +#endif + +// body file: newmat1.cpp +// body file: newmat2.cpp +// body file: newmat3.cpp +// body file: newmat4.cpp +// body file: newmat5.cpp +// body file: newmat6.cpp +// body file: newmat7.cpp +// body file: newmat8.cpp +// body file: newmatex.cpp +// body file: bandmat.cpp +// body file: submat.cpp + + + + + + + diff --git a/Utilities/OSSIM/ossim_core/matrix/newmat.txt b/Utilities/OSSIM/ossim_core/matrix/newmat.txt new file mode 100644 index 0000000000..2cba65433a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/newmat.txt @@ -0,0 +1,3235 @@ + + + DOCUMENTATION FOR NEWMAT10, A MATRIX LIBRARY IN C++ + +Copyright (C) 1991,2,3,4,5,6,7,8,9: R B Davies + +Beta version of 26 December, 1999 + + Introduction 1 + Getting started 2 + Reference manual 3 + Error messages 4 + Bugs 5 + Files in newmat10 6 + Problem report form 7 + Design of the library 8 + +This is the "how to use" documentation for newmat plus the background +information on its design. + +This document is available as an ascii file, newmat.txt, and in hypertext +format for reading with an HTML browser such as Netscape or Internet Explorer. +Cross-references in the ascii version are given as section numbers. The HTML +version can be downloaded from the same site [1.5] as the source files. There +is also a version in RTF format. + +There is additional support material on my web site [1.5]. + +Be sure to read the section on customising [2.3] before attempting to compile +newmat. + + + 1 Introduction + = ============ + + Conditions of use 1.1 + Description 1.2 + Is this the library for you? 1.3 + Other matrix libraries 1.4 + Where to find this library 1.5 + How to contact the author 1.6 + Change history 1.7 + References 1.8 + + + 1.1 Conditions of use + === ========== == === + +Copyright (C) 1991,2,3,4,5,6,7: R B Davies. + +Permission is granted to use and distribute but not to sell except for costs +of distribution. Distribution as part of low cost CD-ROM collections is +welcomed. + +You can use it in your commercial projects. However if you distribute the +source, please make it clear which parts are mine and that they are available +essentially for free over the internet. + + ----------------------------------------------------------------------------- +Please understand that there may still be bugs and errors. Use at your own +risk. I take no responsibility for any errors or omissions in this package or +for any misfortune that may befall you or others as a result of its use. + ----------------------------------------------------------------------------- + +Please report bugs to me at + + robertd@netlink.co.nz + + +When reporting a bug please tell me which C++ compiler you are using (if +known), and what version. Also give me details of your computer (if known). +And tell me which version of Newmat (eg newmat03 or newmat04) you are using. +Note any changes you have made to my code. If at all possible give me a piece +of code illustrating the bug. See the problem report form [7]. + +"Please do report bugs to me." + + + + 1.2 General description + === ======= =========== + +The package is intended for scientists and engineers who need to manipulate a +variety of types of matrices using standard matrix operations. Emphasis is on +the kind of operations needed in statistical calculations such as least +squares, linear equation solve and eigenvalues. + +It supports matrix types + + Matrix (rectangular matrix) + nricMatrix (variant of rectangular matrix) + UpperTriangularMatrix + LowerTriangularMatrix + DiagonalMatrix + SymmetricMatrix + BandMatrix + UpperBandMatrix (upper triangular band matrix) + LowerBandMatrix (lower triangular band matrix) + SymmetricBandMatrix + RowVector (derived from Matrix) + ColumnVector (derived from Matrix). + +Only one element type (float or double) is supported. + +The package includes the operations '*', '+', '-', concatenation, inverse, +transpose, conversion between types, submatrix, determinant, Cholesky +decomposition, QR triangularisation, singular value decomposition, eigenvalues +of a symmetric matrix, sorting, fast Fourier transform, printing and an +interface with "Numerical Recipes in C". + +It is intended for matrices in the range 15 x 15 to the maximum size your +machine will accommodate in a single array. On a PC using the large model, +this is 90 x 90 (125 x 125 for triangular matrices). For Unix machines or PCs +running under a 32 bit flat model the limit is set by the size of available +memory. The number of elements in an array cannot exceed the maximum size of +an "int". The package will work for very small matrices but becomes rather +inefficient. Some of the factorisation functions are not (yet) optimised for +paged memory and so become inefficient when used with very large matrices. + +A "lazy evaluation" approach to evaluating matrix expressions is used to +improve efficiency and reduce the use of temporary storage. + +I have tested the package on variety of compilers and platforms including +AT&T, Borland, Gnu, HP, Microsoft, Sun and Watcom. For more details see the +section on compiler performance [2.4]. + + + + + 1.3 Is this the library for you? + === == ==== === ======= === ==== + +Do you + +1: understand '*' to mean matrix multiply and not element by element multiply + +2: need matrix operators such as '*' and '+' defined as operators so you can +write things like + + X = A * (B + C); + +3: need a variety of types of matrices (but not sparse); + +4: need only one element type (float or double); + +5: work with matrices in the range 10 x 10 up to what can be stored in +memory; + +6: tolerate a large package. + + +Then maybe this is the right package for you. + + + + 1.4 Other matrix libraries + === ===== ====== ========= + +For details of other C++ matrix libraries look at +http://webnz.com/robert/cpp_site.html or +http://webnz.co.nz/robert/cpp_site.html or download the text file +ftp://webnz.com/robert/cpp_site.txt or ftp://webnz.co.nz/robert/cpp_site.txt . +Look at the section "lists of libraries" which gives the locations of several +very comprehensive lists of matrix and other C++ libraries and at the section +"source code". + + + + + 1.5 Where to find this library + === ===== == ==== ==== ======= + + +* http://webnz.com/robert/ + +* http://webnz.co.nz/robert/ + +* ftp://webnz.com/robert/newmat10.zip + +* ftp://webnz.com/robert/newmat10.tar.gz + +* ftp://webnz.co.nz/robert/newmat10.zip + +* ftp://webnz.co.nz/robert/newmat10.tar.gz + + +For the HTML version of the documentation download either nm10html.zip or +nm10html.tar.gz from the same sites. + + + + + 1.6 How to contact the author + === === == ======= === ====== + + + Robert Davies + 16 Gloucester Street + Wilton + Wellington + New Zealand + + "email:" robertd@netlink.co.nz + +(don't forget the "d" in "robertd"). + + + + 1.7 Change history + === ====== ======= + +Newmat10 - August, 1999: + +Improve compatibility with GCC, fix errors in FFT and GenericMatrix, update +simulated exceptions, maxima and minima functions, Determinant function, +update make files for CC and GCC, faster FFT, 'A.ReSize(B)'. + +Newmat09 - September, 1997: + +Operator '==', '!=', '+=', '-=', '*=', '/=', '|=', '&='. Follow new rules for +"for (int i; ... )" construct. Change Boolean, TRUE, FALSE to bool, true, +false. Change ReDimension to ReSize. SubMatrix allows zero rows and columns. +Scalar '+', '-' or '*' matrix is OK. Simplify simulated exceptions. Fix +non-linear programs for AT&T compilers. Dummy inequality operators. Improve +internal row/column operations. Improve matrix LU decomposition. Improve sort. +Reverse function. IsSingular function. Fast trig transforms. Namespace +definitions. + +Newmat08A - July, 1995: + +Fix error in SVD. + +Newmat08 - January, 1995: + +Corrections to improve compatibility with Gnu, Watcom. Concatenation of +matrices. Elementwise products. Option to use compilers supporting exceptions. +Correction to exception module to allow global declarations of matrices. Fix +problem with inverse of symmetric matrices. Fix divide-by-zero problem in SVD. +Include new QR routines. Sum function. Non-linear optimisation. +GenericMatrices. + +Newmat07 - January, 1993 + +Minor corrections to improve compatibility with Zortech, Microsoft and Gnu. +Correction to exception module. Additional FFT functions. Some minor increases +in efficiency. Submatrices can now be used on RHS of =. Option for allowing C +type subscripts. Method for loading short lists of numbers. + + +Newmat06 - December 1992: + +Added band matrices; 'real' changed to 'Real' (to avoid potential conflict in +complex class); Inject doesn't check for no loss of information; fixes for +AT&T C++ version 3.0; real(A) becomes A.AsScalar(); CopyToMatrix becomes +AsMatrix, etc; .c() is no longer required (to be deleted in next version); +option for version 2.1 or later. Suffix for include files changed to .h; BOOL +changed to Boolean (BOOL doesn't work in g++ v 2.0); modifications to allow +for compilers that destroy temporaries very quickly; (Gnu users - see the +section of compiler performance). Added CleanUp, LinearEquationSolver, +primitive version of exceptions. + + +Newmat05 - June 1992: + +For private release only + + +Newmat04 - December 1991: + +Fix problem with G++1.40, some extra documentation + + +Newmat03 - November 1991: + +Col and Cols become Column and Columns. Added Sort, SVD, Jacobi, Eigenvalues, +FFT, real conversion of 1x1 matrix, "Numerical Recipes in C" interface, output +operations, various scalar functions. Improved return from functions. +Reorganised setting options in "include.hxx". + + +Newmat02 - July 1991: + +Version with matrix row/column operations and numerous additional functions. + + +Matrix - October 1990: + +Early version of package. + + + + + 1.8 References + === ========== + +The matrix LU decomposition is from Golub, G.H. & Van Loan, C.F. (1996), +"Matrix Computations", published by John Hopkins University Press. + +Part of the matrix inverse/solve routine is adapted from Press, Flannery, +Teukolsky, Vetterling (1988), "Numerical Recipes in C", published by the +Cambridge University Press. + +Many of the advanced matrix routines are adapted from routines in Wilkinson +and Reinsch (1971), "Handbook for Automatic Computation, Vol II, Linear +Algebra" published by Springer Verlag. + +The fast Fourier transform is adapted from Carl de Boor (1980), "Siam J Sci +Stat Comput", pp173-8 and the fast trigonometric transforms from Charles Van +Loan (1992) in "Computational frameworks for the fast Fourier transform" +published by SIAM. + +The sort function is derived from Sedgewick, Robert (1992), "Algorithms in +C++" published by Addison Wesley. + +For references about "Newmat" see + +Davies, R.B. (1994) Writing a matrix package in C++. In OON-SKI'94: The second +annual object-oriented numerics conference, pp 207-213. Rogue Wave Software, +Corvallis. + +Eddelbuttel, Dirk (1996) Object-oriented econometrics: matrix programming in +C++ using GCC and Newmat. Journal of Applied Econometrics, Vol 11, No 2, pp +199-209. + + + + + + 2 Getting started + = ======= ======= + + Overview 2.1 + Make files 2.2 + Customising 2.3 + Compiler performance 2.4 + Updating from previous versions 2.5 + Example 2.6 + Testing 2.7 + + + + + + 2.1 Overview + === ======== + +I use .h as the suffix of definition files and .cpp as the suffix of C++ +source files. + +You will need to compile all the *.cpp files listed as program files in the +files section [6] to get the complete package. Ideally you should store the +resulting object files as a library. The tmt*.cpp files are used for testing +[2.7], example.cpp is an example [2.6] and sl_ex.cpp, nl_ex.cpp and garch.cpp +are examples of the non-linear [3.27] solve and optimisation routines. A +demonstration of the exception mechanism is in test_exc.cpp. + +I include a number of "make" files for compiling the example and the test +package. See the section on make files [2.2] for details. But with the PC +compilers, its pretty quick just to load all the files in the interactive +environments by pointing and clicking. + +Use the large or win32 console model when you are using a PC. Do not "outline" +inline functions. You may need to increase the stack size. + +Your source files that access the newmat will need to #include one or more of +the following files. + +include.h: + if you want to access just the compiler options + +newmat.h: + to access just the main matrix library (includes include.h) + +newmatap.h: + to access the advanced matrix routines such as Cholesky decomposition, QR +triangularisation etc (includes newmat.h) + +newmatio.h: + to access the output routines (includes newmat.h) You can use this only +with compilers that support the standard input/output routines including +manipulators. + +newmatnl.h: + to access the non-linear optimisation routines (includes newmat.h) + + + +See the section on customising [2.3] to see how to edit include.h for your +environment and the section on compilers [2.4] for any special problems with +the compiler you are using. + + + + + 2.2 Make files + === ==== ===== + +I have included "make" files for a number of compilers. These provide an +alternative way of compiling your programs than with the IDE that comes with +PC compilers. See the files section [6] for details. See the example [2.6] for +how to use them. Leave out the target name to compile and link all my examples +and test files. + +PC + +I include make files for some of PC compilers I have access to. They all use +the make utility that comes with the compiler. I don't know whether they work +with versions of the compilers other than the ones I have. The make files for +Borland need editing to show where you have stored your Borland compiler. + +Unix + +The "make" file for the Unix CC compilers link a .cxx file to each .cpp file +since some of these compilers do not recognise .cpp as a legitimate extension +for a C++ file. I suggest you delete this part of the "make" file and, if +necessary, rename the .cpp files to something your compiler recognises. + +My "make" file for Gnu GCC on Unix systems are for use with 'gmake' rather +than 'make'. This defines BOOL_LIB so there is no need to do this in +'include.h'. I assume your compiler recognises the .cpp extension. Ordinary +'make' works with it on the Sun but not the Silicon Graphics or HP machines. +On Linux use 'make'. + +My make file for the CC compilers works with the ordinary make. + +To compile everything with the CC compiler use + + make -f cc.mak + +or for the gnu compiler use + + gmake -f gnu.mak + + +There is a line in the make file for CC 'rm -f $*.cxx'. Some systems won't +accept this line and you will need to delete it. In this case, if you have a +bad compile and you are using my scheme for linking .cxx files, you will need +to delete the .cxx file link generated by that compile before you can do the +next one. + + + + + 2.3 Customising + === =========== + +The file "include.h" sets a variety of options including several compiler +dependent options. You may need to edit include.h to get the options you +require. If you are using a compiler different from one I have worked with you +may have to set up a new section in include.h appropriate for your compiler. + +Borland, Turbo, Gnu, Microsoft and Watcom are recognised automatically. If +none of these are recognised a default set of options is used. These are fine +for AT&T, HPUX and Sun C++. If you using a compiler I don't know about you may +have to write a new set of options. + +There is an option in include.h for selecting whether you use compiler +supported exceptions, simulated exceptions, or disable exceptions. Use the +option for compiler supported exceptions if and only if you have set the +option on your compiler to recognise exceptions. Disabling exceptions +sometimes helps with compilers that are incompatible with my exception +simulation scheme. + +If your compiler recognises bool as required by the standard activate the +statement '#define bool_LIB'. This will deactivate my Boolean class. If you +are using my make file with the Gnu compiler, then this #define is +automatically activated. + +Activate the appropriate statement to make the element type float or double. + +I suggest you leave the option TEMPS_DESTROYED_QUICKLY activated, even though +the Gnu compiler (<2.6) is the only one I know about that requires it (C-Set +also requires it?). This stores the "trees" describing matrix expressions on +the heap rather than the stack and, surprisingly, seems to give better +performance. See the discussion on destruction of temporaries [8.8] for more +explanation. + +Leave the option TEMPS_DESTROYED_QUICKLY_R not activated unless you are using +the Gnu G++ [2.4.3] compiler earlier than version 2.6. This option controls +whether the ReturnMatrix [3.13] construct uses the stack or the heap. The heap +version is rather kludgy and probably should be avoided where possible. + +The option DO_FREE_CHECK [2.7] is used for tracking memory leaks and normally +should not be activated. + +Activate SETUP_C_SUBSCRIPTS if you want to use traditional C style element +access [3.2]. + +Activate '#define use_namespace' if you want to use namespaces [3.29]. Do this +only if you are sure your compiler supports namespaces. If you do turn this +option on, be prepared to turn it off again if the linker reports missing +links. + +Activate '#define _STANDARD_' to use the standard names for the included files +and to find the floating point precision data using the floating point +standard. Assume that this doesn't work at present. + +If you are using a compiler that "include.h" does not recognise and you want +to pick up the floating point precision data from "float.h" then activate +'#define use_float_h'. Otherwise the floating point precision data will be +accessd from "values.h". You will may need to do this with computers from +Digital, in particular. + + + + + 2.4 Compiler performance + === ======== =========== + +I have tested this library on a number of compilers. Here are the levels of +success and any special considerations. In most cases I have chosen code that +works under all the compilers I have access to, but I have had to include some +specific work-arounds for some compilers. For the PC versions, I use a 486dx +computer running windows 95, a Pentium computer running windows NT or Linux +(Red Hat 4.1) and a 386sx running MSDOS 5. The unix versions are on a Sun +Sparc station or a HP unix workstation. Thanks to Victoria University and +Industrial Research Ltd for access to the Unix machines. + +I have set up a block of code for each of the compilers in include.h. Turbo, +Borland, Gnu, Microsoft and Watcom are recognised automatically. There is a +default option that works for AT&T, Sun C++ 4.0.1 and HPUX. So you don't have +to make any changes for these compilers. Otherwise you may have to build your +own set of options in include.h. + + AT&T 2.4.1 + Borland 2.4.2 + Gnu G++ 2.4.3 + HPUX 2.4.4 + Microsoft 2.4.5 + Sun 2.4.6 + Watcom 2.4.7 + Zortech 2.4.8 + + + + + 2.4.1 AT&T + ===== ==== + +AT&T C++ 2.1;3.0.1 on a Sun: Previous versions worked on these compilers, +which I no longer have access to. + +In AT&T 2.1 you may get an error when you use an expression for the single +argument when constructing a Vector or DiagonalMatrix or one of the Triangular +Matrices. You need to evaluate the expression separately. + + + + + 2.4.2 Borland + ===== ======= + +Borland C++ 3.1, 4.5, 5.02: Recently this has been my main development +platform, so naturally everything works with this compiler. There was a +problem with the library utility in version 2.0 which is now fixed. You will +need to use the large or 32 bit flat model. If you are not debugging, turn off +the options that collect debugging information. Make sure you don't run +Borland's exceptions and my simulated exceptions at the same time. + +If you are using version 5 remember to edit include.h to deactivate my Boolean +class. + +When running my test program under ms-dos you may run out of memory. Either +compile the test routine to run under "easywin" or use simulated exceptions +rather than the built in exceptions. Under "easywin" the test program +indicates a memory leak. I presume this is partly because of the way windows +organises its heap rather than there being a real problem. + +If you can, upgrade to windows 95 or window NT and use the 32 bit console +model. + +If you are using the 16 bit large model, don't forget to keep all matrices +less than 64K bytes in length (90x90 for a rectangular matrix if you are using +'double' as your element type). Otherwise your program will crash without +warning or explanation. You may need to break the tmt [2.7] set of test files +into two parts to get the program to fit into your computer. + +In version 4.5, under "easywin" the automatic clean-up of objects by the +exception mechanism does not seem to work correctly. Use my simulated +exceptions if this is a problem. + +One version of Borland had DBL_MIN incorrectly defined. If you are using an +older version of Borland and are getting strange numerical errors in the test +programs reinstate the commented out statements in precision.h. + +I include make files that work under Borland 4.5 and 5. You will need to edit +these to correctly locate the directories for the include and library files. +Both assume you are using simulated exceptions. 'BC.MAK' also works with +version 3.1 if you delete the options that are not recognised and the +reference to the library file that is not recognised. + +C++ Builder version 4: I have successfully used this using the console wizard +(menu item file/new - select new tab). Either use namespace or rename a couple +of my exception names that conflict with Borland. Use compiler exceptions. +Suppose you are compiling my test program tmt. Rename my "main()" function in +"tmt.cpp" to "my_main()". Rename "tmt.cpp" to "tmt_main.cpp". Borland will +generate a new file "tmt.cpp" containing their "main()" function. Put the line +'int my_main();' above this function and put 'return my_main();' into the body +of "main()". + + + + + 2.4.3 Gnu G++ + ===== === === + +Gnu G++ 2.6.0, 2.7.2, 2.8.1: These work OK. + +If you are using 2.7 or later remember to edit include.h to deactivate my +Boolean class - not necessary if you are using my make [2.2] file. But if you +are using a version earlier than 2.7 edit the second line of gnu.mak to +'CXXFLAGS = -O2 -Wall' + +For versions earlier than 2.6.0 you must enable the options +TEMPS_DESTROYED_QUICKLY and TEMPS_DESTROYED_QUICKLY_R. You can't use +expressions like 'Matrix(X*Y)' in the middle of an expression and +'(Matrix)(X*Y)' is unreliable. If you write a function returning a matrix, you +MUST use the ReturnMatrix [3.13] method described in this documentation. This +is because g++ destroys temporaries occurring in an expression too soon for +the two stage way of evaluating expressions that newmat uses. You will have +problems with versions of Gnu earlier than 2.3.1. + +Gnu seems to leave some rubbish on the stack. Possibly this is a buffer or +dynamically loaded subprogram so may not be a bug. + +Linux: It works fine on my copy of G++ 2.7.2. In 2.6.?, 'fabs(*X++)' causes a +problem. You may need to write you own non-inlined version. + + + + + + 2.4.4 HP-UX + ===== ===== + +HP 9000 series HP-UX. I no longer have access to this compiler. Newmat09 +worked without problems with the simulated exceptions; haven't tried the +built-in exceptions. + With recent versions of the compiler you may get warning messages like +'Unsafe cast between pointers/references to incomplete classes'. At present, I +think these can be ignored. + +Here are comments I made two years ago. + +I have tried the library on two versions of HP-UX. (I don't know the version +numbers, the older is a clone of AT&T 3, the newer is HP's version with +exceptions). Both worked after the modifications described in this section. + +With the older version of the compiler I needed to edit the math.h library +file to remove a duplicate definition of abs. + +With the newer version you can set the +eh option to enable exceptions and +activate the UseExceptions option in include.h. If you are using my make file, +you will need to replace CC with CC +eh where ever CC occurs. I recommend that +you do not do this and either disable exceptions or use my simulated +exceptions. I get core dumps when I use the built-in exceptions and suspect +they are not sufficiently debugged as yet. + +If you are using my simulated exceptions you may get a mass of error messages +from the linker about __EH_JMPBUF_TEMP. In this case get file setjmp.h (in +directory /usr/include/CC ?) and put extern in front of the line + + jmp_buf * __EH_JMPBUF_TEMP; + +The file setjmp.h is accessed in my file myexcept.h. You may want to change +the #include statement to access your edited copy of setjmp.h. + + + + 2.4.5 Microsoft + ===== ========= + +Microsoft Visual C++ 2.0: Seems to work OK. You can use the makefile +'ms_nt.mak'. + +You must '#define TEMPS_DESTROYED_QUICKLY' owing to a bug in version 7 (at +least) of MSC. There are some notes in the file 'include.h' on changes to run +under version 7. I haven't tried newmat10 on version 7. + +Microsoft Visual C++ 1.51. Disable exceptions, comment out the line in +include.h '#define TEMPS_DESTROYED_QUICKLY_R'. In 'tmt.cpp', comment out the +'Try' and 'CatchAll' lines at the beginning of 'main()' and the line +'trymati()'. You can use the makefile 'ms.mak'. You will probably need to +break the tmt [2.7] test files into two parts to get the program to link. + +If you can, upgrade to windows 95, 98 or window NT and use the 32 bit console +model. + +If you are using the 16 bit large model, don't forget to keep all matrices +less than 64K bytes in length (90x90 for a rectangular matrix if you are using +'double' as your element type). Otherwise your program will crash without +warning or explanation. You may need to break the tmt [2.7] set of test files +into two parts to get the program to fit into your computer. + +Microsoft Visual C++ 4: I haven't tried this - a correspondent reports: I use +Microsoft Visual C++ Version 4. there is only one minor problem. In all files +you must include '#include "stdafx.h"' (presumably if you are using MFC). This +file contains essential information for VC++. Leave it out and you get +"Unexpected end of file". + +Microsoft Visual C++ 5: I have tried this in console mode and it seems to work +satisfactorily. There may be a problem with namespace [3.29] (fixed by Service +Pack 3?). Turn optimisation off. Edit 'include.h' to use the compiler +supported exceptions. If you want to work under MFC '#include "stdafx.h"' at +the beginning of each .cpp file. + +Microsoft Visual C++ 6: Get the latest service pack. I have tried this in +console mode and it seems to work satisfactorily. Edit 'include.h' to use the +compiler supported exceptions. If you want to work under MFC '#include +"stdafx.h"' at the beginning of each .cpp file. + + + + + 2.4.6 Sun + ===== === + +Sun C++ (version 4.2): This seems to work fine. + +Sun C++ (version 5): There seems to be a problem with exceptions. If you my +simulated exceptions the non-linear optimsation programs hang. If you use the +compiler supported exceptions my test_exc program crashes. So take your +choice. + + + + + 2.4.7 Watcom & Optima++ + ===== ====== = ======== + +Watcom C++ (version 10): this works fine. Don't try to run Watcom's exceptions +and my simulated exceptions at the same time. + +But best don't use Watcom's exceptions at all in this version as they do seem +to cause problems; even when not used. + +It seems fine on Optima++ 1.0 in console mode. I haven't tested it in gui +mode. Optima++ provides some stuff to insert in the main program. + + + + 2.4.8 Zortech + ===== ======= + +I don't support Zortech any more and haven't tried the Symantec successors to +Zortech. + + + + + + 2.5 Updating from previous versions + === ======== ==== ======== ======== + +Newmat10 includes new maxima, minima and Determinant [3.8] functions, a faster +FFT [3.22], revised make [2.2] files for GCC and CC compilers and several +corrections, new ReSize [3.10] function. The program files include a new file, +'newfft.cpp', so you will need to include this in the list of files in your +IDE and make files. If you are updating from a beta version of newmat09 look +through the next section as there were some late changes to newmat09. + +If you are upgrading from newmat08 note the following: + +* Boolean, TRUE, FALSE are now bool, true, false. See customising [2.3] if +your compiler supports the bool class. + +* ReDimension is now ReSize [3.10]. + +* The simulated exception [3.25] package has been updated. + +* Operators '==', '!=', '+=', '-=', '*=', '|=', '&=' are now supported as +binary [3.6] matrix operators. + +* 'A+=f', 'A-=f', 'A*=f', 'A/=f', 'f+A', 'f-A', 'f*A' are supported for A +matrix, f scalar [3.7]. + +* Fast trigonometric transforms [3.23]. + +* Reverse [3.5] function for reversing order of elements in a vector or +matrix. + +* IsSingular [3.8] function. + +* An option is included for defining namespaces [3.29]. + +* Dummy inequality operators are defined for compatibiity with the STL. + +* The row/column classes in newmat3.cpp have been modified to improve +efficiency and correct an invalid use of pointer arithmetic. Most users won't +be using these classes explicitly; if you are, please contact me for details +of the changes. + +* Matrix LU decomposition rewritten (faster for large arrays). + +* The sort function rewritten (faster). + +* The documentation files newmata.txt and newmatb.txt have been amalgamated +and both are included in the hypertext version. + +* Some of the make [2.2] files reorganised again. + + +If you are upgrading from newmat07 note the following: + +* .cxx files are now .cpp files. Some versions of won't accept .cpp. The +"make" files for Gnu and AT&T link the .cpp files to .cxx files before +compilation and delete the links after compilation. + +* An option [2.3] in include.h allows you to use compiler supported +exceptions, simulated exceptions or disable exceptions. Edit the file +include.h to select one of these three options. Don't simulate exceptions if +you have set your compiler's option to implement exceptions. + +* New QR decomposition [3.18] functions. + +* A non-linear least squares [3.27] class. + +* No need to explicitly set the AT&T option in include.h. + +* Concatenation and elementwise multiplication [3.6]. + +* A new GenericMatrix [3.16] class. + +* Sum [3.8] function. + +* Some of the make [2.2] files reorganised. + + +If you are upgrading from newmat06 note the following: + +* If you are using << to load a Real into a submatrix change this to =. + + +If you are upgrading from newmat03 or newmat04 note the following + +* .hxx files are now .h files + +* real changed to Real + +* BOOL changed to Boolean + +* CopyToMatrix changed to AsMatrix, etc + +* real(A) changed to A.AsScalar() + + +The current version is quite a bit longer that newmat04, so if you are almost +out of space with newmat04, don't throw newmat04 away until you have checked +your program will work under this version. + +See the change history [1.7] for other changes. + + + + 2.6 Example + === ======= + +An example is given in 'example.cpp'. This gives a simple linear regression +example using five different algorithms. The correct output is given in +'example.txt'. The program carries out a rough check that no memory is left +allocated on the heap when it terminates. See the section on testing [2.7] for +a comment on the reliability of this check and the use of the DO_FREE_CHECK +option. + +I include a variety of make files. To compile the example use a command like + + gmake example -f gnu.mak (Gnu G++) + gmake example -f cc.mak (AT&T, HPUX, Sun) + nmake example.exe -f ms_nt.mak (Microsoft Visual C++ 2.0) + nmake example.exe -f ms.mak (Microsoft Visual C++ 1.51) + make -f bc.mak example.exe (Borland C++ 4.5, 5) + make -f bc32.mak example.exe (Borland C++ 4.5, 5, 32 bit) + wmake example.exe -f watcom.mak (Watcom C++ 10A) + wmake example.exe -f watco_nt.mak (Watcom C++ 10A, for win NT) + +To compile all the example and test files use a command like + + gmake -f gnu.mak (Gnu G++) + + + ----------------------------------------------------------------------------- +The example uses io manipulators. It will not work with a compiler that does +not support the standard io manipulators. + ----------------------------------------------------------------------------- + +Other example files are 'nl_ex.cpp' and 'garch.cpp' for demonstrating the +non-linear fitting routines, 'sl_ex' for demonstrating the solve function and +'test_exc' for demonstrating the exceptions. + + + + + 2.7 Testing + === ======= + +The library package contains a comprehensive test program in the form of a +series of files with names of the form tmt?.cxx. The files consist of a large +number of matrix formulae all of which evaluate to zero (except the first one +which is used to check that we are detecting non-zero matrices). The printout +should state that it has found just one non-zero matrix. + +The test program should be run with "Real" typedefed to "double" rather than +"float" in include.h [2.3]. + +Make sure the C subscripts [3.2] are enabled if you want to test these. + +Various versions of the make file (extension .mak) are included with the +package. See the section on make files [2.2]. + +The program also allocates and deletes a large block and small block of memory +before it starts the main testing and then at the end of the test. It then +checks that the blocks of memory were allocated in the same place. If not then +one suspects that there has been a memory leak. i.e. a piece of memory has +been allocated and not deleted. + +This is not completely foolproof. Programs may allocate extra print buffers +while the program is running. I have tried to overcome this by doing a print +before I allocate the first memory block. Programs may allocate memory for +different sized items in different places, or might not allocate items +consecutively. Or they might mix the items with memory blocks from other +programs. Nevertheless, I seem to get consistent answers from many of the +compilers I am working with, so I think this is a worthwhile test. + +If the DO_FREE_CHECK [2.3] option in include.h is activated, the program +checks that each 'new' is balanced with exactly one 'delete'. This provides a +more definitive test of no memory leaks. There are additional statements in +myexcept.cpp which can be activated to print out details of the memory being +allocated and released. + +I have included a facility for checking that each piece of code in the library +is really exercised by the test routines. Each block of code in the main part +of the library contains a word 'REPORT'. 'newmat.h' has a line defining +'REPORT' that can be activated (deactivate the dummy version). This gives a +printout of the number of times each of the 'REPORT' statements in the '.cpp' +files is accessed. Use a grep with line numbers to locate the lines on which +'REPORT' occurs and compare these with the lines that the printout shows were +actually accessed. One can then see which lines of code were not accessed. + + + 3 Reference manual + = ========= ====== + + Constructors 3.1 + Accessing elements 3.2 + Assignment and copying 3.3 + Entering values 3.4 + Unary operations 3.5 + Binary operations 3.6 + Matrix and scalar ops 3.7 + Scalar functions 3.8 + Submatrices 3.9 + Change dimension 3.10 + Change type 3.11 + Multiple matrix solve 3.12 + Memory management 3.13 + Efficiency 3.14 + Output 3.15 + Accessing unspecified type 3.16 + Cholesky decomposition 3.17 + QR decomposition 3.18 + Singular value decomposition 3.19 + Eigenvalue decomposition 3.20 + Sorting 3.21 + Fast Fourier transform 3.22 + Fast trigonometric transforms 3.23 + Numerical recipes in C 3.24 + Exceptions 3.25 + Cleanup following exception 3.26 + Non-linear applications 3.27 + Standard template library 3.28 + Namespace 3.29 + + + + 3.1 Constructors + === ============ + +To construct an m x n matrix, 'A', (m and n are integers) use + + Matrix A(m,n); + +The UpperTriangularMatrix, LowerTriangularMatrix, SymmetricMatrix and +DiagonalMatrix types are square. To construct an n x n matrix use, for example + + UpperTriangularMatrix UT(n); + LowerTriangularMatrix LT(n); + SymmetricMatrix S(n); + DiagonalMatrix D(n); + +Band matrices need to include bandwidth information in their constructors. + + BandMatrix BM(n, lower, upper); + UpperBandMatrix UB(n, upper); + LowerBandMatrix LB(n, lower); + SymmetricBandMatrix SB(n, lower); + +The integers upper and lower are the number of non-zero diagonals above and +below the diagonal (excluding the diagonal) respectively. + +The RowVector and ColumnVector types take just one argument in their +constructors: + + RowVector RV(n); + ColumnVector CV(n); + +These constructors do *not* initialise the elements of the matrices. To set +all the elements to zero use, for example, + + Matrix A(m, n); A = 0.0; + +You can also construct vectors and matrices without specifying the dimension. +For example + + Matrix A; + +In this case the dimension must be set by an assignment statement [3.3] or a +re-dimension statement [3.10]. + +You can also use a constructor to set a matrix equal to another matrix or +matrix expression. + + Matrix A = UT; + Matrix A = UT * LT; + +Only conversions that don't lose information are supported - eg you cannot +convert an upper triangular matrix into a diagonal matrix using =. + + + + + 3.2 Accessing elements + === ========= ======== + +Elements are accessed by expressions of the form 'A(i,j)' where i and j run +from 1 to the appropriate dimension. Access elements of vectors with just one +argument. Diagonal matrices can accept one or two subscripts. + +This is different from the earliest version of the package in which the +subscripts ran from 0 to one less than the appropriate dimension. Use +'A.element(i,j)' if you want this earlier convention. + +'A(i,j)' and 'A.element(i,j)' can appear on either side of an = sign. + +If you activate the '#define SETUP_C_SUBSCRIPTS' in 'include.h' you can also +access elements using the traditional C style notation. That is 'A[i][j]' for +matrices (except diagonal) and 'V[i]' for vectors and diagonal matrices. The +subscripts start at zero (ie like element) and there is no range checking. +Because of the possibility of confusing 'V(i)' and 'V[i]', I suggest you do +not activate this option unless you really want to use it. + +Symmetric matrices are stored as lower triangular matrices. It is important to +remember this if you are using the 'A[i][j]' method of accessing elements. +Make sure the first subscript is greater than or equal to the second +subscript. However, if you are using the 'A(i,j)' method the program will swap +'i' and 'j' if necessary; so it doesn't matter if you think of the storage as +being in the upper triangle (but it "does" matter in some other situations +such as when entering [3.4] data). + + + 3.3 Assignment and copying + === ========== === ======= + +The operator '=' is used for copying matrices, converting matrices, or +evaluating expressions. For example + + A = B; A = L; A = L * U; + +Only conversions that don't lose information are supported. The dimensions of +the matrix on the left hand side are adjusted to those of the matrix or +expression on the right hand side. Elements on the right hand side which are +not present on the left hand side are set to zero. + +The operator '<<' can be used in place of '=' where it is permissible for +information to be lost. + +For example + + SymmetricMatrix S; Matrix A; + ...... + S << A.t() * A; + +is acceptable whereas + + S = A.t() * A; // error + +will cause a runtime error since the package does not (yet?) recognise +'A.t()*A' as symmetric. + +Note that you can not use '<<' with constructors. For example + + SymmetricMatrix S << A.t() * A; // error + +does not work. + +Also note that '<<' cannot be used to load values from a full matrix into a +band matrix, since it will be unable to determine the bandwidth of the band +matrix. + +A third copy routine is used in a similar role to '='. Use + + A.Inject(D); + +to copy the elements of 'D' to the corresponding elements of 'A' but leave the +elements of 'A' unchanged if there is no corresponding element of 'D' (the '=' +operator would set them to 0). This is useful, for example, for setting the +diagonal elements of a matrix without disturbing the rest of the matrix. +Unlike '=' and '<<', Inject does not reset the dimensions of 'A', which must +match those of 'D'. Inject does not test for no loss of information. + +You cannot replace 'D' by a matrix expression. The effect of 'Inject(D)' +depends on the type of 'D'. If 'D' is an expression it might not be obvious to +the user what type it would have. So I thought it best to disallow +expressions. + +Inject can be used for loading values from a regular matrix into a band +matrix. (Don't forget to zero any elements of the left hand side that will not +be set by the loading operation). + +Both '<<' and Inject can be used with submatrix expressions on the left hand +side. See the section on submatrices [3.9]. + +To set the elements of a matrix to a scalar use operator '=' + + Real r; int m,n; + ...... + Matrix A(m,n); A = r; + + + + + + 3.4 Entering values + === ======== ====== + +You can load the elements of a matrix from an array: + + Matrix A(3,2); + Real a[] = { 11,12,21,22,31,33 }; + A << a; + +This construction does not check that the numbers of elements match correctly. +This version of '<<' can be used with submatrices on the left hand side. It is +not defined for band matrices. + +Alternatively you can enter short lists using a sequence of numbers separated +by '<<' . + + Matrix A(3,2); + A << 11 << 12 + << 21 << 22 + << 31 << 32; + +This does check for the correct total number of entries, although the message +for there being insufficient numbers in the list may be delayed until the end +of the block or the next use of this construction. This does not work for band +matrices or submatrices, or for long lists. Also try to restrict its use to +numbers. You can include expressions, but these must not call a function which +includes the same construction. + +Remember that matrices are stored by rows and that symmetric matrices are +stored as lower triangular matrices when using these methods to enter data. + + + + + 3.5 Unary operators + === ===== ========= + +The package supports unary operations + + X = -A; // change sign of elements + X = A.t(); // transpose + X = A.i(); // inverse (of square matrix A) + X = A.Reverse(); // reverse order of elements of vector + // or matrix (not band matrix) + + + + + 3.6 Binary operators + === ====== ========= + +The package supports binary operations + + X = A + B; // matrix addition + X = A - B; // matrix subtraction + X = A * B; // matrix multiplication + X = A.i() * B; // equation solve (square matrix A) + X = A | B; // concatenate horizontally (concatenate the rows) + X = A & B; // concatenate vertically (concatenate the columns) + X = SP(A, B); // elementwise product of A and B (Schur product) + bool b = A == B; // test whether A and B are equal + bool b = A != B; // ! (A == B) + A += B; // A = A + B; + A -= B; // A = A - B; + A *= B; // A = A * B; + A |= B; // A = A | B; + A &= B; // A = A & B; + <, >, <=, >= // included for compatibility with STL - see notes + + +Notes: + +* If you are doing repeated multiplication. For example 'A*B*C', use brackets +to force the order of evaluation to minimise the number of operations. If 'C' +is a column vector and 'A' is not a vector, then it will usually reduce the +number of operations to use 'A*(B*C)'. + +* In the equation solve example case the inverse is not explicitly +calculated. An LU decomposition of 'A' is performed and this is applied to +'B'. This is more efficient than calculating the inverse and then multiplying. +See also multiple matrix solving [3.12]. + +* The package does not (yet?) recognise 'B*A.i()' as an equation solve and +the inverse of 'A' would be calculated. It is probably better to use +'(A.t().i()*B.t()).t()'. + +* Horizontal or vertical concatenation returns a result of type Matrix, +RowVector or ColumnVector. + +* If 'A' is m x p, 'B' is m x q, then 'A | B' is m x (p+q) with the k-th row +being the elements of the k-th row of 'A' followed by the elements of the k-th +row of 'B'. + +* If 'A' is p x n, 'B' is q x n, then 'A & B' is (p+q) x n with the k-th +column being the elements of the k-th column of 'A' followed by the elements +of the k-th column of 'B'. + +* For complicated concatenations of matrices, consider instead using +submatrices [3.9]. + +* See the section on submatrices [3.9] on using a submatrix on the RHS of an +expression. + +* Two matrices are equal if their difference is zero. They may be of +different types. For the CroutMatrix or BandLUMatrix they must be of the same +type and have all their elements equal. This is not a very useful operator and +is included for compatibility with some container templates. + +* The inequality operators are included for compatibility with the standard +template library [3.28]. If actually called, they will throw an exception. So +don't try to sort a "list" of matrices. + + + + + + 3.7 Matrix and scalar + === ====== === ====== + +The following expressions multiply the elements of a matrix 'A' by a scalar f: +'A * f' or 'f * A' . Likewise one can divide the elements of a matrix 'A' by a +scalar f: 'A / f' + +The expressions 'A + f' and 'A - f' add or subtract a rectangular matrix of +the same dimension as 'A' with elements equal to 'f' to or from the matrix +'A'. + +The expression 'f + A' is an alternative to 'A + f'. The expression 'f - A' +subtracts matrix 'A' from a rectangular matrix of the same dimension as 'A' +and with elements equal to 'f' + +The expression 'A += f' replaces 'A' by 'A + f'. Operators '-=', '*=', '/=' +are similarly defined. + + + + 3.8 Scalar functions of a matrix + === ====== ========= == = ====== + + + int i, j; + int m = A.Nrows(); // number of rows + int n = A.Ncols(); // number of columns + Real r = A.AsScalar(); // value of 1x1 matrix + Real ssq = A.SumSquare(); // sum of squares of elements + Real sav = A.SumAbsoluteValue(); // sum of absolute values + Real s = A.Sum(); // sum of values + Real mv = A.MaximumAbsoluteValue(); // maximum of absolute values + Real mv = A.MinimumAbsoluteValue(); // minimum of absolute values + Real mv = A.Maximum(); // maximum value + Real mv = A.Minimum(); // minimum value + Real mv = A.MaximumAbsoluteValue1(i); // maximum of absolute values + Real mv = A.MinimumAbsoluteValue1(i); // minimum of absolute values + Real mv = A.Maximum1(i); // maximum value + Real mv = A.Minimum1(i); // minimum value + Real mv = A.MaximumAbsoluteValue2(i,j);// maximum of absolute values + Real mv = A.MinimumAbsoluteValue2(i,j);// minimum of absolute values + Real mv = A.Maximum2(i,j); // maximum value + Real mv = A.Minimum2(i,j); // minimum value + Real norm = A.Norm1(); // maximum of sum of absolute + values of elements of a column + Real norm = A.NormInfinity(); // maximum of sum of absolute + values of elements of a row + Real t = A.Trace(); // trace + Real d = A.Determinant(); // determinant + LogAndSign ld = A.LogDeterminant(); // log of determinant + bool z = A.IsZero(); // test all elements zero + MatrixType mt = A.Type(); // type of matrix + Real* s = Store(); // pointer to array of elements + int l = Storage(); // length of array of elements + bool s = A.IsSingular(); // A is a CroutMatrix or + BandLUMatrix + MatrixBandWidth mbw = A.BandWidth(); // upper and lower bandwidths + + +The functions 'A.MaximumAbsoluteValue()', 'A.MinimumAbsoluteValue()', +'A.Maximum()' and 'A.Minimum()' throw an exception if 'A' has no rows or no +columns. The versions 'A.MaximumAbsoluteValue1(i)', etc return the location of +the extreme element in a RowVector, ColumnVector or DiagonalMatrix. The +versions 'A.MaximumAbsoluteValue2(i,j)', etc return the row and column numbers +of the extreme element. These versions also throw an exception if 'A' has no +rows or no columns. If the extreme value occurs more than once the location of +the last one is given. + +'A.LogDeterminant()' returns a value of type LogAndSign. If ld is of type +LogAndSign use + + ld.Value() to get the value of the determinant + ld.Sign() to get the sign of the determinant (values 1, 0, -1) + ld.LogValue() to get the log of the absolute value. + +Note that the direct use of the function 'Determinant()' will often cause a +floating point overflow exception. + +'A.IsZero()' returns Boolean value 'true' if the matrix 'A' has all elements +equal to 0.0. + +'IsSingular' is defined only for CroutMatrix and BandLUMatrix. It returns +'true' if one of the diagonal elements of the LU decomposition is exactly +zero. + +'MatrixType mt = A.Type()' returns the type of a matrix. Use '(char*)mt' to +get a string (UT, LT, Rect, Sym, Diag, Band, UB, LB, Crout, BndLU) showing +the type (Vector types are returned as Rect). + +'MatrixBandWidth' has member functions 'Upper()' and 'Lower()' for finding the +upper and lower bandwidths (number of diagonals above and below the diagonal, +both zero for a diagonal matrix). For non-band matrices -1 is returned for +both these values. + +The versions Sum(A), SumSquare(A), SumAbsoluteValue(A), +MaximumAbsoluteValue(A), MinimumAbsoluteValue(A), Maximum(A), Minimum(A), +Trace(A), LogDeterminant(A), Determinant(A), Norm1(A), NormInfinity(A) can be +used in place of A.Sum(), A.SumSquare(), A.SumAbsoluteValue(), +A.MaximumAbsoluteValue(), A.MinimumAbsoluteValue(), A.Maximum(), A.Minimum(), +A.Trace(), A.LogDeterminant(), A.Norm1(), A.NormInfinity(). + + + + + 3.9 Submatrices + === =========== + + + A.SubMatrix(fr,lr,fc,lc) + +This selects a submatrix from 'A'. The arguments fr,lr,fc,lc are the first +row, last row, first column, last column of the submatrix with the numbering +beginning at 1. This may be used in any matrix expression or on the left hand +side of '=', '<<' or Inject. Inject does not check no information loss. You +can also use the construction + + Real c; .... A.SubMatrix(fr,lr,fc,lc) = c; + +to set a submatrix equal to a constant. + +The following are variants of SubMatrix: + + A.SymSubMatrix(f,l) // This assumes fr=fc and lr=lc. + A.Rows(f,l) // select rows + A.Row(f) // select single row + A.Columns(f,l) // select columns + A.Column(f) // select single column + +In each case f and l mean the first and last row or column to be selected +(starting at 1). + +I allow lr = fr-1, lc = fc-1 or l = f-1 to indicate that a matrix of zero rows +or columns is to be returned. + +If SubMatrix or its variant occurs on the right hand side of an '=' or '<<' or +within an expression its type is as follows + + A.SubMatrix(fr,lr,fc,lc): If A is RowVector or + ColumnVector then same type + otherwise type Matrix + A.SymSubMatrix(f,l): Same type as A + A.Rows(f,l): Type Matrix + A.Row(f): Type RowVector + A.Columns(f,l): Type Matrix + A.Column(f): Type ColumnVector + +If SubMatrix or its variant appears on the left hand side of '=' or '<<' , +think of its type being Matrix. Thus 'L.Row(1)' where 'L' is +LowerTriangularMatrix expects 'L.Ncols()' elements even though it will use +only one of them. If you are using '=' the program will check for no loss of +data. + +A SubMatrix can appear on the left-hand side of '+=' or '-=' with a matrix +expression on the right-hand side. It can also appear on the left-hand side of +'+=', '-=', '*=' or '/=' with a Real on the right-hand side. In each case +there must be no loss of information. + +Do not use the '+=' and '-=' operations with a submatrix of a SymmetricMatrix +or BandSymmetricMatrix on the LHS and a Real on the RHS. + +If you are are using the submatrix facility to build a matrix from a small +number of components, consider instead using the concatenation operators +[3.6]. + + + + + 3.10 Change dimensions + ==== ====== ========== + +The following operations change the dimensions of a matrix. The values of the +elements are lost. + + A.ReSize(nrows,ncols); // for type Matrix or nricMatrix + A.ReSize(n); // for all other types, except Band + A.ReSize(n,lower,upper); // for BandMatrix + A.ReSize(n,lower); // for LowerBandMatrix + A.ReSize(n,upper); // for UpperBandMatrix + A.ReSize(n,lower); // for SymmetricBandMatrix + A.ReSize(B); // set dims to those of B + +Use 'A.CleanUp()' to set the dimensions of 'A' to zero and release all the +heap memory. + +'A.ReSize(B)' sets the dimensions of 'A' to those of a matrix 'B'. This +includes the band-width in the case of a band matrix. It is an error for 'A' +to be a band matrix and 'B' not a band matrix (or diagonal matrix). + +Remember that 'ReSize' destroys values. If you want to 'ReSize', but keep the +values in the bit that is left use something like + + ColumnVector V(100); + ... // load values + V = V.Rows(1,50); // to get first 50 values. + +If you want to extend a matrix or vector use something like + + ColumnVector V(50); + ... // load values + { V.Release(); ColumnVector X=V; V.ReSize(100); V.Rows(1,50)=X; } + // V now length 100 + + + + + + 3.11 Change type + ==== ====== ==== + +The following functions interpret the elements of a matrix (stored row by row) +to be a vector or matrix of a different type. Actual copying is usually +avoided where these occur as part of a more complicated expression. + + A.AsRow() + A.AsColumn() + A.AsDiagonal() + A.AsMatrix(nrows,ncols) + A.AsScalar() + +The expression 'A.AsScalar()' is used to convert a 1 x 1 matrix to a scalar. + + + + + 3.12 Multiple matrix solve + ==== ======== ====== ===== + +To solve the matrix equation 'Ay = b' where 'A' is a square matrix of equation +coefficients, 'y' is a column vector of values to be solved for, and 'b' is a +column vector, use the code + + int n = something + Matrix A(n,n); ColumnVector b(n); + ... put values in A and b + ColumnVector y = A.i() * b; // solves matrix equation + +The following notes are for the case where you want to solve more than one +matrix equation with different values of 'b' but the same 'A'. Or where you +want to solve a matrix equation and also find the determinant of 'A'. In these +cases you probably want to avoid repeating the LU decomposition of 'A' for +each solve or determinant calculation. + + + +If 'A' is a square or symmetric matrix use + + CroutMatrix X = A; // carries out LU decomposition + Matrix AP = X.i()*P; Matrix AQ = X.i()*Q; + LogAndSign ld = X.LogDeterminant(); + +rather than + + Matrix AP = A.i()*P; Matrix AQ = A.i()*Q; + LogAndSign ld = A.LogDeterminant(); + +since each operation will repeat the LU decomposition. + +If 'A' is a BandMatrix or a SymmetricBandMatrix begin with + + BandLUMatrix X = A; // carries out LU decomposition + +A CroutMatrix or a BandLUMatrix can't be manipulated or copied. Use references +as an alternative to copying. + +Alternatively use + + LinearEquationSolver X = A; + +This will choose the most appropriate decomposition of 'A'. That is, the band +form if 'A' is banded; the Crout decomposition if 'A' is square or symmetric +and no decomposition if 'A' is triangular or diagonal. If you want to use the +LinearEquationSolver '#include newmatap.h'. + + + + + 3.13 Memory management + ==== ====== ========== + +The package does not support delayed copy. Several strategies are required to +prevent unnecessary matrix copies. + +Where a matrix is called as a function argument use a constant reference. For +example + + YourFunction(const Matrix& A) + +rather than + + YourFunction(Matrix A) + + +Skip the rest of this section on your first reading. + ----------------------------------------------------------------------------- +Gnu g++ (< 2.6) users please read on; if you are returning matrix values from +a function, then you must use the ReturnMatrix construct. + ----------------------------------------------------------------------------- + +A second place where it is desirable to avoid unnecessary copies is when a +function is returning a matrix. Matrices can be returned from a function with +the return command as you would expect. However these may incur one and +possibly two copyings of the matrix. To avoid this use the following +instructions. + +Make your function of type ReturnMatrix . Then precede the return statement +with a Release statement (or a ReleaseAndDelete statement if the matrix was +created with new). For example + + + ReturnMatrix MakeAMatrix() + { + Matrix A; // or any other matrix type + ...... + A.Release(); return A; + } + +or + + ReturnMatrix MakeAMatrix() + { + Matrix* m = new Matrix; + ...... + m->ReleaseAndDelete(); return *m; + } + +If your compiler objects to this code, replace the return statements with + + return A.ForReturn(); + +or + + return m->ForReturn(); + + +If you are using AT&T C++ you may wish to replace 'return A;' by return +'(ReturnMatrix)A;' to avoid a warning message; but this will give a runtime +error with Gnu. (You can't please everyone.) + ----------------------------------------------------------------------------- +Do not forget to make the function of type ReturnMatrix; otherwise you may get +incomprehensible run-time errors. + ----------------------------------------------------------------------------- +You can also use '.Release()' or '->ReleaseAndDelete()' to allow a matrix +expression to recycle space. Suppose you call + + A.Release(); + +just before 'A' is used just once in an expression. Then the memory used by +'A' is either returned to the system or reused in the expression. In either +case, 'A''s memory is destroyed. This procedure can be used to improve +efficiency and reduce the use of memory. + +Use '->ReleaseAndDelete' for matrices created by new if you want to completely +delete the matrix after it is accessed. + + + + + 3.14 Efficiency + ==== ========== + +The package tends to be not very efficient for dealing with matrices with +short rows. This is because some administration is required for accessing rows +for a variety of types of matrices. To reduce the administration a special +multiply routine is used for rectangular matrices in place of the generic one. +Where operations can be done without reference to the individual rows (such as +adding matrices of the same type) appropriate routines are used. + +When you are using small matrices (say smaller than 10 x 10) you may find it +faster to use rectangular matrices rather than the triangular or symmetric +ones. + + + + 3.15 Output + ==== ====== + +To print a matrix use an expression like + + Matrix A; + ...... + cout << setw(10) << setprecision(5) << A; + +This will work only with systems that support the standard input/output +routines including manipulators. You need to #include the file newmatio.h. + +The present version of this routine is useful only for matrices small enough +to fit within a page or screen width. + +To print several vectors or matrices in columns use a concatenation operator +[3.6]: + + ColumnVector A, B; + ..... + cout << setw(10) << setprecision(5) << (A | B); + + + + + 3.16 Unspecified type + ==== =========== ==== + +Skip this section on your first reading. + +If you want to work with a matrix of unknown type, say in a function. You can +construct a matrix of type 'GenericMatrix'. Eg + + Matrix A; + ..... // put some values in A + GenericMatrix GM = A; + +A GenericMatrix matrix can be used anywhere where a matrix expression can be +used and also on the left hand side of an '='. You can pass any type of matrix +(excluding the Crout and BandLUMatrix types) to a 'const GenericMatrix&' +argument in a function. However most scalar functions including Nrows(), +Ncols(), Type() and element access do not work with it. Nor does the +ReturnMatrix construct. See also the paragraph on LinearEquationSolver [3.12]. + +An alternative and less flexible approach is to use BaseMatrix or +GeneralMatrix. + +Suppose you wish to write a function which accesses a matrix of unknown type +including expressions (eg 'A*B'). Then use a layout similar to the following: + + void YourFunction(BaseMatrix& X) + { + GeneralMatrix* gm = X.Evaluate(); // evaluate an expression + // if necessary + ........ // operations on *gm + gm->tDelete(); // delete *gm if a temporary + } + +See, as an example, the definitions of 'operator<<' in newmat9.cpp. + +Under certain circumstances; particularly where 'X' is to be used just once in +an expression you can leave out the 'Evaluate()' statement and the +corresponding 'tDelete()'. Just use 'X' in the expression. + +If you know YourFunction will never have to handle a formula as its argument +you could also use + + void YourFunction(const GeneralMatrix& X) + { + ........ // operations on X + } + +Do not try to construct a GeneralMatrix or BaseMatrix. + + + + + 3.17 Cholesky decomposition + ==== ======== ============= + +Suppose 'S' is symmetric and positive definite. Then there exists a unique +lower triangular matrix 'L' such that 'L * L.t() = S'. To calculate this use + + SymmetricMatrix S; + ...... + LowerTriangularMatrix L = Cholesky(S); + +If 'S' is a symmetric band matrix then 'L' is a band matrix and an alternative +procedure is provided for carrying out the decomposition: + + SymmetricBandMatrix S; + ...... + LowerBandMatrix L = Cholesky(S); + + + + + 3.18 QR decomposition + ==== == ============= + +This is a variant on the usual QR transformation. + +Start with matrix + + / 0 0 \ s + \ X Y / n + + s t + +Our version of the QR decomposition multiplies this matrix by an orthogonal +matrix Q to get + + / U M \ s + \ 0 Z / n + + s t + +where 'U' is upper triangular (the R of the QR transform). + +This is good for solving least squares problems: choose b (matrix or row +vector) to minimise the sum of the squares of the elements of + + Y - X*b + +Then choose 'b = U.i()*M;' The residuals 'Y - X*b' are in 'Z'. + +This is the usual QR transformation applied to the matrix 'X' with the square +zero matrix attached concatenated on top of it. It gives the same triangular +matrix as the QR transform applied directly to 'X' and generally seems to work +in the same way as the usual QR transform. However it fits into the matrix +package better and also gives us the residuals directly. It turns out to be +essentially a modified Gram-Schmidt decomposition. + +Two routines are provided: + + QRZ(X, U); + +replaces 'X' by orthogonal columns and forms 'U'. + + QRZ(X, Y, M); + +uses 'X' from the first routine, replaces 'Y' by 'Z' and forms 'M'. + +The are also two routines 'QRZT(X, L)' and 'QRZT(X, Y, M)' which do the same +decomposition on the transposes of all these matrices. QRZT replaces the +routines HHDecompose in earlier versions of newmat. HHDecompose is still +defined but just calls QRZT. + + + + + 3.19 Singular value decomposition + ==== ======== ===== ============= + +The singular value decomposition of an m x n 'Matrix' 'A' (where m >= n) is a +decomposition + + A = U * D * V.t() + +where 'U' is m x n with 'U.t() * U' equalling the identity, 'D' is an n x n +'DiagonalMatrix' and 'V' is an n x n orthogonal matrix (type 'Matrix' in +"Newmat"). + +Singular value decompositions are useful for understanding the structure of +ill-conditioned matrices, solving least squares problems, and for finding the +eigenvalues of 'A.t() * A'. + +To calculate the singular value decomposition of 'A' (with m >= n) use one of + + SVD(A, D, U, V); // U = A is OK + SVD(A, D); + SVD(A, D, U); // U = A is OK + SVD(A, D, U, false); // U (can = A) for workspace only + SVD(A, D, U, V, false); // U (can = A) for workspace only + +where 'A', 'U' and 'V' are of type 'Matrix' and 'D' is a 'DiagonalMatrix'. +The values of 'A' are not changed unless 'A' is also inserted as the third +argument. + + + + + 3.20 Eigenvalue decomposition + ==== ========== ============= + +An eigenvalue decomposition of a SymmetricMatrix 'A' is a decomposition + + A = V * D * V.t() + +where 'V' is an orthogonal matrix (type 'Matrix' in "Newmat") and 'D' is a +DiagonalMatrix. + +Eigenvalue analyses are used in a wide variety of engineering, statistical and +other mathematical analyses. + +The package includes two algorithms: Jacobi and Householder. The first is +extremely reliable but much slower than the second. + +The code is adapted from routines in "Handbook for Automatic Computation, Vol +II, Linear Algebra" by Wilkinson and Reinsch, published by Springer Verlag. + + + Jacobi(A,D,S,V); // A, S symmetric; S is workspace, + // S = A is OK; V is a matrix + Jacobi(A,D); // A symmetric + Jacobi(A,D,S); // A, S symmetric; S is workspace, + // S = A is OK + Jacobi(A,D,V); // A symmetric; V is a matrix + + EigenValues(A,D); // A symmetric + EigenValues(A,D,S); // A, S symmetric; S is for back + // transforming, S = A is OK + EigenValues(A,D,V); // A symmetric; V is a matrix + +where 'A', 'S' are of type 'SymmetricMatrix', 'D' is of type 'DiagonalMatrix' +and 'V' is of type 'Matrix'. The values of 'A' are not changed unless 'A' is +also inserted as the third argument. If you need eigenvectors use one of the +forms with matrix 'V'. The eigenvectors are returned as the columns of 'V'. + + + + + 3.21 Sorting + ==== ======= + +To sort the values in a matrix or vector, 'A', (in general this operation +makes sense only for vectors and diagonal matrices) use + + SortAscending(A); + +or + + SortDescending(A); + +I use the quicksort algorithm. The algorithm is similar to that in Sedgewick's +algorithms in C++. If the sort seems to be failing (as quicksort can do) an +exception is thrown. + +You will get incorrect results if you try to sort a band matrix - but why +would you want to sort a band matrix? + + + + 3.22 Fast Fourier transform + ==== ==== ======= ========= + + + FFT(X, Y, F, G); // F=X and G=Y are OK + +where 'X', 'Y', 'F', 'G' are column vectors. 'X' and 'Y' are the real and +imaginary input vectors; 'F' and 'G' are the real and imaginary output +vectors. The lengths of 'X' and 'Y' must be equal and should be the product of +numbers less than about 10 for fast execution. + +The formula is + + n-1 + h[k] = SUM z[j] exp (-2 pi i jk/n) + j=0 + +where 'z[j]' is stored complex and stored in 'X(j+1)' and 'Y(j+1)'. Likewise +'h[k]' is complex and stored in 'F(k+1)' and 'G(k+1)'. The fast Fourier +algorithm takes order n log(n) operations (for "good" values of n) rather than +n**2 that straight evaluation (see the file 'tmtf.cpp') takes. + +I use one of two methods: + +* A program originally written by Sande and Gentleman. This requires that "n" +can be expressed as a product of small numbers.</LI> * A method of Carl de +Boor (1980), "Siam J Sci Stat Comput", pp 173-8. The sines and cosines are +calculated explicitly. This gives better accuracy, at an expense of being a +little slower than is otherwise possible. This is slower than the +Sande-Gentleman program but will work for all "n" --- although it will be very +slow for "bad" values of "n".</LI> + + +Related functions + + FFTI(F, G, X, Y); // X=F and Y=G are OK + RealFFT(X, F, G); + RealFFTI(F, G, X); + +'FFTI' is the inverse transform for 'FFT'. 'RealFFT' is for the case when the +input vector is real, that is 'Y = 0'. I assume the length of 'X', denoted by +n, is even. The program sets the lengths of 'F' and 'G' to n/2 + 1. 'RealFFTI' +is the inverse of 'RealFFT'. + +See also the section on fast trigonometric transforms [3.23]. + + + + + 3.23 Fast trigonometric transforms + ==== ==== ============= ========== + +These are the sin and cosine transforms as defined by Charles Van Loan (1992) +in "Computational frameworks for the fast Fourier transform" published by +SIAM. See page 229. Some other authors use slightly different conventions. All +the functions call the fast Fourier transforms [3.22] and require an even +transform length, denoted by "m" in these notes. As with the FFT "m" should be +the product of numbers less than about 10 for fast execution. + +The functions I define are + + DCT(U,V); // U, V are ColumnVectors, length "m+1" + DCT_inverse(U,V); // inverse of DCT + DST(U,V); // U, V are ColumnVectors, length "m+1" + DST_inverse(U,V); // inverse of DST + DCT_II(U,V); // U, V are ColumnVectors, length "m" + DCT_II_inverse(U,V); // inverse of DCT_II + DST_II(U,V); // U, V are ColumnVectors, length "m" + DST_II_inverse(U,V); // inverse of DST_II + +where 'U' is the input and 'V' is the output. 'V = U' is OK. The length of 'V' +is set by the functions. + +Here are the formulae: + +DCT + + m-1 k + v[k] = u[0]/2 + SUM { u[j] cos (pi jk/m) } + (-) u[m]/2 + j=1 + +for 'k = 0...m', where 'u[j]' and 'v[k]' are stored in 'U(j+1)' and 'V(k+1)'. + +DST + + m-1 + v[k] = SUM { u[j] sin (pi jk/m) } + j=1 + +for 'k = 1...(m-1)', where 'u[j]' and 'v[k]' are stored in 'U(j+1)' and +'V(k+1)'. 'u[0]' and 'u[m]' are ignored and 'v[0]' and 'v[m]' are set to zero. + +DCT_II + + m-1 + v[k] = SUM { u[j] cos (pi (j+1/2)k/m) } + j=0 + +for 'k = 0...(m-1)', where 'u[j]' and 'v[k]' are stored in 'U(j+1)' and +'V(k+1)'. + +DST_II + + m + v[k] = SUM { u[j] sin (pi (j-1/2)k/m) } + j=1 + +for 'k = 1...m', where 'u[j]' and 'v[k]' are stored in 'U(j)' and 'V(k)'. + +Note that the relationship between the subscripts in the formulae and those +used in "newmat" is different for DST_II (and DST_II_inverse). + + + + + 3.24 Interface to Numerical Recipes in C + ==== ========= == ========= ======= == = + +This package can be used with the vectors and matrices defined in "Numerical +Recipes in C". You need to edit the routines in Numerical Recipes so that the +elements are of the same type as used in this package. Eg replace float by +double, vector by dvector and matrix by dmatrix, etc. You may need to edit the +function definitions to use the version acceptable to your compiler (if you +are using the first edition of NRIC). You may need to enclose the code from +Numerical Recipes in 'extern "C" { ... }'. You will also need to include the +matrix and vector utility routines. + +Then any vector in Numerical Recipes with subscripts starting from 1 in a +function call can be accessed by a RowVector, ColumnVector or DiagonalMatrix +in the present package. Similarly any matrix with subscripts starting from 1 +can be accessed by an nricMatrix in the present package. The class +nricMatrix is derived from Matrix and can be used in place of Matrix. In each +case, if you wish to refer to a RowVector, ColumnVector, DiagonalMatrix or +nricMatrix X in an function from Numerical Recipes, use 'X.nric()' in the +function call. + +Numerical Recipes cannot change the dimensions of a matrix or vector. So +matrices or vectors must be correctly dimensioned before a Numerical Recipes +routine is called. + +For example + + SymmetricMatrix B(44); + ..... // load values into B + nricMatrix BX = B; // copy values to an nricMatrix + DiagonalMatrix D(44); // Matrices for output + nricMatrix V(44,44); // correctly dimensioned + int nrot; + jacobi(BX.nric(),44,D.nric(),V.nric(),&nrot); + // jacobi from NRIC + cout << D; // print eigenvalues + + + + + + 3.25 Exceptions + ==== ========== + +Here is the class structure for exceptions: + +Exception + Logic_error + ProgramException miscellaneous matrix error + IndexException index out of bounds + VectorException unable to convert matrix to vector + NotSquareException matrix is not square (invert, solve) + SubMatrixDimensionException out of bounds index of submatrix + IncompatibleDimensionsException (multiply, add etc) + NotDefinedException operation not defined (eg <) + CannotBuildException copying a matrix where copy is undefined + InternalException probably an error in newmat + Runtime_error + NPDException matrix not positive definite (Cholesky) + ConvergenceException no convergence (e-values, non-linear, +sort) + SingularException matrix is singular (invert, solve) + SolutionException no convergence in solution routine + OverflowException floating point overflow + Bad_alloc out of space (new fails) + + +I have attempted to mimic the exception class structure in the C++ standard +library, by defining the Logic_error and Runtime_error classes. + +If there is no catch statement or exceptions are disabled then my +'Terminate()' function in 'myexcept.h' is called. This prints out an error +message, the dimensions and types of the matrices involved, the name of the +routine detecting the exception, and any other information set by the Tracer +[4] class. Also see the section on error messages [4] for additional notes on +the messages generated by the exceptions. + +You can also print this information by printing 'Exception::what()'. + +See the file 'test_exc.cpp' as an example of catching an exception and +printing the error message. + +The 08 version of newmat defined a member function 'void SetAction(int)' to +help customise the action when an exception is called. This has been deleted +in the 09 version. Now include an instruction such as 'cout << +Exception::what() << endl;' in the 'Catch' or 'CatchAll' block to determine +the action. + +The library includes the alternatives of using the inbuilt exceptions provided +by a compiler, simulating exceptions, or disabling exceptions. See customising +[2.3] for selecting the correct exception option. + +The rest of this section describes my partial simulation of exceptions for +compilers which do not support C++ exceptions. I use Carlos Vidal's article in +the September 1992 "C Users Journal" as a starting point. + +Newmat does a partial clean up of memory following throwing an exception - see +the next section. However, the present version will leave a little heap memory +unrecovered under some circumstances. I would not expect this to be a major +problem, but it is something that needs to be sorted out. + +The functions/macros I define are Try, Throw, Catch, CatchAll and +CatchAndThrow. Try, Throw, Catch and CatchAll correspond to try, throw, catch +and catch(...) in the C++ standard. A list of Catch clauses must be terminated +by either CatchAll or CatchAndThrow but not both. Throw takes an Exception as +an argument or takes no argument (for passing on an exception). I do not have +a version of Throw for specifying which exceptions a function might throw. +Catch takes an exception class name as an argument; CatchAll and CatchAndThrow +don't have any arguments. Try, Catch and CatchAll must be followed by blocks +enclosed in curly brackets. + +I have added another macro ReThrow to mean a rethrow, Throw(). This was +necessary to enable the package to be compatible with both my exception +package and C++ exceptions. + +If you want to throw an exception, use a statement like + + Throw(Exception("Error message\n")); + +It is important to have the exception declaration in the Throw statement, +rather than as a separate statement. + +All exception classes must be derived from the class, Exception, defined in +newmat and can contain only static variables. See the examples in newmat if +you want to define additional exceptions. + + + + + 3.26 Cleanup after an exception + ==== ======= ===== == ========= + +This section is about the simulated exceptions used in newmat. It is +irrelevant if you are using the exceptions built into a compiler or have set +the disable-exceptions option. + +The simulated exception mechanisms in newmat are based on the C functions +setjmp and longjmp. These functions do not call destructors so can lead to +garbage being left on the heap. (I refer to memory allocated by "new" as heap +memory). For example, when you call + + Matrix A(20,30); + +a small amount of space is used on the stack containing the row and column +dimensions of the matrix and 600 doubles are allocated on the heap for the +actual values of the matrix. At the end of the block in which A is declared, +the destructor for A is called and the 600 doubles are freed. The locations on +the stack are freed as part of the normal operations of the stack. If you +leave the block using a longjmp command those 600 doubles will not be freed +and will occupy space until the program terminates. + +To overcome this problem newmat keeps a list of all the currently declared +matrices and its exception mechanism will return heap memory when you do a +Throw and Catch. + +However it will not return heap memory from objects from other packages. + +If you want the mechanism to work with another class you will have to do four +things: + +1: derive your class from class Janitor defined in except.h; + +2: define a function 'void CleanUp()' in that class to return all heap +memory; + +3: include the following lines in the class definition + + public: + void* operator new(size_t size) + { do_not_link=true; void* t = ::operator new(size); return t; } + void operator delete(void* t) { ::operator delete(t); } + +4: be sure to include a copy constructor in you class definition, that is, +something like + + X(const X&); + + +Note that the function 'CleanUp()' does somewhat the same duties as the +destructor. However 'CleanUp()' has to do the "cleaning" for the class you are +working with and also the classes it is derived from. So it will often be +wrong to use exactly the same code for both 'CleanUp()' and the destructor or +to define your destructor as a call to 'CleanUp()'. + + + + + 3.27 Non-linear applications + ==== ========== ============ + +Files solution.h, solution.cpp contain a class for solving for x in y = f(x) +where x is a one-dimensional continuous monotonic function. This is not a +matrix thing at all but is included because it is a useful thing and because +it is a simpler version of the technique used in the non-linear least squares. + +Files newmatnl.h, newmatnl.cpp contain a series of classes for non-linear +least squares and maximum likelihood. + +Documentation for both of these is in the definition files. Simple examples +are in sl_ex.cpp, nl_ex.cpp and garch.cpp. + + + + + 3.28 Standard template library + ==== ======== ======== ======= + +The standard template library (STL) is the set of "container templates" +(vector, deque, list etc) defined by the C++ standards committee. Newmat is +intended to be compatible with the STL in the sense that you can store +matrices in the standard containers. I have defined '==' and inequality [3.6] +operators to help make this possible. Probably there will have to be some +other changes. My experiments with the Rogue Wave STL that comes with Borland +C++ 5.0 showed that some things worked and some things unexpectedly didn't +work. In particular, I couldn't get the list container to work. I don't know +whose fault this is. + +If you want to use the container classes with Newmat please note + +* Don't use simulated exceptions. + +* Make sure the option DO_FREE_CHECK [2.3] is *not* turned on. + +* You can store only one type of matrix in a container. If you want to use a +variety of types use the GenericMatrix type or store pointers to the matrices. + +* The vector and deque container templates like to copy their elements. For +the vector container this happens when you insert an element anywhere except +at the end or when you append an element and the current vector storage +overflows. Since Newmat does not have "copy-on-write" this could get very +inefficient. (Later versions may have "copy-on-write" for the GenericMatrix +type). + +* You won't be able to sort the container or do anything that would call an +inequality operator. + + +I doubt whether the STL container will be used often for matrices. So I don't +think these limitations are very critical. If you think otherwise, please tell +me. + + + + + + 3.29 Namespace + ==== ========= + +"Namespace" is a new facility in C++. Its purpose is to avoid name clashes +between different libraries. I have included the namespace capability. +Activate the line '#define use_namespace' in 'include.h'. Then include either +the statement + + using namespace NEWMAT; + +at the beginning of any file that needs to access the newmat library or + + using namespace RBD_LIBRARIES; + +at the beginning of any file that needs to access all my libraries. + +This works correctly with Borland [2.4.2] C++ version 5. + +Microsoft [2.4.5] Visual C++ version 5 works in my example and test files, but +fails with apparently insignificant changes (it may be more reliable if you +have applied service pack 3). If you #include "newmatap.h", but no other +newmat include file, then also #include "newmatio.h". + +My use of namespace does not work with Gnu g++ [2.4.3] version 2.7.2. + +I have defined the following namespaces: + +* RBD_COMMON for functions and classes used by most of my libraries * +NEWMAT for the newmat library * RBD_LIBRARIES for all my libraries + + + + + + 4 Error messages + = ===== ======== + +Most error messages are self-explanatory. The message gives the size of the +matrices involved. Matrix types are referred to by the following codes: + + Matrix or vector Rect + Symmetric matrix Sym + Band matrix Band + Symmetric band matrix SmBnd + Lower triangular matrix LT + Lower triangular band matrix LwBnd + Upper triangular matrix UT + Upper triangular band matrix UpBnd + Diagonal matrix Diag + Crout matrix (LU matrix) Crout + Band LU matrix BndLU + +Other codes should not occur. + +See the section on exceptions [3.25] for more details on the structure of the +exception classes. + +I have defined a class Tracer that is intended to help locate the place where +an error has occurred. At the beginning of a function I suggest you include a +statement like + + Tracer tr("name"); + +where name is the name of the function. This name will be printed as part of +the error message, if an exception occurs in that function, or in a function +called from that function. You can change the name as you proceed through a +function with the ReName function + + tr.ReName("new name"); + +if, for example, you want to track progress through the function. + + + + + 5 Bugs + = ==== + + +* Small memory leaks may occur when an exception is thrown and caught. + +* My exception scheme may not be not properly linked in with the standard +library exceptions. In particular, my scheme may fail to catch out-of-memory +exceptions. + + + + + + + 6 List of files + = ==== == ===== + +Documentation + + README readme file + NEWMAT TXT documentation file + + +Definition files + + BOOLEAN H boolean class definition + CONTROLW H control word definition file + INCLUDE H details of include files and options + MYEXCEPT H general exception handler definitions + NEWMAT H main matrix class definition file + NEWMATAP H applications definition file + NEWMATIO H input/output definition file + NEWMATNL H non-linear optimisation definition file + NEWMATRC H row/column functions definition files + NEWMATRM H rectangular matrix access definition files + PRECISIO H numerical precision constants + SOLUTION H one dimensional solve definition file + + +Program files + + BANDMAT CPP band matrix routines + CHOLESKY CPP Cholesky decomposition + EVALUE CPP eigenvalues and eigenvector calculation + FFT CPP fast Fourier, trig. transforms + HHOLDER CPP QR routines + JACOBI CPP eigenvalues by the Jacobi method + MYEXCEPT CPP general error and exception handler + NEWFFT CPP new fast Fourier transform + NEWMAT1 CPP type manipulation routines + NEWMAT2 CPP row and column manipulation functions + NEWMAT3 CPP row and column access functions + NEWMAT4 CPP constructors, resize, utilities + NEWMAT5 CPP transpose, evaluate, matrix functions + NEWMAT6 CPP operators, element access + NEWMAT7 CPP invert, solve, binary operations + NEWMAT8 CPP LU decomposition, scalar functions + NEWMAT9 CPP output routines + NEWMATEX CPP matrix exception handler + NEWMATNL CPP non-linear optimisation + NEWMATRM CPP rectangular matrix access functions + SORT CPP sorting functions + SOLUTION CPP one dimensional solve + SUBMAT CPP submatrix functions + SVD CPP singular value decomposition + + +Example files + + EXAMPLE CPP example of use of package + EXAMPLE TXT output from example + SL_EX CPP example of OneDimSolve routine + SL_EX TXT output from example + NL_EX CPP example of non-linear least squares + NL_EX TXT output from example + GARCH CPP example of maximum-likelihood fit + GARCH DAT data file for garch.cpp + GARCH TXT output from example + TEST_EXC CPP demonstration exceptions + TEST_EXC TXT output from TEST_EXC.CPP + + +Test files + + TMT* CPP test files + TMT TXT output from the test files + +See the section on testing [2.7] for details of the test files. + +Make files + + GNU MAK make file for Gnu G++ + CC MAK make file for AT&T, Sun and HPUX + MS_NT MAK make file for Microsoft Visual C++ 2 (windows NT) + MS MAK make file for Microsoft Visual C++ 1.51 (DOS) + BC MAK make file for Borland C++ 4.5,5 (large model) + BC32 MAK make file for Borland C++ 4.5,5 (32 bit console model) + WATCOM MAK make file for Watcom 10 + WATCO_NT MAK make file for Watcom 10 (windows NT) + + + + + + 7 Problem report form + = ======= ====== ==== + +Copy and paste this to your editor; fill it out and email to + robertd@netlink.co.nz (don't forget the "d" in robertd). + +But first look in my web page http://webnz.com/robert/ to see if the bug has +already been reported. + + Version: ............... newmat10 beta (26 December 1999) + Your email address: .... + Today's date: .......... + Your machine: .......... + Operating system: ...... + Compiler & version: .... + Compiler options + (eg GUI or console)... + Describe the problem - attach examples if possible: + + + + + + + + + + + + + 8 Notes on the design of the library + = ===== == === ====== == === ======= + + Safety, usability, efficiency 8.1 + Matrix vs array library 8.2 + Design questions 8.3 + Data storage 8.4 + Memory management 8.5 + Evaluation of expressions 8.6 + Explosion in the number of operations 8.7 + Destruction of temporaries 8.8 + A calculus of matrix types 8.9 + Error handling 8.10 + Sparse matrices 8.11 + Complex matrices 8.12 + + +I describe some of the ideas behind this package, some of the decisions that I +needed to make and give some details about the way it works. You don't need to +read this part of the documentation in order to use the package. + +It isn't obvious what is the best way of going about structuring a matrix +package. I don't think you can figure this out with "thought" experiments. +Different people have to try out different approaches. And someone else may +have to figure out which is best. Or, more likely, the ultimate packages will +lift some ideas from each of a variety of trial packages. So, I don't claim my +package is an "ultimate" package, but simply a trial of a number of ideas. The +following pages give some background on these ideas. + + + 8.1 Safety, usability, efficiency + === ======= ========== ========== + +Some general comments + +A library like "newmat" needs to balance "safety", "usability" and +"efficiency". + +By safety, I mean getting the right answer, and not causing crashes or damage +to the computer system. + +By usability, I mean being easy to learn and use, including not being too +complicated, being intuitive, saving the users' time, being nice to use. + +Efficiency means minimising the use of computer memory and time. + +In the early days of computers the emphasis was on efficiency. But computer +power gets cheaper and cheaper, halving in price every 18 months. On the other +hand the unaided human brain is probably not a lot better than it was 100,000 +years ago! So we should expect the balance to shift to put more emphasis on +safety and usability and a little less on efficiency. So I don't mind if my +programs are a little less efficient than programs written in pure C (or +Fortran) if I gain substantially in safety and usability. But I would mind if +they were a lot less efficient. + +Type of use + +Second reason for putting extra emphasis on safety and usability is the way I +and, I suspect, most other users actually use "newmat". Most completed +programs are used only a few times. Some result is required for a client, +paper or thesis. The program is developed and tested, the result is obtained, +and the program archived. Of course bits of the program will be recycled for +the next project. But it may be less usual for the same program to be run over +and over again. So the cost, computer time + people time, is in the +development time and often, much less in the actual time to run the final +program. So good use of people time, especially during development is really +important. This means you need highly usable libraries. + +So if you are dealing with matrices, you want the good interface that I have +tried to provide in "newmat", and, of course, reliable methods underneath it. + +Of course, efficiency is still important. We often want to run the biggest +problem our computer will handle and often a little bigger. The C++ language +almost lets us have both worlds. We can define a reasonably good interface, +and get good efficiency in the use of the computer. + +Levels of access + +We can imagine the "black box" model of a "newmat". Suppose the inside is +hidden but can be accessed by the methods described in the reference [3] +section. Then the interface is reasonably consistent and intuitive. Matrices +can be accessed and manipulated in much the same way as doubles or ints in +regular C. All accesses are checked. It is most unlikely that an incorrect +index will crash the system. In general, users do not need to use pointers, so +one shouldn't get pointers pointing into space. And, hopefully, you will get +simpler code and so less errors. + +There are some exceptions to this. In particular, the C-like subscripts [3.2] +are not checked for validity. They give faster access but with a lower level +of safety. + +Then there is the Store() [3.8] function which takes you to the data array +within a matrix. This takes you right inside the "black box". But this is what +you have to use if you are writing, for example, a new matrix factorisation, +and require fast access to the data array. I have tried to write code to +simplify access to the interior of a rectangular matrix, see file +newmatrm.cpp, but I don't regard this as very successful, as yet, and have not +included it in the documentation. Ideally we should have improved versions of +this code for each of the major types of matrix. But, in reality, most of my +matrix factorisations are written in what is basically the C language with +very little C++. + +So our "box" is not very "black". You have a choice of how far you penetrate. +On the outside you have a good level of safety, but in some cases efficiency +is compromised a little. If you penetrate inside the "box" safety is reduced +but you can get better efficiency. + +Some performance data + +This section looks at the performance on "newmat" for simple sums, comparing +it with pure C code and with a somewhat unintelligent array program. + +The following table lists the time (in seconds) for carrying out the +operations 'X=A+B;', 'X=A+B+C;', 'X=A+B+C+D;', where 'X,A,B,C,D' are of type +ColumnVector, with a variety of programs. I am using Borland C++, version 5 in +32 bit console mode under windows NT 4.0 on a PC with a 150 mhz pentium and +128 mbytes of memory. + + length iters. newmat subs. C C-resz array + + X=A+B + 2000000 2 1.2 3.7 1.2 1.4 3.3 + 200000 20 1.2 3.7 1.2 1.5 3.1 + 20000 200 1.0 3.6 1.0 1.2 2.9 + 2000 2000 1.0 3.6 0.9 0.9 2.2 + 200 20000 0.8 3.0 0.4 0.5 1.9 + 20 200000 5.5 2.9 0.4 0.9 2.8 + 2 2000000 43.9 3.2 1.0 4.2 12.3 + + X=A+B+C + 2000000 2 2.5 4.6 1.6 2.1 32.5 + 200000 20 2.1 4.6 1.6 1.8 6.2 + 20000 200 1.8 4.5 1.5 1.8 5.6 + 2000 2000 1.8 4.4 1.3 1.3 3.9 + 200 20000 2.2 4.3 1.0 0.9 2.3 + 20 200000 8.5 4.3 1.0 1.2 3.0 + 2 2000000 62.5 3.9 1.0 4.4 17.7 + + X=A+B+C+D + 2000000 2 3.7 6.7 2.4 2.8 260.7 + 200000 20 3.7 6.7 2.4 2.5 9.2 + 20000 200 3.4 6.6 2.3 2.9 8.2 + 2000 2000 2.9 6.4 2.0 2.0 5.9 + 200 20000 2.5 5.5 1.0 1.3 4.3 + 20 200000 9.9 5.5 1.0 1.6 4.5 + 2 2000000 76.5 5.8 1.7 5.0 24.9 + +The first column gives the lengths of the arrays, the second the number of +iterations and the remaining columns the total time required in seconds. If +the only thing that consumed time was the double precision addition then the +numbers within each block of the table would be the same. + +The column labelled "newmat" is using the standard "newmat" add. In the next +column the calculation is using the usual C style "for" loop and accessing the +elements using "newmat" subscripts such as 'A(i)'. The column labelled "C" +uses the usual C method: 'while (j--) *x++ = *a++ + *b++;' . The following +column also includes an 'X.ReSize()' in the outer loop to correspond to the +reassignment of memory that "newmat" would do. The final column is the time +taken by a simple array package that makes no attempt to eliminate unnecessary +copying or to recycle temporary memory but does have array definitions of the +basic operators. It does, however, do its sums in blocks of 4 and copies in +blocks of 8 in the same way that "newmat" does. + +Here are my conclusions. + + +* "Newmat" does very badly for length 2 and doesn't do very well for length +20. There is some particularly tortuous code in "newmat" for determining which +sum algorithm to use and I am sure this could be improved. However the "array" +program is also having difficulty with length 2 so it is unlikely that the +problem could be completely eliminated. + +* The "array" program is running into problems for length 2,000,000. This is +because RAM memory is being exhausted. + +* For arrays of length 2000 or longer "newmat" is doing about as well as C +and slightly better than C with resize in the 'X=A+B' table. For the other two +tables it is slower, but not dramatically so. + +* Addition using the "newmat" subscripts, while considerably slower than the +others, is still surprisingly good. + +* The "array" program is more than 2 times slower than "newmat" for lengths +2000 or higher. + +In summary: for the situation considered here, "newmat" is doing very well for +large ColumnVectors, even for sums with several terms, but not so well for +shorter ColumnVectors. + + + 8.2 Matrix vs array library + === ====== == ===== ======= + +The "newmat" library is for the manipulation of matrices, including the +standard operations such as multiplication as understood by numerical +analysts, engineers and mathematicians. + +A matrix is a two dimensional array of numbers. However, very special +operations such as matrix multiplication are defined specifically for +matrices. This means that a "matrix" library, as I understand the term, is +different from a general "array" library. + +I see a matrix package as providing the following + + 1. Evaluation of matrix expressions in a form familiar to scientists and +engineers. For example 'A = B * (C + D.t());'. In particular '*' means matrix +multiply. + + 2. Access to the elements of a matrix; + + 3. Access to submatrices; + + 4. Common elementary matrix functions such as determinant and trace; + + 5. A platform for developing advanced matrix functions such as eigen-value +analysis; + + 6. Good efficiency and storage management; + + 7. Graceful exit from errors. + + It may also provide + + 8. A variety of types of elements (eg real and complex); + + 9. A variety of types of matrices (eg rectangular and symmetric). + +In contrast an array package should provide + + 1'. Arrays can be copied with a single instruction; may have some arithmetic +operations for elementwise combination of arrays, say '+', '-', '*', '/', it +may provide matrix multiplication as a function; + + 2'. High speed access to elements directly and perhaps with iterators; + + 3'. Access to subarrays and rows (and columns?); + + 6'. Good efficiency and storage management; + + 7'. Graceful exit from errors; + + 8'. A wide variety of types of elements (eg int, float, double, string etc); + + 9'. One, two and three dimensional arrays, at least, with starting points of +the indices set by user. + +It may be possible to amalgamate these two sets of requirements to some +extent. However "newmat" is definitely oriented towards the first set. + + + 8.3 Design questions + === ====== ========= + +Even within the bounds set by the requirements of a matrix library there is a +substantial opportunity for variation between what different matrix packages +might provide. It is not possible to build a matrix package that will meet +everyone's requirements. In many cases if you put in one facility, you impose +overheads on everyone using the package. This both in storage required for the +program and in efficiency. Likewise a package that is optimised towards +handling large matrices is likely to become less efficient for very small +matrices where the administration time for the matrix may become significant +compared with the time to carry out the operations. It is better to provide a +variety of packages (hopefully compatible) so that most users can find one +that meets their requirements. This package is intended to be one of these +packages; but not all of them. + +Since my background is in statistical methods, this package is oriented +towards the kinds things you need for statistical analyses. + +Now looking at some specific questions. + +What size of matrices? + +A matrix library may target small matrices (say 3 x 3), or medium sized +matrices, or very large matrices. + +A library targeting very small matrices will seek to minimise administration. +A library for medium sized or very large matrices can spend more time on +administration in order to conserve space or optimise the evaluation of +expressions. A library for very large matrices will need to pay special +attention to storage and numerical properties. This library is designed for +medium sized matrices. This means it is worth introducing some optimisations, +but I don't have to worry about setting up some form of virtual memory. + +Which matrix types? + +As well as the usual rectangular matrices, matrices occuring repeatedly in +numerical calculations are upper and lower triangular matrices, symmetric +matrices and diagonal matrices. This is particularly the case in calculations +involving least squares and eigenvalue calculations. So as a first stage these +were the types I decided to include. + +It is also necessary to have types row vector and column vector. In a "matrix" +package, in contrast to an "array" package, it is necessary to have both these +types since they behave differently in matrix expressions. The vector types +can be derived for the rectangular matrix type, so having them does not +greatly increase the complexity of the package. + +The problem with having several matrix types is the number of versions of the +binary operators one needs. If one has 5 distinct matrix types then a simple +library will need 25 versions of each of the binary operators. In fact, we can +evade this problem, but at the cost of some complexity. + +What element types? + +Ideally we would allow element types double, float, complex and int, at least. +It might be reasonably easy, using templates or equivalent, to provide a +library which could handle a variety of element types. However, as soon as one +starts implementing the binary operators between matrices with different +element types, again one gets an explosion in the number of operations one +needs to consider. At the present time the compilers I deal with are not up to +handling this problem with templates. (Of course, when I started writing +"newmat" there were no templates). But even when the compilers do meet the +specifications of the draft standard, writing a matrix package that allows for +a variety of element types using the template mechanism is going to be very +difficult. I am inclined to use templates in an "array" library but not in a +"matrix" library. + +Hence I decided to implement only one element type. But the user can decide +whether this is float or double. The package assumes elements are of type +Real. The user typedefs Real to float or double. + +It might also be worth including symmetric and triangular matrices with extra +precision elements (double or long double) to be used for storage only and +with a minimum of operations defined. These would be used for accumulating the +results of sums of squares and product matrices or multistage QR +triangularisations. + +Allow matrix expressions + +I want to be able to write matrix expressions the way I would on paper. So if +I want to multiply two matrices and then add the transpose of a third one I +can write something like 'X = A * B + C.t();'. I want this expression to be +evaluated with close to the same efficiency as a hand-coded version. This is +not so much of a problem with expressions including a multiply since the +multiply will dominate the time. However, it is not so easy to achieve with +expressions with just '+' and '-'. + +A second requirement is that temporary matrices generated during the +evaluation of an expression are destroyed as quickly as possible. + +A desirable feature is that a certain amount of "intelligence" be displayed in +the evaluation of an expression. For example, in the expression 'X = A.i() * +B;' where 'i()' denotes inverse, it would be desirable if the inverse wasn't +explicitly calculated. + +Naming convention + +How are classes and public member functions to be named? As a general rule I +have spelt identifiers out in full with individual words being capitalised. +For example "UpperTriangularMatrix". If you don't like this you can #define or +typedef shorter names. This convention means you can select an abbreviation +scheme that makes sense to you. + +Exceptions to the general rule are the functions for transpose and inverse. To +make matrix expressions more like the corresponding mathematical formulae, I +have used the single letter abbreviations, 't()' and 'i()'. + +Row and column index ranges + +In mathematical work matrix subscripts usually start at one. In C, array +subscripts start at zero. In Fortran, they start at one. Possibilities for +this package were to make them start at 0 or 1 or be arbitrary. + +Alternatively one could specify an "index set" for indexing the rows and +columns of a matrix. One would be able to add or multiply matrices only if the +appropriate row and column index sets were identical. + +In fact, I adopted the simpler convention of making the rows and columns of a +matrix be indexed by an integer starting at one, following the traditional +convention. In an earlier version of the package I had them starting at zero, +but even I was getting mixed up when trying to use this earlier package. So I +reverted to the more usual notation and started at 1. + +Element access - method and checking + +We want to be able to use the notation 'A(i,j)' to specify the '(i,j)'-th +element of a matrix. This is the way mathematicians expect to address the +elements of matrices. I consider the notation 'A[i][j]' totally alien. However +I include this as an option to help people converting from C. + +There are two ways of working out the address of 'A(i,j)'. One is using a +"dope" vector which contains the first address of each row. Alternatively you +can calculate the address using the formula appropriate for the structure of +'A'. I use this second approach. It is probably slower, but saves worrying +about an extra bit of storage. + +The other question is whether to check for 'i' and 'j' being in range. I do +carry out this check following years of experience with both systems that do +and systems that don't do this check. I would hope that the routines I supply +with this package will reduce your need to access elements of matrices so +speed of access is not a high priority. + +Use iterators + +Iterators are an alternative way of providing fast access to the elements of +an array or matrix when they are to be accessed sequentially. They need to be +customised for each type of matrix. I have not implemented iterators in this +package, although some iterator like functions are used internally for some +row and column functions. + + + 8.4 Data storage + === ==== ======= + +Structure + +Each matrix object contains the basic information such as the number of rows +and columns and a status variable plus a pointer to the data array which is on +the heap. + +One block or several + +The elements of the matrix are stored as a single array. Alternatives would +have been to store each row as a separate array or a set of adjacent rows as a +separate array. The present solution simplifies the program but limits the +size of matrices in 16 bit PCs that have a 64k byte limit on the size of +arrays (I don't use the 'huge' keyword). The large arrays may also cause +problems for memory management in smaller machines. + +By row or by column or other + +In Fortran two dimensional arrays are stored by column. In most other systems +they are stored by row. I have followed this later convention. This makes it +easier to interface with other packages written in C but harder to interface +with those written in Fortran. This may have been a wrong decision. Most work +on the efficient manipulation of large matrices is being done in Fortran. It +would have been easier to use this work if I had adopted the Fortran +convention. + +An alternative would be to store the elements by mid-sized rectangular blocks. +This might impose less strain on memory management when one needs to access +both rows and columns. + +Storage of symmetric matrices + +Symmetric matrices are stored as lower triangular matrices. The decision was +pretty arbitrary, but it does slightly simplify the Cholesky decomposition +program. + + + + 8.5 Memory management - reference counting or status variable? + === ====== ========== = ========= ======== == ====== ========= + +Consider the instruction + + X = A + B + C; + +To evaluate this a simple program will add 'A' to 'B' putting the total in a +temporary 'T1'. Then it will add 'T1' to 'C' creating another temporary 'T2' +which will be copied into 'X'. 'T1' and 'T2' will sit around till the end of +the execution of the statement and perhaps of the block. It would be faster if +the program recognised that 'T1' was temporary and stored the sum of 'T1' and +'C' back into 'T1' instead of creating 'T2' and then avoided the final copy by +just assigning the contents of 'T1' to 'X' rather than copying. In this case +there will be no temporaries requiring deletion. (More precisely there will be +a header to be deleted but no contents). + +For an instruction like + + X = (A * B) + (C * D); + +we can't easily avoid one temporary being left over, so we would like this +temporary deleted as quickly as possible. + +I provide the functionality for doing all this by attaching a status variable +to each matrix. This indicates if the matrix is temporary so that its memory +is available for recycling or deleting. Any matrix operation checks the status +variables of the matrices it is working with and recycles or deletes any +temporary memory. + +An alternative or additional approach would be to use "reference counting and +delayed copying" - also known as "copy on write". If a program requests a +matrix to be copied, the copy is delayed until an instruction is executed +which modifies the memory of either the original matrix or the copy. If the +original matrix is deleted before either matrix is modified, in effect, the +values of the original matrix are transfered to the copy without any actual +copying taking place. This solves the difficult problem of returning an object +from a function without copying and saves the unnecessary copying in the +previous examples. + +There are downsides to the delayed copying approach. Typically, for delayed +copying one uses a structure like the following: + + + Matrix + | + +------> Array Object + | | + | +------> Data array + | | + | +------- Counter + | + +------ Dimension information + + +where the arrows denote a pointer to a data structure. If one wants to access +the "Data array" one will need to track through two pointers. If one is going +to write, one will have to check whether one needs to copy first. This is not +important when one is going to access the whole array, say, for a add +operation. But if one wants to access just a single element, then it imposes a +significant additional overhead on that operation. Any subscript operation +would need to check whether an update was required - even read since it is +hard for the compiler to tell whether a subscript access is a read or write. + +Some matrix libraries don't bother to do this. So if you write 'A = B;' and +then modify an element of one of 'A' or 'B', then the same element of the +other is also modified. I don't think this is acceptable behaviour. + +Delayed copy does not provide the additional functionality of my approach but +I suppose it would be possible to have both delayed copy and tagging +temporaries. + +My approach does not automatically avoid all copying. In particular, you need +use a special technique to return a matrix from a function without copying. + + + + 8.6 Evaluation of expressions - lazy evaluation + === ========== == =========== = ==== ========== + +Consider the instruction + + X = B - X; + +A simple program will subtract 'X' from 'B', store the result in a temporary +'T1' and copy 'T1' into 'X'. It would be faster if the program recognised that +the result could be stored directly into 'X'. This would happen automatically +if the program could look at the instruction first and mark 'X' as temporary. + +C programmers would expect to avoid the same problem with + + X = X - B; + +by using an operator '-=' + + X -= B; + +However this is an unnatural notation for non C users and it may be nicer to +write 'X = X - B'; and know that the program will carry out the +simplification. + +Another example where this intelligent analysis of an instruction is helpful +is in + + X = A.i() * B; + +where 'i()' denotes inverse. Numerical analysts know it is inefficient to +evaluate this expression by carrying out the inverse operation and then the +multiply. Yet it is a convenient way of writing the instruction. It would be +helpful if the program recognised this expression and carried out the more +appropriate approach. + +I regard this interpretation of 'A.i() * B' as just providing a convenient +notation. The objective is not to correct the errors of people who are unaware +of the inefficiency of 'A.i() * B' if interpreted literally. + +There is a third reason for the two-stage evaluation of expressions and this +is probably the most important one. In C++ it is quite hard to return an +expression from a function such as ('*', '+' etc) without a copy. This is +particularly the case when an assignment ('=') is involved. The mechanism +described here provides one way for avoiding this in matrix expressions. + +To carry out this "intelligent" analysis of an instruction matrix expressions +are evaluated in two stages. In the the first stage a tree representation of +the expression is formed. For example '(A+B)*C' is represented by a tree + +' + * + / \ + + C + / \ + A B ' + +Rather than adding 'A' and 'B' the '+' operator yields an object of a class +"AddedMatrix" which is just a pair of pointers to 'A' and 'B'. Then the '*' +operator yields a "MultipliedMatrix" which is a pair of pointers to the +"AddedMatrix" and 'C'. The tree is examined for any simplifications and then +evaluated recursively. + +Further possibilities not yet included are to recognise 'A.t()*A' and +'A.t()+A' as symmetric or to improve the efficiency of evaluation of +expressions like 'A+B+C', 'A*B*C', 'A*B.t()' ('t()' denotes transpose). + +One of the disadvantages of the two-stage approach is that the types of matrix +expressions are determined at run-time. So the compiler will not detect errors +of the type + + + Matrix M; + DiagonalMatrix D; + ....; + D = M; + + +We don't allow conversions using '=' when information would be lost. Such +errors will be detected when the statement is executed. + + + + 8.7 How to overcome an explosion in number of operations + === === == ======== == ========= == ====== == ========== + +The package attempts to solve the problem of the large number of versions of +the binary operations required when one has a variety of types. + +With "n" types of matrices the binary operations will each require "n"-squared +separate algorithms. Some reduction in the number may be possible by carrying +out conversions. However, the situation rapidly becomes impossible with more +than 4 or 5 types. Doug Lea told me that it was possible to avoid this +problem. I don't know what his solution is. Here's mine. + +Each matrix type includes routines for extracting individual rows or columns. +I assume a row or column consists of a sequence of zeros, a sequence of stored +values and then another sequence of zeros. Only a single algorithm is then +required for each binary operation. The rows can be located very quickly since +most of the matrices are stored row by row. Columns must be copied and so the +access is somewhat slower. As far as possible my algorithms access the +matrices by row. + +There is another approach. Each of the matrix types defined in this package +can be set up so both rows and columns have their elements at equal intervals +provided we are prepared to store the rows and columns in up to three chunks. +With such an approach one could write a single "generic" algorithm for each of +multiply and add. This would be a reasonable alternative to my approach. + +I provide several algorithms for operations like + . If one is adding two +matrices of the same type then there is no need to access the individual rows +or columns and a faster general algorithm is appropriate. + +Generally the method works well. However symmetric matrices are not always +handled very efficiently (yet) since complete rows are not stored explicitly. + +The original version of the package did not use this access by row or column +method and provided the multitude of algorithms for the combination of +different matrix types. The code file length turned out to be just a little +longer than the present one when providing the same facilities with 5 distinct +types of matrices. It would have been very difficult to increase the number of +matrix types in the original version. Apparently 4 to 5 types is about the +break even point for switching to the approach adopted in the present package. + +However it must also be admitted that there is a substantial overhead in the +approach adopted in the present package for small matrices. The test program +developed for the original version of the package takes 30 to 50% longer to +run with the current version (though there may be some other reasons for +this). This is for matrices in the range 6x6 to 10x10. + +To try to improve the situation a little I do provide an ordinary matrix +multiplication routine for the case when all the matrices involved are +rectangular. + + + 8.8 Destruction of temporaries + === =========== == =========== + +Versions before version 5 of newmat did not work correctly with Gnu C++ +(version 5 or earlier). This was because the tree structure used to represent +a matrix expression was set up on the stack. This was fine for AT&T, Borland +and Zortech C++. + +However early version Gnu C++ destroys temporary structures as soon as the +function that accesses them finishes. The other compilers wait until the end +of the current expression or current block. To overcome this problem, there is +now an option to store the temporaries forming the tree structure on the heap +(created with new) and to delete them explicitly. Activate the definition of +TEMPS_DESTROYED_QUICKLY to set this option. + +In fact, I suggest this be the default option as, with it, the package uses +less storage and runs faster. There still exist situations Gnu C++ will go +wrong. These include statements like + + A = X * Matrix(P * Q); + + Real r = (A*B)(3,4); + +Neither of these kinds of statements will occur often in practice. + +Now that the C++ standards committee has said that temporary structures should +not be destroyed before a statement finishes, my policy needs to be +re-evaluated. Probably, I'll return to using the stack, because of the +difficulty of managing exceptions with the heap version. + + + + 8.9 A calculus of matrix types + === = ======== == ====== ===== + +The program needs to be able to work out the class of the result of a matrix +expression. This is to check that a conversion is legal or to determine the +class of an intermediate result. To assist with this, a class MatrixType is +defined. Operators '+', '-', '*', '>=' are defined to calculate the types of +the results of expressions or to check that conversions are legal. + +Early versions of "newmat" stored the types of the results of operations in a +table. So, for example, if you multiplied an UpperTriangularMatrix by a +LowerTriangularMatrix, "newmat" would look up the table and see that the +result was of type Matrix. With this approach the exploding [8.7] number of +operations problem recurred although not as seriously as when code had to be +written for each pair of types. But there was always the suspicion that +somewhere, there was an error in one of those 9x9 tables, that would be very +hard to find. And the problem would get worse as additional matrix types or +operators were included. + +The present version of "newmat" solves the problem by assigning "attributes" +such as "diagonal" or "band" or "upper triangular" to each matrix type. Which +attributes a matrix type has, is stored as bits in an integer. As an example, +the DiagonalMatrix type has the bits corresponding to "diagonal", "symmetric" +and "band" equal to 1. By looking at the attributes of each of the operands of +a binary operator, the program can work out the attributes of the result of +the operation with simple bitwise operations. Hence it can deduce an +appropriate type. The "symmetric" attribute is a minor problem because +"symmetric" * "symmetric" does not yield "symmetric" unless both operands are +"diagonal". But otherwise very simple code can be used to deduce the +attributes of the result of a binary operation. + +Tables of the types resulting from the binary operators are output at the +beginning of the test [2.7] program. + + + + + 8.10 Error handling + ==== ===== ======== + +The library now does have a moderately graceful exit from errors. One can use +either the simulated exceptions or the compiler supported exceptions. When +newmat08 was released (in 1995), compiler exception handling in the compilers +I had access to was unreliable. I recommended you used my simulated +exceptions. Now (in 1997) compiler supported exceptions do seem to work on a +variety of compilers - but not all compilers. + +The approach in the present library, attempting to simulate C++ exceptions, is +not completely satisfactory, but seems a good interim solution for those who +cannot use compiler supported exceptions. People who don't want exceptions in +any shape or form, can set the option to exit the program if an exception is +thrown. + +The exception mechanism cannot clean-up objects explicitly created by new. +This must be explicitly carried out by the package writer or the package user. +I have not yet done this completely with the present package so occasionally a +little garbage may be left behind after an exception. I don't think this is a +big problem, but it is one that needs fixing. + + + + 8.11 Sparse matrices + ==== ====== ======== + +The library does not support sparse matrices. + +For sparse matrices there is going to be some kind of structure vector. It is +going to have to be calculated for the results of expressions in much the same +way that types are calculated. In addition, a whole new set of row and column +operations would have to be written. + +Sparse matrices are important for people solving large sets of differential +equations as well as being important for statistical and operational research +applications. + +But there are packages being developed specifically for sparse matrices and +these might present the best approach, at least where sparse matrices are the +main interest. + + + + + 8.12 Complex matrices + ==== ======= ======== + +The package does not yet support matrices with complex elements. There are at +least two approaches to including these. One is to have matrices with complex +elements. + +This probably means making new versions of the basic row and column operations +for Real*Complex, Complex*Complex, Complex*Real and similarly for + and -. +This would be OK, except that if I also want to do this for sparse matrices, +then when you put these together, the whole thing will get out of hand. + +The alternative is to represent a Complex matrix by a pair of Real matrices. +One probably needs another level of decoding expressions but I think it might +still be simpler than the first approach. But there is going to be a problem +with accessing elements and it does not seem possible to solve this in an +entirely satisfactory way. + +Complex matrices are used extensively by electrical engineers and physicists +and really should be fully supported in a comprehensive package. + +You can simulate most complex operations by representing 'Z = X + iY' by + + / X Y \ + \ -Y X / + +Most matrix operations will simulate the corresponding complex operation, when +applied to this matrix. But, of course, this matrix is twice as big as you +would need with a genuine complex matrix library. + + + + + + diff --git a/Utilities/OSSIM/ossim_core/matrix/newmat1.cpp b/Utilities/OSSIM/ossim_core/matrix/newmat1.cpp new file mode 100644 index 0000000000..c1f81e3130 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/newmat1.cpp @@ -0,0 +1,199 @@ +//$$ newmat1.cpp Matrix type functions + +// Copyright (C) 1991,2,3,4: R B Davies + +//#define WANT_STREAM + +#include "newmat.h" + +#ifdef use_namespace +namespace NEWMAT { +#endif + +#ifdef DO_REPORT +#define REPORT { static ExeCounter ExeCount(__LINE__,1); ++ExeCount; } +#else +#define REPORT {} +#endif + + +/************************* MatrixType functions *****************************/ + + +// Skew needs more work <<<<<<<<< + +// all operations to return MatrixTypes which correspond to valid types +// of matrices. +// Eg: if it has the Diagonal attribute, then it must also have +// Upper, Lower, Band, Square and Symmetric. + + +MatrixType MatrixType::operator*(const MatrixType& mt) const +{ + REPORT + int a = attribute & mt.attribute & ~(Symmetric | Skew); + a |= (a & Diagonal) * 63; // recognise diagonal + return MatrixType(a); +} + +MatrixType MatrixType::SP(const MatrixType& mt) const +// elementwise product +// Lower, Upper, Diag, Band if only one is +// Symmetric, Ones, Valid (and Real) if both are +// Need to include Lower & Upper => Diagonal +// Will need to include both Skew => Symmetric +{ + REPORT + int a = ((attribute | mt.attribute) & ~(Symmetric + Skew + Valid + Ones)) + | (attribute & mt.attribute); + if ((a & Lower) != 0 && (a & Upper) != 0) a |= Diagonal; + if ((attribute & Skew) != 0) + { + if ((mt.attribute & Symmetric) != 0) a |= Skew; + if ((mt.attribute & Skew) != 0) { a &= ~Skew; a |= Symmetric; } + } + else if ((mt.attribute & Skew) != 0 && (attribute & Symmetric) != 0) + a |= Skew; + a |= (a & Diagonal) * 63; // recognise diagonal + return MatrixType(a); +} + +MatrixType MatrixType::KP(const MatrixType& mt) const +// Kronecker product +// Lower, Upper, Diag, Symmetric, Band, Valid if both are +// Band if LHS is band & other is square +// Ones is complicated so leave this out +{ + REPORT + int a = (attribute & mt.attribute) & ~Ones; + if ((attribute & Band) != 0 && (mt.attribute & Square) != 0) + a |= Band; + //int a = ((attribute & mt.attribute) | (attribute & Band)) & ~Ones; + + return MatrixType(a); +} + +MatrixType MatrixType::i() const // type of inverse +{ + REPORT + int a = attribute & ~(Band+LUDeco); + a |= (a & Diagonal) * 63; // recognise diagonal + return MatrixType(a); +} + +MatrixType MatrixType::t() const +// swap lower and upper attributes +// assume Upper is in bit above Lower +{ + REPORT + int a = attribute; + a ^= (((a >> 1) ^ a) & Lower) * 3; + return MatrixType(a); +} + +MatrixType MatrixType::MultRHS() const +{ + REPORT + // remove symmetric attribute unless diagonal + return (attribute >= Dg) ? attribute : (attribute & ~Symmetric); +} + +// this is used for deciding type of multiplication +bool Rectangular(MatrixType a, MatrixType b, MatrixType c) +{ + REPORT + return + ((a.attribute | b.attribute | c.attribute) + & ~(MatrixType::Valid | MatrixType::Square)) == 0; +} + +const char* MatrixType::Value() const +{ +// make a string with the name of matrix with the given attributes + switch (attribute) + { + case Valid: REPORT return "Rect "; + case Valid+Square: REPORT return "Squ "; + case Valid+Symmetric+Square: REPORT return "Sym "; + case Valid+Skew+Square: REPORT return "Skew "; + case Valid+Band+Square: REPORT return "Band "; + case Valid+Symmetric+Band+Square: REPORT return "SmBnd"; + case Valid+Upper+Square: REPORT return "UT "; + case Valid+Diagonal+Symmetric+Band+Upper+Lower+Square: + REPORT return "Diag "; + case Valid+Diagonal+Symmetric+Band+Upper+Lower+Ones+Square: + REPORT return "Ident"; + case Valid+Band+Upper+Square: REPORT return "UpBnd"; + case Valid+Lower+Square: REPORT return "LT "; + case Valid+Band+Lower+Square: REPORT return "LwBnd"; + default: + REPORT + if (!(attribute & Valid)) return "UnSp "; + if (attribute & LUDeco) + return (attribute & Band) ? "BndLU" : "Crout"; + return "?????"; + } +} + + +GeneralMatrix* MatrixType::New(int nr, int nc, BaseMatrix* bm) const +{ +// make a new matrix with the given attributes + + Tracer tr("New"); GeneralMatrix* gm=0; // initialised to keep gnu happy + switch (attribute) + { + case Valid: + REPORT + if (nc==1) { gm = new ColumnVector(nr); break; } + if (nr==1) { gm = new RowVector(nc); break; } + gm = new Matrix(nr, nc); break; + + case Valid+Square: + REPORT + if (nc!=nr) { Throw(NotSquareException()); } + gm = new SquareMatrix(nr); break; + + case Valid+Symmetric+Square: + REPORT gm = new SymmetricMatrix(nr); break; + + case Valid+Band+Square: + { + REPORT + MatrixBandWidth bw = bm->BandWidth(); + gm = new BandMatrix(nr,bw.lower,bw.upper); break; + } + + case Valid+Symmetric+Band+Square: + REPORT gm = new SymmetricBandMatrix(nr,bm->BandWidth().lower); break; + + case Valid+Upper+Square: + REPORT gm = new UpperTriangularMatrix(nr); break; + + case Valid+Diagonal+Symmetric+Band+Upper+Lower+Square: + REPORT gm = new DiagonalMatrix(nr); break; + + case Valid+Band+Upper+Square: + REPORT gm = new UpperBandMatrix(nr,bm->BandWidth().upper); break; + + case Valid+Lower+Square: + REPORT gm = new LowerTriangularMatrix(nr); break; + + case Valid+Band+Lower+Square: + REPORT gm = new LowerBandMatrix(nr,bm->BandWidth().lower); break; + + case Valid+Diagonal+Symmetric+Band+Upper+Lower+Ones+Square: + REPORT gm = new IdentityMatrix(nr); break; + + default: + Throw(ProgramException("Invalid matrix type")); + } + + MatrixErrorNoSpace(gm); gm->Protect(); return gm; +} + + +#ifdef use_namespace +} +#endif + diff --git a/Utilities/OSSIM/ossim_core/matrix/newmat2.cpp b/Utilities/OSSIM/ossim_core/matrix/newmat2.cpp new file mode 100644 index 0000000000..ced949741f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/newmat2.cpp @@ -0,0 +1,641 @@ +//$$ newmat2.cpp Matrix row and column operations + +// Copyright (C) 1991,2,3,4: R B Davies + +#define WANT_MATH + +#include "include.h" + +#include "newmat.h" +#include "newmatrc.h" + +#ifdef use_namespace +namespace NEWMAT { +#endif + + +#ifdef DO_REPORT +#define REPORT { static ExeCounter ExeCount(__LINE__,2); ++ExeCount; } +#else +#define REPORT {} +#endif + +//#define MONITOR(what,storage,store) { cout << what << " " << storage << " at " << (long)store << "\n"; } + +#define MONITOR(what,store,storage) {} + +/************************** Matrix Row/Col functions ************************/ + +void MatrixRowCol::Add(const MatrixRowCol& mrc) +{ + // THIS += mrc + REPORT + int f = mrc.skip; int l = f + mrc.storage; int lx = skip + storage; + if (f < skip) f = skip; if (l > lx) l = lx; l -= f; + if (l<=0) return; + Real* elx=data+(f-skip); Real* el=mrc.data+(f-mrc.skip); + while (l--) *elx++ += *el++; +} + +void MatrixRowCol::AddScaled(const MatrixRowCol& mrc, Real x) +{ + REPORT + // THIS += (mrc * x) + int f = mrc.skip; int l = f + mrc.storage; int lx = skip + storage; + if (f < skip) f = skip; if (l > lx) l = lx; l -= f; + if (l<=0) return; + Real* elx=data+(f-skip); Real* el=mrc.data+(f-mrc.skip); + while (l--) *elx++ += *el++ * x; +} + +void MatrixRowCol::Sub(const MatrixRowCol& mrc) +{ + REPORT + // THIS -= mrc + int f = mrc.skip; int l = f + mrc.storage; int lx = skip + storage; + if (f < skip) f = skip; if (l > lx) l = lx; l -= f; + if (l<=0) return; + Real* elx=data+(f-skip); Real* el=mrc.data+(f-mrc.skip); + while (l--) *elx++ -= *el++; +} + +void MatrixRowCol::Inject(const MatrixRowCol& mrc) +// copy stored elements only +{ + REPORT + int f = mrc.skip; int l = f + mrc.storage; int lx = skip + storage; + if (f < skip) f = skip; if (l > lx) l = lx; l -= f; + if (l<=0) return; + Real* elx=data+(f-skip); Real* ely=mrc.data+(f-mrc.skip); + while (l--) *elx++ = *ely++; +} + +Real DotProd(const MatrixRowCol& mrc1, const MatrixRowCol& mrc2) +{ + REPORT // not accessed + int f = mrc1.skip; int f2 = mrc2.skip; + int l = f + mrc1.storage; int l2 = f2 + mrc2.storage; + if (f < f2) f = f2; if (l > l2) l = l2; l -= f; + if (l<=0) return 0.0; + + Real* el1=mrc1.data+(f-mrc1.skip); Real* el2=mrc2.data+(f-mrc2.skip); + Real sum = 0.0; + while (l--) sum += *el1++ * *el2++; + return sum; +} + +void MatrixRowCol::Add(const MatrixRowCol& mrc1, const MatrixRowCol& mrc2) +{ + // THIS = mrc1 + mrc2 + int f = skip; int l = skip + storage; + int f1 = mrc1.skip; int l1 = f1 + mrc1.storage; + if (f1<f) f1=f; if (l1>l) l1=l; + int f2 = mrc2.skip; int l2 = f2 + mrc2.storage; + if (f2<f) f2=f; if (l2>l) l2=l; + Real* el = data + (f-skip); + Real* el1 = mrc1.data+(f1-mrc1.skip); Real* el2 = mrc2.data+(f2-mrc2.skip); + if (f1<f2) + { + int i = f1-f; while (i--) *el++ = 0.0; + if (l1<=f2) // disjoint + { + REPORT // not accessed + i = l1-f1; while (i--) *el++ = *el1++; + i = f2-l1; while (i--) *el++ = 0.0; + i = l2-f2; while (i--) *el++ = *el2++; + i = l-l2; while (i--) *el++ = 0.0; + } + else + { + i = f2-f1; while (i--) *el++ = *el1++; + if (l1<=l2) + { + REPORT + i = l1-f2; while (i--) *el++ = *el1++ + *el2++; + i = l2-l1; while (i--) *el++ = *el2++; + i = l-l2; while (i--) *el++ = 0.0; + } + else + { + REPORT + i = l2-f2; while (i--) *el++ = *el1++ + *el2++; + i = l1-l2; while (i--) *el++ = *el1++; + i = l-l1; while (i--) *el++ = 0.0; + } + } + } + else + { + int i = f2-f; while (i--) *el++ = 0.0; + if (l2<=f1) // disjoint + { + REPORT // not accessed + i = l2-f2; while (i--) *el++ = *el2++; + i = f1-l2; while (i--) *el++ = 0.0; + i = l1-f1; while (i--) *el++ = *el1++; + i = l-l1; while (i--) *el++ = 0.0; + } + else + { + i = f1-f2; while (i--) *el++ = *el2++; + if (l2<=l1) + { + REPORT + i = l2-f1; while (i--) *el++ = *el1++ + *el2++; + i = l1-l2; while (i--) *el++ = *el1++; + i = l-l1; while (i--) *el++ = 0.0; + } + else + { + REPORT + i = l1-f1; while (i--) *el++ = *el1++ + *el2++; + i = l2-l1; while (i--) *el++ = *el2++; + i = l-l2; while (i--) *el++ = 0.0; + } + } + } +} + +void MatrixRowCol::Sub(const MatrixRowCol& mrc1, const MatrixRowCol& mrc2) +{ + // THIS = mrc1 - mrc2 + int f = skip; int l = skip + storage; + int f1 = mrc1.skip; int l1 = f1 + mrc1.storage; + if (f1<f) f1=f; if (l1>l) l1=l; + int f2 = mrc2.skip; int l2 = f2 + mrc2.storage; + if (f2<f) f2=f; if (l2>l) l2=l; + Real* el = data + (f-skip); + Real* el1 = mrc1.data+(f1-mrc1.skip); Real* el2 = mrc2.data+(f2-mrc2.skip); + if (f1<f2) + { + int i = f1-f; while (i--) *el++ = 0.0; + if (l1<=f2) // disjoint + { + REPORT // not accessed + i = l1-f1; while (i--) *el++ = *el1++; + i = f2-l1; while (i--) *el++ = 0.0; + i = l2-f2; while (i--) *el++ = - *el2++; + i = l-l2; while (i--) *el++ = 0.0; + } + else + { + i = f2-f1; while (i--) *el++ = *el1++; + if (l1<=l2) + { + REPORT + i = l1-f2; while (i--) *el++ = *el1++ - *el2++; + i = l2-l1; while (i--) *el++ = - *el2++; + i = l-l2; while (i--) *el++ = 0.0; + } + else + { + REPORT + i = l2-f2; while (i--) *el++ = *el1++ - *el2++; + i = l1-l2; while (i--) *el++ = *el1++; + i = l-l1; while (i--) *el++ = 0.0; + } + } + } + else + { + int i = f2-f; while (i--) *el++ = 0.0; + if (l2<=f1) // disjoint + { + REPORT // not accessed + i = l2-f2; while (i--) *el++ = - *el2++; + i = f1-l2; while (i--) *el++ = 0.0; + i = l1-f1; while (i--) *el++ = *el1++; + i = l-l1; while (i--) *el++ = 0.0; + } + else + { + i = f1-f2; while (i--) *el++ = - *el2++; + if (l2<=l1) + { + REPORT + i = l2-f1; while (i--) *el++ = *el1++ - *el2++; + i = l1-l2; while (i--) *el++ = *el1++; + i = l-l1; while (i--) *el++ = 0.0; + } + else + { + REPORT + i = l1-f1; while (i--) *el++ = *el1++ - *el2++; + i = l2-l1; while (i--) *el++ = - *el2++; + i = l-l2; while (i--) *el++ = 0.0; + } + } + } +} + + +void MatrixRowCol::Add(const MatrixRowCol& mrc1, Real x) +{ + // THIS = mrc1 + x + REPORT + if (!storage) return; + int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage; + if (f < skip) { f = skip; if (l < f) l = f; } + if (l > lx) { l = lx; if (f > lx) f = lx; } + + Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip); + + int l1 = f-skip; while (l1--) *elx++ = x; + l1 = l-f; while (l1--) *elx++ = *ely++ + x; + lx -= l; while (lx--) *elx++ = x; +} + +void MatrixRowCol::NegAdd(const MatrixRowCol& mrc1, Real x) +{ + // THIS = x - mrc1 + REPORT + if (!storage) return; + int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage; + if (f < skip) { f = skip; if (l < f) l = f; } + if (l > lx) { l = lx; if (f > lx) f = lx; } + + Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip); + + int l1 = f-skip; while (l1--) *elx++ = x; + l1 = l-f; while (l1--) *elx++ = x - *ely++; + lx -= l; while (lx--) *elx++ = x; +} + +void MatrixRowCol::RevSub(const MatrixRowCol& mrc1) +{ + // THIS = mrc - THIS + REPORT + if (!storage) return; + int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage; + if (f < skip) { f = skip; if (l < f) l = f; } + if (l > lx) { l = lx; if (f > lx) f = lx; } + + Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip); + + int l1 = f-skip; while (l1--) { *elx = - *elx; elx++; } + l1 = l-f; while (l1--) { *elx = *ely++ - *elx; elx++; } + lx -= l; while (lx--) { *elx = - *elx; elx++; } +} + +void MatrixRowCol::ConCat(const MatrixRowCol& mrc1, const MatrixRowCol& mrc2) +{ + // THIS = mrc1 | mrc2 + REPORT + int f1 = mrc1.skip; int l1 = f1 + mrc1.storage; int lx = skip + storage; + if (f1 < skip) { f1 = skip; if (l1 < f1) l1 = f1; } + if (l1 > lx) { l1 = lx; if (f1 > lx) f1 = lx; } + + Real* elx = data; + + int i = f1-skip; while (i--) *elx++ =0.0; + i = l1-f1; + if (i) // in case f1 would take ely out of range + { Real* ely = mrc1.data+(f1-mrc1.skip); while (i--) *elx++ = *ely++; } + + int f2 = mrc2.skip; int l2 = f2 + mrc2.storage; i = mrc1.length; + int skipx = l1 - i; lx -= i; // addresses rel to second seg, maybe -ve + if (f2 < skipx) { f2 = skipx; if (l2 < f2) l2 = f2; } + if (l2 > lx) { l2 = lx; if (f2 > lx) f2 = lx; } + + i = f2-skipx; while (i--) *elx++ = 0.0; + i = l2-f2; + if (i) // in case f2 would take ely out of range + { Real* ely = mrc2.data+(f2-mrc2.skip); while (i--) *elx++ = *ely++; } + lx -= l2; while (lx--) *elx++ = 0.0; +} + +void MatrixRowCol::Multiply(const MatrixRowCol& mrc1) +// element by element multiply into +{ + REPORT + if (!storage) return; + int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage; + if (f < skip) { f = skip; if (l < f) l = f; } + if (l > lx) { l = lx; if (f > lx) f = lx; } + + Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip); + + int l1 = f-skip; while (l1--) *elx++ = 0; + l1 = l-f; while (l1--) *elx++ *= *ely++; + lx -= l; while (lx--) *elx++ = 0; +} + +void MatrixRowCol::Multiply(const MatrixRowCol& mrc1, const MatrixRowCol& mrc2) +// element by element multiply +{ + int f = skip; int l = skip + storage; + int f1 = mrc1.skip; int l1 = f1 + mrc1.storage; + if (f1<f) f1=f; if (l1>l) l1=l; + int f2 = mrc2.skip; int l2 = f2 + mrc2.storage; + if (f2<f) f2=f; if (l2>l) l2=l; + Real* el = data + (f-skip); int i; + if (f1<f2) f1 = f2; if (l1>l2) l1 = l2; + if (l1<=f1) { REPORT i = l-f; while (i--) *el++ = 0.0; } // disjoint + else + { + REPORT + Real* el1 = mrc1.data+(f1-mrc1.skip); + Real* el2 = mrc2.data+(f1-mrc2.skip); + i = f1-f ; while (i--) *el++ = 0.0; + i = l1-f1; while (i--) *el++ = *el1++ * *el2++; + i = l-l1; while (i--) *el++ = 0.0; + } +} + +void MatrixRowCol::KP(const MatrixRowCol& mrc1, const MatrixRowCol& mrc2) +// row for Kronecker product +{ + int f = skip; int s = storage; Real* el = data; int i; + + i = mrc1.skip * mrc2.length; + if (i > f) + { + i -= f; f = 0; if (i > s) { i = s; s = 0; } else s -= i; + while (i--) *el++ = 0.0; + if (s == 0) return; + } + else f -= i; + + i = mrc1.storage; Real* el1 = mrc1.data; + int mrc2_skip = mrc2.skip; int mrc2_storage = mrc2.storage; + int mrc2_length = mrc2.length; + int mrc2_remain = mrc2_length - mrc2_skip - mrc2_storage; + while (i--) + { + int j; Real* el2 = mrc2.data; Real vel1 = *el1; + if (f == 0 && mrc2_length <= s) + { + j = mrc2_skip; s -= j; while (j--) *el++ = 0.0; + j = mrc2_storage; s -= j; while (j--) *el++ = vel1 * *el2++; + j = mrc2_remain; s -= j; while (j--) *el++ = 0.0; + } + else if (f >= mrc2_length) f -= mrc2_length; + else + { + j = mrc2_skip; + if (j > f) + { + j -= f; f = 0; if (j > s) { j = s; s = 0; } else s -= j; + while (j--) *el++ = 0.0; + } + else f -= j; + + j = mrc2_storage; + if (j > f) + { + j -= f; el2 += f; f = 0; if (j > s) { j = s; s = 0; } else s -= j; + while (j--) *el++ = vel1 * *el2++; + } + else f -= j; + + j = mrc2_remain; + if (j > f) + { + j -= f; f = 0; if (j > s) { j = s; s = 0; } else s -= j; + while (j--) *el++ = 0.0; + } + else f -= j; + } + if (s == 0) return; + ++el1; + } + + i = (mrc1.length - mrc1.skip - mrc1.storage) * mrc2.length; + if (i > f) + { + i -= f; if (i > s) i = s; + while (i--) *el++ = 0.0; + } +} + + +void MatrixRowCol::Copy(const MatrixRowCol& mrc1) +{ + // THIS = mrc1 + REPORT + if (!storage) return; + int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage; + if (f < skip) { f = skip; if (l < f) l = f; } + if (l > lx) { l = lx; if (f > lx) f = lx; } + + Real* elx = data; Real* ely = 0; + + if (l-f) ely = mrc1.data+(f-mrc1.skip); + + int l1 = f-skip; while (l1--) *elx++ = 0.0; + l1 = l-f; while (l1--) *elx++ = *ely++; + lx -= l; while (lx--) *elx++ = 0.0; +} + +void MatrixRowCol::CopyCheck(const MatrixRowCol& mrc1) +// Throw an exception if this would lead to a loss of data +{ + REPORT + if (!storage) return; + int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage; + if (f < skip || l > lx) Throw(ProgramException("Illegal Conversion")); + + Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip); + + int l1 = f-skip; while (l1--) *elx++ = 0.0; + l1 = l-f; while (l1--) *elx++ = *ely++; + lx -= l; while (lx--) *elx++ = 0.0; +} + +void MatrixRowCol::Check(const MatrixRowCol& mrc1) +// Throw an exception if +=, -=, copy etc would lead to a loss of data +{ + REPORT + int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage; + if (f < skip || l > lx) Throw(ProgramException("Illegal Conversion")); +} + +void MatrixRowCol::Check() +// Throw an exception if +=, -= of constant would lead to a loss of data +// that is: check full row is present +// may not be appropriate for symmetric matrices +{ + REPORT + if (skip!=0 || storage!=length) + Throw(ProgramException("Illegal Conversion")); +} + +void MatrixRowCol::Negate(const MatrixRowCol& mrc1) +{ + // THIS = -mrc1 + REPORT + if (!storage) return; + int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage; + if (f < skip) { f = skip; if (l < f) l = f; } + if (l > lx) { l = lx; if (f > lx) f = lx; } + + Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip); + + int l1 = f-skip; while (l1--) *elx++ = 0.0; + l1 = l-f; while (l1--) *elx++ = - *ely++; + lx -= l; while (lx--) *elx++ = 0.0; +} + +void MatrixRowCol::Multiply(const MatrixRowCol& mrc1, Real s) +{ + // THIS = mrc1 * s + REPORT + if (!storage) return; + int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage; + if (f < skip) { f = skip; if (l < f) l = f; } + if (l > lx) { l = lx; if (f > lx) f = lx; } + + Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip); + + int l1 = f-skip; while (l1--) *elx++ = 0.0; + l1 = l-f; while (l1--) *elx++ = *ely++ * s; + lx -= l; while (lx--) *elx++ = 0.0; +} + +void DiagonalMatrix::Solver(MatrixColX& mrc, const MatrixColX& mrc1) +{ + // mrc = mrc / mrc1 (elementwise) + REPORT + int f = mrc1.skip; int f0 = mrc.skip; + int l = f + mrc1.storage; int lx = f0 + mrc.storage; + if (f < f0) { f = f0; if (l < f) l = f; } + if (l > lx) { l = lx; if (f > lx) f = lx; } + + Real* elx = mrc.data; Real* eld = store+f; + + int l1 = f-f0; while (l1--) *elx++ = 0.0; + l1 = l-f; while (l1--) *elx++ /= *eld++; + lx -= l; while (lx--) *elx++ = 0.0; + // Solver makes sure input and output point to same memory +} + +void IdentityMatrix::Solver(MatrixColX& mrc, const MatrixColX& mrc1) +{ + // mrc = mrc / mrc1 (elementwise) + REPORT + int f = mrc1.skip; int f0 = mrc.skip; + int l = f + mrc1.storage; int lx = f0 + mrc.storage; + if (f < f0) { f = f0; if (l < f) l = f; } + if (l > lx) { l = lx; if (f > lx) f = lx; } + + Real* elx = mrc.data; Real eldv = *store; + + int l1 = f-f0; while (l1--) *elx++ = 0.0; + l1 = l-f; while (l1--) *elx++ /= eldv; + lx -= l; while (lx--) *elx++ = 0.0; + // Solver makes sure input and output point to same memory +} + +void MatrixRowCol::Copy(const Real*& r) +{ + // THIS = *r + REPORT + Real* elx = data; const Real* ely = r+skip; r += length; + int l = storage; while (l--) *elx++ = *ely++; +} + +void MatrixRowCol::Copy(const int*& r) +{ + // THIS = *r + REPORT + Real* elx = data; const int* ely = r+skip; r += length; + int l = storage; while (l--) *elx++ = *ely++; +} + +void MatrixRowCol::Copy(Real r) +{ + // THIS = r + REPORT Real* elx = data; int l = storage; while (l--) *elx++ = r; +} + +void MatrixRowCol::Zero() +{ + // THIS = 0 + REPORT Real* elx = data; int l = storage; while (l--) *elx++ = 0; +} + +void MatrixRowCol::Multiply(Real r) +{ + // THIS *= r + REPORT Real* elx = data; int l = storage; while (l--) *elx++ *= r; +} + +void MatrixRowCol::Add(Real r) +{ + // THIS += r + REPORT + Real* elx = data; int l = storage; while (l--) *elx++ += r; +} + +Real MatrixRowCol::SumAbsoluteValue() +{ + REPORT + Real sum = 0.0; Real* elx = data; int l = storage; + while (l--) sum += fabs(*elx++); + return sum; +} + +// max absolute value of r and elements of row/col +// we use <= or >= in all of these so we are sure of getting +// r reset at least once. +Real MatrixRowCol::MaximumAbsoluteValue1(Real r, int& i) +{ + REPORT + Real* elx = data; int l = storage; int li = -1; + while (l--) { Real f = fabs(*elx++); if (r <= f) { r = f; li = l; } } + i = (li >= 0) ? storage - li + skip : 0; + return r; +} + +// min absolute value of r and elements of row/col +Real MatrixRowCol::MinimumAbsoluteValue1(Real r, int& i) +{ + REPORT + Real* elx = data; int l = storage; int li = -1; + while (l--) { Real f = fabs(*elx++); if (r >= f) { r = f; li = l; } } + i = (li >= 0) ? storage - li + skip : 0; + return r; +} + +// max value of r and elements of row/col +Real MatrixRowCol::Maximum1(Real r, int& i) +{ + REPORT + Real* elx = data; int l = storage; int li = -1; + while (l--) { Real f = *elx++; if (r <= f) { r = f; li = l; } } + i = (li >= 0) ? storage - li + skip : 0; + return r; +} + +// min value of r and elements of row/col +Real MatrixRowCol::Minimum1(Real r, int& i) +{ + REPORT + Real* elx = data; int l = storage; int li = -1; + while (l--) { Real f = *elx++; if (r >= f) { r = f; li = l; } } + i = (li >= 0) ? storage - li + skip : 0; + return r; +} + +Real MatrixRowCol::Sum() +{ + REPORT + Real sum = 0.0; Real* elx = data; int l = storage; + while (l--) sum += *elx++; + return sum; +} + +void MatrixRowCol::SubRowCol(MatrixRowCol& mrc, int skip1, int l1) const +{ + mrc.length = l1; int d = skip - skip1; + if (d<0) { mrc.skip = 0; mrc.data = data - d; } + else { mrc.skip = d; mrc.data = data; } + d = skip + storage - skip1; + d = ((l1 < d) ? l1 : d) - mrc.skip; mrc.storage = (d < 0) ? 0 : d; + mrc.cw = 0; +} + +#ifdef use_namespace +} +#endif + diff --git a/Utilities/OSSIM/ossim_core/matrix/newmat3.cpp b/Utilities/OSSIM/ossim_core/matrix/newmat3.cpp new file mode 100644 index 0000000000..7bc2d4f8a0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/newmat3.cpp @@ -0,0 +1,842 @@ +//$$ newmat3.cpp Matrix get and restore rows and columns + +// Copyright (C) 1991,2,3,4: R B Davies + +//#define WANT_STREAM + +#include "include.h" + +#include "newmat.h" +#include "newmatrc.h" + +#ifdef use_namespace +namespace NEWMAT { +#endif + + +#ifdef DO_REPORT +#define REPORT { static ExeCounter ExeCount(__LINE__,3); ++ExeCount; } +#else +#define REPORT {} +#endif + +//#define MONITOR(what,storage,store) +// { cout << what << " " << storage << " at " << (long)store << "\n"; } + +#define MONITOR(what,store,storage) {} + + +// Control bits codes for GetRow, GetCol, RestoreRow, RestoreCol +// +// LoadOnEntry: +// Load data into MatrixRow or Col dummy array under GetRow or GetCol +// StoreOnExit: +// Restore data to original matrix under RestoreRow or RestoreCol +// DirectPart: +// Load or restore only part directly stored; must be set with StoreOnExit +// Still have decide how to handle this with symmetric +// StoreHere: +// used in columns only - store data at supplied storage address; +// used for GetCol, NextCol & RestoreCol. No need to fill out zeros +// HaveStore: +// dummy array has been assigned (internal use only). + +// For symmetric matrices, treat columns as rows unless StoreHere is set; +// then stick to columns as this will give better performance for doing +// inverses + +// How components are used: + +// Use rows wherever possible in preference to columns + +// Columns without StoreHere are used in in-exact transpose, sum column, +// multiply a column vector, and maybe in future access to column, +// additional multiply functions, add transpose + +// Columns with StoreHere are used in exact transpose (not symmetric matrices +// or vectors, load only) + +// Columns with MatrixColX (Store to full column) are used in inverse and solve + +// Functions required for each matrix class + +// GetRow(MatrixRowCol& mrc) +// GetCol(MatrixRowCol& mrc) +// GetCol(MatrixColX& mrc) +// RestoreRow(MatrixRowCol& mrc) +// RestoreCol(MatrixRowCol& mrc) +// RestoreCol(MatrixColX& mrc) +// NextRow(MatrixRowCol& mrc) +// NextCol(MatrixRowCol& mrc) +// NextCol(MatrixColX& mrc) + +// The Restore routines assume StoreOnExit has already been checked +// Defaults for the Next routines are given below +// Assume cannot have both !DirectPart && StoreHere for MatrixRowCol routines + + +// Default NextRow and NextCol: +// will work as a default but need to override NextRow for efficiency + +void GeneralMatrix::NextRow(MatrixRowCol& mrc) +{ + REPORT + if (+(mrc.cw*StoreOnExit)) { REPORT this->RestoreRow(mrc); } + mrc.rowcol++; + if (mrc.rowcol<nrows) { REPORT this->GetRow(mrc); } + else { REPORT mrc.cw -= StoreOnExit; } +} + +void GeneralMatrix::NextCol(MatrixRowCol& mrc) +{ + REPORT // 423 + if (+(mrc.cw*StoreOnExit)) { REPORT this->RestoreCol(mrc); } + mrc.rowcol++; + if (mrc.rowcol<ncols) { REPORT this->GetCol(mrc); } + else { REPORT mrc.cw -= StoreOnExit; } +} + +void GeneralMatrix::NextCol(MatrixColX& mrc) +{ + REPORT // 423 + if (+(mrc.cw*StoreOnExit)) { REPORT this->RestoreCol(mrc); } + mrc.rowcol++; + if (mrc.rowcol<ncols) { REPORT this->GetCol(mrc); } + else { REPORT mrc.cw -= StoreOnExit; } +} + + +// routines for matrix + +void Matrix::GetRow(MatrixRowCol& mrc) +{ + REPORT + mrc.skip=0; mrc.storage=mrc.length=ncols; mrc.data=store+mrc.rowcol*ncols; +} + + +void Matrix::GetCol(MatrixRowCol& mrc) +{ + REPORT + mrc.skip=0; mrc.storage=mrc.length=nrows; + if ( ncols==1 && !(mrc.cw*StoreHere) ) // ColumnVector + { REPORT mrc.data=store; } + else + { + Real* ColCopy; + if ( !(mrc.cw*(HaveStore+StoreHere)) ) + { + REPORT + ColCopy = new Real [nrows]; MatrixErrorNoSpace(ColCopy); + MONITOR_REAL_NEW("Make (MatGetCol)",nrows,ColCopy) + mrc.data = ColCopy; mrc.cw += HaveStore; + } + else { REPORT ColCopy = mrc.data; } + if (+(mrc.cw*LoadOnEntry)) + { + REPORT + Real* Mstore = store+mrc.rowcol; int i=nrows; + //while (i--) { *ColCopy++ = *Mstore; Mstore+=ncols; } + if (i) for (;;) + { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore+=ncols; } + } + } +} + +void Matrix::GetCol(MatrixColX& mrc) +{ + REPORT + mrc.skip=0; mrc.storage=nrows; mrc.length=nrows; + if (+(mrc.cw*LoadOnEntry)) + { + REPORT Real* ColCopy = mrc.data; + Real* Mstore = store+mrc.rowcol; int i=nrows; + //while (i--) { *ColCopy++ = *Mstore; Mstore+=ncols; } + if (i) for (;;) + { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore+=ncols; } + } +} + +void Matrix::RestoreCol(MatrixRowCol& mrc) +{ + // always check StoreOnExit before calling RestoreCol + REPORT // 429 + if (+(mrc.cw*HaveStore)) + { + REPORT // 426 + Real* Mstore = store+mrc.rowcol; int i=nrows; + Real* Cstore = mrc.data; + // while (i--) { *Mstore = *Cstore++; Mstore+=ncols; } + if (i) for (;;) + { *Mstore = *Cstore++; if (!(--i)) break; Mstore+=ncols; } + } +} + +void Matrix::RestoreCol(MatrixColX& mrc) +{ + REPORT + Real* Mstore = store+mrc.rowcol; int i=nrows; Real* Cstore = mrc.data; + // while (i--) { *Mstore = *Cstore++; Mstore+=ncols; } + if (i) for (;;) + { *Mstore = *Cstore++; if (!(--i)) break; Mstore+=ncols; } +} + +void Matrix::NextRow(MatrixRowCol& mrc) { REPORT mrc.IncrMat(); } // 1808 + +void Matrix::NextCol(MatrixRowCol& mrc) +{ + REPORT // 632 + if (+(mrc.cw*StoreOnExit)) { REPORT RestoreCol(mrc); } + mrc.rowcol++; + if (mrc.rowcol<ncols) + { + if (+(mrc.cw*LoadOnEntry)) + { + REPORT + Real* ColCopy = mrc.data; + Real* Mstore = store+mrc.rowcol; int i=nrows; + //while (i--) { *ColCopy++ = *Mstore; Mstore+=ncols; } + if (i) for (;;) + { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore+=ncols; } + } + } + else { REPORT mrc.cw -= StoreOnExit; } +} + +void Matrix::NextCol(MatrixColX& mrc) +{ + REPORT + if (+(mrc.cw*StoreOnExit)) { REPORT RestoreCol(mrc); } + mrc.rowcol++; + if (mrc.rowcol<ncols) + { + if (+(mrc.cw*LoadOnEntry)) + { + REPORT + Real* ColCopy = mrc.data; + Real* Mstore = store+mrc.rowcol; int i=nrows; + // while (i--) { *ColCopy++ = *Mstore; Mstore+=ncols; } + if (i) for (;;) + { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore+=ncols; } + } + } + else { REPORT mrc.cw -= StoreOnExit; } +} + +// routines for diagonal matrix + +void DiagonalMatrix::GetRow(MatrixRowCol& mrc) +{ + REPORT + mrc.skip=mrc.rowcol; mrc.storage=1; + mrc.data=store+mrc.skip; mrc.length=ncols; +} + +void DiagonalMatrix::GetCol(MatrixRowCol& mrc) +{ + REPORT + mrc.skip=mrc.rowcol; mrc.storage=1; mrc.length=nrows; + if (+(mrc.cw*StoreHere)) // should not happen + Throw(InternalException("DiagonalMatrix::GetCol(MatrixRowCol&)")); + else { REPORT mrc.data=store+mrc.skip; } + // not accessed +} + +void DiagonalMatrix::GetCol(MatrixColX& mrc) +{ + REPORT + mrc.skip=mrc.rowcol; mrc.storage=1; mrc.length=nrows; + mrc.data = mrc.store+mrc.skip; + *(mrc.data)=*(store+mrc.skip); +} + +void DiagonalMatrix::NextRow(MatrixRowCol& mrc) { REPORT mrc.IncrDiag(); } + // 800 + +void DiagonalMatrix::NextCol(MatrixRowCol& mrc) { REPORT mrc.IncrDiag(); } + // not accessed + +void DiagonalMatrix::NextCol(MatrixColX& mrc) +{ + REPORT + if (+(mrc.cw*StoreOnExit)) + { REPORT *(store+mrc.rowcol)=*(mrc.data); } + mrc.IncrDiag(); + int t1 = +(mrc.cw*LoadOnEntry); + if (t1 && mrc.rowcol < ncols) + { REPORT *(mrc.data)=*(store+mrc.rowcol); } +} + +// routines for upper triangular matrix + +void UpperTriangularMatrix::GetRow(MatrixRowCol& mrc) +{ + REPORT + int row = mrc.rowcol; mrc.skip=row; mrc.length=ncols; + mrc.storage=ncols-row; mrc.data=store+(row*(2*ncols-row+1))/2; +} + + +void UpperTriangularMatrix::GetCol(MatrixRowCol& mrc) +{ + REPORT + mrc.skip=0; int i=mrc.rowcol+1; mrc.storage=i; + mrc.length=nrows; Real* ColCopy; + if ( !(mrc.cw*(StoreHere+HaveStore)) ) + { + REPORT // not accessed + ColCopy = new Real [nrows]; MatrixErrorNoSpace(ColCopy); + MONITOR_REAL_NEW("Make (UT GetCol)",nrows,ColCopy) + mrc.data = ColCopy; mrc.cw += HaveStore; + } + else { REPORT ColCopy = mrc.data; } + if (+(mrc.cw*LoadOnEntry)) + { + REPORT + Real* Mstore = store+mrc.rowcol; int j = ncols; + // while (i--) { *ColCopy++ = *Mstore; Mstore += --j; } + if (i) for (;;) + { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += --j; } + } +} + +void UpperTriangularMatrix::GetCol(MatrixColX& mrc) +{ + REPORT + mrc.skip=0; int i=mrc.rowcol+1; mrc.storage=i; + mrc.length=nrows; + if (+(mrc.cw*LoadOnEntry)) + { + REPORT + Real* ColCopy = mrc.data; + Real* Mstore = store+mrc.rowcol; int j = ncols; + // while (i--) { *ColCopy++ = *Mstore; Mstore += --j; } + if (i) for (;;) + { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += --j; } + } +} + +void UpperTriangularMatrix::RestoreCol(MatrixRowCol& mrc) +{ + REPORT + Real* Mstore = store+mrc.rowcol; int i=mrc.rowcol+1; int j = ncols; + Real* Cstore = mrc.data; + // while (i--) { *Mstore = *Cstore++; Mstore += --j; } + if (i) for (;;) + { *Mstore = *Cstore++; if (!(--i)) break; Mstore += --j; } +} + +void UpperTriangularMatrix::NextRow(MatrixRowCol& mrc) { REPORT mrc.IncrUT(); } + // 722 + +// routines for lower triangular matrix + +void LowerTriangularMatrix::GetRow(MatrixRowCol& mrc) +{ + REPORT + int row=mrc.rowcol; mrc.skip=0; mrc.storage=row+1; mrc.length=ncols; + mrc.data=store+(row*(row+1))/2; +} + +void LowerTriangularMatrix::GetCol(MatrixRowCol& mrc) +{ + REPORT + int col=mrc.rowcol; mrc.skip=col; mrc.length=nrows; + int i=nrows-col; mrc.storage=i; Real* ColCopy; + if ( +(mrc.cw*(StoreHere+HaveStore)) ) + { REPORT ColCopy = mrc.data; } + else + { + REPORT // not accessed + ColCopy = new Real [nrows]; MatrixErrorNoSpace(ColCopy); + MONITOR_REAL_NEW("Make (LT GetCol)",nrows,ColCopy) + mrc.cw += HaveStore; mrc.data = ColCopy; + } + + if (+(mrc.cw*LoadOnEntry)) + { + REPORT + Real* Mstore = store+(col*(col+3))/2; + // while (i--) { *ColCopy++ = *Mstore; Mstore += ++col; } + if (i) for (;;) + { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += ++col; } + } +} + +void LowerTriangularMatrix::GetCol(MatrixColX& mrc) +{ + REPORT + int col=mrc.rowcol; mrc.skip=col; mrc.length=nrows; + int i=nrows-col; mrc.storage=i; mrc.data = mrc.store + col; + + if (+(mrc.cw*LoadOnEntry)) + { + REPORT Real* ColCopy = mrc.data; + Real* Mstore = store+(col*(col+3))/2; + // while (i--) { *ColCopy++ = *Mstore; Mstore += ++col; } + if (i) for (;;) + { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += ++col; } + } +} + +void LowerTriangularMatrix::RestoreCol(MatrixRowCol& mrc) +{ + REPORT + int col=mrc.rowcol; Real* Cstore = mrc.data; + Real* Mstore = store+(col*(col+3))/2; int i=nrows-col; + //while (i--) { *Mstore = *Cstore++; Mstore += ++col; } + if (i) for (;;) + { *Mstore = *Cstore++; if (!(--i)) break; Mstore += ++col; } +} + +void LowerTriangularMatrix::NextRow(MatrixRowCol& mrc) { REPORT mrc.IncrLT(); } + //712 + +// routines for symmetric matrix + +void SymmetricMatrix::GetRow(MatrixRowCol& mrc) +{ + REPORT //571 + mrc.skip=0; int row=mrc.rowcol; mrc.length=ncols; + if (+(mrc.cw*DirectPart)) + { REPORT mrc.storage=row+1; mrc.data=store+(row*(row+1))/2; } + else + { + // do not allow StoreOnExit and !DirectPart + if (+(mrc.cw*StoreOnExit)) + Throw(InternalException("SymmetricMatrix::GetRow(MatrixRowCol&)")); + mrc.storage=ncols; Real* RowCopy; + if (!(mrc.cw*HaveStore)) + { + REPORT + RowCopy = new Real [ncols]; MatrixErrorNoSpace(RowCopy); + MONITOR_REAL_NEW("Make (SymGetRow)",ncols,RowCopy) + mrc.cw += HaveStore; mrc.data = RowCopy; + } + else { REPORT RowCopy = mrc.data; } + if (+(mrc.cw*LoadOnEntry)) + { + REPORT // 544 + Real* Mstore = store+(row*(row+1))/2; int i = row; + while (i--) *RowCopy++ = *Mstore++; + i = ncols-row; + // while (i--) { *RowCopy++ = *Mstore; Mstore += ++row; } + if (i) for (;;) + { *RowCopy++ = *Mstore; if (!(--i)) break; Mstore += ++row; } + } + } +} + +void SymmetricMatrix::GetCol(MatrixRowCol& mrc) +{ + // do not allow StoreHere + if (+(mrc.cw*StoreHere)) + Throw(InternalException("SymmetricMatrix::GetCol(MatrixRowCol&)")); + + int col=mrc.rowcol; mrc.length=nrows; + REPORT + mrc.skip=0; + if (+(mrc.cw*DirectPart)) // actually get row ?? + { REPORT mrc.storage=col+1; mrc.data=store+(col*(col+1))/2; } + else + { + // do not allow StoreOnExit and !DirectPart + if (+(mrc.cw*StoreOnExit)) + Throw(InternalException("SymmetricMatrix::GetCol(MatrixRowCol&)")); + + mrc.storage=ncols; Real* ColCopy; + if ( +(mrc.cw*HaveStore)) { REPORT ColCopy = mrc.data; } + else + { + REPORT // not accessed + ColCopy = new Real [ncols]; MatrixErrorNoSpace(ColCopy); + MONITOR_REAL_NEW("Make (SymGetCol)",ncols,ColCopy) + mrc.cw += HaveStore; mrc.data = ColCopy; + } + if (+(mrc.cw*LoadOnEntry)) + { + REPORT + Real* Mstore = store+(col*(col+1))/2; int i = col; + while (i--) *ColCopy++ = *Mstore++; + i = ncols-col; + // while (i--) { *ColCopy++ = *Mstore; Mstore += ++col; } + if (i) for (;;) + { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += ++col; } + } + } +} + +void SymmetricMatrix::GetCol(MatrixColX& mrc) +{ + int col=mrc.rowcol; mrc.length=nrows; + if (+(mrc.cw*DirectPart)) + { + REPORT + mrc.skip=col; int i=nrows-col; mrc.storage=i; + mrc.data = mrc.store+col; + if (+(mrc.cw*LoadOnEntry)) + { + REPORT // not accessed + Real* ColCopy = mrc.data; + Real* Mstore = store+(col*(col+3))/2; + // while (i--) { *ColCopy++ = *Mstore; Mstore += ++col; } + if (i) for (;;) + { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += ++col; } + } + } + else + { + REPORT + // do not allow StoreOnExit and !DirectPart + if (+(mrc.cw*StoreOnExit)) + Throw(InternalException("SymmetricMatrix::GetCol(MatrixColX&)")); + + mrc.skip=0; mrc.storage=ncols; + if (+(mrc.cw*LoadOnEntry)) + { + REPORT + Real* ColCopy = mrc.data; + Real* Mstore = store+(col*(col+1))/2; int i = col; + while (i--) *ColCopy++ = *Mstore++; + i = ncols-col; + // while (i--) { *ColCopy++ = *Mstore; Mstore += ++col; } + if (i) for (;;) + { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += ++col; } + } + } +} + +// Do not need RestoreRow because we do not allow !DirectPart && StoreOnExit + +void SymmetricMatrix::RestoreCol(MatrixColX& mrc) +{ + REPORT + // Really do restore column + int col=mrc.rowcol; Real* Cstore = mrc.data; + Real* Mstore = store+(col*(col+3))/2; int i = nrows-col; + // while (i--) { *Mstore = *Cstore++; Mstore+= ++col; } + if (i) for (;;) + { *Mstore = *Cstore++; if (!(--i)) break; Mstore+= ++col; } + +} + +// routines for row vector + +void RowVector::GetCol(MatrixRowCol& mrc) +{ + REPORT + // do not allow StoreHere + if (+(mrc.cw*StoreHere)) + Throw(InternalException("RowVector::GetCol(MatrixRowCol&)")); + + mrc.skip=0; mrc.storage=1; mrc.length=nrows; mrc.data = store+mrc.rowcol; + +} + +void RowVector::GetCol(MatrixColX& mrc) +{ + REPORT + mrc.skip=0; mrc.storage=1; mrc.length=nrows; + if (mrc.cw >= LoadOnEntry) + { REPORT *(mrc.data) = *(store+mrc.rowcol); } + +} + +void RowVector::NextCol(MatrixRowCol& mrc) +{ REPORT mrc.rowcol++; mrc.data++; } + +void RowVector::NextCol(MatrixColX& mrc) +{ + if (+(mrc.cw*StoreOnExit)) { REPORT *(store+mrc.rowcol)=*(mrc.data); } + + mrc.rowcol++; + if (mrc.rowcol < ncols) + { + if (+(mrc.cw*LoadOnEntry)) { REPORT *(mrc.data)=*(store+mrc.rowcol); } + } + else { REPORT mrc.cw -= StoreOnExit; } +} + +void RowVector::RestoreCol(MatrixColX& mrc) + { REPORT *(store+mrc.rowcol)=*(mrc.data); } // not accessed + + +// routines for band matrices + +void BandMatrix::GetRow(MatrixRowCol& mrc) +{ + REPORT + int r = mrc.rowcol; int w = lower+1+upper; mrc.length=ncols; + int s = r-lower; + if (s<0) { mrc.data = store+(r*w-s); w += s; s = 0; } + else mrc.data = store+r*w; + mrc.skip = s; s += w-ncols; if (s>0) w -= s; mrc.storage = w; +} + +// should make special versions of this for upper and lower band matrices + +void BandMatrix::NextRow(MatrixRowCol& mrc) +{ + REPORT + int r = ++mrc.rowcol; + if (r<=lower) { mrc.storage++; mrc.data += lower+upper; } + else { mrc.skip++; mrc.data += lower+upper+1; } + if (r>=ncols-upper) mrc.storage--; +} + +void BandMatrix::GetCol(MatrixRowCol& mrc) +{ + REPORT + int c = mrc.rowcol; int n = lower+upper; int w = n+1; + mrc.length=nrows; Real* ColCopy; + int b; int s = c-upper; + if (s<=0) { w += s; s = 0; b = c+lower; } else b = s*w+n; + mrc.skip = s; s += w-nrows; if (s>0) w -= s; mrc.storage = w; + if ( +(mrc.cw*(StoreHere+HaveStore)) ) + { REPORT ColCopy = mrc.data; } + else + { + REPORT + ColCopy = new Real [n+1]; MatrixErrorNoSpace(ColCopy); + MONITOR_REAL_NEW("Make (BMGetCol)",n+1,ColCopy) + mrc.cw += HaveStore; mrc.data = ColCopy; + } + + if (+(mrc.cw*LoadOnEntry)) + { + REPORT + Real* Mstore = store+b; + // while (w--) { *ColCopy++ = *Mstore; Mstore+=n; } + if (w) for (;;) + { *ColCopy++ = *Mstore; if (!(--w)) break; Mstore+=n; } + } +} + +void BandMatrix::GetCol(MatrixColX& mrc) +{ + REPORT + int c = mrc.rowcol; int n = lower+upper; int w = n+1; + mrc.length=nrows; int b; int s = c-upper; + if (s<=0) { w += s; s = 0; b = c+lower; } else b = s*w+n; + mrc.skip = s; s += w-nrows; if (s>0) w -= s; mrc.storage = w; + mrc.data = mrc.store+mrc.skip; + + if (+(mrc.cw*LoadOnEntry)) + { + REPORT + Real* ColCopy = mrc.data; Real* Mstore = store+b; + // while (w--) { *ColCopy++ = *Mstore; Mstore+=n; } + if (w) for (;;) + { *ColCopy++ = *Mstore; if (!(--w)) break; Mstore+=n; } + } +} + +void BandMatrix::RestoreCol(MatrixRowCol& mrc) +{ + REPORT + int c = mrc.rowcol; int n = lower+upper; int s = c-upper; + Real* Mstore = store + ((s<=0) ? c+lower : s*n+s+n); + Real* Cstore = mrc.data; + int w = mrc.storage; + // while (w--) { *Mstore = *Cstore++; Mstore += n; } + if (w) for (;;) + { *Mstore = *Cstore++; if (!(--w)) break; Mstore += n; } +} + +// routines for symmetric band matrix + +void SymmetricBandMatrix::GetRow(MatrixRowCol& mrc) +{ + REPORT + int r=mrc.rowcol; int s = r-lower; int w1 = lower+1; int o = r*w1; + mrc.length = ncols; + if (s<0) { w1 += s; o -= s; s = 0; } + mrc.skip = s; + + if (+(mrc.cw*DirectPart)) + { REPORT mrc.data = store+o; mrc.storage = w1; } + else + { + // do not allow StoreOnExit and !DirectPart + if (+(mrc.cw*StoreOnExit)) + Throw(InternalException("SymmetricBandMatrix::GetRow(MatrixRowCol&)")); + int w = w1+lower; s += w-ncols; Real* RowCopy; + if (s>0) w -= s; mrc.storage = w; int w2 = w-w1; + if (!(mrc.cw*HaveStore)) + { + REPORT + RowCopy = new Real [2*lower+1]; MatrixErrorNoSpace(RowCopy); + MONITOR_REAL_NEW("Make (SmBGetRow)",2*lower+1,RowCopy) + mrc.cw += HaveStore; mrc.data = RowCopy; + } + else { REPORT RowCopy = mrc.data; } + + if (+(mrc.cw*LoadOnEntry)) + { + REPORT + Real* Mstore = store+o; + while (w1--) *RowCopy++ = *Mstore++; + Mstore--; + while (w2--) { Mstore += lower; *RowCopy++ = *Mstore; } + } + } +} + +void SymmetricBandMatrix::GetCol(MatrixRowCol& mrc) +{ + // do not allow StoreHere + if (+(mrc.cw*StoreHere)) + Throw(InternalException("SymmetricBandMatrix::GetCol(MatrixRowCol&)")); + + int c=mrc.rowcol; int w1 = lower+1; mrc.length=nrows; + REPORT + int s = c-lower; int o = c*w1; + if (s<0) { w1 += s; o -= s; s = 0; } + mrc.skip = s; + + if (+(mrc.cw*DirectPart)) + { REPORT mrc.data = store+o; mrc.storage = w1; } + else + { + // do not allow StoreOnExit and !DirectPart + if (+(mrc.cw*StoreOnExit)) + Throw(InternalException("SymmetricBandMatrix::GetCol(MatrixRowCol&)")); + int w = w1+lower; s += w-ncols; Real* ColCopy; + if (s>0) w -= s; mrc.storage = w; int w2 = w-w1; + + if ( +(mrc.cw*HaveStore) ) { REPORT ColCopy = mrc.data; } + else + { + REPORT ColCopy = new Real [2*lower+1]; MatrixErrorNoSpace(ColCopy); + MONITOR_REAL_NEW("Make (SmBGetCol)",2*lower+1,ColCopy) + mrc.cw += HaveStore; mrc.data = ColCopy; + } + + if (+(mrc.cw*LoadOnEntry)) + { + REPORT + Real* Mstore = store+o; + while (w1--) *ColCopy++ = *Mstore++; + Mstore--; + while (w2--) { Mstore += lower; *ColCopy++ = *Mstore; } + } + } +} + +void SymmetricBandMatrix::GetCol(MatrixColX& mrc) +{ + int c=mrc.rowcol; int w1 = lower+1; mrc.length=nrows; + if (+(mrc.cw*DirectPart)) + { + REPORT + int b = c*w1+lower; + mrc.skip = c; c += w1-nrows; w1 -= c; mrc.storage = w1; + Real* ColCopy = mrc.data = mrc.store+mrc.skip; + if (+(mrc.cw*LoadOnEntry)) + { + REPORT + Real* Mstore = store+b; + // while (w1--) { *ColCopy++ = *Mstore; Mstore += lower; } + if (w1) for (;;) + { *ColCopy++ = *Mstore; if (!(--w1)) break; Mstore += lower; } + } + } + else + { + REPORT + // do not allow StoreOnExit and !DirectPart + if (+(mrc.cw*StoreOnExit)) + Throw(InternalException("SymmetricBandMatrix::GetCol(MatrixColX&)")); + int s = c-lower; int o = c*w1; + if (s<0) { w1 += s; o -= s; s = 0; } + mrc.skip = s; + + int w = w1+lower; s += w-ncols; + if (s>0) w -= s; mrc.storage = w; int w2 = w-w1; + + Real* ColCopy = mrc.data = mrc.store+mrc.skip; + + if (+(mrc.cw*LoadOnEntry)) + { + REPORT + Real* Mstore = store+o; + while (w1--) *ColCopy++ = *Mstore++; + Mstore--; + while (w2--) { Mstore += lower; *ColCopy++ = *Mstore; } + } + + } +} + +void SymmetricBandMatrix::RestoreCol(MatrixColX& mrc) +{ + REPORT + int c = mrc.rowcol; + Real* Mstore = store + c*lower+c+lower; + Real* Cstore = mrc.data; int w = mrc.storage; + // while (w--) { *Mstore = *Cstore++; Mstore += lower; } + if (w) for (;;) + { *Mstore = *Cstore++; if (!(--w)) break; Mstore += lower; } +} + +// routines for identity matrix + +void IdentityMatrix::GetRow(MatrixRowCol& mrc) +{ + REPORT + mrc.skip=mrc.rowcol; mrc.storage=1; mrc.data=store; mrc.length=ncols; +} + +void IdentityMatrix::GetCol(MatrixRowCol& mrc) +{ + REPORT + mrc.skip=mrc.rowcol; mrc.storage=1; mrc.length=nrows; + if (+(mrc.cw*StoreHere)) // should not happen + Throw(InternalException("IdentityMatrix::GetCol(MatrixRowCol&)")); + else { REPORT mrc.data=store; } +} + +void IdentityMatrix::GetCol(MatrixColX& mrc) +{ + REPORT + mrc.skip=mrc.rowcol; mrc.storage=1; mrc.length=nrows; + mrc.data = mrc.store+mrc.skip; *(mrc.data)=*store; +} + +void IdentityMatrix::NextRow(MatrixRowCol& mrc) { REPORT mrc.IncrId(); } + +void IdentityMatrix::NextCol(MatrixRowCol& mrc) { REPORT mrc.IncrId(); } + +void IdentityMatrix::NextCol(MatrixColX& mrc) +{ + REPORT + if (+(mrc.cw*StoreOnExit)) { REPORT *store=*(mrc.data); } + mrc.IncrDiag(); // must increase mrc.data so need IncrDiag + int t1 = +(mrc.cw*LoadOnEntry); + if (t1 && mrc.rowcol < ncols) { REPORT *(mrc.data)=*store; } +} + + + + +// *************************** destructors ******************************* + +MatrixRowCol::~MatrixRowCol() +{ + if (+(cw*HaveStore)) + { + MONITOR_REAL_DELETE("Free (RowCol)",-1,data) // do not know length + delete [] data; + } +} + +MatrixRow::~MatrixRow() { if (+(cw*StoreOnExit)) gm->RestoreRow(*this); } + +MatrixCol::~MatrixCol() { if (+(cw*StoreOnExit)) gm->RestoreCol(*this); } + +MatrixColX::~MatrixColX() { if (+(cw*StoreOnExit)) gm->RestoreCol(*this); } + +#ifdef use_namespace +} +#endif + diff --git a/Utilities/OSSIM/ossim_core/matrix/newmat4.cpp b/Utilities/OSSIM/ossim_core/matrix/newmat4.cpp new file mode 100644 index 0000000000..bcde93a50d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/newmat4.cpp @@ -0,0 +1,1027 @@ +//$$ newmat4.cpp Constructors, ReSize, basic utilities + +// Copyright (C) 1991,2,3,4,8,9: R B Davies + +#include "include.h" + +#include "newmat.h" +#include "newmatrc.h" + +#ifdef use_namespace +namespace NEWMAT { +#endif + + + +#ifdef DO_REPORT +#define REPORT { static ExeCounter ExeCount(__LINE__,4); ++ExeCount; } +#else +#define REPORT {} +#endif + + +#define DO_SEARCH // search for LHS of = in RHS + +// ************************* general utilities *************************/ + +static int tristore(int n) // elements in triangular matrix +{ return (n*(n+1))/2; } + + +// **************************** constructors ***************************/ + +GeneralMatrix::GeneralMatrix() +{ store=0; storage=0; nrows=0; ncols=0; tag=-1; } + +GeneralMatrix::GeneralMatrix(ArrayLengthSpecifier s) +{ + REPORT + storage=s.Value(); tag=-1; + if (storage) + { + store = new Real [storage]; MatrixErrorNoSpace(store); + MONITOR_REAL_NEW("Make (GenMatrix)",storage,store) + } + else store = 0; +} + +Matrix::Matrix(int m, int n) : GeneralMatrix(m*n) +{ REPORT nrows=m; ncols=n; } + +SquareMatrix::SquareMatrix(ArrayLengthSpecifier n) + : Matrix(n.Value(),n.Value()) +{ REPORT } + +SymmetricMatrix::SymmetricMatrix(ArrayLengthSpecifier n) + : GeneralMatrix(tristore(n.Value())) +{ REPORT nrows=n.Value(); ncols=n.Value(); } + +UpperTriangularMatrix::UpperTriangularMatrix(ArrayLengthSpecifier n) + : GeneralMatrix(tristore(n.Value())) +{ REPORT nrows=n.Value(); ncols=n.Value(); } + +LowerTriangularMatrix::LowerTriangularMatrix(ArrayLengthSpecifier n) + : GeneralMatrix(tristore(n.Value())) +{ REPORT nrows=n.Value(); ncols=n.Value(); } + +DiagonalMatrix::DiagonalMatrix(ArrayLengthSpecifier m) : GeneralMatrix(m) +{ REPORT nrows=m.Value(); ncols=m.Value(); } + +Matrix::Matrix(const BaseMatrix& M) +{ + REPORT // CheckConversion(M); + // MatrixConversionCheck mcc; + GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::Rt); + GetMatrix(gmx); +} + +SquareMatrix::SquareMatrix(const BaseMatrix& M) : Matrix(M) +{ + REPORT + if (ncols != nrows) + { + Tracer tr("SquareMatrix"); + Throw(NotSquareException(*this)); + } +} + + +SquareMatrix::SquareMatrix(const Matrix& gm) +{ + REPORT + if (gm.ncols != gm.nrows) + { + Tracer tr("SquareMatrix(Matrix)"); + Throw(NotSquareException(gm)); + } + GetMatrix(&gm); +} + + +RowVector::RowVector(const BaseMatrix& M) : Matrix(M) +{ + REPORT + if (nrows!=1) + { + Tracer tr("RowVector"); + Throw(VectorException(*this)); + } +} + +ColumnVector::ColumnVector(const BaseMatrix& M) : Matrix(M) +{ + REPORT + if (ncols!=1) + { + Tracer tr("ColumnVector"); + Throw(VectorException(*this)); + } +} + +SymmetricMatrix::SymmetricMatrix(const BaseMatrix& M) +{ + REPORT // CheckConversion(M); + // MatrixConversionCheck mcc; + GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::Sm); + GetMatrix(gmx); +} + +UpperTriangularMatrix::UpperTriangularMatrix(const BaseMatrix& M) +{ + REPORT // CheckConversion(M); + // MatrixConversionCheck mcc; + GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::UT); + GetMatrix(gmx); +} + +LowerTriangularMatrix::LowerTriangularMatrix(const BaseMatrix& M) +{ + REPORT // CheckConversion(M); + // MatrixConversionCheck mcc; + GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::LT); + GetMatrix(gmx); +} + +DiagonalMatrix::DiagonalMatrix(const BaseMatrix& M) +{ + REPORT //CheckConversion(M); + // MatrixConversionCheck mcc; + GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::Dg); + GetMatrix(gmx); +} + +IdentityMatrix::IdentityMatrix(const BaseMatrix& M) +{ + REPORT //CheckConversion(M); + // MatrixConversionCheck mcc; + GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::Id); + GetMatrix(gmx); +} + +GeneralMatrix::~GeneralMatrix() +{ + if (store) + { + MONITOR_REAL_DELETE("Free (GenMatrix)",storage,store) + delete [] store; + } +} + +CroutMatrix::CroutMatrix(const BaseMatrix& m) +{ + REPORT + Tracer tr("CroutMatrix"); + indx = 0; // in case of exception at next line + GeneralMatrix* gm = ((BaseMatrix&)m).Evaluate(MatrixType::Rt); + GetMatrix(gm); + if (nrows!=ncols) { CleanUp(); Throw(NotSquareException(*gm)); } + d=true; sing=false; + indx=new int [nrows]; MatrixErrorNoSpace(indx); + MONITOR_INT_NEW("Index (CroutMat)",nrows,indx) + ludcmp(); +} + +CroutMatrix::~CroutMatrix() +{ + MONITOR_INT_DELETE("Index (CroutMat)",nrows,indx) + delete [] indx; +} + +//ReturnMatrix::ReturnMatrix(GeneralMatrix& gmx) +//{ +// REPORT +// gm = gmx.Image(); gm->ReleaseAndDelete(); +//} + + +GeneralMatrix::operator ReturnMatrix() const +{ + REPORT + GeneralMatrix* gm = Image(); gm->ReleaseAndDelete(); + return ReturnMatrix(gm); +} + + + +ReturnMatrix GeneralMatrix::ForReturn() const +{ + REPORT + GeneralMatrix* gm = Image(); gm->ReleaseAndDelete(); + return ReturnMatrix(gm); +} + + +// ************************** ReSize matrices ***************************/ + +void GeneralMatrix::ReSize(int nr, int nc, int s) +{ + REPORT + if (store) + { + MONITOR_REAL_DELETE("Free (ReDimensi)",storage,store) + delete [] store; + } + storage=s; nrows=nr; ncols=nc; tag=-1; + if (s) + { + store = new Real [storage]; MatrixErrorNoSpace(store); + MONITOR_REAL_NEW("Make (ReDimensi)",storage,store) + } + else store = 0; +} + +void Matrix::ReSize(int nr, int nc) +{ REPORT GeneralMatrix::ReSize(nr,nc,nr*nc); } + +void SquareMatrix::ReSize(int n) +{ REPORT GeneralMatrix::ReSize(n,n,n*n); } + +void SquareMatrix::ReSize(int nr, int nc) +{ + REPORT + Tracer tr("SquareMatrix::ReSize"); + if (nc != nr) Throw(NotSquareException(*this)); + GeneralMatrix::ReSize(nr,nc,nr*nc); +} + +void SymmetricMatrix::ReSize(int nr) +{ REPORT GeneralMatrix::ReSize(nr,nr,tristore(nr)); } + +void UpperTriangularMatrix::ReSize(int nr) +{ REPORT GeneralMatrix::ReSize(nr,nr,tristore(nr)); } + +void LowerTriangularMatrix::ReSize(int nr) +{ REPORT GeneralMatrix::ReSize(nr,nr,tristore(nr)); } + +void DiagonalMatrix::ReSize(int nr) +{ REPORT GeneralMatrix::ReSize(nr,nr,nr); } + +void RowVector::ReSize(int nc) +{ REPORT GeneralMatrix::ReSize(1,nc,nc); } + +void ColumnVector::ReSize(int nr) +{ REPORT GeneralMatrix::ReSize(nr,1,nr); } + +void RowVector::ReSize(int nr, int nc) +{ + Tracer tr("RowVector::ReSize"); + if (nr != 1) Throw(VectorException(*this)); + REPORT GeneralMatrix::ReSize(1,nc,nc); +} + +void ColumnVector::ReSize(int nr, int nc) +{ + Tracer tr("ColumnVector::ReSize"); + if (nc != 1) Throw(VectorException(*this)); + REPORT GeneralMatrix::ReSize(nr,1,nr); +} + +void IdentityMatrix::ReSize(int nr) +{ REPORT GeneralMatrix::ReSize(nr,nr,1); *store = 1; } + + +void Matrix::ReSize(const GeneralMatrix& A) +{ REPORT ReSize(A.Nrows(), A.Ncols()); } + +void SquareMatrix::ReSize(const GeneralMatrix& A) +{ + REPORT + int n = A.Nrows(); + if (n != A.Ncols()) + { + Tracer tr("SquareMatrix::ReSize(GM)"); + Throw(NotSquareException(*this)); + } + ReSize(n); +} + +void nricMatrix::ReSize(const GeneralMatrix& A) +{ REPORT ReSize(A.Nrows(), A.Ncols()); } + +void ColumnVector::ReSize(const GeneralMatrix& A) +{ REPORT ReSize(A.Nrows(), A.Ncols()); } + +void RowVector::ReSize(const GeneralMatrix& A) +{ REPORT ReSize(A.Nrows(), A.Ncols()); } + +void SymmetricMatrix::ReSize(const GeneralMatrix& A) +{ + REPORT + int n = A.Nrows(); + if (n != A.Ncols()) + { + Tracer tr("SymmetricMatrix::ReSize(GM)"); + Throw(NotSquareException(*this)); + } + ReSize(n); +} + +void DiagonalMatrix::ReSize(const GeneralMatrix& A) +{ + REPORT + int n = A.Nrows(); + if (n != A.Ncols()) + { + Tracer tr("DiagonalMatrix::ReSize(GM)"); + Throw(NotSquareException(*this)); + } + ReSize(n); +} + +void UpperTriangularMatrix::ReSize(const GeneralMatrix& A) +{ + REPORT + int n = A.Nrows(); + if (n != A.Ncols()) + { + Tracer tr("UpperTriangularMatrix::ReSize(GM)"); + Throw(NotSquareException(*this)); + } + ReSize(n); +} + +void LowerTriangularMatrix::ReSize(const GeneralMatrix& A) +{ + REPORT + int n = A.Nrows(); + if (n != A.Ncols()) + { + Tracer tr("LowerTriangularMatrix::ReSize(GM)"); + Throw(NotSquareException(*this)); + } + ReSize(n); +} + +void IdentityMatrix::ReSize(const GeneralMatrix& A) +{ + REPORT + int n = A.Nrows(); + if (n != A.Ncols()) + { + Tracer tr("IdentityMatrix::ReSize(GM)"); + Throw(NotSquareException(*this)); + } + ReSize(n); +} + +void GeneralMatrix::ReSize(const GeneralMatrix&) +{ + REPORT + Tracer tr("GeneralMatrix::ReSize(GM)"); + Throw(NotDefinedException("ReSize", "this type of matrix")); +} + +void GeneralMatrix::ReSizeForAdd(const GeneralMatrix& A, const GeneralMatrix&) +{ REPORT ReSize(A); } + +void GeneralMatrix::ReSizeForSP(const GeneralMatrix& A, const GeneralMatrix&) +{ REPORT ReSize(A); } + + +// ************************* SameStorageType ******************************/ + +// SameStorageType checks A and B have same storage type including bandwidth +// It does not check same dimensions since we assume this is already done + +bool GeneralMatrix::SameStorageType(const GeneralMatrix& A) const +{ + REPORT + return Type() == A.Type(); +} + + +// ******************* manipulate types, storage **************************/ + +int GeneralMatrix::search(const BaseMatrix* s) const +{ REPORT return (s==this) ? 1 : 0; } + +int GenericMatrix::search(const BaseMatrix* s) const +{ REPORT return gm->search(s); } + +int MultipliedMatrix::search(const BaseMatrix* s) const +{ REPORT return bm1->search(s) + bm2->search(s); } + +int ShiftedMatrix::search(const BaseMatrix* s) const +{ REPORT return bm->search(s); } + +int NegatedMatrix::search(const BaseMatrix* s) const +{ REPORT return bm->search(s); } + +int ReturnMatrix::search(const BaseMatrix* s) const +{ REPORT return (s==gm) ? 1 : 0; } + +MatrixType Matrix::Type() const { return MatrixType::Rt; } +MatrixType SquareMatrix::Type() const { return MatrixType::Sq; } +MatrixType SymmetricMatrix::Type() const { return MatrixType::Sm; } +MatrixType UpperTriangularMatrix::Type() const { return MatrixType::UT; } +MatrixType LowerTriangularMatrix::Type() const { return MatrixType::LT; } +MatrixType DiagonalMatrix::Type() const { return MatrixType::Dg; } +MatrixType RowVector::Type() const { return MatrixType::RV; } +MatrixType ColumnVector::Type() const { return MatrixType::CV; } +MatrixType CroutMatrix::Type() const { return MatrixType::Ct; } +MatrixType BandMatrix::Type() const { return MatrixType::BM; } +MatrixType UpperBandMatrix::Type() const { return MatrixType::UB; } +MatrixType LowerBandMatrix::Type() const { return MatrixType::LB; } +MatrixType SymmetricBandMatrix::Type() const { return MatrixType::SB; } + +MatrixType IdentityMatrix::Type() const { return MatrixType::Id; } + + + +MatrixBandWidth BaseMatrix::BandWidth() const { REPORT return -1; } +MatrixBandWidth DiagonalMatrix::BandWidth() const { REPORT return 0; } +MatrixBandWidth IdentityMatrix::BandWidth() const { REPORT return 0; } + +MatrixBandWidth UpperTriangularMatrix::BandWidth() const + { REPORT return MatrixBandWidth(0,-1); } + +MatrixBandWidth LowerTriangularMatrix::BandWidth() const + { REPORT return MatrixBandWidth(-1,0); } + +MatrixBandWidth BandMatrix::BandWidth() const + { REPORT return MatrixBandWidth(lower,upper); } + +MatrixBandWidth GenericMatrix::BandWidth()const + { REPORT return gm->BandWidth(); } + +MatrixBandWidth AddedMatrix::BandWidth() const + { REPORT return gm1->BandWidth() + gm2->BandWidth(); } + +MatrixBandWidth SPMatrix::BandWidth() const + { REPORT return gm1->BandWidth().minimum(gm2->BandWidth()); } + +MatrixBandWidth KPMatrix::BandWidth() const +{ + int lower, upper; + MatrixBandWidth bw1 = gm1->BandWidth(), bw2 = gm2->BandWidth(); + if (bw1.Lower() < 0) + { + if (bw2.Lower() < 0) { REPORT lower = -1; } + else { REPORT lower = bw2.Lower() + (gm1->Nrows() - 1) * gm2->Nrows(); } + } + else + { + if (bw2.Lower() < 0) + { REPORT lower = (1 + bw1.Lower()) * gm2->Nrows() - 1; } + else { REPORT lower = bw2.Lower() + bw1.Lower() * gm2->Nrows(); } + } + if (bw1.Upper() < 0) + { + if (bw2.Upper() < 0) { REPORT upper = -1; } + else { REPORT upper = bw2.Upper() + (gm1->Nrows() - 1) * gm2->Nrows(); } + } + else + { + if (bw2.Upper() < 0) + { REPORT upper = (1 + bw1.Upper()) * gm2->Nrows() - 1; } + else { REPORT upper = bw2.Upper() + bw1.Upper() * gm2->Nrows(); } + } + return MatrixBandWidth(lower, upper); +} + +MatrixBandWidth MultipliedMatrix::BandWidth() const +{ REPORT return gm1->BandWidth() * gm2->BandWidth(); } + +MatrixBandWidth ConcatenatedMatrix::BandWidth() const { REPORT return -1; } + +MatrixBandWidth SolvedMatrix::BandWidth() const +{ + if (+gm1->Type() & MatrixType::Diagonal) + { REPORT return gm2->BandWidth(); } + else { REPORT return -1; } +} + +MatrixBandWidth ScaledMatrix::BandWidth() const + { REPORT return gm->BandWidth(); } + +MatrixBandWidth NegatedMatrix::BandWidth() const + { REPORT return gm->BandWidth(); } + +MatrixBandWidth TransposedMatrix::BandWidth() const + { REPORT return gm->BandWidth().t(); } + +MatrixBandWidth InvertedMatrix::BandWidth() const +{ + if (+gm->Type() & MatrixType::Diagonal) + { REPORT return MatrixBandWidth(0,0); } + else { REPORT return -1; } +} + +MatrixBandWidth RowedMatrix::BandWidth() const { REPORT return -1; } +MatrixBandWidth ColedMatrix::BandWidth() const { REPORT return -1; } +MatrixBandWidth DiagedMatrix::BandWidth() const { REPORT return 0; } +MatrixBandWidth MatedMatrix::BandWidth() const { REPORT return -1; } +MatrixBandWidth ReturnMatrix::BandWidth() const + { REPORT return gm->BandWidth(); } + +MatrixBandWidth GetSubMatrix::BandWidth() const +{ + + if (row_skip==col_skip && row_number==col_number) + { REPORT return gm->BandWidth(); } + else { REPORT return MatrixBandWidth(-1); } +} + +// ********************** the memory managment tools **********************/ + +// Rules regarding tDelete, reuse, GetStore, BorrowStore +// All matrices processed during expression evaluation must be subject +// to exactly one of reuse(), tDelete(), GetStore() or BorrowStore(). +// If reuse returns true the matrix must be reused. +// GetMatrix(gm) always calls gm->GetStore() +// gm->Evaluate obeys rules +// bm->Evaluate obeys rules for matrices in bm structure + +void GeneralMatrix::tDelete() +{ + if (tag<0) + { + if (tag<-1) { REPORT store = 0; delete this; return; } // borrowed + else { REPORT return; } // not a temporary matrix - leave alone + } + if (tag==1) + { + if (store) + { + REPORT MONITOR_REAL_DELETE("Free (tDelete)",storage,store) + delete [] store; + } + MiniCleanUp(); return; // CleanUp + } + if (tag==0) { REPORT delete this; return; } + + REPORT tag--; return; +} + +static void BlockCopy(int n, Real* from, Real* to) +{ + REPORT + int i = (n >> 3); + while (i--) + { + *to++ = *from++; *to++ = *from++; *to++ = *from++; *to++ = *from++; + *to++ = *from++; *to++ = *from++; *to++ = *from++; *to++ = *from++; + } + i = n & 7; while (i--) *to++ = *from++; +} + +bool GeneralMatrix::reuse() +{ + if (tag < -1) // borrowed storage + { + if (storage) + { + REPORT + Real* s = new Real [storage]; MatrixErrorNoSpace(s); + MONITOR_REAL_NEW("Make (reuse)",storage,s) + BlockCopy(storage, store, s); store = s; + } + else { REPORT MiniCleanUp(); } // CleanUp + tag = 0; return true; + } + if (tag < 0 ) { REPORT return false; } + if (tag <= 1 ) { REPORT return true; } + REPORT tag--; return false; +} + +Real* GeneralMatrix::GetStore() +{ + if (tag<0 || tag>1) + { + Real* s; + if (storage) + { + s = new Real [storage]; MatrixErrorNoSpace(s); + MONITOR_REAL_NEW("Make (GetStore)",storage,s) + BlockCopy(storage, store, s); + } + else s = 0; + if (tag > 1) { REPORT tag--; } + else if (tag < -1) { REPORT store = 0; delete this; } // borrowed store + else { REPORT } + return s; + } + Real* s = store; // CleanUp - done later + if (tag==0) { REPORT store = 0; delete this; } + else { REPORT MiniCleanUp(); } + return s; +} + +void GeneralMatrix::GetMatrix(const GeneralMatrix* gmx) +{ + REPORT tag=-1; nrows=gmx->Nrows(); ncols=gmx->Ncols(); + storage=gmx->storage; SetParameters(gmx); + store=((GeneralMatrix*)gmx)->GetStore(); +} + +GeneralMatrix* GeneralMatrix::BorrowStore(GeneralMatrix* gmx, MatrixType mt) +// Copy storage of *this to storage of *gmx. Then convert to type mt. +// If mt == 0 just let *gmx point to storage of *this if tag==-1. +{ + if (!mt) + { + if (tag == -1) { REPORT gmx->tag = -2; gmx->store = store; } + else { REPORT gmx->tag = 0; gmx->store = GetStore(); } + } + else if (Compare(gmx->Type(),mt)) + { REPORT gmx->tag = 0; gmx->store = GetStore(); } + else + { + REPORT gmx->tag = -2; gmx->store = store; + gmx = gmx->Evaluate(mt); gmx->tag = 0; tDelete(); + } + + return gmx; +} + +void GeneralMatrix::Eq(const BaseMatrix& X, MatrixType mt) +// Count number of references to this in X. +// If zero delete storage in this; +// otherwise tag this to show when storage can be deleted +// evaluate X and copy to this +{ +#ifdef DO_SEARCH + int counter=X.search(this); + if (counter==0) + { + REPORT + if (store) + { + MONITOR_REAL_DELETE("Free (operator=)",storage,store) + REPORT delete [] store; storage = 0; store = 0; + } + } + else { REPORT Release(counter); } + GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate(mt); + if (gmx!=this) { REPORT GetMatrix(gmx); } + else { REPORT } + Protect(); +#else + GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate(mt); + if (gmx!=this) + { + REPORT + if (store) + { + MONITOR_REAL_DELETE("Free (operator=)",storage,store) + REPORT delete [] store; storage = 0; store = 0; + } + GetMatrix(gmx); + } + else { REPORT } + Protect(); +#endif +} + +// version with no conversion +void GeneralMatrix::Eq(const GeneralMatrix& X) +{ + GeneralMatrix* gmx = (GeneralMatrix*)&X; + if (gmx!=this) + { + REPORT + if (store) + { + MONITOR_REAL_DELETE("Free (operator=)",storage,store) + REPORT delete [] store; storage = 0; store = 0; + } + GetMatrix(gmx); + } + else { REPORT } + Protect(); +} + +// version to work with operator<< +void GeneralMatrix::Eq(const BaseMatrix& X, MatrixType mt, bool ldok) +{ + REPORT + if (ldok) mt.SetDataLossOK(); + Eq(X, mt); +} + +void GeneralMatrix::Eq2(const BaseMatrix& X, MatrixType mt) +// a cut down version of Eq for use with += etc. +// we know BaseMatrix points to two GeneralMatrix objects, +// the first being this (may be the same). +// we know tag has been set correctly in each. +{ + GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate(mt); + if (gmx!=this) { REPORT GetMatrix(gmx); } // simplify GetMatrix ? + else { REPORT } + Protect(); +} + +void GeneralMatrix::Inject(const GeneralMatrix& X) +// copy stored values of X; otherwise leave els of *this unchanged +{ + REPORT + Tracer tr("Inject"); + if (nrows != X.nrows || ncols != X.ncols) + Throw(IncompatibleDimensionsException()); + MatrixRow mr((GeneralMatrix*)&X, LoadOnEntry); + MatrixRow mrx(this, LoadOnEntry+StoreOnExit+DirectPart); + int i=nrows; + while (i--) { mrx.Inject(mr); mrx.Next(); mr.Next(); } +} + +// ************* checking for data loss during conversion *******************/ + +bool Compare(const MatrixType& source, MatrixType& destination) +{ + if (!destination) { destination=source; return true; } + if (destination==source) return true; + if (!destination.DataLossOK && !(destination>=source)) + Throw(ProgramException("Illegal Conversion", source, destination)); + return false; +} + +// ************* Make a copy of a matrix on the heap *********************/ + +GeneralMatrix* Matrix::Image() const +{ + REPORT + GeneralMatrix* gm = new Matrix(*this); MatrixErrorNoSpace(gm); + return gm; +} + +GeneralMatrix* SquareMatrix::Image() const +{ + REPORT + GeneralMatrix* gm = new SquareMatrix(*this); MatrixErrorNoSpace(gm); + return gm; +} + +GeneralMatrix* SymmetricMatrix::Image() const +{ + REPORT + GeneralMatrix* gm = new SymmetricMatrix(*this); MatrixErrorNoSpace(gm); + return gm; +} + +GeneralMatrix* UpperTriangularMatrix::Image() const +{ + REPORT + GeneralMatrix* gm = new UpperTriangularMatrix(*this); + MatrixErrorNoSpace(gm); return gm; +} + +GeneralMatrix* LowerTriangularMatrix::Image() const +{ + REPORT + GeneralMatrix* gm = new LowerTriangularMatrix(*this); + MatrixErrorNoSpace(gm); return gm; +} + +GeneralMatrix* DiagonalMatrix::Image() const +{ + REPORT + GeneralMatrix* gm = new DiagonalMatrix(*this); MatrixErrorNoSpace(gm); + return gm; +} + +GeneralMatrix* RowVector::Image() const +{ + REPORT + GeneralMatrix* gm = new RowVector(*this); MatrixErrorNoSpace(gm); + return gm; +} + +GeneralMatrix* ColumnVector::Image() const +{ + REPORT + GeneralMatrix* gm = new ColumnVector(*this); MatrixErrorNoSpace(gm); + return gm; +} + +GeneralMatrix* BandMatrix::Image() const +{ + REPORT + GeneralMatrix* gm = new BandMatrix(*this); MatrixErrorNoSpace(gm); + return gm; +} + +GeneralMatrix* UpperBandMatrix::Image() const +{ + REPORT + GeneralMatrix* gm = new UpperBandMatrix(*this); MatrixErrorNoSpace(gm); + return gm; +} + +GeneralMatrix* LowerBandMatrix::Image() const +{ + REPORT + GeneralMatrix* gm = new LowerBandMatrix(*this); MatrixErrorNoSpace(gm); + return gm; +} + +GeneralMatrix* SymmetricBandMatrix::Image() const +{ + REPORT + GeneralMatrix* gm = new SymmetricBandMatrix(*this); MatrixErrorNoSpace(gm); + return gm; +} + +GeneralMatrix* nricMatrix::Image() const +{ + REPORT + GeneralMatrix* gm = new nricMatrix(*this); MatrixErrorNoSpace(gm); + return gm; +} + +GeneralMatrix* IdentityMatrix::Image() const +{ + REPORT + GeneralMatrix* gm = new IdentityMatrix(*this); MatrixErrorNoSpace(gm); + return gm; +} + +GeneralMatrix* GeneralMatrix::Image() const +{ + bool dummy = true; + if (dummy) // get rid of warning message + Throw(InternalException("Cannot apply Image to this matrix type")); + return 0; +} + + +// *********************** nricMatrix routines *****************************/ + +void nricMatrix::MakeRowPointer() +{ + REPORT + if (nrows > 0) + { + row_pointer = new Real* [nrows]; MatrixErrorNoSpace(row_pointer); + Real* s = Store() - 1; int i = nrows; Real** rp = row_pointer; + if (i) for (;;) { *rp++ = s; if (!(--i)) break; s+=ncols; } + } + else row_pointer = 0; +} + +void nricMatrix::DeleteRowPointer() + { REPORT if (nrows) delete [] row_pointer; } + +void GeneralMatrix::CheckStore() const +{ + REPORT + if (!store) + Throw(ProgramException("NRIC accessing matrix with unset dimensions")); +} + + +// *************************** CleanUp routines *****************************/ + +void GeneralMatrix::CleanUp() +{ + // set matrix dimensions to zero, delete storage + REPORT + if (store && storage) + { + MONITOR_REAL_DELETE("Free (CleanUp) ",storage,store) + REPORT delete [] store; + } + store=0; storage=0; nrows=0; ncols=0; tag = -1; +} + +void nricMatrix::CleanUp() + { REPORT DeleteRowPointer(); GeneralMatrix::CleanUp(); } + +void nricMatrix::MiniCleanUp() + { REPORT DeleteRowPointer(); GeneralMatrix::MiniCleanUp(); } + +void RowVector::CleanUp() + { REPORT GeneralMatrix::CleanUp(); nrows=1; } + +void ColumnVector::CleanUp() + { REPORT GeneralMatrix::CleanUp(); ncols=1; } + +void CroutMatrix::CleanUp() +{ + REPORT + if (nrows) delete [] indx; + GeneralMatrix::CleanUp(); +} + +void CroutMatrix::MiniCleanUp() +{ + REPORT + if (nrows) delete [] indx; + GeneralMatrix::MiniCleanUp(); +} + +void BandLUMatrix::CleanUp() +{ + REPORT + if (nrows) delete [] indx; + if (storage2) delete [] store2; + GeneralMatrix::CleanUp(); +} + +void BandLUMatrix::MiniCleanUp() +{ + REPORT + if (nrows) delete [] indx; + if (storage2) delete [] store2; + GeneralMatrix::MiniCleanUp(); +} + +// ************************ simple integer array class *********************** + +// construct a new array of length xn. Check that xn is non-negative and +// that space is available + +SimpleIntArray::SimpleIntArray(int xn) : n(xn) +{ + if (n < 0) Throw(Logic_error("invalid array length")); + else if (n == 0) { REPORT a = 0; } + else { REPORT a = new int [n]; if (!a) Throw(Bad_alloc()); } +} + +// destroy an array - return its space to memory + +SimpleIntArray::~SimpleIntArray() { REPORT if (a) delete [] a; } + +// access an element of an array; return a "reference" so elements +// can be modified. +// check index is within range +// in this array class the index runs from 0 to n-1 + +int& SimpleIntArray::operator[](int i) +{ + REPORT + if (i < 0 || i >= n) Throw(Logic_error("array index out of range")); + return a[i]; +} + +// same thing again but for arrays declared constant so we can't +// modify its elements + +int SimpleIntArray::operator[](int i) const +{ + REPORT + if (i < 0 || i >= n) Throw(Logic_error("array index out of range")); + return a[i]; +} + +// set all the elements equal to a given value + +void SimpleIntArray::operator=(int ai) + { REPORT for (int i = 0; i < n; i++) a[i] = ai; } + +// set the elements equal to those of another array. +// check the arrays are of the same length + +void SimpleIntArray::operator=(const SimpleIntArray& b) +{ + REPORT + if (b.n != n) Throw(Logic_error("array lengths differ in copy")); + for (int i = 0; i < n; i++) a[i] = b.a[i]; +} + +// construct a new array equal to an existing array +// check that space is available + +SimpleIntArray::SimpleIntArray(const SimpleIntArray& b) : n(b.n) +{ + if (n == 0) { REPORT a = 0; } + else + { + REPORT + a = new int [n]; if (!a) Throw(Bad_alloc()); + for (int i = 0; i < n; i++) a[i] = b.a[i]; + } +} + +// change the size of an array; optionally copy data from old array to +// new array + +void SimpleIntArray::ReSize(int n1, bool keep) +{ + if (n1 == n) { REPORT return; } + else if (n1 == 0) { REPORT n = 0; delete [] a; a = 0; } + else if (n == 0) + { REPORT a = new int [n1]; if (!a) Throw(Bad_alloc()); n = n1; } + else + { + int* a1 = a; + if (keep) + { + REPORT + a = new int [n1]; if (!a) Throw(Bad_alloc()); + if (n > n1) n = n1; + for (int i = 0; i < n; i++) a[i] = a1[i]; + n = n1; delete [] a1; + } + else + { + REPORT n = n1; delete [] a1; + a = new int [n]; if (!a) Throw(Bad_alloc()); + } + } +} + + +#ifdef use_namespace +} +#endif + diff --git a/Utilities/OSSIM/ossim_core/matrix/newmat5.cpp b/Utilities/OSSIM/ossim_core/matrix/newmat5.cpp new file mode 100644 index 0000000000..665da82e66 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/newmat5.cpp @@ -0,0 +1,485 @@ +//$$ newmat5.cpp Transpose, evaluate etc + +// Copyright (C) 1991,2,3,4: R B Davies + +//#define WANT_STREAM + +#include "include.h" + +#include "newmat.h" +#include "newmatrc.h" + +#ifdef use_namespace +namespace NEWMAT { +#endif + + +#ifdef DO_REPORT +#define REPORT { static ExeCounter ExeCount(__LINE__,5); ++ExeCount; } +#else +#define REPORT {} +#endif + + +/************************ carry out operations ******************************/ + + +GeneralMatrix* GeneralMatrix::Transpose(TransposedMatrix* tm, MatrixType mt) +{ + GeneralMatrix* gm1; + + if (Compare(Type().t(),mt)) + { + REPORT + gm1 = mt.New(ncols,nrows,tm); + for (int i=0; i<ncols; i++) + { + MatrixRow mr(gm1, StoreOnExit+DirectPart, i); + MatrixCol mc(this, mr.Data(), LoadOnEntry, i); + } + } + else + { + REPORT + gm1 = mt.New(ncols,nrows,tm); + MatrixRow mr(this, LoadOnEntry); + MatrixCol mc(gm1, StoreOnExit+DirectPart); + int i = nrows; + while (i--) { mc.Copy(mr); mr.Next(); mc.Next(); } + } + tDelete(); gm1->ReleaseAndDelete(); return gm1; +} + +GeneralMatrix* SymmetricMatrix::Transpose(TransposedMatrix*, MatrixType mt) +{ REPORT return Evaluate(mt); } + + +GeneralMatrix* DiagonalMatrix::Transpose(TransposedMatrix*, MatrixType mt) +{ REPORT return Evaluate(mt); } + +GeneralMatrix* ColumnVector::Transpose(TransposedMatrix*, MatrixType mt) +{ + REPORT + GeneralMatrix* gmx = new RowVector; MatrixErrorNoSpace(gmx); + gmx->nrows = 1; gmx->ncols = gmx->storage = storage; + return BorrowStore(gmx,mt); +} + +GeneralMatrix* RowVector::Transpose(TransposedMatrix*, MatrixType mt) +{ + REPORT + GeneralMatrix* gmx = new ColumnVector; MatrixErrorNoSpace(gmx); + gmx->ncols = 1; gmx->nrows = gmx->storage = storage; + return BorrowStore(gmx,mt); +} + +GeneralMatrix* IdentityMatrix::Transpose(TransposedMatrix*, MatrixType mt) +{ REPORT return Evaluate(mt); } + +GeneralMatrix* GeneralMatrix::Evaluate(MatrixType mt) +{ + if (Compare(this->Type(),mt)) { REPORT return this; } + REPORT + GeneralMatrix* gmx = mt.New(nrows,ncols,this); + MatrixRow mr(this, LoadOnEntry); + MatrixRow mrx(gmx, StoreOnExit+DirectPart); + int i=nrows; + while (i--) { mrx.Copy(mr); mrx.Next(); mr.Next(); } + tDelete(); gmx->ReleaseAndDelete(); return gmx; +} + +GeneralMatrix* GenericMatrix::Evaluate(MatrixType mt) + { REPORT return gm->Evaluate(mt); } + +GeneralMatrix* ShiftedMatrix::Evaluate(MatrixType mt) +{ + gm=((BaseMatrix*&)bm)->Evaluate(); + int nr=gm->Nrows(); int nc=gm->Ncols(); + Compare(gm->Type().AddEqualEl(),mt); + if (!(mt==gm->Type())) + { + REPORT + GeneralMatrix* gmx = mt.New(nr,nc,this); + MatrixRow mr(gm, LoadOnEntry); + MatrixRow mrx(gmx, StoreOnExit+DirectPart); + while (nr--) { mrx.Add(mr,f); mrx.Next(); mr.Next(); } + gmx->ReleaseAndDelete(); gm->tDelete(); + return gmx; + } + else if (gm->reuse()) + { + REPORT gm->Add(f); + return gm; + } + else + { + REPORT GeneralMatrix* gmy = gm->Type().New(nr,nc,this); + gmy->ReleaseAndDelete(); gmy->Add(gm,f); + return gmy; + } +} + +GeneralMatrix* NegShiftedMatrix::Evaluate(MatrixType mt) +{ + gm=((BaseMatrix*&)bm)->Evaluate(); + int nr=gm->Nrows(); int nc=gm->Ncols(); + Compare(gm->Type().AddEqualEl(),mt); + if (!(mt==gm->Type())) + { + REPORT + GeneralMatrix* gmx = mt.New(nr,nc,this); + MatrixRow mr(gm, LoadOnEntry); + MatrixRow mrx(gmx, StoreOnExit+DirectPart); + while (nr--) { mrx.NegAdd(mr,f); mrx.Next(); mr.Next(); } + gmx->ReleaseAndDelete(); gm->tDelete(); + return gmx; + } + else if (gm->reuse()) + { + REPORT gm->NegAdd(f); + return gm; + } + else + { + REPORT GeneralMatrix* gmy = gm->Type().New(nr,nc,this); + gmy->ReleaseAndDelete(); gmy->NegAdd(gm,f); + return gmy; + } +} + +GeneralMatrix* ScaledMatrix::Evaluate(MatrixType mt) +{ + gm=((BaseMatrix*&)bm)->Evaluate(); + int nr=gm->Nrows(); int nc=gm->Ncols(); + if (Compare(gm->Type(),mt)) + { + if (gm->reuse()) + { + REPORT gm->Multiply(f); + return gm; + } + else + { + REPORT GeneralMatrix* gmx = gm->Type().New(nr,nc,this); + gmx->ReleaseAndDelete(); gmx->Multiply(gm,f); + return gmx; + } + } + else + { + REPORT + GeneralMatrix* gmx = mt.New(nr,nc,this); + MatrixRow mr(gm, LoadOnEntry); + MatrixRow mrx(gmx, StoreOnExit+DirectPart); + while (nr--) { mrx.Multiply(mr,f); mrx.Next(); mr.Next(); } + gmx->ReleaseAndDelete(); gm->tDelete(); + return gmx; + } +} + +GeneralMatrix* NegatedMatrix::Evaluate(MatrixType mt) +{ + gm=((BaseMatrix*&)bm)->Evaluate(); + int nr=gm->Nrows(); int nc=gm->Ncols(); + if (Compare(gm->Type(),mt)) + { + if (gm->reuse()) + { + REPORT gm->Negate(); + return gm; + } + else + { + REPORT + GeneralMatrix* gmx = gm->Type().New(nr,nc,this); + gmx->ReleaseAndDelete(); gmx->Negate(gm); + return gmx; + } + } + else + { + REPORT + GeneralMatrix* gmx = mt.New(nr,nc,this); + MatrixRow mr(gm, LoadOnEntry); + MatrixRow mrx(gmx, StoreOnExit+DirectPart); + while (nr--) { mrx.Negate(mr); mrx.Next(); mr.Next(); } + gmx->ReleaseAndDelete(); gm->tDelete(); + return gmx; + } +} + +GeneralMatrix* ReversedMatrix::Evaluate(MatrixType mt) +{ + gm=((BaseMatrix*&)bm)->Evaluate(); GeneralMatrix* gmx; + + if ((gm->Type()).IsBand() && ! (gm->Type()).IsDiagonal()) + { + gm->tDelete(); + Throw(NotDefinedException("Reverse", "band matrices")); + } + + if (gm->reuse()) { REPORT gm->ReverseElements(); gmx = gm; } + else + { + REPORT + gmx = gm->Type().New(gm->Nrows(), gm->Ncols(), this); + gmx->ReverseElements(gm); gmx->ReleaseAndDelete(); + } + return gmx->Evaluate(mt); // target matrix is different type? + +} + +GeneralMatrix* TransposedMatrix::Evaluate(MatrixType mt) +{ + REPORT + gm=((BaseMatrix*&)bm)->Evaluate(); + Compare(gm->Type().t(),mt); + GeneralMatrix* gmx=gm->Transpose(this, mt); + return gmx; +} + +GeneralMatrix* RowedMatrix::Evaluate(MatrixType mt) +{ + gm = ((BaseMatrix*&)bm)->Evaluate(); + GeneralMatrix* gmx = new RowVector; MatrixErrorNoSpace(gmx); + gmx->nrows = 1; gmx->ncols = gmx->storage = gm->storage; + return gm->BorrowStore(gmx,mt); +} + +GeneralMatrix* ColedMatrix::Evaluate(MatrixType mt) +{ + gm = ((BaseMatrix*&)bm)->Evaluate(); + GeneralMatrix* gmx = new ColumnVector; MatrixErrorNoSpace(gmx); + gmx->ncols = 1; gmx->nrows = gmx->storage = gm->storage; + return gm->BorrowStore(gmx,mt); +} + +GeneralMatrix* DiagedMatrix::Evaluate(MatrixType mt) +{ + gm = ((BaseMatrix*&)bm)->Evaluate(); + GeneralMatrix* gmx = new DiagonalMatrix; MatrixErrorNoSpace(gmx); + gmx->nrows = gmx->ncols = gmx->storage = gm->storage; + return gm->BorrowStore(gmx,mt); +} + +GeneralMatrix* MatedMatrix::Evaluate(MatrixType mt) +{ + Tracer tr("MatedMatrix::Evaluate"); + gm = ((BaseMatrix*&)bm)->Evaluate(); + GeneralMatrix* gmx = new Matrix; MatrixErrorNoSpace(gmx); + gmx->nrows = nr; gmx->ncols = nc; gmx->storage = gm->storage; + if (nr*nc != gmx->storage) + Throw(IncompatibleDimensionsException()); + return gm->BorrowStore(gmx,mt); +} + +GeneralMatrix* GetSubMatrix::Evaluate(MatrixType mt) +{ + REPORT + Tracer tr("SubMatrix(evaluate)"); + gm = ((BaseMatrix*&)bm)->Evaluate(); + if (row_number < 0) row_number = gm->Nrows(); + if (col_number < 0) col_number = gm->Ncols(); + if (row_skip+row_number > gm->Nrows() || col_skip+col_number > gm->Ncols()) + { + gm->tDelete(); + Throw(SubMatrixDimensionException()); + } + if (IsSym) Compare(gm->Type().ssub(), mt); + else Compare(gm->Type().sub(), mt); + GeneralMatrix* gmx = mt.New(row_number, col_number, this); + int i = row_number; + MatrixRow mr(gm, LoadOnEntry, row_skip); + MatrixRow mrx(gmx, StoreOnExit+DirectPart); + MatrixRowCol sub; + while (i--) + { + mr.SubRowCol(sub, col_skip, col_number); // put values in sub + mrx.Copy(sub); mrx.Next(); mr.Next(); + } + gmx->ReleaseAndDelete(); gm->tDelete(); + return gmx; +} + + +GeneralMatrix* ReturnMatrix::Evaluate(MatrixType mt) +{ + return gm->Evaluate(mt); +} + + +void GeneralMatrix::Add(GeneralMatrix* gm1, Real f) +{ + REPORT + Real* s1=gm1->store; Real* s=store; int i=(storage >> 2); + while (i--) + { *s++ = *s1++ + f; *s++ = *s1++ + f; *s++ = *s1++ + f; *s++ = *s1++ + f; } + i = storage & 3; while (i--) *s++ = *s1++ + f; +} + +void GeneralMatrix::Add(Real f) +{ + REPORT + Real* s=store; int i=(storage >> 2); + while (i--) { *s++ += f; *s++ += f; *s++ += f; *s++ += f; } + i = storage & 3; while (i--) *s++ += f; +} + +void GeneralMatrix::NegAdd(GeneralMatrix* gm1, Real f) +{ + REPORT + Real* s1=gm1->store; Real* s=store; int i=(storage >> 2); + while (i--) + { *s++ = f - *s1++; *s++ = f - *s1++; *s++ = f - *s1++; *s++ = f - *s1++; } + i = storage & 3; while (i--) *s++ = f - *s1++; +} + +void GeneralMatrix::NegAdd(Real f) +{ + REPORT + Real* s=store; int i=(storage >> 2); + while (i--) + { + *s = f - *s; s++; *s = f - *s; s++; + *s = f - *s; s++; *s = f - *s; s++; + } + i = storage & 3; while (i--) { *s = f - *s; s++; } +} + +void GeneralMatrix::Negate(GeneralMatrix* gm1) +{ + // change sign of elements + REPORT + Real* s1=gm1->store; Real* s=store; int i=(storage >> 2); + while (i--) + { *s++ = -(*s1++); *s++ = -(*s1++); *s++ = -(*s1++); *s++ = -(*s1++); } + i = storage & 3; while(i--) *s++ = -(*s1++); +} + +void GeneralMatrix::Negate() +{ + REPORT + Real* s=store; int i=(storage >> 2); + while (i--) + { *s = -(*s); s++; *s = -(*s); s++; *s = -(*s); s++; *s = -(*s); s++; } + i = storage & 3; while(i--) { *s = -(*s); s++; } +} + +void GeneralMatrix::Multiply(GeneralMatrix* gm1, Real f) +{ + REPORT + Real* s1=gm1->store; Real* s=store; int i=(storage >> 2); + while (i--) + { *s++ = *s1++ * f; *s++ = *s1++ * f; *s++ = *s1++ * f; *s++ = *s1++ * f; } + i = storage & 3; while (i--) *s++ = *s1++ * f; +} + +void GeneralMatrix::Multiply(Real f) +{ + REPORT + Real* s=store; int i=(storage >> 2); + while (i--) { *s++ *= f; *s++ *= f; *s++ *= f; *s++ *= f; } + i = storage & 3; while (i--) *s++ *= f; +} + + +/************************ MatrixInput routines ****************************/ + +// int MatrixInput::n; // number values still to be read +// Real* MatrixInput::r; // pointer to next location to be read to + +MatrixInput MatrixInput::operator<<(Real f) +{ + REPORT + Tracer et("MatrixInput"); + if (n<=0) Throw(ProgramException("List of values too long")); + *r = f; int n1 = n-1; n=0; // n=0 so we won't trigger exception + return MatrixInput(n1, r+1); +} + + +MatrixInput GeneralMatrix::operator<<(Real f) +{ + REPORT + Tracer et("MatrixInput"); + int n = Storage(); + if (n<=0) Throw(ProgramException("Loading data to zero length matrix")); + Real* r; r = Store(); *r = f; n--; + return MatrixInput(n, r+1); +} + +MatrixInput GetSubMatrix::operator<<(Real f) +{ + REPORT + Tracer et("MatrixInput (GetSubMatrix)"); + SetUpLHS(); + if (row_number != 1 || col_skip != 0 || col_number != gm->Ncols()) + { + Throw(ProgramException("MatrixInput requires complete rows")); + } + MatrixRow mr(gm, DirectPart, row_skip); // to pick up location and length + int n = mr.Storage(); + if (n<=0) + { + Throw(ProgramException("Loading data to zero length row")); + } + Real* r; r = mr.Data(); *r = f; n--; + if (+(mr.cw*HaveStore)) + { + Throw(ProgramException("Fails with this matrix type")); + } + return MatrixInput(n, r+1); +} + +MatrixInput::~MatrixInput() +{ + REPORT + Tracer et("MatrixInput"); + if (n!=0) Throw(ProgramException("A list of values was too short")); +} + +MatrixInput BandMatrix::operator<<(Real) +{ + Tracer et("MatrixInput"); + bool dummy = true; + if (dummy) // get rid of warning message + Throw(ProgramException("Cannot use list read with a BandMatrix")); + return MatrixInput(0, 0); +} + +void BandMatrix::operator<<(const Real*) +{ Throw(ProgramException("Cannot use array read with a BandMatrix")); } + +void BandMatrix::operator<<(const int*) +{ Throw(ProgramException("Cannot use array read with a BandMatrix")); } + +void SymmetricBandMatrix::operator<<(const Real*) +{ Throw(ProgramException("Cannot use array read with a BandMatrix")); } + +void SymmetricBandMatrix::operator<<(const int*) +{ Throw(ProgramException("Cannot use array read with a BandMatrix")); } + +// ************************* Reverse order of elements *********************** + +void GeneralMatrix::ReverseElements(GeneralMatrix* gm) +{ + // reversing into a new matrix + REPORT + int n = Storage(); Real* rx = Store() + n; Real* x = gm->Store(); + while (n--) *(--rx) = *(x++); +} + +void GeneralMatrix::ReverseElements() +{ + // reversing in place + REPORT + int n = Storage(); Real* x = Store(); Real* rx = x + n; + n /= 2; + while (n--) { Real t = *(--rx); *rx = *x; *(x++) = t; } +} + + +#ifdef use_namespace +} +#endif + diff --git a/Utilities/OSSIM/ossim_core/matrix/newmat6.cpp b/Utilities/OSSIM/ossim_core/matrix/newmat6.cpp new file mode 100644 index 0000000000..08b3b907d5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/newmat6.cpp @@ -0,0 +1,884 @@ +//$$ newmat6.cpp Operators, element access, submatrices + +// Copyright (C) 1991,2,3,4: R B Davies + +#include "include.h" + +#include "newmat.h" +#include "newmatrc.h" + +#ifdef use_namespace +namespace NEWMAT { +#endif + + + +#ifdef DO_REPORT +#define REPORT { static ExeCounter ExeCount(__LINE__,6); ++ExeCount; } +#else +#define REPORT {} +#endif + +/*************************** general utilities *************************/ + +static int tristore(int n) // els in triangular matrix +{ return (n*(n+1))/2; } + + +/****************************** operators *******************************/ + +Real& Matrix::operator()(int m, int n) +{ + REPORT + if (m<=0 || m>nrows || n<=0 || n>ncols) + Throw(IndexException(m,n,*this)); + return store[(m-1)*ncols+n-1]; +} + +Real& SymmetricMatrix::operator()(int m, int n) +{ + REPORT + if (m<=0 || n<=0 || m>nrows || n>ncols) + Throw(IndexException(m,n,*this)); + if (m>=n) return store[tristore(m-1)+n-1]; + else return store[tristore(n-1)+m-1]; +} + +Real& UpperTriangularMatrix::operator()(int m, int n) +{ + REPORT + if (m<=0 || n<m || n>ncols) + Throw(IndexException(m,n,*this)); + return store[(m-1)*ncols+n-1-tristore(m-1)]; +} + +Real& LowerTriangularMatrix::operator()(int m, int n) +{ + REPORT + if (n<=0 || m<n || m>nrows) + Throw(IndexException(m,n,*this)); + return store[tristore(m-1)+n-1]; +} + +Real& DiagonalMatrix::operator()(int m, int n) +{ + REPORT + if (n<=0 || m!=n || m>nrows || n>ncols) + Throw(IndexException(m,n,*this)); + return store[n-1]; +} + +Real& DiagonalMatrix::operator()(int m) +{ + REPORT + if (m<=0 || m>nrows) Throw(IndexException(m,*this)); + return store[m-1]; +} + +Real& ColumnVector::operator()(int m) +{ + REPORT + if (m<=0 || m> nrows) Throw(IndexException(m,*this)); + return store[m-1]; +} + +Real& RowVector::operator()(int n) +{ + REPORT + if (n<=0 || n> ncols) Throw(IndexException(n,*this)); + return store[n-1]; +} + +Real& BandMatrix::operator()(int m, int n) +{ + REPORT + int w = upper+lower+1; int i = lower+n-m; + if (m<=0 || m>nrows || n<=0 || n>ncols || i<0 || i>=w) + Throw(IndexException(m,n,*this)); + return store[w*(m-1)+i]; +} + +Real& UpperBandMatrix::operator()(int m, int n) +{ + REPORT + int w = upper+1; int i = n-m; + if (m<=0 || m>nrows || n<=0 || n>ncols || i<0 || i>=w) + Throw(IndexException(m,n,*this)); + return store[w*(m-1)+i]; +} + +Real& LowerBandMatrix::operator()(int m, int n) +{ + REPORT + int w = lower+1; int i = lower+n-m; + if (m<=0 || m>nrows || n<=0 || n>ncols || i<0 || i>=w) + Throw(IndexException(m,n,*this)); + return store[w*(m-1)+i]; +} + +Real& SymmetricBandMatrix::operator()(int m, int n) +{ + REPORT + int w = lower+1; + if (m>=n) + { + REPORT + int i = lower+n-m; + if ( m>nrows || n<=0 || i<0 ) + Throw(IndexException(m,n,*this)); + return store[w*(m-1)+i]; + } + else + { + REPORT + int i = lower+m-n; + if ( n>nrows || m<=0 || i<0 ) + Throw(IndexException(m,n,*this)); + return store[w*(n-1)+i]; + } +} + + +Real Matrix::operator()(int m, int n) const +{ + REPORT + if (m<=0 || m>nrows || n<=0 || n>ncols) + Throw(IndexException(m,n,*this)); + return store[(m-1)*ncols+n-1]; +} + +Real SymmetricMatrix::operator()(int m, int n) const +{ + REPORT + if (m<=0 || n<=0 || m>nrows || n>ncols) + Throw(IndexException(m,n,*this)); + if (m>=n) return store[tristore(m-1)+n-1]; + else return store[tristore(n-1)+m-1]; +} + +Real UpperTriangularMatrix::operator()(int m, int n) const +{ + REPORT + if (m<=0 || n<m || n>ncols) + Throw(IndexException(m,n,*this)); + return store[(m-1)*ncols+n-1-tristore(m-1)]; +} + +Real LowerTriangularMatrix::operator()(int m, int n) const +{ + REPORT + if (n<=0 || m<n || m>nrows) + Throw(IndexException(m,n,*this)); + return store[tristore(m-1)+n-1]; +} + +Real DiagonalMatrix::operator()(int m, int n) const +{ + REPORT + if (n<=0 || m!=n || m>nrows || n>ncols) + Throw(IndexException(m,n,*this)); + return store[n-1]; +} + +Real DiagonalMatrix::operator()(int m) const +{ + REPORT + if (m<=0 || m>nrows) Throw(IndexException(m,*this)); + return store[m-1]; +} + +Real ColumnVector::operator()(int m) const +{ + REPORT + if (m<=0 || m> nrows) Throw(IndexException(m,*this)); + return store[m-1]; +} + +Real RowVector::operator()(int n) const +{ + REPORT + if (n<=0 || n> ncols) Throw(IndexException(n,*this)); + return store[n-1]; +} + +Real BandMatrix::operator()(int m, int n) const +{ + REPORT + int w = upper+lower+1; int i = lower+n-m; + if (m<=0 || m>nrows || n<=0 || n>ncols || i<0 || i>=w) + Throw(IndexException(m,n,*this)); + return store[w*(m-1)+i]; +} + +Real UpperBandMatrix::operator()(int m, int n) const +{ + REPORT + int w = upper+1; int i = n-m; + if (m<=0 || m>nrows || n<=0 || n>ncols || i<0 || i>=w) + Throw(IndexException(m,n,*this)); + return store[w*(m-1)+i]; +} + +Real LowerBandMatrix::operator()(int m, int n) const +{ + REPORT + int w = lower+1; int i = lower+n-m; + if (m<=0 || m>nrows || n<=0 || n>ncols || i<0 || i>=w) + Throw(IndexException(m,n,*this)); + return store[w*(m-1)+i]; +} + +Real SymmetricBandMatrix::operator()(int m, int n) const +{ + REPORT + int w = lower+1; + if (m>=n) + { + REPORT + int i = lower+n-m; + if ( m>nrows || n<=0 || i<0 ) + Throw(IndexException(m,n,*this)); + return store[w*(m-1)+i]; + } + else + { + REPORT + int i = lower+m-n; + if ( n>nrows || m<=0 || i<0 ) + Throw(IndexException(m,n,*this)); + return store[w*(n-1)+i]; + } +} + + +Real BaseMatrix::AsScalar() const +{ + REPORT + GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); + + if (gm->nrows!=1 || gm->ncols!=1) + { + Tracer tr("AsScalar"); + Try + { Throw(ProgramException("Cannot convert to scalar", *gm)); } + CatchAll { gm->tDelete(); ReThrow; } + } + + Real x = *(gm->store); gm->tDelete(); return x; +} + + +AddedMatrix BaseMatrix::operator+(const BaseMatrix& bm) const +{ REPORT return AddedMatrix(this, &bm); } + +SPMatrix SP(const BaseMatrix& bm1,const BaseMatrix& bm2) +{ REPORT return SPMatrix(&bm1, &bm2); } + +KPMatrix KP(const BaseMatrix& bm1,const BaseMatrix& bm2) +{ REPORT return KPMatrix(&bm1, &bm2); } + +MultipliedMatrix BaseMatrix::operator*(const BaseMatrix& bm) const +{ REPORT return MultipliedMatrix(this, &bm); } + +ConcatenatedMatrix BaseMatrix::operator|(const BaseMatrix& bm) const +{ REPORT return ConcatenatedMatrix(this, &bm); } + +StackedMatrix BaseMatrix::operator&(const BaseMatrix& bm) const +{ REPORT return StackedMatrix(this, &bm); } + +SolvedMatrix InvertedMatrix::operator*(const BaseMatrix& bmx) const +{ REPORT return SolvedMatrix(bm, &bmx); } + +SubtractedMatrix BaseMatrix::operator-(const BaseMatrix& bm) const +{ REPORT return SubtractedMatrix(this, &bm); } + +ShiftedMatrix BaseMatrix::operator+(Real f) const +{ REPORT return ShiftedMatrix(this, f); } + +ShiftedMatrix operator+(Real f, const BaseMatrix& BM) +{ REPORT return ShiftedMatrix(&BM, f); } + +NegShiftedMatrix operator-(Real f, const BaseMatrix& bm) +{ REPORT return NegShiftedMatrix(f, &bm); } + +ScaledMatrix BaseMatrix::operator*(Real f) const +{ REPORT return ScaledMatrix(this, f); } + +ScaledMatrix BaseMatrix::operator/(Real f) const +{ REPORT return ScaledMatrix(this, 1.0/f); } + +ScaledMatrix operator*(Real f, const BaseMatrix& BM) +{ REPORT return ScaledMatrix(&BM, f); } + +ShiftedMatrix BaseMatrix::operator-(Real f) const +{ REPORT return ShiftedMatrix(this, -f); } + +TransposedMatrix BaseMatrix::t() const +{ REPORT return TransposedMatrix(this); } + +NegatedMatrix BaseMatrix::operator-() const +{ REPORT return NegatedMatrix(this); } + +ReversedMatrix BaseMatrix::Reverse() const +{ REPORT return ReversedMatrix(this); } + +InvertedMatrix BaseMatrix::i() const +{ REPORT return InvertedMatrix(this); } + + +RowedMatrix BaseMatrix::AsRow() const +{ REPORT return RowedMatrix(this); } + +ColedMatrix BaseMatrix::AsColumn() const +{ REPORT return ColedMatrix(this); } + +DiagedMatrix BaseMatrix::AsDiagonal() const +{ REPORT return DiagedMatrix(this); } + +MatedMatrix BaseMatrix::AsMatrix(int nrx, int ncx) const +{ REPORT return MatedMatrix(this,nrx,ncx); } + + +void GeneralMatrix::operator=(Real f) +{ REPORT int i=storage; Real* s=store; while (i--) { *s++ = f; } } + +void Matrix::operator=(const BaseMatrix& X) +{ + REPORT //CheckConversion(X); + // MatrixConversionCheck mcc; + Eq(X,MatrixType::Rt); +} + +void SquareMatrix::operator=(const BaseMatrix& X) +{ + REPORT //CheckConversion(X); + // MatrixConversionCheck mcc; + Eq(X,MatrixType::Rt); + if (nrows != ncols) + { Tracer tr("SquareMatrix(=)"); Throw(NotSquareException(*this)); } +} + +void SquareMatrix::operator=(const Matrix& m) +{ + REPORT + if (m.nrows != m.ncols) + { Tracer tr("SquareMatrix(=Matrix)"); Throw(NotSquareException(*this)); } + Eq(m); +} + +void RowVector::operator=(const BaseMatrix& X) +{ + REPORT // CheckConversion(X); + // MatrixConversionCheck mcc; + Eq(X,MatrixType::RV); + if (nrows!=1) + { Tracer tr("RowVector(=)"); Throw(VectorException(*this)); } +} + +void ColumnVector::operator=(const BaseMatrix& X) +{ + REPORT //CheckConversion(X); + // MatrixConversionCheck mcc; + Eq(X,MatrixType::CV); + if (ncols!=1) + { Tracer tr("ColumnVector(=)"); Throw(VectorException(*this)); } +} + +void SymmetricMatrix::operator=(const BaseMatrix& X) +{ + REPORT // CheckConversion(X); + // MatrixConversionCheck mcc; + Eq(X,MatrixType::Sm); +} + +void UpperTriangularMatrix::operator=(const BaseMatrix& X) +{ + REPORT //CheckConversion(X); + // MatrixConversionCheck mcc; + Eq(X,MatrixType::UT); +} + +void LowerTriangularMatrix::operator=(const BaseMatrix& X) +{ + REPORT //CheckConversion(X); + // MatrixConversionCheck mcc; + Eq(X,MatrixType::LT); +} + +void DiagonalMatrix::operator=(const BaseMatrix& X) +{ + REPORT // CheckConversion(X); + // MatrixConversionCheck mcc; + Eq(X,MatrixType::Dg); +} + +void IdentityMatrix::operator=(const BaseMatrix& X) +{ + REPORT // CheckConversion(X); + // MatrixConversionCheck mcc; + Eq(X,MatrixType::Id); +} + +void GeneralMatrix::operator<<(const Real* r) +{ + REPORT + int i = storage; Real* s=store; + while(i--) *s++ = *r++; +} + + +void GeneralMatrix::operator<<(const int* r) +{ + REPORT + int i = storage; Real* s=store; + while(i--) *s++ = *r++; +} + + +void GenericMatrix::operator=(const GenericMatrix& bmx) +{ + if (&bmx != this) { REPORT if (gm) delete gm; gm = bmx.gm->Image();} + else { REPORT } + gm->Protect(); +} + +void GenericMatrix::operator=(const BaseMatrix& bmx) +{ + if (gm) + { + int counter=bmx.search(gm); + if (counter==0) { REPORT delete gm; gm=0; } + else { REPORT gm->Release(counter); } + } + else { REPORT } + GeneralMatrix* gmx = ((BaseMatrix&)bmx).Evaluate(); + if (gmx != gm) { REPORT if (gm) delete gm; gm = gmx->Image(); } + else { REPORT } + gm->Protect(); +} + + +/*************************** += etc ***************************************/ + +// will also need versions for SubMatrix + + + +// GeneralMatrix operators + +void GeneralMatrix::operator+=(const BaseMatrix& X) +{ + REPORT + Tracer tr("GeneralMatrix::operator+="); + // MatrixConversionCheck mcc; + Protect(); // so it cannot get deleted + // during Evaluate + GeneralMatrix* gm = ((BaseMatrix&)X).Evaluate(); + AddedMatrix am(this,gm); + if (gm==this) Release(2); else Release(); + Eq2(am,Type()); +} + +void GeneralMatrix::operator-=(const BaseMatrix& X) +{ + REPORT + Tracer tr("GeneralMatrix::operator-="); + // MatrixConversionCheck mcc; + Protect(); // so it cannot get deleted + // during Evaluate + GeneralMatrix* gm = ((BaseMatrix&)X).Evaluate(); + SubtractedMatrix am(this,gm); + if (gm==this) Release(2); else Release(); + Eq2(am,Type()); +} + +void GeneralMatrix::operator*=(const BaseMatrix& X) +{ + REPORT + Tracer tr("GeneralMatrix::operator*="); + // MatrixConversionCheck mcc; + Protect(); // so it cannot get deleted + // during Evaluate + GeneralMatrix* gm = ((BaseMatrix&)X).Evaluate(); + MultipliedMatrix am(this,gm); + if (gm==this) Release(2); else Release(); + Eq2(am,Type()); +} + +void GeneralMatrix::operator|=(const BaseMatrix& X) +{ + REPORT + Tracer tr("GeneralMatrix::operator|="); + // MatrixConversionCheck mcc; + Protect(); // so it cannot get deleted + // during Evaluate + GeneralMatrix* gm = ((BaseMatrix&)X).Evaluate(); + ConcatenatedMatrix am(this,gm); + if (gm==this) Release(2); else Release(); + Eq2(am,Type()); +} + +void GeneralMatrix::operator&=(const BaseMatrix& X) +{ + REPORT + Tracer tr("GeneralMatrix::operator&="); + // MatrixConversionCheck mcc; + Protect(); // so it cannot get deleted + // during Evaluate + GeneralMatrix* gm = ((BaseMatrix&)X).Evaluate(); + StackedMatrix am(this,gm); + if (gm==this) Release(2); else Release(); + Eq2(am,Type()); +} + +void GeneralMatrix::operator+=(Real r) +{ + REPORT + Tracer tr("GeneralMatrix::operator+=(Real)"); + // MatrixConversionCheck mcc; + ShiftedMatrix am(this,r); + Release(); Eq2(am,Type()); +} + +void GeneralMatrix::operator*=(Real r) +{ + REPORT + Tracer tr("GeneralMatrix::operator*=(Real)"); + // MatrixConversionCheck mcc; + ScaledMatrix am(this,r); + Release(); Eq2(am,Type()); +} + + +// Generic matrix operators + +void GenericMatrix::operator+=(const BaseMatrix& X) +{ + REPORT + Tracer tr("GenericMatrix::operator+="); + if (!gm) Throw(ProgramException("GenericMatrix is null")); + gm->Protect(); // so it cannot get deleted during Evaluate + GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate(); + AddedMatrix am(gm,gmx); + if (gmx==gm) gm->Release(2); else gm->Release(); + GeneralMatrix* gmy = am.Evaluate(); + if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); } + else { REPORT } + gm->Protect(); +} + +void GenericMatrix::operator-=(const BaseMatrix& X) +{ + REPORT + Tracer tr("GenericMatrix::operator-="); + if (!gm) Throw(ProgramException("GenericMatrix is null")); + gm->Protect(); // so it cannot get deleted during Evaluate + GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate(); + SubtractedMatrix am(gm,gmx); + if (gmx==gm) gm->Release(2); else gm->Release(); + GeneralMatrix* gmy = am.Evaluate(); + if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); } + else { REPORT } + gm->Protect(); +} + +void GenericMatrix::operator*=(const BaseMatrix& X) +{ + REPORT + Tracer tr("GenericMatrix::operator*="); + if (!gm) Throw(ProgramException("GenericMatrix is null")); + gm->Protect(); // so it cannot get deleted during Evaluate + GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate(); + MultipliedMatrix am(gm,gmx); + if (gmx==gm) gm->Release(2); else gm->Release(); + GeneralMatrix* gmy = am.Evaluate(); + if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); } + else { REPORT } + gm->Protect(); +} + +void GenericMatrix::operator|=(const BaseMatrix& X) +{ + REPORT + Tracer tr("GenericMatrix::operator|="); + if (!gm) Throw(ProgramException("GenericMatrix is null")); + gm->Protect(); // so it cannot get deleted during Evaluate + GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate(); + ConcatenatedMatrix am(gm,gmx); + if (gmx==gm) gm->Release(2); else gm->Release(); + GeneralMatrix* gmy = am.Evaluate(); + if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); } + else { REPORT } + gm->Protect(); +} + +void GenericMatrix::operator&=(const BaseMatrix& X) +{ + REPORT + Tracer tr("GenericMatrix::operator&="); + if (!gm) Throw(ProgramException("GenericMatrix is null")); + gm->Protect(); // so it cannot get deleted during Evaluate + GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate(); + StackedMatrix am(gm,gmx); + if (gmx==gm) gm->Release(2); else gm->Release(); + GeneralMatrix* gmy = am.Evaluate(); + if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); } + else { REPORT } + gm->Protect(); +} + +void GenericMatrix::operator+=(Real r) +{ + REPORT + Tracer tr("GenericMatrix::operator+= (Real)"); + if (!gm) Throw(ProgramException("GenericMatrix is null")); + ShiftedMatrix am(gm,r); + gm->Release(); + GeneralMatrix* gmy = am.Evaluate(); + if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); } + else { REPORT } + gm->Protect(); +} + +void GenericMatrix::operator*=(Real r) +{ + REPORT + Tracer tr("GenericMatrix::operator*= (Real)"); + if (!gm) Throw(ProgramException("GenericMatrix is null")); + ScaledMatrix am(gm,r); + gm->Release(); + GeneralMatrix* gmy = am.Evaluate(); + if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); } + else { REPORT } + gm->Protect(); +} + + +/************************* element access *********************************/ + +Real& Matrix::element(int m, int n) +{ + REPORT + if (m<0 || m>= nrows || n<0 || n>= ncols) + Throw(IndexException(m,n,*this,true)); + return store[m*ncols+n]; +} + +Real Matrix::element(int m, int n) const +{ + REPORT + if (m<0 || m>= nrows || n<0 || n>= ncols) + Throw(IndexException(m,n,*this,true)); + return store[m*ncols+n]; +} + +Real& SymmetricMatrix::element(int m, int n) +{ + REPORT + if (m<0 || n<0 || m >= nrows || n>=ncols) + Throw(IndexException(m,n,*this,true)); + if (m>=n) return store[tristore(m)+n]; + else return store[tristore(n)+m]; +} + +Real SymmetricMatrix::element(int m, int n) const +{ + REPORT + if (m<0 || n<0 || m >= nrows || n>=ncols) + Throw(IndexException(m,n,*this,true)); + if (m>=n) return store[tristore(m)+n]; + else return store[tristore(n)+m]; +} + +Real& UpperTriangularMatrix::element(int m, int n) +{ + REPORT + if (m<0 || n<m || n>=ncols) + Throw(IndexException(m,n,*this,true)); + return store[m*ncols+n-tristore(m)]; +} + +Real UpperTriangularMatrix::element(int m, int n) const +{ + REPORT + if (m<0 || n<m || n>=ncols) + Throw(IndexException(m,n,*this,true)); + return store[m*ncols+n-tristore(m)]; +} + +Real& LowerTriangularMatrix::element(int m, int n) +{ + REPORT + if (n<0 || m<n || m>=nrows) + Throw(IndexException(m,n,*this,true)); + return store[tristore(m)+n]; +} + +Real LowerTriangularMatrix::element(int m, int n) const +{ + REPORT + if (n<0 || m<n || m>=nrows) + Throw(IndexException(m,n,*this,true)); + return store[tristore(m)+n]; +} + +Real& DiagonalMatrix::element(int m, int n) +{ + REPORT + if (n<0 || m!=n || m>=nrows || n>=ncols) + Throw(IndexException(m,n,*this,true)); + return store[n]; +} + +Real DiagonalMatrix::element(int m, int n) const +{ + REPORT + if (n<0 || m!=n || m>=nrows || n>=ncols) + Throw(IndexException(m,n,*this,true)); + return store[n]; +} + +Real& DiagonalMatrix::element(int m) +{ + REPORT + if (m<0 || m>=nrows) Throw(IndexException(m,*this,true)); + return store[m]; +} + +Real DiagonalMatrix::element(int m) const +{ + REPORT + if (m<0 || m>=nrows) Throw(IndexException(m,*this,true)); + return store[m]; +} + +Real& ColumnVector::element(int m) +{ + REPORT + if (m<0 || m>= nrows) Throw(IndexException(m,*this,true)); + return store[m]; +} + +Real ColumnVector::element(int m) const +{ + REPORT + if (m<0 || m>= nrows) Throw(IndexException(m,*this,true)); + return store[m]; +} + +Real& RowVector::element(int n) +{ + REPORT + if (n<0 || n>= ncols) Throw(IndexException(n,*this,true)); + return store[n]; +} + +Real RowVector::element(int n) const +{ + REPORT + if (n<0 || n>= ncols) Throw(IndexException(n,*this,true)); + return store[n]; +} + +Real& BandMatrix::element(int m, int n) +{ + REPORT + int w = upper+lower+1; int i = lower+n-m; + if (m<0 || m>= nrows || n<0 || n>= ncols || i<0 || i>=w) + Throw(IndexException(m,n,*this,true)); + return store[w*m+i]; +} + +Real BandMatrix::element(int m, int n) const +{ + REPORT + int w = upper+lower+1; int i = lower+n-m; + if (m<0 || m>= nrows || n<0 || n>= ncols || i<0 || i>=w) + Throw(IndexException(m,n,*this,true)); + return store[w*m+i]; +} + +Real& UpperBandMatrix::element(int m, int n) +{ + REPORT + int w = upper+1; int i = n-m; + if (m<0 || m>= nrows || n<0 || n>= ncols || i<0 || i>=w) + Throw(IndexException(m,n,*this,true)); + return store[w*m+i]; +} + +Real UpperBandMatrix::element(int m, int n) const +{ + REPORT + int w = upper+1; int i = n-m; + if (m<0 || m>= nrows || n<0 || n>= ncols || i<0 || i>=w) + Throw(IndexException(m,n,*this,true)); + return store[w*m+i]; +} + +Real& LowerBandMatrix::element(int m, int n) +{ + REPORT + int w = lower+1; int i = lower+n-m; + if (m<0 || m>= nrows || n<0 || n>= ncols || i<0 || i>=w) + Throw(IndexException(m,n,*this,true)); + return store[w*m+i]; +} + +Real LowerBandMatrix::element(int m, int n) const +{ + REPORT + int w = lower+1; int i = lower+n-m; + if (m<0 || m>= nrows || n<0 || n>= ncols || i<0 || i>=w) + Throw(IndexException(m,n,*this,true)); + return store[w*m+i]; +} + +Real& SymmetricBandMatrix::element(int m, int n) +{ + REPORT + int w = lower+1; + if (m>=n) + { + REPORT + int i = lower+n-m; + if ( m>=nrows || n<0 || i<0 ) + Throw(IndexException(m,n,*this,true)); + return store[w*m+i]; + } + else + { + REPORT + int i = lower+m-n; + if ( n>=nrows || m<0 || i<0 ) + Throw(IndexException(m,n,*this,true)); + return store[w*n+i]; + } +} + +Real SymmetricBandMatrix::element(int m, int n) const +{ + REPORT + int w = lower+1; + if (m>=n) + { + REPORT + int i = lower+n-m; + if ( m>=nrows || n<0 || i<0 ) + Throw(IndexException(m,n,*this,true)); + return store[w*m+i]; + } + else + { + REPORT + int i = lower+m-n; + if ( n>=nrows || m<0 || i<0 ) + Throw(IndexException(m,n,*this,true)); + return store[w*n+i]; + } +} + +#ifdef use_namespace +} +#endif + diff --git a/Utilities/OSSIM/ossim_core/matrix/newmat7.cpp b/Utilities/OSSIM/ossim_core/matrix/newmat7.cpp new file mode 100644 index 0000000000..c82e1a853e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/newmat7.cpp @@ -0,0 +1,1037 @@ +//$$ newmat7.cpp Invert, solve, binary operations + +// Copyright (C) 1991,2,3,4: R B Davies + +#include "include.h" + +#include "newmat.h" +#include "newmatrc.h" + +#ifdef use_namespace +namespace NEWMAT { +#endif + + +#ifdef DO_REPORT +#define REPORT { static ExeCounter ExeCount(__LINE__,7); ++ExeCount; } +#else +#define REPORT {} +#endif + + +//***************************** solve routines ******************************/ + +GeneralMatrix* GeneralMatrix::MakeSolver() +{ + REPORT + GeneralMatrix* gm = new CroutMatrix(*this); + MatrixErrorNoSpace(gm); gm->ReleaseAndDelete(); return gm; +} + +GeneralMatrix* Matrix::MakeSolver() +{ + REPORT + GeneralMatrix* gm = new CroutMatrix(*this); + MatrixErrorNoSpace(gm); gm->ReleaseAndDelete(); return gm; +} + +void CroutMatrix::Solver(MatrixColX& mcout, const MatrixColX& mcin) +{ + REPORT + int i = mcin.skip; Real* el = mcin.data-i; Real* el1 = el; + while (i--) *el++ = 0.0; + el += mcin.storage; i = nrows - mcin.skip - mcin.storage; + while (i--) *el++ = 0.0; + lubksb(el1, mcout.skip); +} + + +// Do we need check for entirely zero output? + +void UpperTriangularMatrix::Solver(MatrixColX& mcout, + const MatrixColX& mcin) +{ + REPORT + int i = mcin.skip-mcout.skip; Real* elx = mcin.data-i; + while (i-- > 0) *elx++ = 0.0; + int nr = mcin.skip+mcin.storage; + elx = mcin.data+mcin.storage; Real* el = elx; + int j = mcout.skip+mcout.storage-nr; int nc = ncols-nr; i = nr-mcout.skip; + while (j-- > 0) *elx++ = 0.0; + Real* Ael = store + (nr*(2*ncols-nr+1))/2; j = 0; + while (i-- > 0) + { + elx = el; Real sum = 0.0; int jx = j++; Ael -= nc; + while (jx--) sum += *(--Ael) * *(--elx); + elx--; *elx = (*elx - sum) / *(--Ael); + } +} + +void LowerTriangularMatrix::Solver(MatrixColX& mcout, + const MatrixColX& mcin) +{ + REPORT + int i = mcin.skip-mcout.skip; Real* elx = mcin.data-i; + while (i-- > 0) *elx++ = 0.0; + int nc = mcin.skip; i = nc+mcin.storage; elx = mcin.data+mcin.storage; + int nr = mcout.skip+mcout.storage; int j = nr-i; i = nr-nc; + while (j-- > 0) *elx++ = 0.0; + Real* el = mcin.data; Real* Ael = store + (nc*(nc+1))/2; j = 0; + while (i-- > 0) + { + elx = el; Real sum = 0.0; int jx = j++; Ael += nc; + while (jx--) sum += *Ael++ * *elx++; + *elx = (*elx - sum) / *Ael++; + } +} + +//******************* carry out binary operations *************************/ + +static GeneralMatrix* + GeneralMult(GeneralMatrix*,GeneralMatrix*,MultipliedMatrix*,MatrixType); +static GeneralMatrix* + GeneralSolv(GeneralMatrix*,GeneralMatrix*,BaseMatrix*,MatrixType); +static GeneralMatrix* + GeneralSolvI(GeneralMatrix*,BaseMatrix*,MatrixType); +static GeneralMatrix* + GeneralKP(GeneralMatrix*,GeneralMatrix*,KPMatrix*,MatrixType); + +GeneralMatrix* MultipliedMatrix::Evaluate(MatrixType mt) +{ + REPORT + gm2 = ((BaseMatrix*&)bm2)->Evaluate(); + gm2 = gm2->Evaluate(gm2->Type().MultRHS()); // no symmetric on RHS + gm1=((BaseMatrix*&)bm1)->Evaluate(); + return GeneralMult(gm1, gm2, this, mt); +} + +GeneralMatrix* SolvedMatrix::Evaluate(MatrixType mt) +{ + REPORT + gm1=((BaseMatrix*&)bm1)->Evaluate(); + gm2=((BaseMatrix*&)bm2)->Evaluate(); + return GeneralSolv(gm1,gm2,this,mt); +} + +GeneralMatrix* KPMatrix::Evaluate(MatrixType mt) +{ + REPORT + gm1=((BaseMatrix*&)bm1)->Evaluate(); + gm2=((BaseMatrix*&)bm2)->Evaluate(); + return GeneralKP(gm1,gm2,this,mt); +} + +// routines for adding or subtracting matrices of identical storage structure + +static void Add(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2) +{ + REPORT + Real* s1=gm1->Store(); Real* s2=gm2->Store(); + Real* s=gm->Store(); int i=gm->Storage() >> 2; + while (i--) + { + *s++ = *s1++ + *s2++; *s++ = *s1++ + *s2++; + *s++ = *s1++ + *s2++; *s++ = *s1++ + *s2++; + } + i=gm->Storage() & 3; while (i--) *s++ = *s1++ + *s2++; +} + +static void AddTo(GeneralMatrix* gm, const GeneralMatrix* gm2) +{ + REPORT + const Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2; + while (i--) + { *s++ += *s2++; *s++ += *s2++; *s++ += *s2++; *s++ += *s2++; } + i=gm->Storage() & 3; while (i--) *s++ += *s2++; +} + +void GeneralMatrix::PlusEqual(const GeneralMatrix& gm) +{ + REPORT + if (nrows != gm.nrows || ncols != gm.ncols) + Throw(IncompatibleDimensionsException(*this, gm)); + AddTo(this, &gm); +} + +static void Subtract(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2) +{ + REPORT + Real* s1=gm1->Store(); Real* s2=gm2->Store(); + Real* s=gm->Store(); int i=gm->Storage() >> 2; + while (i--) + { + *s++ = *s1++ - *s2++; *s++ = *s1++ - *s2++; + *s++ = *s1++ - *s2++; *s++ = *s1++ - *s2++; + } + i=gm->Storage() & 3; while (i--) *s++ = *s1++ - *s2++; +} + +static void SubtractFrom(GeneralMatrix* gm, const GeneralMatrix* gm2) +{ + REPORT + const Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2; + while (i--) + { *s++ -= *s2++; *s++ -= *s2++; *s++ -= *s2++; *s++ -= *s2++; } + i=gm->Storage() & 3; while (i--) *s++ -= *s2++; +} + +void GeneralMatrix::MinusEqual(const GeneralMatrix& gm) +{ + REPORT + if (nrows != gm.nrows || ncols != gm.ncols) + Throw(IncompatibleDimensionsException(*this, gm)); + SubtractFrom(this, &gm); +} + +static void ReverseSubtract(GeneralMatrix* gm, const GeneralMatrix* gm2) +{ + REPORT + const Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2; + while (i--) + { + *s = *s2++ - *s; s++; *s = *s2++ - *s; s++; + *s = *s2++ - *s; s++; *s = *s2++ - *s; s++; + } + i=gm->Storage() & 3; while (i--) { *s = *s2++ - *s; s++; } +} + +static void SP(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2) +{ + REPORT + Real* s1=gm1->Store(); Real* s2=gm2->Store(); + Real* s=gm->Store(); int i=gm->Storage() >> 2; + while (i--) + { + *s++ = *s1++ * *s2++; *s++ = *s1++ * *s2++; + *s++ = *s1++ * *s2++; *s++ = *s1++ * *s2++; + } + i=gm->Storage() & 3; while (i--) *s++ = *s1++ * *s2++; +} + +static void SP(GeneralMatrix* gm, GeneralMatrix* gm2) +{ + REPORT + Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2; + while (i--) + { *s++ *= *s2++; *s++ *= *s2++; *s++ *= *s2++; *s++ *= *s2++; } + i=gm->Storage() & 3; while (i--) *s++ *= *s2++; +} + +// routines for adding or subtracting matrices of different storage structure + +static void AddDS(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2) +{ + REPORT + int nr = gm->Nrows(); + MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry); + MatrixRow mr(gm, StoreOnExit+DirectPart); + while (nr--) { mr.Add(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); } +} + +static void AddDS(GeneralMatrix* gm, GeneralMatrix* gm2) +// Add into first argument +{ + REPORT + int nr = gm->Nrows(); + MatrixRow mr(gm, StoreOnExit+LoadOnEntry+DirectPart); + MatrixRow mr2(gm2, LoadOnEntry); + while (nr--) { mr.Add(mr2); mr.Next(); mr2.Next(); } +} + +static void SubtractDS + (GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2) +{ + REPORT + int nr = gm->Nrows(); + MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry); + MatrixRow mr(gm, StoreOnExit+DirectPart); + while (nr--) { mr.Sub(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); } +} + +static void SubtractDS(GeneralMatrix* gm, GeneralMatrix* gm2) +{ + REPORT + int nr = gm->Nrows(); + MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart); + MatrixRow mr2(gm2, LoadOnEntry); + while (nr--) { mr.Sub(mr2); mr.Next(); mr2.Next(); } +} + +static void ReverseSubtractDS(GeneralMatrix* gm, GeneralMatrix* gm2) +{ + REPORT + int nr = gm->Nrows(); + MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart); + MatrixRow mr2(gm2, LoadOnEntry); + while (nr--) { mr.RevSub(mr2); mr2.Next(); mr.Next(); } +} + +static void SPDS(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2) +{ + REPORT + int nr = gm->Nrows(); + MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry); + MatrixRow mr(gm, StoreOnExit+DirectPart); + while (nr--) { mr.Multiply(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); } +} + +static void SPDS(GeneralMatrix* gm, GeneralMatrix* gm2) +// SP into first argument +{ + REPORT + int nr = gm->Nrows(); + MatrixRow mr(gm, StoreOnExit+LoadOnEntry+DirectPart); + MatrixRow mr2(gm2, LoadOnEntry); + while (nr--) { mr.Multiply(mr2); mr.Next(); mr2.Next(); } +} + +static GeneralMatrix* GeneralMult1(GeneralMatrix* gm1, GeneralMatrix* gm2, + MultipliedMatrix* mm, MatrixType mtx) +{ + REPORT + Tracer tr("GeneralMult1"); + int nr=gm1->Nrows(); int nc=gm2->Ncols(); + if (gm1->Ncols() !=gm2->Nrows()) + Throw(IncompatibleDimensionsException(*gm1, *gm2)); + GeneralMatrix* gmx = mtx.New(nr,nc,mm); + + MatrixCol mcx(gmx, StoreOnExit+DirectPart); + MatrixCol mc2(gm2, LoadOnEntry); + while (nc--) + { + MatrixRow mr1(gm1, LoadOnEntry, mcx.Skip()); + Real* el = mcx.Data(); // pointer to an element + int n = mcx.Storage(); + while (n--) { *(el++) = DotProd(mr1,mc2); mr1.Next(); } + mc2.Next(); mcx.Next(); + } + gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx; +} + +static GeneralMatrix* GeneralMult2(GeneralMatrix* gm1, GeneralMatrix* gm2, + MultipliedMatrix* mm, MatrixType mtx) +{ + // version that accesses by row only - not good for thin matrices + // or column vectors in right hand term. + REPORT + Tracer tr("GeneralMult2"); + int nr=gm1->Nrows(); int nc=gm2->Ncols(); + if (gm1->Ncols() !=gm2->Nrows()) + Throw(IncompatibleDimensionsException(*gm1, *gm2)); + GeneralMatrix* gmx = mtx.New(nr,nc,mm); + + MatrixRow mrx(gmx, LoadOnEntry+StoreOnExit+DirectPart); + MatrixRow mr1(gm1, LoadOnEntry); + while (nr--) + { + MatrixRow mr2(gm2, LoadOnEntry, mr1.Skip()); + Real* el = mr1.Data(); // pointer to an element + int n = mr1.Storage(); + mrx.Zero(); + while (n--) { mrx.AddScaled(mr2, *el++); mr2.Next(); } + mr1.Next(); mrx.Next(); + } + gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx; +} + +static GeneralMatrix* mmMult(GeneralMatrix* gm1, GeneralMatrix* gm2) +{ + // matrix multiplication for type Matrix only + REPORT + Tracer tr("MatrixMult"); + + int nr=gm1->Nrows(); int ncr=gm1->Ncols(); int nc=gm2->Ncols(); + if (ncr != gm2->Nrows()) Throw(IncompatibleDimensionsException(*gm1,*gm2)); + + Matrix* gm = new Matrix(nr,nc); MatrixErrorNoSpace(gm); + + Real* s1=gm1->Store(); Real* s2=gm2->Store(); Real* s=gm->Store(); + + if (ncr) + { + while (nr--) + { + Real* s2x = s2; int j = ncr; + Real* sx = s; Real f = *s1++; int k = nc; + while (k--) *sx++ = f * *s2x++; + while (--j) + { sx = s; f = *s1++; k = nc; while (k--) *sx++ += f * *s2x++; } + s = sx; + } + } + else *gm = 0.0; + + gm->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gm; +} + +static GeneralMatrix* GeneralMult(GeneralMatrix* gm1, GeneralMatrix* gm2, + MultipliedMatrix* mm, MatrixType mtx) +{ + if ( Rectangular(gm1->Type(), gm2->Type(), mtx)) + { + REPORT + return mmMult(gm1, gm2); + } + else + { + REPORT + Compare(gm1->Type() * gm2->Type(),mtx); + int nr = gm2->Nrows(); int nc = gm2->Ncols(); + if (nc <= 5 && nr > nc) + { + REPORT + return GeneralMult1(gm1, gm2, mm, mtx); + } + else + { + REPORT + return GeneralMult2(gm1, gm2, mm, mtx); + } + } + return NULL; +} + +static GeneralMatrix* GeneralKP(GeneralMatrix* gm1, GeneralMatrix* gm2, + KPMatrix* kp, MatrixType mtx) +{ + REPORT + Tracer tr("GeneralKP"); + int nr1 = gm1->Nrows(); int nc1 = gm1->Ncols(); + int nr2 = gm2->Nrows(); int nc2 = gm2->Ncols(); + Compare((gm1->Type()).KP(gm2->Type()),mtx); + GeneralMatrix* gmx = mtx.New(nr1*nr2, nc1*nc2, kp); + MatrixRow mrx(gmx, LoadOnEntry+StoreOnExit+DirectPart); + MatrixRow mr1(gm1, LoadOnEntry); + for (int i = 1; i <= nr1; ++i) + { + MatrixRow mr2(gm2, LoadOnEntry); + for (int j = 1; j <= nr2; ++j) + { mrx.KP(mr1,mr2); mr2.Next(); mrx.Next(); } + mr1.Next(); + } + gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx; +} + +static GeneralMatrix* GeneralSolv(GeneralMatrix* gm1, GeneralMatrix* gm2, + BaseMatrix* sm, MatrixType mtx) +{ + REPORT + Tracer tr("GeneralSolv"); + Compare(gm1->Type().i() * gm2->Type(),mtx); + int nr = gm1->Nrows(); + if (nr != gm1->Ncols()) Throw(NotSquareException(*gm1)); + int nc = gm2->Ncols(); + if (gm1->Ncols() != gm2->Nrows()) + Throw(IncompatibleDimensionsException(*gm1, *gm2)); + GeneralMatrix* gmx = mtx.New(nr,nc,sm); MatrixErrorNoSpace(gmx); + Real* r = new Real [nr]; MatrixErrorNoSpace(r); + MONITOR_REAL_NEW("Make (GenSolv)",nr,r) + GeneralMatrix* gms = gm1->MakeSolver(); + Try + { + + MatrixColX mcx(gmx, r, StoreOnExit+DirectPart); // copy to and from r + // this must be inside Try so mcx is destroyed before gmx + MatrixColX mc2(gm2, r, LoadOnEntry); + while (nc--) { gms->Solver(mcx, mc2); mcx.Next(); mc2.Next(); } + } + CatchAll + { + if (gms) gms->tDelete(); + delete gmx; // <-------------------- + gm2->tDelete(); + MONITOR_REAL_DELETE("Delete (GenSolv)",nr,r) + // AT&T version 2.1 gives an internal error + delete [] r; + ReThrow; + } + gms->tDelete(); gmx->ReleaseAndDelete(); gm2->tDelete(); + MONITOR_REAL_DELETE("Delete (GenSolv)",nr,r) + // AT&T version 2.1 gives an internal error + delete [] r; + return gmx; +} + +// version for inverses - gm2 is identity +static GeneralMatrix* GeneralSolvI(GeneralMatrix* gm1, BaseMatrix* sm, + MatrixType mtx) +{ + REPORT + Tracer tr("GeneralSolvI"); + Compare(gm1->Type().i(),mtx); + int nr = gm1->Nrows(); + if (nr != gm1->Ncols()) Throw(NotSquareException(*gm1)); + int nc = nr; + // DiagonalMatrix I(nr); I = 1; + IdentityMatrix I(nr); + GeneralMatrix* gmx = mtx.New(nr,nc,sm); MatrixErrorNoSpace(gmx); + Real* r = new Real [nr]; MatrixErrorNoSpace(r); + MONITOR_REAL_NEW("Make (GenSolvI)",nr,r) + GeneralMatrix* gms = gm1->MakeSolver(); + Try + { + + MatrixColX mcx(gmx, r, StoreOnExit+DirectPart); // copy to and from r + // this must be inside Try so mcx is destroyed before gmx + MatrixColX mc2(&I, r, LoadOnEntry); + while (nc--) { gms->Solver(mcx, mc2); mcx.Next(); mc2.Next(); } + } + CatchAll + { + if (gms) gms->tDelete(); + delete gmx; + MONITOR_REAL_DELETE("Delete (GenSolvI)",nr,r) + // AT&T version 2.1 gives an internal error + delete [] r; + ReThrow; + } + gms->tDelete(); gmx->ReleaseAndDelete(); + MONITOR_REAL_DELETE("Delete (GenSolvI)",nr,r) + // AT&T version 2.1 gives an internal error + delete [] r; + return gmx; +} + +GeneralMatrix* InvertedMatrix::Evaluate(MatrixType mtx) +{ + // Matrix Inversion - use solve routines + Tracer tr("InvertedMatrix::Evaluate"); + REPORT + gm=((BaseMatrix*&)bm)->Evaluate(); + return GeneralSolvI(gm,this,mtx); +} + +//*************************** New versions ************************ + +GeneralMatrix* AddedMatrix::Evaluate(MatrixType mtd) +{ + REPORT + Tracer tr("AddedMatrix::Evaluate"); + gm1=((BaseMatrix*&)bm1)->Evaluate(); gm2=((BaseMatrix*&)bm2)->Evaluate(); + int nr=gm1->Nrows(); int nc=gm1->Ncols(); + if (nr!=gm2->Nrows() || nc!=gm2->Ncols()) + { + Try { Throw(IncompatibleDimensionsException(*gm1, *gm2)); } + CatchAll + { + gm1->tDelete(); gm2->tDelete(); + ReThrow; + } + } + MatrixType mt1 = gm1->Type(), mt2 = gm2->Type(); MatrixType mts = mt1 + mt2; + if (!mtd) { REPORT mtd = mts; } + else if (!(mtd.DataLossOK || mtd >= mts)) + { + REPORT + gm1->tDelete(); gm2->tDelete(); + Throw(ProgramException("Illegal Conversion", mts, mtd)); + } + GeneralMatrix* gmx; + bool c1 = (mtd == mt1), c2 = (mtd == mt2); + if ( c1 && c2 && (gm1->SimpleAddOK(gm2) == 0) ) + { + if (gm1->reuse()) { REPORT AddTo(gm1,gm2); gm2->tDelete(); gmx = gm1; } + else if (gm2->reuse()) { REPORT AddTo(gm2,gm1); gmx = gm2; } + else + { + REPORT + // what if new throws an exception + Try { gmx = mt1.New(nr,nc,this); } + CatchAll + { + ReThrow; + } + gmx->ReleaseAndDelete(); Add(gmx,gm1,gm2); + } + } + else + { + if (c1 && c2) + { + short SAO = gm1->SimpleAddOK(gm2); + if (SAO & 1) { REPORT c1 = false; } + if (SAO & 2) { REPORT c2 = false; } + } + if (c1 && gm1->reuse() ) // must have type test first + { REPORT AddDS(gm1,gm2); gm2->tDelete(); gmx = gm1; } + else if (c2 && gm2->reuse() ) + { REPORT AddDS(gm2,gm1); if (!c1) gm1->tDelete(); gmx = gm2; } + else + { + REPORT + Try { gmx = mtd.New(nr,nc,this); } + CatchAll + { + if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete(); + ReThrow; + } + AddDS(gmx,gm1,gm2); + if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete(); + gmx->ReleaseAndDelete(); + } + } + return gmx; +} + +GeneralMatrix* SubtractedMatrix::Evaluate(MatrixType mtd) +{ + REPORT + Tracer tr("SubtractedMatrix::Evaluate"); + gm1=((BaseMatrix*&)bm1)->Evaluate(); gm2=((BaseMatrix*&)bm2)->Evaluate(); + int nr=gm1->Nrows(); int nc=gm1->Ncols(); + if (nr!=gm2->Nrows() || nc!=gm2->Ncols()) + { + Try { Throw(IncompatibleDimensionsException(*gm1, *gm2)); } + CatchAll + { + gm1->tDelete(); gm2->tDelete(); + ReThrow; + } + } + MatrixType mt1 = gm1->Type(), mt2 = gm2->Type(); MatrixType mts = mt1 + mt2; + if (!mtd) { REPORT mtd = mts; } + else if (!(mtd.DataLossOK || mtd >= mts)) + { + gm1->tDelete(); gm2->tDelete(); + Throw(ProgramException("Illegal Conversion", mts, mtd)); + } + GeneralMatrix* gmx; + bool c1 = (mtd == mt1), c2 = (mtd == mt2); + if ( c1 && c2 && (gm1->SimpleAddOK(gm2) == 0) ) + { + if (gm1->reuse()) + { REPORT SubtractFrom(gm1,gm2); gm2->tDelete(); gmx = gm1; } + else if (gm2->reuse()) { REPORT ReverseSubtract(gm2,gm1); gmx = gm2; } + else + { + REPORT + Try { gmx = mt1.New(nr,nc,this); } + CatchAll + { + ReThrow; + } + gmx->ReleaseAndDelete(); Subtract(gmx,gm1,gm2); + } + } + else + { + if (c1 && c2) + { + short SAO = gm1->SimpleAddOK(gm2); + if (SAO & 1) { REPORT c1 = false; } + if (SAO & 2) { REPORT c2 = false; } + } + if (c1 && gm1->reuse() ) // must have type test first + { REPORT SubtractDS(gm1,gm2); gm2->tDelete(); gmx = gm1; } + else if (c2 && gm2->reuse() ) + { + REPORT ReverseSubtractDS(gm2,gm1); + if (!c1) gm1->tDelete(); gmx = gm2; + } + else + { + REPORT + // what if New throws and exception + Try { gmx = mtd.New(nr,nc,this); } + CatchAll + { + if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete(); + ReThrow; + } + SubtractDS(gmx,gm1,gm2); + if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete(); + gmx->ReleaseAndDelete(); + } + } + return gmx; +} + +GeneralMatrix* SPMatrix::Evaluate(MatrixType mtd) +{ + REPORT + Tracer tr("SPMatrix::Evaluate"); + gm1=((BaseMatrix*&)bm1)->Evaluate(); gm2=((BaseMatrix*&)bm2)->Evaluate(); + int nr=gm1->Nrows(); int nc=gm1->Ncols(); + if (nr!=gm2->Nrows() || nc!=gm2->Ncols()) + { + Try { Throw(IncompatibleDimensionsException(*gm1, *gm2)); } + CatchAll + { + gm1->tDelete(); gm2->tDelete(); + ReThrow; + } + } + MatrixType mt1 = gm1->Type(), mt2 = gm2->Type(); + MatrixType mts = mt1.SP(mt2); + if (!mtd) { REPORT mtd = mts; } + else if (!(mtd.DataLossOK || mtd >= mts)) + { + gm1->tDelete(); gm2->tDelete(); + Throw(ProgramException("Illegal Conversion", mts, mtd)); + } + GeneralMatrix* gmx; + bool c1 = (mtd == mt1), c2 = (mtd == mt2); + if ( c1 && c2 && (gm1->SimpleAddOK(gm2) == 0) ) + { + if (gm1->reuse()) { REPORT SP(gm1,gm2); gm2->tDelete(); gmx = gm1; } + else if (gm2->reuse()) { REPORT SP(gm2,gm1); gmx = gm2; } + else + { + REPORT + Try { gmx = mt1.New(nr,nc,this); } + CatchAll + { + ReThrow; + } + gmx->ReleaseAndDelete(); SP(gmx,gm1,gm2); + } + } + else + { + if (c1 && c2) + { + short SAO = gm1->SimpleAddOK(gm2); + if (SAO & 1) { REPORT c2 = false; } // c1 and c2 swapped + if (SAO & 2) { REPORT c1 = false; } + } + if (c1 && gm1->reuse() ) // must have type test first + { REPORT SPDS(gm1,gm2); gm2->tDelete(); gmx = gm1; } + else if (c2 && gm2->reuse() ) + { REPORT SPDS(gm2,gm1); if (!c1) gm1->tDelete(); gmx = gm2; } + else + { + REPORT + // what if New throws and exception + Try { gmx = mtd.New(nr,nc,this); } + CatchAll + { + if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete(); + ReThrow; + } + SPDS(gmx,gm1,gm2); + if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete(); + gmx->ReleaseAndDelete(); + } + } + return gmx; +} + + + +//*************************** norm functions ****************************/ + +Real BaseMatrix::Norm1() const +{ + // maximum of sum of absolute values of a column + REPORT + GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); + int nc = gm->Ncols(); Real value = 0.0; + MatrixCol mc(gm, LoadOnEntry); + while (nc--) + { Real v = mc.SumAbsoluteValue(); if (value < v) value = v; mc.Next(); } + gm->tDelete(); return value; +} + +Real BaseMatrix::NormInfinity() const +{ + // maximum of sum of absolute values of a row + REPORT + GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); + int nr = gm->Nrows(); Real value = 0.0; + MatrixRow mr(gm, LoadOnEntry); + while (nr--) + { Real v = mr.SumAbsoluteValue(); if (value < v) value = v; mr.Next(); } + gm->tDelete(); return value; +} + +//********************** Concatenation and stacking *************************/ + +GeneralMatrix* ConcatenatedMatrix::Evaluate(MatrixType mtx) +{ + REPORT + Tracer tr("Concatenate"); + gm2 = ((BaseMatrix*&)bm2)->Evaluate(); + gm1 = ((BaseMatrix*&)bm1)->Evaluate(); + Compare(gm1->Type() | gm2->Type(),mtx); + int nr=gm1->Nrows(); int nc = gm1->Ncols() + gm2->Ncols(); + if (nr != gm2->Nrows()) + Throw(IncompatibleDimensionsException(*gm1, *gm2)); + GeneralMatrix* gmx = mtx.New(nr,nc,this); + MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry); + MatrixRow mr(gmx, StoreOnExit+DirectPart); + while (nr--) { mr.ConCat(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); } + gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx; +} + +GeneralMatrix* StackedMatrix::Evaluate(MatrixType mtx) +{ + REPORT + Tracer tr("Stack"); + gm2 = ((BaseMatrix*&)bm2)->Evaluate(); + gm1 = ((BaseMatrix*&)bm1)->Evaluate(); + Compare(gm1->Type() & gm2->Type(),mtx); + int nc=gm1->Ncols(); + int nr1 = gm1->Nrows(); int nr2 = gm2->Nrows(); + if (nc != gm2->Ncols()) + Throw(IncompatibleDimensionsException(*gm1, *gm2)); + GeneralMatrix* gmx = mtx.New(nr1+nr2,nc,this); + MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry); + MatrixRow mr(gmx, StoreOnExit+DirectPart); + while (nr1--) { mr.Copy(mr1); mr1.Next(); mr.Next(); } + while (nr2--) { mr.Copy(mr2); mr2.Next(); mr.Next(); } + gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx; +} + +// ************************* equality of matrices ******************** // + +static bool RealEqual(Real* s1, Real* s2, int n) +{ + int i = n >> 2; + while (i--) + { + if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false; + if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false; + } + i = n & 3; while (i--) if (*s1++ != *s2++) return false; + return true; +} + +static bool intEqual(int* s1, int* s2, int n) +{ + int i = n >> 2; + while (i--) + { + if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false; + if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false; + } + i = n & 3; while (i--) if (*s1++ != *s2++) return false; + return true; +} + + +bool operator==(const BaseMatrix& A, const BaseMatrix& B) +{ + Tracer tr("BaseMatrix =="); + REPORT + GeneralMatrix* gmA = ((BaseMatrix&)A).Evaluate(); + GeneralMatrix* gmB = ((BaseMatrix&)B).Evaluate(); + + if (gmA == gmB) // same matrix + { REPORT gmA->tDelete(); return true; } + + if ( gmA->Nrows() != gmB->Nrows() || gmA->Ncols() != gmB->Ncols() ) + // different dimensions + { REPORT gmA->tDelete(); gmB->tDelete(); return false; } + + // check for CroutMatrix or BandLUMatrix + MatrixType AType = gmA->Type(); MatrixType BType = gmB->Type(); + if (AType.CannotConvert() || BType.CannotConvert() ) + { + REPORT + bool bx = gmA->IsEqual(*gmB); + gmA->tDelete(); gmB->tDelete(); + return bx; + } + + // is matrix storage the same + // will need to modify if further matrix structures are introduced + if (AType == BType && gmA->BandWidth() == gmB->BandWidth()) + { // compare store + REPORT + bool bx = RealEqual(gmA->Store(),gmB->Store(),gmA->Storage()); + gmA->tDelete(); gmB->tDelete(); + return bx; + } + + // matrix storage different - just subtract + REPORT return IsZero(*gmA-*gmB); +} + +bool operator==(const GeneralMatrix& A, const GeneralMatrix& B) +{ + Tracer tr("GeneralMatrix =="); + // May or may not call tDeletes + REPORT + + if (&A == &B) // same matrix + { REPORT return true; } + + if ( A.Nrows() != B.Nrows() || A.Ncols() != B.Ncols() ) + { REPORT return false; } // different dimensions + + // check for CroutMatrix or BandLUMatrix + MatrixType AType = A.Type(); MatrixType BType = B.Type(); + if (AType.CannotConvert() || BType.CannotConvert() ) + { REPORT return A.IsEqual(B); } + + // is matrix storage the same + // will need to modify if further matrix structures are introduced + if (AType == BType && A.BandWidth() == B.BandWidth()) + { REPORT return RealEqual(A.Store(),B.Store(),A.Storage()); } + + // matrix storage different - just subtract + REPORT return IsZero(A-B); +} + +bool GeneralMatrix::IsZero() const +{ + REPORT + Real* s=store; int i = storage >> 2; + while (i--) + { + if (*s++) return false; if (*s++) return false; + if (*s++) return false; if (*s++) return false; + } + i = storage & 3; while (i--) if (*s++) return false; + return true; +} + +bool IsZero(const BaseMatrix& A) +{ + Tracer tr("BaseMatrix::IsZero"); + REPORT + GeneralMatrix* gm1 = 0; bool bx; + Try { gm1=((BaseMatrix&)A).Evaluate(); bx = gm1->IsZero(); } + CatchAll { if (gm1) gm1->tDelete(); ReThrow; } + gm1->tDelete(); + return bx; +} + +// IsEqual functions - insist matrices are of same type +// as well as equal values to be equal + +bool GeneralMatrix::IsEqual(const GeneralMatrix& A) const +{ + Tracer tr("GeneralMatrix IsEqual"); + if (A.Type() != Type()) // not same types + { REPORT return false; } + if (&A == this) // same matrix + { REPORT return true; } + if (A.nrows != nrows || A.ncols != ncols) + // different dimensions + { REPORT return false; } + // is matrix storage the same - compare store + REPORT + return RealEqual(A.store,store,storage); +} + +bool CroutMatrix::IsEqual(const GeneralMatrix& A) const +{ + Tracer tr("CroutMatrix IsEqual"); + if (A.Type() != Type()) // not same types + { REPORT return false; } + if (&A == this) // same matrix + { REPORT return true; } + if (A.nrows != nrows || A.ncols != ncols) + // different dimensions + { REPORT return false; } + // is matrix storage the same - compare store + REPORT + return RealEqual(A.store,store,storage) + && intEqual(((CroutMatrix&)A).indx, indx, nrows); +} + + +bool BandLUMatrix::IsEqual(const GeneralMatrix& A) const +{ + Tracer tr("BandLUMatrix IsEqual"); + if (A.Type() != Type()) // not same types + { REPORT return false; } + if (&A == this) // same matrix + { REPORT return true; } + if ( A.Nrows() != nrows || A.Ncols() != ncols + || ((BandLUMatrix&)A).m1 != m1 || ((BandLUMatrix&)A).m2 != m2 ) + // different dimensions + { REPORT return false; } + + // matrix storage the same - compare store + REPORT + return RealEqual(A.Store(),store,storage) + && RealEqual(((BandLUMatrix&)A).store2,store2,storage2) + && intEqual(((BandLUMatrix&)A).indx, indx, nrows); +} + + +// ************************* cross products ******************** // + +inline void CrossProductBody(Real* a, Real* b, Real* c) +{ + c[0] = a[1] * b[2] - a[2] * b[1]; + c[1] = a[2] * b[0] - a[0] * b[2]; + c[2] = a[0] * b[1] - a[1] * b[0]; +} + +Matrix CrossProduct(const Matrix& A, const Matrix& B) +{ + REPORT + int ac = A.Ncols(); int ar = A.Nrows(); + int bc = B.Ncols(); int br = B.Nrows(); + Real* a = A.Store(); Real* b = B.Store(); + if (ac == 3) + { + if (bc != 3 || ar != 1 || br != 1) + { Tracer et("CrossProduct"); IncompatibleDimensionsException(A, B); } + REPORT + RowVector C(3); Real* c = C.Store(); CrossProductBody(a, b, c); + return C; + } + else + { + if (ac != 1 || bc != 1 || ar != 3 || br != 3) + { Tracer et("CrossProduct"); IncompatibleDimensionsException(A, B); } + REPORT + ColumnVector C(3); Real* c = C.Store(); CrossProductBody(a, b, c); + return C; + } +} + +ReturnMatrix CrossProductRows(const Matrix& A, const Matrix& B) +{ + REPORT + int n = A.Nrows(); + if (A.Ncols() != 3 || B.Ncols() != 3 || n != B.Nrows()) + { Tracer et("CrossProductRows"); IncompatibleDimensionsException(A, B); } + Matrix C(n, 3); + Real* a = A.Store(); Real* b = B.Store(); Real* c = C.Store(); + if (n--) + { + for (;;) + { + CrossProductBody(a, b, c); + if (!(n--)) break; + a += 3; b += 3; c += 3; + } + } + + return C.ForReturn(); +} + +ReturnMatrix CrossProductColumns(const Matrix& A, const Matrix& B) +{ + REPORT + int n = A.Ncols(); + if (A.Nrows() != 3 || B.Nrows() != 3 || n != B.Ncols()) + { Tracer et("CrossProductColumns"); IncompatibleDimensionsException(A, B); } + Matrix C(3, n); + Real* a = A.Store(); Real* b = B.Store(); Real* c = C.Store(); + Real* an = a+n; Real* an2 = an+n; + Real* bn = b+n; Real* bn2 = bn+n; + Real* cn = c+n; Real* cn2 = cn+n; + + int i = n; + while (i--) + { + *c++ = *an * *bn2 - *an2 * *bn; + *cn++ = *an2++ * *b - *a * *bn2++; + *cn2++ = *a++ * *bn++ - *an++ * *b++; + } + + return C.ForReturn(); +} + + +#ifdef use_namespace +} +#endif + + diff --git a/Utilities/OSSIM/ossim_core/matrix/newmat8.cpp b/Utilities/OSSIM/ossim_core/matrix/newmat8.cpp new file mode 100644 index 0000000000..ca9842afb6 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/newmat8.cpp @@ -0,0 +1,734 @@ +//$$ newmat8.cpp Advanced LU transform, scalar functions + +// Copyright (C) 1991,2,3,4,8: R B Davies + +#define WANT_MATH + +#include "include.h" + +#include "newmat.h" +#include "newmatrc.h" +#include "precisio.h" + +#ifdef use_namespace +namespace NEWMAT { +#endif + + +#ifdef DO_REPORT +#define REPORT { static ExeCounter ExeCount(__LINE__,8); ++ExeCount; } +#else +#define REPORT {} +#endif + + +/************************** LU transformation ****************************/ + +void CroutMatrix::ludcmp() +// LU decomposition from Golub & Van Loan, algorithm 3.4.1, (the "outer +// product" version). +// This replaces the code derived from Numerical Recipes in C in previous +// versions of newmat and being row oriented runs much faster with large +// matrices. +{ + REPORT + Tracer trace( "Crout(ludcmp)" ); sing = false; + Real* akk = store; // runs down diagonal + + Real big = fabs(*akk); int mu = 0; Real* ai = akk; int k; + + for (k = 1; k < nrows; k++) + { + ai += nrows; const Real trybig = fabs(*ai); + if (big < trybig) { big = trybig; mu = k; } + } + + + if (nrows) for (k = 0;;) + { + /* + int mu1; + { + Real big = fabs(*akk); mu1 = k; Real* ai = akk; int i; + + for (i = k+1; i < nrows; i++) + { + ai += nrows; const Real trybig = fabs(*ai); + if (big < trybig) { big = trybig; mu1 = i; } + } + } + if (mu1 != mu) cout << k << " " << mu << " " << mu1 << endl; + */ + + indx[k] = mu; + + if (mu != k) //row swap + { + Real* a1 = store + nrows * k; Real* a2 = store + nrows * mu; d = !d; + int j = nrows; + while (j--) { const Real temp = *a1; *a1++ = *a2; *a2++ = temp; } + } + + Real diag = *akk; big = 0; mu = k + 1; + if (diag != 0) + { + ai = akk; int i = nrows - k - 1; + while (i--) + { + ai += nrows; Real* al = ai; Real mult = *al / diag; *al = mult; + int l = nrows - k - 1; Real* aj = akk; + // work out the next pivot as part of this loop + // this saves a column operation + if (l-- != 0) + { + *(++al) -= (mult * *(++aj)); + const Real trybig = fabs(*al); + if (big < trybig) { big = trybig; mu = nrows - i - 1; } + while (l--) *(++al) -= (mult * *(++aj)); + } + } + } + else sing = true; + if (++k == nrows) break; // so next line won't overflow + akk += nrows + 1; + } +} + +void CroutMatrix::lubksb(Real* B, int mini) +{ + REPORT + // this has been adapted from Numerical Recipes in C. The code has been + // substantially streamlined, so I do not think much of the original + // copyright remains. However there is not much opportunity for + // variation in the code, so it is still similar to the NR code. + // I follow the NR code in skipping over initial zeros in the B vector. + + Tracer trace("Crout(lubksb)"); + if (sing) Throw(SingularException(*this)); + int i, j, ii = nrows; // ii initialised : B might be all zeros + + + // scan for first non-zero in B + for (i = 0; i < nrows; i++) + { + int ip = indx[i]; Real temp = B[ip]; B[ip] = B[i]; B[i] = temp; + if (temp != 0.0) { ii = i; break; } + } + + Real* bi; Real* ai; + i = ii + 1; + + if (i < nrows) + { + bi = B + ii; ai = store + ii + i * nrows; + for (;;) + { + int ip = indx[i]; Real sum = B[ip]; B[ip] = B[i]; + Real* aij = ai; Real* bj = bi; j = i - ii; + while (j--) sum -= *aij++ * *bj++; + B[i] = sum; + if (++i == nrows) break; + ai += nrows; + } + } + + ai = store + nrows * nrows; + + for (i = nrows - 1; i >= mini; i--) + { + Real* bj = B+i; ai -= nrows; Real* ajx = ai+i; + Real sum = *bj; Real diag = *ajx; + j = nrows - i; while(--j) sum -= *(++ajx) * *(++bj); + B[i] = sum / diag; + } +} + +/****************************** scalar functions ****************************/ + +inline Real square(Real x) { return x*x; } + +Real GeneralMatrix::SumSquare() const +{ + REPORT + Real sum = 0.0; int i = storage; Real* s = store; + while (i--) sum += square(*s++); + ((GeneralMatrix&)*this).tDelete(); return sum; +} + +Real GeneralMatrix::SumAbsoluteValue() const +{ + REPORT + Real sum = 0.0; int i = storage; Real* s = store; + while (i--) sum += fabs(*s++); + ((GeneralMatrix&)*this).tDelete(); return sum; +} + +Real GeneralMatrix::Sum() const +{ + REPORT + Real sum = 0.0; int i = storage; Real* s = store; + while (i--) sum += *s++; + ((GeneralMatrix&)*this).tDelete(); return sum; +} + +// maxima and minima + +// There are three sets of routines +// MaximumAbsoluteValue, MinimumAbsoluteValue, Maximum, Minimum +// ... these find just the maxima and minima +// MaximumAbsoluteValue1, MinimumAbsoluteValue1, Maximum1, Minimum1 +// ... these find the maxima and minima and their locations in a +// one dimensional object +// MaximumAbsoluteValue2, MinimumAbsoluteValue2, Maximum2, Minimum2 +// ... these find the maxima and minima and their locations in a +// two dimensional object + +// If the matrix has no values throw an exception + +// If we do not want the location find the maximum or minimum on the +// array stored by GeneralMatrix +// This won't work for BandMatrices. We call ClearCorner for +// MaximumAbsoluteValue but for the others use the AbsoluteMinimumValue2 +// version and discard the location. + +// For one dimensional objects, when we want the location of the +// maximum or minimum, work with the array stored by GeneralMatrix + +// For two dimensional objects where we want the location of the maximum or +// minimum proceed as follows: + +// For rectangular matrices use the array stored by GeneralMatrix and +// deduce the location from the location in the GeneralMatrix + +// For other two dimensional matrices use the Matrix Row routine to find the +// maximum or minimum for each row. + +static void NullMatrixError(const GeneralMatrix* gm) +{ + ((GeneralMatrix&)*gm).tDelete(); + Throw(ProgramException("Maximum or minimum of null matrix")); +} + +Real GeneralMatrix::MaximumAbsoluteValue() const +{ + REPORT + if (storage == 0) NullMatrixError(this); + Real maxval = 0.0; int l = storage; Real* s = store; + while (l--) { Real a = fabs(*s++); if (maxval < a) maxval = a; } + ((GeneralMatrix&)*this).tDelete(); return maxval; +} + +Real GeneralMatrix::MaximumAbsoluteValue1(int& i) const +{ + REPORT + if (storage == 0) NullMatrixError(this); + Real maxval = 0.0; int l = storage; Real* s = store; int li = storage; + while (l--) + { Real a = fabs(*s++); if (maxval <= a) { maxval = a; li = l; } } + i = storage - li; + ((GeneralMatrix&)*this).tDelete(); return maxval; +} + +Real GeneralMatrix::MinimumAbsoluteValue() const +{ + REPORT + if (storage == 0) NullMatrixError(this); + int l = storage - 1; Real* s = store; Real minval = fabs(*s++); + while (l--) { Real a = fabs(*s++); if (minval > a) minval = a; } + ((GeneralMatrix&)*this).tDelete(); return minval; +} + +Real GeneralMatrix::MinimumAbsoluteValue1(int& i) const +{ + REPORT + if (storage == 0) NullMatrixError(this); + int l = storage - 1; Real* s = store; Real minval = fabs(*s++); int li = l; + while (l--) + { Real a = fabs(*s++); if (minval >= a) { minval = a; li = l; } } + i = storage - li; + ((GeneralMatrix&)*this).tDelete(); return minval; +} + +Real GeneralMatrix::Maximum() const +{ + REPORT + if (storage == 0) NullMatrixError(this); + int l = storage - 1; Real* s = store; Real maxval = *s++; + while (l--) { Real a = *s++; if (maxval < a) maxval = a; } + ((GeneralMatrix&)*this).tDelete(); return maxval; +} + +Real GeneralMatrix::Maximum1(int& i) const +{ + REPORT + if (storage == 0) NullMatrixError(this); + int l = storage - 1; Real* s = store; Real maxval = *s++; int li = l; + while (l--) { Real a = *s++; if (maxval <= a) { maxval = a; li = l; } } + i = storage - li; + ((GeneralMatrix&)*this).tDelete(); return maxval; +} + +Real GeneralMatrix::Minimum() const +{ + REPORT + if (storage == 0) NullMatrixError(this); + int l = storage - 1; Real* s = store; Real minval = *s++; + while (l--) { Real a = *s++; if (minval > a) minval = a; } + ((GeneralMatrix&)*this).tDelete(); return minval; +} + +Real GeneralMatrix::Minimum1(int& i) const +{ + REPORT + if (storage == 0) NullMatrixError(this); + int l = storage - 1; Real* s = store; Real minval = *s++; int li = l; + while (l--) { Real a = *s++; if (minval >= a) { minval = a; li = l; } } + i = storage - li; + ((GeneralMatrix&)*this).tDelete(); return minval; +} + +Real GeneralMatrix::MaximumAbsoluteValue2(int& i, int& j) const +{ + REPORT + if (storage == 0) NullMatrixError(this); + Real maxval = 0.0; int nr = Nrows(); + MatrixRow mr((GeneralMatrix*)this, LoadOnEntry+DirectPart); + for (int r = 1; r <= nr; r++) + { + int c; maxval = mr.MaximumAbsoluteValue1(maxval, c); + if (c > 0) { i = r; j = c; } + mr.Next(); + } + ((GeneralMatrix&)*this).tDelete(); return maxval; +} + +Real GeneralMatrix::MinimumAbsoluteValue2(int& i, int& j) const +{ + REPORT + if (storage == 0) NullMatrixError(this); + Real minval = FloatingPointPrecision::Maximum(); int nr = Nrows(); + MatrixRow mr((GeneralMatrix*)this, LoadOnEntry+DirectPart); + for (int r = 1; r <= nr; r++) + { + int c; minval = mr.MinimumAbsoluteValue1(minval, c); + if (c > 0) { i = r; j = c; } + mr.Next(); + } + ((GeneralMatrix&)*this).tDelete(); return minval; +} + +Real GeneralMatrix::Maximum2(int& i, int& j) const +{ + REPORT + if (storage == 0) NullMatrixError(this); + Real maxval = -FloatingPointPrecision::Maximum(); int nr = Nrows(); + MatrixRow mr((GeneralMatrix*)this, LoadOnEntry+DirectPart); + for (int r = 1; r <= nr; r++) + { + int c; maxval = mr.Maximum1(maxval, c); + if (c > 0) { i = r; j = c; } + mr.Next(); + } + ((GeneralMatrix&)*this).tDelete(); return maxval; +} + +Real GeneralMatrix::Minimum2(int& i, int& j) const +{ + REPORT + if (storage == 0) NullMatrixError(this); + Real minval = FloatingPointPrecision::Maximum(); int nr = Nrows(); + MatrixRow mr((GeneralMatrix*)this, LoadOnEntry+DirectPart); + for (int r = 1; r <= nr; r++) + { + int c; minval = mr.Minimum1(minval, c); + if (c > 0) { i = r; j = c; } + mr.Next(); + } + ((GeneralMatrix&)*this).tDelete(); return minval; +} + +Real Matrix::MaximumAbsoluteValue2(int& i, int& j) const +{ + REPORT + int k; Real m = GeneralMatrix::MaximumAbsoluteValue1(k); k--; + i = k / Ncols(); j = k - i * Ncols(); i++; j++; + return m; +} + +Real Matrix::MinimumAbsoluteValue2(int& i, int& j) const +{ + REPORT + int k; Real m = GeneralMatrix::MinimumAbsoluteValue1(k); k--; + i = k / Ncols(); j = k - i * Ncols(); i++; j++; + return m; +} + +Real Matrix::Maximum2(int& i, int& j) const +{ + REPORT + int k; Real m = GeneralMatrix::Maximum1(k); k--; + i = k / Ncols(); j = k - i * Ncols(); i++; j++; + return m; +} + +Real Matrix::Minimum2(int& i, int& j) const +{ + REPORT + int k; Real m = GeneralMatrix::Minimum1(k); k--; + i = k / Ncols(); j = k - i * Ncols(); i++; j++; + return m; +} + +Real SymmetricMatrix::SumSquare() const +{ + REPORT + Real sum1 = 0.0; Real sum2 = 0.0; Real* s = store; int nr = nrows; + for (int i = 0; i<nr; i++) + { + int j = i; + while (j--) sum2 += square(*s++); + sum1 += square(*s++); + } + ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2; +} + +Real SymmetricMatrix::SumAbsoluteValue() const +{ + REPORT + Real sum1 = 0.0; Real sum2 = 0.0; Real* s = store; int nr = nrows; + for (int i = 0; i<nr; i++) + { + int j = i; + while (j--) sum2 += fabs(*s++); + sum1 += fabs(*s++); + } + ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2; +} + +Real IdentityMatrix::SumAbsoluteValue() const + { REPORT return fabs(Trace()); } // no need to do tDelete? + +Real SymmetricMatrix::Sum() const +{ + REPORT + Real sum1 = 0.0; Real sum2 = 0.0; Real* s = store; int nr = nrows; + for (int i = 0; i<nr; i++) + { + int j = i; + while (j--) sum2 += *s++; + sum1 += *s++; + } + ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2; +} + +Real IdentityMatrix::SumSquare() const +{ + Real sum = *store * *store * nrows; + ((GeneralMatrix&)*this).tDelete(); return sum; +} + + +Real BaseMatrix::SumSquare() const +{ + REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); + Real s = gm->SumSquare(); return s; +} + +Real BaseMatrix::NormFrobenius() const + { REPORT return sqrt(SumSquare()); } + +Real BaseMatrix::SumAbsoluteValue() const +{ + REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); + Real s = gm->SumAbsoluteValue(); return s; +} + +Real BaseMatrix::Sum() const +{ + REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); + Real s = gm->Sum(); return s; +} + +Real BaseMatrix::MaximumAbsoluteValue() const +{ + REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); + Real s = gm->MaximumAbsoluteValue(); return s; +} + +Real BaseMatrix::MaximumAbsoluteValue1(int& i) const +{ + REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); + Real s = gm->MaximumAbsoluteValue1(i); return s; +} + +Real BaseMatrix::MaximumAbsoluteValue2(int& i, int& j) const +{ + REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); + Real s = gm->MaximumAbsoluteValue2(i, j); return s; +} + +Real BaseMatrix::MinimumAbsoluteValue() const +{ + REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); + Real s = gm->MinimumAbsoluteValue(); return s; +} + +Real BaseMatrix::MinimumAbsoluteValue1(int& i) const +{ + REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); + Real s = gm->MinimumAbsoluteValue1(i); return s; +} + +Real BaseMatrix::MinimumAbsoluteValue2(int& i, int& j) const +{ + REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); + Real s = gm->MinimumAbsoluteValue2(i, j); return s; +} + +Real BaseMatrix::Maximum() const +{ + REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); + Real s = gm->Maximum(); return s; +} + +Real BaseMatrix::Maximum1(int& i) const +{ + REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); + Real s = gm->Maximum1(i); return s; +} + +Real BaseMatrix::Maximum2(int& i, int& j) const +{ + REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); + Real s = gm->Maximum2(i, j); return s; +} + +Real BaseMatrix::Minimum() const +{ + REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); + Real s = gm->Minimum(); return s; +} + +Real BaseMatrix::Minimum1(int& i) const +{ + REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); + Real s = gm->Minimum1(i); return s; +} + +Real BaseMatrix::Minimum2(int& i, int& j) const +{ + REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); + Real s = gm->Minimum2(i, j); return s; +} + +Real DotProduct(const Matrix& A, const Matrix& B) +{ + REPORT + int n = A.storage; + if (n != B.storage) Throw(IncompatibleDimensionsException(A,B)); + Real sum = 0.0; Real* a = A.store; Real* b = B.store; + while (n--) sum += *a++ * *b++; + return sum; +} + +Real Matrix::Trace() const +{ + REPORT + Tracer trace("Trace"); + int i = nrows; int d = i+1; + if (i != ncols) Throw(NotSquareException(*this)); + Real sum = 0.0; Real* s = store; +// while (i--) { sum += *s; s += d; } + if (i) for (;;) { sum += *s; if (!(--i)) break; s += d; } + ((GeneralMatrix&)*this).tDelete(); return sum; +} + +Real DiagonalMatrix::Trace() const +{ + REPORT + int i = nrows; Real sum = 0.0; Real* s = store; + while (i--) sum += *s++; + ((GeneralMatrix&)*this).tDelete(); return sum; +} + +Real SymmetricMatrix::Trace() const +{ + REPORT + int i = nrows; Real sum = 0.0; Real* s = store; int j = 2; + // while (i--) { sum += *s; s += j++; } + if (i) for (;;) { sum += *s; if (!(--i)) break; s += j++; } + ((GeneralMatrix&)*this).tDelete(); return sum; +} + +Real LowerTriangularMatrix::Trace() const +{ + REPORT + int i = nrows; Real sum = 0.0; Real* s = store; int j = 2; + // while (i--) { sum += *s; s += j++; } + if (i) for (;;) { sum += *s; if (!(--i)) break; s += j++; } + ((GeneralMatrix&)*this).tDelete(); return sum; +} + +Real UpperTriangularMatrix::Trace() const +{ + REPORT + int i = nrows; Real sum = 0.0; Real* s = store; + while (i) { sum += *s; s += i--; } // won t cause a problem + ((GeneralMatrix&)*this).tDelete(); return sum; +} + +Real BandMatrix::Trace() const +{ + REPORT + int i = nrows; int w = lower+upper+1; + Real sum = 0.0; Real* s = store+lower; + // while (i--) { sum += *s; s += w; } + if (i) for (;;) { sum += *s; if (!(--i)) break; s += w; } + ((GeneralMatrix&)*this).tDelete(); return sum; +} + +Real SymmetricBandMatrix::Trace() const +{ + REPORT + int i = nrows; int w = lower+1; + Real sum = 0.0; Real* s = store+lower; + // while (i--) { sum += *s; s += w; } + if (i) for (;;) { sum += *s; if (!(--i)) break; s += w; } + ((GeneralMatrix&)*this).tDelete(); return sum; +} + +Real IdentityMatrix::Trace() const +{ + Real sum = *store * nrows; + ((GeneralMatrix&)*this).tDelete(); return sum; +} + + +Real BaseMatrix::Trace() const +{ + REPORT + MatrixType Diag = MatrixType::Dg; Diag.SetDataLossOK(); + GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(Diag); + Real sum = gm->Trace(); return sum; +} + +void LogAndSign::operator*=(Real x) +{ + if (x > 0.0) { log_value += log(x); } + else if (x < 0.0) { log_value += log(-x); sign = -sign; } + else sign = 0; +} + +void LogAndSign::PowEq(int k) +{ + if (sign) + { + log_value *= k; + if ( (k & 1) == 0 ) sign = 1; + } +} + +Real LogAndSign::Value() const +{ + Tracer et("LogAndSign::Value"); + if (log_value >= FloatingPointPrecision::LnMaximum()) + Throw(OverflowException("Overflow in exponential")); + return sign * exp(log_value); +} + +LogAndSign::LogAndSign(Real f) +{ + if (f == 0.0) { log_value = 0.0; sign = 0; return; } + else if (f < 0.0) { sign = -1; f = -f; } + else sign = 1; + log_value = log(f); +} + +LogAndSign DiagonalMatrix::LogDeterminant() const +{ + REPORT + int i = nrows; LogAndSign sum; Real* s = store; + while (i--) sum *= *s++; + ((GeneralMatrix&)*this).tDelete(); return sum; +} + +LogAndSign LowerTriangularMatrix::LogDeterminant() const +{ + REPORT + int i = nrows; LogAndSign sum; Real* s = store; int j = 2; + // while (i--) { sum *= *s; s += j++; } + if (i) for(;;) { sum *= *s; if (!(--i)) break; s += j++; } + ((GeneralMatrix&)*this).tDelete(); return sum; +} + +LogAndSign UpperTriangularMatrix::LogDeterminant() const +{ + REPORT + int i = nrows; LogAndSign sum; Real* s = store; + while (i) { sum *= *s; s += i--; } + ((GeneralMatrix&)*this).tDelete(); return sum; +} + +LogAndSign IdentityMatrix::LogDeterminant() const +{ + REPORT + int i = nrows; LogAndSign sum; + if (i > 0) { sum = *store; sum.PowEq(i); } + ((GeneralMatrix&)*this).tDelete(); return sum; +} + +LogAndSign BaseMatrix::LogDeterminant() const +{ + REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); + LogAndSign sum = gm->LogDeterminant(); return sum; +} + +LogAndSign GeneralMatrix::LogDeterminant() const +{ + REPORT + Tracer tr("LogDeterminant"); + if (nrows != ncols) Throw(NotSquareException(*this)); + CroutMatrix C(*this); return C.LogDeterminant(); +} + +LogAndSign CroutMatrix::LogDeterminant() const +{ + REPORT + if (sing) return 0.0; + int i = nrows; int dd = i+1; LogAndSign sum; Real* s = store; + if (i) for(;;) + { + sum *= *s; + if (!(--i)) break; + s += dd; + } + if (!d) sum.ChangeSign(); return sum; + +} + +Real BaseMatrix::Determinant() const +{ + REPORT + Tracer tr("Determinant"); + REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); + LogAndSign ld = gm->LogDeterminant(); + return ld.Value(); +} + + + + + +LinearEquationSolver::LinearEquationSolver(const BaseMatrix& bm) +{ + gm = ((BaseMatrix&) bm ).Evaluate()->MakeSolver(); + if (gm==&bm) { REPORT gm = gm->Image(); } + // want a copy if *gm is actually bm + else { REPORT gm->Protect(); } +} + + +#ifdef use_namespace +} +#endif + diff --git a/Utilities/OSSIM/ossim_core/matrix/newmat9.cpp b/Utilities/OSSIM/ossim_core/matrix/newmat9.cpp new file mode 100644 index 0000000000..80500e6d6d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/newmat9.cpp @@ -0,0 +1,76 @@ +//$$ newmat9.cpp Input and output + +// Copyright (C) 1991,2,3,4: R B Davies + + +#define WANT_STREAM + +#include "include.h" + +#include "newmat.h" +#include "newmatio.h" +#include "newmatrc.h" + +#ifdef use_namespace +namespace NEWMAT { +#endif + +using namespace std; + +#ifdef DO_REPORT +#define REPORT { static ExeCounter ExeCount(__LINE__,9); ++ExeCount; } +#else +#define REPORT {} +#endif + +// for G++ 3.01 +#ifndef ios_format_flags +#define ios_format_flags long +#endif + +ostream& operator<<(ostream& s, const BaseMatrix& X) +{ + GeneralMatrix* gm = ((BaseMatrix&)X).Evaluate(); operator<<(s, *gm); + gm->tDelete(); return s; +} + + +ostream& operator<<(ostream& s, const GeneralMatrix& X) +{ + MatrixRow mr((GeneralMatrix*)&X, LoadOnEntry); + int w = s.width(); int nr = X.Nrows(); ios_format_flags f = s.flags(); + s.setf(ios::fixed, ios::floatfield); + for (int i=1; i<=nr; i++) + { + int skip = mr.skip; int storage = mr.storage; + Real* store = mr.data; skip *= w+1; + while (skip--) s << " "; + while (storage--) { s.width(w); s << *store++ << " "; } +// while (storage--) s << setw(w) << *store++ << " "; + mr.Next(); s << "\n"; + } + s << flush; s.flags(f); return s; +} + +// include this stuff if you are using an old version of G++ +// with an incomplete io library + +/* + +ostream& operator<<(ostream& os, Omanip_precision i) + { os.precision(i.x); return os; } + +Omanip_precision setprecision(int i) { return Omanip_precision(i); } + +ostream& operator<<(ostream& os, Omanip_width i) + { os.width(i.x); return os; } + +Omanip_width setw(int i) { return Omanip_width(i); } + +*/ + +#ifdef use_namespace +} +#endif + + diff --git a/Utilities/OSSIM/ossim_core/matrix/newmatap.h b/Utilities/OSSIM/ossim_core/matrix/newmatap.h new file mode 100644 index 0000000000..f25e6234f4 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/newmatap.h @@ -0,0 +1,201 @@ +//$$ newmatap.h definition file for matrix package applications + +// Copyright (C) 1991,2,3,4,8: R B Davies + +#ifndef NEWMATAP_LIB +#define NEWMATAP_LIB 0 + +#include "newmat.h" + +#ifdef use_namespace +namespace NEWMAT { +#endif + + +// ************************** applications *****************************/ + + +void QRZT(Matrix&, LowerTriangularMatrix&); + +void QRZT(const Matrix&, Matrix&, Matrix&); + +void QRZ(Matrix&, UpperTriangularMatrix&); + +void QRZ(const Matrix&, Matrix&, Matrix&); + +inline void HHDecompose(Matrix& X, LowerTriangularMatrix& L) +{ QRZT(X,L); } + +inline void HHDecompose(const Matrix& X, Matrix& Y, Matrix& M) +{ QRZT(X, Y, M); } + +void UpdateQRZT(Matrix& X, LowerTriangularMatrix& L); + +void UpdateQRZ(Matrix& X, UpperTriangularMatrix& U); + + +ReturnMatrix Cholesky(const SymmetricMatrix&); + +ReturnMatrix Cholesky(const SymmetricBandMatrix&); + + +// produces the Cholesky decomposition of A + x.t() * x where A = chol.t() * chol +// and x is a RowVector +void UpdateCholesky(UpperTriangularMatrix &chol, RowVector r1Modification); + +// produces the Cholesky decomposition of A - x.t() * x where A = chol.t() * chol +// and x is a RowVector +void DowndateCholesky(UpperTriangularMatrix &chol, RowVector x); + +// a RIGHT circular shift of the rows and columns from +// 1,...,k-1,k,k+1,...l,l+1,...,p to +// 1,...,k-1,l,k,k+1,...l-1,l+1,...p +void RightCircularUpdateCholesky(UpperTriangularMatrix &chol, int k, int l); + +// a LEFT circular shift of the rows and columns from +// 1,...,k-1,k,k+1,...l,l+1,...,p to +// 1,...,k-1,k+1,...l,k,l+1,...,p to +void LeftCircularUpdateCholesky(UpperTriangularMatrix &chol, int k, int l); + + +void SVD(const Matrix&, DiagonalMatrix&, Matrix&, Matrix&, + bool=true, bool=true); + +void SVD(const Matrix&, DiagonalMatrix&); + +inline void SVD(const Matrix& A, DiagonalMatrix& D, Matrix& U, + bool withU = true) { SVD(A, D, U, U, withU, false); } + +void SortSV(DiagonalMatrix& D, Matrix& U, bool ascending = false); + +void SortSV(DiagonalMatrix& D, Matrix& U, Matrix& V, bool ascending = false); + +void Jacobi(const SymmetricMatrix&, DiagonalMatrix&); + +void Jacobi(const SymmetricMatrix&, DiagonalMatrix&, SymmetricMatrix&); + +void Jacobi(const SymmetricMatrix&, DiagonalMatrix&, Matrix&); + +void Jacobi(const SymmetricMatrix&, DiagonalMatrix&, SymmetricMatrix&, + Matrix&, bool=true); + +void EigenValues(const SymmetricMatrix&, DiagonalMatrix&); + +void EigenValues(const SymmetricMatrix&, DiagonalMatrix&, SymmetricMatrix&); + +void EigenValues(const SymmetricMatrix&, DiagonalMatrix&, Matrix&); + +class SymmetricEigenAnalysis +// not implemented yet +{ +public: + SymmetricEigenAnalysis(const SymmetricMatrix&); +private: + DiagonalMatrix diag; + DiagonalMatrix offdiag; + SymmetricMatrix backtransform; + FREE_CHECK(SymmetricEigenAnalysis) +}; + +void SortAscending(GeneralMatrix&); + +void SortDescending(GeneralMatrix&); + + +// class for deciding which fft to use and containing new fft function +class FFT_Controller +{ +public: + static bool OnlyOldFFT; + static bool ar_1d_ft (int PTS, Real* X, Real *Y); + static bool CanFactor(int PTS); +}; + +void FFT(const ColumnVector&, const ColumnVector&, + ColumnVector&, ColumnVector&); + +void FFTI(const ColumnVector&, const ColumnVector&, + ColumnVector&, ColumnVector&); + +void RealFFT(const ColumnVector&, ColumnVector&, ColumnVector&); + +void RealFFTI(const ColumnVector&, const ColumnVector&, ColumnVector&); + +void DCT_II(const ColumnVector&, ColumnVector&); + +void DCT_II_inverse(const ColumnVector&, ColumnVector&); + +void DST_II(const ColumnVector&, ColumnVector&); + +void DST_II_inverse(const ColumnVector&, ColumnVector&); + +void DCT(const ColumnVector&, ColumnVector&); + +void DCT_inverse(const ColumnVector&, ColumnVector&); + +void DST(const ColumnVector&, ColumnVector&); + +void DST_inverse(const ColumnVector&, ColumnVector&); + +void FFT2(const Matrix& U, const Matrix& V, Matrix& X, Matrix& Y); + +void FFT2I(const Matrix& U, const Matrix& V, Matrix& X, Matrix& Y); + + +// This class is used by the new FFT program + +// Suppose an integer is expressed as a sequence of digits with each +// digit having a different radix. +// This class supposes we are counting with this multi-radix number +// but also keeps track of the number with the digits (and radices) +// reversed. +// The integer starts at zero +// operator++() increases it by 1 +// Counter gives the number of increments +// Reverse() gives the value with the digits in reverse order +// Swap is true if reverse is less than counter +// Finish is true when we have done a complete cycle and are back at zero + +class MultiRadixCounter +{ + const SimpleIntArray& Radix; + // radix of each digit + // n-1 highest order, 0 lowest order + SimpleIntArray& Value; // value of each digit + const int n; // number of digits + int reverse; // value when order of digits is reversed + int product; // product of radices + int counter; // counter + bool finish; // true when we have gone over whole range +public: + MultiRadixCounter(int nx, const SimpleIntArray& rx, + SimpleIntArray& vx); + void operator++(); // increment the multi-radix counter + bool Swap() const { return reverse < counter; } + bool Finish() const { return finish; } + int Reverse() const { return reverse; } + int Counter() const { return counter; } +}; + + +#ifdef use_namespace +} +#endif + + + +#endif + +// body file: cholesky.cpp +// body file: evalue.cpp +// body file: fft.cpp +// body file: hholder.cpp +// body file: jacobi.cpp +// body file: newfft.cpp +// body file: sort.cpp +// body file: svd.cpp + + + + + diff --git a/Utilities/OSSIM/ossim_core/matrix/newmatex.cpp b/Utilities/OSSIM/ossim_core/matrix/newmatex.cpp new file mode 100644 index 0000000000..55e393bf91 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/newmatex.cpp @@ -0,0 +1,313 @@ +//$$ newmatex.cpp Exception handler + +// Copyright (C) 1992,3,4,7: R B Davies + +#define WANT_STREAM // include.h will get stream fns + +#include "include.h" // include standard files +#include "newmat.h" + +#ifdef use_namespace +namespace NEWMAT { +#endif + +unsigned long OverflowException::Select; +unsigned long SingularException::Select; +unsigned long NPDException::Select; +unsigned long ConvergenceException::Select; +unsigned long ProgramException::Select; +unsigned long IndexException::Select; +unsigned long VectorException::Select; +unsigned long NotSquareException::Select; +unsigned long SubMatrixDimensionException::Select; +unsigned long IncompatibleDimensionsException::Select; +unsigned long NotDefinedException::Select; +unsigned long CannotBuildException::Select; +unsigned long InternalException::Select; + + + +static void MatrixDetails(const GeneralMatrix& A) +// write matrix details to Exception buffer +{ + MatrixBandWidth bw = A.BandWidth(); int ubw = bw.upper; int lbw = bw.lower; + BaseException::AddMessage("MatrixType = "); + BaseException::AddMessage(A.Type().Value()); + BaseException::AddMessage(" # Rows = "); BaseException::AddInt(A.Nrows()); + BaseException::AddMessage("; # Cols = "); BaseException::AddInt(A.Ncols()); + if (lbw >=0) + { + BaseException::AddMessage("; lower BW = "); + BaseException::AddInt(lbw); + } + if (ubw >=0) + { + BaseException::AddMessage("; upper BW = "); + BaseException::AddInt(ubw); + } + BaseException::AddMessage("\n"); +} + +NPDException::NPDException(const GeneralMatrix& A) + : Runtime_error() +{ + Select = BaseException::Select; + AddMessage("detected by Newmat: matrix not positive definite\n\n"); + MatrixDetails(A); + Tracer::AddTrace(); +} + +SingularException::SingularException(const GeneralMatrix& A) + : Runtime_error() +{ + Select = BaseException::Select; + AddMessage("detected by Newmat: matrix is singular\n\n"); + MatrixDetails(A); + Tracer::AddTrace(); +} + +ConvergenceException::ConvergenceException(const GeneralMatrix& A) + : Runtime_error() +{ + Select = BaseException::Select; + AddMessage("detected by Newmat: process fails to converge\n\n"); + MatrixDetails(A); + Tracer::AddTrace(); +} + +ConvergenceException::ConvergenceException(const char* c) : Runtime_error() +{ + Select = BaseException::Select; + AddMessage("detected by Newmat: "); + AddMessage(c); AddMessage("\n\n"); + if (c) Tracer::AddTrace(); +} + +OverflowException::OverflowException(const char* c) : Runtime_error() +{ + Select = BaseException::Select; + AddMessage("detected by Newmat: "); + AddMessage(c); AddMessage("\n\n"); + if (c) Tracer::AddTrace(); +} + +ProgramException::ProgramException(const char* c) : Logic_error() +{ + Select = BaseException::Select; + AddMessage("detected by Newmat: "); + AddMessage(c); AddMessage("\n\n"); + if (c) Tracer::AddTrace(); +} + +ProgramException::ProgramException(const char* c, const GeneralMatrix& A) + : Logic_error() +{ + Select = BaseException::Select; + AddMessage("detected by Newmat: "); + AddMessage(c); AddMessage("\n\n"); + MatrixDetails(A); + if (c) Tracer::AddTrace(); +} + +ProgramException::ProgramException(const char* c, const GeneralMatrix& A, + const GeneralMatrix& B) : Logic_error() +{ + Select = BaseException::Select; + AddMessage("detected by Newmat: "); + AddMessage(c); AddMessage("\n\n"); + MatrixDetails(A); MatrixDetails(B); + if (c) Tracer::AddTrace(); +} + +ProgramException::ProgramException(const char* c, MatrixType a, MatrixType b) + : Logic_error() +{ + Select = BaseException::Select; + AddMessage("detected by Newmat: "); + AddMessage(c); AddMessage("\nMatrixTypes = "); + AddMessage(a.Value()); AddMessage("; "); + AddMessage(b.Value()); AddMessage("\n\n"); + if (c) Tracer::AddTrace(); +} + +VectorException::VectorException() : Logic_error() +{ + Select = BaseException::Select; + AddMessage("detected by Newmat: cannot convert matrix to vector\n\n"); + Tracer::AddTrace(); +} + +VectorException::VectorException(const GeneralMatrix& A) + : Logic_error() +{ + Select = BaseException::Select; + AddMessage("detected by Newmat: cannot convert matrix to vector\n\n"); + MatrixDetails(A); + Tracer::AddTrace(); +} + +NotSquareException::NotSquareException(const GeneralMatrix& A) + : Logic_error() +{ + Select = BaseException::Select; + AddMessage("detected by Newmat: matrix is not square\n\n"); + MatrixDetails(A); + Tracer::AddTrace(); +} + +NotSquareException::NotSquareException() + : Logic_error() +{ + Select = BaseException::Select; + AddMessage("detected by Newmat: matrix is not square\n\n"); + Tracer::AddTrace(); +} + +SubMatrixDimensionException::SubMatrixDimensionException() + : Logic_error() +{ + Select = BaseException::Select; + AddMessage("detected by Newmat: incompatible submatrix dimension\n\n"); + Tracer::AddTrace(); +} + +IncompatibleDimensionsException::IncompatibleDimensionsException() + : Logic_error() +{ + Select = BaseException::Select; + AddMessage("detected by Newmat: incompatible dimensions\n\n"); + Tracer::AddTrace(); +} + +IncompatibleDimensionsException::IncompatibleDimensionsException + (const GeneralMatrix& A, const GeneralMatrix& B) + : Logic_error() +{ + Select = BaseException::Select; + AddMessage("detected by Newmat: incompatible dimensions\n\n"); + MatrixDetails(A); MatrixDetails(B); + Tracer::AddTrace(); +} + +NotDefinedException::NotDefinedException(const char* op, const char* matrix) + : Logic_error() +{ + Select = BaseException::Select; + AddMessage("detected by Newmat: "); + AddMessage(op); + AddMessage(" not defined for "); + AddMessage(matrix); + AddMessage("\n\n"); + Tracer::AddTrace(); +} + +CannotBuildException::CannotBuildException(const char* matrix) + : Logic_error() +{ + Select = BaseException::Select; + AddMessage("detected by Newmat: cannot build matrix type "); + AddMessage(matrix); AddMessage("\n\n"); + Tracer::AddTrace(); +} + +IndexException::IndexException(int i, const GeneralMatrix& A) + : Logic_error() +{ + Select = BaseException::Select; + AddMessage("detected by Newmat: index error: requested index = "); + AddInt(i); AddMessage("\n\n"); + MatrixDetails(A); + Tracer::AddTrace(); +} + +IndexException::IndexException(int i, int j, const GeneralMatrix& A) + : Logic_error() +{ + Select = BaseException::Select; + AddMessage("detected by Newmat: index error: requested indices = "); + AddInt(i); AddMessage(", "); AddInt(j); + AddMessage("\n\n"); + MatrixDetails(A); + Tracer::AddTrace(); +} + + +IndexException::IndexException(int i, const GeneralMatrix& A, bool) + : Logic_error() +{ + Select = BaseException::Select; + AddMessage("detected by Newmat: element error: requested index (wrt 0) = "); + AddInt(i); + AddMessage("\n\n"); + MatrixDetails(A); + Tracer::AddTrace(); +} + +IndexException::IndexException(int i, int j, const GeneralMatrix& A, bool) + : Logic_error() +{ + Select = BaseException::Select; + AddMessage( + "detected by Newmat: element error: requested indices (wrt 0) = "); + AddInt(i); AddMessage(", "); AddInt(j); + AddMessage("\n\n"); + MatrixDetails(A); + Tracer::AddTrace(); +} + +InternalException::InternalException(const char* c) : Logic_error() +{ + Select = BaseException::Select; + AddMessage("internal error detected by Newmat: please inform author\n"); + AddMessage(c); AddMessage("\n\n"); + Tracer::AddTrace(); +} + + + + +/************************* ExeCounter functions *****************************/ + +#ifdef DO_REPORT + +int ExeCounter::nreports; // will be set to zero + +ExeCounter::ExeCounter(int xl, int xf) : line(xl), fileid(xf), nexe(0) {} + +ExeCounter::~ExeCounter() +{ + nreports++; + cout << "REPORT " << setw(6) << nreports << " " + << setw(6) << fileid << " " << setw(6) << line + << " " << setw(6) << nexe << "\n"; +} + +#endif + +/**************************** error handler *******************************/ + +void MatrixErrorNoSpace(const void* v) { if (!v) Throw(Bad_alloc()); } +// throw exception if v is null + + + + +/************************* miscellanous errors ***************************/ + + +void CroutMatrix::GetRow(MatrixRowCol&) + { Throw(NotDefinedException("GetRow","Crout")); } +void CroutMatrix::GetCol(MatrixRowCol&) + { Throw(NotDefinedException("GetCol","Crout")); } +void BandLUMatrix::GetRow(MatrixRowCol&) + { Throw(NotDefinedException("GetRow","BandLUMatrix")); } +void BandLUMatrix::GetCol(MatrixRowCol&) + { Throw(NotDefinedException("GetCol","BandLUMatrix")); } +void BaseMatrix::IEQND() const + { Throw(NotDefinedException("inequalities", "matrices")); } + + +#ifdef use_namespace +} +#endif + diff --git a/Utilities/OSSIM/ossim_core/matrix/newmatio.h b/Utilities/OSSIM/ossim_core/matrix/newmatio.h new file mode 100644 index 0000000000..af8231d9c1 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/newmatio.h @@ -0,0 +1,61 @@ +//$$ newmatio.h definition file for matrix package input/output + +// Copyright (C) 1991,2,3,4: R B Davies + +#ifndef NEWMATIO_LIB +#define NEWMATIO_LIB 0 + +#ifndef WANT_STREAM +#define WANT_STREAM +#endif + +#include "newmat.h" + +#ifdef use_namespace +namespace NEWMAT { +#endif + + + +/**************************** input/output *****************************/ + + OSSIM_DLL std::ostream& operator<<(std::ostream&, const BaseMatrix&); + + OSSIM_DLL std::ostream& operator<<(std::ostream&, const GeneralMatrix&); + + +/* Use in some old versions of G++ without complete iomanipulators + +class Omanip_precision +{ + int x; +public: + Omanip_precision(int i) : x(i) {} + friend ostream& operator<<(ostream& os, Omanip_precision i); +}; + + +Omanip_precision setprecision(int i); + +class Omanip_width +{ + int x; +public: + Omanip_width(int i) : x(i) {} + friend ostream& operator<<(ostream& os, Omanip_width i); +}; + +Omanip_width setw(int i); + +*/ + +#ifdef use_namespace +} +#endif + + + +#endif + +// body file: newmat9.cpp + diff --git a/Utilities/OSSIM/ossim_core/matrix/newmatnl.cpp b/Utilities/OSSIM/ossim_core/matrix/newmatnl.cpp new file mode 100644 index 0000000000..ba0140c99f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/newmatnl.cpp @@ -0,0 +1,260 @@ +//$$ newmatnl.cpp Non-linear optimisation + +// Copyright (C) 1993,4,5,6: R B Davies + + +#define WANT_MATH +#define WANT_STREAM + +#include "newmatap.h" +#include "newmatnl.h" + +#ifdef use_namespace +namespace NEWMAT { +#endif + +using namespace std; + +void FindMaximum2::Fit(ColumnVector& Theta, int n_it) +{ + Tracer tr("FindMaximum2::Fit"); + enum State {Start, Restart, Continue, Interpolate, Extrapolate, + Fail, Convergence}; + State TheState = Start; + Real z,w,x,x2,g,l1,l2,l3,d1,d2=0,d3; + ColumnVector Theta1, Theta2, Theta3; + int np = Theta.Nrows(); + ColumnVector H1(np), H3, HP(np), K, K1(np); + bool oorg, conv; + int counter = 0; + Theta1 = Theta; HP = 0.0; g = 0.0; + + // This is really a set of gotos and labels, but they do not work + // correctly in AT&T C++ and Sun 4.01 C++. + + for(;;) + { + switch (TheState) + { + case Start: + tr.ReName("FindMaximum2::Fit/Start"); + Value(Theta1, true, l1, oorg); + if (oorg) Throw(ProgramException("invalid starting value\n")); + + case Restart: + tr.ReName("FindMaximum2::Fit/ReStart"); + conv = NextPoint(H1, d1); + if (conv) { TheState = Convergence; break; } + if (counter++ > n_it) { TheState = Fail; break; } + + z = 1.0 / sqrt(d1); + H3 = H1 * z; K = (H3 - HP) * g; HP = H3; + g = 0.0; // de-activate to use curved projection + if (g==0.0) K1 = 0.0; else K1 = K * 0.2 + K1 * 0.6; + // (K - K1) * alpha + K1 * (1 - alpha) + // = K * alpha + K1 * (1 - 2 * alpha) + K = K1 * d1; g = z; + + case Continue: + tr.ReName("FindMaximum2::Fit/Continue"); + Theta2 = Theta1 + H1 + K; + Value(Theta2, false, l2, oorg); + if (counter++ > n_it) { TheState = Fail; break; } + if (oorg) + { + H1 *= 0.5; K *= 0.25; d1 *= 0.5; g *= 2.0; + TheState = Continue; break; + } + d2 = LastDerivative(H1 + K * 2.0); + + case Interpolate: + tr.ReName("FindMaximum2::Fit/Interpolate"); + z = d1 + d2 - 3.0 * (l2 - l1); + w = z * z - d1 * d2; + if (w < 0.0) { TheState = Extrapolate; break; } + w = z + sqrt(w); + if (1.5 * w + d1 < 0.0) + { TheState = Extrapolate; break; } + if (d2 > 0.0 && l2 > l1 && w > 0.0) + { TheState = Extrapolate; break; } + x = d1 / (w + d1); x2 = x * x; g /= x; + Theta3 = Theta1 + H1 * x + K * x2; + Value(Theta3, true, l3, oorg); + if (counter++ > n_it) { TheState = Fail; break; } + if (oorg) + { + if (x <= 1.0) + { x *= 0.5; x2 = x*x; g *= 2.0; d1 *= x; H1 *= x; K *= x2; } + else + { + x = 0.5 * (x-1.0); x2 = x*x; Theta1 = Theta2; + H1 = (H1 + K * 2.0) * x; + K *= x2; g = 0.0; d1 = x * d2; l1 = l2; + } + TheState = Continue; break; + } + + if (l3 >= l1 && l3 >= l2) + { Theta1 = Theta3; l1 = l3; TheState = Restart; break; } + + d3 = LastDerivative(H1 + K * 2.0); + if (l1 > l2) + { H1 *= x; K *= x2; Theta2 = Theta3; d1 *= x; d2 = d3*x; } + else + { + Theta1 = Theta2; Theta2 = Theta3; + x -= 1.0; x2 = x*x; g = 0.0; H1 = (H1 + K * 2.0) * x; + K *= x2; l1 = l2; l2 = l3; d1 = x*d2; d2 = x*d3; + if (d1 <= 0.0) { TheState = Start; break; } + } + TheState = Interpolate; break; + + case Extrapolate: + tr.ReName("FindMaximum2::Fit/Extrapolate"); + Theta1 = Theta2; g = 0.0; K *= 4.0; H1 = (H1 * 2.0 + K); + d1 = 2.0 * d2; l1 = l2; + TheState = Continue; break; + + case Fail: + Throw(ConvergenceException(Theta)); + + case Convergence: + Theta = Theta1; return; + } + } +} + + + +void NonLinearLeastSquares::Value + (const ColumnVector& Parameters, bool, Real& v, bool& oorg) +{ + Tracer tr("NonLinearLeastSquares::Value"); + Y.ReSize(n_obs); X.ReSize(n_obs,n_param); + // put the fitted values in Y, the derivatives in X. + Pred.Set(Parameters); + if (!Pred.IsValid()) { oorg=true; return; } + for (int i=1; i<=n_obs; i++) + { + Y(i) = Pred(i); + X.Row(i) = Pred.Derivatives(); + } + if (!Pred.IsValid()) { oorg=true; return; } // check afterwards as well + Y = *DataPointer - Y; Real ssq = Y.SumSquare(); + errorvar = ssq / (n_obs - n_param); + cout << endl; + cout << setw(15) << setprecision(10) << " " << errorvar; + Derivs = Y.t() * X; // get the derivative and stash it + oorg = false; v = -0.5 * ssq; +} + +bool NonLinearLeastSquares::NextPoint(ColumnVector& Adj, Real& test) +{ + Tracer tr("NonLinearLeastSquares::NextPoint"); + QRZ(X, U); QRZ(X, Y, M); // do the QR decomposition + test = M.SumSquare(); + cout << " " << setw(15) << setprecision(10) + << test << " " << Y.SumSquare() / (n_obs - n_param); + Adj = U.i() * M; + if (test < errorvar * criterion) return true; + else return false; +} + +Real NonLinearLeastSquares::LastDerivative(const ColumnVector& H) +{ return (Derivs * H).AsScalar(); } + +void NonLinearLeastSquares::Fit(const ColumnVector& Data, + ColumnVector& Parameters) +{ + Tracer tr("NonLinearLeastSquares::Fit"); + n_param = Parameters.Nrows(); n_obs = Data.Nrows(); + DataPointer = &Data; + FindMaximum2::Fit(Parameters, Lim); + cout << "\nConverged" << endl; +} + +void NonLinearLeastSquares::MakeCovariance() +{ + if (Covariance.Nrows()==0) + { + UpperTriangularMatrix UI = U.i(); + Covariance << UI * UI.t() * errorvar; + SE << Covariance; // get diagonals + for (int i = 1; i<=n_param; i++) SE(i) = sqrt(SE(i)); + } +} + +void NonLinearLeastSquares::GetStandardErrors(ColumnVector& SEX) + { MakeCovariance(); SEX = SE.AsColumn(); } + +void NonLinearLeastSquares::GetCorrelations(SymmetricMatrix& Corr) + { MakeCovariance(); Corr << SE.i() * Covariance * SE.i(); } + +void NonLinearLeastSquares::GetHatDiagonal(DiagonalMatrix& Hat) const +{ + Hat.ReSize(n_obs); + for (int i = 1; i<=n_obs; i++) Hat(i) = X.Row(i).SumSquare(); +} + + +// the MLE_D_FI routines + +void MLE_D_FI::Value + (const ColumnVector& Parameters, bool wg, Real& v, bool& oorg) +{ + Tracer tr("MLE_D_FI::Value"); + if (!LL.IsValid(Parameters,wg)) { oorg=true; return; } + v = LL.LogLikelihood(); + if (!LL.IsValid()) { oorg=true; return; } // check validity again + cout << endl; + cout << setw(20) << setprecision(10) << v; + oorg = false; + Derivs = LL.Derivatives(); // Get derivatives +} + +bool MLE_D_FI::NextPoint(ColumnVector& Adj, Real& test) +{ + Tracer tr("MLE_D_FI::NextPoint"); + SymmetricMatrix FI = LL.FI(); + LT = Cholesky(FI); + ColumnVector Adj1 = LT.i() * Derivs; + Adj = LT.t().i() * Adj1; + test = SumSquare(Adj1); + cout << " " << setw(20) << setprecision(10) << test; + return (test < Criterion); +} + +Real MLE_D_FI::LastDerivative(const ColumnVector& H) +{ return (Derivs.t() * H).AsScalar(); } + +void MLE_D_FI::Fit(ColumnVector& Parameters) +{ + Tracer tr("MLE_D_FI::Fit"); + FindMaximum2::Fit(Parameters,Lim); + cout << "\nConverged" << endl; +} + +void MLE_D_FI::MakeCovariance() +{ + if (Covariance.Nrows()==0) + { + LowerTriangularMatrix LTI = LT.i(); + Covariance << LTI.t() * LTI; + SE << Covariance; // get diagonal + int n = Covariance.Nrows(); + for (int i=1; i <= n; i++) SE(i) = sqrt(SE(i)); + } +} + +void MLE_D_FI::GetStandardErrors(ColumnVector& SEX) +{ MakeCovariance(); SEX = SE.AsColumn(); } + +void MLE_D_FI::GetCorrelations(SymmetricMatrix& Corr) +{ MakeCovariance(); Corr << SE.i() * Covariance * SE.i(); } + + + +#ifdef use_namespace +} +#endif + diff --git a/Utilities/OSSIM/ossim_core/matrix/newmatnl.h b/Utilities/OSSIM/ossim_core/matrix/newmatnl.h new file mode 100644 index 0000000000..9f49adc040 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/newmatnl.h @@ -0,0 +1,322 @@ +//$$ newmatnl.h definition file for non-linear optimisation + +// Copyright (C) 1993,4,5: R B Davies + +#ifndef NEWMATNL_LIB +#define NEWMATNL_LIB 0 + +#include "newmat.h" + +#ifdef use_namespace +namespace NEWMAT { +#endif + + + +/* + +This is a beginning of a series of classes for non-linear optimisation. + +At present there are two classes. FindMaximum2 is the basic optimisation +strategy when one is doing an optimisation where one has first +derivatives and estimates of the second derivatives. Class +NonLinearLeastSquares is derived from FindMaximum2. This provides the +functions that calculate function values and derivatives. + +A third class is now added. This is for doing maximum-likelihood when +you have first derviatives and something like the Fisher Information +matrix (eg the variance covariance matrix of the first derivatives or +minus the second derivatives - this matrix is assumed to be positive +definite). + + + + class FindMaximum2 + +Suppose T is the ColumnVector of parameters, F(T) the function we want +to maximise, D(T) the ColumnVector of derivatives of F with respect to +T, and S(T) the matrix of second derivatives. + +Then the basic iteration is given a value of T, update it to + + T - S.i() * D + +where .i() denotes inverse. + +If F was quadratic this would give exactly the right answer (except it +might get a minimum rather than a maximum). Since F is not usually +quadratic, the simple procedure would be to recalculate S and D with the +new value of T and keep iterating until the process converges. This is +known as the method of conjugate gradients. + +In practice, this method may not converge. FindMaximum2 considers an +iteration of the form + + T - x * S.i() * D + +where x is a number. It tries x = 1 and uses the values of F and its +slope with respect to x at x = 0 and x = 1 to fit a cubic in x. It then +choses x to maximise the resulting function. This gives our new value of +T. The program checks that the value of F is getting better and carries +out a variety of strategies if it is not. + +The program also has a second strategy. If the successive values of T +seem to be lying along a curve - eg we are following along a curved +ridge, the program will try to fit this ridge and project along it. This +does not work at present and is commented out. + +FindMaximum2 has three virtual functions which need to be over-ridden by +a derived class. + + void Value(const ColumnVector& T, bool wg, Real& f, bool& oorg); + +T is the column vector of parameters. The function returns the value of +the function to f, but may instead set oorg to true if the parameter +values are not valid. If wg is true it may also calculate and store the +second derivative information. + + bool NextPoint(ColumnVector& H, Real& d); + +Using the value of T provided in the previous call of Value, find the +conjugate gradients adjustment to T, that is - S.i() * D. Also return + + d = D.t() * S.i() * D. + +NextPoint should return true if it considers that the process has +converged (d very small) and false otherwise. The previous call of Value +will have set wg to true, so that S will be available. + + Real LastDerivative(const ColumnVector& H); + +Return the scalar product of H and the vector of derivatives at the last +value of T. + +The function Fit is the function that calls the iteration. + + void Fit(ColumnVector&, int); + +The arguments are the trial parameter values as a ColumnVector and the +maximum number of iterations. The program calls a DataException if the +initial parameters are not valid and a ConvergenceException if the +process fails to converge. + + + class NonLinearLeastSquares + +This class is derived from FindMaximum2 and carries out a non-linear +least squares fit. It uses a QR decomposition to carry out the +operations required by FindMaximum2. + +A prototype class R1_Col_I_D is provided. The user needs to derive a +class from this which includes functions the predicted value of each +observation its derivatives. An object from this class has to be +provided to class NonLinearLeastSquares. + +Suppose we observe n normal random variables with the same unknown +variance and such the i-th one has expected value given by f(i,P) +where P is a column vector of unknown parameters and f is a known +function. We wish to estimate P. + +First derive a class from R1_Col_I_D and override Real operator()(int i) +to give the value of the function f in terms of i and the ColumnVector +para defined in class R1_CoL_I_D. Also override ReturnMatrix +Derivatives() to give the derivates of f at para and the value of i +used in the preceeding call to operator(). Return the result as a +RowVector. Construct an object from this class. Suppose in what follows +it is called pred. + +Now constuct a NonLinearLeastSquaresObject accessing pred and optionally +an iteration limit and an accuracy critierion. + + NonLinearLeastSquares NLLS(pred, 1000, 0.0001); + +The accuracy critierion should be somewhat less than one and 0.0001 is +about the smallest sensible value. + +Define a ColumnVector P containing a guess at the value of the unknown +parameter, and a ColumnVector Y containing the unknown data. Call + + NLLS.Fit(Y,P); + +If the process converges, P will contain the estimates of the unknown +parameters. If it does not converge an exception will be generated. + +The following member functions can be called after you have done a fit. + +Real ResidualVariance() const; + +The estimate of the variance of the observations. + +void GetResiduals(ColumnVector& Z) const; + +The residuals of the individual observations. + +void GetStandardErrors(ColumnVector&); + +The standard errors of the observations. + +void GetCorrelations(SymmetricMatrix&); + +The correlations of the observations. + +void GetHatDiagonal(DiagonalMatrix&) const; + +Forms a diagonal matrix of values between 0 and 1. If the i-th value is +larger than, say 0.2, then the i-th data value could have an undue +influence on your estimates. + + +*/ + +class FindMaximum2 +{ + virtual void Value(const ColumnVector&, bool, Real&, bool&) = 0; + virtual bool NextPoint(ColumnVector&, Real&) = 0; + virtual Real LastDerivative(const ColumnVector&) = 0; +public: + void Fit(ColumnVector&, int); + virtual ~FindMaximum2() {} // to keep gnu happy +}; + +class R1_Col_I_D +{ + // The prototype for a Real function of a ColumnVector and an + // integer. + // You need to derive your function from this one and put in your + // function for operator() and Derivatives() at least. + // You may also want to set up a constructor to enter in additional + // parameter values (that will not vary during the solve). + +protected: + ColumnVector para; // Current x value + +public: + virtual bool IsValid() { return true; } + // is the current x value OK + virtual Real operator()(int i) = 0; // i-th function value at current para + virtual void Set(const ColumnVector& X) { para = X; } + // set current para + bool IsValid(const ColumnVector& X) + { Set(X); return IsValid(); } + // set para, check OK + Real operator()(int i, const ColumnVector& X) + { Set(X); return operator()(i); } + // set para, return value + virtual ReturnMatrix Derivatives() = 0; + // return derivatives as RowVector + virtual ~R1_Col_I_D() {} // to keep gnu happy +}; + + +class NonLinearLeastSquares : public FindMaximum2 +{ + // these replace the corresponding functions in FindMaximum2 + void Value(const ColumnVector&, bool, Real&, bool&); + bool NextPoint(ColumnVector&, Real&); + Real LastDerivative(const ColumnVector&); + + Matrix X; // the things we need to do the + ColumnVector Y; // QR triangularisation + UpperTriangularMatrix U; // see the write-up in newmata.txt + ColumnVector M; + Real errorvar, criterion; + int n_obs, n_param; + const ColumnVector* DataPointer; + RowVector Derivs; + SymmetricMatrix Covariance; + DiagonalMatrix SE; + R1_Col_I_D& Pred; // Reference to predictor object + int Lim; // maximum number of iterations + +public: + NonLinearLeastSquares(R1_Col_I_D& pred, int lim=1000, Real crit=0.0001) + : criterion(crit), Pred(pred), Lim(lim) {} + void Fit(const ColumnVector&, ColumnVector&); + Real ResidualVariance() const { return errorvar; } + void GetResiduals(ColumnVector& Z) const { Z = Y; } + void GetStandardErrors(ColumnVector&); + void GetCorrelations(SymmetricMatrix&); + void GetHatDiagonal(DiagonalMatrix&) const; + +private: + void MakeCovariance(); +}; + + +// The next class is the prototype class for calculating the +// log-likelihood. +// I assume first derivatives are available and something like the +// Fisher Information or variance/covariance matrix of the first +// derivatives or minus the matrix of second derivatives is +// available. This matrix must be positive definite. + +class LL_D_FI +{ +protected: + ColumnVector para; // current parameter values + bool wg; // true if FI matrix wanted + +public: + virtual void Set(const ColumnVector& X) { para = X; } + // set parameter values + virtual void WG(bool wgx) { wg = wgx; } + // set wg + + virtual bool IsValid() { return true; } + // return true is para is OK + bool IsValid(const ColumnVector& X, bool wgx=true) + { Set(X); WG(wgx); return IsValid(); } + + virtual Real LogLikelihood() = 0; // return the loglikelihhod + Real LogLikelihood(const ColumnVector& X, bool wgx=true) + { Set(X); WG(wgx); return LogLikelihood(); } + + virtual ReturnMatrix Derivatives() = 0; + // column vector of derivatives + virtual ReturnMatrix FI() = 0; // Fisher Information matrix + virtual ~LL_D_FI() {} // to keep gnu happy +}; + +// This is the class for doing the maximum likelihood estimation + +class MLE_D_FI : public FindMaximum2 +{ + // these replace the corresponding functions in FindMaximum2 + void Value(const ColumnVector&, bool, Real&, bool&); + bool NextPoint(ColumnVector&, Real&); + Real LastDerivative(const ColumnVector&); + + // the things we need for the analysis + LL_D_FI& LL; // reference to log-likelihood + int Lim; // maximum number of iterations + Real Criterion; // convergence criterion + ColumnVector Derivs; // for the derivatives + LowerTriangularMatrix LT; // Cholesky decomposition of FI + SymmetricMatrix Covariance; + DiagonalMatrix SE; + +public: + MLE_D_FI(LL_D_FI& ll, int lim=1000, Real criterion=0.0001) + : LL(ll), Lim(lim), Criterion(criterion) {} + void Fit(ColumnVector& Parameters); + void GetStandardErrors(ColumnVector&); + void GetCorrelations(SymmetricMatrix&); + +private: + void MakeCovariance(); +}; + + +#ifdef use_namespace +} +#endif + + + +#endif + +// body file: newmatnl.cpp + + + + diff --git a/Utilities/OSSIM/ossim_core/matrix/newmatrc.h b/Utilities/OSSIM/ossim_core/matrix/newmatrc.h new file mode 100644 index 0000000000..ac62825745 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/newmatrc.h @@ -0,0 +1,171 @@ +//$$ newmatrc.h definition file for row/column classes + +// Copyright (C) 1991,2,3,4,7: R B Davies + +#ifndef NEWMATRC_LIB +#define NEWMATRC_LIB 0 + +#ifdef use_namespace +namespace NEWMAT { +#endif + +#include "controlw.h" + + +/************** classes MatrixRowCol, MatrixRow, MatrixCol *****************/ + +// Used for accessing the rows and columns of matrices +// All matrix classes must provide routines for calculating matrix rows and +// columns. Assume rows can be found very efficiently. + +enum LSF { LoadOnEntry=1,StoreOnExit=2,DirectPart=4,StoreHere=8,HaveStore=16 }; + + +class LoadAndStoreFlag : public ControlWord +{ +public: + LoadAndStoreFlag() {} + LoadAndStoreFlag(int i) : ControlWord(i) {} + LoadAndStoreFlag(LSF lsf) : ControlWord(lsf) {} + LoadAndStoreFlag(const ControlWord& cwx) : ControlWord(cwx) {} +}; + +class MatrixRowCol +// the row or column of a matrix +{ +public: // these are public to avoid + // numerous friend statements + int length; // row or column length + int skip; // initial number of zeros + int storage; // number of stored elements + int rowcol; // row or column number + GeneralMatrix* gm; // pointer to parent matrix + Real* data; // pointer to local storage + LoadAndStoreFlag cw; // Load? Store? Is a Copy? + void IncrMat() { rowcol++; data += storage; } // used by NextRow + void IncrDiag() { rowcol++; skip++; data++; } + void IncrId() { rowcol++; skip++; } + void IncrUT() { rowcol++; data += storage; storage--; skip++; } + void IncrLT() { rowcol++; data += storage; storage++; } + +public: + void Zero(); // set elements to zero + void Add(const MatrixRowCol&); // add a row/col + void AddScaled(const MatrixRowCol&, Real); // add a multiple of a row/col + void Add(const MatrixRowCol&, const MatrixRowCol&); + // add two rows/cols + void Add(const MatrixRowCol&, Real); // add a row/col + void NegAdd(const MatrixRowCol&, Real); // Real - a row/col + void Sub(const MatrixRowCol&); // subtract a row/col + void Sub(const MatrixRowCol&, const MatrixRowCol&); + // sub a row/col from another + void RevSub(const MatrixRowCol&); // subtract from a row/col + void ConCat(const MatrixRowCol&, const MatrixRowCol&); + // concatenate two row/cols + void Multiply(const MatrixRowCol&); // multiply a row/col + void Multiply(const MatrixRowCol&, const MatrixRowCol&); + // multiply two row/cols + void KP(const MatrixRowCol&, const MatrixRowCol&); + // Kronecker Product two row/cols + void Copy(const MatrixRowCol&); // copy a row/col + void CopyCheck(const MatrixRowCol&); // ... check for data loss + void Check(const MatrixRowCol&); // just check for data loss + void Check(); // check full row/col present + void Copy(const Real*&); // copy from an array + void Copy(const int*&); // copy from an array + void Copy(Real); // copy from constant + void Add(Real); // add a constant + void Multiply(Real); // multiply by constant + Real SumAbsoluteValue(); // sum of absolute values + Real MaximumAbsoluteValue1(Real r, int& i); // maximum of absolute values + Real MinimumAbsoluteValue1(Real r, int& i); // minimum of absolute values + Real Maximum1(Real r, int& i); // maximum + Real Minimum1(Real r, int& i); // minimum + Real Sum(); // sum of values + void Inject(const MatrixRowCol&); // copy stored els of a row/col + void Negate(const MatrixRowCol&); // change sign of a row/col + void Multiply(const MatrixRowCol&, Real); // scale a row/col + friend Real DotProd(const MatrixRowCol&, const MatrixRowCol&); + // sum of pairwise product + Real* Data() { return data; } + int Skip() { return skip; } // number of elements skipped + int Storage() { return storage; } // number of elements stored + int Length() { return length; } // length of row or column + void Skip(int i) { skip=i; } + void Storage(int i) { storage=i; } + void Length(int i) { length=i; } + void SubRowCol(MatrixRowCol&, int, int) const; + // get part of a row or column + MatrixRowCol() {} // to stop warning messages + ~MatrixRowCol(); + FREE_CHECK(MatrixRowCol) +}; + +class MatrixRow : public MatrixRowCol +{ +public: + // bodies for these are inline at the end of this .h file + MatrixRow(GeneralMatrix*, LoadAndStoreFlag, int=0); + // extract a row + ~MatrixRow(); + void Next(); // get next row + FREE_CHECK(MatrixRow) +}; + +class MatrixCol : public MatrixRowCol +{ +public: + // bodies for these are inline at the end of this .h file + MatrixCol(GeneralMatrix*, LoadAndStoreFlag, int=0); + // extract a col + MatrixCol(GeneralMatrix*, Real*, LoadAndStoreFlag, int=0); + // store/retrieve a col + ~MatrixCol(); + void Next(); // get next row + FREE_CHECK(MatrixCol) +}; + +// MatrixColX is an alternative to MatrixCol where the complete +// column is stored externally + +class MatrixColX : public MatrixRowCol +{ +public: + // bodies for these are inline at the end of this .h file + MatrixColX(GeneralMatrix*, Real*, LoadAndStoreFlag, int=0); + // store/retrieve a col + ~MatrixColX(); + void Next(); // get next row + Real* store; // pointer to local storage + // less skip + FREE_CHECK(MatrixColX) +}; + +/**************************** inline bodies ****************************/ + +inline MatrixRow::MatrixRow(GeneralMatrix* gmx, LoadAndStoreFlag cwx, int row) +{ gm=gmx; cw=cwx; rowcol=row; gm->GetRow(*this); } + +inline void MatrixRow::Next() { gm->NextRow(*this); } + +inline MatrixCol::MatrixCol(GeneralMatrix* gmx, LoadAndStoreFlag cwx, int col) +{ gm=gmx; cw=cwx; rowcol=col; gm->GetCol(*this); } + +inline MatrixCol::MatrixCol(GeneralMatrix* gmx, Real* r, + LoadAndStoreFlag cwx, int col) +{ gm=gmx; data=r; cw=cwx+StoreHere; rowcol=col; gm->GetCol(*this); } + +inline MatrixColX::MatrixColX(GeneralMatrix* gmx, Real* r, + LoadAndStoreFlag cwx, int col) +{ gm=gmx; store=data=r; cw=cwx+StoreHere; rowcol=col; gm->GetCol(*this); } + + +inline void MatrixCol::Next() { gm->NextCol(*this); } + +inline void MatrixColX::Next() { gm->NextCol(*this); } + +#ifdef use_namespace +} +#endif + +#endif diff --git a/Utilities/OSSIM/ossim_core/matrix/newmatrm.cpp b/Utilities/OSSIM/ossim_core/matrix/newmatrm.cpp new file mode 100644 index 0000000000..2aa5068a1b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/newmatrm.cpp @@ -0,0 +1,216 @@ +//$$newmatrm.cpp rectangular matrix operations + +// Copyright (C) 1991,2,3,4: R B Davies + +#define WANT_MATH + +#include "newmat.h" +#include "newmatrm.h" + +#ifdef use_namespace +namespace NEWMAT { +#endif + +#ifdef DO_REPORT +#define REPORT { static ExeCounter ExeCount(__LINE__,12); ++ExeCount; } +#else +#define REPORT {} +#endif + + +// operations on rectangular matrices + + +void RectMatrixRow::Reset (const Matrix& M, int row, int skip, int length) +{ + REPORT + RectMatrixRowCol::Reset + ( M.Store()+row*M.Ncols()+skip, length, 1, M.Ncols() ); +} + +void RectMatrixRow::Reset (const Matrix& M, int row) +{ + REPORT + RectMatrixRowCol::Reset( M.Store()+row*M.Ncols(), M.Ncols(), 1, M.Ncols() ); +} + +void RectMatrixCol::Reset (const Matrix& M, int skip, int col, int length) +{ + REPORT + RectMatrixRowCol::Reset + ( M.Store()+col+skip*M.Ncols(), length, M.Ncols(), 1 ); +} + +void RectMatrixCol::Reset (const Matrix& M, int col) +{ + REPORT + RectMatrixRowCol::Reset( M.Store()+col, M.Nrows(), M.Ncols(), 1 ); +} + + +Real RectMatrixRowCol::SumSquare() const +{ + REPORT + long_Real sum = 0.0; int i = n; Real* s = store; int d = spacing; + // while (i--) { sum += (long_Real)*s * *s; s += d; } + if (i) for(;;) + { sum += (long_Real)*s * *s; if (!(--i)) break; s += d; } + return (Real)sum; +} + +Real RectMatrixRowCol::operator*(const RectMatrixRowCol& rmrc) const +{ + REPORT + long_Real sum = 0.0; int i = n; + Real* s = store; int d = spacing; + Real* s1 = rmrc.store; int d1 = rmrc.spacing; + if (i!=rmrc.n) + { + Tracer tr("newmatrm"); + Throw(InternalException("Dimensions differ in *")); + } + // while (i--) { sum += (long_Real)*s * *s1; s += d; s1 += d1; } + if (i) for(;;) + { sum += (long_Real)*s * *s1; if (!(--i)) break; s += d; s1 += d1; } + return (Real)sum; +} + +void RectMatrixRowCol::AddScaled(const RectMatrixRowCol& rmrc, Real r) +{ + REPORT + int i = n; Real* s = store; int d = spacing; + Real* s1 = rmrc.store; int d1 = rmrc.spacing; + if (i!=rmrc.n) + { + Tracer tr("newmatrm"); + Throw(InternalException("Dimensions differ in AddScaled")); + } + // while (i--) { *s += *s1 * r; s += d; s1 += d1; } + if (i) for (;;) + { *s += *s1 * r; if (!(--i)) break; s += d; s1 += d1; } +} + +void RectMatrixRowCol::Divide(const RectMatrixRowCol& rmrc, Real r) +{ + REPORT + int i = n; Real* s = store; int d = spacing; + Real* s1 = rmrc.store; int d1 = rmrc.spacing; + if (i!=rmrc.n) + { + Tracer tr("newmatrm"); + Throw(InternalException("Dimensions differ in Divide")); + } + // while (i--) { *s = *s1 / r; s += d; s1 += d1; } + if (i) for (;;) { *s = *s1 / r; if (!(--i)) break; s += d; s1 += d1; } +} + +void RectMatrixRowCol::Divide(Real r) +{ + REPORT + int i = n; Real* s = store; int d = spacing; + // while (i--) { *s /= r; s += d; } + if (i) for (;;) { *s /= r; if (!(--i)) break; s += d; } +} + +void RectMatrixRowCol::Negate() +{ + REPORT + int i = n; Real* s = store; int d = spacing; + // while (i--) { *s = - *s; s += d; } + if (i) for (;;) { *s = - *s; if (!(--i)) break; s += d; } +} + +void RectMatrixRowCol::Zero() +{ + REPORT + int i = n; Real* s = store; int d = spacing; + // while (i--) { *s = 0.0; s += d; } + if (i) for (;;) { *s = 0.0; if (!(--i)) break; s += d; } +} + +void ComplexScale(RectMatrixCol& U, RectMatrixCol& V, Real x, Real y) +{ + REPORT + int n = U.n; + if (n != V.n) + { + Tracer tr("newmatrm"); + Throw(InternalException("Dimensions differ in ComplexScale")); + } + Real* u = U.store; Real* v = V.store; + int su = U.spacing; int sv = V.spacing; + //while (n--) + //{ + // Real z = *u * x - *v * y; *v = *u * y + *v * x; *u = z; + // u += su; v += sv; + //} + if (n) for (;;) + { + Real z = *u * x - *v * y; *v = *u * y + *v * x; *u = z; + if (!(--n)) break; + u += su; v += sv; + } +} + +void Rotate(RectMatrixCol& U, RectMatrixCol& V, Real tau, Real s) +{ + REPORT + // (U, V) = (U, V) * (c, s) where tau = s/(1+c), c^2 + s^2 = 1 + int n = U.n; + if (n != V.n) + { + Tracer tr("newmatrm"); + Throw(InternalException("Dimensions differ in Rotate")); + } + Real* u = U.store; Real* v = V.store; + int su = U.spacing; int sv = V.spacing; + //while (n--) + //{ + // Real zu = *u; Real zv = *v; + // *u -= s * (zv + zu * tau); *v += s * (zu - zv * tau); + // u += su; v += sv; + //} + if (n) for(;;) + { + Real zu = *u; Real zv = *v; + *u -= s * (zv + zu * tau); *v += s * (zu - zv * tau); + if (!(--n)) break; + u += su; v += sv; + } +} + + +// misc procedures for numerical things + +Real pythag(Real f, Real g, Real& c, Real& s) +// return z=sqrt(f*f+g*g), c=f/z, s=g/z +// set c=1,s=0 if z==0 +// avoid floating point overflow or divide by zero +{ + if (f==0 && g==0) { c=1.0; s=0.0; return 0.0; } + Real af = f>=0 ? f : -f; + Real ag = g>=0 ? g : -g; + if (ag<af) + { + REPORT + Real h = g/f; Real sq = sqrt(1.0+h*h); + if (f<0) sq = -sq; // make return value non-negative + c = 1.0/sq; s = h/sq; return sq*f; + } + else + { + REPORT + Real h = f/g; Real sq = sqrt(1.0+h*h); + if (g<0) sq = -sq; + s = 1.0/sq; c = h/sq; return sq*g; + } +} + + + + +#ifdef use_namespace +} +#endif + + diff --git a/Utilities/OSSIM/ossim_core/matrix/newmatrm.h b/Utilities/OSSIM/ossim_core/matrix/newmatrm.h new file mode 100644 index 0000000000..fab132a7f9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/newmatrm.h @@ -0,0 +1,145 @@ +//$$newmatrm.h rectangular matrix operations + +// Copyright (C) 1991,2,3,4: R B Davies + +#ifndef NEWMATRM_LIB +#define NEWMATRM_LIB 0 + +#ifdef use_namespace +namespace NEWMAT { +#endif + +// operations on rectangular matrices + +class RectMatrixCol; + +class RectMatrixRowCol +// a class for accessing rows and columns of rectangular matrices +{ +protected: +#ifdef use_namespace // to make namespace work +public: +#endif + Real* store; // pointer to storage + int n; // number of elements + int spacing; // space between elements + int shift; // space between cols or rows + RectMatrixRowCol(Real* st, int nx, int sp, int sh) + : store(st), n(nx), spacing(sp), shift(sh) {} + void Reset(Real* st, int nx, int sp, int sh) + { store=st; n=nx; spacing=sp; shift=sh; } +public: + Real operator*(const RectMatrixRowCol&) const; // dot product + void AddScaled(const RectMatrixRowCol&, Real); // add scaled + void Divide(const RectMatrixRowCol&, Real); // scaling + void Divide(Real); // scaling + void Negate(); // change sign + void Zero(); // zero row col + Real& operator[](int i) { return *(store+i*spacing); } // element + Real SumSquare() const; // sum of squares + Real& First() { return *store; } // get first element + void DownDiag() { store += (shift+spacing); n--; } + void UpDiag() { store -= (shift+spacing); n++; } + friend void ComplexScale(RectMatrixCol&, RectMatrixCol&, Real, Real); + friend void Rotate(RectMatrixCol&, RectMatrixCol&, Real, Real); + FREE_CHECK(RectMatrixRowCol) +}; + +class RectMatrixRow : public RectMatrixRowCol +{ +public: + RectMatrixRow(const Matrix&, int, int, int); + RectMatrixRow(const Matrix&, int); + void Reset(const Matrix&, int, int, int); + void Reset(const Matrix&, int); + Real& operator[](int i) { return *(store+i); } + void Down() { store += shift; } + void Right() { store++; n--; } + void Up() { store -= shift; } + void Left() { store--; n++; } + FREE_CHECK(RectMatrixRow) +}; + +class RectMatrixCol : public RectMatrixRowCol +{ +public: + RectMatrixCol(const Matrix&, int, int, int); + RectMatrixCol(const Matrix&, int); + void Reset(const Matrix&, int, int, int); + void Reset(const Matrix&, int); + void Down() { store += spacing; n--; } + void Right() { store++; } + void Up() { store -= spacing; n++; } + void Left() { store--; } + friend void ComplexScale(RectMatrixCol&, RectMatrixCol&, Real, Real); + friend void Rotate(RectMatrixCol&, RectMatrixCol&, Real, Real); + FREE_CHECK(RectMatrixCol) +}; + +class RectMatrixDiag : public RectMatrixRowCol +{ +public: + RectMatrixDiag(const DiagonalMatrix& D) + : RectMatrixRowCol(D.Store(), D.Nrows(), 1, 1) {} + Real& operator[](int i) { return *(store+i); } + void DownDiag() { store++; n--; } + void UpDiag() { store--; n++; } + FREE_CHECK(RectMatrixDiag) +}; + + + + +inline RectMatrixRow::RectMatrixRow + (const Matrix& M, int row, int skip, int length) + : RectMatrixRowCol( M.Store()+row*M.Ncols()+skip, length, 1, M.Ncols() ) {} + +inline RectMatrixRow::RectMatrixRow (const Matrix& M, int row) + : RectMatrixRowCol( M.Store()+row*M.Ncols(), M.Ncols(), 1, M.Ncols() ) {} + +inline RectMatrixCol::RectMatrixCol + (const Matrix& M, int skip, int col, int length) + : RectMatrixRowCol( M.Store()+col+skip*M.Ncols(), length, M.Ncols(), 1 ) {} + +inline RectMatrixCol::RectMatrixCol (const Matrix& M, int col) + : RectMatrixRowCol( M.Store()+col, M.Nrows(), M.Ncols(), 1 ) {} + +inline Real square(Real x) { return x*x; } +inline Real sign(Real x, Real y) + { return (y>=0) ? x : -x; } // assume x >=0 + + +// Misc numerical things + +Real pythag(Real f, Real g, Real& c, Real& s); + +inline void GivensRotation(Real cGivens, Real sGivens, Real& x, Real& y) +{ + // allow for possibility &x = &y + Real tmp0 = cGivens * x + sGivens * y; + Real tmp1 = -sGivens * x + cGivens * y; + x = tmp0; y = tmp1; +} + +inline void GivensRotationR(Real cGivens, Real sGivens, Real& x, Real& y) +{ + // also change sign of y + // allow for possibility &x = &y + Real tmp0 = cGivens * x + sGivens * y; + Real tmp1 = sGivens * x - cGivens * y; + x = tmp0; y = tmp1; +} + + + + + +#ifdef use_namespace +} +#endif + +#endif + +// body file: newmatrm.cpp + + diff --git a/Utilities/OSSIM/ossim_core/matrix/nl_ex.txt b/Utilities/OSSIM/ossim_core/matrix/nl_ex.txt new file mode 100644 index 0000000000..78bfef7523 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/nl_ex.txt @@ -0,0 +1,42 @@ +Fitting parameters + + 70.02918529 209.6252324 0.1541078372 + 94.78295699 + 49.23360397 147.1803571 0.1734849298 + 1.848950128 + 0.7422941575 1.70673579 0.1733822274 + 0.2113527145 + 0.1955923541 0.06041118379 0.1754552928 + 0.1754553498 + 0.1754553471 2.341694142e-08 0.1754553393 +Converged + + +Estimates and standard errors + 19.77 0.73 + -23.63 0.82 + 0.35 0.04 + + +Residual s.d. = 0.42 + +CorrelationMatrix + 1.00 -0.05 -0.91 + -0.05 1.00 -0.31 + -0.91 -0.31 1.00 + + +X, Y, Residual, Hat + 1.00 3.20 0.10 0.89 + 2.00 7.90 -0.11 0.33 + 3.00 11.10 -0.38 0.39 + 4.00 14.50 0.58 0.35 + 6.00 16.70 -0.16 0.32 + 8.00 18.30 -0.02 0.73 + + +Var/cov + 0.5295 -0.0324 -0.0250 + -0.0324 0.6668 -0.0096 + -0.0250 -0.0096 0.0014 + diff --git a/Utilities/OSSIM/ossim_core/matrix/precisio.h b/Utilities/OSSIM/ossim_core/matrix/precisio.h new file mode 100644 index 0000000000..f5ef68cbb7 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/precisio.h @@ -0,0 +1,241 @@ +//$$ precisio.h floating point constants + +#ifndef PRECISION_LIB +#define PRECISION_LIB 0 + +#ifdef _STANDARD_ // standard library available +#include <limits> +#endif + +#ifdef use_namespace +namespace NEWMAT { +#endif + +#ifdef _STANDARD_ // standard library available + +using namespace std; + +class FloatingPointPrecision +{ +public: + static int Dig() // number of decimal digits or precision + { return numeric_limits<Real>::digits10 ; } + + static Real Epsilon() // smallest number such that 1+Eps!=Eps + { return numeric_limits<Real>::epsilon(); } + + static int Mantissa() // bits in mantisa + { return numeric_limits<Real>::digits; } + + static Real Maximum() // maximum value + { return numeric_limits<Real>::max(); } + + static int MaximumDecimalExponent() // maximum decimal exponent + { return numeric_limits<Real>::max_exponent10; } + + static int MaximumExponent() // maximum binary exponent + { return numeric_limits<Real>::max_exponent; } + + static Real LnMaximum() // natural log of maximum + { return (Real)log(Maximum()); } + + static Real Minimum() // minimum positive value + { return numeric_limits<Real>::min(); } + + static int MinimumDecimalExponent() // minimum decimal exponent + { return numeric_limits<Real>::min_exponent10; } + + static int MinimumExponent() // minimum binary exponent + { return numeric_limits<Real>::min_exponent; } + + static Real LnMinimum() // natural log of minimum + { return (Real)log(Minimum()); } + + static int Radix() // exponent radix + { return numeric_limits<Real>::radix; } + + static int Rounds() // addition rounding (1 = does round) + { + return numeric_limits<Real>::round_style == + round_to_nearest ? 1 : 0; + } + +}; + + +#else // _STANDARD_ not defined + +#ifndef SystemV // if there is float.h + + +#ifdef USING_FLOAT + + +class FloatingPointPrecision +{ +public: + static int Dig() + { return FLT_DIG; } // number of decimal digits or precision + + static Real Epsilon() + { return FLT_EPSILON; } // smallest number such that 1+Eps!=Eps + + static int Mantissa() + { return FLT_MANT_DIG; } // bits in mantisa + + static Real Maximum() + { return FLT_MAX; } // maximum value + + static int MaximumDecimalExponent() + { return FLT_MAX_10_EXP; } // maximum decimal exponent + + static int MaximumExponent() + { return FLT_MAX_EXP; } // maximum binary exponent + + static Real LnMaximum() + { return (Real)log(Maximum()); } // natural log of maximum + + static Real Minimum() + { return FLT_MIN; } // minimum positive value + + static int MinimumDecimalExponent() + { return FLT_MIN_10_EXP; } // minimum decimal exponent + + static int MinimumExponent() + { return FLT_MIN_EXP; } // minimum binary exponent + + static Real LnMinimum() + { return (Real)log(Minimum()); } // natural log of minimum + + static int Radix() + { return FLT_RADIX; } // exponent radix + + static int Rounds() + { return FLT_ROUNDS; } // addition rounding (1 = does round) + +}; + +#endif // USING_FLOAT + + +#ifdef USING_DOUBLE + +class FloatingPointPrecision +{ +public: + + static int Dig() + { return DBL_DIG; } // number of decimal digits or precision + + static Real Epsilon() + { return DBL_EPSILON; } // smallest number such that 1+Eps!=Eps + + static int Mantissa() + { return DBL_MANT_DIG; } // bits in mantisa + + static Real Maximum() + { return DBL_MAX; } // maximum value + + static int MaximumDecimalExponent() + { return DBL_MAX_10_EXP; } // maximum decimal exponent + + static int MaximumExponent() + { return DBL_MAX_EXP; } // maximum binary exponent + + static Real LnMaximum() + { return (Real)log(Maximum()); } // natural log of maximum + + static Real Minimum() + { +//#ifdef __BCPLUSPLUS__ +// return 2.225074e-308; // minimum positive value +//#else + return DBL_MIN; +//#endif + } + + static int MinimumDecimalExponent() + { return DBL_MIN_10_EXP; } // minimum decimal exponent + + static int MinimumExponent() + { return DBL_MIN_EXP; } // minimum binary exponent + + static Real LnMinimum() + { return (Real)log(Minimum()); } // natural log of minimum + + + static int Radix() + { return FLT_RADIX; } // exponent radix + + static int Rounds() + { return FLT_ROUNDS; } // addition rounding (1 = does round) + +}; + +#endif // USING_DOUBLE + +#else // if there is no float.h + +#ifdef USING_FLOAT + +class FloatingPointPrecision +{ +public: + + static Real Epsilon() + { return pow(2.0,(int)(1-FSIGNIF)); } + // smallest number such that 1+Eps!=Eps + + static Real Maximum() + { return MAXFLOAT; } // maximum value + + static Real LnMaximum() + { return (Real)log(Maximum()); } // natural log of maximum + + static Real Minimum() + { return MINFLOAT; } // minimum positive value + + static Real LnMinimum() + { return (Real)log(Minimum()); } // natural log of minimum + +}; + +#endif // USING_FLOAT + + +#ifdef USING_DOUBLE + +class FloatingPointPrecision +{ +public: + + static Real Epsilon() + { return pow(2.0,(int)(1-DSIGNIF)); } + // smallest number such that 1+Eps!=Eps + + static Real Maximum() + { return MAXDOUBLE; } // maximum value + + static Real LnMaximum() + { return LN_MAXDOUBLE; } // natural log of maximum + + static Real Minimum() + { return MINDOUBLE; } + + static Real LnMinimum() + { return LN_MINDOUBLE; } // natural log of minimum +}; + +#endif // USING_DOUBLE + +#endif // SystemV + +#endif // _STANDARD_ + +#ifdef use_namespace +} +#endif // use_namespace + + + +#endif // PRECISION_LIB diff --git a/Utilities/OSSIM/ossim_core/matrix/sl_ex.txt b/Utilities/OSSIM/ossim_core/matrix/sl_ex.txt new file mode 100644 index 0000000000..b578f10a72 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/sl_ex.txt @@ -0,0 +1,21 @@ +-10 -2.15443 +-9 -2.08008 +-8 -2 +-7 -1.91293 +-6 -1.81712 +-5 -1.70998 +-4 -1.5874 +-3 -1.44225 +-2 -1.25992 +-1 -1.00001 +0 0 +1 1.00001 +2 1.25992 +3 1.44225 +4 1.58741 +5 1.70998 +6 1.81712 +7 1.91293 +8 2 +9 2.08008 +10 2.15443 diff --git a/Utilities/OSSIM/ossim_core/matrix/solution.cpp b/Utilities/OSSIM/ossim_core/matrix/solution.cpp new file mode 100644 index 0000000000..128bf5b20a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/solution.cpp @@ -0,0 +1,203 @@ +//$$ solution.cpp // solve routines + +// Copyright (C) 1994: R B Davies + + +#define WANT_STREAM // include.h will get stream fns +#define WANT_MATH // include.h will get math fns + +#include "include.h" +#include "boolean.h" +#include "myexcept.h" + +#include "solution.h" + +#ifdef use_namespace +namespace RBD_COMMON { +#endif + +R1_R1::~R1_R1() +{ +} + +void R1_R1::Set(Real X) +{ + if ((!minXinf && X <= minX) || (!maxXinf && X >= maxX)) + Throw(SolutionException("X value out of range")); + x = X; xSet = true; +} + +R1_R1::operator Real() +{ + if (!xSet) Throw(SolutionException("Value of X not set")); + Real y = operator()(); + return y; +} + +unsigned long SolutionException::Select; + +SolutionException::SolutionException(const char* a_what) : Exception() +{ + Select = Exception::Select; + AddMessage("Error detected by solution package\n"); + AddMessage(a_what); AddMessage("\n"); + if (a_what) Tracer::AddTrace(); +}; + +inline Real square(Real x) { return x*x; } + +void OneDimSolve::LookAt(int V) +{ + lim--; + if (!lim) Throw(SolutionException("Does not converge")); + Last = V; + Real yy = function(x[V]) - YY; + Finish = (fabs(yy) <= accY) || (Captured && fabs(x[L]-x[U]) <= accX ); + y[V] = vpol*yy; +} + +void OneDimSolve::HFlip() { hpol=-hpol; State(U,C,L); } + +void OneDimSolve::VFlip() + { vpol = -vpol; y[0] = -y[0]; y[1] = -y[1]; y[2] = -y[2]; } + +void OneDimSolve::Flip() +{ + hpol=-hpol; vpol=-vpol; State(U,C,L); + y[0] = -y[0]; y[1] = -y[1]; y[2] = -y[2]; +} + +void OneDimSolve::State(int I, int J, int K) { L=I; C=J; U=K; } + +void OneDimSolve::Linear(int I, int J, int K) +{ + x[J] = (x[I]*y[K] - x[K]*y[I])/(y[K] - y[I]); + // cout << "Linear\n"; +} + +void OneDimSolve::Quadratic(int I, int J, int K) +{ + // result to overwrite I + Real YJK, YIK, YIJ, XKI, XKJ; + YJK = y[J] - y[K]; YIK = y[I] - y[K]; YIJ = y[I] - y[J]; + XKI = (x[K] - x[I]); + XKJ = (x[K]*y[J] - x[J]*y[K])/YJK; + if ( square(YJK/YIK)>(x[K] - x[J])/XKI || + square(YIJ/YIK)>(x[J] - x[I])/XKI ) + { + x[I] = XKJ; + // cout << "Quadratic - exceptional\n"; + } + else + { + XKI = (x[K]*y[I] - x[I]*y[K])/YIK; + x[I] = (XKJ*y[I] - XKI*y[J])/YIJ; + // cout << "Quadratic - normal\n"; + } +} + +Real OneDimSolve::Solve(Real Y, Real X, Real Dev, int Lim) +{ + enum Loop { start, captured1, captured2, binary, finish }; + Tracer et("OneDimSolve::Solve"); + lim=Lim; Captured = false; + if (Dev==0.0) Throw(SolutionException("Dev is zero")); + L=0; C=1; U=2; vpol=1; hpol=1; y[C]=0.0; y[U]=0.0; + if (Dev<0.0) { hpol=-1; Dev = -Dev; } + YY=Y; // target value + x[L] = X; // initial trial value + if (!function.IsValid(X)) + Throw(SolutionException("Starting value is invalid")); + Loop TheLoop = start; + for (;;) + { + switch (TheLoop) + { + case start: + LookAt(L); if (Finish) { TheLoop = finish; break; } + if (y[L]>0.0) VFlip(); // so Y[L] < 0 + + x[U] = X + Dev * hpol; + if (!function.maxXinf && x[U] > function.maxX) + x[U] = (function.maxX + X) / 2.0; + if (!function.minXinf && x[U] < function.minX) + x[U] = (function.minX + X) / 2.0; + + LookAt(U); if (Finish) { TheLoop = finish; break; } + if (y[U] > 0.0) { TheLoop = captured1; Captured = true; break; } + if (y[U] == y[L]) + Throw(SolutionException("Function is flat")); + if (y[U] < y[L]) HFlip(); // Change direction + State(L,U,C); + for (i=0; i<20; i++) + { + // cout << "Searching for crossing point\n"; + // Have L C then crossing point, Y[L]<Y[C]<0 + x[U] = x[C] + Dev * hpol; + if (!function.maxXinf && x[U] > function.maxX) + x[U] = (function.maxX + x[C]) / 2.0; + if (!function.minXinf && x[U] < function.minX) + x[U] = (function.minX + x[C]) / 2.0; + + LookAt(U); if (Finish) { TheLoop = finish; break; } + if (y[U] > 0) { TheLoop = captured2; Captured = true; break; } + if (y[U] < y[C]) + Throw(SolutionException("Function is not monotone")); + Dev *= 2.0; + State(C,U,L); + } + if (TheLoop != start ) break; + Throw(SolutionException("Cannot locate a crossing point")); + + case captured1: + // cout << "Captured - 1\n"; + // We have 2 points L and U with crossing between them + Linear(L,C,U); // linear interpolation + // - result to C + LookAt(C); if (Finish) { TheLoop = finish; break; } + if (y[C] > 0.0) Flip(); // Want y[C] < 0 + if (y[C] < 0.5*y[L]) { State(C,L,U); TheLoop = binary; break; } + + case captured2: + // cout << "Captured - 2\n"; + // We have L,C before crossing, U after crossing + Quadratic(L,C,U); // quad interpolation + // - result to L + State(C,L,U); + if ((x[C] - x[L])*hpol <= 0.0 || (x[C] - x[U])*hpol >= 0.0) + { TheLoop = captured1; break; } + LookAt(C); if (Finish) { TheLoop = finish; break; } + // cout << "Through first stage\n"; + if (y[C] > 0.0) Flip(); + if (y[C] > 0.5*y[L]) { TheLoop = captured2; break; } + else { State(C,L,U); TheLoop = captured1; break; } + + case binary: + // We have L, U around crossing - do binary search + // cout << "Binary\n"; + for (i=3; i; i--) + { + x[C] = 0.5*(x[L]+x[U]); + LookAt(C); if (Finish) { TheLoop = finish; break; } + if (y[C]>0.0) State(L,U,C); else State(C,L,U); + } + if (TheLoop != binary) break; + TheLoop = captured1; break; + + case finish: + return x[Last]; + + } + } +} + +bool R1_R1::IsValid(Real X) +{ + Set(X); + return (minXinf || x > minX) && (maxXinf || x < maxX); +} + +#ifdef use_namespace +} +#endif + diff --git a/Utilities/OSSIM/ossim_core/matrix/solution.h b/Utilities/OSSIM/ossim_core/matrix/solution.h new file mode 100644 index 0000000000..d44ed3ba6b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/solution.h @@ -0,0 +1,96 @@ +//$$ solution.h // solve routines + +#include "boolean.h" +#include "myexcept.h" + +#ifdef use_namespace +namespace RBD_COMMON { +#endif + + +// Solve the equation f(x)=y for x where f is a monotone continuous +// function of x +// Essentially Brent s method + +// You need to derive a class from R1_R1 and override "operator()" +// with the function you want to solve. +// Use an object from this class in OneDimSolve + +class R1_R1 +{ + // the prototype for a Real function of a Real variable + // you need to derive your function from this one and put in your + // function for operator() at least. You probably also want to set up a + // constructor to put in additional parameter values (e.g. that will not + // vary during a solve) + +protected: + Real x; // Current x value + bool xSet; // true if a value assigned to x + +public: + virtual ~R1_R1(); + + Real minX, maxX; // range of value x + bool minXinf, maxXinf; // true if these are infinite + R1_R1() : xSet(false), minXinf(true), maxXinf(true) {} + virtual Real operator()() = 0; // function value at current x + // set current x + virtual void Set(Real X); // set x, check OK + Real operator()(Real X) { Set(X); return operator()(); } + // set x, return value + virtual bool IsValid(Real X); + operator Real(); // implicit conversion +}; + +class SolutionException : public Exception +{ +public: + static unsigned long Select; + SolutionException(const char* a_what = 0); +}; + +class OneDimSolve +{ + R1_R1& function; // reference to the function + Real accX; // accuracy in X direction + Real accY; // accuracy in Y direction + int lim; // maximum number of iterations + +public: + OneDimSolve(R1_R1& f, Real AccY = 0.0001, Real AccX = 0.0) + : function(f), accX(AccX), accY(AccY) {} + // f is an R1_R1 function + Real Solve(Real Y, Real X, Real Dev, int Lim=100); + // Solve for x in Y=f(x) + // X is the initial trial value of x + // X+Dev is the second trial value + // program returns a value of x such that + // |Y-f(x)| <= accY or |f.inv(Y)-x| <= accX + +private: + Real x[3], y[3]; // Trial values of X and Y + int L,C,U,Last; // Locations of trial values + int vpol, hpol; // polarities + Real YY; // target value + int i; + void LookAt(int); // get new value of function + bool Finish; // true if LookAt finds conv. + bool Captured; // true when target surrounded + void VFlip(); + void HFlip(); + void Flip(); + void State(int I, int J, int K); + void Linear(int, int, int); + void Quadratic(int, int, int); +}; + + +#ifdef use_namespace +} +#endif + +// body file: solution.cpp + + + diff --git a/Utilities/OSSIM/ossim_core/matrix/sort.cpp b/Utilities/OSSIM/ossim_core/matrix/sort.cpp new file mode 100644 index 0000000000..a30081135c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/sort.cpp @@ -0,0 +1,272 @@ +//$$ sort.cpp Sorting + +// Copyright (C) 1991,2,3,4: R B Davies + +#define WANT_MATH + +#include "include.h" + +#include "newmatap.h" + +#ifdef use_namespace +namespace NEWMAT { +#endif + +#ifdef DO_REPORT +#define REPORT { static ExeCounter ExeCount(__LINE__,13); ++ExeCount; } +#else +#define REPORT {} +#endif + +/******************************** Quick sort ********************************/ + +// Quicksort. +// Essentially the method described in Sedgewick s algorithms in C++ +// My version is still partially recursive, unlike Segewick s, but the +// smallest segment of each split is used in the recursion, so it should +// not overlead the stack. + +// If the process does not seems to be converging an exception is thrown. + + +#define DoSimpleSort 17 // when to switch to insert sort +#define MaxDepth 50 // maximum recursion depth + +static void MyQuickSortDescending(Real* first, Real* last, int depth); +static void InsertionSortDescending(Real* first, const int length, + int guard); +static Real SortThreeDescending(Real* a, Real* b, Real* c); + +static void MyQuickSortAscending(Real* first, Real* last, int depth); +static void InsertionSortAscending(Real* first, const int length, + int guard); + + +void SortDescending(GeneralMatrix& GM) +{ + REPORT + Tracer et("QuickSortDescending"); + + Real* data = GM.Store(); int max = GM.Storage(); + + if (max > DoSimpleSort) MyQuickSortDescending(data, data + max - 1, 0); + InsertionSortDescending(data, max, DoSimpleSort); + +} + +static Real SortThreeDescending(Real* a, Real* b, Real* c) +{ + // sort *a, *b, *c; return *b; optimise for already sorted + if (*a >= *b) + { + if (*b >= *c) { REPORT return *b; } + else if (*a >= *c) { REPORT Real x = *c; *c = *b; *b = x; return x; } + else { REPORT Real x = *a; *a = *c; *c = *b; *b = x; return x; } + } + else if (*c >= *b) { REPORT Real x = *c; *c = *a; *a = x; return *b; } + else if (*a >= *c) { REPORT Real x = *a; *a = *b; *b = x; return x; } + else { REPORT Real x = *c; *c = *a; *a = *b; *b = x; return x; } +} + +static void InsertionSortDescending(Real* first, const int length, + int guard) +// guard gives the length of the sequence to scan to find first +// element (eg = length) +{ + REPORT + if (length <= 1) return; + + // scan for first element + Real* f = first; Real v = *f; Real* h = f; + if (guard > length) { REPORT guard = length; } + int i = guard - 1; + while (i--) if (v < *(++f)) { v = *f; h = f; } + *h = *first; *first = v; + + // do the sort + i = length - 1; f = first; + while (i--) + { + Real* g = f++; h = f; v = *h; + while (*g < v) *h-- = *g--; + *h = v; + } +} + +static void MyQuickSortDescending(Real* first, Real* last, int depth) +{ + REPORT + for (;;) + { + const int length = last - first + 1; + if (length < DoSimpleSort) { REPORT return; } + if (depth++ > MaxDepth) + Throw(ConvergenceException("QuickSortDescending fails: ")); + Real* centre = first + length/2; + const Real test = SortThreeDescending(first, centre, last); + Real* f = first; Real* l = last; + for (;;) + { + while (*(++f) > test) {} + while (*(--l) < test) {} + if (l <= f) break; + const Real temp = *f; *f = *l; *l = temp; + } + if (f > centre) + { REPORT MyQuickSortDescending(l+1, last, depth); last = f-1; } + else { REPORT MyQuickSortDescending(first, f-1, depth); first = l+1; } + } +} + +void SortAscending(GeneralMatrix& GM) +{ + REPORT + Tracer et("QuickSortAscending"); + + Real* data = GM.Store(); int max = GM.Storage(); + + if (max > DoSimpleSort) MyQuickSortAscending(data, data + max - 1, 0); + InsertionSortAscending(data, max, DoSimpleSort); + +} + +static void InsertionSortAscending(Real* first, const int length, + int guard) +// guard gives the length of the sequence to scan to find first +// element (eg guard = length) +{ + REPORT + if (length <= 1) return; + + // scan for first element + Real* f = first; Real v = *f; Real* h = f; + if (guard > length) { REPORT guard = length; } + int i = guard - 1; + while (i--) if (v > *(++f)) { v = *f; h = f; } + *h = *first; *first = v; + + // do the sort + i = length - 1; f = first; + while (i--) + { + Real* g = f++; h = f; v = *h; + while (*g > v) *h-- = *g--; + *h = v; + } +} +static void MyQuickSortAscending(Real* first, Real* last, int depth) +{ + REPORT + for (;;) + { + const int length = last - first + 1; + if (length < DoSimpleSort) { REPORT return; } + if (depth++ > MaxDepth) + Throw(ConvergenceException("QuickSortAscending fails: ")); + Real* centre = first + length/2; + const Real test = SortThreeDescending(last, centre, first); + Real* f = first; Real* l = last; + for (;;) + { + while (*(++f) < test) {} + while (*(--l) > test) {} + if (l <= f) break; + const Real temp = *f; *f = *l; *l = temp; + } + if (f > centre) + { REPORT MyQuickSortAscending(l+1, last, depth); last = f-1; } + else { REPORT MyQuickSortAscending(first, f-1, depth); first = l+1; } + } +} + +//********* sort diagonal matrix & rearrange matrix columns **************** + +// used by SVD + +// these are for sorting singular values - should be updated with faster +// sorts that handle exchange of columns better +// however time is probably not significant compared with SVD time + +void SortSV(DiagonalMatrix& D, Matrix& U, bool ascending) +{ + REPORT + Tracer trace("SortSV_DU"); + int m = U.Nrows(); int n = U.Ncols(); + if (n != D.Nrows()) Throw(IncompatibleDimensionsException(D,U)); + Real* u = U.Store(); + for (int i=0; i<n; i++) + { + int k = i; Real p = D.element(i); + if (ascending) + { + for (int j=i+1; j<n; j++) + { if (D.element(j) < p) { k = j; p = D.element(j); } } + } + else + { + for (int j=i+1; j<n; j++) + { if (D.element(j) > p) { k = j; p = D.element(j); } } + } + if (k != i) + { + D.element(k) = D.element(i); D.element(i) = p; int j = m; + Real* uji = u + i; Real* ujk = u + k; + if (j) for(;;) + { + p = *uji; *uji = *ujk; *ujk = p; + if (!(--j)) break; + uji += n; ujk += n; + } + } + } +} + +void SortSV(DiagonalMatrix& D, Matrix& U, Matrix& V, bool ascending) +{ + REPORT + Tracer trace("SortSV_DUV"); + int mu = U.Nrows(); int mv = V.Nrows(); int n = D.Nrows(); + if (n != U.Ncols()) Throw(IncompatibleDimensionsException(D,U)); + if (n != V.Ncols()) Throw(IncompatibleDimensionsException(D,V)); + Real* u = U.Store(); Real* v = V.Store(); + for (int i=0; i<n; i++) + { + int k = i; Real p = D.element(i); + if (ascending) + { + for (int j=i+1; j<n; j++) + { if (D.element(j) < p) { k = j; p = D.element(j); } } + } + else + { + for (int j=i+1; j<n; j++) + { if (D.element(j) > p) { k = j; p = D.element(j); } } + } + if (k != i) + { + D.element(k) = D.element(i); D.element(i) = p; + Real* uji = u + i; Real* ujk = u + k; + Real* vji = v + i; Real* vjk = v + k; + int j = mu; + if (j) for(;;) + { + p = *uji; *uji = *ujk; *ujk = p; if (!(--j)) break; + uji += n; ujk += n; + } + j = mv; + if (j) for(;;) + { + p = *vji; *vji = *vjk; *vjk = p; if (!(--j)) break; + vji += n; vjk += n; + } + } + } +} + + + + +#ifdef use_namespace +} +#endif + diff --git a/Utilities/OSSIM/ossim_core/matrix/submat.cpp b/Utilities/OSSIM/ossim_core/matrix/submat.cpp new file mode 100644 index 0000000000..79f57147be --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/submat.cpp @@ -0,0 +1,340 @@ +//$$ submat.cpp submatrices + +// Copyright (C) 1991,2,3,4: R B Davies + +#include "include.h" + +#include "newmat.h" +#include "newmatrc.h" + +#ifdef use_namespace +namespace NEWMAT { +#endif + +#ifdef DO_REPORT +#define REPORT { static ExeCounter ExeCount(__LINE__,11); ++ExeCount; } +#else +#define REPORT {} +#endif + + +/****************************** submatrices *********************************/ + +GetSubMatrix BaseMatrix::SubMatrix(int first_row, int last_row, int first_col, + int last_col) const +{ + REPORT + Tracer tr("SubMatrix"); + int a = first_row - 1; int b = last_row - first_row + 1; + int c = first_col - 1; int d = last_col - first_col + 1; + if (a<0 || b<0 || c<0 || d<0) Throw(SubMatrixDimensionException()); + // allow zero rows or columns + return GetSubMatrix(this, a, b, c, d, false); +} + +GetSubMatrix BaseMatrix::SymSubMatrix(int first_row, int last_row) const +{ + REPORT + Tracer tr("SubMatrix(symmetric)"); + int a = first_row - 1; int b = last_row - first_row + 1; + if (a<0 || b<0) Throw(SubMatrixDimensionException()); + // allow zero rows or columns + return GetSubMatrix( this, a, b, a, b, true); +} + +GetSubMatrix BaseMatrix::Row(int first_row) const +{ + REPORT + Tracer tr("SubMatrix(row)"); + int a = first_row - 1; + if (a<0) Throw(SubMatrixDimensionException()); + return GetSubMatrix(this, a, 1, 0, -1, false); +} + +GetSubMatrix BaseMatrix::Rows(int first_row, int last_row) const +{ + REPORT + Tracer tr("SubMatrix(rows)"); + int a = first_row - 1; int b = last_row - first_row + 1; + if (a<0 || b<0) Throw(SubMatrixDimensionException()); + // allow zero rows or columns + return GetSubMatrix(this, a, b, 0, -1, false); +} + +GetSubMatrix BaseMatrix::Column(int first_col) const +{ + REPORT + Tracer tr("SubMatrix(column)"); + int c = first_col - 1; + if (c<0) Throw(SubMatrixDimensionException()); + return GetSubMatrix(this, 0, -1, c, 1, false); +} + +GetSubMatrix BaseMatrix::Columns(int first_col, int last_col) const +{ + REPORT + Tracer tr("SubMatrix(columns)"); + int c = first_col - 1; int d = last_col - first_col + 1; + if (c<0 || d<0) Throw(SubMatrixDimensionException()); + // allow zero rows or columns + return GetSubMatrix(this, 0, -1, c, d, false); +} + +void GetSubMatrix::SetUpLHS() +{ + REPORT + Tracer tr("SubMatrix(LHS)"); + const BaseMatrix* bm1 = bm; + GeneralMatrix* gm1 = ((BaseMatrix*&)bm)->Evaluate(); + if ((BaseMatrix*)gm1!=bm1) + Throw(ProgramException("Invalid LHS")); + if (row_number < 0) row_number = gm1->Nrows(); + if (col_number < 0) col_number = gm1->Ncols(); + if (row_skip+row_number > gm1->Nrows() + || col_skip+col_number > gm1->Ncols()) + Throw(SubMatrixDimensionException()); +} + +void GetSubMatrix::operator<<(const BaseMatrix& bmx) +{ + REPORT + Tracer tr("SubMatrix(<<)"); GeneralMatrix* gmx = 0; + Try + { + SetUpLHS(); gmx = ((BaseMatrix&)bmx).Evaluate(); + if (row_number != gmx->Nrows() || col_number != gmx->Ncols()) + Throw(IncompatibleDimensionsException()); + MatrixRow mrx(gmx, LoadOnEntry); + MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip); + // do need LoadOnEntry + MatrixRowCol sub; int i = row_number; + while (i--) + { + mr.SubRowCol(sub, col_skip, col_number); // put values in sub + sub.Copy(mrx); mr.Next(); mrx.Next(); + } + gmx->tDelete(); + } + + CatchAll + { + if (gmx) gmx->tDelete(); + ReThrow; + } +} + +void GetSubMatrix::operator=(const BaseMatrix& bmx) +{ + REPORT + Tracer tr("SubMatrix(=)"); GeneralMatrix* gmx = 0; + // MatrixConversionCheck mcc; // Check for loss of info + Try + { + SetUpLHS(); gmx = ((BaseMatrix&)bmx).Evaluate(); + if (row_number != gmx->Nrows() || col_number != gmx->Ncols()) + Throw(IncompatibleDimensionsException()); + LoadAndStoreFlag lasf = + ( row_skip == col_skip + && gm->Type().IsSymmetric() + && gmx->Type().IsSymmetric() ) + ? LoadOnEntry+DirectPart + : LoadOnEntry; + MatrixRow mrx(gmx, lasf); + MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip); + // do need LoadOnEntry + MatrixRowCol sub; int i = row_number; + while (i--) + { + mr.SubRowCol(sub, col_skip, col_number); // put values in sub + sub.CopyCheck(mrx); mr.Next(); mrx.Next(); + } + gmx->tDelete(); + } + + CatchAll + { + if (gmx) gmx->tDelete(); + ReThrow; + } +} + +void GetSubMatrix::operator<<(const Real* r) +{ + REPORT + Tracer tr("SubMatrix(<<Real*)"); + SetUpLHS(); + if (row_skip+row_number > gm->Nrows() || col_skip+col_number > gm->Ncols()) + Throw(SubMatrixDimensionException()); + MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip); + // do need LoadOnEntry + MatrixRowCol sub; int i = row_number; + while (i--) + { + mr.SubRowCol(sub, col_skip, col_number); // put values in sub + sub.Copy(r); mr.Next(); + } +} + +void GetSubMatrix::operator<<(const int* r) +{ + REPORT + Tracer tr("SubMatrix(<<int*)"); + SetUpLHS(); + if (row_skip+row_number > gm->Nrows() || col_skip+col_number > gm->Ncols()) + Throw(SubMatrixDimensionException()); + MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip); + // do need LoadOnEntry + MatrixRowCol sub; int i = row_number; + while (i--) + { + mr.SubRowCol(sub, col_skip, col_number); // put values in sub + sub.Copy(r); mr.Next(); + } +} + +void GetSubMatrix::operator=(Real r) +{ + REPORT + Tracer tr("SubMatrix(=Real)"); + SetUpLHS(); + MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip); + // do need LoadOnEntry + MatrixRowCol sub; int i = row_number; + while (i--) + { + mr.SubRowCol(sub, col_skip, col_number); // put values in sub + sub.Copy(r); mr.Next(); + } +} + +void GetSubMatrix::Inject(const GeneralMatrix& gmx) +{ + REPORT + Tracer tr("SubMatrix(inject)"); + SetUpLHS(); + if (row_number != gmx.Nrows() || col_number != gmx.Ncols()) + Throw(IncompatibleDimensionsException()); + MatrixRow mrx((GeneralMatrix*)(&gmx), LoadOnEntry); + MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip); + // do need LoadOnEntry + MatrixRowCol sub; int i = row_number; + while (i--) + { + mr.SubRowCol(sub, col_skip, col_number); // put values in sub + sub.Inject(mrx); mr.Next(); mrx.Next(); + } +} + +void GetSubMatrix::operator+=(const BaseMatrix& bmx) +{ + REPORT + Tracer tr("SubMatrix(+=)"); GeneralMatrix* gmx = 0; + // MatrixConversionCheck mcc; // Check for loss of info + Try + { + SetUpLHS(); gmx = ((BaseMatrix&)bmx).Evaluate(); + if (row_number != gmx->Nrows() || col_number != gmx->Ncols()) + Throw(IncompatibleDimensionsException()); + MatrixRow mrx(gmx, LoadOnEntry); + MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip); + // do need LoadOnEntry + MatrixRowCol sub; int i = row_number; + while (i--) + { + mr.SubRowCol(sub, col_skip, col_number); // put values in sub + sub.Check(mrx); // check for loss of info + sub.Add(mrx); mr.Next(); mrx.Next(); + } + gmx->tDelete(); + } + + CatchAll + { + if (gmx) gmx->tDelete(); + ReThrow; + } +} + +void GetSubMatrix::operator-=(const BaseMatrix& bmx) +{ + REPORT + Tracer tr("SubMatrix(-=)"); GeneralMatrix* gmx = 0; + // MatrixConversionCheck mcc; // Check for loss of info + Try + { + SetUpLHS(); gmx = ((BaseMatrix&)bmx).Evaluate(); + if (row_number != gmx->Nrows() || col_number != gmx->Ncols()) + Throw(IncompatibleDimensionsException()); + MatrixRow mrx(gmx, LoadOnEntry); + MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip); + // do need LoadOnEntry + MatrixRowCol sub; int i = row_number; + while (i--) + { + mr.SubRowCol(sub, col_skip, col_number); // put values in sub + sub.Check(mrx); // check for loss of info + sub.Sub(mrx); mr.Next(); mrx.Next(); + } + gmx->tDelete(); + } + + CatchAll + { + if (gmx) gmx->tDelete(); + ReThrow; + } +} + +void GetSubMatrix::operator+=(Real r) +{ + REPORT + Tracer tr("SubMatrix(+= or -= Real)"); + // MatrixConversionCheck mcc; // Check for loss of info + Try + { + SetUpLHS(); + MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip); + // do need LoadOnEntry + MatrixRowCol sub; int i = row_number; + while (i--) + { + mr.SubRowCol(sub, col_skip, col_number); // put values in sub + sub.Check(); // check for loss of info + sub.Add(r); mr.Next(); + } + } + + CatchAll + { + ReThrow; + } +} + +void GetSubMatrix::operator*=(Real r) +{ + REPORT + Tracer tr("SubMatrix(*= or /= Real)"); + // MatrixConversionCheck mcc; // Check for loss of info + Try + { + SetUpLHS(); + MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip); + // do need LoadOnEntry + MatrixRowCol sub; int i = row_number; + while (i--) + { + mr.SubRowCol(sub, col_skip, col_number); // put values in sub + sub.Multiply(r); mr.Next(); + } + } + + CatchAll + { + ReThrow; + } +} + +#ifdef use_namespace +} +#endif + diff --git a/Utilities/OSSIM/ossim_core/matrix/svd.cpp b/Utilities/OSSIM/ossim_core/matrix/svd.cpp new file mode 100644 index 0000000000..fd499fa183 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/svd.cpp @@ -0,0 +1,204 @@ +//$$svd.cpp singular value decomposition + +// Copyright (C) 1991,2,3,4,5: R B Davies +// Updated 17 July, 1995 + +#define WANT_MATH + +#include "include.h" +#include "newmatap.h" +#include "newmatrm.h" +#include "precisio.h" + +#ifdef use_namespace +namespace NEWMAT { +#endif + +#ifdef DO_REPORT +#define REPORT { static ExeCounter ExeCount(__LINE__,15); ++ExeCount; } +#else +#define REPORT {} +#endif + + + + +void SVD(const Matrix& A, DiagonalMatrix& Q, Matrix& U, Matrix& V, + bool withU, bool withV) +// from Wilkinson and Reinsch: "Handbook of Automatic Computation" +{ + REPORT + Tracer trace("SVD"); + Real eps = FloatingPointPrecision::Epsilon(); + Real tol = FloatingPointPrecision::Minimum()/eps; + + int m = A.Nrows(); int n = A.Ncols(); + if (m<n) + Throw(ProgramException("Want no. Rows >= no. Cols", A)); + if (withV && &U == &V) + Throw(ProgramException("Need different matrices for U and V", U, V)); + U = A; Real g = 0.0; Real f,h; Real x = 0.0; int i; + RowVector E(n); RectMatrixRow EI(E,0); Q.ReSize(n); + RectMatrixCol UCI(U,0); RectMatrixRow URI(U,0,1,n-1); + + if (n) for (i=0;;) + { + EI.First() = g; Real ei = g; EI.Right(); Real s = UCI.SumSquare(); + if (s<tol) { REPORT Q.element(i) = 0.0; } + else + { + REPORT + f = UCI.First(); g = -sign(sqrt(s), f); h = f*g-s; UCI.First() = f-g; + Q.element(i) = g; RectMatrixCol UCJ = UCI; int j=n-i; + while (--j) { UCJ.Right(); UCJ.AddScaled(UCI, (UCI*UCJ)/h); } + } + + s = URI.SumSquare(); + if (s<tol) { REPORT g = 0.0; } + else + { + REPORT + f = URI.First(); g = -sign(sqrt(s), f); URI.First() = f-g; + EI.Divide(URI,f*g-s); RectMatrixRow URJ = URI; int j=m-i; + while (--j) { URJ.Down(); URJ.AddScaled(EI, URI*URJ); } + } + + Real y = fabs(Q.element(i)) + fabs(ei); if (x<y) { REPORT x = y; } + if (++i == n) { REPORT break; } + UCI.DownDiag(); URI.DownDiag(); + } + + if (withV) + { + REPORT + V.ReSize(n,n); V = 0.0; RectMatrixCol VCI(V,n-1,n-1,1); + if (n) { VCI.First() = 1.0; g=E.element(n-1); if (n!=1) URI.UpDiag(); } + for (i=n-2; i>=0; i--) + { + VCI.Left(); + if (g!=0.0) + { + VCI.Divide(URI, URI.First()*g); int j = n-i; + RectMatrixCol VCJ = VCI; + while (--j) { VCJ.Right(); VCJ.AddScaled( VCI, (URI*VCJ) ); } + } + VCI.Zero(); VCI.Up(); VCI.First() = 1.0; g=E.element(i); + if (i==0) break; + URI.UpDiag(); + } + } + + if (withU) + { + REPORT + for (i=n-1; i>=0; i--) + { + g = Q.element(i); URI.Reset(U,i,i+1,n-i-1); URI.Zero(); + if (g!=0.0) + { + h=UCI.First()*g; int j=n-i; RectMatrixCol UCJ = UCI; + while (--j) + { + UCJ.Right(); UCI.Down(); UCJ.Down(); Real s = UCI*UCJ; + UCI.Up(); UCJ.Up(); UCJ.AddScaled(UCI,s/h); + } + UCI.Divide(g); + } + else UCI.Zero(); + UCI.First() += 1.0; + if (i==0) break; + UCI.UpDiag(); + } + } + + eps *= x; + for (int k=n-1; k>=0; k--) + { + Real z = -FloatingPointPrecision::Maximum(); // to keep Gnu happy + Real y; int limit = 50; int l = 0; + while (limit--) + { + Real c, s; int i; int l1=k; bool tfc=false; + for (l=k; l>=0; l--) + { +// if (fabs(E.element(l))<=eps) goto test_f_convergence; + if (fabs(E.element(l))<=eps) { REPORT tfc=true; break; } + if (fabs(Q.element(l-1))<=eps) { REPORT l1=l; break; } + REPORT + } + if (!tfc) + { + REPORT + l=l1; l1=l-1; s = -1.0; c = 0.0; + for (i=l; i<=k; i++) + { + f = - s * E.element(i); E.element(i) *= c; +// if (fabs(f)<=eps) goto test_f_convergence; + if (fabs(f)<=eps) { REPORT break; } + g = Q.element(i); h = pythag(g,f,c,s); Q.element(i) = h; + if (withU) + { + REPORT + RectMatrixCol UCI(U,i); RectMatrixCol UCJ(U,l1); + ComplexScale(UCJ, UCI, c, s); + } + } + } +// test_f_convergence: z = Q.element(k); if (l==k) goto convergence; + z = Q.element(k); if (l==k) { REPORT break; } + + x = Q.element(l); y = Q.element(k-1); + g = E.element(k-1); h = E.element(k); + f = ((y-z)*(y+z) + (g-h)*(g+h)) / (2*h*y); + if (f>1) { REPORT g = f * sqrt(1 + square(1/f)); } + else if (f<-1) { REPORT g = -f * sqrt(1 + square(1/f)); } + else { REPORT g = sqrt(f*f + 1); } + { REPORT f = ((x-z)*(x+z) + h*(y / ((f<0.0) ? f-g : f+g)-h)) / x; } + + c = 1.0; s = 1.0; + for (i=l+1; i<=k; i++) + { + g = E.element(i); y = Q.element(i); h = s*g; g *= c; + z = pythag(f,h,c,s); E.element(i-1) = z; + f = x*c + g*s; g = -x*s + g*c; h = y*s; y *= c; + if (withV) + { + REPORT + RectMatrixCol VCI(V,i); RectMatrixCol VCJ(V,i-1); + ComplexScale(VCI, VCJ, c, s); + } + z = pythag(f,h,c,s); Q.element(i-1) = z; + f = c*g + s*y; x = -s*g + c*y; + if (withU) + { + REPORT + RectMatrixCol UCI(U,i); RectMatrixCol UCJ(U,i-1); + ComplexScale(UCI, UCJ, c, s); + } + } + E.element(l) = 0.0; E.element(k) = f; Q.element(k) = x; + } + if (l!=k) { Throw(ConvergenceException(A)); } +// convergence: + if (z < 0.0) + { + REPORT + Q.element(k) = -z; + if (withV) { RectMatrixCol VCI(V,k); VCI.Negate(); } + } + } + if (withU & withV) SortSV(Q, U, V); + else if (withU) SortSV(Q, U); + else if (withV) SortSV(Q, V); + else SortDescending(Q); +} + +void SVD(const Matrix& A, DiagonalMatrix& D) +{ REPORT Matrix U; SVD(A, D, U, U, false, false); } + + + +#ifdef use_namespace +} +#endif + diff --git a/Utilities/OSSIM/ossim_core/matrix/test_exc.txt b/Utilities/OSSIM/ossim_core/matrix/test_exc.txt new file mode 100644 index 0000000000..f22356b04d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/test_exc.txt @@ -0,0 +1,189 @@ + +This tests the exception system, so you will get +a long list of error messages + + +Print a real number (may help lost memory test): 3.14159 +----------------------------------------- + +Incompatible dimensions + + +An exception has been thrown +Logic error:- detected by Newmat: incompatible dimensions + +MatrixType = Rect # Rows = 2; # Cols = 3 +MatrixType = Rect # Rows = 4; # Cols = 5 +Trace: AddedMatrix::Evaluate; Block A; Test. + +----------------------------------------- + +Bad index + + +An exception has been thrown +Logic error:- detected by Newmat: index error: requested indices = 3, 3 + +MatrixType = Rect # Rows = 2; # Cols = 3 +Trace: Block B; Test. + +----------------------------------------- + +Illegal conversion + + +An exception has been thrown +Logic error:- detected by Newmat: Illegal Conversion +MatrixTypes = Rect ; UT + +Trace: Block C; Test. + +----------------------------------------- + +Invert non-square matrix - 1 + + +An exception has been thrown +Logic error:- detected by Newmat: matrix is not square + +MatrixType = Rect # Rows = 2; # Cols = 3 +Trace: CroutMatrix; Block D; Test. + +----------------------------------------- + +Invert non-square matrix - 2 + + +An exception has been thrown +Logic error:- detected by Newmat: matrix is not square + +MatrixType = Rect # Rows = 2; # Cols = 3 +Trace: GeneralSolvI; InvertedMatrix::Evaluate; Block E; Test. + +----------------------------------------- + +Non 1x1 matrix to scalar + + +An exception has been thrown +Logic error:- detected by Newmat: Cannot convert to scalar + +MatrixType = Rect # Rows = 2; # Cols = 3 +Trace: AsScalar; Block F; Test. + +----------------------------------------- + +Matrix to vector + + +An exception has been thrown +Logic error:- detected by Newmat: cannot convert matrix to vector + +MatrixType = Rect # Rows = 2; # Cols = 3 +Trace: ColumnVector; Block G; Test. + +----------------------------------------- + +Invert singular matrix + + +An exception has been thrown +Runtime error:- detected by Newmat: matrix is singular + +MatrixType = Crout # Rows = 2; # Cols = 2 +Trace: Crout(lubksb); GeneralSolvI; InvertedMatrix::Evaluate; Block H; Test. + +----------------------------------------- + +SubMatrix error + + +An exception has been thrown +Logic error:- detected by Newmat: incompatible submatrix dimension + +Trace: SubMatrix(evaluate); Block I; Test. + +----------------------------------------- + +SubMatrix error + + +An exception has been thrown +Logic error:- detected by Newmat: incompatible submatrix dimension + +Trace: SubMatrix(row); Block J; Test. + +----------------------------------------- + +Cholesky error + + +An exception has been thrown +Runtime error:- detected by Newmat: matrix not positive definite + +MatrixType = Sym # Rows = 50; # Cols = 50 +Trace: Cholesky; Block K; Test. + +----------------------------------------- + +Inequality error + + +An exception has been thrown +Logic error:- detected by Newmat: inequalities not defined for matrices + +Trace: Block L; Test. + +----------------------------------------- + +Maximum of empty matrix + + +An exception has been thrown +Logic error:- detected by Newmat: Maximum or minimum of null matrix + +Trace: Block M; Test. + +----------------------------------------- + +Incorrectly ReSizing band matrix + + +An exception has been thrown +Logic error:- detected by Newmat: UpperBandMatrix with non-zero lower band + +Trace: UpperBandMatrix::ReSize; Block N; Test. + +----------------------------------------- + +Incorrectly ReSizing symmetric band matrix + + +An exception has been thrown +Logic error:- detected by Newmat: Upper and lower band-widths not equal + +Trace: SymmetricBandMatrix::ReSize(GM); Block M; Test. + +----------------------------------------- + +ReSize CroutMatrix + + +An exception has been thrown +Logic error:- detected by Newmat: ReSize not defined for this type of matrix + +Trace: GeneralMatrix::ReSize(GM); Block O; Test. + +----------------------------------------- + + +End test + +(The following memory checks are probably not valid with all +compilers - see documentation) + +Checking for lost memory: 8141636 8141636 - ok + + +Checking for lost memory: 8141636 8141636 - ok + diff --git a/Utilities/OSSIM/ossim_core/matrix/watco_nt.mak b/Utilities/OSSIM/ossim_core/matrix/watco_nt.mak new file mode 100644 index 0000000000..7939bd8d06 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/watco_nt.mak @@ -0,0 +1,205 @@ +everything: tmt.exe example.exe nl_ex.exe sl_ex.exe garch.exe test_exc.exe + +.cpp.obj: + wpp386/bt=nt $*.cpp + +OBJ_LIB = bandmat.obj cholesky.obj evalue.obj fft.obj hholder.obj & + jacobi.obj myexcept.obj newmat1.obj newmat2.obj newmat3.obj & + newmat4.obj newmat5.obj newmat6.obj newmat7.obj newmat8.obj & + newmat9.obj newmatex.obj newmatnl.obj newmatrm.obj solution.obj & + sort.obj submat.obj svd.obj newfft.obj + +OBJ_T = tmt.obj tmt1.obj tmt2.obj tmt3.obj tmt4.obj tmt5.obj tmt6.obj & + tmt7.obj tmt8.obj tmt9.obj tmta.obj tmtb.obj tmtc.obj tmtd.obj tmte.obj & + tmtf.obj tmtg.obj tmth.obj tmti.obj tmtj.obj tmtk.obj tmtl.obj + +tmt.exe: $(OBJ_T) $(OBJ_LIB) + echo file newmat1.obj,newmat2.obj,newmat3.obj > link.lnk + echo file newmat4.obj,svd.obj,newmat5.obj >> link.lnk + echo file newmat6.obj,newmat7.obj,newmat8.obj >> link.lnk + echo file tmt.obj,tmt1.obj,tmt2.obj,tmt3.obj >> link.lnk + echo file tmt4.obj,tmt5.obj,tmt6.obj,tmt7.obj >> link.lnk + echo file tmt8.obj,tmt9.obj,tmta.obj,tmti.obj >> link.lnk + echo file tmtb.obj,tmtc.obj,tmtd.obj,tmte.obj >> link.lnk + echo file tmtf.obj,tmtg.obj,tmth.obj,tmtj.obj >> link.lnk + echo file tmtk.obj,tmtl.obj >> link.lnk + echo file cholesky.obj,hholder.obj,sort.obj >> link.lnk + echo file submat.obj,jacobi.obj,newmatrm.obj >> link.lnk + echo file fft.obj,evalue.obj,bandmat.obj >> link.lnk + echo file newmatex.obj,myexcept.obj,newfft.obj >> link.lnk + echo name tmt.exe >> link.lnk + echo SYSTEM nt >> link.lnk + wlink @link.lnk + +OBJ_E = example.obj + +example.exe: $(OBJ_E) $(OBJ_LIB) + echo file newmat1.obj,newmat2.obj,newmat3.obj > link.lnk + echo file newmat4.obj,svd.obj,newmat5.obj >> link.lnk + echo file newmat6.obj,newmat7.obj,newmat8.obj >> link.lnk + echo file cholesky.obj,hholder.obj,sort.obj >> link.lnk + echo file submat.obj,jacobi.obj,newmatrm.obj >> link.lnk + echo file fft.obj,evalue.obj,bandmat.obj >> link.lnk + echo file newmatex.obj,myexcept.obj,example.obj >> link.lnk + echo file newmat9.obj,newfft.obj >> link.lnk + echo name example.exe >> link.lnk + echo SYSTEM nt >> link.lnk + wlink @link.lnk + +OBJ_N = nl_ex.obj + +nl_ex.exe: $(OBJ_N) $(OBJ_LIB) + echo file newmat1.obj,newmat2.obj,newmat3.obj > link.lnk + echo file newmat4.obj,svd.obj,newmat5.obj >> link.lnk + echo file newmat6.obj,newmat7.obj,newmat8.obj >> link.lnk + echo file nl_ex.obj,newmatnl.obj,newmat9.obj >> link.lnk + echo file cholesky.obj,hholder.obj,sort.obj >> link.lnk + echo file submat.obj,jacobi.obj,newmatrm.obj >> link.lnk + echo file fft.obj,evalue.obj,bandmat.obj >> link.lnk + echo file newmatex.obj,myexcept.obj,newfft.obj >> link.lnk + echo name nl_ex.exe >> link.lnk + echo SYSTEM nt >> link.lnk + wlink @link.lnk + +OBJ_S = sl_ex.obj + +sl_ex.exe: $(OBJ_S) $(OBJ_LIB) + echo file sl_ex.obj,myexcept.obj,solution.obj > link.lnk + echo name sl_ex.exe >> link.lnk + echo SYSTEM nt >> link.lnk + wlink @link.lnk + +OBJ_G = garch.obj + +garch.exe: $(OBJ_G) $(OBJ_LIB) + echo file newmat1.obj,newmat2.obj,newmat3.obj > link.lnk + echo file newmat4.obj,svd.obj,newmat5.obj >> link.lnk + echo file newmat6.obj,newmat7.obj,newmat8.obj >> link.lnk + echo file garch.obj,newmatnl.obj,newmat9.obj >> link.lnk + echo file cholesky.obj,hholder.obj,sort.obj >> link.lnk + echo file submat.obj,jacobi.obj,newmatrm.obj >> link.lnk + echo file fft.obj,evalue.obj,bandmat.obj >> link.lnk + echo file newmatex.obj,myexcept.obj,newfft.obj >> link.lnk + echo name garch.exe >> link.lnk + echo SYSTEM nt >> link.lnk + wlink @link.lnk + +OBJ_X = test_exc.obj + +test_exc.exe: $(OBJ_X) $(OBJ_LIB) + echo file newmat1.obj,newmat2.obj,newmat3.obj > link.lnk + echo file newmat4.obj,svd.obj,newmat5.obj >> link.lnk + echo file newmat6.obj,newmat7.obj,newmat8.obj >> link.lnk + echo file test_exc.obj,newmatnl.obj,newmat9.obj >> link.lnk + echo file cholesky.obj,hholder.obj,sort.obj >> link.lnk + echo file submat.obj,jacobi.obj,newmatrm.obj >> link.lnk + echo file fft.obj,evalue.obj,bandmat.obj >> link.lnk + echo file newmatex.obj,myexcept.obj,newfft.obj >> link.lnk + echo name test_exc.exe >> link.lnk + echo SYSTEM nt >> link.lnk + wlink @link.lnk + +newmatxx = include.h newmat.h boolean.h myexcept.h + +myexcept.obj: include.h boolean.h myexcept.h myexcept.cpp + +newmatex.obj: $(newmatxx) newmatex.cpp + +newmatnl.obj: $(newmatxx) newmatnl.h newmatap.h + +example.obj: $(newmatxx) newmatap.h example.cpp + +cholesky.obj: $(newmatxx) cholesky.cpp + +evalue.obj: $(newmatxx) newmatrm.h precisio.h evalue.cpp + +fft.obj: $(newmatxx) newmatap.h fft.cpp + +newfft.obj: $(newmatxx) newmatap.h newfft.cpp + +hholder.obj: $(newmatxx) newmatap.h hholder.cpp + +jacobi.obj: $(newmatxx) precisio.h newmatrm.h jacobi.cpp + +bandmat.obj: $(newmatxx) newmatrc.h controlw.h bandmat.cpp + +newmat1.obj: $(newmatxx) newmat1.cpp + +newmat2.obj: $(newmatxx) newmatrc.h controlw.h newmat2.cpp + +newmat3.obj: $(newmatxx) newmatrc.h controlw.h newmat3.cpp + +newmat4.obj: $(newmatxx) newmatrc.h controlw.h newmat4.cpp + +newmat5.obj: $(newmatxx) newmatrc.h controlw.h newmat5.cpp + +newmat6.obj: $(newmatxx) newmatrc.h controlw.h newmat6.cpp + +newmat7.obj: $(newmatxx) newmatrc.h controlw.h newmat7.cpp + +newmat8.obj: $(newmatxx) newmatap.h newmat8.cpp + +newmat9.obj: $(newmatxx) newmatrc.h controlw.h newmatio.h newmat9.cpp + +newmatrm.obj: $(newmatxx) newmatrm.h newmatrm.cpp + +sort.obj: $(newmatxx) newmatap.h sort.cpp + +submat.obj: $(newmatxx) newmatrc.h controlw.h submat.cpp + +svd.obj: $(newmatxx) newmatrm.h precisio.h svd.cpp + +tmt.obj: $(newmatxx) newmatap.h tmt.cpp + +tmt1.obj: $(newmatxx) newmatap.h tmt1.cpp + +tmt2.obj: $(newmatxx) newmatap.h tmt2.cpp + +tmt3.obj: $(newmatxx) newmatap.h tmt3.cpp + +tmt4.obj: $(newmatxx) newmatap.h tmt4.cpp + +tmt5.obj: $(newmatxx) newmatap.h tmt5.cpp + +tmt6.obj: $(newmatxx) newmatap.h tmt6.cpp + +tmt7.obj: $(newmatxx) newmatap.h tmt7.cpp + +tmt8.obj: $(newmatxx) newmatap.h tmt8.cpp + +tmt9.obj: $(newmatxx) newmatap.h tmt9.cpp + +tmta.obj: $(newmatxx) newmatap.h tmta.cpp + +tmtb.obj: $(newmatxx) newmatap.h tmtb.cpp + +tmtc.obj: $(newmatxx) newmatap.h tmtc.cpp + +tmtd.obj: $(newmatxx) newmatap.h tmtd.cpp + +tmte.obj: $(newmatxx) newmatap.h tmte.cpp + +tmtf.obj: $(newmatxx) newmatap.h tmtf.cpp + +tmtg.obj: $(newmatxx) newmatap.h tmtg.cpp + +tmth.obj: $(newmatxx) newmatap.h tmth.cpp + +tmti.obj: $(newmatxx) newmatap.h tmti.cpp + +tmtj.obj: $(newmatxx) newmatap.h tmtj.cpp + +tmtk.obj: $(newmatxx) newmatap.h tmtk.cpp + +tmtl.obj: $(newmatxx) newmatap.h tmtl.cpp + +nl_ex.obj: $(newmatxx) newmatap.h newmatnl.h nl_ex.cpp + +sl_ex.obj: include.h boolean.h myexcept.h sl_ex.cpp + +solution.obj: include.h boolean.h myexcept.h solution.cpp + +garch.obj: $(newmatxx) newmatap.h newmatnl.h garch.cpp + +test_exc.obj: $(newmatxx) test_exc.cpp + diff --git a/Utilities/OSSIM/ossim_core/matrix/watcom.mak b/Utilities/OSSIM/ossim_core/matrix/watcom.mak new file mode 100644 index 0000000000..c6fdc4d0bd --- /dev/null +++ b/Utilities/OSSIM/ossim_core/matrix/watcom.mak @@ -0,0 +1,200 @@ +everything: tmt.exe example.exe nl_ex.exe sl_ex.exe garch.exe test_exc.exe + + +.cpp.obj: + wpp386 $*.cpp + +OBJ_LIB = bandmat.obj cholesky.obj evalue.obj fft.obj hholder.obj & + jacobi.obj myexcept.obj newmat1.obj newmat2.obj newmat3.obj & + newmat4.obj newmat5.obj newmat6.obj newmat7.obj newmat8.obj & + newmat9.obj newmatex.obj newmatnl.obj newmatrm.obj solution.obj & + sort.obj submat.obj svd.obj newfft.obj + +OBJ_T = tmt.obj tmt1.obj tmt2.obj tmt3.obj tmt4.obj tmt5.obj tmt6.obj & + tmt7.obj tmt8.obj tmt9.obj tmta.obj tmtb.obj tmtc.obj tmtd.obj tmte.obj & + tmtf.obj tmtg.obj tmth.obj tmti.obj tmtj.obj tmtk.obj tmtl.obj + +tmt.exe: $(OBJ_T) $(OBJ_LIB) + echo file newmat1.obj,newmat2.obj,newmat3.obj > link.lnk + echo file newmat4.obj,svd.obj,newmat5.obj >> link.lnk + echo file newmat6.obj,newmat7.obj,newmat8.obj >> link.lnk + echo file tmt.obj,tmt1.obj,tmt2.obj,tmt3.obj >> link.lnk + echo file tmt4.obj,tmt5.obj,tmt6.obj,tmt7.obj >> link.lnk + echo file tmt8.obj,tmt9.obj,tmta.obj,tmti.obj >> link.lnk + echo file tmtb.obj,tmtc.obj,tmtd.obj,tmte.obj >> link.lnk + echo file tmtf.obj,tmtg.obj,tmth.obj,tmtj.obj >> link.lnk + echo file tmtk.obj,tmtl.obj >> link.lnk + echo file cholesky.obj,hholder.obj,sort.obj >> link.lnk + echo file submat.obj,jacobi.obj,newmatrm.obj >> link.lnk + echo file fft.obj,evalue.obj,bandmat.obj >> link.lnk + echo file newmatex.obj,myexcept.obj,newfft.obj >> link.lnk + echo name tmt.exe >> link.lnk + echo option stack=8192 >> link.lnk + wlink @link.lnk + +OBJ_E = example.obj + +example.exe: $(OBJ_E) $(OBJ_LIB) + echo file newmat1.obj,newmat2.obj,newmat3.obj > link.lnk + echo file newmat4.obj,svd.obj,newmat5.obj >> link.lnk + echo file newmat6.obj,newmat7.obj,newmat8.obj >> link.lnk + echo file cholesky.obj,hholder.obj,sort.obj >> link.lnk + echo file submat.obj,jacobi.obj,newmatrm.obj >> link.lnk + echo file fft.obj,evalue.obj,bandmat.obj >> link.lnk + echo file newmatex.obj,myexcept.obj,example.obj >> link.lnk + echo file newmat9.obj,newfft.obj >> link.lnk + echo name example.exe >> link.lnk + wlink @link.lnk + +OBJ_N = nl_ex.obj + +nl_ex.exe: $(OBJ_N) $(OBJ_LIB) + echo file newmat1.obj,newmat2.obj,newmat3.obj > link.lnk + echo file newmat4.obj,svd.obj,newmat5.obj >> link.lnk + echo file newmat6.obj,newmat7.obj,newmat8.obj >> link.lnk + echo file nl_ex.obj,newmatnl.obj,newmat9.obj >> link.lnk + echo file cholesky.obj,hholder.obj,sort.obj >> link.lnk + echo file submat.obj,jacobi.obj,newmatrm.obj >> link.lnk + echo file fft.obj,evalue.obj,bandmat.obj >> link.lnk + echo file newmatex.obj,myexcept.obj,newfft.obj >> link.lnk + echo name nl_ex.exe >> link.lnk + wlink @link.lnk + +OBJ_S = sl_ex.obj + +sl_ex.exe: $(OBJ_S) $(OBJ_LIB) + echo file sl_ex.obj,myexcept.obj,solution.obj > link.lnk + echo name sl_ex.exe >> link.lnk + wlink @link.lnk + +OBJ_G = garch.obj + +garch.exe: $(OBJ_G) $(OBJ_LIB) + echo file newmat1.obj,newmat2.obj,newmat3.obj > link.lnk + echo file newmat4.obj,svd.obj,newmat5.obj >> link.lnk + echo file newmat6.obj,newmat7.obj,newmat8.obj >> link.lnk + echo file garch.obj,newmatnl.obj,newmat9.obj >> link.lnk + echo file cholesky.obj,hholder.obj,sort.obj >> link.lnk + echo file submat.obj,jacobi.obj,newmatrm.obj >> link.lnk + echo file fft.obj,evalue.obj,bandmat.obj >> link.lnk + echo file newmatex.obj,myexcept.obj,newfft.obj >> link.lnk + echo name garch.exe >> link.lnk + wlink @link.lnk + +OBJ_X = test_exc.obj + +test_exc.exe: $(OBJ_X) $(OBJ_LIB) + echo file newmat1.obj,newmat2.obj,newmat3.obj > link.lnk + echo file newmat4.obj,svd.obj,newmat5.obj >> link.lnk + echo file newmat6.obj,newmat7.obj,newmat8.obj >> link.lnk + echo file test_exc.obj,newmatnl.obj,newmat9.obj >> link.lnk + echo file cholesky.obj,hholder.obj,sort.obj >> link.lnk + echo file submat.obj,jacobi.obj,newmatrm.obj >> link.lnk + echo file fft.obj,evalue.obj,bandmat.obj >> link.lnk + echo file newmatex.obj,myexcept.obj,newfft.obj >> link.lnk + echo name test_exc.exe >> link.lnk + wlink @link.lnk + +newmatxx = include.h newmat.h boolean.h myexcept.h + +myexcept.obj: include.h boolean.h myexcept.h myexcept.cpp + +newmatex.obj: $(newmatxx) newmatex.cpp + +newmatnl.obj: $(newmatxx) newmatnl.h newmatap.h + +example.obj: $(newmatxx) newmatap.h example.cpp + +cholesky.obj: $(newmatxx) cholesky.cpp + +evalue.obj: $(newmatxx) newmatrm.h precisio.h evalue.cpp + +fft.obj: $(newmatxx) newmatap.h fft.cpp + +newfft.obj: $(newmatxx) newmatap.h newfft.cpp + +hholder.obj: $(newmatxx) newmatap.h hholder.cpp + +jacobi.obj: $(newmatxx) precisio.h newmatrm.h jacobi.cpp + +bandmat.obj: $(newmatxx) newmatrc.h controlw.h bandmat.cpp + +newmat1.obj: $(newmatxx) newmat1.cpp + +newmat2.obj: $(newmatxx) newmatrc.h controlw.h newmat2.cpp + +newmat3.obj: $(newmatxx) newmatrc.h controlw.h newmat3.cpp + +newmat4.obj: $(newmatxx) newmatrc.h controlw.h newmat4.cpp + +newmat5.obj: $(newmatxx) newmatrc.h controlw.h newmat5.cpp + +newmat6.obj: $(newmatxx) newmatrc.h controlw.h newmat6.cpp + +newmat7.obj: $(newmatxx) newmatrc.h controlw.h newmat7.cpp + +newmat8.obj: $(newmatxx) newmatap.h newmat8.cpp + +newmat9.obj: $(newmatxx) newmatrc.h controlw.h newmatio.h newmat9.cpp + +newmatrm.obj: $(newmatxx) newmatrm.h newmatrm.cpp + +sort.obj: $(newmatxx) newmatap.h sort.cpp + +submat.obj: $(newmatxx) newmatrc.h controlw.h submat.cpp + +svd.obj: $(newmatxx) newmatrm.h precisio.h svd.cpp + +tmt.obj: $(newmatxx) newmatap.h tmt.cpp + +tmt1.obj: $(newmatxx) newmatap.h tmt1.cpp + +tmt2.obj: $(newmatxx) newmatap.h tmt2.cpp + +tmt3.obj: $(newmatxx) newmatap.h tmt3.cpp + +tmt4.obj: $(newmatxx) newmatap.h tmt4.cpp + +tmt5.obj: $(newmatxx) newmatap.h tmt5.cpp + +tmt6.obj: $(newmatxx) newmatap.h tmt6.cpp + +tmt7.obj: $(newmatxx) newmatap.h tmt7.cpp + +tmt8.obj: $(newmatxx) newmatap.h tmt8.cpp + +tmt9.obj: $(newmatxx) newmatap.h tmt9.cpp + +tmta.obj: $(newmatxx) newmatap.h tmta.cpp + +tmtb.obj: $(newmatxx) newmatap.h tmtb.cpp + +tmtc.obj: $(newmatxx) newmatap.h tmtc.cpp + +tmtd.obj: $(newmatxx) newmatap.h tmtd.cpp + +tmte.obj: $(newmatxx) newmatap.h tmte.cpp + +tmtf.obj: $(newmatxx) newmatap.h tmtf.cpp + +tmtg.obj: $(newmatxx) newmatap.h tmtg.cpp + +tmth.obj: $(newmatxx) newmatap.h tmth.cpp + +tmti.obj: $(newmatxx) newmatap.h tmti.cpp + +tmtj.obj: $(newmatxx) newmatap.h tmtj.cpp + +tmtk.obj: $(newmatxx) newmatap.h tmtk.cpp + +tmtl.obj: $(newmatxx) newmatap.h tmtl.cpp + +nl_ex.obj: $(newmatxx) newmatap.h newmatnl.h nl_ex.cpp + +sl_ex.obj: include.h boolean.h myexcept.h sl_ex.cpp + +solution.obj: include.h boolean.h myexcept.h solution.cpp + +garch.obj: $(newmatxx) newmatap.h newmatnl.h garch.cpp + +test_exc.obj: $(newmatxx) newmatap.h newmatnl.h test_exc.cpp diff --git a/Utilities/OSSIM/ossim_core/parallel/.cvsignore b/Utilities/OSSIM/ossim_core/parallel/.cvsignore new file mode 100644 index 0000000000..c7420bf174 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/parallel/.cvsignore @@ -0,0 +1,4 @@ +*.d +Makefile +.shared_obj + diff --git a/Utilities/OSSIM/ossim_core/parallel/CMakeLists.txt b/Utilities/OSSIM/ossim_core/parallel/CMakeLists.txt new file mode 100644 index 0000000000..22cae85d29 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/parallel/CMakeLists.txt @@ -0,0 +1,6 @@ +FILE(GLOB_RECURSE ossim_parallel_SRCS "*.cpp") +FILE(GLOB_RECURSE ossim_parallel_HDRS "*.h") +ADD_LIBRARY(ossim_parallel ${ossim_parallel_SRCS}) + +INSTALL_TARGETS(/lib/otb/ ossim_parallel) +INSTALL_FILES(/include/otb/Utilities/OSSIM/ossim_core/ "\\.h$" ${ossim_parallel_HRDS}) diff --git a/Utilities/OSSIM/ossim_core/parallel/ossimIgen.cpp b/Utilities/OSSIM/ossim_core/parallel/ossimIgen.cpp new file mode 100644 index 0000000000..4fd5a108fb --- /dev/null +++ b/Utilities/OSSIM/ossim_core/parallel/ossimIgen.cpp @@ -0,0 +1,805 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: implementation for image generator +// +//************************************************************************* +// $Id: ossimIgen.cpp,v 1.18 2005/12/25 17:33:14 dburken Exp $ + +#include <iterator> +#include <sstream> +#include <exception> + +#include <ossimConfig.h> /* To pick up define OSSIM_HAS_MPI. */ + +#ifdef OSSIM_HAS_MPI +# if OSSIM_HAS_MPI +# include <mpi.h> +# endif +#endif + +#include <parallel/ossimIgen.h> +#include <base/common/ossimKeywordNames.h> +#include <base/common/ossimTrace.h> +#include <base/common/ossimStdOutProgress.h> + +#include <init/ossimInit.h> +#include <projections/ossimProjection.h> +// #include "projections/map_projections/ossimUtmProjection.h> + +#include <projections/map_projections/ossimMapProjection.h> +#include <projections/map_projections/ossimMapProjectionInfo.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <projections/factory/ossimMapProjectionFactory.h> +#include <imaging/ossimImageChain.h> +#include <base/data_types/ossimKeywordlist.h> +#include <imaging/ossimImageData.h> +#include <imaging/ossimImageChain.h> +#include <imaging/tile_sources/ossimImageRenderer.h> +#include <imaging/tile_sources/ossimRectangleCutFilter.h> +#include <imaging/formats/tiff/ossimTiffWriter.h> +#include <imaging/factory/ossimImageWriterFactoryRegistry.h> +#include <base/data_types/ossimDpt.h> +#include <base/factory/ossimDatumFactory.h> +#include <imaging/factory/ossimImageHandlerRegistry.h> +#include <imaging/formats/ossimImageHandler.h> +#include <projections/ossimImageViewProjectionTransform.h> +#include <base/factory/ossimObjectFactoryRegistry.h> +#include <imaging/annotation/ossimGeoAnnotationSource.h> +#include <base/common/ossimPreferences.h> +#include <base/common/ossimKeywordNames.h> +#include <parallel/ossimMpi.h> +#include <base/common/ossimArgumentParser.h> +#include <base/common/ossimApplicationUsage.h> + +// include the Master implementation for the writer +// sequence. +// +#include <parallel/ossimImageMpiMWriterSequenceConnection.h> +#include <parallel/ossimImageMpiSWriterSequenceConnection.h> + +// #include <parallel/ossimImageMpiSequenceConnection.h> + +static ossimTrace traceDebug(ossimString("ossimIgen:debug")); + +ossimIgen::ossimIgen() + : + theProductProjection(NULL), + theOutputRect(), + theBuildThumbnailFlag(false), + theThumbnailResolution(0, 0), + theNumberOfTilesToBuffer(2), + theKwl(), + theTilingEnabled(false), + theTiling(), + theProgressFlag(true) +{ + theOutputRect.makeNan(); +} + +ossimIgen::~ossimIgen() +{ + deleteAttributes(); + +} + +void ossimIgen::initializeAttributes() +{ + theBuildThumbnailFlag = false; + theThumbnailResolution = ossimIpt(0,0); + theTilingEnabled = false; + + if(ossimMpi::instance()->getRank() != 0) + { + ossimPreferences::instance()->addPreferences(theKwl, + "preferences.", + true); + } + + const char* lookup = theKwl.find("igen.output_progress"); + if (lookup) + { + ossimString os = lookup; + theProgressFlag = os.toBool(); + } + + const char* thumbnailStr = theKwl.find("igen.thumbnail"); + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "Thumbnail string = " << ossimString(thumbnailStr) << std::endl; + } + if(thumbnailStr) + { + theBuildThumbnailFlag= ossimString(thumbnailStr).toBool(); + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "Generate thumbnail attribute is set to " + << theBuildThumbnailFlag << std::endl; + } + if(theBuildThumbnailFlag) + { + const char* resStr = theKwl.find("igen.thumbnail_res"); + if(resStr) + { + theThumbnailResolution = ossimIpt(0,0); + std::istringstream in(resStr); + in >> theThumbnailResolution.x >> theThumbnailResolution.y; + + if(theThumbnailResolution.x < 1) + { + theThumbnailResolution.x = 128; + } + if(theThumbnailResolution.y < 1) + { + theThumbnailResolution.y = theThumbnailResolution.x; + } +// theThumbnailResolution = ossimString(resStr).toInt32(); + + } + else + { + theThumbnailResolution = ossimIpt(128, 128); + } + } + } + const char* numberOfSlaveTileBuffersStr = theKwl.find("igen.slave_tile_buffers"); + if(numberOfSlaveTileBuffersStr) + { + theNumberOfTilesToBuffer = ossimString(numberOfSlaveTileBuffersStr).toLong(); + } + + const char* tilingKw = theKwl.find("igen.tiling.type"); + if(tilingKw) + { + theTilingEnabled = true; + if(!theTiling.loadState(theKwl, "igen.tiling.")) + { + theTilingEnabled = false; + } + } +} + +void ossimIgen::slaveSetup() +{ +#ifdef OSSIM_HAS_MPI +# if OSSIM_HAS_MPI + int stringSize; + MPI_Status status; + int numberOfTimes = 0; + + // we first need to receive the size of the keyword list to load + MPI_Recv(&stringSize, + 1, + MPI_INT, + 0, // source + 0, // tag + MPI_COMM_WORLD, + &status); + + if(status.MPI_ERROR != MPI_SUCCESS) + { + ossimNotify(ossimNotifyLevel_WARN) + << "SLAVE = " + << ossimMpi::instance()->getRank() + << "Had errors receiving!!!!" << std::endl; + return; + } + + char* buf = new char[stringSize+1]; + + numberOfTimes = 0; + + // now lets get the keywordlist as a string so we can load it up + MPI_Recv(buf, + stringSize, + MPI_CHAR, + 0, // source + 0, // tag + MPI_COMM_WORLD, + &status); + + if(status.MPI_ERROR != MPI_SUCCESS) + { + ossimNotify(ossimNotifyLevel_WARN) + << "SLAVE = " << ossimMpi::instance()->getRank() + << "Had errors receiving in ossimIgen::slaveCreate(!!!!" + << std::endl; + return; + } + buf[stringSize] = '\0'; + + if(status.MPI_ERROR != MPI_SUCCESS) + { + ossimNotify(ossimNotifyLevel_WARN) + << "SLAVE = " << ossimMpi::instance()->getRank() + << "Had errors receiving!!!!" << std::endl; + return; + } + + // now lets convert the received keywordlist into an actual + // ossimKeywordlist by using the parsStream method. + std::ostringstream kwlStream; + + kwlStream << buf << ends; + + istringstream kwlInStream(kwlStream.str()); + theKwl.clear(); + theKwl.parseStream(kwlInStream); + initializeAttributes(); + delete buf; + buf = NULL; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "****************** KWL ************************" << std::endl; + ossimNotify(ossimNotifyLevel_DEBUG) << theKwl << std::endl; + ossimNotify(ossimNotifyLevel_DEBUG) << "**************** END KWL ************************" << std::endl; + + } + loadProduct(); +# endif +#endif +} + +void ossimIgen::initialize(const ossimKeywordlist& kwl) +{ +#ifdef OSSIM_HAS_MPI +# if OSSIM_HAS_MPI + if(ossimMpi::instance()->getNumberOfProcessors() > 0) + { + if(ossimMpi::instance()->getRank() != 0) + { + slaveSetup(); + return; + } + } +# endif +#endif + theKwl = kwl; + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "The igen kewyord list ==== \n" << theKwl << std::endl; + } + ossimKeywordlist kwlPrefs = ossimPreferences::instance()->preferencesKWL(); + + kwlPrefs.addPrefixToAll("preferences."); + theKwl.add(kwlPrefs); + + initializeAttributes(); + + // now stream it to all slave processors + // +#ifdef OSSIM_HAS_MPI +# if OSSIM_HAS_MPI + + if(ossimMpi::instance()->getNumberOfProcessors() > 0) + { + std::ostringstream outputKeywordlist; + + theKwl.writeToStream(outputKeywordlist); + ossimString kwlString = outputKeywordlist.str(); + ossim_uint32 size = kwlString.size(); + + for(long processor = 1; + processor < ossimMpi::instance()->getNumberOfProcessors(); + ++processor) + { + // let's send the keywordlist argument. + // This is two steps. We send a message to + // indicate the size and then we send the + // string. + // + MPI_Send(&size, + 1, + MPI_INT, + processor, + 0, + MPI_COMM_WORLD); + + MPI_Send((void*)kwlString.c_str(), + size, + MPI_CHAR, + processor, + 0, + MPI_COMM_WORLD); + } + } +# endif +#endif + loadProduct(); + +} + +bool ossimIgen::loadProduct()//ossimKeywordlist& kwl, + //bool thumbnail, + //long resolution) +{ + const char* MODULE = "ossimIgen::loadProduct"; + + if(traceDebug()) + { + CLOG << "entered..." << std::endl; + } + + if(traceDebug()) + { + CLOG << " Creating object1..." << std::endl; + } + + theContainer.deleteAllChildren(); + + theContainer.loadState(theKwl); + + theProductProjection = buildProductProjection(theKwl); + + if(theProductProjection) + { + vector<ossimImageViewTransform*> transforms; + setView(&theContainer, theProductProjection); + // if it's a thumbnail then adjust the GSD and + // reset the view proj to the chain. + if(theBuildThumbnailFlag) + { + buildThumbnail(); + delete theProductProjection; + + theProductProjection = buildProductProjection(theKwl); + + setView(&theContainer, theProductProjection); + } + + } + + ossimKeywordlist proj; + + ossimDrect rect; + ossimImageChain* chain = getChain(); + if(!getOutputRect(theKwl, rect)&&chain) + { + rect = chain->getBoundingRect(); + } + else + { + rect.makeNan(); + } + + // Stretch the rectangle out to integer boundaries. + if(!rect.hasNans()) + { + rect.stretchOut(); + } + theOutputRect = rect; + + if(theProductProjection) + { + theProductProjection->saveState(proj, "projection."); + + } + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "bounding rect = " << theOutputRect << std::endl; + CLOG << "leaving..." << std::endl; + } + + return true; +} + +void ossimIgen::outputProduct() +{ + ossimImageChain* chain = getChain(); + if(chain) + { + chain->initialize(); + } + ossimImageSourceSequencer* sequencer = NULL; + +#ifdef OSSIM_HAS_MPI +# if OSSIM_HAS_MPI + // only allocate the slave connection if + // the number of processors is larger than + // 1 + // + if(ossimMpi::instance()->getNumberOfProcessors() > 1) + { + if(ossimMpi::instance()->getRank()!=0) + { + sequencer = new ossimImageMpiSWriterSequenceConnection(NULL, + theNumberOfTilesToBuffer); + } + else + { + sequencer = new ossimImageMpiMWriterSequenceConnection(); + } + } + else + { + sequencer = new ossimImageSourceSequencer(); + } +# else + + // we will just load a serial connection if MPI is not supported. + // + sequencer = new ossimImageSourceSequencer(NULL); + +# endif +#else + + // we will just load a serial connection if MPI is not supported. + sequencer = new ossimImageSourceSequencer(NULL); + +#endif + + std::vector<ossimConnectableObject*> imageWriters = theContainer.findAllObjectsOfType(STATIC_TYPE_INFO(ossimImageFileWriter), + false); + if(imageWriters.size() > 0) + { + ossimImageFileWriter* writer = PTR_CAST(ossimImageFileWriter, imageWriters[0]); + + + writer->changeSequencer(sequencer); + writer->connectMyInputTo(chain); + writer->initialize(); + } + else + { + delete sequencer; + sequencer = NULL; + } + + std::vector<ossimConnectableObject*> processObjects = theContainer.findAllObjectsOfType(STATIC_TYPE_INFO(ossimProcessInterface), + false); + ossim_uint32 i = 0; + ossimImageFileWriter* writer = 0; + for(i = 0; ((i < processObjects.size())&&(!writer)); ++i) + { + writer = PTR_CAST(ossimImageFileWriter, + processObjects[i]); + } + + if(writer) + { + ossimRefPtr<ossimProjection> proj = buildProductProjection(theKwl); + ossimMapProjection *mapProj = PTR_CAST(ossimMapProjection,proj.get()); + + if(theTilingEnabled&&mapProj) + { + ossimRefPtr<ossimMapProjection> view; + ossimIrect clipRect; + theTiling.initialize(*mapProj, + chain->getBoundingRect()); + ossimRectangleCutFilter* cut = new ossimRectangleCutFilter; + + chain->addFirst(cut); + ossim_uint32 idx = 0; + ossimFilename tempFile = writer->getFilename(); + + if(!tempFile.isDir()) + { + tempFile = tempFile.path(); + } + ossimString tileName; + + while(theTiling.next(view, + clipRect, + tileName)) + { + ossimStdOutProgress* prog = NULL; + if ( (ossimMpi::instance()->getRank() == 0) && theProgressFlag) + { + // Add a listener to master. + prog = new ossimStdOutProgress(0, true); + writer->addListener(prog); + } + + setView(chain, view.get()); + chain->initialize(); + cut->setRectangle(clipRect); + chain->initialize(); + writer->disconnect(); + writer->connectMyInputTo(chain); + writer->setFilename(tempFile.dirCat(tileName)); + writer->initialize(); + + try + { + writer->execute(); + } + catch(std::exception& e) + { + ossimNotify(ossimNotifyLevel_FATAL) + << "ossimIgen::outputProduct ERROR:\n" + << "Caught exception!\n" + << e.what() + << std::endl; + } + catch(...) + { + ossimNotify(ossimNotifyLevel_FATAL) + << "ossimIgen::outputProduct ERROR:\n" + << "Unknown exception caught!\n" + << std::endl; + } + + ++idx; + + if (prog) + { + writer->removeListener(prog); + delete prog; + prog = NULL; + } + + } + } + else + { + ossimStdOutProgress* prog = NULL; + if ( (ossimMpi::instance()->getRank() == 0) && theProgressFlag) + { + // Add a listener to master. + prog = new ossimStdOutProgress(0, true); + writer->addListener(prog); + } + + try + { + writer->execute(); + } + catch(std::exception& e) + { + ossimNotify(ossimNotifyLevel_FATAL) + << "ossimIgen::outputProduct ERROR:\n" + << "Caught exception!\n" + << e.what() + << std::endl; + } + catch(...) + { + ossimNotify(ossimNotifyLevel_FATAL) + << "ossimIgen::outputProduct ERROR:\n" + << "Unknown exception caught!\n" + << std::endl; + } + + if (prog) + { + writer->removeListener(prog); + delete prog; + prog = NULL; + } + } + } + + if(ossimMpi::instance()->getRank() == 0) + { + for(ossim_uint32 i = 0; i < processObjects.size(); ++i) + { + if(!PTR_CAST(ossimImageFileWriter, + processObjects[i])) + { + ossimProcessInterface* process = PTR_CAST(ossimProcessInterface, + processObjects[i]); + if(process) + { + processObjects[i]->connectMyInputTo(chain); + process->execute(); + } + } + } + } +} + +void ossimIgen::deleteAttributes() +{ + if(theProductProjection) + { + delete theProductProjection; + theProductProjection = NULL; + } + theContainer.deleteAllChildren(); +} + +ossimProjection* ossimIgen::createImageProjection(const ossimKeywordlist& kwl) +{ + // here we need to modify the factory to produce the correct + // projector so we can seemlessly use sensors as well. For + // now we hardcode the Map projector + ossimProjection* imageProjection = ossimProjectionFactoryRegistry::instance()->createProjection(kwl); + + if(!imageProjection) + { + +// cerr << "Unable to create Image projection: " +// << ossimString(kwl.find("projection.type")) +// << " in ossimIgen::createImageProjection" << endl; + // ERROR + } + + return imageProjection; +} + +ossimProjection* ossimIgen::buildProductProjection(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimKeywordlist kwlProj; + + ossimString projPrefix = ossimString(prefix) + "projection."; + const char* ul_lat = kwl.find(prefix, ossimKeywordNames::UL_LAT_KW); + const char* ul_lon = kwl.find(prefix, ossimKeywordNames::UL_LON_KW); + const char* lr_lat = kwl.find(prefix, ossimKeywordNames::LR_LAT_KW); + const char* lr_lon = kwl.find(prefix, ossimKeywordNames::LR_LON_KW); + const char* origin_latitude = kwl.find(projPrefix.c_str(), + ossimKeywordNames::ORIGIN_LATITUDE_KW); + const char* central_meridian = kwl.find(projPrefix.c_str(), + ossimKeywordNames::CENTRAL_MERIDIAN_KW); + double originLat = 0.0; + double originLon = 0.0; + + ossimProjection* projection = NULL; + projection = ossimProjectionFactoryRegistry::instance()->createProjection(kwl, "product.projection."); + + ossimMapProjection* mapProj = PTR_CAST(ossimMapProjection, projection); + + + if(mapProj) + { + ossimKeywordlist projKwl; + mapProj->saveState(projKwl); + + // allow one to override + if(origin_latitude&¢ral_meridian) + { + originLat = ossimString(origin_latitude).toDouble(); + originLon = ossimString(central_meridian).toDouble(); + } + // default + else if(ul_lat&&ul_lon&&lr_lat&&lr_lon) + { + double ulLat = ossimString(ul_lat).toDouble(); + double ulLon = ossimString(ul_lon).toDouble(); + double lrLat = ossimString(lr_lat).toDouble(); + double lrLon = ossimString(lr_lon).toDouble(); + + originLat = (ulLat + lrLat)*.5; + originLon = (ulLon + lrLon)*.5; + + if (origin_latitude) + { + originLat = ossimString(origin_latitude).toDouble(); + } + if (central_meridian) + { + originLon = ossimString(central_meridian).toDouble(); + } + } + + if(origin_latitude) + { + projKwl.add(ossimKeywordNames::ORIGIN_LATITUDE_KW, + originLat, + true); + } + + if(central_meridian) + { + projKwl.add(ossimKeywordNames::CENTRAL_MERIDIAN_KW, + originLon, + true); + } + delete mapProj; + + projection = ossimProjectionFactoryRegistry::instance()->createProjection(projKwl); + + } + else + { + +// cout << "ERROR: not all product information was supplied. \n" +// << " need: ul_lat, ul_lon, lr_lat lr_lon (area of coverage)\n" +// << " projection datum and projection type"; + } + + + return projection; +} + +void ossimIgen::setView(ossimConnectableObject* obj, + ossimObject* viewObj) +{ + if(!viewObj||!obj) + { + return; + } + vector<ossimConnectableObject*> result; + obj->findAllInputsOfType(result, STATIC_TYPE_INFO(ossimViewInterface), true, true); + + for(ossim_uint32 i = 0; i < result.size();++i) + { + ossimViewInterface* viewInterface = PTR_CAST(ossimViewInterface, + result[i]); + if(viewInterface) + { + ossimObject* obj = viewObj->dup(); + viewInterface->setView(obj, true); + } + } +} + + +bool ossimIgen::getOutputRect(const ossimKeywordlist& kwl, + ossimDrect& rect) +{ + ossimProjection* viewProj = buildProductProjection(kwl); + ossimImageChain* chain = getChain(); + + + + if(chain) + { + setView(chain, viewProj); + chain->initialize(); + rect = chain->getBoundingRect(); + + return true; + } + if(viewProj) + { + delete viewProj; + } + + return false; +} + +void ossimIgen::buildThumbnail() +{ + double resolution = ossimMax(theThumbnailResolution.x, theThumbnailResolution.y); + ossimProjection* viewProj = buildProductProjection(theKwl); + ossimMapProjection* mapProj = PTR_CAST(ossimMapProjection, viewProj); + + + ossimDrect rect; + + if(mapProj && getOutputRect(theKwl, rect)) + { + double xScale = rect.width() / (double)resolution; + double yScale = rect.height() / (double)resolution; + + //--- + // Maintain aspect ratio - adjust based on largest Scale. + // + // Note the second argument to applyScale is to + // "not recenter the tie point". This was added to fix a resampler + // runaway split problem. (drb 20051225) + //--- + if (xScale > yScale) + { + mapProj->applyScale(ossimDpt(xScale, xScale), false); + } + else + { + mapProj->applyScale(ossimDpt(yScale, yScale), false); + } + mapProj->saveState(theKwl, "product.projection."); + } + + delete viewProj; +} + +ossimImageChain* ossimIgen::getChain() +{ + ossimConnectableObject* obj = theContainer.findFirstObjectOfType(STATIC_TYPE_NAME(ossimImageChain), + false); + + return PTR_CAST(ossimImageChain, obj); +} diff --git a/Utilities/OSSIM/ossim_core/parallel/ossimIgen.h b/Utilities/OSSIM/ossim_core/parallel/ossimIgen.h new file mode 100644 index 0000000000..d1023b9355 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/parallel/ossimIgen.h @@ -0,0 +1,94 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: Class declaration for image generator. +// +//************************************************************************* +// $Id: ossimIgen.h,v 1.6 2005/10/11 22:19:58 dburken Exp $ +#ifndef ossimIgen_HEADER +#define ossimIgen_HEADER + +#include <iostream> +#include <list> +#include <fstream> + +#include <base/data_types/ossimDrect.h> +#include <base/data_types/ossimFilename.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/common/ossimConnectableContainer.h> +#include <imaging/ossimTiling.h> + +class ossimImageChain; +class ossimImageFileWriter; +class ossimProjection; +class ossimImageViewTransform; +class ossimImageSource; +class ossimImageMpiMWriterSequenceConnection; +class ossimImageMpiSWriterSequenceConnection; +class ossimObject; +class ossimArgumentParser; + +class OSSIM_DLL ossimIgen +{ +public: + ossimIgen(); + virtual ~ossimIgen(); + + virtual void initialize(const ossimKeywordlist& kwl); + virtual void outputProduct(); + +protected: + ossimConnectableContainer theContainer; + + ossimProjection* theProductProjection; + ossimDrect theOutputRect; + bool theBuildThumbnailFlag; + ossimIpt theThumbnailResolution; + long theNumberOfTilesToBuffer; + ossimKeywordlist theKwl; + bool theTilingEnabled; + ossimTiling theTiling; + bool theProgressFlag; + + /** + * Initializes attributes of class. + * + * Keywords searched for by method: + * + * igen.output_progress: true (bool) + * + * igen.thumbnail: true (bool) + * + * igen.thumbnail_res: 128 128 (x_res, y_res) + * + * (number of buffers for slave nodes to process before waiting) + * igen.slave_tile_buffers: 2 + * + * igen.tiling.type: ? + * + * igen.tiling: ? + */ + void initializeAttributes(); + void slaveSetup(); + + bool loadProduct(); + + void deleteAttributes(); + void setView(ossimConnectableObject* obj, ossimObject* viewObj); + ossimProjection* createImageProjection(const ossimKeywordlist& kwl); + virtual ossimProjection* buildProductProjection(const ossimKeywordlist& kwl, + const char* prefix="product."); + bool getOutputRect(const ossimKeywordlist& kwl, + ossimDrect& rect); + void buildThumbnail(); + void outputImageGeometry(const char* filename); + ossimImageChain* getChain(); +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/parallel/ossimImageMpiMWriterSequenceConnection.cpp b/Utilities/OSSIM/ossim_core/parallel/ossimImageMpiMWriterSequenceConnection.cpp new file mode 100644 index 0000000000..7cc5a56600 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/parallel/ossimImageMpiMWriterSequenceConnection.cpp @@ -0,0 +1,290 @@ +//******************************************************************* +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +// This class is specific to the Master connection and is optimized +// for the writer sequence and batch processing chain. For the Slave +// implementation look for the ossimImageMpiSWriterSequenceConnection.cc and .h +// files. The Master connection is currently implemented to allways do +// a recieve and does no processing itself. The slave connection does +// all the actual work and processing. +// +//******************************************************************* +// $Id: ossimImageMpiMWriterSequenceConnection.cpp,v 1.20 2005/11/07 22:03:24 dburken Exp $ + + +#include <ossimConfig.h> /* To pick up OSSIM_HAS_MPI. */ + +#ifdef OSSIM_HAS_MPI +# if OSSIM_HAS_MPI +# include <mpi.h> +# endif +#endif + +#include <parallel/ossimImageMpiMWriterSequenceConnection.h> +#include <parallel/ossimMpi.h> +#include <imaging/ossimImageData.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <base/common/ossimTrace.h> +#include <base/misc/ossimEndian.h> + +static ossimTrace traceDebug = ossimTrace("ossimImageMpiMWriterSequenceConnection:debug"); + +RTTI_DEF1(ossimImageMpiMWriterSequenceConnection, "ossimImageMpiMWriterSequenceConnection", ossimImageSourceSequencer) + + +ossimImageMpiMWriterSequenceConnection::ossimImageMpiMWriterSequenceConnection( + ossimImageSource* inputSource, + ossimObject* owner) + :ossimImageSourceSequencer(inputSource, owner), + theOutputTile(NULL) +{ + theRank = 0; + theNumberOfProcessors = 1; + +#ifdef OSSIM_HAS_MPI +# if OSSIM_HAS_MPI + MPI_Comm_rank(MPI_COMM_WORLD, &theRank); + MPI_Comm_size(MPI_COMM_WORLD, &theNumberOfProcessors); +# endif +#endif + + if(theRank!=0) + { + theCurrentTileNumber = theRank -1; + } + else + { + theCurrentTileNumber = 0; + } + theNeedToSendRequest = true; +} + +ossimImageMpiMWriterSequenceConnection::ossimImageMpiMWriterSequenceConnection(ossimObject* owner) + :ossimImageSourceSequencer(NULL, owner), + theOutputTile(NULL) +{ + theRank = 0; + theNumberOfProcessors = 1; + +#ifdef OSSIM_HAS_MPI +# if OSSIM_HAS_MPI + MPI_Comm_rank(MPI_COMM_WORLD, &theRank); + MPI_Comm_size(MPI_COMM_WORLD, &theNumberOfProcessors); +# endif +#endif + + if(theRank!=0) + { + theCurrentTileNumber = theRank -1; + } + else + { + theCurrentTileNumber = 0; + } + theNeedToSendRequest = true; +} + +ossimImageMpiMWriterSequenceConnection::~ossimImageMpiMWriterSequenceConnection() +{ +} + +void ossimImageMpiMWriterSequenceConnection::initialize() +{ + ossimImageSourceSequencer::initialize(); + + theCurrentTileNumber = theRank;//-1; + theOutputTile = NULL; + + if(theInputConnection) + { + theOutputTile = ossimImageDataFactory::instance()->create(this, this); + theOutputTile->initialize(); + } +} + +void ossimImageMpiMWriterSequenceConnection::setToStartOfSequence() +{ + ossimImageSourceSequencer::setToStartOfSequence(); + if(theRank != 0) + { + // we will subtract one since the masters job is just + // writting and not issue getTiles. + theCurrentTileNumber = theRank-1; + + } + else + { + // the master will start at 0 + theCurrentTileNumber = 0; + } +} + +/*! + * Will allow you to get the next tile in the sequence. + */ +ossimRefPtr<ossimImageData> ossimImageMpiMWriterSequenceConnection::getNextTile(ossim_uint32 resLevel) +{ +#if OSSIM_HAS_MPI + ossimEndian endian; + MPI_Status status; + if(!theOutputTile) + { + initialize(); + if (!theOutputTile) + { + return theOutputTile; + } + } + + void* buf = theOutputTile->getBuf(); + + ossim_uint32 numberOfTiles = getNumberOfTiles(); + int errorValue = 0; + + if(theCurrentTileNumber >= numberOfTiles) + { + return NULL; + } + errorValue = MPI_Recv(buf, + theOutputTile->getSizeInBytes(), + MPI_UNSIGNED_CHAR, + theCurrentTileNumber%(theNumberOfProcessors-1)+1, + 0, + MPI_COMM_WORLD, + &status); + if((endian.getSystemEndianType()!=OSSIM_BIG_ENDIAN)&& + (theOutputTile->getScalarType()!=OSSIM_UINT8)) + { + endian.swap(theOutputTile->getScalarType(), + buf, + theOutputTile->getSize()); + } + +#if 0 + // Since MPI can run on different platforms + // I am not sure if MPI has built in byte + // swap. If so I will name each datatype + // so it can handle byte swap. Does anyone + // know if MPI does byte swapping. + switch(theOutputTile->getScalarType()) + { + case OSSIM_UINT8: + { + // we add 1 to the rank so we don't wait on a message + // to ourself (rank = 0). + errorValue = MPI_Recv(buf, + theOutputTile->getSize(), + MPI_UNSIGNED_CHAR, + theCurrentTileNumber%(theNumberOfProcessors-1)+1, + 0, + MPI_COMM_WORLD, + &status); + break; + } + case OSSIM_SINT8: + { + // we add 1 to the rank so we don't wait on a message + // to ourself (rank = 0). + errorValue = MPI_Recv(buf, + theOutputTile->getSize(), + MPI_CHAR, + theCurrentTileNumber%(theNumberOfProcessors-1)+1, + 0, + MPI_COMM_WORLD, + &status); + break; + } + case OSSIM_UINT16: + case OSSIM_USHORT11: + { + errorValue = MPI_Recv(buf, + theOutputTile->getSize(), + MPI_UNSIGNED_SHORT, + theCurrentTileNumber%(theNumberOfProcessors-1)+1, + 0, + MPI_COMM_WORLD, + &status); + break; + } + case OSSIM_SINT16: + { + errorValue = MPI_Recv(buf, + theOutputTile->getSize(), + MPI_SHORT, + theCurrentTileNumber%(theNumberOfProcessors-1)+1, + 0, + MPI_COMM_WORLD, + &status); + break; + } + case OSSIM_SINT32: + { + errorValue = MPI_Recv(buf, + theOutputTile->getSize(), + MPI_LONG, + theCurrentTileNumber%(theNumberOfProcessors-1)+1, + 0, + MPI_COMM_WORLD, + &status); + break; + } + case OSSIM_UINT32: + { + errorValue = MPI_Recv(buf, + theOutputTile->getSize(), + MPI_UNSIGNED_LONG, + theCurrentTileNumber%(theNumberOfProcessors-1)+1, + 0, + MPI_COMM_WORLD, + &status); + break; + } + case OSSIM_FLOAT32: + case OSSIM_NORMALIZED_FLOAT: + { + errorValue = MPI_Recv(buf, + theOutputTile->getSize(), + MPI_FLOAT, + theCurrentTileNumber%(theNumberOfProcessors-1)+1, + 0, + MPI_COMM_WORLD, + &status); + break; + } + case OSSIM_FLOAT64: + case OSSIM_NORMALIZED_DOUBLE: + { + errorValue = MPI_Recv(buf, + theOutputTile->getSize(), + MPI_DOUBLE, + theCurrentTileNumber%(theNumberOfProcessors-1)+1, + 0, + MPI_COMM_WORLD, + &status); + break; + } + default: + { + break; + } + } +#endif + ossimIpt origin; + getTileOrigin(theCurrentTileNumber, + origin); + theOutputTile->setOrigin(origin); + theOutputTile->validate(); + ++theCurrentTileNumber; + return theOutputTile; +#else + return ossimImageSourceSequencer::getNextTile(resLevel); +#endif + +} diff --git a/Utilities/OSSIM/ossim_core/parallel/ossimImageMpiMWriterSequenceConnection.h b/Utilities/OSSIM/ossim_core/parallel/ossimImageMpiMWriterSequenceConnection.h new file mode 100644 index 0000000000..e0b9e3e3cb --- /dev/null +++ b/Utilities/OSSIM/ossim_core/parallel/ossimImageMpiMWriterSequenceConnection.h @@ -0,0 +1,60 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +// This class is specific to the Master connection and is optimized +// for the writer sequence and batch processing chain. For the Slave +// implementation look for the ossimImageMpiSWriterSequenceConnection.cc and .h +// files. The Master connection is currently implemented to allways do +// a recieve and does no processing itself. The slave connection does +// all the actual work and processing. +// +//******************************************************************* +// $Id: ossimImageMpiMWriterSequenceConnection.h,v 1.6 2005/02/11 15:07:35 dburken Exp $ +#ifndef ossimImageMpiMWriterSequenceConnection_HEADER +#define ossimImageMpiMWriterSequenceConnection_HEADER +#include <imaging/ossimImageSourceSequencer.h> +class ossimImageData; +class ossimImageMpiMWriterSequenceConnection : public ossimImageSourceSequencer +{ +public: + ossimImageMpiMWriterSequenceConnection(ossimObject* owner=NULL); + ossimImageMpiMWriterSequenceConnection(ossimImageSource* inputSource, + ossimObject* owner=NULL); + virtual ~ossimImageMpiMWriterSequenceConnection(); + + /*! + * This is a virtual method that can be overriden + * by derived classes (MPI, or PVM or other + * parallel connections. This method is to indicate + * whether or not this connection is the master/ + * controlling connection. + */ + virtual void initialize(); + virtual void setToStartOfSequence(); + + virtual bool isMaster()const + { + return true; + } + /*! + * Will allow you to get the next tile in the sequence. + */ + virtual ossimRefPtr<ossimImageData> getNextTile(ossim_uint32 resLevel=0); +protected: + int theNumberOfProcessors; + int theRank; + bool theNeedToSendRequest; + ossimRefPtr<ossimImageData> theOutputTile; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/parallel/ossimImageMpiSWriterSequenceConnection.cpp b/Utilities/OSSIM/ossim_core/parallel/ossimImageMpiSWriterSequenceConnection.cpp new file mode 100644 index 0000000000..5ddf3dacb6 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/parallel/ossimImageMpiSWriterSequenceConnection.cpp @@ -0,0 +1,355 @@ +//---------------------------------------------------------------------------- +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// $Id: ossimImageMpiSWriterSequenceConnection.cpp,v 1.26 2005/11/07 22:03:24 dburken Exp $ +//---------------------------------------------------------------------------- + +#include <ossimConfig.h> /* To pick up OSSIM_HAS_MPI. */ + +#ifdef OSSIM_HAS_MPI +# if OSSIM_HAS_MPI +# include <mpi.h> +# endif +#endif + +#include <parallel/ossimImageMpiSWriterSequenceConnection.h> +#include <parallel/ossimMpi.h> +#include <imaging/ossimImageData.h> +#include <imaging/factory/ossimImageDataFactory.h> +#include <base/common/ossimTrace.h> +#include <base/misc/ossimEndian.h> +#include <base/context/ossimNotifyContext.h> + +static ossimTrace traceDebug = ossimTrace("ossimImageMpiSWriterSequenceConnection:debug"); + +RTTI_DEF1(ossimImageMpiSWriterSequenceConnection, "ossimImageMpiSWriterSequenceConnection", ossimImageSourceSequencer) + +ossimImageMpiSWriterSequenceConnection::ossimImageMpiSWriterSequenceConnection(ossimObject* owner, + long numberOfTilesToBuffer) + :ossimImageSourceSequencer(NULL, + owner), + theNumberOfTilesToBuffer(numberOfTilesToBuffer), + theOutputTile(NULL) +{ + theRank = 0; + theNumberOfProcessors = 1; + theNumberOfTilesToBuffer = ((theNumberOfTilesToBuffer>0)?theNumberOfTilesToBuffer:2); + +#ifdef OSSIM_HAS_MPI +# if OSSIM_HAS_MPI + MPI_Comm_rank(MPI_COMM_WORLD, &theRank); + MPI_Comm_size(MPI_COMM_WORLD, &theNumberOfProcessors); +# endif +#endif + + if(theRank!=0) + { + theCurrentTileNumber = theRank -1; + } + else + { + theCurrentTileNumber = 0; + } +} + +ossimImageMpiSWriterSequenceConnection::ossimImageMpiSWriterSequenceConnection(ossimImageSource* inputSource, + ossimObject* owner, + long numberOfTilesToBuffer) + :ossimImageSourceSequencer(inputSource, + owner), + theNumberOfTilesToBuffer(numberOfTilesToBuffer), + theOutputTile(NULL) +{ + theRank = 0; + theNumberOfProcessors = 1; + theNumberOfTilesToBuffer = ((theNumberOfTilesToBuffer>0)?theNumberOfTilesToBuffer:2); +#if OSSIM_HAS_MPI + MPI_Comm_rank(MPI_COMM_WORLD, &theRank); + MPI_Comm_size(MPI_COMM_WORLD, &theNumberOfProcessors); +#endif + if(theRank!=0) + { + theCurrentTileNumber = theRank -1; + } + else + { + theCurrentTileNumber = 0; + } +} + +ossimImageMpiSWriterSequenceConnection::~ossimImageMpiSWriterSequenceConnection() +{ + deleteOutputTiles(); +} + +void ossimImageMpiSWriterSequenceConnection::deleteOutputTiles() +{ + if(theOutputTile) + { + delete [] theOutputTile; + theOutputTile = NULL; + } +} + +void ossimImageMpiSWriterSequenceConnection::initialize() +{ + ossimImageSourceSequencer::initialize(); + + theCurrentTileNumber = theRank-1; + if(theOutputTile) + { + deleteOutputTiles(); + } + + if(theInputConnection) + { + theOutputTile = new ossimRefPtr<ossimImageData>[theNumberOfTilesToBuffer]; + + for(long index = 0; index < theNumberOfTilesToBuffer; ++index) + { + theOutputTile[index] = ossimImageDataFactory::instance()->create(this, + this); + theOutputTile[index]->initialize(); + } + } +} + +void ossimImageMpiSWriterSequenceConnection::setToStartOfSequence() +{ + ossimImageSourceSequencer::setToStartOfSequence(); + if(theRank != 0) + { + // we will subtract one since the masters job is just + // writting and not issue getTiles. + theCurrentTileNumber = theRank-1; + + } + else + { + // the master will start at 0 + theCurrentTileNumber = 0; + } +} + +void ossimImageMpiSWriterSequenceConnection::slaveProcessTiles() +{ +#ifdef OSSIM_HAS_MPI +# if OSSIM_HAS_MPI + ossimEndian endian; + ossim_uint32 numberOfTiles = getNumberOfTiles(); + long currentSendRequest = 0; + long numberOfTilesSent = 0; + int errorValue= 0; + MPI_Status status; + MPI_Status *statusArray = new MPI_Status[theNumberOfTilesToBuffer]; + MPI_Request *requests = new MPI_Request[theNumberOfTilesToBuffer]; + + memset(statusArray, '\0', sizeof(MPI_Status)*theNumberOfTilesToBuffer); + memset(requests, '\0', sizeof(MPI_Request)*theNumberOfTilesToBuffer); + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimImageMpiSWriterSequenceConnection::slaveProcessTiles(): entering slave and will look at " << numberOfTiles << " tiles" << std::endl; + } + while(theCurrentTileNumber < numberOfTiles) + { + ossimRefPtr<ossimImageData> data = ossimImageSourceSequencer::getTile(theCurrentTileNumber); + + // if the current send requests have looped around + // make sure we wait to see if it was sent + // + errorValue = MPI_Wait(&requests[currentSendRequest], + &status); + requests[currentSendRequest] = 0; + if(data.valid() && + (data->getDataObjectStatus()!=OSSIM_NULL)&& + (data->getDataObjectStatus()!=OSSIM_EMPTY)) + { + theOutputTile[currentSendRequest]->setImageRectangle(data->getImageRectangle()); + theOutputTile[currentSendRequest]->initialize(); + + theOutputTile[currentSendRequest]->loadTile(data.get()); + theOutputTile[currentSendRequest]->setDataObjectStatus(data->getDataObjectStatus()); + + if(traceDebug()) + { + if(data->getDataObjectStatus() == OSSIM_EMPTY) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimImageMpiSWriterSequenceConnection::slaveProcessTiles(): In salve = " + << theRank << " tile is empty" << std::endl; + } + } + } + else + { + if(traceDebug()) + { + if(!data) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimImageMpiSWriterSequenceConnection::slaveProcessTiles(): In slave = " + << theRank << " ptr is null " << std::endl; + } + else + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimImageMpiSWriterSequenceConnection::slaveProcessTiles(): In slave = " << theRank << " tile is empty" << std::endl; + } + } + theOutputTile[currentSendRequest]->makeBlank(); + } + + void* buf = theOutputTile[currentSendRequest]->getBuf(); + if((endian.getSystemEndianType()!=OSSIM_BIG_ENDIAN)&& + (theOutputTile[currentSendRequest]->getScalarType()!=OSSIM_UINT8)) + { + endian.swap(theOutputTile[currentSendRequest]->getScalarType(), + buf, + theOutputTile[currentSendRequest]->getSize()); + } + errorValue = MPI_Isend(buf, + theOutputTile[currentSendRequest]->getSizeInBytes(), + MPI_UNSIGNED_CHAR, + 0, + 0, + MPI_COMM_WORLD, + &requests[currentSendRequest]); +#if 0 + switch(theOutputTile[currentSendRequest]->getScalarType()) + { + case OSSIM_UINT8: + { + errorValue = MPI_Isend(buf, + theOutputTile[currentSendRequest]->getSize(), + MPI_UNSIGNED_CHAR, + 0, + 0, + MPI_COMM_WORLD, + &requests[currentSendRequest]); + break; + } + case OSSIM_SINT8: + { + errorValue = MPI_Isend(buf, + theOutputTile[currentSendRequest]->getSize(), + MPI_CHAR, + 0, + 0, + MPI_COMM_WORLD, + &requests[currentSendRequest]); + break; + } + case OSSIM_UINT16: + { + errorValue = MPI_Isend(buf, + theOutputTile[currentSendRequest]->getSize(), + MPI_UNSIGNED_SHORT, + 0, + 0, + MPI_COMM_WORLD, + &requests[currentSendRequest]); + break; + } + case OSSIM_SINT16: + { + errorValue = MPI_Isend(buf, + theOutputTile[currentSendRequest]->getSize(), + MPI_SHORT, + 0, + 0, + MPI_COMM_WORLD, + &requests[currentSendRequest]); + break; + } + case OSSIM_UINT32: + { + errorValue = MPI_Isend(buf, + theOutputTile[currentSendRequest]->getSize(), + MPI_UNSIGNED_LONG, + 0, + 0, + MPI_COMM_WORLD, + &requests[currentSendRequest]); + break; + } + case OSSIM_SINT32: + { + errorValue = MPI_Isend(buf, + theOutputTile[currentSendRequest]->getSize(), + MPI_LONG, + 0, + 0, + MPI_COMM_WORLD, + &requests[currentSendRequest]); + break; + } + case OSSIM_FLOAT32: + case OSSIM_NORMALIZED_FLOAT: + { + errorValue = MPI_Isend(buf, + theOutputTile[currentSendRequest]->getSize(), + MPI_FLOAT, + 0, + 0, + MPI_COMM_WORLD, + &requests[currentSendRequest]); + break; + } + case OSSIM_FLOAT64: + case OSSIM_NORMALIZED_DOUBLE: + { + errorValue = MPI_Isend(buf, + theOutputTile[currentSendRequest]->getSize(), + MPI_DOUBLE, + 0, + 0, + MPI_COMM_WORLD, + &requests[currentSendRequest]); + break; + } + default: + break; + } +#endif + theCurrentTileNumber += (theNumberOfProcessors-1); + numberOfTilesSent++; + currentSendRequest++; + currentSendRequest %= theNumberOfTilesToBuffer; + } + ossim_int32 tempCount = 0; + // must wait in the correct order + // + while(tempCount < theNumberOfTilesToBuffer) + { + currentSendRequest++; + currentSendRequest %= theNumberOfTilesToBuffer; + + errorValue = MPI_Wait(&requests[currentSendRequest], + &status); + ++tempCount; + } + +// MPI_Waitall(theNumberOfTilesToBuffer, +// requests, +// statusArray); + + delete [] statusArray; + delete [] requests; +# endif +#endif +} + + +ossimRefPtr<ossimImageData> ossimImageMpiSWriterSequenceConnection::getNextTile(ossim_uint32 resLevel) +{ + ossimNotify(ossimNotifyLevel_FATAL) + << "FATAL ossimImageMpiSWriterSequenceConnection::getNextTile(): " + << "should not be called" << std::endl; + return ossimRefPtr<ossimImageData>(); +} + diff --git a/Utilities/OSSIM/ossim_core/parallel/ossimImageMpiSWriterSequenceConnection.h b/Utilities/OSSIM/ossim_core/parallel/ossimImageMpiSWriterSequenceConnection.h new file mode 100644 index 0000000000..cc138cce53 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/parallel/ossimImageMpiSWriterSequenceConnection.h @@ -0,0 +1,53 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimImageMpiSWriterSequenceConnection.h,v 1.9 2005/02/11 15:07:35 dburken Exp $ +#ifndef ossimImageMpiSWriterSequenceConnection_HEADER +#define ossimImageMpiSWriterSequenceConnection_HEADER +#include <imaging/ossimImageSourceSequencer.h> +class ossimImageData; +class ossimImageMpiSWriterSequenceConnection : public ossimImageSourceSequencer +{ +public: + ossimImageMpiSWriterSequenceConnection(ossimObject* owner=NULL, + long numberOfTilesToBuffer = 2); + + ossimImageMpiSWriterSequenceConnection(ossimImageSource* inputSource, + ossimObject* owner=NULL, + long numberOfTilesToBuffer = 2); + + virtual ~ossimImageMpiSWriterSequenceConnection(); + virtual bool isMaster()const + { + return false; + } + + virtual void initialize(); + virtual void setToStartOfSequence(); + /*! + * Will allow you to get the next tile in the sequence. + */ + virtual ossimRefPtr<ossimImageData> getNextTile(ossim_uint32 resLevel=0); + + virtual void slaveProcessTiles(); + +protected: + int theNumberOfProcessors; + int theRank; + int theNumberOfTilesToBuffer; + + ossimRefPtr<ossimImageData>* theOutputTile; + + void deleteOutputTiles(); + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/parallel/ossimMpi.cpp b/Utilities/OSSIM/ossim_core/parallel/ossimMpi.cpp new file mode 100644 index 0000000000..683cd203a0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/parallel/ossimMpi.cpp @@ -0,0 +1,175 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimMpi.cpp,v 1.20 2005/11/07 22:03:24 dburken Exp $ + +#include <parallel/ossimMpi.h> +#include <base/common/ossimTrace.h> +#include <base/context/ossimNotifyContext.h> +#include <time.h> + +#ifdef OSSIM_ID_ENABLED +static const char OSSIM_ID[] = "$Id: ossimMpi.cpp,v 1.20 2005/11/07 22:03:24 dburken Exp $"; +#endif + +static ossimTrace traceDebug = ossimTrace("ossimMpi:debug"); + +ossimMpi* ossimMpi::theInstance=0; + +ossimMpi* ossimMpi::instance() +{ + if(!theInstance) + { + theInstance = new ossimMpi; + theInstance->setEnabledFlag(true); + } + + return theInstance; +} + +bool ossimMpi::isEnabled()const +{ + return theEnabledFlag; +} + +ossim_float64 ossimMpi::getTime()const +{ +#ifdef OSSIM_HAS_MPI +# if OSSIM_HAS_MPI + if(theEnabledFlag) + { + return MPI_Wtime(); + } + else + { + return time(0); + } +# else + return time(0); +# endif +#else + return time(0); +#endif +} + +void ossimMpi::initialize(int* argc, char*** argv) +{ + if(theEnabledFlag) + { +#ifdef OSSIM_HAS_MPI +# if OSSIM_HAS_MPI + int success=0; + success = MPI_Init(argc, argv); + if(traceDebug()) + { +# ifdef OSSIM_ID_ENABLED + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimMpi::initialize: OSSIM_ID = " + << OSSIM_ID << std::endl; +# endif + if(success == MPI_SUCCESS) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimMpi::initialize\n" + << "MPI is initialized and running with " + << getNumberOfProcessors() + << " processors..." + << std::endl; + } + else + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimMpi::initialize: MPI is not initialized." + << std::endl; + } + } +# else + if(traceDebug()) + { +# ifdef OSSIM_ID_ENABLED + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimMpi::initialize: OSSIM_ID = " + << OSSIM_ID << std::endl; +# endif + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimMpi::initialize: Not compiled with mpi!" + << std::endl; + } +# endif +#else + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimMpi::initialize: Not compiled with mpi!" + << std::endl; +#endif + } +} +void ossimMpi::setEnabledFlag(bool flag) +{ + theEnabledFlag = flag; +} + +void ossimMpi::finalize() +{ +#ifdef OSSIM_HAS_MPI +# if OSSIM_HAS_MPI + if(theEnabledFlag) + { + int success; + success = MPI_Finalize(); + if(traceDebug()) + { + if(success == MPI_SUCCESS) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimMpi::finalize(): mpi is finalized" << std::endl; + } + else + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimMpi::finalize(): " + << "mpi is not finalized successfully" << std::endl; + } + } + } +# endif +#endif +} + +int ossimMpi::getRank()const +{ + int result = 0; + +#ifdef OSSIM_HAS_MPI +# if OSSIM_HAS_MPI + if(theEnabledFlag) + { + MPI_Comm_rank(MPI_COMM_WORLD, &result); + } +# endif +#endif + + return result; +} + +int ossimMpi::getNumberOfProcessors()const +{ + int result = 1; + +#ifdef OSSIM_HAS_MPI +# if OSSIM_HAS_MPI + if(theEnabledFlag) + { + MPI_Comm_size(MPI_COMM_WORLD, &result); + } +# endif +#endif + + return result; +} diff --git a/Utilities/OSSIM/ossim_core/parallel/ossimMpi.h b/Utilities/OSSIM/ossim_core/parallel/ossimMpi.h new file mode 100644 index 0000000000..71dd0e9246 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/parallel/ossimMpi.h @@ -0,0 +1,59 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimMpi.h,v 1.10 2005/11/07 22:03:24 dburken Exp $ +#ifndef ossimMpi_HEADER +#define ossimMpi_HEADER + +#include <ossimConfig.h> +#include <base/common/ossimConstants.h> + +#ifdef OSSIM_HAS_MPI +# if OSSIM_HAS_MPI +# include <mpi.h> +# endif +#endif + +class OSSIM_DLL ossimMpi +{ +public: + static ossimMpi* instance(); + + ossim_float64 getTime()const; + /*! + * Typically called only one time + */ + void initialize(int* argc, char*** argv); + + /*! + * Called only once when we would like to + * shutdown mpi + */ + void finalize(); + int getRank()const; + int getNumberOfProcessors()const; + void setEnabledFlag(bool flag); + bool isEnabled()const; +protected: + ossimMpi(){} // hide + ossimMpi(const ossimMpi&){} // hide + void operator =(const ossimMpi&){} // hide + + /*! + * We will have only a single instance of + * this class. + */ + static ossimMpi* theInstance; + bool theEnabledFlag; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/parallel/ossimOrthoIgen.cpp b/Utilities/OSSIM/ossim_core/parallel/ossimOrthoIgen.cpp new file mode 100644 index 0000000000..995a0d2aa9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/parallel/ossimOrthoIgen.cpp @@ -0,0 +1,1051 @@ +#include <sstream> +#include <parallel/ossimOrthoIgen.h> +#include <parallel/ossimIgen.h> +#include <base/context/ossimNotifyContext.h> +#include <base/common/ossimTrace.h> +#include <base/data_types/ossimKeywordlist.h> +#include <imaging/annotation/ossimGeoAnnotationSource.h> +#include <imaging/ossimImageChain.h> +#include <imaging/formats/ossimImageHandler.h> +#include <imaging/tile_sources/ossimImageRenderer.h> +#include <imaging/tile_sources/ossimHistogramRemapper.h> +#include <imaging/tile_sources/ossimImageCombiner.h> +#include <imaging/resample/ossimFilterResampler.h> +#include <imaging/factory/ossimImageHandlerRegistry.h> +#include <imaging/factory/ossimImageWriterFactoryRegistry.h> +#include <base/common/ossimKeywordNames.h> +#include <imaging/formats/tiff/ossimTiffWriter.h> +#include <projections/map_projections/ossimUtmProjection.h> +#include <projections/map_projections/ossimEquDistCylProjection.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <base/factory/ossimObjectFactoryRegistry.h> +#include <imaging/tile_sources/ossimGeoPolyCutter.h> +#include <imaging/tile_sources/ossimEastingNorthingCutter.h> +#include <base/misc/ossimUnitConversionTool.h> +#include "ossimMpi.h" + +static ossimTrace traceDebug("ossimOrthoIgen:debug"); +static ossimTrace traceLog("ossimOrthoIgen:log"); + +ossimOrthoIgen::ossimOrthoIgenFilename::ossimOrthoIgenFilename(const ossimFilename& file, bool decodeEntry) +{ + if(decodeEntry) + { + setFilenameWithDecoding(file); + } + else + { + setFilenameAndEntry(file, -1); + } +} + +void ossimOrthoIgen::ossimOrthoIgenFilename::setFilenameWithDecoding(const ossimFilename& file) +{ + ossimFilename::size_type idx = file.rfind("|", file.length()); + ossimString actualFile = file; + ossimString entry("-1"); + if(idx != ossimFilename::npos) + { + actualFile = ossimString(file.begin(), file.begin()+idx); + entry = ossimString(file.begin()+idx+1, + file.end()); + entry = entry.trim(); + actualFile = actualFile.trim(); + } + + theFilename = ossimFilename(actualFile); + theEntry = entry.toInt32(); +} + +ossimOrthoIgen::ossimOrthoIgen() + : + theThumbnailRes(""), + theThumbnailFlag(false), + theMetersPerPixelOverride(OSSIM_DBL_NAN, OSSIM_DBL_NAN), + theProjectionType(OSSIM_UNKNOWN_PROJECTION), + theProjectionName(""), + theGeographicOriginOfLatitude(0.0), + theCombinerType("ossimImageMosaic"), + theResamplerType("nearest neighbor"), + theTemplateView(""), + theTilingTemplate(""), + theTilingFilename(""), + theChainTemplate(""), + theCombinerTemplate(""), + theAnnotationTemplate(""), + theWriterTemplate(""), + theSlaveBuffers("2"), + theCutCenter(OSSIM_DBL_NAN, OSSIM_DBL_NAN), + theCutDxDy(OSSIM_DBL_NAN, OSSIM_DBL_NAN), + theCutCenterUnit(OSSIM_UNIT_UNKNOWN), + theCutDxDyUnit(OSSIM_UNIT_UNKNOWN), + theLowPercentClip(OSSIM_DBL_NAN), + theHighPercentClip(OSSIM_DBL_NAN), + theFilenames() +{ + // setDefaultValues(); +} + +void ossimOrthoIgen::addArguments(ossimArgumentParser& argumentParser) +{ + argumentParser.getApplicationUsage()->addCommandLineOption("--annotate", "annotation keyword list"); + + argumentParser.getApplicationUsage()->addCommandLineOption("-t or --thumbnail", "thumbnail resolution"); + + argumentParser.getApplicationUsage()->addCommandLineOption("--meters","Specifies an override for the meters per pixel"); + argumentParser.getApplicationUsage()->addCommandLineOption("--slave-buffers","number of slave tile buffers for mpi processing (default = 2)"); + argumentParser.getApplicationUsage()->addCommandLineOption("--view-template","Specify an external file that contains view information"); + argumentParser.getApplicationUsage()->addCommandLineOption("--chain-template","Specify an external file that contains chain information"); + argumentParser.getApplicationUsage()->addCommandLineOption("--combiner-template","Specify an external file that contains combiner information"); + argumentParser.getApplicationUsage()->addCommandLineOption("--tiling-template","Specify an external file that contains tiling information"); + argumentParser.getApplicationUsage()->addCommandLineOption("--writer-template","Specify an external file that contains tiling information"); + + argumentParser.getApplicationUsage()->addCommandLineOption("--utm","Defaults to a utm image chain with GSD = to the input"); + + argumentParser.getApplicationUsage()->addCommandLineOption("--geo","Defaults to a geographic image chain with GSD = to the input. Origin of latitude is on the equator."); + argumentParser.getApplicationUsage()->addCommandLineOption("--input-proj","Makes the view equal to the input. If more than one file then the first is taken"); + + argumentParser.getApplicationUsage()->addCommandLineOption("--geo-scaled","Takes a latitude as an argument for purpose of scaling. Specifies that no spec file was defined. Defaults to a scaled geographic image chain with GSD = to the input."); + + argumentParser.getApplicationUsage()->addCommandLineOption("--combiner-type","Specify what mosaic to use, ossimImageMosiac or ossimFeatherMosaic or osimBlendMosaic ... etc"); + + argumentParser.getApplicationUsage()->addCommandLineOption("--resample-type","Specify what resampler to use, nearest neighbor, bilinear, bicubic"); + + argumentParser.getApplicationUsage()->addCommandLineOption("--cut-center-ll","Specify the center cut in lat lon space. Takes two argument <lat> <lon>"); + argumentParser.getApplicationUsage()->addCommandLineOption("--cut-radius-meters","Specify the cut distance in meters. A bounding box for the cut will be produced"); + + argumentParser.getApplicationUsage()->addCommandLineOption("--hist-stretch","Specify in normalized percent the low clip and then the high clip value"); +} + +void ossimOrthoIgen::initialize(ossimArgumentParser& argumentParser) +{ + double tempDouble; + double tempDouble2; + ossimString tempString; + ossimArgumentParser::ossimParameter stringParam(tempString); + ossimArgumentParser::ossimParameter doubleParam(tempDouble); + ossimArgumentParser::ossimParameter doubleParam2(tempDouble2); + theCutCenter.makeNan(); + theCutDxDy.makeNan(); + theCutCenterUnit = OSSIM_UNIT_UNKNOWN; + theCutDxDyUnit = OSSIM_UNIT_UNKNOWN; + theLowPercentClip = OSSIM_DBL_NAN; + theHighPercentClip = OSSIM_DBL_NAN; + + theMetersPerPixelOverride.makeNan(); + if(argumentParser.read("--annotate", stringParam)) + { + theAnnotationTemplate = ossimFilename(tempString); + } + if(argumentParser.read("-t", stringParam) || + argumentParser.read("--thumbnail", stringParam)) + { + theThumbnailRes = tempString; + theThumbnailFlag = true; + } + if(argumentParser.read("--slave-buffers", stringParam)) + { + theSlaveBuffers = tempString; + } + if(argumentParser.read("--cut-center-ll", doubleParam, doubleParam2)) + { + theCutCenter.lat = tempDouble; + theCutCenter.lon = tempDouble2; + theCutCenterUnit = OSSIM_DEGREES; + } + if(argumentParser.read("--cut-radius-meters", doubleParam)) + { + theCutDxDy.x = tempDouble; + theCutDxDy.y = tempDouble; + theCutDxDyUnit = OSSIM_METERS; + } + if(argumentParser.read("--hist-stretch", doubleParam, doubleParam2)) + { + theLowPercentClip = tempDouble; + theHighPercentClip = tempDouble2; + } + if(argumentParser.read("--meters", doubleParam)) + { + theMetersPerPixelOverride.x = tempDouble; + theMetersPerPixelOverride.y = tempDouble; + } + if(argumentParser.read("--writer-template", + stringParam)) + { + theWriterTemplate = tempString; + } + if(argumentParser.read("--tiling-template", + stringParam)) + { + theTilingTemplate = ossimFilename(tempString); + } + if(argumentParser.read("--chain-template", stringParam)) + { + theChainTemplate = ossimFilename(tempString); + } + if(argumentParser.read("--combiner-template", stringParam)) + { + theCombinerTemplate = ossimFilename(tempString); + } + if (argumentParser.read("--utm")) + { + theProjectionType = OSSIM_UTM_PROJECTION; + theProjectionName = "ossimUtmProjection"; + } + else if(argumentParser.read("--geo")) + { + theProjectionType = OSSIM_GEO_PROJECTION; + theProjectionName = "ossimEquDistCylProjection"; + } + else if(argumentParser.read("--input-proj")) + { + theProjectionType = OSSIM_INPUT_PROJECTION; + } + else + { + theProjectionType = OSSIM_UNKNOWN_PROJECTION; + } + if(argumentParser.read("--view-template", stringParam)) + { + theTemplateView = ossimFilename(tempString); + theProjectionType = OSSIM_EXTERNAL_PROJECTION; + } + if(argumentParser.read("--geo-scaled", doubleParam)) + { + theProjectionType = OSSIM_GEO_PROJECTION; + theProjectionName = "ossimEquDistCylProjection"; + if ( (tempDouble < 90.0) && (tempDouble > -90.0) ) + { + theGeographicOriginOfLatitude = tempDouble; + } + else + { + theGeographicOriginOfLatitude = 0.0; + ossimNotify(ossimNotifyLevel_WARN) + << "ossimOrthoIgen::initialize WARNING:" + << "\nLatitude out of range! Must be between -90 and 90." + << "\nRemains at zero." + << std::endl; + } + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimOrthoIgen::initialize DEBUG:" + << "\ngeographicOriginOfLatitude: " << theGeographicOriginOfLatitude + << std::endl; + } + } + if(argumentParser.read("--combiner-type", stringParam)) + { + theCombinerType = tempString; + } + else + { + theCombinerType = "ossimImageMosaic"; + } + if(argumentParser.read("--resample-type", stringParam)) + { + theResamplerType = tempString; + } + + +} + +void ossimOrthoIgen::addFiles(ossimArgumentParser& argumentParser, + bool withDecoding, + ossim_uint32 startIdx) +{ + ossim_uint32 idx = startIdx; + while(argumentParser.argv()[idx]) + { + addFile(ossimFilename(argumentParser.argv()[idx]), withDecoding); +// theFilenames.push_back(ossimFilename(argumentParser.argv()[idx])); + ++idx; + } +} + +bool ossimOrthoIgen::execute() +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimOrthoIgen::execute DEBUG: Entered ..." + << std::endl; + } +// double start=0, stop=0; + + if(theFilenames.size() < 1) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimOrthoIgen::execute WARNING: No filenames to process" + << std::endl; + return false; + } + +// if(ossimMpi::instance()->getRank() == 0) +// { +// start = ossimMpi::instance()->getTime(); +// } + ossimKeywordlist igenKwl; + ossimKeywordlist inputGeom; + if(ossimMpi::instance()->getRank() == 0) + { + if(!setupIgenKwl(igenKwl)) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimOrthoIgen::execute DEBUG: setupIgenKwl returned false..." + << std::endl; + } + return false; + } + + if (traceLog()) + { + const char* lookup = igenKwl.find("object2.filename"); + if (lookup) + { + ossimFilename logFile = lookup; + logFile.setExtension("log"); + igenKwl.write(logFile.c_str()); + } + } + } + + ossimIgen *igen = new ossimIgen; + igen->initialize(igenKwl); + igen->outputProduct(); + +// if(ossimMpi::instance()->getRank() == 0) +// { +// stop = ossimMpi::instance()->getTime(); +// ossimNotify(ossimNotifyLevel_NOTICE) +// << "Time elapsed: " << (stop-start) +// << std::endl; +// } + delete igen; + igen = NULL; + + return true; +} + +void ossimOrthoIgen::clearFilenameList() +{ + theFilenames.clear(); +} + +void ossimOrthoIgen::addFile(const ossimFilename& file, + bool withEncodedEntry) +{ + ossimOrthoIgenFilename filename; + if(withEncodedEntry) + { + filename.setFilenameWithDecoding(file); + } + else + { + filename.setFilenameAndEntry(file, -1); + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimOrthoIgen::addFile DEBUG:" + << "\nAdded file: " << filename.theFilename + << std::endl; + } + + theFilenames.push_back(filename); +} + +void ossimOrthoIgen::setDefaultValues() +{ + theThumbnailRes = ""; + theThumbnailFlag = false; + theMetersPerPixelOverride.makeNan(); + theTemplateView = ""; + theProjectionType = OSSIM_UNKNOWN_PROJECTION; + theGeographicOriginOfLatitude = 0.0; + theCombinerType = "ossimImageMosaic"; + theResamplerType = "nearest neighbor"; + theTilingTemplate = ""; + theTilingFilename = ""; + theSlaveBuffers = "2"; + clearFilenameList(); + theLowPercentClip = OSSIM_DBL_NAN; + theHighPercentClip = OSSIM_DBL_NAN; + theCutCenter.makeNan(); + theCutDxDy.makeNan(); + theCutCenterUnit = OSSIM_UNIT_UNKNOWN; + theCutDxDyUnit = OSSIM_UNIT_UNKNOWN; +} + +void ossimOrthoIgen::setCombinerType(const ossimString& combinerType) +{ + theCombinerType = combinerType; +} + +void ossimOrthoIgen::setProjectionName(const ossimString& projName) +{ + // for now we will only support utm or geographic for this. + theProjectionName = projName; + + if(projName == "ossimUtmProjection") + { + theProjectionType = OSSIM_UTM_PROJECTION; + } + else if(projName == "ossimEquDistCylProjection") + { + theProjectionType = OSSIM_GEO_PROJECTION; + } +} + +void ossimOrthoIgen::setResamplerType(const ossimString& resamplerType) +{ + theResamplerType = resamplerType; +} + +void ossimOrthoIgen::setCutCenter(const ossimDpt& dpt, + ossimUnitType unit) +{ + theCutCenter = dpt; + theCutCenterUnit = unit; +} + +void ossimOrthoIgen::setCutDxDy(const ossimDpt& dpt, + ossimUnitType unit) +{ + theCutDxDy = dpt; + theCutDxDyUnit = unit; +} + +bool ossimOrthoIgen::setupIgenKwl(ossimKeywordlist& kwl) +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimOrthoIgen::setupIgenKwl DEBUG: Entered ..." + << std::endl; + } + setupTiling(kwl); + kwl.add("igen.thumbnail", + theThumbnailFlag, + true); + if((theThumbnailRes != "")&& + theThumbnailFlag) + { + kwl.add("igen.thumbnail_res", + theThumbnailRes.c_str(), + true); + } + if(theSlaveBuffers == "") + { + kwl.add("igen.slave_tile_buffers", + 2, + true); + } + else + { + kwl.add("igen.slave_tile_buffers", + theSlaveBuffers.c_str(), + true); + } + ossim_uint32 inputFileIdx = 0; + if(!setupView(kwl)) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimOrthoIgen::execute DEBUG: setupView returned false..." + << std::endl; + } + return false; + } + + if(theFilenames.size() > 1) + { + ossimKeywordlist tempKwl; + ossimRefPtr<ossimObject> obj; + + + if(theChainTemplate.exists()) + { + tempKwl.addFile(theChainTemplate); + obj = ossimObjectFactoryRegistry::instance()->createObject(tempKwl); + } + ossimRefPtr<ossimImageChain> chain = PTR_CAST(ossimImageChain, obj.get()); + + if(!chain) // then create a default rendering chain + { + ossimImageChain* tempChain = new ossimImageChain; + if(theProjectionType != OSSIM_UNKNOWN_PROJECTION) + { + ossimImageRenderer* tempObject = new ossimImageRenderer; + if(tempObject->getResampler()) + { + tempObject->getResampler()->setFilterType(theResamplerType); + } + if(tempObject) + { + tempChain->addChild(tempObject); + } + } + obj = tempChain; + chain = tempChain; + } + + ossimRefPtr<ossimConnectableObject> mosaicObject; + if(theCombinerTemplate.exists()) + { + tempKwl.clear(); + tempKwl.addFile(theCombinerTemplate); + } + mosaicObject = (ossimConnectableObject*)ossimObjectFactoryRegistry::instance()->createObject(tempKwl); + if(!PTR_CAST(ossimImageCombiner, + mosaicObject.get())) + { + mosaicObject = 0; + } + if(!mosaicObject.valid()) + { + mosaicObject = (ossimConnectableObject*)ossimObjectFactoryRegistry::instance()->createObject(theCombinerType); + } + if(!mosaicObject) + { + mosaicObject = (ossimConnectableObject*)ossimObjectFactoryRegistry::instance()->createObject(ossimString("ossimImageMosaic")); + } + + if(!mosaicObject) + { + ossimNotify(ossimNotifyLevel_WARN) + << "Unable to create a mosaic object" << std::endl; + return false; + } + + ossim_uint32 fileSize = theFilenames.size()-1; + ossim_uint32 idx; + ossim_uint32 chainIdx = 1; + ossimRefPtr<ossimImageChain> rootChain = new ossimImageChain; + chain->saveState(kwl, "object1.object1."); + for(idx = inputFileIdx;idx < fileSize; ++idx) + { + // first lets add an input to the chain + // + ossimFilename input = theFilenames[idx].theFilename; + ossimRefPtr<ossimImageHandler> handler = ossimImageHandlerRegistry::instance()->open(input); + ossimHistogramRemapper* histRemapper = 0; + if(handler.valid()) + { + std::vector<ossim_uint32> entryList; + if(theFilenames[idx].theEntry >-1) + { + entryList.push_back(theFilenames[idx].theEntry); + } + else + { + handler->getEntryList(entryList); + } + + ossim_uint32 entryIdx = 0; + for(entryIdx = 0; entryIdx < entryList.size(); ++entryIdx) + { + ossimImageHandler* h = (ossimImageHandler*)handler->dup(); + h->setCurrentEntry(entryList[entryIdx]); + ossimImageChain* tempChain = (ossimImageChain*)chain->dup(); + tempChain->addLast(h); + + if((theHighPercentClip!=OSSIM_DBL_NAN)&& + (theLowPercentClip!=OSSIM_DBL_NAN)) + { + ossimFilename inputHisto = handler->createHistogramFilename(); + if(inputHisto.exists()) + { + tempChain->addLast(histRemapper); + histRemapper = new ossimHistogramRemapper; + tempChain->insertRight(histRemapper, h); + histRemapper->openHistogram(inputHisto); + histRemapper->setHighNormalizedClipPoint(1.0-theHighPercentClip); + histRemapper->setLowNormalizedClipPoint(theLowPercentClip); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) + <<"Histogram file " << inputHisto + << " not found!" + << std::endl; + } + } + tempChain->makeUniqueIds(); + tempChain->saveState(kwl, (ossimString("object1.object")+ossimString::toString(chainIdx)+".").c_str()); + rootChain->add(tempChain); + ++chainIdx; + mosaicObject->connectMyInputTo(tempChain); + } + } + else if(input == "NULL_FILE") + { + ossimImageChain* tempChain = (ossimImageChain*)chain->dup(); + tempChain->makeUniqueIds(); + tempChain->saveState(kwl, (ossimString("object1.object")+ossimString::toString(chainIdx)+".").c_str()); + rootChain->add(tempChain); + ++chainIdx; + mosaicObject->connectMyInputTo(tempChain); + } + } + mosaicObject->saveState(kwl, (ossimString("object1.object")+ + ossimString::toString(chainIdx)+".").c_str()); + + ++chainIdx; + + ossimRefPtr<ossimConnectableObject> input = mosaicObject; + + // Annotation setup... + ossimRefPtr<ossimConnectableObject> annotator = + setupAnnotation(kwl, input.get()); + if (annotator.valid()) + { + annotator->saveState( + kwl, + (ossimString("object1.object")+ + ossimString::toString(chainIdx)+".").c_str()); + input = annotator; + ++chainIdx; + } + else + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimOrthoIgen::setupIgenKwl DEBUG:\n" + << "setupAnnotation failed..." + << std::endl; + } + // return false; Not sure if we want this to be an error??? + } + + ossimRefPtr<ossimConnectableObject> cutter = setupCutter(kwl, + input.get()); + + if(cutter.valid()) + { + cutter->saveState(kwl, (ossimString("object1.object")+ + ossimString::toString(chainIdx)+".").c_str()); + input = cutter; + } + + rootChain = 0; + kwl.add("object1.type", + "ossimImageChain", + true); + + if(!setupWriter(kwl, input.get())) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimOrthoIgen::execute DEBUG: setupWriter returned false..." + << std::endl; + } + return false; + } + + } + + return true; +} + +ossimRefPtr<ossimConnectableObject> ossimOrthoIgen::setupCutter( + ossimKeywordlist& kwl, ossimConnectableObject* input) +{ + ossimRefPtr<ossimConnectableObject> result; + if(theCutDxDy.hasNans()) + { + return result; + } + ossimRefPtr<ossimProjection> viewProj = ossimProjectionFactoryRegistry::instance()->createProjection(kwl, "product.projection."); + + if(viewProj.valid()) + { + ossimMapProjection* mapProj = PTR_CAST(ossimMapProjection, viewProj.get()); + if(mapProj) + { + ossimGpt centerLatLon(theCutCenter.lat, + theCutCenter.lon, + 0.0, + mapProj->getDatum()); +// if(theCutDxDyUnit == OSSIM_METERS) + { + if(!mapProj->isGeographic()) + { + ossimDpt dxdy(ossimUnitConversionTool(theCutDxDy.x, theCutDxDyUnit).getValue(OSSIM_METERS), + ossimUnitConversionTool(theCutDxDy.y, theCutDxDyUnit).getValue(OSSIM_METERS)); + + ossimEastingNorthingCutter* cutter = new ossimEastingNorthingCutter; + ossimDpt pt, centerEn; + mapProj->worldToLineSample(centerLatLon, + pt); + pt = ossimIpt(pt); + mapProj->lineSampleToEastingNorthing(pt, centerEn); + + ossimDpt ul = centerEn + ossimDpt(-dxdy.x, + dxdy.y); + ossimDpt lr = centerEn + ossimDpt(dxdy.x, + -dxdy.y); + + + cutter->setEastingNorthingRectangle(ul, lr); + + result = cutter; + } + else + { + ossimDpt dxdy(ossimUnitConversionTool(theCutDxDy.x, theCutDxDyUnit).getValue(OSSIM_DEGREES), + ossimUnitConversionTool(theCutDxDy.y, theCutDxDyUnit).getValue(OSSIM_DEGREES)); + ossimGeoPolyCutter* cutter = new ossimGeoPolyCutter; + ossimDpt metersPerDegree = centerLatLon.metersPerDegree(); + ossimDpt degreePerMeter; + std::vector<ossimGpt> polygon; + degreePerMeter.x = ((metersPerDegree.x > FLT_EPSILON)?1.0/metersPerDegree.x:0.0); + degreePerMeter.y = ((metersPerDegree.y > FLT_EPSILON)?1.0/metersPerDegree.y:0.0); + + ossimGpt ul(centerLatLon.latd() + dxdy.y, + centerLatLon.lond() - dxdy.x); + ossimGpt ur(centerLatLon.latd() + dxdy.y, + centerLatLon.lond() + dxdy.x); + ossimGpt lr(centerLatLon.latd() - dxdy.y, + centerLatLon.lond() + dxdy.x); + ossimGpt ll(centerLatLon.latd() - dxdy.y, + centerLatLon.lond() - dxdy.x); + + polygon.push_back(ul); + polygon.push_back(ur); + polygon.push_back(lr); + polygon.push_back(ll); + cutter->setNumberOfPolygons(1); + cutter->setPolygon(polygon); + + result = cutter; + + } + } + } + } + if(result.valid()) + { + result->connectMyInputTo(input); + } + + return result; +} + +bool ossimOrthoIgen::setupWriter(ossimKeywordlist& kwl, ossimConnectableObject* input) +{ + ossimFilename outputFilename = theFilenames[theFilenames.size()-1].theFilename; + ossimImageFileWriter* writer = 0; + if(theTilingFilename!="") + { + if(!outputFilename.isDir()) + { + outputFilename = outputFilename.path(); + } + outputFilename = outputFilename.dirCat(theTilingFilename); + } + + if((theWriterTemplate == "")|| + (!theWriterTemplate.exists())) + { + ossimRefPtr<ossimImageFileWriter> outputObj = 0; + if(theTilingFilename == "%SRTM%") + { + ossimKeywordlist kwlWriter; + + kwlWriter.add("type", + "ossimGeneralRasterWriter", + true); + kwlWriter.add("byte_order", + "big_endian"); + outputObj = ossimImageWriterFactoryRegistry::instance()->createWriter(kwlWriter); + outputFilename = outputFilename.path(); + } + else if(outputFilename.ext() != "") + { + ossimFilename ext = outputFilename.ext(); + outputObj = ossimImageWriterFactoryRegistry::instance()->createWriterFromExtension(ext); + if(!outputObj.valid()) + { + outputObj = new ossimTiffWriter; + writer = (ossimImageFileWriter*)outputObj.get(); + outputFilename.setExtension("tif"); + } + } + else + { + // just do a default just so we can set the keywords for now + // + outputObj = new ossimTiffWriter; + } + if(outputObj.valid()) + { + writer = (ossimImageFileWriter*)outputObj.get(); + writer->setFilename(outputFilename); + + writer->connectMyInputTo(0, input); + writer->saveState(kwl, "object2."); + } + kwl.add("object2.", + ossimKeywordNames::FILENAME_KW, + outputFilename.c_str(), + true); + + if(!kwl.find("object2.type")) + { + kwl.add("object2.", + "type", + "ossimImageFileWriter", + true); + } + } + + return true; +} + +bool ossimOrthoIgen::setupView(ossimKeywordlist& kwl) +{ + ossimKeywordlist tempKwl; + if(theTemplateView != "") + { + tempKwl.addFile(theTemplateView); + } + ossimRefPtr<ossimObject> productObj = ossimObjectFactoryRegistry::instance()->createObject(tempKwl, "product.projection."); + if(!productObj.valid()) + { + productObj = ossimObjectFactoryRegistry::instance()->createObject(tempKwl); + if(!PTR_CAST(ossimProjection, productObj.get())) + { + productObj = 0; + } + else + { + if(!theMetersPerPixelOverride.hasNans()) + { + ossimMapProjection* mapProj = PTR_CAST(ossimMapProjection, productObj.get()); + + if(mapProj&&!theMetersPerPixelOverride.hasNans()) + { + mapProj->setMetersPerPixel(theMetersPerPixelOverride); + } + } + } + } + if(!productObj.valid() && (theTemplateView!="")) + { + ossimNotify(ossimNotifyLevel_WARN) + << "ossimOrthoIgen::setupView WARNING: File template " + << theTemplateView << " did not have a valid view" << std::endl; + } + if(productObj.valid()) + { + productObj->saveState(kwl, "product.projection."); + } + else + { + ossimKeywordlist inputGeom; + // Open up the image. + ossimFilename input = theFilenames[0].theFilename; + ossimRefPtr<ossimImageHandler> handler = + ossimImageHandlerRegistry::instance()->open(input); + if(!handler) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimOrthoIgen::setupView DEBUG:" + << "\nCould not open: " << input.c_str() + << std::endl; + } + + return false; + } + handler->getImageGeometry(inputGeom); + + // Get the input projection. + ossimRefPtr<ossimProjection> inputProj = + ossimProjectionFactoryRegistry::instance()->createProjection( + inputGeom); + if(inputProj.valid()&& + (theProjectionType !=OSSIM_UNKNOWN_PROJECTION)) + { + // Get the input resolution. + ossimDpt metersPerPixel = inputProj->getMetersPerPixel(); + + ossim_float64 gsd = (metersPerPixel.x+metersPerPixel.y)/2.0; + if(!theMetersPerPixelOverride.hasNans()) + { + gsd = theMetersPerPixelOverride.x; + } + + // Get the bounding rect. + ossimIrect rect = handler->getBoundingRect(); + + // Create an output projection. + ossimRefPtr<ossimMapProjection> outputProjection; + if (theProjectionType == OSSIM_GEO_PROJECTION) + { + // Assuming WGS 84 for now. + outputProjection = new ossimEquDistCylProjection(); + ossimGpt gpt(theGeographicOriginOfLatitude, 0.0); + + // Set the origin. + outputProjection->setOrigin(gpt); + // Set the resolution. + outputProjection->setMetersPerPixel(ossimDpt(gsd, gsd)); + + // Save the state to keyword list. + outputProjection->saveState(kwl, "product.projection."); + } + else if((theProjectionType == OSSIM_UTM_PROJECTION)|| + ((theProjectionType == OSSIM_INPUT_PROJECTION) && + !PTR_CAST(ossimMapProjection, inputProj.get()))) + + { + // Default to UTM. + ossimUtmProjection* utm = new ossimUtmProjection; + ossimGpt midGpt; + + + inputProj->lineSampleToWorld(ossimDpt(rect.midPoint()), + midGpt); + + utm->setZone(midGpt); + + ossimDpt eastingNorthing; + + utm->setMetersPerPixel(ossimDpt(gsd, gsd)); + + eastingNorthing = utm->forward(utm->origin()); + + utm->setUlEastingNorthing(eastingNorthing); + outputProjection = utm; + // Set the resolution. + outputProjection->setMetersPerPixel(ossimDpt(gsd, gsd)); + // Save the state to keyword list. + outputProjection->saveState(kwl, "product.projection."); + } + else // input is a map projection so just use that if we are type INPUT + { + inputProj->saveState(kwl, "product.projection."); + } + } + } + return true; +} + +ossimRefPtr<ossimConnectableObject> ossimOrthoIgen::setupAnnotation( + ossimKeywordlist& kwl, ossimConnectableObject* input) const +{ + ossimRefPtr<ossimConnectableObject> result = NULL; + + if(theAnnotationTemplate.exists() == false) + { + return result; + } + + ossimKeywordlist tempKwl; + if (tempKwl.addFile(theAnnotationTemplate) == false) + { + return result; + } + + ossimRefPtr<ossimObject> obj = ossimObjectFactoryRegistry::instance()-> + createObject(tempKwl, "object1."); + if (obj.valid()) + { + ossimGeoAnnotationSource* oga = PTR_CAST(ossimGeoAnnotationSource, + obj.get()); + if (oga) + { + // Connect to input. + oga->connectMyInputTo(input); + + // Set the view. + ossimRefPtr<ossimProjection> viewProj = + ossimProjectionFactoryRegistry::instance()->createProjection( + kwl, "product.projection."); + if (viewProj.valid()) + { + oga->setProjection(viewProj.get(), + false); // False for doesn't own projection. + } + + result = oga; + } + } + + return result; +} + +bool ossimOrthoIgen::setupTiling(ossimKeywordlist& kwl) +{ + ossimKeywordlist tempKwl; + ossimFilename outputFilename = theFilenames[theFilenames.size()-1].theFilename; + + if((theTilingTemplate == "")|| + (!tempKwl.addFile(theTilingTemplate))) + { + return false; + } + + if(outputFilename.isDir()) + { + if(tempKwl.find("igen.tiling.type")) + { + kwl.add(tempKwl); + theTilingFilename = tempKwl.find("igen.tiling.tile_name_mask"); + } + else if(tempKwl.find("type")) + { + kwl.add("igen.tiling.", tempKwl); + theTilingFilename = tempKwl.find("tile_name_mask"); + } + } + else + { + theTilingFilename = outputFilename.file(); + if(tempKwl.find("igen.tiling.type")) + { + tempKwl.add("igen.tiling.tile_name_mask", + theTilingFilename.c_str(), + true); + kwl.add(tempKwl); + } + else if(tempKwl.find("type")) + { + tempKwl.add("tile_name_mask", + theTilingFilename.c_str(), + true); + kwl.add("igen.tiling.", tempKwl); + } + } + + return true; +} + +void ossimOrthoIgen::setMetersPerPixel(const ossimDpt& mpp) +{ + theMetersPerPixelOverride = mpp; +} + +void ossimOrthoIgen::setThumbnailResolution(const ossimIpt& res) +{ + std::ostringstream out; + + out << res.x << " " << res.y; + + theThumbnailRes = out.str().c_str(); +} + +void ossimOrthoIgen::setThumbnailFlag(bool thumbnailFlag) +{ + theThumbnailFlag = thumbnailFlag; +} diff --git a/Utilities/OSSIM/ossim_core/parallel/ossimOrthoIgen.h b/Utilities/OSSIM/ossim_core/parallel/ossimOrthoIgen.h new file mode 100644 index 0000000000..0e91f28cf6 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/parallel/ossimOrthoIgen.h @@ -0,0 +1,144 @@ +#ifndef ossimOrthoIgen_HEADER +#define ossimOrthoIgen_HEADER +#include <base/common/ossimObject.h> +#include <base/common/ossimArgumentParser.h> +#include <base/common/ossimApplicationUsage.h> +#include <base/common/ossimRefPtr.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimFilename.h> +class ossimConnectableObject; +class OSSIM_DLL ossimOrthoIgen : public ossimReferenced +{ +public: + enum ossimOrthoIgenProjectionType + { + OSSIM_UNKNOWN_PROJECTION = 0, + OSSIM_UTM_PROJECTION, + OSSIM_GEO_PROJECTION, + OSSIM_INPUT_PROJECTION, + OSSIM_EXTERNAL_PROJECTION + }; + class ossimOrthoIgenFilename + { + public: + ossimOrthoIgenFilename() + :theFilename(""), + theEntry(-1) + {} + ossimOrthoIgenFilename(const ossimFilename& file, bool decodeEntry); + ossimOrthoIgenFilename(const ossimFilename& file, ossim_int32 entryNumber) + :theFilename(file), + theEntry(entryNumber) + { + } + void setFilenameWithDecoding(const ossimFilename& file); + void setFilenameAndEntry(const ossimFilename& file, + ossim_int32 entry) + { + theFilename = file; + theEntry = entry; + } + ossimFilename theFilename; + ossim_int32 theEntry; + }; + ossimOrthoIgen(); + + /** + * Will add command line arguments to initialize this object from a command line application + * + * <pre> + * Command Line Arguments: + * + * -t or --thumbnail Takes an integer argument that is used to set both width + * and height. + * example: -t 1024 will produce an image that is 1024x1024 + * --meters Takes a double precision argument that is used for meters per pixel + * override. + * example: --meters 5 will create a 5 meter product. + * --slave-buffers Takes an integer as an argument that specifies the number of slave tile buffers per + * slave node. The slave nodes are suppose to be asynch send. It will + * not wait for the send to finish. It will got to the next buffer and check to + * see if it's been sent and if not it will then wait for the buffer to be free. + * example: --slave-buffers 10 will create 10 buffers per slave node. + * --chain-template Takes a file name that is a kewyord list that is used as a template for every + * input file. + * example: + * + * @param argumentParser Argument parser object to add command line options to + * + */ + void addArguments(ossimArgumentParser& argumentParser); + void initialize(ossimArgumentParser& argumentParser); + void addFiles(ossimArgumentParser& argumentParser, + bool withDecoding, + ossim_uint32 startIdx = 1); + void clearFilenameList(); + void addFile(const ossimFilename& file, bool withDecoding=false); + bool execute(); + void setDefaultValues(); + + void setCombinerType(const ossimString& combinerName); + + void setProjectionName(const ossimString& proj); + void setResamplerType(const ossimString& resamplerType); + + + void setCutCenter(const ossimDpt& dpt, + ossimUnitType unit = OSSIM_DEGREES); + void setCutDxDy(const ossimDpt& dpt, + ossimUnitType unit = OSSIM_METERS); + void setMetersPerPixel(const ossimDpt& mpp); + void setThumbnailResolution(const ossimIpt& res); + void setThumbnailFlag(bool flag); + + bool setupIgenKwl(ossimKeywordlist& kwl); + +protected: + ossimString theThumbnailRes; + bool theThumbnailFlag; + ossimDpt theMetersPerPixelOverride; + ossimOrthoIgenProjectionType theProjectionType; + ossimString theProjectionName; + ossim_float64 theGeographicOriginOfLatitude; + ossimString theCombinerType; + ossimString theResamplerType; + ossimFilename theTemplateView; + ossimFilename theTilingTemplate; + ossimFilename theTilingFilename; + ossimFilename theChainTemplate; + ossimFilename theCombinerTemplate; + ossimFilename theAnnotationTemplate; + ossimFilename theWriterTemplate; + ossimString theSlaveBuffers; + ossimDpt theCutCenter; + ossimDpt theCutDxDy; + ossimUnitType theCutCenterUnit; + ossimUnitType theCutDxDyUnit; + ossim_float64 theLowPercentClip; + ossim_float64 theHighPercentClip; + + std::vector<ossimOrthoIgenFilename> theFilenames; + + bool setupTiling(ossimKeywordlist& kwl); + + ossimRefPtr<ossimConnectableObject> setupCutter(ossimKeywordlist& kwl, + ossimConnectableObject* input); + bool setupWriter(ossimKeywordlist& kwl, + ossimConnectableObject* input); + bool setupView(ossimKeywordlist& kwl); + + /** + * Sets up any annotation from --annotate option. + * + * @param kwl Main keyword list to save to. + * + * @param input Input connection of the annotation filter. + * + * @note This must be called after "setupView" as it needs a projection. + */ + ossimRefPtr<ossimConnectableObject> setupAnnotation( + ossimKeywordlist& kwl, + ossimConnectableObject* input) const; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/plugin/.cvsignore b/Utilities/OSSIM/ossim_core/plugin/.cvsignore new file mode 100644 index 0000000000..a4383358ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/plugin/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/Utilities/OSSIM/ossim_core/plugin/CMakeLists.txt b/Utilities/OSSIM/ossim_core/plugin/CMakeLists.txt new file mode 100644 index 0000000000..e4ce402dd8 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/plugin/CMakeLists.txt @@ -0,0 +1,6 @@ +FILE(GLOB_RECURSE ossim_plugin_SRCS "*.cpp") +FILE(GLOB_RECURSE ossim_plugin_HDRS "*.h") +ADD_LIBRARY(ossim_plugin ${ossim_plugin_SRCS}) + +INSTALL_TARGETS(/lib/otb/ ossim_plugin) +INSTALL_FILES(/include/otb/Utilities/OSSIM/ossim_core/ "\\.h$" ${ossim_plugin_HRDS}) diff --git a/Utilities/OSSIM/ossim_core/plugin/ossimDynamicLibrary.cpp b/Utilities/OSSIM/ossim_core/plugin/ossimDynamicLibrary.cpp new file mode 100644 index 0000000000..6383f20d4c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/plugin/ossimDynamicLibrary.cpp @@ -0,0 +1,118 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// LICENSE: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//********************************************************************* +// $Id: ossimDynamicLibrary.cpp,v 1.13 2005/10/17 18:42:27 gpotts Exp $ +#include <plugin/ossimDynamicLibrary.h> +#include <plugin/ossimSharedObjectBridge.h> +#include <base/common/ossimTrace.h> +#include <base/context/ossimNotifyContext.h> + + +RTTI_DEF(ossimDynamicLibrary, "ossimDynamicLibrary"); + +// Static trace for debugging. +static ossimTrace traceDebug(ossimString("ossimDynamicLibrary:debug")); + +ossimDynamicLibrary::ossimDynamicLibrary() + :theLibrary(0) +{ +} + +ossimDynamicLibrary::ossimDynamicLibrary(const ossimString& name) +{ + load(name); +} + +ossimDynamicLibrary::~ossimDynamicLibrary() +{ +} + +bool ossimDynamicLibrary::load() +{ + return load(theLibraryName); +} + + +bool ossimDynamicLibrary::load(const ossimString& name) +{ + ossimFilename libraryName = name; +#if OSSIM_DYNAMIC_ENABLED +# if defined(__WIN32__) || defined(_WIN32) + libraryName.convertForwardToBackSlashes(); + theLibrary = LoadLibrary(libraryName.c_str()); +# elif HAVE_DLFCN_H + libraryName.convertBackToForwardSlashes(); + theLibrary = dlopen(libraryName.c_str(), RTLD_LAZY); +# endif +#endif + + if (isLoaded()) + { + theLibraryName = libraryName; + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimDynamicLibrary::load DEBUG:" << std::endl; + + if (isLoaded()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "Loaded library: " << name << std::endl; + } + else + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimDynamicLibrary::load DEBUG:" + << "\nFailed to load library: " << name + << std::endl; +#if OSSIM_DYNAMIC_ENABLED +# if HAVE_DLFCN_H + ossimNotify(ossimNotifyLevel_DEBUG) << dlerror() << std::endl; +# endif +#endif + } + + } + + return isLoaded(); +} + +void ossimDynamicLibrary::unload() +{ + if(isLoaded()) + { +#if OSSIM_DYNAMIC_ENABLED +# if defined(__WIN32__) || defined(_WIN32) + FreeLibrary(theLibrary); +# elif HAVE_DLFCN_H + dlclose(theLibrary); +# endif +#endif + theLibrary = NULL; + } +} + +void *ossimDynamicLibrary::getSymbol(const ossimString& name) const +{ + if(isLoaded()) + { +#if OSSIM_DYNAMIC_ENABLED +# if defined(__WIN32__) || defined(_WIN32) + return (void*)GetProcAddress( (HINSTANCE)theLibrary, name.c_str()); +# elif HAVE_DLFCN_H + return dlsym(theLibrary, name.c_str()); +# endif +#endif + } + + return (void*)NULL; +} diff --git a/Utilities/OSSIM/ossim_core/plugin/ossimDynamicLibrary.h b/Utilities/OSSIM/ossim_core/plugin/ossimDynamicLibrary.h new file mode 100644 index 0000000000..2908188e14 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/plugin/ossimDynamicLibrary.h @@ -0,0 +1,69 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// LICENSE: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimDynamicLibrary.h,v 1.9 2004/11/10 17:44:32 dburken Exp $ +#ifndef ossimDynamicLibrary_HEADER +#define ossimDynamicLibrary_HEADER + +#include <base/data_types/ossimString.h> +#include <base/common/ossimRtti.h> +#include <base/common/ossimReferenced.h> + +#include <ossimConfig.h> + +#if defined(_WIN32) || defined(__WIN32__) +#include <windows.h> +#elif HAVE_DLFCN_H +#include <dlfcn.h> +#else +#define OSSIM_DYNAMIC_DISABLED +// #error "dynamic loading interface is unsupported on this platform" +#endif + +class ossimDynamicLibrary : public ossimReferenced +{ +public: + ossimDynamicLibrary(); + ossimDynamicLibrary(const ossimString& name); + virtual ~ossimDynamicLibrary(); + // return TRUE if the library was loaded successfully + bool isLoaded() const { return theLibrary != 0; } + + // load the library with the given name (full or not), return TRUE on + // success + bool load(const ossimString& name); + + bool load(); + // unload the library, also done automatically in dtor + void unload(); + + // load a symbol from the library, return NULL if an error occured or + // symbol wasn't found + void *getSymbol(const ossimString& name) const; + + const ossimString& getName()const + { + return theLibraryName; + } + +protected: + // the handle to DLL or NULL +#if defined(_WIN32) + HINSTANCE theLibrary; +#else + void* theLibrary; +#endif + ossimString theLibraryName; + +TYPE_DATA +}; + + +#endif diff --git a/Utilities/OSSIM/ossim_core/plugin/ossimPluginLibrary.cpp b/Utilities/OSSIM/ossim_core/plugin/ossimPluginLibrary.cpp new file mode 100644 index 0000000000..ee4f480dca --- /dev/null +++ b/Utilities/OSSIM/ossim_core/plugin/ossimPluginLibrary.cpp @@ -0,0 +1,95 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossimPluginLibrary.cpp,v 1.4 2005/05/20 16:28:31 gpotts Exp $ +#include "ossimPluginLibrary.h" + +RTTI_DEF1(ossimPluginLibrary, "ossimPluginLibrary", ossimDynamicLibrary); + +ossimPluginLibrary::ossimPluginLibrary() + :ossimDynamicLibrary(), + theInfo(0) +{ +} + +ossimPluginLibrary::ossimPluginLibrary(const ossimString& name) + :ossimDynamicLibrary(name), + theInfo(0) +{ + initialize(); +} + +ossimPluginLibrary::~ossimPluginLibrary() +{ +} + +void ossimPluginLibrary::initialize() +{ + if(!isLoaded()) + { + load(); + } + + ossimSharedLibraryInitializePtr init = (ossimSharedLibraryInitializePtr)getSymbol("ossimSharedLibraryInitialize"); + + if(init) + { + init(&theInfo); + } +} + +void ossimPluginLibrary::finalize() +{ + ossimSharedLibraryInitializePtr finalizeLib = (ossimSharedLibraryInitializePtr)getSymbol("ossimSharedLibraryFinalize"); + if(finalizeLib) + { + finalizeLib(&theInfo); + } + + unload(); +} + +ossimString ossimPluginLibrary::getDescription()const +{ + ossimString result; + + if(theInfo&&isLoaded()&&theInfo->getDescription) + { + result = theInfo->getDescription(); + } + + return result; +} + +void ossimPluginLibrary::getClassNames(std::vector<ossimString>& classNames)const +{ + if(theInfo&&theInfo->getNumberOfClassNames&&theInfo->getClassName) + { + ossim_int32 idx = 0; + ossim_int32 numObjects = 0; + + numObjects = theInfo->getNumberOfClassNames(); + for(idx = 0; idx < numObjects; ++idx) + { + classNames.push_back(theInfo->getClassName(idx)); + } + } +} diff --git a/Utilities/OSSIM/ossim_core/plugin/ossimPluginLibrary.h b/Utilities/OSSIM/ossim_core/plugin/ossimPluginLibrary.h new file mode 100644 index 0000000000..b0dd643fc1 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/plugin/ossimPluginLibrary.h @@ -0,0 +1,45 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossimPluginLibrary.h,v 1.3 2004/05/19 18:37:37 dburken Exp $ +#ifndef ossimPluginLibrary_HEADER +#define ossimPluginLibrary_HEADER +#include "plugin/ossimSharedObjectBridge.h" +#include "ossimDynamicLibrary.h" + +class OSSIMDLLEXPORT ossimPluginLibrary : public ossimDynamicLibrary +{ +public: + ossimPluginLibrary(); + ossimPluginLibrary(const ossimString& name); + virtual ~ossimPluginLibrary(); + void initialize(); + void finalize(); + ossimString getDescription()const; + void getClassNames(std::vector<ossimString>& classNames)const; + +protected: + ossimSharedObjectInfo* theInfo; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/plugin/ossimSharedObjectBridge.cpp b/Utilities/OSSIM/ossim_core/plugin/ossimSharedObjectBridge.cpp new file mode 100644 index 0000000000..afb8ec014c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/plugin/ossimSharedObjectBridge.cpp @@ -0,0 +1,27 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossimSharedObjectBridge.cpp,v 1.3 2004/08/30 17:16:54 gpotts Exp $ +#include "ossimSharedObjectBridge.h" + +extern "C" +{ +} diff --git a/Utilities/OSSIM/ossim_core/plugin/ossimSharedObjectBridge.h b/Utilities/OSSIM/ossim_core/plugin/ossimSharedObjectBridge.h new file mode 100644 index 0000000000..d1ca048487 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/plugin/ossimSharedObjectBridge.h @@ -0,0 +1,54 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossimSharedObjectBridge.h,v 1.17 2005/05/20 20:28:27 dburken Exp $ +#ifndef ossimSharedObjectBridge_HEADER +#define ossimSharedObjectBridge_HEADER +#include <vector> +#include "base/common/ossimObject.h" +#include "base/common/ossimConstants.h" + +extern "C" +{ + typedef const char* (*ossimSharedLibraryGetDescriptionPtr)(); + typedef int (*ossimSharedLibraryGetNumberOfClassNamesPtr)(); + typedef const char* (*ossimSharedLibraryGetClassNamesPtr)(int idx); + + struct OSSIMDLLEXPORT ossimSharedObjectInfo + { + ossimSharedLibraryGetDescriptionPtr getDescription; + ossimSharedLibraryGetNumberOfClassNamesPtr getNumberOfClassNames; + ossimSharedLibraryGetClassNamesPtr getClassName; + }; + + + typedef void (*ossimSharedLibraryInitializePtr)(ossimSharedObjectInfo** info); + typedef void (*ossimSharedLibraryFinalizePtr)(); + + /* + * these need to define these in your plugin. They are only here for clairity + * + * extern void ossimSharedLibraryInitialize(ossimSharedObjectInfo** info); + * extern void ossimSharedLibraryFinalize(); + */ +} + +#endif diff --git a/Utilities/OSSIM/ossim_core/plugin/ossimSharedPluginRegistry.cpp b/Utilities/OSSIM/ossim_core/plugin/ossimSharedPluginRegistry.cpp new file mode 100644 index 0000000000..e0b2f1b9f0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/plugin/ossimSharedPluginRegistry.cpp @@ -0,0 +1,181 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimSharedPluginRegistry.cpp,v 1.25 2005/05/20 20:28:27 dburken Exp $ +#include <algorithm> +#include <plugin/ossimSharedPluginRegistry.h> +#include <base/common/ossimConstants.h> +#include <base/common/ossimTrace.h> +#include <base/common/ossimKeywordNames.h> +#include <base/data_types/ossimKeywordlist.h> +#include <plugin/ossimSharedObjectBridge.h> + +ossimSharedPluginRegistry* ossimSharedPluginRegistry::theInstance = NULL; +//ossimPluginBridgeStructure ossimSharedPluginRegistry::thePluginBridgeFactoryPointers; + +static ossimTrace traceDebug("ossimSharedPluginRegistry:debug"); + +ossimSharedPluginRegistry::~ossimSharedPluginRegistry() +{ + theLibraryList.clear(); + + theInstance = NULL; +} + +ossimSharedPluginRegistry* ossimSharedPluginRegistry::instance() +{ + if(!theInstance) + { + theInstance = new ossimSharedPluginRegistry; + } + + return theInstance; +} + +bool ossimSharedPluginRegistry::registerPlugin(const ossimFilename& filename) +{ + bool result = false; + if(!getPlugin(filename)) + { + ossimPluginLibrary *lib =new ossimPluginLibrary; + if(lib->load(filename)) + { + if(lib->getSymbol("ossimSharedLibraryInitialize")) + { + lib->initialize(); + theLibraryList.push_back(lib); + result = true; + } + else + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "ossimSharedPluginRegistry DEBUG:" + << "ossimSharedLibraryInitialize symbol not found\n" + << endl; + } + + } + } + else + { + delete lib; + lib = 0; + } + } + return result; +} + +bool ossimSharedPluginRegistry::unregisterPlugin(int idx) +{ + ossimPluginLibrary* lib = getPlugin(idx); + bool result = false; + if(lib) + { + std::vector<ossimRefPtr<ossimPluginLibrary> >::iterator iter = std::find(theLibraryList.begin(), + theLibraryList.end(), + lib); + + if(iter != theLibraryList.end()) + { + (*iter)->finalize(); + theLibraryList.erase(iter); + result = true; + } + } + + return result; +} + +const ossimPluginLibrary* ossimSharedPluginRegistry::getPlugin(const ossimFilename& filename)const +{ + ossim_uint32 idx = 0; + + for(idx = 0; idx < theLibraryList.size();++idx) + { + if(filename == theLibraryList[idx]->getName()) + { + return theLibraryList[idx].get(); + } + } + + return 0; +} + +ossimPluginLibrary* ossimSharedPluginRegistry::getPlugin(const ossimFilename& filename) +{ + ossim_uint32 idx = 0; + + for(idx = 0; idx < theLibraryList.size();++idx) + { + if(filename == theLibraryList[idx]->getName()) + { + return theLibraryList[idx].get(); + } + } + + return 0; +} + +ossim_uint32 ossimSharedPluginRegistry::getIndex(const ossimPluginLibrary* lib)const +{ + ossim_uint32 idx = 0; + + for(idx = 0; idx < theLibraryList.size(); ++idx) + { + if(theLibraryList[idx] == lib) + { + return idx; + } + } + + return idx; +} + +ossimPluginLibrary* ossimSharedPluginRegistry::getPlugin(ossim_uint32 idx) +{ + ossimPluginLibrary* result = 0; + + if((idx>=0)&&(idx < theLibraryList.size())) + { + result = theLibraryList[idx].get(); + } + + return result; +} + +const ossimPluginLibrary* ossimSharedPluginRegistry::getPlugin(ossim_uint32 idx)const +{ + const ossimPluginLibrary* result = 0; + + if((idx>=0)&&(idx < theLibraryList.size())) + { + result = theLibraryList[idx].get(); + } + + return result; +} + +ossim_uint32 ossimSharedPluginRegistry::getNumberOfPlugins()const +{ + return theLibraryList.size(); +} diff --git a/Utilities/OSSIM/ossim_core/plugin/ossimSharedPluginRegistry.h b/Utilities/OSSIM/ossim_core/plugin/ossimSharedPluginRegistry.h new file mode 100644 index 0000000000..5edbb9eaae --- /dev/null +++ b/Utilities/OSSIM/ossim_core/plugin/ossimSharedPluginRegistry.h @@ -0,0 +1,36 @@ +#ifndef ossimSharedPluginRegistry_HEADER +#define ossimSharedPluginRegistry_HEADER +#include <vector> +#include <plugin/ossimSharedObjectBridge.h> +#include <base/data_types/ossimFilename.h> +#include <base/common/ossimRefPtr.h> +#include <plugin/ossimPluginLibrary.h> + +class OSSIMDLLEXPORT ossimSharedPluginRegistry +{ +public: + virtual ~ossimSharedPluginRegistry(); + + static ossimSharedPluginRegistry* instance(); + + bool registerPlugin(const ossimFilename& filename); + bool unregisterPlugin(int idx); + const ossimPluginLibrary* getPlugin(const ossimFilename& filename)const; + ossimPluginLibrary* getPlugin(const ossimFilename& filename); + + ossim_uint32 getIndex(const ossimPluginLibrary* lib)const; + ossimPluginLibrary* getPlugin(ossim_uint32 idx); + const ossimPluginLibrary* getPlugin(ossim_uint32 idx)const; + ossim_uint32 getNumberOfPlugins()const; + +protected: + ossimSharedPluginRegistry(){} + ossimSharedPluginRegistry(const ossimSharedPluginRegistry&){} + void operator = (const ossimSharedPluginRegistry&){} + + static ossimSharedPluginRegistry* theInstance; + + std::vector<ossimRefPtr<ossimPluginLibrary> > theLibraryList; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/.cvsignore b/Utilities/OSSIM/ossim_core/projections/.cvsignore new file mode 100644 index 0000000000..5e618e9f5c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/.cvsignore @@ -0,0 +1,3 @@ +*.d +.shared_obj +Makefile diff --git a/Utilities/OSSIM/ossim_core/projections/CMakeLists.txt b/Utilities/OSSIM/ossim_core/projections/CMakeLists.txt new file mode 100644 index 0000000000..1a192de6a0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/CMakeLists.txt @@ -0,0 +1,6 @@ +FILE(GLOB_RECURSE ossim_projections_SRCS "*.cpp") +FILE(GLOB_RECURSE ossim_projections_HDRS "*.h") +ADD_LIBRARY(ossim_projections ${ossim_projections_SRCS}) + +INSTALL_TARGETS(/lib/otb/ ossim_projections) +INSTALL_FILES(/include/otb/Utilities/OSSIM/ossim_core/ "\\.h$" ${ossim_projections_HRDS}) diff --git a/Utilities/OSSIM/ossim_core/projections/factory/.cvsignore b/Utilities/OSSIM/ossim_core/projections/factory/.cvsignore new file mode 100644 index 0000000000..7df3918588 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/factory/.cvsignore @@ -0,0 +1,3 @@ +*.d +Makefile + diff --git a/Utilities/OSSIM/ossim_core/projections/factory/ossimImageViewTransformFactory.cpp b/Utilities/OSSIM/ossim_core/projections/factory/ossimImageViewTransformFactory.cpp new file mode 100644 index 0000000000..3f5858d547 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/factory/ossimImageViewTransformFactory.cpp @@ -0,0 +1,69 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimImageViewTransformFactory.cpp,v 1.3 2002/08/27 17:30:11 gpotts Exp $ +#include "ossimImageViewTransformFactory.h" +#include "projections/ossimImageViewProjectionTransform.h" +#include "projections/ossimImageViewAffineTransform.h" +#include "base/data_types/ossimKeywordlist.h" + +RTTI_DEF1(ossimImageViewTransformFactory, "ossimImageViewTransformFactory", ossimObject) + +ossimImageViewTransformFactory* ossimImageViewTransformFactory::theInstance = 0; + +ossimImageViewTransformFactory* ossimImageViewTransformFactory::instance() +{ + if(!theInstance) + { + theInstance = new ossimImageViewTransformFactory; + } + + return theInstance; +} + +ossimImageViewTransform* ossimImageViewTransformFactory::createTransform(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimImageViewTransform* result=NULL; + + const char *lookup = kwl.find(prefix, "type"); + + if(lookup) + { + if(ossimString(lookup) == STATIC_TYPE_NAME(ossimImageViewProjectionTransform)) + { + result = new ossimImageViewProjectionTransform; + } + if(ossimString(lookup) == STATIC_TYPE_NAME(ossimImageViewAffineTransform)) + { + result = new ossimImageViewAffineTransform; + } + } + if(result) + { + result->loadState(kwl, prefix); + } + + return result; +} + diff --git a/Utilities/OSSIM/ossim_core/projections/factory/ossimImageViewTransformFactory.h b/Utilities/OSSIM/ossim_core/projections/factory/ossimImageViewTransformFactory.h new file mode 100644 index 0000000000..0ef7269f50 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/factory/ossimImageViewTransformFactory.h @@ -0,0 +1,49 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimImageViewTransformFactory.h,v 1.1 2001/10/26 13:49:04 gpotts Exp $ +#ifndef ossimImageViewTransformFactory_HEADER +#define ossimImageViewTransformFactory_HEADER +#include "base/common/ossimObject.h" + +class ossimImageViewTransform; +class ossimKeywordlist; + +class ossimImageViewTransformFactory : public ossimObject +{ +public: + static ossimImageViewTransformFactory* instance(); + virtual ossimImageViewTransform* createTransform(const ossimKeywordlist& kwl, + const char* prefix = 0); + +protected: + ossimImageViewTransformFactory(){}//hide + ossimImageViewTransformFactory(const ossimImageViewTransformFactory&){} + void operator =(const ossimImageViewTransformFactory&){} + + static ossimImageViewTransformFactory* theInstance; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/factory/ossimMapProjectionFactory.cpp b/Utilities/OSSIM/ossim_core/projections/factory/ossimMapProjectionFactory.cpp new file mode 100644 index 0000000000..de275890b1 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/factory/ossimMapProjectionFactory.cpp @@ -0,0 +1,326 @@ +//***************************************************************************** +// FILE: ossimMapProjectionFactory.cc +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// DESCRIPTION: +// Contains implementation of class ossimMapProjectionFactory +// +// SOFTWARE HISTORY: +//> +// 15Jun2001 Garrett Potts +// Initial coding. +//< +//***************************************************************************** +// $Id: ossimMapProjectionFactory.cpp,v 1.42 2004/09/24 17:19:40 dburken Exp $ + +#include <projections/factory/ossimMapProjectionFactory.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/common/ossimKeywordNames.h> +#include <base/data_types/ossimFilename.h> + +//*** +// Note to programmer: To add a new projection, search this file for +// "ADD_PROJECTION" to locate places requiring editing. Functional example +// below... +// +// ADD_PROJECTION: Include all map projection headers here: +//*** + +#include "projections/map_projections/ossimAlbersProjection.h" +#include "projections/map_projections/ossimAzimEquDistProjection.h" +#include "projections/map_projections/ossimBonneProjection.h" +#include "projections/map_projections/ossimBngProjection.h" +#include "projections/map_projections/ossimCassiniProjection.h" +#include "projections/map_projections/ossimCylEquAreaProjection.h" +#include "projections/map_projections/ossimEquDistCylProjection.h" +#include "projections/map_projections/ossimEckert4Projection.h" +#include "projections/map_projections/ossimEckert6Projection.h" +#include "projections/map_projections/ossimGnomonicProjection.h" +#include "projections/map_projections/ossimLambertConformalConicProjection.h" +#include "projections/map_projections/ossimLlxyProjection.h" +#include "projections/map_projections/ossimMercatorProjection.h" +#include "projections/map_projections/ossimMillerProjection.h" +#include "projections/map_projections/ossimMollweidProjection.h" +#include "projections/map_projections/ossimNewZealandMapGridProjection.h" +#include "projections/map_projections/ossimObliqueMercatorProjection.h" +#include "projections/map_projections/ossimOrthoGraphicProjection.h" +#include "projections/map_projections/ossimPolarStereoProjection.h" +#include "projections/map_projections/ossimPolyconicProjection.h" +#include "projections/map_projections/ossimSinusoidalProjection.h" +#include "projections/map_projections/ossimStereographicProjection.h" +#include "projections/map_projections/ossimTransCylEquAreaProjection.h" +#include "projections/map_projections/ossimTransMercatorProjection.h" +#include "projections/map_projections/ossimUpsProjection.h" +#include "projections/map_projections/ossimUtmProjection.h" +#include "projections/map_projections/ossimVanDerGrintenProjection.h" +#include "projections/map_projections/ossimSpaceObliqueMercatorProjection.h" +#include <support_data/ikonos/ossimSpaceImagingGeom.h> +//*** +// ADD_PROJECTION: List names of all map projections produced by this factory: +//*** + +ossimMapProjectionFactory* ossimMapProjectionFactory::theInstance = 0; + +//***************************************************************************** +// STATIC METHOD: ossimMapProjectionFactory::instance() +// +//***************************************************************************** +ossimMapProjectionFactory* ossimMapProjectionFactory::instance() +{ + if(!theInstance) + { + theInstance = new ossimMapProjectionFactory; + } + + return (ossimMapProjectionFactory*) theInstance; +} + +ossimProjection* +ossimMapProjectionFactory::createProjection(const ossimFilename& filename, + ossim_uint32 entryIdx)const +{ + if(!filename.exists()) + { + return NULL; + } + + // Check for external geometry file. + ossimProjection* proj = createProjectionFromGeometryFile(filename, + entryIdx); + if (proj) + { + return proj; + } + + ossimFilename geomFile = filename; + geomFile = geomFile.setExtension("geom"); + if(!geomFile.exists()) + { + return NULL; + } + ossimKeywordlist kwl; + if(kwl.addFile(geomFile)) + { + return createProjection(kwl); + } + + return NULL; +} + +//***************************************************************************** +// METHOD: ossimSensorModelFactory::create(kwl, prefix) +// +//***************************************************************************** +ossimProjection* ossimMapProjectionFactory::createProjection(const ossimKeywordlist &keywordList, + const char *prefix) const +{ + ossimProjection *result=NULL; + + const char *lookup = keywordList.find(prefix, ossimKeywordNames::TYPE_KW); + const char *lookupSpaceImaging = keywordList.find(prefix, ossimSpaceImagingGeom::SIG_PRODUCER_KW); + if(lookup) + { + result = createProjection(ossimString(lookup).trim()); + if(result) + { + result->loadState(keywordList, prefix); + } + } + else + { + if(lookupSpaceImaging) + { + ossimKeywordlist kwl; + ossimKeywordlist kwl2; + kwl.add(keywordList, + prefix, + true); + + ossimSpaceImagingGeom spaceImaging; + + spaceImaging.setGeometry(kwl); + + spaceImaging.exportToOssim(kwl2); + + result = ossimProjectionFactoryRegistry::instance()->createProjection(kwl2); + if(result) + { + return result; + } + } + // look for the geom_file keyword. + // + lookup = keywordList.find(prefix, ossimKeywordNames::GEOM_FILE_KW); + if(lookup) + { + ossimKeywordlist kwl; + + kwl.addFile(lookup); + + result = createProjection(kwl); + + if(!result) + { + // maybe they prepend projection. in the geom + // file. + result = createProjection(kwl, "projection."); + } + + } + } + return result; +} + +//***************************************************************************** +// METHOD: ossimSensorModelFactory::create(projection_name) +// +//***************************************************************************** +ossimProjection* ossimMapProjectionFactory::createProjection(const ossimString &name) const +{ + //*** + // ADD_PROJECTION: Test for each map projection here: + //*** + if(name == STATIC_TYPE_NAME(ossimAlbersProjection)) + return new ossimAlbersProjection; + if(name == STATIC_TYPE_NAME(ossimAzimEquDistProjection)) + return new ossimAzimEquDistProjection; + if( name == STATIC_TYPE_NAME(ossimBonneProjection)) + return new ossimBonneProjection; + if( name == STATIC_TYPE_NAME(ossimBngProjection)) + return new ossimBngProjection; + if(name == STATIC_TYPE_NAME(ossimCassiniProjection)) + return new ossimCassiniProjection; + if(name == STATIC_TYPE_NAME(ossimCylEquAreaProjection)) + return new ossimCylEquAreaProjection; + if(name == STATIC_TYPE_NAME(ossimEquDistCylProjection)) + return new ossimEquDistCylProjection; + if(name == STATIC_TYPE_NAME(ossimEckert4Projection)) + return new ossimEckert4Projection; + if(name == STATIC_TYPE_NAME(ossimEckert6Projection)) + return new ossimEckert6Projection; + if(name == STATIC_TYPE_NAME(ossimGnomonicProjection)) + return new ossimGnomonicProjection; + if(name == STATIC_TYPE_NAME(ossimLambertConformalConicProjection)) + return new ossimLambertConformalConicProjection; + if(name == STATIC_TYPE_NAME(ossimLlxyProjection)) + return new ossimLlxyProjection; + if(name == STATIC_TYPE_NAME(ossimMercatorProjection)) + return new ossimMercatorProjection; + if(name == STATIC_TYPE_NAME(ossimMillerProjection)) + return new ossimMillerProjection; + if(name == STATIC_TYPE_NAME(ossimMollweidProjection)) + return new ossimMollweidProjection; + if(name == STATIC_TYPE_NAME(ossimNewZealandMapGridProjection)) + return new ossimNewZealandMapGridProjection; + if(name == STATIC_TYPE_NAME(ossimObliqueMercatorProjection)) + return new ossimObliqueMercatorProjection; + if(name == STATIC_TYPE_NAME(ossimOrthoGraphicProjection)) + return new ossimOrthoGraphicProjection; + if(name == STATIC_TYPE_NAME(ossimPolarStereoProjection)) + return new ossimPolarStereoProjection; + if(name == STATIC_TYPE_NAME(ossimPolyconicProjection)) + return new ossimPolyconicProjection; + if(name == STATIC_TYPE_NAME(ossimSinusoidalProjection)) + return new ossimSinusoidalProjection; + if(name == STATIC_TYPE_NAME(ossimStereographicProjection)) + return new ossimStereographicProjection; + if(name == STATIC_TYPE_NAME(ossimTransCylEquAreaProjection)) + return new ossimTransCylEquAreaProjection; + if(name == STATIC_TYPE_NAME(ossimTransMercatorProjection)) + return new ossimTransMercatorProjection; + if(name == STATIC_TYPE_NAME(ossimUpsProjection)) + return new ossimUpsProjection; + if(name == STATIC_TYPE_NAME(ossimUtmProjection)) + return new ossimUtmProjection; + if(name == STATIC_TYPE_NAME(ossimVanDerGrintenProjection)) + return new ossimVanDerGrintenProjection; + if(name == STATIC_TYPE_NAME(ossimSpaceObliqueMercatorProjection)) + { + return new ossimSpaceObliqueMercatorProjection; + } + return NULL; +} + +ossimObject* ossimMapProjectionFactory::createObject(const ossimString& typeName)const +{ + return createProjection(typeName); +} + +ossimObject* ossimMapProjectionFactory::createObject(const ossimKeywordlist& kwl, + const char* prefix)const +{ + return createProjection(kwl, prefix); +} + +void ossimMapProjectionFactory::getTypeNameList(std::vector<ossimString>& typeList)const +{ + + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimAlbersProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimAzimEquDistProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimBonneProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimBngProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimCassiniProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimCylEquAreaProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimEquDistCylProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimEckert4Projection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimEckert6Projection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimGnomonicProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimLambertConformalConicProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimLlxyProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimMercatorProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimMillerProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimMollweidProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimNewZealandMapGridProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimObliqueMercatorProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimOrthoGraphicProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimPolarStereoProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimPolyconicProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimSinusoidalProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimStereographicProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimTransCylEquAreaProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimTransMercatorProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimUpsProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimUtmProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimVanDerGrintenProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimSpaceObliqueMercatorProjection))); +} + +list<ossimString> ossimMapProjectionFactory::getList()const +{ + list<ossimString> result; + + result.push_back(ossimString(STATIC_TYPE_NAME(ossimAlbersProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimAzimEquDistProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimBonneProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimBngProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimCassiniProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimCylEquAreaProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimEquDistCylProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimEckert4Projection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimEckert6Projection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimGnomonicProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimLambertConformalConicProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimLlxyProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimMercatorProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimMillerProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimMollweidProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimNewZealandMapGridProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimObliqueMercatorProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimOrthoGraphicProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimPolarStereoProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimPolyconicProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimSinusoidalProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimStereographicProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimTransCylEquAreaProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimTransMercatorProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimUpsProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimUtmProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimVanDerGrintenProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimSpaceObliqueMercatorProjection))); + + return result; +} diff --git a/Utilities/OSSIM/ossim_core/projections/factory/ossimMapProjectionFactory.h b/Utilities/OSSIM/ossim_core/projections/factory/ossimMapProjectionFactory.h new file mode 100644 index 0000000000..1584e0691f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/factory/ossimMapProjectionFactory.h @@ -0,0 +1,74 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +// class ossimProjectionFactory maintains a static list of projection +// makers. If a user wants to create a projection they can pass in +// a projection name and a datum if desired. Currently the default +// datum will be WGS84. +//******************************************************************* +// $Id: ossimMapProjectionFactory.h,v 1.7 2004/09/24 17:19:40 dburken Exp $ + +#ifndef ossimMapProjectionFactory_HEADER +#define ossimMapProjectionFactory_HEADER + +#include "ossimProjectionFactoryBase.h" + +class ossimProjection; +class ossimString; + +class OSSIMDLLEXPORT ossimMapProjectionFactory : public ossimProjectionFactoryBase +{ +public: + /*! + * METHOD: instance() + * Instantiates singleton instance of this class: + */ + static ossimMapProjectionFactory* instance(); + + virtual ossimProjection* createProjection(const ossimFilename& filename, + ossim_uint32 entryIdx)const; + /*! + * METHOD: create() + * Attempts to create an instance of the projection specified by name. + * Returns successfully constructed projection or NULL. + */ + virtual ossimProjection* createProjection(const ossimString& name)const; + virtual ossimProjection* createProjection(const ossimKeywordlist& kwl, + const char* prefix = 0)const; + + virtual ossimObject* createObject(const ossimString& typeName)const; + + /*! + * Creates and object given a keyword list. + */ + virtual ossimObject* createObject(const ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * This should return the type name of all objects in all factories. + * This is the name used to construct the objects dynamially and this + * name must be unique. + */ + virtual void getTypeNameList(std::vector<ossimString>& typeList)const; + + /*! + * METHOD: getList() + * Returns list of all projections represented by this factory: + */ + virtual list<ossimString> getList()const; + +protected: + ossimMapProjectionFactory() {} + static ossimMapProjectionFactory* theInstance; + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/factory/ossimMiscProjectionFactory.cpp b/Utilities/OSSIM/ossim_core/projections/factory/ossimMiscProjectionFactory.cpp new file mode 100644 index 0000000000..5926e8280b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/factory/ossimMiscProjectionFactory.cpp @@ -0,0 +1,190 @@ +//***************************************************************************** +// FILE: ossimMiscProjectionFactory.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// DESCRIPTION: +// Contains implementation of class ossimMiscProjectionFactory +// +// SOFTWARE HISTORY: +//> +// 15Jun2001 Garrett Potts +// Initial coding. +//< +//***************************************************************************** +// $Id: ossimMiscProjectionFactory.cpp,v 1.8 2004/10/04 18:57:11 gpotts Exp $ + +#include <projections/factory/ossimMiscProjectionFactory.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimFilename.h> +#include <base/common/ossimKeywordNames.h> + +//*** +// Note to programmer: To add a new projection, search this file for +// "ADD_PROJECTION" to locate places requiring editing. Functional example +// below... +// +// ADD_PROJECTION: Include all map projection headers here: +//*** + +#include <projections/ossimAffineProjection.h> +#include <projections/ossimBilinearProjection.h> +#include <projections/ossimQuadProjection.h> +#include <projections/ossimWarpProjection.h> +#include <projections/ossimRpcProjection.h> + +//*** +// ADD_PROJECTION: List names of all map projections produced by this factory: +//*** + +ossimMiscProjectionFactory* ossimMiscProjectionFactory::theInstance = 0; + +//***************************************************************************** +// STATIC METHOD: ossimMiscProjectionFactory::instance() +// +//***************************************************************************** +ossimMiscProjectionFactory* ossimMiscProjectionFactory::instance() +{ + if(!theInstance) + { + theInstance = new ossimMiscProjectionFactory; + } + + return (ossimMiscProjectionFactory*) theInstance; +} + +ossimProjection* +ossimMiscProjectionFactory::createProjection(const ossimFilename& filename, + ossim_uint32 entryIdx) const +{ + // Check for external geometry file. + return createProjectionFromGeometryFile(filename, entryIdx); +} + +//***************************************************************************** +// METHOD: ossimMiscProjectionFactory::createProjection(kwl, prefix) +// +//***************************************************************************** +ossimProjection* +ossimMiscProjectionFactory::createProjection(const ossimKeywordlist &kwl, + const char *prefix) const +{ + ossimProjection *result=NULL; + + const char *lookup = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + + if(lookup) + { + result = createProjection(ossimString(lookup).trim()); + if(result) + { + result->loadState(kwl, prefix); + } + } + else + { + // look for the geom_file keyword. + // + lookup = kwl.find(prefix, "geom_file"); + if(lookup) + { + ossimKeywordlist kwl2; + + kwl2.addFile(lookup); + + result = createProjection(kwl2, "projection."); + // maybe they did not prepend projection. in the pro + // file. + if(!result) + { + result = createProjection(kwl2); + } + + } + } + return result; +} + +//***************************************************************************** +// METHOD: ossimMiscProjectionFactory::createProjection(projection_name) +// +//***************************************************************************** +ossimProjection* +ossimMiscProjectionFactory::createProjection(const ossimString &name) const +{ + //*** + // ADD_PROJECTION: Test for each map projection here: + //*** + if(name == STATIC_TYPE_NAME(ossimAffineProjection)) + { + return new ossimAffineProjection; + } + if(name == STATIC_TYPE_NAME(ossimBilinearProjection)) + { + return new ossimBilinearProjection; + } + if(name == STATIC_TYPE_NAME(ossimQuadProjection)) + { + return new ossimQuadProjection; + } + if(name == STATIC_TYPE_NAME(ossimRpcProjection)) + { + return new ossimRpcProjection; + } + if(name == STATIC_TYPE_NAME(ossimWarpProjection)) + { + return new ossimWarpProjection; + } + return NULL; +} + +//***************************************************************************** +// METHOD +//***************************************************************************** +ossimObject* +ossimMiscProjectionFactory::createObject(const ossimString& typeName)const +{ + return createProjection(typeName); +} + +//***************************************************************************** +// METHOD +//***************************************************************************** +ossimObject* +ossimMiscProjectionFactory::createObject(const ossimKeywordlist& kwl, + const char* prefix)const +{ + return createProjection(kwl, prefix); +} + +//***************************************************************************** +// METHOD +//***************************************************************************** +void ossimMiscProjectionFactory::getTypeNameList(std::vector<ossimString>& typeList)const +{ + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimAffineProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimBilinearProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimRpcProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimQuadProjection))); + typeList.push_back(ossimString(STATIC_TYPE_NAME(ossimWarpProjection))); +} + +//***************************************************************************** +// METHOD +//***************************************************************************** +list<ossimString> ossimMiscProjectionFactory::getList()const +{ + list<ossimString> result; + + result.push_back(ossimString(STATIC_TYPE_NAME(ossimAffineProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimBilinearProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimRpcProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimQuadProjection))); + result.push_back(ossimString(STATIC_TYPE_NAME(ossimWarpProjection))); + + return result; +} diff --git a/Utilities/OSSIM/ossim_core/projections/factory/ossimMiscProjectionFactory.h b/Utilities/OSSIM/ossim_core/projections/factory/ossimMiscProjectionFactory.h new file mode 100644 index 0000000000..7529ef7339 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/factory/ossimMiscProjectionFactory.h @@ -0,0 +1,74 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +// class ossimProjectionFactory maintains a static list of projection +// makers. If a user wants to create a projection they can pass in +// a projection name and a datum if desired. Currently the default +// datum will be WGS84. +//******************************************************************* +// $Id: ossimMiscProjectionFactory.h,v 1.4 2004/09/24 17:19:40 dburken Exp $ + +#ifndef ossimMiscProjectionFactory_HEADER +#define ossimMiscProjectionFactory_HEADER + +#include "ossimProjectionFactoryBase.h" + +class ossimProjection; +class ossimString; + +class ossimMiscProjectionFactory : public ossimProjectionFactoryBase +{ +public: + /*! + * METHOD: instance() + * Instantiates singleton instance of this class: + */ + static ossimMiscProjectionFactory* instance(); + + /*! + * METHOD: create() + * Attempts to create an instance of the projection specified by name. + * Returns successfully constructed projection or NULL. + */ + virtual ossimProjection* createProjection(const ossimFilename& filename, + ossim_uint32 entryIdx)const; + virtual ossimProjection* createProjection(const ossimString& name)const; + virtual ossimProjection* createProjection(const ossimKeywordlist& kwl, + const char* prefix = 0)const; + + virtual ossimObject* createObject(const ossimString& typeName)const; + + /*! + * Creates and object given a keyword list. + */ + virtual ossimObject* createObject(const ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * This should return the type name of all objects in all factories. + * This is the name used to construct the objects dynamially and this + * name must be unique. + */ + virtual void getTypeNameList(std::vector<ossimString>& typeList)const; + + /*! + * METHOD: getList() + * Returns list of all projections represented by this factory: + */ + virtual list<ossimString> getList()const; + +protected: + ossimMiscProjectionFactory() {} + static ossimMiscProjectionFactory* theInstance; + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/factory/ossimNitfProjectionFactory.cpp b/Utilities/OSSIM/ossim_core/projections/factory/ossimNitfProjectionFactory.cpp new file mode 100644 index 0000000000..d058e1f87f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/factory/ossimNitfProjectionFactory.cpp @@ -0,0 +1,874 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2004 Intelligence Data Systems, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Matt Revelle +// David Burken +// +// Description: +// +// Contains class definition for ossimNitfProjectionFactory. +// +// $Id: ossimNitfProjectionFactory.cpp,v 1.18 2005/10/16 22:59:03 dburken Exp $ +//---------------------------------------------------------------------------- + +#include <fstream> +#include <cmath> + +#include <projections/factory/ossimNitfProjectionFactory.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <projections/map_projections/ossimUtmProjection.h> +#include <projections/map_projections/ossimEquDistCylProjection.h> +#include <projections/map_projections/ossimLlxyProjection.h> +#include <projections/ossimBilinearProjection.h> +#include <support_data/nitf/ossimNitfFile.h> +#include <support_data/nitf/ossimNitfFileHeader.h> +#include <support_data/nitf/ossimNitfImageHeader.h> +#include <support_data/nitf/ossimNitfBlockaTag.h> +#include <base/common/ossimKeywordNames.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimFilename.h> +#include <base/data_types/ossimDms.h> +#include <base/data_types/ossimGpt.h> +#include <base/data_types/ossimKeywordlist.h> +#include <projections/ossimProjection.h> +#include <projections/sensor_modeling/rpc/ossimIkonosRpcModel.h> +#include <projections/sensor_modeling/rpc/ossimNitfRpcModel.h> +#include <projections/sensor_modeling/rpc/ossimQuickbirdRpcModel.h> +#include <support_data/nitf/ossimNitfFile.h> +#include <support_data/nitf/ossimNitfImageHeader.h> + + +//--- +// Define Trace flags for use within this file: +//--- +#include <base/common/ossimTrace.h> +static ossimTrace traceDebug = ossimTrace("ossimNitfProjectionFactory:debug"); + +ossimNitfProjectionFactory* ossimNitfProjectionFactory::theInstance = NULL; + +ossimNitfProjectionFactory::ossimNitfProjectionFactory() +{ +} + +ossimNitfProjectionFactory::~ossimNitfProjectionFactory() +{ +} + +ossimNitfProjectionFactory* ossimNitfProjectionFactory::instance() +{ + if(!theInstance) + { + theInstance = new ossimNitfProjectionFactory(); + } + + return theInstance; +} + +ossimProjection* +ossimNitfProjectionFactory::createProjection(const ossimFilename& filename, + ossim_uint32 entryIdx)const +{ + static const char MODULE[]="ossimNitfProjectionFactory::createProjection"; + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " DEBUG:" + << "\nfilename: " << filename + << "\nentryIdx: " << entryIdx + << std::endl; + } + + // See if there is an external geomtry. + ossimProjection* result = createProjectionFromGeometryFile(filename, + entryIdx); + if (result) + { + return result; + } + + if(!isNitf(filename)) + { + return result; // result is NULL + } + + ossimNitfFile* nitf = new ossimNitfFile(); + if (!nitf->parseFile(filename)) + { + delete nitf; + nitf = NULL; + return result; // result is NULL + } + + long imageIndex = static_cast<long>(entryIdx); + if ( imageIndex > (nitf->getHeader()->getNumberOfImages()-1) ) + { + return result; + } + + ossimNitfImageHeader* imageHeader = nitf->getNewImageHeader(imageIndex); + { + if (!imageHeader) + { + return result; + } + } + + ossimString coordinateSystem = imageHeader->getCoordinateSystem(); + + if (coordinateSystem == "G" || coordinateSystem == "D") + { + result = makeGeographic(imageHeader, coordinateSystem, filename); + } + else if(coordinateSystem == "N" || coordinateSystem == "S") + { + result = makeUtm(imageHeader, coordinateSystem, filename); + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " DEBUG:" + << "\ncoordinateSysetm: " << coordinateSystem + << std::endl; + } + + return result; +} + + +ossimProjection* +ossimNitfProjectionFactory::createProjection(const ossimKeywordlist& kwl, + const char *prefix) const +{ + return NULL; +} + +ossimProjection* +ossimNitfProjectionFactory::createProjection(const ossimString &name) const +{ + return NULL; +} + +ossimObject* +ossimNitfProjectionFactory::createObject(const ossimString& typeName)const +{ + return (ossimObject*)createProjection(typeName); +} + +ossimObject* +ossimNitfProjectionFactory::createObject(const ossimKeywordlist& kwl, + const char* prefix)const +{ + return createProjection(kwl, prefix); +} + +void ossimNitfProjectionFactory::getTypeNameList(std::vector<ossimString>& typeList)const +{ + +} + +list<ossimString> ossimNitfProjectionFactory::getList()const +{ + list<ossimString> result; + return result; +} + +bool ossimNitfProjectionFactory::isNitf(const ossimFilename& filename)const +{ + std::ifstream in(filename.c_str(), ios::in|ios::binary); + + if(in) + { + char nitfFile[4]; + in.read((char*)nitfFile, 4); + ossimString s(nitfFile, nitfFile+4); + if ( (s == "NITF") || (s == "NSIF") ) + { + return true; + } + } + + return false; +} + +ossimProjection* ossimNitfProjectionFactory::makeGeographic( + const ossimNitfImageHeader* hdr, + const ossimString& coordinateSysetm, + const ossimFilename& filename) const +{ + ossimProjection* proj = NULL; + if (!hdr) + { + return proj; + } + + // To hold corner points. + std::vector<ossimGpt> gpts; + + //--- + // Get the corner points. + // + // Look for points from the BLOCKA tag. This may or may not be present. + // If present since it has six digit precision use it for the points. + //--- + if ( getBlockaPoints(hdr, gpts, filename) == false ) + { + ossimString geographicLocation = hdr->getGeographicLocation(); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimNitfProjectionFactory::makeGeographic DEBUG:" + << "\ngeographicLocation: " << geographicLocation + << std::endl; + } + + if (coordinateSysetm == "G") + { + //--- + // If coord system is G then format is: + // Lat = ddmmssX + // where d is degrees and m is minutes + // and s is seconds and X is either N (North) or S (South). + // Lon = dddmmssX + // where d is degrees and m is minutes + // and s is seconds and X is either N (North) or S (South). + //--- + parseGeographicString(geographicLocation, gpts); + } + else if (coordinateSysetm == "D") + { + //--- + // If coor system is D then format is: + // +-dd.ddd +-dd.ddd four times where + is northern hemispher and + // - is souther hemisphere for lat and longitude + // + is easting and - is westing. + //--- + parseDecimalDegreesString(geographicLocation, gpts); + } + } + + if (gpts.size() != 4) + { + return 0; + } + + if (!isSkewed(gpts)) + { + proj = makeEuiDistant(hdr, gpts); + } + else + { + // Image is rotated. Make a Bilinear. + proj = makeBilinear(hdr, gpts); + } + + if (traceDebug() && proj) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimNitfProjectionFactory::makeGeographic DEBUG:" + << "\nUpper left corner: " << gpts[0] + << "\nUpper right corner: " << gpts[1] + << "\nLower right corner: " << gpts[2] + << "\nLower left corner: " << gpts[3] << endl + << proj->print(ossimNotify(ossimNotifyLevel_DEBUG)) + << std::endl; + } + + return proj; +} + +ossimProjection* ossimNitfProjectionFactory::makeUtm( + const ossimNitfImageHeader* hdr, + const ossimString& coordinateSystem, + const ossimFilename& filename) const +{ + ossimUtmProjection* proj = NULL; + if (!hdr) + { + return proj; + } + + ossimString geographicLocation = hdr->getGeographicLocation(); + + std::vector<ossimDpt> utmPoints; + ossim_uint32 zone; + ossimDpt scale; + parseUtmString(geographicLocation, + zone, + utmPoints); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimNitfProjectionFactory::makeUtm DEBUG" + << "\ngeo string: " << geographicLocation + << std::endl; + for (ossim_uint32 i=0; i<utmPoints.size(); ++i) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "utmPoints[" << utmPoints[i] << std::endl; + } + } + + proj = new ossimUtmProjection; + if(coordinateSystem == "S") + { + proj->setHemisphere('S'); + } + else + { + proj->setHemisphere('N'); + } + proj->setZone(zone); + + if(isSkewed(utmPoints)) + { + std::vector<ossimGpt> gpts; + + // Try blocka points first as they are more accurate. + if ( getBlockaPoints(hdr, gpts, filename) == false ) + { + ossimGpt ul = proj->inverse(utmPoints[0]); + ossimGpt ur = proj->inverse(utmPoints[1]); + ossimGpt lr = proj->inverse(utmPoints[2]); + ossimGpt ll = proj->inverse(utmPoints[3]); + gpts.push_back(ul); + gpts.push_back(ur); + gpts.push_back(lr); + gpts.push_back(ll); + } + + delete proj; + proj = 0; + return makeBilinear(hdr, gpts); + } + else + { + computeScaleInMeters(hdr, utmPoints, scale); + } + + ossimProjection* result = 0; + if(!scale.hasNans()) + { + //--- + // Get the tie point. + // + // Look for the the BLOCKA tag which may or may not be present. + // This has six digit precision in decimal degrees which equates to + // about 0.11 meters (at equator) as compared to 1.0 accuaracy of the + // IGEOLO field. + //--- + ossimDpt tie; + std::vector<ossimGpt> gpts; + if ( getBlockaPoints(hdr, gpts, filename) ) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimNitfProjectionFactory::makeUtm DEBUG:" + << "\nTie point from blocka: " << gpts[0] + << endl; + } + + tie = proj->forward(gpts[0]); + tie.x += scale.x/2.0; + tie.y -= scale.y/2.0; + } + else + { + tie.x = utmPoints[0].x + scale.x/2.0; + tie.y = utmPoints[0].y - scale.y/2.0; + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimNitfProjectionFactory::makeUtm DEBUG:" + << "\nTie point: " << tie + << "\nScale: " << scale + << endl; + } + + proj->setUlEastingNorthing(tie); + proj->setMetersPerPixel(scale); + result = proj; + } + else + { + delete proj; + proj = 0; + } + return result; +} + +ossimProjection* ossimNitfProjectionFactory::makeEuiDistant( + const ossimNitfImageHeader* hdr, + const std::vector<ossimGpt>& gpts) const +{ + ossimEquDistCylProjection* proj = NULL; + + // Get the scale. + ossimDpt scale; + computeScaleInDecimalDegrees(hdr, gpts, scale); + + if (scale.hasNans()) + { + return proj; + } + + // Make the projection. + proj = new ossimEquDistCylProjection(); + + // Shift the tie to the center of the pixel. + ossimGpt tiePoint; + tiePoint.latd(gpts[0].latd() - (scale.y/2.0)); + tiePoint.lond(gpts[0].lond() + (scale.x/2.0)); + + // Set the tie point... +// proj->setOrigin(tiePoint); + proj->setUlGpt(tiePoint); + + // Set the scale + proj->setLatSpacing(scale.y); + proj->setLonSpacing(scale.x); + + return proj; +} + +ossimProjection* ossimNitfProjectionFactory::makeBilinear( + const ossimNitfImageHeader* hdr, + const std::vector<ossimGpt>& gpts) const +{ + double rows = hdr->getNumberOfRows(); + double cols = hdr->getNumberOfCols(); + + ossimDpt ul(0.0, 0.0); + ossimDpt ur(cols-1.0, 0.0); + ossimDpt lr(cols-1.0, rows-1.0); + ossimDpt ll(0.0, rows-1.0); + + return new ossimBilinearProjection(ul, + ur, + lr, + ll, + gpts[0], + gpts[1], + gpts[2], + gpts[3]); +} + +bool ossimNitfProjectionFactory::isSkewed( + const std::vector<ossimGpt>& gpts) const +{ + + return !( (gpts[0].latd() == gpts[1].latd()) && + (gpts[2].latd() == gpts[3].latd()) && + (gpts[0].lond() == gpts[3].lond()) && + (gpts[1].lond() == gpts[2].lond()) ); + +} + +bool ossimNitfProjectionFactory::isSkewed( + const std::vector<ossimDpt>& dpts) const +{ + return !( (dpts[0].y == dpts[1].y) && + (dpts[2].y == dpts[3].y) && + (dpts[0].x == dpts[3].x) && + (dpts[1].x == dpts[2].x) ); + +} + +bool ossimNitfProjectionFactory::getBlockaPoints( + const ossimNitfImageHeader* hdr, + std::vector<ossimGpt>& gpts, + const ossimFilename& filename) const +{ + if (!hdr) + { + return false; + } + + ossimNitfTagInformation tagInfo; + ossimRefPtr<ossimNitfRegisteredTag> blockaTag; + + if (hdr->getTag(tagInfo, ossimString("BLOCKA")) == true) + { + blockaTag = tagInfo.getTagData(); + + if (!blockaTag) // Tag is there but it was not parsed. + { + blockaTag = new ossimNitfBlockaTag(); + std::ifstream in(filename.c_str(), ios::in|ios::binary); + if(in) + { + // Seek to the start of tag data. + in.seekg(tagInfo.getTagDataOffset()); + blockaTag->parseStream(in); + in.close(); + } + } + } + + if (!blockaTag) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimNitfProjectionFactory::getBlockaPoints DEBUG:" + << "\nBLOCKA tag not found." + << std::endl; + } + return false; + } + + if (gpts.size()) + { + gpts.clear(); + } + + ossimNitfBlockaTag* tag = PTR_CAST(ossimNitfBlockaTag, blockaTag.get()); + if (!tag) + { + return false; + } + + ossimDpt dpt; + ossimGpt gpt; + + // Get the upper left or first row first column. + tag->getFrfcLoc(dpt); + gpt.latd(dpt.y); + gpt.lond(dpt.x); + gpts.push_back(gpt); + + // Get the upper right or first row last column. + tag->getFrlcLoc(dpt); + gpt.latd(dpt.y); + gpt.lond(dpt.x); + gpts.push_back(gpt); + + // Get the lower right or last row last column. + tag->getLrlcLoc(dpt); + gpt.latd(dpt.y); + gpt.lond(dpt.x); + gpts.push_back(gpt); + + // Get the lower left or last row first column. + tag->getLrfcLoc(dpt); + gpt.latd(dpt.y); + gpt.lond(dpt.x); + gpts.push_back(gpt); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimNitfProjectionFactory::getBlockaPoints DEBUG:" + << std::endl; + for (int i=0; i<4; ++i) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "gpt[" << i << "] " << gpts[i] << std::endl; + } + } + + return true; +} + +void ossimNitfProjectionFactory::computeScaleInDecimalDegrees( + const ossimNitfImageHeader* hdr, + const std::vector<ossimGpt>& gpts, + ossimDpt& scale) const +{ + if ( !hdr || isSkewed(gpts)) + { + scale.makeNan(); + return; + } + ossimIrect imageRect = hdr->getImageRect(); + + //--- + // Calculate the scale. This assumes that the corner points are for the + // edge of the corner pixels, not the center of the corner pixels. + //--- + double longitudeSize = 0.0; + double latitudeSize = 0.0; + if ( (gpts[1].lond() < 0.0) && (gpts[0].lond() >= 0) ) + { + //--- + // Upper right negative(Western), upper left positive (Eastern). + // Crossing date line maybe??? + //--- + longitudeSize = (gpts[1].lond() + 360.0) - gpts[0].lond(); + } + else + { + longitudeSize = gpts[1].lond() - gpts[0].lond(); + } + + latitudeSize = gpts[0].latd() - gpts[2].latd(); + + double rows = imageRect.height(); + double cols = imageRect.width(); +// double rows = hdr->getNumberOfRows(); +// double cols = hdr->getNumberOfCols(); + + if (!rows || !cols) + { + scale.makeNan(); + return; + } + scale.y = latitudeSize / rows; + scale.x = longitudeSize / cols; +} + +void ossimNitfProjectionFactory::computeScaleInMeters( + const ossimNitfImageHeader* hdr, + const std::vector<ossimDpt>& dpts, + ossimDpt& scale) const +{ + if ( !hdr || isSkewed(dpts)) + { + scale.makeNan(); + return; + } + ossimIrect imageRect = hdr->getImageRect(); + + //--- + // Calculate the scale. This assumes that the corner points are for the + // edge of the corner pixels, not the center of the corner pixels. + //--- + double eastingSize = 0.0; + double northingSize = 0.0; + + eastingSize = fabs(dpts[1].x - dpts[0].x); + northingSize = fabs(dpts[0].y - dpts[3].y); + + double rows = imageRect.height();//hdr->getNumberOfRows(); + double cols = imageRect.width();//hdr->getNumberOfCols(); + + if (!rows || !cols) + { + scale.makeNan(); + return; + } + scale.y = northingSize / rows; + scale.x = eastingSize / cols; +} + +void ossimNitfProjectionFactory::parseUtmString(const ossimString& utmLocation, + ossim_uint32& zone, + std::vector<ossimDpt>& utmPoints)const +{ + ossim_uint32 idx = 0; + ossimString z; + ossimString east; + ossimString north; + + + z = ossimString(utmLocation.begin() + idx, + utmLocation.begin() + idx + 2); + idx += 2; + east = ossimString(utmLocation.begin() + idx, + utmLocation.begin() + idx + 6); + idx += 6; + north = ossimString(utmLocation.begin() + idx, + utmLocation.begin() + idx + 7); + idx += 7; + + utmPoints.push_back(ossimDpt(east.toDouble(), + north.toDouble())); + + z = ossimString(utmLocation.begin() + idx, + utmLocation.begin() + idx + 2); + idx += 2; + east = ossimString(utmLocation.begin() + idx, + utmLocation.begin() + idx + 6); + idx += 6; + north = ossimString(utmLocation.begin() + idx, + utmLocation.begin() + idx + 7); + idx += 7; + utmPoints.push_back(ossimDpt(east.toDouble(), + north.toDouble())); + + z = ossimString(utmLocation.begin() + idx, + utmLocation.begin() + idx + 2); + idx += 2; + east = ossimString(utmLocation.begin() + idx, + utmLocation.begin() + idx + 6); + idx += 6; + north = ossimString(utmLocation.begin() + idx, + utmLocation.begin() + idx + 7); + idx += 7; + utmPoints.push_back(ossimDpt(east.toDouble(), + north.toDouble())); + + z = ossimString(utmLocation.begin() + idx, + utmLocation.begin() + idx + 2); + idx += 2; + east = ossimString(utmLocation.begin() + idx, + utmLocation.begin() + idx + 6); + idx += 6; + north = ossimString(utmLocation.begin() + idx, + utmLocation.begin() + idx + 7); + idx += 7; + utmPoints.push_back(ossimDpt(east.toDouble(), + north.toDouble())); + + zone = z.toUInt32(); +} + + +void ossimNitfProjectionFactory::parseGeographicString( + const ossimString& geographicLocation, std::vector<ossimGpt>& gpts) const +{ + gpts.clear(); + + if (geographicLocation.size() != 60) + { + return; + } + + int geo_index = 0; + for (int i=0; i<4; ++i) + { + //--- + // We have to split up the geographicLocation string for the dms class. + // + // geographicLocation = ddmmssXdddmmssX (four times). + // "dd mm ss X" has a string length of 10 + // "ddd mm ss X" has a string length of 11 + //--- + int lat_index = 0; + int lon_index = 0; + const char SPACE = ' '; + ossimString latString(10, SPACE); + ossimString lonString(11, SPACE); + + // degrees latitude + latString[lat_index++] = geographicLocation[geo_index++]; + latString[lat_index++] = geographicLocation[geo_index++]; + ++lat_index; + + // minutes latitude + latString[lat_index++] = geographicLocation[geo_index++]; + latString[lat_index++] = geographicLocation[geo_index++]; + ++lat_index; + + // seconds latitude + latString[lat_index++] = geographicLocation[geo_index++]; + latString[lat_index++] = geographicLocation[geo_index++]; + ++lat_index; + + // hemisphere + latString[lat_index++] = geographicLocation[geo_index++]; + + // degrees longitude + lonString[lon_index++] = geographicLocation[geo_index++]; + lonString[lon_index++] = geographicLocation[geo_index++]; + lonString[lon_index++] = geographicLocation[geo_index++]; + ++lon_index; + + // minutes longitude + lonString[lon_index++] = geographicLocation[geo_index++]; + lonString[lon_index++] = geographicLocation[geo_index++]; + ++lon_index; + + // seconds longitude + lonString[lon_index++] = geographicLocation[geo_index++]; + lonString[lon_index++] = geographicLocation[geo_index++]; + ++lon_index; + + // hemisphere + lonString[lon_index++] = geographicLocation[geo_index++]; + + // Convert to decimal degrees using the dms class. + ossimGpt gpt; + ossimDms dms(0.0); + dms.setLatFlag(true); + if ( ! dms.setDegrees(latString.c_str()) ) + { + gpts.clear(); + return; + } + gpt.latd(dms.getDegrees()); + + dms.setLatFlag(false); + if ( ! dms.setDegrees(lonString.c_str()) ) + { + gpts.clear(); + return; + } + gpt.lond(dms.getDegrees()); + + gpts.push_back(gpt); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimNitfProjectionFactory::parseGeographicString DEBUG:" + << "\nground point[" << i << "]: " << gpt + << std::endl; + } + } +} + +void ossimNitfProjectionFactory::parseDecimalDegreesString(const ossimString& geographicLocation, + std::vector<ossimGpt>& gpts) const +{ + const char* bufPtr = geographicLocation.c_str(); + + + ossimString ulLat(bufPtr, + bufPtr + 7); + bufPtr+=7; + ossimString ulLon(bufPtr, + bufPtr+8); + bufPtr+=8; + ossimString urLat(bufPtr, + bufPtr + 7); + bufPtr+=7; + ossimString urLon(bufPtr, + bufPtr+8); + bufPtr+=8; + ossimString lrLat(bufPtr, + bufPtr + 7); + bufPtr+=7; + ossimString lrLon(bufPtr, + bufPtr+8); + bufPtr+=8; + ossimString llLat(bufPtr, + bufPtr + 7); + bufPtr+=7; + ossimString llLon(bufPtr, + bufPtr+8); + + gpts.push_back(ossimGpt(ulLat.toDouble(), ulLon.toDouble())); + gpts.push_back(ossimGpt(urLat.toDouble(), urLon.toDouble())); + gpts.push_back(ossimGpt(lrLat.toDouble(), lrLon.toDouble())); + gpts.push_back(ossimGpt(llLat.toDouble(), llLon.toDouble())); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimNitfProjectionFactory::parseDecimalDegreesString DEBUG:" + << "\nground point[" << 0 << "]: " << gpts[0] + << "\nground point[" << 1 << "]: " << gpts[1] + << "\nground point[" << 2 << "]: " << gpts[2] + << "\nground point[" << 3 << "]: " << gpts[3] + << std::endl; + } +} + +ossimNitfProjectionFactory::ossimNitfProjectionFactory(const ossimNitfProjectionFactory&) +{ +} + +ossimNitfProjectionFactory& ossimNitfProjectionFactory::operator=(const ossimNitfProjectionFactory&) +{ + return *this; +} diff --git a/Utilities/OSSIM/ossim_core/projections/factory/ossimNitfProjectionFactory.h b/Utilities/OSSIM/ossim_core/projections/factory/ossimNitfProjectionFactory.h new file mode 100644 index 0000000000..10361cf2ec --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/factory/ossimNitfProjectionFactory.h @@ -0,0 +1,253 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2004 Intelligence Data Systems, Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Matt Revelle +// David Burken +// +// Description: +// +// Contains class declaration for ossimNitfProjectionFactory. +// +// $Id: ossimNitfProjectionFactory.h,v 1.8 2005/10/16 22:02:09 dburken Exp $ +//---------------------------------------------------------------------------- +#ifndef ossimNitfProjectionFactory_HEADER +#define ossimNitfProjectionFactory_HEADER + +#include <vector> +#include <projections/factory/ossimProjectionFactoryBase.h> + +class ossimProjection; +class ossimString; +class ossimGpt; +class ossimNitfImageHeader; +class ossimDpt; + +class OSSIMDLLEXPORT ossimNitfProjectionFactory : public ossimProjectionFactoryBase +{ +public: + + /** + * METHOD: instance() + * + * @return Singleton instance of this class. + */ + static ossimNitfProjectionFactory* instance(); + + /** + * destructor + */ + virtual ~ossimNitfProjectionFactory(); + + /** + * @param filename This filename can be an image file or + * it can also be a ossim .geom file. It could be other + * forms of geom files as well. The factories job will be to + * determine what parser to use and return a projection if + * successful. + * + * @return ossimProjection* on success or NULL if not handled. + */ + virtual ossimProjection* createProjection(const ossimFilename& filename, + ossim_uint32 entryIdx)const; + + /** + * @param name This would be a projection name. + * + * @return ossimProjection* on success or NULL if not handled. + */ + virtual ossimProjection* createProjection(const ossimString& name)const; + + + /** + * @param kwl Keyword list to instantiate projection from. + * + * @return ossimProjection* on success or NULL if not handled. + */ + virtual ossimProjection* createProjection(const ossimKeywordlist& kwl, + const char* prefix = 0)const; + /** + * Creates an object given a type name. + * + * @return ossimObject on success or NULL if not handled. + */ + virtual ossimObject* createObject(const ossimString& typeName)const; + + /** + * Creates and object given a keyword list. + * + * @return ossimObject on success or NULL if not handled. + */ + virtual ossimObject* createObject(const ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * This should return the type name of all objects in all factories. + * This is the name used to construct the objects dynamially and this + * name must be unique. + * + * @param typeList List to append names to. + */ + virtual void getTypeNameList(std::vector<ossimString>& typeList)const; + + /** + * @note Being depricated with getTypeNameList found in ossimObjectFactory + */ + virtual list<ossimString> getList()const; + +private: + /** + * @param hdr The nitf image header. + * + * @param coordianteSystem The coordinate system as a string. + * + * @param geographicLocation This should contain the four corner strings. + * + * @param filename The nitf file name. + * + * @return Either an ossimEquDistCylProjection or ossimBilinearProjection + * depending upon if the corner points line up evenly. + */ + ossimProjection* makeGeographic(const ossimNitfImageHeader* hdr, + const ossimString& coordinateSysetm, + const ossimFilename& filename) const; + + /** + * @param hdr The nitf image header. + * + * @param coordianteSystem The coordinate system as a string. + * + * @param geographicLocation This should contain the four corner strings. + * + * @param filename The nitf file name. + * + * @return ossimUtmProjection + */ + ossimProjection* makeUtm(const ossimNitfImageHeader* hdr, + const ossimString& coordinateSysetm, + const ossimFilename& filename) const; + + /** + * @param hdr The nitf image header. + * + * @param gpts Four geographic corner points. + * + * @return ossimEquDistCylProjection* or null if a problem is found. + */ + ossimProjection* makeEuiDistant(const ossimNitfImageHeader* hdr, + const std::vector<ossimGpt>& gpts) const; + + /** + * @return ossimBilinearProjection* or null if a problem is found. + */ + ossimProjection* makeBilinear(const ossimNitfImageHeader* hdr, + const std::vector<ossimGpt>& gpts) const; + + /** + * Parses geographic stream. This will initialize the vector of ossimGpt's + * with the four corners. If the string geographicLocation is not the + * correct size the vector will be cleared. + * + * @param geographicLocation String containing corners. + * + * @param gpts Vector to initialize. + */ + void parseGeographicString(const ossimString& geographicLocation, + std::vector<ossimGpt>& gpts) const; + + /** + * Parses Decimal degree stream. This will initialize the vector of ossimGpt's + * with the four corners. If the string geographicLocation is not the + * correct size the vector will be cleared. + * + * @param geographicLocation String containing corners. + * + * @param gpts Vector to initialize. + */ + void parseDecimalDegreesString(const ossimString& geographicLocation, + std::vector<ossimGpt>& gpts) const; + + void parseUtmString(const ossimString& utmLocation, + ossim_uint32& zone, + std::vector<ossimDpt>& utmPoints)const; + /** + * Computes the scale in decimal degrees with scale.x being longitude, + * y being latitude. + * + * @param hdr The nitf image header from the currently opened nitf file. + * + * @param gpts Four geographic corner points. + * + * @param scale Scale to initialize. + * + * @note scale will be set to nan's on failure. + */ + void computeScaleInDecimalDegrees(const ossimNitfImageHeader* hdr, + const std::vector<ossimGpt>& gpts, + ossimDpt& scale) const; + + /** + * Computes the scale in meters with scale.x being easting, + * y being northing. + * + * @param hdr The nitf image header from the currently opened nitf file. + * + * @param dpts Four utm corner points. + * + * @param scale Scale to initialize. + * + * @note scale will be set to nan's on failure. + */ + void ossimNitfProjectionFactory::computeScaleInMeters( + const ossimNitfImageHeader* hdr, + const std::vector<ossimDpt>& dpts, + ossimDpt& scale) const; + + /** + * @return true if corner points are parallel to each other, else false. + */ + bool isSkewed(const std::vector<ossimGpt>& gpts) const; + + /** + * @return true if corner points are parallel to each other, else false. + */ + bool isSkewed(const std::vector<ossimDpt>& gpts) const; + + /** + * @param hdr The nitf image header from the currently opened nitf file. + * + * @param gpts Ground points to initialize from BLOCKA tag. This should + * be an empty vector. + * + * @param filename The nitf file name. + * + * @return true if BLOCKA tag was parsed. + */ + bool getBlockaPoints(const ossimNitfImageHeader* hdr, + std::vector<ossimGpt>& gpts, + const ossimFilename& filename) const; + + /** + * Private constructor, users must go through instance() method. + */ + ossimNitfProjectionFactory(); + + /** + * Private copy constructor to hide from use. + */ + ossimNitfProjectionFactory(const ossimNitfProjectionFactory& obj); + + /** + * Private operator = to hide from use. + */ + ossimNitfProjectionFactory& operator=(const ossimNitfProjectionFactory& rhs); + + static ossimNitfProjectionFactory* theInstance; + + bool isNitf(const ossimFilename& filename)const; +}; + +#endif /* End of "#ifndef ossimNitfProjectionFactory_HEADER" */ diff --git a/Utilities/OSSIM/ossim_core/projections/factory/ossimPcsCodeProjectionFactory.cpp b/Utilities/OSSIM/ossim_core/projections/factory/ossimPcsCodeProjectionFactory.cpp new file mode 100644 index 0000000000..6b352caafb --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/factory/ossimPcsCodeProjectionFactory.cpp @@ -0,0 +1,327 @@ +//---------------------------------------------------------------------------- +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Class definition of projection factory to return projection from +// a Projection Coordinate System (PCS) code. +// +// For current documentation on pcs codes see: +// +// http://www.remotesensing.org/geotiff/spec/geotiff6.html#6.3.3.1 +// +//---------------------------------------------------------------------------- +// $Id: ossimPcsCodeProjectionFactory.cpp,v 1.1 2005/11/25 20:30:48 dburken Exp $ + +#include <projections/factory/ossimPcsCodeProjectionFactory.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimFilename.h> +#include <base/common/ossimKeywordNames.h> +#include <base/common/ossimTrace.h> +#include <base/context/ossimNotifyContext.h> +#include <projections/map_projections/ossimUtmProjection.h> + + +static const ossimTrace +traceDebug(ossimString("ossimPcsCodeProjectionFactory:debug")); + +#if OSSIM_ID_ENABLED +static const char OSSIM_ID[] = "$Id: ossimPcsCodeProjectionFactory.cpp,v 1.1 2005/11/25 20:30:48 dburken Exp $"; +#endif + +ossimPcsCodeProjectionFactory* ossimPcsCodeProjectionFactory::theInstance = 0; + +ossimPcsCodeProjectionFactory::ossimPcsCodeProjectionFactory() +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimPcsCodeProjectionFactory::ossimPcsCodeProjectionFactory" + << " entered..." << std::endl; +#if OSSIM_ID_ENABLED + ossimNotify(ossimNotifyLevel_DEBUG) + << "OSSIM_ID: " << OSSIM_ID << std::endl; +#endif + } +} + +ossimPcsCodeProjectionFactory* ossimPcsCodeProjectionFactory::instance() +{ + if(!theInstance) + { + theInstance = new ossimPcsCodeProjectionFactory; + } + + return (ossimPcsCodeProjectionFactory*) theInstance; +} + +ossimProjection* +ossimPcsCodeProjectionFactory::createProjection(const ossimFilename& filename, + ossim_uint32 entryIdx)const +{ + if(!filename.exists()) + { + return NULL; + } + + // Check for external geometry file. + ossimProjection* proj = createProjectionFromGeometryFile(filename, + entryIdx); + if (proj) + { + return proj; + } + + ossimFilename geomFile = filename; + geomFile = geomFile.setExtension("geom"); + if(!geomFile.exists()) + { + return NULL; + } + + ossimKeywordlist kwl; + if(kwl.addFile(geomFile)) + { + return createProjection(kwl); + } + + return NULL; +} + +ossimProjection* ossimPcsCodeProjectionFactory::createProjection( + const ossimKeywordlist &keywordList, const char *prefix) const +{ + ossimProjection *result=NULL; + + const char *lookup = keywordList.find(prefix, + ossimKeywordNames::PCS_CODE_KW); + if(lookup) + { + result = createProjection(ossimString(lookup).trim()); + if(result) + { + result->loadState(keywordList, prefix); + } + } + return result; +} + +ossimProjection* ossimPcsCodeProjectionFactory::createProjection( + const ossimString &name) const +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimPcsCodeProjectionFactory::createProjection entered..." + << "\nname: " << name << endl; + } + + ossimProjection* result = NULL; + + ossim_int32 code = name.toInt32(); + + //--- + // Divide the code by 100. Then check for a known type. If it is a + // utm projection the last two digits represent the zone. + //--- + int type = code/100; + int zone = code%100; + + switch (type) + { + case 322: + { + //--- + // utm, WGS72 (WGD), northern hemisphere + // All 60 zones handled. + //--- + if ( (zone > 0) && (zone < 61) ) + { + ossimUtmProjection* proj = + new ossimUtmProjection(*(ossimDatumFactory::instance()-> + wgs72()->ellipsoid())); + proj->setDatum(ossimDatumFactory::instance()-> + wgs72()); + proj->setZone(zone); + proj->setHemisphere('N'); + result = proj; + return result; + } + break; + } + + case 323: + { + //--- + // utm, WGS72 (WGD), southern hemisphere + // All 60 zones handled. + //--- + if ( (zone > 0) && (zone < 61) ) + { + ossimUtmProjection* proj = + new ossimUtmProjection(*(ossimDatumFactory::instance()-> + wgs72()->ellipsoid())); + proj->setDatum(ossimDatumFactory::instance()-> + wgs72()); + proj->setZone(zone); + proj->setHemisphere('S'); + result = proj; + return result; + } + break; + } + + case 326: + { + //--- + // utm, WGS84 (WGE), northern hemisphere + // All 60 zones hadled. + //--- + if ( (zone > 0) && (zone < 61) ) + { + ossimUtmProjection* proj = + new ossimUtmProjection(*(ossimDatumFactory::instance()-> + wgs84()->ellipsoid())); + proj->setDatum(ossimDatumFactory::instance()-> + wgs84()); + proj->setZone(zone); + proj->setHemisphere('N'); + result = proj; + return result; + } + break; + } + + case 327: + { + //--- + // utm, WGS84 (WGE), southern hemisphere + // All 60 zones handled. + //--- + if ( (zone > 0) && (zone < 61) ) + { + ossimUtmProjection* proj = + new ossimUtmProjection(*(ossimDatumFactory::instance()-> + wgs84()->ellipsoid())); + proj->setDatum(ossimDatumFactory::instance()-> + wgs84()); + proj->setZone(zone); + proj->setHemisphere('S'); + result = proj; + return result; + } + break; + } + + case 267: + { + //--- + // utm, "NAS-C", northern hemisphere + // Only UTM NAD27 North zones 3 to 22 are in the 267xx range... + // 26729 through 26803 handled by state plane factory. + //--- + if ( (code > 26702) && (code < 26723) ) + { + ossimUtmProjection* proj = + new ossimUtmProjection(*(ossimDatumFactory::instance()-> + create(ossimString("NAS-C"))-> + ellipsoid())); + proj->setDatum(ossimDatumFactory::instance()-> + create(ossimString("NAS-C"))); + proj->setZone(zone); + proj->setHemisphere('N'); + result = proj; + return result; + } + break; + } + + case 269: + { + //--- + // utm, "NAR-C", northern hemisphere + // Only UTM NAD83 North zones 3 to 23 are in the 269xx + // range... + // 26929 through 26998 handled by state plane factory. + //--- + if ( (code > 26902) && (code < 26924) ) + { + ossimUtmProjection* proj = + new ossimUtmProjection(*(ossimDatumFactory::instance()-> + create(ossimString("NAR-C"))-> + ellipsoid())); + proj->setDatum(ossimDatumFactory::instance()-> + create(ossimString("NAR-C"))); + proj->setZone(zone); + proj->setHemisphere('N'); + result = proj; + return result; + } + break; + } + + case 248: + { + //--- + // Provisional S. American 1956 + // 24818 through 24880 + //--- + if ( (code > 24817) && (code < 24881) ) + { + ossimUtmProjection* proj = + new ossimUtmProjection(*(ossimDatumFactory::instance()-> + create(ossimString("PRB-M"))-> + ellipsoid())); + + proj->setDatum(ossimDatumFactory::instance()-> + create(ossimString("PRB-M"))); + if (zone > 60) + { + proj->setZone(zone - 60); + proj->setHemisphere('S'); + } + else + { + proj->setZone(zone); + proj->setHemisphere('N'); + } + result = proj; + return result; + } + break; + } + + } // End of switch on code. + + return result; +} + +ossimObject* ossimPcsCodeProjectionFactory::createObject( + const ossimString& typeName)const +{ + return createProjection(typeName); +} + +ossimObject* ossimPcsCodeProjectionFactory::createObject( + const ossimKeywordlist& kwl, + const char* prefix)const +{ + return createProjection(kwl, prefix); +} + +void ossimPcsCodeProjectionFactory::getTypeNameList( + std::vector<ossimString>& /* typeList */)const +{ +} + +list<ossimString> ossimPcsCodeProjectionFactory::getList()const +{ + list<ossimString> result; + return result; +} diff --git a/Utilities/OSSIM/ossim_core/projections/factory/ossimPcsCodeProjectionFactory.h b/Utilities/OSSIM/ossim_core/projections/factory/ossimPcsCodeProjectionFactory.h new file mode 100644 index 0000000000..46796e5d6d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/factory/ossimPcsCodeProjectionFactory.h @@ -0,0 +1,84 @@ +//---------------------------------------------------------------------------- +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Class declaration of projection factory to return projection from +// a Projection Coordinate System (PCS) code. +// +// For current documentation on pcs codes see: +// +// http://www.remotesensing.org/geotiff/spec/geotiff6.html#6.3.3.1 +// +//---------------------------------------------------------------------------- +// $Id: ossimPcsCodeProjectionFactory.h,v 1.1 2005/11/25 20:30:48 dburken Exp $ + +#ifndef ossimPcsCodeProjectionFactory_HEADER +#define ossimPcsCodeProjectionFactory_HEADER + +#include <projections/factory/ossimProjectionFactoryBase.h> + +class ossimProjection; +class ossimString; + +class OSSIMDLLEXPORT ossimPcsCodeProjectionFactory : public ossimProjectionFactoryBase +{ +public: + /*! + * METHOD: instance() + * Instantiates singleton instance of this class: + */ + static ossimPcsCodeProjectionFactory* instance(); + + virtual ossimProjection* createProjection(const ossimFilename& filename, + ossim_uint32 entryIdx)const; + /*! + * METHOD: create() + * Attempts to create an instance of the projection specified by name. + * Returns successfully constructed projection or NULL. + */ + + /** + * Creates projection from a pcs code string. + * + * @return ossimProjection* or null if code is not handled. + */ + virtual ossimProjection* createProjection(const ossimString& name)const; + + virtual ossimProjection* createProjection(const ossimKeywordlist& kwl, + const char* prefix = 0)const; + + virtual ossimObject* createObject(const ossimString& typeName)const; + + /*! + * Creates and object given a keyword list. + */ + virtual ossimObject* createObject(const ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * This should return the type name of all objects in all factories. + * This is the name used to construct the objects dynamially and this + * name must be unique. + */ + virtual void getTypeNameList(std::vector<ossimString>& typeList)const; + + /*! + * METHOD: getList() + * Returns list of all projections represented by this factory: + */ + virtual list<ossimString> getList()const; + +protected: + ossimPcsCodeProjectionFactory(); + + static ossimPcsCodeProjectionFactory* theInstance; + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/factory/ossimProjectionFactoryBase.cpp b/Utilities/OSSIM/ossim_core/projections/factory/ossimProjectionFactoryBase.cpp new file mode 100644 index 0000000000..c3822258d6 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/factory/ossimProjectionFactoryBase.cpp @@ -0,0 +1,90 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +//******************************************************************* +// $Id: ossimProjectionFactoryBase.cpp,v 1.3 2004/09/24 17:19:40 dburken Exp $ + +#include <projections/factory/ossimProjectionFactoryBase.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <base/data_types/ossimFilename.h> + +//--- +// Define Trace flags for use within this file: +//--- +#include <base/common/ossimTrace.h> +static ossimTrace traceDebug = ossimTrace("ossimProjectionFactoryBase:debug"); + +RTTI_DEF1(ossimProjectionFactoryBase, "ossimProjectionFactoryBase", ossimObjectFactory); + +ossimProjection* ossimProjectionFactoryBase::createProjectionFromGeometryFile(const ossimFilename& imageFile, ossim_uint32 entryIdx)const +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "ossimProjectionFactoryBase::createProjectionFromGeometryFile " + << "DEBUG:" + << "\nimageFile: " << imageFile + << "\nentryIdx: " << entryIdx + << endl; + } + + // Try to find a geometry file for imageFile. + + ossimFilename geomFile = imageFile; + if (entryIdx == 0) + { + geomFile.setExtension("geom"); + if(geomFile.exists()) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "Found geometry file: " << geomFile + << endl; + } + + ossimKeywordlist kwl; + if(kwl.addFile(geomFile)) + { + return ossimProjectionFactoryRegistry::instance()-> + createProjection(kwl); + } + } + } + + // Look for an indexed geometry file. + geomFile = imageFile.fileNoExtension(); + geomFile += "_e"; + geomFile += ossimString::toString(entryIdx); + geomFile.setExtension("geom"); + if(geomFile.exists()) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "Found geometry file: " << geomFile + << endl; + } + + ossimKeywordlist kwl; + if(kwl.addFile(geomFile)) + { + return ossimProjectionFactoryRegistry::instance()-> + createProjection(kwl); + } + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG: No geometry file found. Returning NULL..." + << endl; + } + + return NULL; +} diff --git a/Utilities/OSSIM/ossim_core/projections/factory/ossimProjectionFactoryBase.h b/Utilities/OSSIM/ossim_core/projections/factory/ossimProjectionFactoryBase.h new file mode 100644 index 0000000000..07f9062939 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/factory/ossimProjectionFactoryBase.h @@ -0,0 +1,78 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +//******************************************************************* +// $Id: ossimProjectionFactoryBase.h,v 1.9 2005/10/28 14:01:03 gpotts Exp $ +#ifndef ossimProjectionFactoryBase_HEADER +#define ossimProjectionFactoryBase_HEADER + +#include <list> +#include <base/data_types/ossimString.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/factory/ossimObjectFactory.h> + +class ossimProjection; + +class OSSIM_DLL ossimProjectionFactoryBase : public ossimObjectFactory +{ +public: + + /** + * takes a filename. This filename can be an image file or + * it can also be a ossim .geom file. It could be other + * forms of geom files as well. The factories job will be to + * determine what parser to use and return a projection if + * successful. + */ + virtual ossimProjection* createProjection(const ossimFilename& filename, + ossim_uint32 entryIdx)const=0; + + /** + * Take a projection type name. + */ + virtual ossimProjection* createProjection(const ossimString& name)const=0; + + /** + * Take a keywordlist. + */ + virtual ossimProjection* createProjection(const ossimKeywordlist& kwl, + const char* prefix)const=0; + + /** + * Being depricated with getTypeNameList found in ossimObjectFactory + */ + virtual std::list<ossimString> getList()const=0; + +protected: + + /** + * This method takes the filename and tries to find an external ".geom" + * file. + * + * If the "entryIndx" is 0 and the "imageFile" is foo.ntf this will + * look for "foo.geom". If that fails it will look for foo_e0.geom. + * + * If the "entryIndx" is 5 and the "imageFile" is foo.ntf this will + * look for foo_e5.geom. + * + * @param imageFile Image file that needs a projection. + * + * @param entryIdx For image files that support multiple images this is + * the zero base index to that image. Images that don't support multiple + * indexes should just pass 0. + * + * @return An ossimProjection* on success or NULL on failure. + */ + ossimProjection* + createProjectionFromGeometryFile(const ossimFilename& imageFile, + ossim_uint32 entryIdx)const; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/factory/ossimProjectionFactoryRegistry.cpp b/Utilities/OSSIM/ossim_core/projections/factory/ossimProjectionFactoryRegistry.cpp new file mode 100644 index 0000000000..3f368f0ca5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/factory/ossimProjectionFactoryRegistry.cpp @@ -0,0 +1,199 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimProjectionFactoryRegistry.cpp,v 1.23 2005/11/25 20:31:35 dburken Exp $ +#include <algorithm> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <projections/factory/ossimProjectionFactoryBase.h> +#include <projections/factory/ossimSrsProjectionFactory.h> +#include <projections/factory/ossimMapProjectionFactory.h> +#include <projections/factory/ossimTiffProjectionFactory.h> +#include <projections/factory/ossimNitfProjectionFactory.h> +#include <projections/factory/ossimPcsCodeProjectionFactory.h> +#include <projections/factory/ossimStatePlaneProjectionFactory.h> +#include <projections/factory/ossimSensorModelFactory.h> +#include <projections/factory/ossimMiscProjectionFactory.h> +#include <projections/ossimProjection.h> +#include <base/factory/ossimObjectFactoryRegistry.h> + +ossimProjectionFactoryRegistry* ossimProjectionFactoryRegistry::theInstance=NULL; + +ossimProjectionFactoryRegistry* ossimProjectionFactoryRegistry::instance() +{ + if(!theInstance) + { + theInstance = new ossimProjectionFactoryRegistry; + theInstance->initializeDefaults(); + ossimObjectFactoryRegistry::instance()->registerFactory(theInstance); + } + + return theInstance; +} + +ossimProjection* +ossimProjectionFactoryRegistry::createProjection(const ossimFilename& name, + ossim_uint32 entryIdx)const +{ + ossimProjection* result = NULL; + vector<ossimProjectionFactoryBase*>::const_iterator factory = theFactoryList.begin(); + + while( (factory != theFactoryList.end()) && !result ) + { + if(*factory) + { + result = (*factory)->createProjection(name, entryIdx); + } + + ++factory; + } + + return result; +} + +ossimProjection* ossimProjectionFactoryRegistry::createProjection(const ossimString& name)const +{ + ossimProjection* result = NULL; + vector<ossimProjectionFactoryBase*>::const_iterator factory = theFactoryList.begin(); + + while((factory != theFactoryList.end()&&! + result)) + { + if(*factory) + { + result = (*factory)->createProjection(name); + } + + ++factory; + } + + return result; +} + +ossimProjection* ossimProjectionFactoryRegistry::createProjection( + const ossimKeywordlist& kwl, const char* prefix)const +{ + ossimProjection* result = NULL; + vector<ossimProjectionFactoryBase*>::const_iterator factory = theFactoryList.begin(); + + while( (factory != theFactoryList.end()) && !result ) + { + if(*factory) + { + result = (*factory)->createProjection(kwl, prefix); + } + + ++factory; + } + + return result; +} + +bool ossimProjectionFactoryRegistry::registerFactory(ossimProjectionFactoryBase* factory) +{ + if(factory&&!findFactory(factory)) + { + theFactoryList.push_back(factory); + return true; + } + + return false; +} + +void ossimProjectionFactoryRegistry::unregisterFactory(ossimProjectionFactoryBase* factory) +{ + std::vector<ossimProjectionFactoryBase*>::iterator iter = std::find(theFactoryList.begin(), + theFactoryList.end(), + factory); + if(iter != theFactoryList.end()) + { + theFactoryList.erase(iter); + } +} + +bool ossimProjectionFactoryRegistry::findFactory(ossimProjectionFactoryBase* factory)const +{ + return (std::find(theFactoryList.begin(), + theFactoryList.end(), + factory)!=theFactoryList.end()); +} + +std::list<ossimString> ossimProjectionFactoryRegistry::getList()const +{ + list<ossimString> result; + vector<ossimProjectionFactoryBase*>::const_iterator factory = theFactoryList.begin(); + + while(factory != theFactoryList.end()) + { + if(*factory) + { + list<ossimString> temp = (*factory)->getList(); + result.insert(result.end(), + temp.begin(), + temp.end()); + } + + ++factory; + } + + return result; + +} + +ossimObject* ossimProjectionFactoryRegistry::createObject(const ossimString& typeName)const +{ + return createProjection(typeName); +} + +ossimObject* ossimProjectionFactoryRegistry::createObject(const ossimKeywordlist& kwl, + const char* prefix)const +{ + return createProjection(kwl, prefix); +} + +void ossimProjectionFactoryRegistry::getTypeNameList(std::vector<ossimString>& typeList)const +{ + vector<ossimString> result; + vector<ossimProjectionFactoryBase*>::const_iterator factory = theFactoryList.begin(); + + while(factory != theFactoryList.end()) + { + if(*factory) + { + result.clear(); + (*factory)->getTypeNameList(result); + typeList.insert(typeList.end(), + result.begin(), + result.end()); + } + + ++factory; + } +} + +void ossimProjectionFactoryRegistry::initializeDefaults() +{ + theInstance->registerFactory(ossimSensorModelFactory::instance()); + theInstance->registerFactory(ossimMapProjectionFactory::instance()); + theInstance->registerFactory(ossimSrsProjectionFactory::instance()); + theInstance->registerFactory(ossimTiffProjectionFactory::instance()); + theInstance->registerFactory(ossimPcsCodeProjectionFactory::instance()); + theInstance->registerFactory(ossimStatePlaneProjectionFactory::instance()); + theInstance->registerFactory(ossimNitfProjectionFactory::instance()); + theInstance->registerFactory(ossimMiscProjectionFactory::instance()); +} + +extern "C" +{ + void* ossimProjectionFactoryRegistryGetInstance() + { + return ossimProjectionFactoryRegistry::instance(); + } + +} diff --git a/Utilities/OSSIM/ossim_core/projections/factory/ossimProjectionFactoryRegistry.h b/Utilities/OSSIM/ossim_core/projections/factory/ossimProjectionFactoryRegistry.h new file mode 100644 index 0000000000..0337b133bd --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/factory/ossimProjectionFactoryRegistry.h @@ -0,0 +1,71 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//************************************************************************* +// $Id: ossimProjectionFactoryRegistry.h,v 1.13 2005/09/08 17:30:52 gpotts Exp $ +#ifndef ossimProjectionFactoryRegistry_HEADER +#define ossimProjectionFactoryRegistry_HEADER +#include <base/data_types/ossimString.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/factory/ossimObjectFactory.h> + +#include <vector> +#include <list> +class ossimProjectionFactoryBase; +class ossimProjection; + +class OSSIMDLLEXPORT ossimProjectionFactoryRegistry : public ossimObjectFactory +{ +public: + static ossimProjectionFactoryRegistry* instance(); + + ossimProjection* createProjection(const ossimFilename& filename, + ossim_uint32 entryIdx)const; + ossimProjection* createProjection(const ossimString& name)const; + ossimProjection* createProjection(const ossimKeywordlist& kwl, + const char* prefix=NULL)const; + + virtual ossimObject* createObject(const ossimString& typeName)const; + + /** + * Creates and object given a keyword list. + */ + virtual ossimObject* createObject(const ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * This should return the type name of all objects in all factories. + * This is the name used to construct the objects dynamially and this + * name must be unique. + */ + virtual void getTypeNameList(std::vector<ossimString>& typeList)const; + + bool registerFactory(ossimProjectionFactoryBase* factory); + void unregisterFactory(ossimProjectionFactoryBase* factory); + bool findFactory(ossimProjectionFactoryBase* factory)const; + + std::list<ossimString> getList()const; + +protected: + ossimProjectionFactoryRegistry(){} + ossimProjectionFactoryRegistry(const ossimProjectionFactoryRegistry& rhs):ossimObjectFactory(rhs){} + void operator = (const ossimProjectionFactoryRegistry&){} + + static ossimProjectionFactoryRegistry* theInstance; + std::vector<ossimProjectionFactoryBase*> theFactoryList; + + void initializeDefaults(); +}; + +extern "C" +{ + OSSIMDLLEXPORT void* ossimProjectionFactoryRegistryGetInstance(); +} + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/factory/ossimProjectionViewControllerFactory.cpp b/Utilities/OSSIM/ossim_core/projections/factory/ossimProjectionViewControllerFactory.cpp new file mode 100644 index 0000000000..f5fdbbb3af --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/factory/ossimProjectionViewControllerFactory.cpp @@ -0,0 +1,90 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimProjectionViewControllerFactory.cpp,v 1.5 2005/09/14 19:23:14 gpotts Exp $ + +#include "ossimProjectionViewControllerFactory.h" +#include "base/factory/ossimObjectFactoryRegistry.h" +#include "projections/ossimMapViewController.h" +#include "base/common/ossimKeywordNames.h" +#include "base/data_types/ossimKeywordlist.h" + +RTTI_DEF1(ossimProjectionViewControllerFactory, "ossimProjectionViewControllerFactory", ossimObjectFactory); + +ossimProjectionViewControllerFactory* ossimProjectionViewControllerFactory::theInstance = NULL; + +ossimProjectionViewControllerFactory* ossimProjectionViewControllerFactory::instance() +{ + if(!theInstance) + { + theInstance = new ossimProjectionViewControllerFactory; + } + + return theInstance; +} + +ossimViewController* ossimProjectionViewControllerFactory::createViewController(const ossimString& name)const +{ + if(name == STATIC_TYPE_NAME(ossimMapViewController)) + { + return new ossimMapViewController; + } + + return (ossimViewController*)NULL; +} + +ossimViewController* ossimProjectionViewControllerFactory::createViewController(const ossimKeywordlist& kwl, + const char* prefix)const +{ + const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + ossimViewController* result = NULL; + if(type) + { + result = createViewController(ossimString(type)); + if(result) + { + if(!result->loadState(kwl, prefix)) + { + delete result; + result = NULL; + } + } + } + + return result; +} + +ossimObject* ossimProjectionViewControllerFactory::createObject(const ossimString& typeName)const +{ + return createViewController(typeName); +} + +ossimObject* ossimProjectionViewControllerFactory::createObject(const ossimKeywordlist& kwl, + const char* prefix)const +{ + return createViewController(kwl, prefix); +} + +void ossimProjectionViewControllerFactory::getTypeNameList(std::vector<ossimString>& typeList)const +{ + typeList.push_back("ossimMapViewController"); +} diff --git a/Utilities/OSSIM/ossim_core/projections/factory/ossimProjectionViewControllerFactory.h b/Utilities/OSSIM/ossim_core/projections/factory/ossimProjectionViewControllerFactory.h new file mode 100644 index 0000000000..8f0114e12c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/factory/ossimProjectionViewControllerFactory.h @@ -0,0 +1,54 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// Description: +// +//************************************************************************* +// $Id: ossimProjectionViewControllerFactory.h,v 1.2 2005/09/14 19:23:30 gpotts Exp $ +#ifndef ossimProjectionViewControllerFactory_HEADER +#define ossimProjectionViewControllerFactory_HEADER +#include "base/factory/ossimBaseObjectFactory.h" +#include "base/data_types/ossimString.h" + +class ossimViewController; + +class ossimProjectionViewControllerFactory : public ossimObjectFactory +{ +public: + static ossimProjectionViewControllerFactory* instance(); + + virtual ossimViewController* createViewController(const ossimString& name)const; + virtual ossimViewController* createViewController(const ossimKeywordlist& kwl, + const char* prefix)const; + + virtual ossimObject* createObject(const ossimString& typeName)const; + virtual ossimObject* createObject(const ossimKeywordlist& kwl, + const char* prefix)const; + + virtual void getTypeNameList(std::vector<ossimString>& typeList)const; + +protected: + ossimProjectionViewControllerFactory(){} + ossimProjectionViewControllerFactory(const ossimProjectionViewControllerFactory& rhs ){} + + static ossimProjectionViewControllerFactory* theInstance; +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/factory/ossimSensorModelFactory.cpp b/Utilities/OSSIM/ossim_core/projections/factory/ossimSensorModelFactory.cpp new file mode 100644 index 0000000000..9be8a6e67f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/factory/ossimSensorModelFactory.cpp @@ -0,0 +1,548 @@ +//***************************************************************************** +// FILE: ossimSensorModelFactory.cc +// +// License: See LICENSE.txt file in the top level directory. +// +// AUTHOR: Oscar Kramer +// +// DESCRIPTION: +// Contains implementation of class ossimSensorModelFactory +// +//***************************************************************************** +// $Id: ossimSensorModelFactory.cpp,v 1.43 2005/11/29 18:36:58 dburken Exp $ +#include <fstream> +#include <algorithm> +#include <projections/factory/ossimSensorModelFactory.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimDirectory.h> +#include <base/common/ossimKeywordNames.h> +#include <base/context/ossimNotifyContext.h> + +//*** +// Define Trace flags for use within this file: +//*** +#include <base/common/ossimTrace.h> +static ossimTrace traceExec = ossimTrace("ossimSensorModelFactory:exec"); +static ossimTrace traceDebug = ossimTrace("ossimSensorModelFactory:debug"); + +//*** +// Note to programmer: To add a new model, search this file for "ADD_MODEL" +// to locate places requiring editing. Functional example below... +// +// ADD_MODEL: Include all sensor model headers here: +//*** +#include <projections/sensor_modeling/coarse_grid/ossimCoarseGridModel.h> +#include <projections/sensor_modeling/rpc/ossimRpcModel.h> +#include <projections/sensor_modeling/rpc/ossimIkonosRpcModel.h> +#include <projections/sensor_modeling/rpc/ossimNitfRpcModel.h> +#include <projections/sensor_modeling/rpc/ossimQuickbirdRpcModel.h> +#include <projections/sensor_modeling/landsat/ossimLandSatModel.h> +#include <projections/sensor_modeling/spot/ossimSpot5Model.h> +#include <support_data/spot/ossimSpotDimapSupportData.h> +#include <projections/sensor_modeling/ossimNitfMapModel.h> +#include <projections/sensor_modeling/fcsi/ossimFcsiModel.h> +#include <projections/sensor_modeling/fcsi/ossimApplanixUtmModel.h> +#include <projections/sensor_modeling/fcsi/ossimApplanixEcefModel.h> +#include <support_data/ff_l7/ossimFfL7.h> +#include <support_data/ff_l7/ossimFfL5.h> + +//*** +// ADD_MODEL: List names of all sensor models produced by this factory: +//*** +//const char* MY_NEW_MODEL = "myNewModel"; +// const char* OCG_MODEL = "ossimCoarseGridModel"; +// const char* RPC_MODEL = "ossimRpcModel"; +// const char* IKONOS_RPC_MODEL = "ossimIkonosRpcModel"; +// const char* NITF_RPC_MODEL = "ossimNitfRpcModel"; +// const char* LANDSAT_MODEL = "ossimLandSatModel"; +// const char* NITF_MAP_MODEL = "ossimNitfMapModel"; +// const char* FCSI_MODEL = "ossimFcsiModel"; +// const char* EMERGE_FCSI_MODEL= "ossimEmergeFcsiModel"; + +ossimSensorModelFactory* ossimSensorModelFactory::theInstance = 0; + +//***************************************************************************** +// STATIC METHOD: ossimSensorModelFactory::instance() +// +//***************************************************************************** +ossimSensorModelFactory* ossimSensorModelFactory::instance() +{ + if(!theInstance) + { + theInstance = new ossimSensorModelFactory; + } + + return (ossimSensorModelFactory*) theInstance; +} + +//***************************************************************************** +// METHOD: ossimSensorModelFactory::create(kwl, prefix) +//***************************************************************************** +ossimProjection* ossimSensorModelFactory::createProjection(const ossimKeywordlist &keywordList, + const char *prefix) const +{ + ossimProjection *result=NULL; + + // + // Permit specification of geometry file name in lieu of type: + // + const char* value = keywordList.find(prefix, ossimKeywordNames::GEOM_FILE_KW); + if (value) + { + result = createProjection(ossimFilename(value), 0); + } + // + // Search for occurence of "type" keyword: + // + else + { + value = keywordList.find(prefix, ossimKeywordNames::TYPE_KW); + if(value) + { + result = createProjection(ossimString(value)); + if(result) + { + if(!result->loadState(keywordList, prefix)) + { + delete result; + result = NULL; + } + } + } + } + + return result; +} + +//***************************************************************************** +// METHOD: +// +//***************************************************************************** +ossimProjection* +ossimSensorModelFactory::createProjection(const ossimString &name) const +{ + //*** + // Name should represent the model type: + //*** + if(name == STATIC_TYPE_NAME(ossimCoarseGridModel)) + { + return new ossimCoarseGridModel; + } + + if (name == STATIC_TYPE_NAME(ossimRpcModel)) + { + return new ossimRpcModel; + } + + if(name == STATIC_TYPE_NAME(ossimLandSatModel)) + { + return new ossimLandSatModel; + } + + if(name == STATIC_TYPE_NAME(ossimNitfMapModel)) + { + return new ossimNitfMapModel; + } + + if(name == STATIC_TYPE_NAME(ossimQuickbirdRpcModel)) + { + return new ossimQuickbirdRpcModel; + } + + if(name == STATIC_TYPE_NAME(ossimNitfRpcModel)) + { + return new ossimNitfRpcModel; + } + if(name == STATIC_TYPE_NAME(ossimFcsiModel)) + { + return new ossimFcsiModel; + } + if(name == STATIC_TYPE_NAME(ossimApplanixUtmModel)) + { + return new ossimApplanixUtmModel; + } + if(name == STATIC_TYPE_NAME(ossimApplanixEcefModel)) + { + return new ossimApplanixEcefModel; + } + + if(name == STATIC_TYPE_NAME(ossimSpot5Model)) + { + return new ossimSpot5Model; + } + + //*** + // ADD_MODEL: (Please leave this comment for the next programmer) + //*** +// if(name == MY_NEW_MODEL) +// return new myNewModel; + + return NULL; +} + + +//***************************************************************************** +// METHOD: ossimSensorModelFactory::getList() +// +//***************************************************************************** +list<ossimString> ossimSensorModelFactory::getList() const +{ + list<ossimString> result; + + //*** + // Place the name of each model produced in the list: + //*** + result.push_back(STATIC_TYPE_NAME(ossimCoarseGridModel)); + result.push_back(STATIC_TYPE_NAME(ossimRpcModel)); + result.push_back(STATIC_TYPE_NAME(ossimIkonosRpcModel)); + result.push_back(STATIC_TYPE_NAME(ossimNitfRpcModel)); + result.push_back(STATIC_TYPE_NAME(ossimQuickbirdRpcModel)); + result.push_back(STATIC_TYPE_NAME(ossimLandSatModel)); + result.push_back(STATIC_TYPE_NAME(ossimNitfMapModel)); + result.push_back(STATIC_TYPE_NAME(ossimFcsiModel)); + result.push_back(STATIC_TYPE_NAME(ossimApplanixUtmModel)); + result.push_back(STATIC_TYPE_NAME(ossimApplanixEcefModel)); + result.push_back(STATIC_TYPE_NAME(ossimSpot5Model)); + + //*** + // ADD_MODEL: Please leave this comment for the next programmer. Add above. + //*** + //result.push_back(ossimString(MY_NEW_MODEL)); + + return result; +} + +//***************************************************************************** +// METHOD +//***************************************************************************** +ossimObject* +ossimSensorModelFactory::createObject(const ossimString& typeName)const +{ + return createProjection(typeName); +} + +//***************************************************************************** +// METHOD +//***************************************************************************** +ossimObject* +ossimSensorModelFactory::createObject(const ossimKeywordlist& kwl, + const char* prefix)const +{ + return createProjection(kwl, prefix); +} + +//***************************************************************************** +// METHOD +//***************************************************************************** +void +ossimSensorModelFactory::getTypeNameList(std::vector<ossimString>& typeList) + const +{ + typeList.push_back(STATIC_TYPE_NAME(ossimApplanixEcefModel)); + typeList.push_back(STATIC_TYPE_NAME(ossimApplanixUtmModel)); + typeList.push_back(STATIC_TYPE_NAME(ossimCoarseGridModel)); + typeList.push_back(STATIC_TYPE_NAME(ossimRpcModel)); + typeList.push_back(STATIC_TYPE_NAME(ossimIkonosRpcModel)); + typeList.push_back(STATIC_TYPE_NAME(ossimQuickbirdRpcModel)); + typeList.push_back(STATIC_TYPE_NAME(ossimNitfRpcModel)); + typeList.push_back(STATIC_TYPE_NAME(ossimLandSatModel)); + typeList.push_back(STATIC_TYPE_NAME(ossimNitfMapModel)); + typeList.push_back(STATIC_TYPE_NAME(ossimFcsiModel)); + typeList.push_back(STATIC_TYPE_NAME(ossimSpot5Model)); + + //*** + // ADD_MODEL: Please leave this comment for the next programmer. Add above. + //*** + //typeList.push_back(ossimString(MY_NEW_MODEL)); + +} + +ossimProjection* ossimSensorModelFactory::createProjection(const ossimFilename& filename, + ossim_uint32 entryIdx) const +{ + ossimKeywordlist kwl; + ossimProjection* model = 0; + + ossimFilename geomFile = filename; + geomFile = geomFile.setExtension("geom"); + + if(geomFile.exists()&& + kwl.addFile(filename.c_str())) + { + ossimFilename coarseGrid; + + const char* type = kwl.find(ossimKeywordNames::TYPE_KW); + if(type) + { + if(ossimString(type) == ossimString(STATIC_TYPE_NAME(ossimCoarseGridModel))) + { + findCoarseGrid(coarseGrid, + filename); + + if(coarseGrid.exists() &&(coarseGrid != "")) + { + kwl.add("grid_file_name", + coarseGrid.c_str(), + true); + model = new ossimCoarseGridModel(kwl); + if(!model->getErrorStatus()) + { + return model; + } + } + } + } + kwl.clear(); + } + + // See if there is an external geomtry. + ossimProjection* proj = createProjectionFromGeometryFile(filename, + entryIdx); + if (proj) + { + return proj; + } + + if(model) + { + delete model; + model = 0; + } + // first check for override + // + if(geomFile.exists()&&kwl.addFile(geomFile.c_str())) + { + model = createProjection(kwl); + } + if(model) + { + return model; + } + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimSensorModelFactory::createProjection: Testing ossimCoarsGridModel" << std::endl; + } + + ifstream input(geomFile.c_str()); + char ecgTest[4]; + input.read((char*)ecgTest, 3); + ecgTest[3] = '\0'; + input.close(); + if(ossimString(ecgTest) == "eCG") + { + ossimKeywordlist kwlTemp; + kwlTemp.add("type", + "ossimCoarseGridModel", + true); + kwlTemp.add("geom_file", + geomFile.c_str(), + true); + return createProjection(kwlTemp); + } + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimSensorModelFactory::createProjection: testing ossimRpcModel" << std::endl; + } + + //--- + // Test for quick bird rpc. Could be either a tiff or nitf so not wrapped + // around "isNitf()" anymore. + //--- + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimSensorModelFactory::createProjection: " + << "testing ossimQuickbirdRpcModel" + << std::endl; + } + + ossimQuickbirdRpcModel* qbModel = new ossimQuickbirdRpcModel; + if(qbModel->parseFile(filename)) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimSensorModelFactory::createProjection: " + << "returning ossimQuickbirdRpcModel" << std::endl; + } + model = qbModel; + return model; + } + else + { + delete qbModel; + qbModel = NULL; + } + + if(isNitf(filename)) + { + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimSensorModelFactory::createProjection: " + << " testing ossimNitfRpcModel" << std::endl; + } + + model = new ossimNitfRpcModel(filename); // filename = NITF_file + if(!model->getErrorStatus()) + { + return model; + } + delete model; + model = 0; + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimSensorModelFactory::createProjection: testing ossimIkinosRpcModel" << std::endl; + } + + model = new ossimIkonosRpcModel(filename); + if(!model->getErrorStatus()) + { + return model; + } + delete model; + model = 0; + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimSensorModelFactory::createProjection: testing ossimNitfMapModel" << std::endl; + } + + model = new ossimNitfMapModel(filename); // filename = NITF_file + if(!model->getErrorStatus()) + { + return model; + } + delete model; + model = 0; + } + else if(isLandsat(filename)) + { + model = new ossimLandSatModel(filename); + if(!model->getErrorStatus()) + return model; + delete model; + model = 0; + } + + ossimFilename spot5Test = geomFile; + + + if(!spot5Test.exists()) + { + spot5Test = geomFile.path(); + spot5Test = spot5Test.dirCat(ossimFilename("metadata.dim")); + } + if(spot5Test.exists()) + { + ossimSpotDimapSupportData *meta = new ossimSpotDimapSupportData; + if(meta->loadXmlFile(spot5Test)) + { + model = new ossimSpot5Model(meta); + if(!model->getErrorStatus()) + { + return model; + } + delete model; + model = 0; + } + else + { + delete meta; + meta = 0; + } + } + + model = new ossimCoarseGridModel(geomFile); + if(model) + { + if(!model->getErrorStatus()) + return model; + delete model; + model = 0; + } + return model; +} + +bool ossimSensorModelFactory::isNitf(const ossimFilename& filename)const +{ + std::ifstream in(filename.c_str(), ios::in|ios::binary); + + if(in) + { + char nitfFile[4]; + in.read((char*)nitfFile, 4); + + return (ossimString(nitfFile, + nitfFile+4) == "NITF"); + } + + return false; +} + +bool ossimSensorModelFactory::isLandsat(const ossimFilename& filename)const +{ + ossimFilename temp(filename); + temp.downcase(); + ossimFfL7* ff_headerp = 0; + if (temp.contains("header.dat")) + { + ff_headerp = new ossimFfL5(filename); + } else { + ff_headerp = new ossimFfL7(filename); + } + bool r = !(ff_headerp->getErrorStatus()); + + delete ff_headerp; + return r; +} + +void ossimSensorModelFactory::findCoarseGrid(ossimFilename& result, + const ossimFilename& geomFile)const +{ + result = geomFile; + result.setFile(result.fileNoExtension()+"_ocg"); + result.setExtension("dat"); + + if(!result.exists()) + { + result = geomFile; + result.setExtension("dat"); + } + + // let's find a .dat file in the current directory + // + if(!result.exists()) + { + result = ""; + ossimDirectory directoryList(geomFile.path()); + ossimFilename file; + if(directoryList.getFirst(file, + ossimDirectory::OSSIM_DIR_FILES)) + { + ossimString testString = "OSSIM_DBL_GRID"; + char tempBuf[14]; + do + { + if(file.ext().downcase() == "dat") + { + ifstream in(file); + if(in) + { + in.read((char*)tempBuf, 14); + in.close(); + if(ossimString(tempBuf, tempBuf+14) == testString) + { + result = file; + } + } + + } + }while((directoryList.getNext(file))&&(result == "")); + } + // try to find it + } +} + diff --git a/Utilities/OSSIM/ossim_core/projections/factory/ossimSensorModelFactory.h b/Utilities/OSSIM/ossim_core/projections/factory/ossimSensorModelFactory.h new file mode 100644 index 0000000000..404a2b1881 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/factory/ossimSensorModelFactory.h @@ -0,0 +1,73 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Oscar Kramer +// +// Description: Factory for all ossim sensor models. +// +//******************************************************************* +// $Id: ossimSensorModelFactory.h,v 1.7 2004/09/24 17:19:40 dburken Exp $ +#ifndef ossimSensorModelFactory_HEADER +#define ossimSensorModelFactory_HEADER +#include "ossimProjectionFactoryBase.h" + +class ossimProjection; +class ossimString; +class ossimFilename; + +class ossimSensorModelFactory : public ossimProjectionFactoryBase +{ +public: + /*! + * METHOD: instance() + * For accessing static instance of concrete factory. + */ + static ossimSensorModelFactory* instance(); + + virtual ossimProjection* createProjection(const ossimFilename& filename, + ossim_uint32 entryIdx)const; + /*! + * METHOD: create() + * Attempts to create an instance of the Product given a Specifier or + * keywordlist. Returns successfully constructed product or NULL. + */ + virtual ossimProjection* createProjection(const ossimString& spec) const; + virtual ossimProjection* createProjection(const ossimKeywordlist& kwl, + const char* prefix = 0) const; + + virtual ossimObject* createObject(const ossimString& typeName)const; + + /*! + * Creates and object given a keyword list. + */ + virtual ossimObject* createObject(const ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * This should return the type name of all objects in all factories. + * This is the name used to construct the objects dynamially and this + * name must be unique. + */ + virtual void getTypeNameList(std::vector<ossimString>& typeList)const; + + /*! + * METHOD: getList() + * Returns name list of all products represented by this factory. + */ + virtual std::list<ossimString> getList() const; + +protected: + ossimSensorModelFactory() {} + + static ossimSensorModelFactory* theInstance; + bool isNitf(const ossimFilename& filename)const; + bool isLandsat(const ossimFilename& filename)const; + void findCoarseGrid(ossimFilename& result, + const ossimFilename& geomFile)const; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/factory/ossimSrsProjectionFactory.cpp b/Utilities/OSSIM/ossim_core/projections/factory/ossimSrsProjectionFactory.cpp new file mode 100644 index 0000000000..f30de560e7 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/factory/ossimSrsProjectionFactory.cpp @@ -0,0 +1,159 @@ +//***************************************************************************** +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// DESCRIPTION: +// Contains implementation of class ossimMapProjectionFactory +// +//***************************************************************************** +// $Id: ossimSrsProjectionFactory.cpp,v 1.2 2005/09/08 17:36:22 gpotts Exp $ +#include <sstream> +#include "ossimSrsProjectionFactory.h" +#include <base/common/ossimKeywordNames.h> +#include <projections/map_projections/ossimUtmProjection.h> +#include <projections/map_projections/ossimEquDistCylProjection.h> +#include <projections/map_projections/ossimEquDistCylProjection.h> +#include <projections/map_projections/ossimTransMercatorProjection.h> +#include <projections/map_projections/ossimOrthoGraphicProjection.h> + +ossimSrsProjectionFactory* ossimSrsProjectionFactory::theInstance = 0; + +ossimSrsProjectionFactory* ossimSrsProjectionFactory::instance() +{ + if(!theInstance) + { + theInstance = new ossimSrsProjectionFactory; + } + + return (ossimSrsProjectionFactory*) theInstance; +} + +ossimProjection* ossimSrsProjectionFactory::createProjection(const ossimFilename& filename, + ossim_uint32 entryIdx)const +{ + return 0; +} + +ossimProjection* ossimSrsProjectionFactory::createProjection(const ossimKeywordlist &keywordList, + const char *prefix) const +{ + const char *lookup = keywordList.find(prefix, ossimKeywordNames::TYPE_KW); + + if(lookup) + { + ossimProjection* proj = createProjection(ossimString(lookup)); + if(proj) + { + proj->loadState(keywordList, prefix); + return proj; + } + } + + return 0; +} + +ossimProjection* ossimSrsProjectionFactory::createProjection(const ossimString &name) const +{ + ossimString tempName = name; + tempName = tempName.trim(); + tempName = tempName.upcase(); + if(tempName.contains("AUTO")) + { + ossimString projId; + ossimString projUnits; + ossimString projOriginLon; + ossimString projOriginLat; + tempName = tempName.substitute("AUTO:", + ""); + tempName = tempName.substitute(",", + " ", + true); + std::istringstream in(tempName); + in >> projId >> projUnits >> projOriginLon >> projOriginLat; + + ossimGpt origin(projOriginLat.toDouble(), + projOriginLon.toDouble()); + + switch(projId.toUInt32()) + { + case 42001: + { + ossimUtmProjection* utm = new ossimUtmProjection; + utm->setZone(origin); + utm->setOrigin(origin); + utm->update(); + return utm; + } + case 42002: + { + ossimTransMercatorProjection* transMerc = new ossimTransMercatorProjection; + + transMerc->setFalseNorthing(origin.latd()>=0.0?0.0:10000000.0); + transMerc->setOrigin(ossimGpt(0.0, origin.lond())); + transMerc->setScaleFactor(.9996); + transMerc->update(); + return transMerc; + } + case 42003: + { + ossimOrthoGraphicProjection* ortho = new ossimOrthoGraphicProjection; + ortho->setOrigin(origin); + ortho->update(); + return ortho; + } + case 42004: + { + ossimEquDistCylProjection* geographic = new ossimEquDistCylProjection; + geographic->setOrigin(origin); + geographic->update(); + return geographic; + } + default: + { + return 0; + } + } + } + else if(tempName.contains("EPSG")) + { + tempName = tempName.substitute("EPSG:", ""); + switch(tempName.toUInt32()) + { + case 4326: + { + return new ossimEquDistCylProjection; + } + default: + { + return 0; + } + } + } + + return 0; +} + +ossimObject* ossimSrsProjectionFactory::createObject(const ossimString& typeName)const +{ + return createProjection(typeName); +} + +ossimObject* ossimSrsProjectionFactory::createObject(const ossimKeywordlist& kwl, + const char* prefix)const +{ + return createProjection(kwl, prefix); +} + +void ossimSrsProjectionFactory::getTypeNameList(std::vector<ossimString>& typeList)const +{ + +} + +list<ossimString> ossimSrsProjectionFactory::getList()const +{ + list<ossimString> result; + + + return result; +} diff --git a/Utilities/OSSIM/ossim_core/projections/factory/ossimSrsProjectionFactory.h b/Utilities/OSSIM/ossim_core/projections/factory/ossimSrsProjectionFactory.h new file mode 100644 index 0000000000..480287c7c1 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/factory/ossimSrsProjectionFactory.h @@ -0,0 +1,68 @@ +//******************************************************************* +// Copyright (C) 2005 Garrett Potts +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimSrsProjectionFactory.h,v 1.1 2005/09/08 16:49:27 gpotts Exp $ + +#ifndef ossimSrsProjectionFactory_HEADER +#define ossimSrsProjectionFactory_HEADER + +#include "ossimProjectionFactoryBase.h" + +class ossimProjection; +class ossimString; + +class OSSIMDLLEXPORT ossimSrsProjectionFactory : public ossimProjectionFactoryBase +{ +public: + /*! + * METHOD: instance() + * Instantiates singleton instance of this class: + */ + static ossimSrsProjectionFactory* instance(); + + virtual ossimProjection* createProjection(const ossimFilename& filename, + ossim_uint32 entryIdx)const; + /*! + * METHOD: create() + * Attempts to create an instance of the projection specified by name. + * Returns successfully constructed projection or NULL. + */ + virtual ossimProjection* createProjection(const ossimString& name)const; + virtual ossimProjection* createProjection(const ossimKeywordlist& kwl, + const char* prefix = 0)const; + + virtual ossimObject* createObject(const ossimString& typeName)const; + + /*! + * Creates and object given a keyword list. + */ + virtual ossimObject* createObject(const ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * This should return the type name of all objects in all factories. + * This is the name used to construct the objects dynamially and this + * name must be unique. + */ + virtual void getTypeNameList(std::vector<ossimString>& typeList)const; + + /*! + * METHOD: getList() + * Returns list of all projections represented by this factory: + */ + virtual list<ossimString> getList()const; + +protected: + ossimSrsProjectionFactory() {} + static ossimSrsProjectionFactory* theInstance; + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/factory/ossimStatePlaneProjectionFactory.cpp b/Utilities/OSSIM/ossim_core/projections/factory/ossimStatePlaneProjectionFactory.cpp new file mode 100644 index 0000000000..417bf92fb6 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/factory/ossimStatePlaneProjectionFactory.cpp @@ -0,0 +1,854 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +//******************************************************************* +// $Id: ossimStatePlaneProjectionFactory.cpp,v 1.15 2005/03/30 17:12:24 dburken Exp $ +#include "ossimStatePlaneProjectionFactory.h" +#include "projections/ossimStatePlaneProjectionInfo.h" +#include "projections/factory/ossimMapProjectionFactory.h" +#include "base/common/ossimKeywordNames.h" +#include "base/data_types/ossimFilename.h" +#include "projections/ossimProjection.h" +using namespace std; + +ossimStatePlaneProjectionFactory* ossimStatePlaneProjectionFactory::theInstance = NULL; + +ossimStatePlaneProjectionFactory::~ossimStatePlaneProjectionFactory() +{ + theInstance = NULL; +} + +ossimStatePlaneProjectionFactory* ossimStatePlaneProjectionFactory::instance() +{ + if(!theInstance) + { + theInstance = new ossimStatePlaneProjectionFactory; + + theInstance->initializeMap(); + } + + return theInstance; +} + +ossimProjection* ossimStatePlaneProjectionFactory::createProjection( + const ossimFilename& filename, ossim_uint32 entryIdx)const +{ + // See if there is an external geomtry. + return createProjectionFromGeometryFile(filename, entryIdx); +} + +ossimProjection* ossimStatePlaneProjectionFactory::createProjection( + const ossimString& name)const +{ + ossimProjection* result = NULL; + + std::map<ossim_int32, ossimStatePlaneProjectionInfo*>::const_iterator current; + ossim_int32 c = name.toLong(); + current = theStatePlaneInfoMap.find(c); + + if(current != theStatePlaneInfoMap.end()) + { + ossimKeywordlist kwl2; + + (*current).second->populateProjectionKeywords(kwl2); + + result = ossimMapProjectionFactory::instance()->createProjection(kwl2); + } + + if(!result) + { + std::map<ossimString, ossimStatePlaneProjectionInfo*>::const_iterator currentName; + currentName = theStatePlaneInfoNameMap.find(c); + if(currentName != theStatePlaneInfoNameMap.end()) + { + ossimKeywordlist kwl2; + + (*currentName).second->populateProjectionKeywords(kwl2); + + result = ossimMapProjectionFactory::instance()->createProjection(kwl2); + } + } + + return result; +} + +ossimProjection* ossimStatePlaneProjectionFactory::createProjection(const ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimProjection* result = NULL; + const char* pcs_code = kwl.find(prefix, + ossimKeywordNames::PCS_CODE_KW); + const char* type_kw = kwl.find(prefix, + ossimKeywordNames::TYPE_KW); + if(pcs_code) + { + std::map<ossim_int32, ossimStatePlaneProjectionInfo*>::const_iterator current; + ossim_int32 code = ossimString(pcs_code).toLong(); + current = theStatePlaneInfoMap.find(code); + + if(current != theStatePlaneInfoMap.end()) + { + ossimKeywordlist kwl2 = kwl; + + (*current).second->populateProjectionKeywords(kwl2, prefix); + + result = ossimMapProjectionFactory::instance()->createProjection(kwl2, prefix); + + } + } + else if(type_kw) + { + std::map<ossimString, ossimStatePlaneProjectionInfo*>::const_iterator current; + current = theStatePlaneInfoNameMap.find(ossimString(type_kw)); + if(current != theStatePlaneInfoNameMap.end()) + { + ossimKeywordlist kwl2 = kwl; + + (*current).second->populateProjectionKeywords(kwl2, prefix); + + result = ossimMapProjectionFactory::instance()->createProjection(kwl2, prefix); + } + } + + return result; +} + +const ossimStatePlaneProjectionInfo* ossimStatePlaneProjectionFactory::getInfo(ossim_int32 pcsCode)const +{ + std::map<ossim_int32, ossimStatePlaneProjectionInfo*>::const_iterator current; + current = theStatePlaneInfoMap.find(pcsCode); + + if(current != theStatePlaneInfoMap.end()) + { + return (*current).second; + } + + return (const ossimStatePlaneProjectionInfo*)NULL; +} + +const ossimStatePlaneProjectionInfo* ossimStatePlaneProjectionFactory::getInfo(const ossimString& name)const +{ + std::map<ossimString, ossimStatePlaneProjectionInfo*>::const_iterator current; + current = theStatePlaneInfoNameMap.find(name); + + if(current != theStatePlaneInfoNameMap.end()) + { + return (*current).second; + } + + return (const ossimStatePlaneProjectionInfo*)NULL; +} + + + +std::list<ossimString> ossimStatePlaneProjectionFactory::getList()const +{ + list<ossimString> result; + + std::map<ossim_int32, ossimStatePlaneProjectionInfo*>::const_iterator current = theStatePlaneInfoMap.begin(); + + while(current != theStatePlaneInfoMap.end()) + { + result.push_back((*current).second->name()); + + ++current; + } + + return result; +} + +ossimObject* ossimStatePlaneProjectionFactory::createObject(const ossimString& typeName)const +{ + return createProjection(typeName); +} + +ossimObject* ossimStatePlaneProjectionFactory::createObject(const ossimKeywordlist& kwl, + const char* prefix)const +{ + return createProjection(kwl, prefix); +} + +void ossimStatePlaneProjectionFactory::getTypeNameList(std::vector<ossimString>& typeList)const +{ + std::map<ossim_int32, ossimStatePlaneProjectionInfo*>::const_iterator current = theStatePlaneInfoMap.begin(); + + while(current != theStatePlaneInfoMap.end()) + { + typeList.push_back((*current).second->name()); + + ++current; + } +// typeList.push_back("ossimStatePlaneProjection"); +} + +bool ossimStatePlaneProjectionFactory::addStatePlaneInfo(ossimStatePlaneProjectionInfo* info) +{ + if(info) + { + theStatePlaneInfoMap.insert(make_pair((ossim_int32)info->code(), + info)); + theStatePlaneInfoNameMap.insert(make_pair(info->name(), + info)); + + return true; + } + + return false; + +} + +void ossimStatePlaneProjectionFactory::initializeMap() +{ + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Alabama_East", 26729, "ossimTransMercatorProjection", "30 30 n", "85 50 w", + 25000, 0, 500000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Alabama_West", 26730, "ossimTransMercatorProjection", "30 n", "87 30 w", + 15000, 0, 500000, 0.0, "ft")); + + // addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Alaska_zone_1", 26731 UNSUPPORTED! (Hotine Mercator) + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Alaska_zone_2", 26732, "ossimTransMercatorProjection", "54 n", "142 w", 10000, 0, + 500000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Alaska_zone_3", 26733, "ossimTransMercatorProjection", "54 n", "146 w", 10000, 0, + 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Alaska_zone_4", 26734, "ossimTransMercatorProjection", "54 n", "150 w", 10000, 0, + 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Alaska_zone_5", 26735, "ossimTransMercatorProjection", "54 n", "154 w", 10000, 0, + 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Alaska_zone_6", 26736, "ossimTransMercatorProjection", "54 n", "158 w", 10000, 0, + 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Alaska_zone_7", 26737, "ossimTransMercatorProjection", "54 n", "162 w", 10000, 0, + 700000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Alaska_zone_8", 26738, "ossimTransMercatorProjection", "54 n", "166 w", 10000, 0, + 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Alaska_zone_9", 26739, "ossimTransMercatorProjection", "54 n", "170 w", 10000, 0, + 600000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Alaska_zone_10", 26740, "ossimLambertConformalConicProjection", "51 n", "176 w", + "51 50 n", "53 50 n", 3000000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_California_I", 26741, "ossimLambertConformalConicProjection", "39 20", "122 w", + "40 n", "41 40 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_California_II", 26742, "ossimLambertConformalConicProjection", "37 40", "122 w", + "38 20", "39 50", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_California_III", 26743, "ossimLambertConformalConicProjection", "36 30 n", "120 30 w", + "37 04 n", "38 26 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_California_IV", 26744, "ossimLambertConformalConicProjection", "35 20 n", "119 w", + "36 n", "37 15 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_California_V", 26745, "ossimLambertConformalConicProjection", "33 30 n", "118 w", + "34 02 n", "35 28 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_California_VI", 26746, "ossimLambertConformalConicProjection", "32 10", "116 15 w", + "32 47 n", "33 53 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_California_VII", 26747, "ossimLambertConformalConicProjection", "34 08 n", "118 20 w", + "33 52 n", "34 25 n", 4186692.58, 4160926.74, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Arizona_East", 26748, "ossimTransMercatorProjection", "31 n", "110 10 w", + 10000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Arizona_Central", 26749, "ossimTransMercatorProjection", "31 n", "111 55 w", + 10000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Arizona_West", 26750, "ossimTransMercatorProjection", "31 n", "113 45 w", + 15000, 0, 500000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Arkansas_North", 26751, "ossimLambertConformalConicProjection", "34 20 n", "92 w", + "34 56 n", "36 14 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Arkansas_South", 26752, "ossimLambertConformalConicProjection", "32 40 n", "92 w", + "33 18 n", "34 46 n", 2000000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Colorado_North", 26753, "ossimLambertConformalConicProjection", "39 20 n", "105 30 w", + "39 43 n", "40 47 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Colorado_Central",26754, "ossimLambertConformalConicProjection", "37 50 n", "105 30 w", + "38 27 n", "39 45 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Colorado_South", 26755, "ossimLambertConformalConicProjection", "36 40 n", "105 30 w", + "37 14 n", "38 26 n", 2000000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Connecticut", 26756, "ossimLambertConformalConicProjection", "40 50 n", "72 45 w", + "41 12 n", "41 52 n", 600000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Delaware", 26757, "ossimTransMercatorProjection", "38 n", "75 25 w", + 200000, 0, 500000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Florida_East", 26758, "ossimTransMercatorProjection", "24 20 n", "81 w", + 17000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Florida_West", 26759, "ossimTransMercatorProjection", "24 20 n", "82 w", + 17000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Florida_North", 26760, "ossimLambertConformalConicProjection", "29 n", "84 30 w", + "29 35 n", "30 45 n", 2000000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Hawaii_zone_1", 26761, "ossimTransMercatorProjection", "18 50 n", "155 30 w", + 30000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Hawaii_zone_2", 26762, "ossimTransMercatorProjection", "20 20 n","156 40 w", + 30000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Hawaii_zone_3", 26763, "ossimTransMercatorProjection", "21 10 n", "158 w", + 100000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Hawaii_zone_4", 26764, "ossimTransMercatorProjection", "21 50 n", "159 30 w", + 100000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Hawaii_zone_5", 26765, "ossimTransMercatorProjection", "21 40 n", "160 10 w", + 0.0, 0, 500000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Georgia_East", 26766, "ossimTransMercatorProjection", "30 n", "82 10 w", + 10000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Georgia_West", 26767, "ossimTransMercatorProjection", "30 n", "84 10 w", + 10000, 0, 500000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Idaho_East", 26768, "ossimTransMercatorProjection", "41 40 n", "112 10 w", + 19000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Idaho_Central", 26769, "ossimTransMercatorProjection", "41 40 n", "114 w", + 19000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Idaho_West", 26770, "ossimTransMercatorProjection", "41 40 n", "115 45 w", + 15000, 0, 500000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Illinois_East", 26771, "ossimTransMercatorProjection", "36 40 n", "88 20 w", + 40000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Illinois_West", 26772, "ossimTransMercatorProjection", "36 40 n", "90 10 w", + 17000, 0, 500000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Indiana_East", 26773, "ossimTransMercatorProjection", "37 30 n", "85 40 w", + 30000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Indiana_West", 26774, "ossimTransMercatorProjection", "37 30 n", "87 05 w", + 30000, 0, 500000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Iowa_North", 26775, "ossimLambertConformalConicProjection", "41 30 n", "93 30 w", + "42 04 n", "43 16 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Iowa_South", 26776, "ossimLambertConformalConicProjection", "40 n", "93 30 w", + "40 37 n", "41 47 n", 2000000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Kansas_North", 26777, "ossimLambertConformalConicProjection", "38 20 n", "98 00 w", + "38 43 n", "39 47 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Kansas_South", 26778, "ossimLambertConformalConicProjection", "36 40 n", "98 30 w", + "37 16 n", "38 34 n", 2000000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Kentucky_North", 26779, "ossimLambertConformalConicProjection", "37 30 n", "84 15 w", + "37 58 n", "38 58 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Kentucky_South", 26780, "ossimLambertConformalConicProjection", "36 20 n", "85 45 w", + "36 44 n", "37 56 n", 2000000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Louisiana_North", 26781, "ossimLambertConformalConicProjection", "30 40 n", "92 30 w", + "31 10 n", "32 40 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Louisiana_South", 26782, "ossimLambertConformalConicProjection", "28 40 n", "91 20 w", + "29 18 n", "30 42 n", 2000000, 0.0, "ft")); + +// addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Louisiana_Offshore", 0, "ossimLambertConformalConicProjection", "25 40 n", "91 20 w", +// "26 10 n", "27 50 n", 2000000, 0.0, "ft")); + + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Maine_East", 26783, "ossimTransMercatorProjection", "43 50 n", "68 30 w", + 10000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Maine_West", 26784, "ossimTransMercatorProjection", "42 50 n", "70 10 w", + 30000, 0, 500000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Maryland", 26785, "ossimLambertConformalConicProjection", "37 50 n", "77 00 w", + "38 18 n", "39 27 n", 800000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Massachusetts", 26786, "ossimLambertConformalConicProjection", "41 00 n", "71 30 w", + "41 43 n", "42 41 n", 600000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Massachusetts_Is",26787, "ossimLambertConformalConicProjection", "41 00 n", "70 30 w", + "41 17 n", "41 29 n", 200000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Michigan_North", 26788, "ossimLambertConformalConicProjection", "44 47 n", "87 w", + "45 29 n", "47 05 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Michigan_Central",26789, "ossimLambertConformalConicProjection", "43 19 n", "84 20 w", + "44 11 n", "45 42 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Michigan_South", 26790, "ossimLambertConformalConicProjection", "41 30 n", "84 20 w", + "42 06 n", "43 40 n", 2000000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Minnesota_North", 26791, "ossimLambertConformalConicProjection", "46 30 n", "93 06 w", + "47 02 n", "48 38 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Minnesota_Cent", 26792, "ossimLambertConformalConicProjection", "45 00 n", "94 15 w", + "45 37 n", "47 03 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Minnesota_South", 26793, "ossimLambertConformalConicProjection", "43 00 n", "94 00 w", + "43 47 n", "45 13 n", 2000000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Mississippi_East",26794, "ossimTransMercatorProjection", "29 40 n", "88 50 w", + 25000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Mississippi_West",26795, "ossimTransMercatorProjection", "30 30 n", "90 20 w", + 17000, 0, 500000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Missouri_East", 26796, "ossimTransMercatorProjection", "35 50 n", "90 30 w", + 15000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Missouri_Central",26797, "ossimTransMercatorProjection", "35 50 n", "92 30 w", + 15000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Missouri_West", 26798, "ossimTransMercatorProjection", "36 10 n", "94 30 w", + 17000, 0, 500000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD_Michigan_Old_East", 26801, "ossimTransMercatorProjection", "41 30 n", "83 40 w", + 17500, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD_Michigan_Old_Centr",26802, "ossimTransMercatorProjection", "41 30 n", "85 45 w", + 11000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD_Michigan_Old_West", 26803, "ossimTransMercatorProjection", "41 30 n", "88 45 w", + 11000, 0, 500000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Montana_North", 32001, "ossimLambertConformalConicProjection", "47 00 n", "109 30 w", + "47 51 n", "48 43 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Montana_Central", 32002, "ossimLambertConformalConicProjection", "45 50 n", "109 30 w", + "46 27 n", "47 53 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Montana_South", 32003, "ossimLambertConformalConicProjection", "44 00 n", "109 30 w", + "44 52 n", "46 24 n", 2000000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Nebraska_North", 32005, "ossimLambertConformalConicProjection", "41 20 n", "100 00 w", + "41 51 n", "42 49 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Nebraska_South", 32006, "ossimLambertConformalConicProjection", "39 40 n", "99 30 w", + "40 17 n", "41 43 n", 2000000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Nevada_East", 32007, "ossimTransMercatorProjection", "34 45 n", "115 35 w", + 10000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Nevada_Central", 32008, "ossimTransMercatorProjection", "34 45 n", "116 40 w", + 10000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Nevada_West", 32009, "ossimTransMercatorProjection", "34 45 n", "118 35 w", + 10000, 0, 500000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_New_Hampshire", 32010, "ossimTransMercatorProjection", "42 30 n", "71 40 w", + 30000, 0, 500000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_New_Jersey", 32011, "ossimTransMercatorProjection", "38 50 n", "74 40 w", + 40000, 0, 2000000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_New_Mexico_East", 32012, "ossimTransMercatorProjection", "31 00 n", "104 20 w", + 11000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_New_Mexico_Cent", 32013, "ossimTransMercatorProjection", "31 00 n", "106 15 w", + 10000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_New_Mexico_West", 32014, "ossimTransMercatorProjection", "31 00 n", "107 50 w", + 12000, 0, 500000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_New_York_East", 32015, "ossimTransMercatorProjection", "40 00 n", "74 20 w", + 30000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_New_York_Central",32016, "ossimTransMercatorProjection", "40 00 n", "76 35 w", + 16000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_New_York_West", 32017, "ossimTransMercatorProjection", "40 00 n", "78 35 w", + 16000, 0, 500000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_New_York_Long_Is",32018, "ossimLambertConformalConicProjection", "40 30 n", "74 w", + "40 40 n", "41 02 n", 2000000, 100000, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_North_Carolina", 32019, "ossimLambertConformalConicProjection", "33 45 n", "79 00 w", + "34 20 n", "36 10 n", 2000000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_North_Dakota_N", 32020, "ossimLambertConformalConicProjection", "47 00 n", "100 30 w", + "47 26 n", "48 44 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_North_Dakota_S", 32021, "ossimLambertConformalConicProjection", "45 40 n", "100 30 w", + "46 11 n", "47 29 n", 2000000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Ohio_North", 32022, "ossimLambertConformalConicProjection", "39 40 n", "82 30 w", + "40 26 n", "41 42 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Ohio_South", 32023, "ossimLambertConformalConicProjection", "38 00 n", "82 30 w", + "38 44 n", "40 02 n", 2000000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Oklahoma_North", 32024, "ossimLambertConformalConicProjection", "35 00 n", "98 00 w", + "35 34 n", "36 46 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Oklahoma_South", 32025, "ossimLambertConformalConicProjection", "33 20 n", "98 00 w", + "33 56 n", "35 14 n", 2000000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Oregon_North", 32026, "ossimLambertConformalConicProjection", "43 40 n", "120 30 w", + "44 20 n", "46 00 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Oregon_South", 32027, "ossimLambertConformalConicProjection", "41 40 n", "120 30 w", + "42 20 n", "44 00 n", 2000000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Pennsylvania_N", 32028, "ossimLambertConformalConicProjection", "40 10 n", "77 45 w", + "40 53 n", "41 57 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Pennsylvania_S", 32029, "ossimLambertConformalConicProjection", "39 20 n", "77 45 w", + "39 56 n", "40 58 n", 2000000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Rhode_Island", 32030, "ossimTransMercatorProjection", "41 05 n", "71 30 w", + 160000, 0, 500000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_South_Carolina_N",32031, "ossimLambertConformalConicProjection", "33 00 n", "81 00 w", + "33 46 n", "34 58 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_South_Carolina_S",32033, "ossimLambertConformalConicProjection", "31 50 n", "81 00 w", + "32 20 n", "33 40 n", 2000000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_South_Dakota_N", 32034, "ossimLambertConformalConicProjection", "43 50 n", "100 00 w", + "44 25 n", "45 41 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_South_Dakota_S", 32035, "ossimLambertConformalConicProjection", "42 20 n", "100 20 w", + "42 50 n", "44 24 n", 2000000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Tennessee", 32036, "ossimLambertConformalConicProjection", "34 40 n", "86 00 w", + "35 15 n", "36 25 n", 2000000, 100000, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Texas_North", 32037, "ossimLambertConformalConicProjection", "34 00 n", "101 30 w", + "34 39 n", "36 11 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Texas_North_Cen", 32038, "ossimLambertConformalConicProjection", "31 40 n", "97 30 w", + "32 08 n", "33 58 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Texas_Central", 32039, "ossimLambertConformalConicProjection", "29 40 n", "100 20 w", + "30 07 n", "31 53 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Texas_South_Cen", 32040, "ossimLambertConformalConicProjection", "27 50 n", "99 00 w", + "28 23 n", "30 17 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Texas_South", 32041, "ossimLambertConformalConicProjection", "25 40 n", "98 30 w", + "26 10 n", "27 50 n", 2000000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Utah_North", 32042, "ossimLambertConformalConicProjection", "40 20 n", "111 30 w", + "40 43 n", "41 47 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Utah_Central", 32043, "ossimLambertConformalConicProjection", "38 20 n", "111 30 w", + "39 01 n", "40 39 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Utah_South", 32044, "ossimLambertConformalConicProjection", "36 40 n", "111 30 w", + "37 13 n", "38 21 n", 2000000, 0.0, "ft")); + + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Vermont", 32045, "ossimTransMercatorProjection", "42 30 n", "72 30 w", 28000, 0, + 500000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Virginia_North", 32046, "ossimLambertConformalConicProjection", "37 40 n", "78 30 w", + "38 02 n", "39 12 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Virginia_South", 32047, "ossimLambertConformalConicProjection", "36 20 n", "78 30 w", + "36 46 n", "37 58 n", 2000000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Washington_North",32048, "ossimLambertConformalConicProjection", "47 00 n", "120 50 w", + "47 30 n", "48 44 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Washington_South",32049, "ossimLambertConformalConicProjection", "45 20 n", "120 30 w", + "45 50 n", "47 20 n", 2000000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_West_Virginia_N", 32050, "ossimLambertConformalConicProjection", "38 30 n", "79 30 w", + "39 00 n", "40 15 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_West_Virginia_S", 32051, "ossimLambertConformalConicProjection", "37 00 n", "81 00 w", + "37 29 n", "38 53 n", 2000000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Wisconsin_North", 32052, "ossimLambertConformalConicProjection", "45 10 n", "90 00 w", + "45 34 n", "46 46 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Wisconsin_Cen", 32053, "ossimLambertConformalConicProjection", "43 50 n", "90 00 w", + "44 15 n", "45 30 n", 2000000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Wisconsin_South", 32054, "ossimLambertConformalConicProjection", "42 00 n", "90 00 w", + "42 44 n", "44 04 n", 2000000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Wyoming_East", 32055, "ossimTransMercatorProjection", "40 40 n", "105 10 w", + 17000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Wyoming_E_Cen", 32056, "ossimTransMercatorProjection", "40 40 n", "107 20 w", + 17000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Wyoming_W_Cen", 32057, "ossimTransMercatorProjection", "40 40 n", "108 45 w", + 17000, 0, 500000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Wyoming_West", 32058, "ossimTransMercatorProjection", "40 40 n", "110 05 w", + 17000, 0, 500000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_Puerto_Rico", 32059, "ossimLambertConformalConicProjection", "17 50 n", "66 26 w", + "18 02 n", "18 26 n", 500000, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD27_St_Croix", 32060, "ossimLambertConformalConicProjection", "17 50 n", "66 26 w", + "18 02 n", "18 26 n", 500000, 100000, "ft")); + + + //*** + // NAD83 Datum based State Plane Projections + //*** + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Alabama_East", 26929, "ossimTransMercatorProjection", "30 30 n", "85 50 w", + 25000, 0, 200000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Alabama_West", 26930, "ossimTransMercatorProjection", "30 n", "87 30 w", + 15000, 0, 600000, 0.0, "m")); + + // addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Alaska_zone_1", 26931 UNSUPPORTED! + // (Hotine Mercator) + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Alaska_zone_2", 26932, "ossimTransMercatorProjection", "54 n", "142 w", 10000, 0, + 500000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Alaska_zone_3", 26933, "ossimTransMercatorProjection", "54 n", "146 w", 10000, 0, + 500000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Alaska_zone_4", 26934, "ossimTransMercatorProjection", "54 n", "150 w", 10000, 0, + 500000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Alaska_zone_5", 26935, "ossimTransMercatorProjection", "54 n", "154 w", 10000, 0, + 500000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Alaska_zone_6", 26936, "ossimTransMercatorProjection", "54 n", "158 w", 10000, 0, + 500000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Alaska_zone_7", 26937, "ossimTransMercatorProjection", "54 n", "162 w", 10000, 0, + 500000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Alaska_zone_8", 26938, "ossimTransMercatorProjection", "54 n", "166 w", 10000, 0, + 500000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Alaska_zone_9", 26939, "ossimTransMercatorProjection", "54 n", "170 w", 10000, 0, + 500000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Alaska_zone_10",26940, "ossimLambertConformalConicProjection", "51 n", "176 w", + "51 50 n", "53 50 n", 1000000, 0.0, "m")); + +// California + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_California_1", 26941, "ossimLambertConformalConicProjection", "39 20 n", "122 w", + "40 n", "41 40 n", 2000000, 500000, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_California_2", 26942, "ossimLambertConformalConicProjection", "37 40 n", "122 w", + "38 20 n", "39 50 n", 2000000, 500000, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_California_3", 26943, "ossimLambertConformalConicProjection", "36 30 n", "120 30 w", + "37 04 n", "38 26 n", 2000000, 500000, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_California_4", 26944, "ossimLambertConformalConicProjection", "35 20 n", "119 w", + "36 n", "37 15 n", 2000000, 500000, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_California_5", 26945, "ossimLambertConformalConicProjection", "33 30 n", "118 w", + "34 02 n", "35 28 n", 2000000, 500000, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_California_6", 26946, "ossimLambertConformalConicProjection", "32 10", "116 15 w", + "32 47 n", "33 53 n", 2000000, 500000, "m")); + +// Arizona + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Arizona_East", 26948, "ossimTransMercatorProjection", "31 n", "110 10 w", + 10000, 0, 213360, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Arizona_Centr", 26949, "ossimTransMercatorProjection", "31 n", "111 55 w", + 10000, 0, 213360, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Arizona_West", 26950, "ossimTransMercatorProjection", "31 n", "113 45 w", + 15000, 0, 213360, 0.0, "ft")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Arkansas_North", 26951, "ossimLambertConformalConicProjection", "34 20 n", "92 w", + "34 56 n", "36 14 n", 400000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Arkansas_South", 26952, "ossimLambertConformalConicProjection", "32 40 n", "92 w", + "33 18 n", "34 46 n", 400000, 400000, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Colorado_North", 26953, "ossimLambertConformalConicProjection", "39 20 n", "105 30 w", + "39 43 n", "40 47 n", 914401.8289, 304800.6096, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Colorado_Centr", 26954, "ossimLambertConformalConicProjection", "37 50 n", "105 30 w", + "38 27 n", "39 45 n", 914401.8289, 304800.6096, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Colorado_South", 26955, "ossimLambertConformalConicProjection", "36 40 n", "105 30 w", + "37 14 n", "38 26 n", 914401.8289, 304800.6096, "m")); + + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Connecticut", 26956, "ossimLambertConformalConicProjection", "40 50 n", "72 45 w", + "41 12 n", "41 52 n", 304800.6096, 152400.3048, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Delaware", 26957, "ossimTransMercatorProjection", "38 n", "75 25 w", 200000, 0, + 200000, 0.0, "m")); + +// Florida + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Florida_East", 26958, "ossimTransMercatorProjection", "24 20 n", "81 w", + 17000, 0, 200000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Florida_West", 26959, "ossimTransMercatorProjection", "24 20 n", "82 w", + 17000, 0, 200000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Florida_North", 26960, "ossimLambertConformalConicProjection", "29 n", "84 30 w", + "29 35 n", "30 45 n", 600000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Hawaii_zone_1", 26961, "ossimTransMercatorProjection", "18 50 n", "155 30 w", + 30000, 0, 500000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Hawaii_zone_2", 26962, "ossimTransMercatorProjection", "20 20 n","156 40 w", + 30000, 0, 500000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Hawaii_zone_3", 26963, "ossimTransMercatorProjection", "21 10 n", "158 w", + 100000, 0, 500000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Hawaii_zone_4", 26964, "ossimTransMercatorProjection", "21 50 n", "159 30 w", + 100000, 0, 500000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Hawaii_zone_5", 26965, "ossimTransMercatorProjection", "21 40 n", "160 10 w", + 0.0, 0, 500000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Georgia_East", 26966, "ossimTransMercatorProjection", "30 n", "82 10 w", + 10000, 0, 200000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Georgia_West", 26967, "ossimTransMercatorProjection", "30 n", "84 10 w", + 10000, 0, 700000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Idaho_East", 26968, "ossimTransMercatorProjection", "41 40 n", "112 10 w", + 19000, 0, 200000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Idaho_Central", 26969, "ossimTransMercatorProjection", "41 40 n", "114 w", + 19000, 0, 500000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Idaho_West", 26970, "ossimTransMercatorProjection", "41 40 n", "115 45 w", + 15000, 0, 800000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Illinois_East", 26971, "ossimTransMercatorProjection", "36 40 n", "88 20 w", + 40000, 0, 300000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Illinois_West", 26972, "ossimTransMercatorProjection", "36 40 n", "90 10 w", + 17000, 0, 700000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Indiana_East", 26973, "ossimTransMercatorProjection", "37 30 n", "85 40 w", + 30000, 0, 100000, 250000, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Indiana_West", 26974, "ossimTransMercatorProjection", "37 30 n", "87 05 w", + 30000, 0, 900000, 250000, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Iowa_North", 26975, "ossimLambertConformalConicProjection", "41 30 n", "93 30 w", + "42 04 n", "43 16 n", 1500000, 1000000, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Iowa_South", 26976, "ossimLambertConformalConicProjection", "40 n", "93 30 w", + "40 37 n", "41 47 n", 500000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Kansas_North", 26977, "ossimLambertConformalConicProjection", "38 20 n", "98 00 w", + "38 43 n", "39 47 n", 400000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Kansas_South", 26978, "ossimLambertConformalConicProjection", "36 40 n", "98 30 w", + "37 16 n", "38 34 n", 400000, 400000, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Kentucky_North", 26979, "ossimLambertConformalConicProjection", "37 30 n", "84 15 w", + "37 58 n", "38 58 n", 500000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Kentucky_South", 26980, "ossimLambertConformalConicProjection", "36 20 n", "85 45 w", + "36 44 n", "37 56 n", 500000, 500000, "m")); + + // Louisiana + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Louisiana_North", 26981, "ossimLambertConformalConicProjection", "30 30 n", "92 30 w", + "31 10 n", "32 40 n", 1000000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Louisiana_South", 26982, "ossimLambertConformalConicProjection", "28 30 n", "91 20 w", + "29 18 n", "30 42 n", 1000000, 0.0, "m")); + +// addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Louisiana_Offshore", 0, "ossimLambertConformalConicProjection", "25 30 n", "91 20 w", +// "26 10 n", "27 50 n", 1000000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Maine_East", 26983, "ossimTransMercatorProjection", "43 40 n", "68 30 w", + 10000, 0, 300000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Maine_West", 26984, "ossimTransMercatorProjection", "42 50 n", "70 10 w", + 30000, 0, 900000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Maryland", 26985, "ossimLambertConformalConicProjection","37 40 n", "77 00 w", + "38 18 n", "39 27 n", 400000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Massachusetts", 26986, "ossimLambertConformalConicProjection", "41 00 n", "71 30 w", + "41 43 n", "42 41 n", 200000, 750000, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Massachusetts_Is", 26987, "ossimLambertConformalConicProjection", "41 00 n", "70 30 w", + "41 17 n", "41 29 n", 500000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Michigan_North", 26988, "ossimLambertConformalConicProjection", "44 47 n", "87 w", + "45 29 n", "47 05 n", 8000000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Michigan_Central",26989, "ossimLambertConformalConicProjection", "43 19 n", "84 22 w", + "44 11 n", "45 42 n", 6000000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Michigan_South", 26990, "ossimLambertConformalConicProjection", "41 30 n", "84 22 w", + "42 06 n", "43 40 n", 4000000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Minnesota_North", 26991, "ossimLambertConformalConicProjection", "46 30 n", "93 06 w", + "47 02 n", "48 38 n", 800000, 100000, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Minnesota_Cent", 26992, "ossimLambertConformalConicProjection", "45 00 n", "94 15 w", + "45 37 n", "47 03 n", 800000, 100000, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Minnesota_South", 26993, "ossimLambertConformalConicProjection", "43 00 n", "94 00 w", + "43 47 n", "45 13 n", 800000, 100000, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Mississippi_East",26994, "ossimTransMercatorProjection", "29 30 n", "88 50 w", + 20000, 0, 300000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Mississippi_West",26995, "ossimTransMercatorProjection", "29 30 n", "90 20 w", + 20000, 0, 700000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Missouri_East", 26996, "ossimTransMercatorProjection", "35 50 n", "90 30 w", + 15000, 0, 250000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Missouri_Central",26997, "ossimTransMercatorProjection", "35 50 n", "92 30 w", + 15000, 0, 500000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Missouri_West", 26998, "ossimTransMercatorProjection", "36 10 n", "94 30 w", + 17000, 0, 850000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Montana", 32100, "ossimLambertConformalConicProjection", "44 15 n", "109 30 w", + "45 00 n", "49 00 n", 600000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Nebraska", 32104, "ossimLambertConformalConicProjection", "39 50 n", "100 00 w", + "40 00 n", "43 00 n", 500000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Nevada_East", 32107, "ossimTransMercatorProjection", "34 45 n", "115 35 w", + 10000, 0, 200000, 8000000, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Nevada_Central", 32108, "ossimTransMercatorProjection", "34 45 n", "116 40 w", + 10000, 0, 500000, 6000000, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Nevada_West", 32109, "ossimTransMercatorProjection", "34 45 n", "118 35 w", + 10000, 0, 800000, 4000000, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_New_Hampshire", 32110, "ossimTransMercatorProjection", "42 30 n", "71 40 w", + 30000, 0, 300000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_New_Jersey", 32111, "ossimTransMercatorProjection", "38 50 n", "74 30 w", + 10000, 0, 150000, 0.0, "m")); + + // AddStatePlaneMapInfo(New Mexico + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_New_Mexico_East", 32112, "ossimTransMercatorProjection", "31 00 n", "104 20 w", + 11000, 0, 165000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_New_Mexico_Cent", 32113, "ossimTransMercatorProjection", "31 00 n", "106 15 w", + 10000, 0, 500000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_New_Mexico_West", 32114, "ossimTransMercatorProjection", "31 00 n", "107 50 w", + 12000, 0, 830000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_New_York_East", 32115, "ossimTransMercatorProjection", "38 50 n", "74 30 w", + 10000, 0, 150000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_New_York_Central",32116, "ossimTransMercatorProjection", "40 00 n", "76 35 w", + 16000, 0, 250000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_New_York_West", 32117, "ossimTransMercatorProjection", "40 00 n", "78 35 w", + 16000, 0, 350000, 0.0, "ft")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_New_York_Long_Is",32118, "ossimLambertConformalConicProjection", "40 10 n", "74 w", + "40 40 n", "41 02 n", 300000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_North_Carolina", 32119, "ossimLambertConformalConicProjection", "33 45 n", "79 00 w", + "34 20 n", "36 10 n", 609601.22, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_North_Dakota_N", 32120, "ossimLambertConformalConicProjection", "47 00 n", "100 30 w", + "47 26 n", "48 44 n", 600000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_North_Dakota_S", 32121, "ossimLambertConformalConicProjection", "45 40 n", "100 30 w", + "46 11 n", "47 29 n", 600000, 0.0, "m")); + + // Ohio + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Ohio_North", 32122, "ossimLambertConformalConicProjection", "39 40 n", "82 30 w", + "40 26 n", "41 42 n", 600000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Ohio_South", 32123, "ossimLambertConformalConicProjection", "38 00 n", "82 30 w", + "38 44 n", "40 02 n", 600000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Oklahoma_North", 32124, "ossimLambertConformalConicProjection", "35 00 n", "98 00 w", + "35 34 n", "36 46 n", 600000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Oklahoma_South", 32125, "ossimLambertConformalConicProjection", "33 20 n", "98 00 w", + "33 56 n", "35 14 n", 600000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Oregon_North", 32126, "ossimLambertConformalConicProjection", "43 40 n", + "120 30 w", "44 20 n", "46 00 n", 2500000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Oregon_South", 32127, "ossimLambertConformalConicProjection", "41 40 n", "120 30 w", + "42 20 n", "44 00 n", 1500000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Pennsylvania_N", 32128, "ossimLambertConformalConicProjection", "40 10 n", "77 45 w", + "40 53 n", "41 57 n", 600000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Pennsylvania_S", 32129, "ossimLambertConformalConicProjection", "39 20 n", "77 45 w", + "39 56 n", "40 58 n", 600000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Rhode_Island", 32130, "ossimTransMercatorProjection", "41 05 n", "71 30 w", + 160000, 0, 100000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_South_Carolina", 32133, "ossimLambertConformalConicProjection", "31 50 n", "81 00 w", + "32 30 n", "34 50 n", 609600, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_South_Dakota_N", 32134, "ossimLambertConformalConicProjection", "43 50 n", "100 00 w", + "44 25 n", "45 41 n", 600000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_South_Dakota_S", 32135, "ossimLambertConformalConicProjection", "42 20 n", "100 20 w", + "42 50 n", "44 24 n", 600000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Tennessee", 32136, "ossimLambertConformalConicProjection", "34 20 n", "86 00 w", + "35 15 n", "36 25 n", 600000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Texas_North", 32137, "ossimLambertConformalConicProjection", "34 00 n", "101 30 w", + "34 39 n", "36 11 n", 200000, 1000000, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Texas_North_Cen", 32138, "ossimLambertConformalConicProjection", "31 40 n", "98 30 w", + "32 08 n", "33 58 n", 600000, 2000000, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Texas_Central", 32139, "ossimLambertConformalConicProjection", "29 40 n", "100 20 w", + "30 07 n", "31 53 n", 700000, 3000000, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Texas_South_Cen", 32140, "ossimLambertConformalConicProjection", "27 50 n", "99 00 w", + "28 23 n", "30 17 n", 600000, 4000000, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Texas_South", 32141, "ossimLambertConformalConicProjection", "25 40 n", "98 30 w", + "26 10 n", "27 50 n", 300000, 5000000, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Utah_North", 32142, "ossimLambertConformalConicProjection", "40 20 n", "111 30 w", + "40 43 n", "41 47 n", 500000, 1000000, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Utah_Central", 32143, "ossimLambertConformalConicProjection", "38 20 n", "111 30 w", + "39 01 n", "40 39 n", 500000, 2000000, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Utah_South", 32144, "ossimLambertConformalConicProjection", "36 40 n", "111 30 w", + "37 13 n", "38 21 n", 500000, 3000000, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Vermont", 32145, "ossimTransMercatorProjection", "42 30 n", "72 30 w", 28000, 0, + 500000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Virginia_North", 32146, "ossimLambertConformalConicProjection", "37 40 n", "78 30 w", + "38 02 n", "39 12 n", 3500000, 2000000, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Virginia_South", 32147, "ossimLambertConformalConicProjection", "36 20 n", "78 30 w", + "36 46 n", "37 58 n", 3500000, 1000000, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Washington_North",32148, "ossimLambertConformalConicProjection", "47 00 n", "120 50 w", + "47 30 n", "48 44 n", 500000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Washington_South",32149, "ossimLambertConformalConicProjection", "45 20 n", "120 30 w", + "45 50 n", "47 20 n", 500000, 0.0, "m")); + + // West Virginia + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_West_Virginia_N", 32150, "ossimLambertConformalConicProjection", "38 30 n", "79 30 w", + "39 00 n", "40 15 n", 600000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_West_Virginia_S", 32151, "ossimLambertConformalConicProjection", "37 00 n", "81 00 w", + "37 29 n", "38 53 n", 600000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Wisconsin_North", 32152, "ossimLambertConformalConicProjection", "45 10 n", "90 00 w", + "45 34 n", "46 46 n", 600000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Wisconsin_Cen", 32153, "ossimLambertConformalConicProjection", "43 50 n", "90 00 w", + "44 15 n", "45 30 n", 600000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Wisconsin_South", 32154, "ossimLambertConformalConicProjection", "42 00 n", "90 00 w", + "42 44 n", "44 04 n", 600000, 0.0, "m")); + + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Wyoming_East", 32155, "ossimTransMercatorProjection", "40 30 n", "105 10 w", + 16000, 0, 200000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Wyoming_E_Cen", 32156, "ossimTransMercatorProjection", "40 30 n", "107 20 w", + 16000, 0, 400000, 100000, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Wyoming_W_Cen", 32157, "ossimTransMercatorProjection", "40 30 n", "108 45 w", + 16000, 0, 600000, 0.0, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo("NAD83_Wyoming_West", 32158, "ossimTransMercatorProjection", "40 30 n", "110 05 w", + 16000, 0, 800000, 100000, "m")); + addStatePlaneInfo(new ossimStatePlaneProjectionInfo ("NAD83_Puerto_Rico", 32161, "ossimLambertConformalConicProjection", "17 50 n", "66 26 w", + "18 02 n", "18 26 n", 200000, 200000, "m")); +} + +//--- +// Hidden from use stuff. +//--- +ossimStatePlaneProjectionFactory::ossimStatePlaneProjectionFactory() + : ossimProjectionFactoryBase() +{} + +ossimStatePlaneProjectionFactory::ossimStatePlaneProjectionFactory(const ossimStatePlaneProjectionFactory&) + : ossimProjectionFactoryBase() +{} + +void ossimStatePlaneProjectionFactory::operator=(const ossimStatePlaneProjectionFactory& /* rhs */) +{} diff --git a/Utilities/OSSIM/ossim_core/projections/factory/ossimStatePlaneProjectionFactory.h b/Utilities/OSSIM/ossim_core/projections/factory/ossimStatePlaneProjectionFactory.h new file mode 100644 index 0000000000..03cfa66c1b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/factory/ossimStatePlaneProjectionFactory.h @@ -0,0 +1,57 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +//******************************************************************* +// $Id: ossimStatePlaneProjectionFactory.h,v 1.9 2004/09/24 17:19:40 dburken Exp $ +#ifndef ossimStatePlaneProjectionFactory_HEADER +#define ossimStatePlaneProjectionFactory_HEADER +#include "ossimProjectionFactoryBase.h" +class ossimStatePlaneProjectionInfo; + +class OSSIMDLLEXPORT ossimStatePlaneProjectionFactory : public ossimProjectionFactoryBase +{ +public: + static ossimStatePlaneProjectionFactory* instance(); + virtual ~ossimStatePlaneProjectionFactory(); + virtual ossimProjection* createProjection(const ossimFilename& filename, + ossim_uint32 entryIdx)const; + virtual ossimProjection* createProjection(const ossimString& name)const; + virtual ossimProjection* createProjection(const ossimKeywordlist& kwl, + const char* prefix=0)const; + const ossimStatePlaneProjectionInfo* getInfo(ossim_int32 pcsCode)const; + const ossimStatePlaneProjectionInfo* getInfo(const ossimString& name)const; + virtual std::list<ossimString> getList()const; + virtual ossimObject* createObject(const ossimString& typeName)const; + + /*! + * Creates and object given a keyword list. + */ + virtual ossimObject* createObject(const ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * This should return the type name of all objects in all factories. + * This is the name used to construct the objects dynamially and this + * name must be unique. + */ + virtual void getTypeNameList(std::vector<ossimString>& typeList)const; + + bool addStatePlaneInfo(ossimStatePlaneProjectionInfo* info); +protected: + ossimStatePlaneProjectionFactory(); + ossimStatePlaneProjectionFactory(const ossimStatePlaneProjectionFactory&); + void operator =(const ossimStatePlaneProjectionFactory& rhs); + + static ossimStatePlaneProjectionFactory* theInstance; + + std::map<ossim_int32, ossimStatePlaneProjectionInfo*> theStatePlaneInfoMap; + std::map<ossimString, ossimStatePlaneProjectionInfo*> theStatePlaneInfoNameMap; + + void initializeMap(); +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/factory/ossimTiffProjectionFactory.cpp b/Utilities/OSSIM/ossim_core/projections/factory/ossimTiffProjectionFactory.cpp new file mode 100644 index 0000000000..bbcfeb5cdc --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/factory/ossimTiffProjectionFactory.cpp @@ -0,0 +1,133 @@ +//***************************************************************************** +// FILE: ossimTiffProjectionFactory.cc +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// DESCRIPTION: +// Contains implementation of class ossimTiffProjectionFactory +// +//***************************************************************************** +// $Id: ossimTiffProjectionFactory.cpp,v 1.3 2004/09/24 17:19:40 dburken Exp $ + +#include "ossimTiffProjectionFactory.h" +#include "support_data/tiff/ossimGeoTiff.h" +#include "ossimProjectionFactoryRegistry.h" +#include "base/data_types/ossimKeywordlist.h" +#include "base/common/ossimKeywordNames.h" +#include "base/data_types/ossimFilename.h" +#include "projections/ossimProjection.h" +#include <fstream> + +ossimTiffProjectionFactory* ossimTiffProjectionFactory::theInstance = 0; + +//***************************************************************************** +// STATIC METHOD: ossimTiffProjectionFactory::instance() +// +//***************************************************************************** +ossimTiffProjectionFactory* ossimTiffProjectionFactory::instance() +{ + if(!theInstance) + { + theInstance = new ossimTiffProjectionFactory; + } + + return (ossimTiffProjectionFactory*) theInstance; +} + +ossimProjection* +ossimTiffProjectionFactory::createProjection(const ossimFilename& filename, + ossim_uint32 entryIdx)const +{ + if(!filename.exists()) + { + return NULL; + } + + // See if there is an external geomtry. + ossimProjection* result = createProjectionFromGeometryFile(filename, + entryIdx); + if (result) + { + return result; + } + + if(isTiff(filename)) + { + ossimGeoTiff geotiff(filename); + ossimKeywordlist kwl; + + if(geotiff.addImageGeometry(kwl)) + { + return ossimProjectionFactoryRegistry::instance()-> + createProjection(kwl); + } + } + + return NULL; +} + +//***************************************************************************** +// METHOD: ossimSensorModelFactory::create(kwl, prefix) +// +//***************************************************************************** +ossimProjection* +ossimTiffProjectionFactory::createProjection(const ossimKeywordlist &keywordList, + const char *prefix) const +{ + return NULL; +} + +//***************************************************************************** +// METHOD: ossimSensorModelFactory::create(projection_name) +// +//***************************************************************************** +ossimProjection* ossimTiffProjectionFactory::createProjection(const ossimString &name) const +{ + return NULL; +} + +ossimObject* ossimTiffProjectionFactory::createObject(const ossimString& typeName)const +{ + return (ossimObject*)createProjection(typeName); +} + +ossimObject* ossimTiffProjectionFactory::createObject(const ossimKeywordlist& kwl, + const char* prefix)const +{ + return createProjection(kwl, prefix); +} + +void ossimTiffProjectionFactory::getTypeNameList(std::vector<ossimString>& typeList)const +{ + +} + +list<ossimString> ossimTiffProjectionFactory::getList()const +{ + list<ossimString> result; + + + return result; +} + +bool ossimTiffProjectionFactory::isTiff(const ossimFilename& filename)const +{ + std::ifstream in; + unsigned char header[2]; + + in.open( filename.c_str(), ios::in|ios::binary); + if( !in) + return false; + + in.read( (char*)header, 2); + + if( (header[0] != 'M' || header[1] != 'M') + && (header[0] != 'I' || header[1] != 'I') ) + { + return false; + } + + return true; +} diff --git a/Utilities/OSSIM/ossim_core/projections/factory/ossimTiffProjectionFactory.h b/Utilities/OSSIM/ossim_core/projections/factory/ossimTiffProjectionFactory.h new file mode 100644 index 0000000000..7e966b5aff --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/factory/ossimTiffProjectionFactory.h @@ -0,0 +1,75 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +// class ossimProjectionFactory maintains a static list of projection +// makers. If a user wants to create a projection they can pass in +// a projection name and a datum if desired. Currently the default +// datum will be WGS84. +//******************************************************************* +// $Id: ossimTiffProjectionFactory.h,v 1.3 2004/09/24 17:19:40 dburken Exp $ + +#ifndef ossimTiffProjectionFactory_HEADER +#define ossimTiffProjectionFactory_HEADER + +#include "ossimProjectionFactoryBase.h" + +class ossimProjection; +class ossimString; + +class ossimTiffProjectionFactory : public ossimProjectionFactoryBase +{ +public: + /*! + * METHOD: instance() + * Instantiates singleton instance of this class: + */ + static ossimTiffProjectionFactory* instance(); + + virtual ossimProjection* createProjection(const ossimFilename& filename, + ossim_uint32 entryIdx)const; + /*! + * METHOD: create() + * Attempts to create an instance of the projection specified by name. + * Returns successfully constructed projection or NULL. + */ + virtual ossimProjection* createProjection(const ossimString& name)const; + virtual ossimProjection* createProjection(const ossimKeywordlist& kwl, + const char* prefix = 0)const; + + virtual ossimObject* createObject(const ossimString& typeName)const; + + /*! + * Creates and object given a keyword list. + */ + virtual ossimObject* createObject(const ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * This should return the type name of all objects in all factories. + * This is the name used to construct the objects dynamially and this + * name must be unique. + */ + virtual void getTypeNameList(std::vector<ossimString>& typeList)const; + + /*! + * METHOD: getList() + * Returns list of all projections represented by this factory: + */ + virtual list<ossimString> getList()const; + +protected: + ossimTiffProjectionFactory() {} + static ossimTiffProjectionFactory* theInstance; + + bool isTiff(const ossimFilename& filename)const; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/.cvsignore b/Utilities/OSSIM/ossim_core/projections/map_projections/.cvsignore new file mode 100644 index 0000000000..7df3918588 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/.cvsignore @@ -0,0 +1,3 @@ +*.d +Makefile + diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimAlbersProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimAlbersProjection.cpp new file mode 100644 index 0000000000..3d4ab0264b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimAlbersProjection.cpp @@ -0,0 +1,660 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Albers projection code. +//******************************************************************* +// $Id: ossimAlbersProjection.cpp,v 1.17 2005/09/09 19:23:58 gpotts Exp $ + +#include "ossimAlbersProjection.h" + +#include "base/common/ossimKeywordNames.h" + +RTTI_DEF1(ossimAlbersProjection, "ossimAlbersProjection", ossimMapProjection) + +#ifdef PI_OVER_2 +# undef PI_OVER_2 +#endif + +#define ALBERS_NO_ERROR 0x0000 +#define ALBERS_LAT_ERROR 0x0001 +#define ALBERS_LON_ERROR 0x0002 +#define ALBERS_EASTING_ERROR 0x0004 +#define ALBERS_NORTHING_ERROR 0x0008 +#define ALBERS_ORIGIN_LAT_ERROR 0x0010 +#define ALBERS_CENT_MER_ERROR 0x0020 +#define ALBERS_A_ERROR 0x0040 +#define ALBERS_INV_F_ERROR 0x0080 +#define ALBERS_FIRST_STDP_ERROR 0x0100 +#define ALBERS_SECOND_STDP_ERROR 0x0200 +#define ALBERS_FIRST_SECOND_ERROR 0x0400 +#define ALBERS_HEMISPHERE_ERROR 0x0800 + +#define PI_OVER_2 ( M_PI / 2.0) +#define ES_SIN(sinlat) (es * sinlat) +#define ONE_MINUS_SQR(x) (1.0 - x * x) +#define ALBERS_M(clat,oneminussqressin) (clat / sqrt(oneminussqressin)) +#define ALBERS_Q(slat,oneminussqressin,essin) (one_MINUS_es2)*(slat / (oneminussqressin)- \ + (1 / (two_es)) *log((1 - essin) / (1 + essin))) + + +ossimAlbersProjection::ossimAlbersProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + :ossimMapProjection(ellipsoid, origin) +{ + Albers_Delta_Northing = 40000000.0; + Albers_Delta_Easting = 40000000.0; + setDefaults(); + update(); +} + +ossimAlbersProjection::ossimAlbersProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double stdParallel1, + double stdParallel2, + double falseEasting, + double falseNorthing) + :ossimMapProjection(ellipsoid, origin) +{ + Albers_Std_Parallel_1 = stdParallel1*RAD_PER_DEG; + Albers_Std_Parallel_2 = stdParallel2*RAD_PER_DEG; + Albers_Delta_Northing = 40000000.0; + Albers_Delta_Easting = 40000000.0; + Albers_False_Easting = falseEasting; + Albers_False_Northing = falseNorthing; + + update(); + +} + +ossimObject* ossimAlbersProjection::dup() const +{ + return new ossimAlbersProjection(*this); +} + +ossimAlbersProjection::~ossimAlbersProjection() +{ +} + +void ossimAlbersProjection::update() +{ + Set_Albers_Parameters(theEllipsoid.getA(), + theEllipsoid.getFlattening(), + theOrigin.latr(), + theOrigin.lonr(), + Albers_Std_Parallel_1, + Albers_Std_Parallel_2, + Albers_False_Easting, + Albers_False_Northing); + + ossimMapProjection::update(); +} + + +ossimGpt ossimAlbersProjection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat, lon; + + + Convert_Albers_To_Geodetic(eastingNorthing.x, + eastingNorthing.y, + &lat, + &lon); + + return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0, theDatum); +} + +ossimDpt ossimAlbersProjection::forward(const ossimGpt &latLon)const +{ + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + + Convert_Geodetic_To_Albers(gpt.latr(), + gpt.lonr(), + &easting, + &northing); + + return ossimDpt(easting, northing); +} + +void ossimAlbersProjection::setStandardParallel1(double degree) +{ + Albers_Std_Parallel_1 = degree*RAD_PER_DEG; + update(); +} + +void ossimAlbersProjection::setStandardParallel2(double degree) +{ + Albers_Std_Parallel_2 = degree*RAD_PER_DEG; + update(); +} + +void ossimAlbersProjection::setStandardParallels(double parallel1Degree, + double parallel2Degree) +{ + Albers_Std_Parallel_1 = parallel1Degree*RAD_PER_DEG; + Albers_Std_Parallel_2 = parallel2Degree*RAD_PER_DEG; + update(); + +} + +void ossimAlbersProjection::setFalseEasting(double falseEasting) +{ + Albers_False_Easting = falseEasting; + update(); +} + +void ossimAlbersProjection::setFalseNorthing(double falseNorthing) +{ + Albers_False_Northing = falseNorthing; + update(); +} + +void ossimAlbersProjection::setFalseEastingNorthing(double falseEasting, + double falseNorthing) +{ + Albers_False_Easting = falseEasting; + Albers_False_Northing = falseNorthing; + update(); +} + +void ossimAlbersProjection::setParameters(double parallel1, + double parallel2, + double falseEasting, + double falseNorthing) +{ + Albers_False_Easting = falseEasting; + Albers_False_Northing = falseNorthing; + Albers_Std_Parallel_1 = parallel1*RAD_PER_DEG; + Albers_Std_Parallel_2 = parallel2*RAD_PER_DEG; + update(); +} + +double ossimAlbersProjection::getStandardParallel1()const +{ + return Albers_Std_Parallel_1; +} + +double ossimAlbersProjection::getStandardParallel2()const +{ + return Albers_Std_Parallel_2; +} + +double ossimAlbersProjection::getFalseEasting()const +{ + return Albers_False_Easting; +} + +double ossimAlbersProjection::getFalseNorthing()const +{ + return Albers_False_Northing; +} + +void ossimAlbersProjection::setDefaults() +{ + + // initialize to some default + // + Albers_Std_Parallel_1 = 29.5*RAD_PER_DEG; + Albers_Std_Parallel_2 = 45.5*RAD_PER_DEG; + Albers_False_Easting = 0.0; + Albers_False_Northing = 0.0; +} + +bool ossimAlbersProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const +{ + kwl.add(prefix, + ossimKeywordNames::STD_PARALLEL_1_KW, + Albers_Std_Parallel_1*DEG_PER_RAD, + true); + + kwl.add(prefix, + ossimKeywordNames::STD_PARALLEL_2_KW, + Albers_Std_Parallel_2*DEG_PER_RAD, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_EASTING_KW, + Albers_False_Easting, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_NORTHING_KW, + Albers_False_Northing, + true); + + return ossimMapProjection::saveState(kwl, prefix); +} + +bool ossimAlbersProjection::loadState(const ossimKeywordlist& kwl, const char* prefix) +{ + bool flag = ossimMapProjection::loadState(kwl, prefix); + + const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + const char* falseEasting = kwl.find(prefix, ossimKeywordNames::FALSE_EASTING_KW); + const char* falseNorthing = kwl.find(prefix, ossimKeywordNames::FALSE_NORTHING_KW); + const char* stdParallel1 = kwl.find(prefix, ossimKeywordNames::STD_PARALLEL_1_KW); + const char* stdParallel2 = kwl.find(prefix, ossimKeywordNames::STD_PARALLEL_2_KW); + + + if(ossimString(type) == STATIC_TYPE_NAME(ossimAlbersProjection)) + { + if(falseEasting) + { + Albers_False_Easting = ossimString(falseEasting).toDouble(); + } + if(falseNorthing) + { + Albers_False_Northing = ossimString(falseNorthing).toDouble(); + } + if(stdParallel1) + { + Albers_Std_Parallel_1 = ossimString(stdParallel1).toDouble()*RAD_PER_DEG; + } + else + { + Albers_Std_Parallel_1 = 29.5*RAD_PER_DEG; + } + if(stdParallel2) + { + Albers_Std_Parallel_2 = ossimString(stdParallel2).toDouble()*RAD_PER_DEG; + } + else + { + Albers_Std_Parallel_2 = 45.5*RAD_PER_DEG; + } + } + + update(); + + return flag; +} + + +/***************************************************************************/ +/* + * FUNCTIONS + */ +long ossimAlbersProjection::Set_Albers_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double Std_Parallel_1, + double Std_Parallel_2, + double False_Easting, + double False_Northing) + +{ +/* + * The function Set_Albers_Parameters receives the ellipsoid parameters and + * projection parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the function, + * otherwise ALBERS_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at which the (input) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * Std_Parallel_1 : First standard parallel (input) + * Std_Parallel_2 : Second standard parallel (input) + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + + double sin_lat, sin_lat_1, cos_lat; + double m1, m2, SQRm1; + double q0, q1, q2; + double es_sin, one_MINUS_SQRes_sin; + double nq0; + double inv_f = 1 / f; + long Error_Code = ALBERS_NO_ERROR; + + if (a <= 0.0) + { /* Semi-major axis must be greater than zero */ + Error_Code |= ALBERS_A_ERROR; + } + if ((inv_f < 250) || (inv_f > 350)) + { /* Inverse flattening must be between 250 and 350 */ + Error_Code |= ALBERS_INV_F_ERROR; + } + if ((Origin_Latitude < -PI_OVER_2) || (Origin_Latitude > PI_OVER_2)) + { /* origin latitude out of range */ + Error_Code |= ALBERS_ORIGIN_LAT_ERROR; + } + if ((Central_Meridian < -M_PI) || (Central_Meridian > TWO_PI)) + { /* origin longitude out of range */ + Error_Code |= ALBERS_CENT_MER_ERROR; + } + if ((Std_Parallel_1 < -PI_OVER_2) || (Std_Parallel_1 > PI_OVER_2)) + { /* First Standard Parallel out of range */ + Error_Code |= ALBERS_FIRST_STDP_ERROR; + } + if ((Std_Parallel_2 < -PI_OVER_2) || (Std_Parallel_2 > PI_OVER_2)) + { /* Second Standard Parallel out of range */ + Error_Code |= ALBERS_SECOND_STDP_ERROR; + } + if ((Std_Parallel_1 == 0.0) && (Std_Parallel_2 == 0.0)) + { /* First & Second Standard Parallels equal 0 */ + Error_Code |= ALBERS_FIRST_SECOND_ERROR; + } + if (Std_Parallel_1 == -Std_Parallel_2) + { /* Parallels are opposite latitudes */ + Error_Code |= ALBERS_HEMISPHERE_ERROR; + } + + if (!Error_Code) + { /* no errors */ + Albers_a = a; + Albers_f = f; + Albers_Origin_Lat = Origin_Latitude; + Albers_Std_Parallel_1 = Std_Parallel_1; + Albers_Std_Parallel_2 = Std_Parallel_2; + if (Central_Meridian > M_PI) + Central_Meridian -= TWO_PI; + Albers_Origin_Long = Central_Meridian; + Albers_False_Easting = False_Easting; + Albers_False_Northing = False_Northing; + + es2 = 2 * Albers_f - Albers_f * Albers_f; + es = sqrt(es2); + one_MINUS_es2 = 1 - es2; + two_es = 2 * es; + + sin_lat = sin(Albers_Origin_Lat); + es_sin = ES_SIN(sin_lat); + one_MINUS_SQRes_sin = ONE_MINUS_SQR(es_sin); + q0 = ALBERS_Q(sin_lat, one_MINUS_SQRes_sin, es_sin); + + sin_lat_1 = sin(Albers_Std_Parallel_1); + cos_lat = cos(Albers_Std_Parallel_1); + es_sin = ES_SIN(sin_lat_1); + one_MINUS_SQRes_sin = ONE_MINUS_SQR(es_sin); + m1 = ALBERS_M(cos_lat, one_MINUS_SQRes_sin); + q1 = ALBERS_Q(sin_lat_1, one_MINUS_SQRes_sin, es_sin); + + SQRm1 = m1 * m1; + if (fabs(Albers_Std_Parallel_1 - Albers_Std_Parallel_2) > 1.0e-10) + { + sin_lat = sin(Albers_Std_Parallel_2); + cos_lat = cos(Albers_Std_Parallel_2); + es_sin = ES_SIN(sin_lat); + one_MINUS_SQRes_sin = ONE_MINUS_SQR(es_sin); + m2 = ALBERS_M(cos_lat, one_MINUS_SQRes_sin); + q2 = ALBERS_Q(sin_lat, one_MINUS_SQRes_sin, es_sin); + n = (SQRm1 - m2 * m2) / (q2 - q1); + } + else + n = sin_lat_1; + + C = SQRm1 + n * q1; + Albers_a_OVER_n = Albers_a / n; + nq0 = n * q0; + if (C < nq0) + rho0 = 0; + else + rho0 = Albers_a_OVER_n * sqrt(C - nq0); + + + } /* END OF if(!Error_Code) */ + return (Error_Code); +} /* END OF Set_Albers_Parameters */ + + +void ossimAlbersProjection::Get_Albers_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *Std_Parallel_1, + double *Std_Parallel_2, + double *False_Easting, + double *False_Northing)const + +{ /* BEGIN Get_Albers_Parameters */ +/* + * The function Get_Albers_Parameters returns the current ellipsoid + * parameters, and Albers projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at which the (output) + * point scale factor is 1.0 + * Origin_Longitude : Longitude in radians at the center of (output) + * the projection + * Std_Parallel_1 : First standard parallel (output) + * Std_Parallel_2 : Second standard parallel (output) + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + + *a = Albers_a; + *f = Albers_f; + *Origin_Latitude = Albers_Origin_Lat; + *Std_Parallel_1 = Albers_Std_Parallel_1; + *Std_Parallel_2 = Albers_Std_Parallel_2; + *Central_Meridian = Albers_Origin_Long; + *False_Easting = Albers_False_Easting; + *False_Northing = Albers_False_Northing; + return; +} /* END OF Get_Albers_Parameters */ + + +long ossimAlbersProjection::Convert_Geodetic_To_Albers (double Latitude, + double Longitude, + double *Easting, + double *Northing)const + +{ /* BEGIN Convert_Geodetic_To_Albers */ +/* + * The function Convert_Geodetic_To_Albers converts geodetic (latitude and + * longitude) coordinates to Albers projection (easting and northing) + * coordinates, according to the current ellipsoid and Albers projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise ALBERS_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + + double dlam; /* Longitude - Central Meridan */ + double sin_lat, cos_lat; + double es_sin, one_MINUS_SQRes_sin; + double q; + double rho; + double theta; + double nq; + long Error_Code = ALBERS_NO_ERROR; + + if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2)) + { /* Latitude out of range */ + Error_Code |= ALBERS_LAT_ERROR; + } + if ((Longitude < -M_PI) || (Longitude > TWO_PI)) + { /* Longitude out of range */ + Error_Code|= ALBERS_LON_ERROR; + } + + if (!Error_Code) + { /* no errors */ + + dlam = Longitude - Albers_Origin_Long; + if (dlam > M_PI) + { + dlam -= TWO_PI; + } + if (dlam < -M_PI) + { + dlam += TWO_PI; + } + sin_lat = sin(Latitude); + cos_lat = cos(Latitude); + es_sin = ES_SIN(sin_lat); + one_MINUS_SQRes_sin = ONE_MINUS_SQR(es_sin); + q = ALBERS_Q(sin_lat, one_MINUS_SQRes_sin, es_sin); + nq = n * q; + if (C < nq) + rho = 0; + else + rho = Albers_a_OVER_n * sqrt(C - nq); + + + theta = n * dlam; + *Easting = rho * sin(theta) + Albers_False_Easting; + *Northing = rho0 - rho * cos(theta) + Albers_False_Northing; + } + return (Error_Code); +} /* END OF Convert_Geodetic_To_Albers */ + + +long ossimAlbersProjection::Convert_Albers_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const +{ /* BEGIN Convert_Albers_To_Geodetic */ +/* + * The function Convert_Albers_To_Geodetic converts Albers projection + * (easting and northing) coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Albers projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise ALBERS_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + + double dy, dx; + double rho0_MINUS_dy; + double q, qconst, q_OVER_2; + double rho, rho_n; + double PHI, Delta_PHI = 1.0; + double sin_phi; + double es_sin, one_MINUS_SQRes_sin; + double theta = 0.0; + double tolerance = 4.85e-10; /* approximately 1/1000th of + an arc second or 1/10th meter */ + long Error_Code = ALBERS_NO_ERROR; + + if ((Easting < (Albers_False_Easting - Albers_Delta_Easting)) + || (Easting > Albers_False_Easting + Albers_Delta_Easting)) + { /* Easting out of range */ + Error_Code |= ALBERS_EASTING_ERROR; + } + if ((Northing < (Albers_False_Northing - Albers_Delta_Northing)) + || (Northing > Albers_False_Northing + Albers_Delta_Northing)) + { /* Northing out of range */ + Error_Code |= ALBERS_NORTHING_ERROR; + } + + if (!Error_Code) + { + dy = Northing - Albers_False_Northing; + dx = Easting - Albers_False_Easting; + rho0_MINUS_dy = rho0 - dy; + rho = sqrt(dx * dx + rho0_MINUS_dy * rho0_MINUS_dy); + + if (n < 0) + { + rho *= -1.0; + dy *= -1.0; + dx *= -1.0; + rho0_MINUS_dy *= -1.0; + } + + if (rho != 0.0) + theta = atan2(dx, rho0_MINUS_dy); + rho_n = rho * n; + q = (C - (rho_n * rho_n) / (Albers_a * Albers_a)) / n; + qconst = 1 - ((one_MINUS_es2) / (two_es)) * log((1.0 - es) / (1.0 + es)); + if (fabs(fabs(qconst) - fabs(q)) > 1.0e-6) + { + q_OVER_2 = q / 2.0; + if (q_OVER_2 > 1.0) + *Latitude = PI_OVER_2; + else if (q_OVER_2 < -1.0) + *Latitude = -PI_OVER_2; + else + { + PHI = asin(q_OVER_2); + if (es < 1.0e-10) + *Latitude = PHI; + else + { + while (fabs(Delta_PHI) > tolerance) + { + sin_phi = sin(PHI); + es_sin = ES_SIN(sin_phi); + one_MINUS_SQRes_sin = ONE_MINUS_SQR(es_sin); + Delta_PHI = (one_MINUS_SQRes_sin * one_MINUS_SQRes_sin) / (2.0 * cos(PHI)) * + (q / (one_MINUS_es2) - sin_phi / one_MINUS_SQRes_sin + + (log((1.0 - es_sin) / (1.0 + es_sin)) / (two_es))); + PHI += Delta_PHI; + } + *Latitude = PHI; + } + + if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */ + *Latitude = PI_OVER_2; + else if (*Latitude < -PI_OVER_2) + *Latitude = -PI_OVER_2; + + } + } + else + { + if (q >= 0.0) + *Latitude = PI_OVER_2; + else + *Latitude = -PI_OVER_2; + } + *Longitude = Albers_Origin_Long + theta / n; + + if (*Longitude > M_PI) + *Longitude -= TWO_PI; + if (*Longitude < -M_PI) + *Longitude += TWO_PI; + + if (*Longitude > M_PI) /* force distorted values to 180, -180 degrees */ + *Longitude = M_PI; + else if (*Longitude < -M_PI) + *Longitude = -M_PI; + + } + return (Error_Code); +} /* END OF Convert_Albers_To_Geodetic */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimAlbersProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimAlbersProjection.h new file mode 100644 index 0000000000..18382b0572 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimAlbersProjection.h @@ -0,0 +1,252 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Albers projection code. +//******************************************************************* +// $Id: ossimAlbersProjection.h,v 1.9 2005/09/09 19:23:58 gpotts Exp $ + +#ifndef ossimAlbersProjection_HEADER +#define ossimAlbersProjection_HEADER +#include "ossimMapProjection.h" + +//! Albers Equal Area Conic Projection +/*! + * A basic conic projection developed by H.C. Albers. Classified as a + * conic and equal area. A graphic can be found at: + * http://everest.hunter.cuny.edu/mp/pbander/albers.gif + */ + +class ossimAlbersProjection : public ossimMapProjection +{ +public: + ossimAlbersProjection(const ossimEllipsoid& ellipsoid = ossimEllipsoid(), + const ossimGpt& origin = ossimGpt()); + ossimAlbersProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double stdParallel1, + double stdParallel2, + double falseEasting, + double falseNorthing); + + virtual ~ossimAlbersProjection(); + + ossimObject *dup()const; + + virtual ossimDpt forward(const ossimGpt &worldPoint) const; + virtual ossimGpt inverse(const ossimDpt &projectedPoint)const; + virtual void update(); + + /*! + * The passed in Argument is in degrees and will convert it to radians + * for Geotrans. Update is then called so we can pre-compute paramters. + */ + void setStandardParallel1(double degree); + + /*! + * The passed in Argument is in degrees and will convert it to radians + * for Geotrans. Update is then called so we can pre-compute paramters + */ + void setStandardParallel2(double degree); + + /*! + * Will allow you to set both parallels. both are passed in degrees. + */ + void setStandardParallels(double parallel1Degree, + double prallel2Degree); + + /*! + * SetFalseEasting. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEasting(double falseEasting); + + /*! + * SetFalseNorthing. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseNorthing(double falseNorthing); + + /*! + * Sets both false easting and northing values. The values are + * expected to be in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEastingNorthing(double falseEasting, double falseNorthing); + + /*! + * Allows one to set all parameters for this projections. parallels are in + * degrees and easting northings are in meters. + * Update is then called so we can pre-compute paramters. + */ + void setParameters(double parallel1, + double parallel2, + double falseEasting, + double falseNorthing); + + virtual double getStandardParallel1() const; + virtual double getStandardParallel2() const; + virtual double getFalseEasting() const; + virtual double getFalseNorthing() const; + + void setDefaults(); + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); +private: + + + //________________________GEOTRANS__________________________ + // + mutable double Albers_a; /* Semi-major axis of ellipsoid in meters */ + mutable double Albers_f; /* Flattening of ellipsoid */ + mutable double es; /* Eccentricity of ellipsoid */ + mutable double es2; /* Eccentricity squared */ + mutable double C; /* constant c */ + mutable double rho0; /* height above ellipsoid */ + mutable double n; /* ratio between meridians */ + mutable double Albers_a_OVER_n; /* Albers_a / n */ + mutable double one_MINUS_es2; /* 1 - es2 */ + mutable double two_es; /* 2 * es */ + +/* Albers Projection Parameters */ + mutable double Albers_Origin_Lat; /* Latitude of origin in radians */ + mutable double Albers_Origin_Long; /* Longitude of origin in radians */ + mutable double Albers_Std_Parallel_1; + mutable double Albers_Std_Parallel_2; + mutable double Albers_False_Easting; + mutable double Albers_False_Northing; + + mutable double Albers_Delta_Northing; + mutable double Albers_Delta_Easting; + +/*! + * The function Set_Albers_Parameters receives the ellipsoid parameters and + * projection parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the function, + * otherwise ALBERS_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at which the (input) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (input) + * the projection (central meridian) + * Std_Parallel_1 : First standard parallel (input) + * Std_Parallel_2 : Second standard parallel (input) + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + long Set_Albers_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double Std_Parallel_1, + double Std_Parallel_2, + double False_Easting, + double False_Northing); + + +/*! + * The function Get_Albers_Parameters returns the current ellipsoid + * parameters, and Albers projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at which the (output) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * Std_Parallel_1 : First standard parallel (output) + * Std_Parallel_2 : Second standard parallel (output) + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + void Get_Albers_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *Std_Parallel_1, + double *Std_Parallel_2, + double *False_Easting, + double *False_Northing)const; + + + +/*! + * The function Convert_Geodetic_To_Albers converts geodetic (latitude and + * longitude) coordinates to Albers projection (easting and northing) + * coordinates, according to the current ellipsoid and Albers projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise ALBERS_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + long Convert_Geodetic_To_Albers (double Latitude, + double Longitude, + double *Easting, + double *Northing)const; + + + +/*! + * The function Convert_Albers_To_Geodetic converts Albers projection + * (easting and northing) coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Albers projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise ALBERS_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + long Convert_Albers_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const; + + + +/* + * RTTI information defined in data_types/rtti.h + */ +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimAzimEquDistProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimAzimEquDistProjection.cpp new file mode 100644 index 0000000000..63cd95f8a8 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimAzimEquDistProjection.cpp @@ -0,0 +1,491 @@ +#include "ossimAzimEquDistProjection.h" +#include "base/common/ossimKeywordNames.h" +#include "base/data_types/ossimKeywordlist.h" +#include "base/common/ossimTrace.h" + + +#define PI_OVER_2 ( M_PI / 2.0) +#define ONE (1.0 * M_PI / 180.0) /* 1 degree in radians */ + +#define AZEQ_NO_ERROR 0x0000 +#define AZEQ_LAT_ERROR 0x0001 +#define AZEQ_LON_ERROR 0x0002 +#define AZEQ_EASTING_ERROR 0x0004 +#define AZEQ_NORTHING_ERROR 0x0008 +#define AZEQ_ORIGIN_LAT_ERROR 0x0010 +#define AZEQ_CENT_MER_ERROR 0x0020 +#define AZEQ_A_ERROR 0x0040 +#define AZEQ_INV_F_ERROR 0x0080 +#define AZEQ_PROJECTION_ERROR 0x0100 + +RTTI_DEF1(ossimAzimEquDistProjection,"ossimAzimEquDistProjection", ossimMapProjection) + +ossimAzimEquDistProjection::ossimAzimEquDistProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + :ossimMapProjection(ellipsoid, + origin) +{ + setDefaults(); +} + +ossimAzimEquDistProjection::ossimAzimEquDistProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double falseEasting, + double falseNorthing) + :ossimMapProjection(ellipsoid, + origin) +{ + setFalseEastingNorthing(falseEasting, falseNorthing); +} + +void ossimAzimEquDistProjection::update() +{ + ossimMapProjection::update(); + Set_Azimuthal_Equidistant_Parameters(theEllipsoid.getA(), + theEllipsoid.getFlattening(), + theOrigin.latr(), + theOrigin.lonr(), + Azeq_False_Easting, + Azeq_False_Northing); + +} + +ossimGpt ossimAzimEquDistProjection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat, lon; + + Convert_Azimuthal_Equidistant_To_Geodetic(eastingNorthing.x, + eastingNorthing.y, + &lat, + &lon); + + return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum); +} + +ossimDpt ossimAzimEquDistProjection::forward(const ossimGpt &latLon)const +{ + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + Convert_Geodetic_To_Azimuthal_Equidistant(gpt.latr(), + gpt.lonr(), + &easting, + &northing); + return ossimDpt(easting, northing); +} + +void ossimAzimEquDistProjection::setFalseEasting(double falseEasting) +{ + Azeq_False_Easting = falseEasting; + + update(); +} + +void ossimAzimEquDistProjection::setFalseNorthing(double falseNorthing) +{ + Azeq_False_Northing = falseNorthing; + + update(); +} + +void ossimAzimEquDistProjection::setFalseEastingNorthing(double falseEasting, + double falseNorthing) +{ + Azeq_False_Easting = falseEasting; + Azeq_False_Northing = falseNorthing; + + update(); +} + +void ossimAzimEquDistProjection::setDefaults() +{ + Azeq_False_Easting = 0.0; + Azeq_False_Northing = 0.0; + update(); +} + +bool ossimAzimEquDistProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const +{ + ossimMapProjection::saveState(kwl, prefix); + + kwl.add(prefix, + ossimKeywordNames::FALSE_EASTING_KW, + Azeq_False_Easting, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_NORTHING_KW, + Azeq_False_Northing, + true); + + return true; +} + +bool ossimAzimEquDistProjection::loadState(const ossimKeywordlist& kwl, const char* prefix) +{ + bool flag = ossimMapProjection::loadState(kwl, prefix); + + update(); + + const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + const char* falseEasting = kwl.find(prefix, ossimKeywordNames::FALSE_EASTING_KW); + const char* falseNorthing = kwl.find(prefix, ossimKeywordNames::FALSE_NORTHING_KW); + setDefaults(); + if(ossimString(type) == STATIC_TYPE_NAME(ossimAzimEquDistProjection)) + { + if(falseEasting) + { + Azeq_False_Easting = ossimString(falseEasting).toDouble(); + } + if(falseNorthing) + { + Azeq_False_Northing = ossimString(falseNorthing).toDouble(); + } + } + + update(); + + return flag; +} + +long ossimAzimEquDistProjection::Set_Azimuthal_Equidistant_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing) +{ +/* BEGIN Set_Azimuthal_Equidistant_Parameters */ +/* + * The function Set_Azimuthal_Equidistant_Parameters receives the ellipsoid parameters and + * projection parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the function, + * otherwise AZEQ_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at which the (input) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + + double es2, es4, es6; +// double inv_f = 1 / f; + double temp_Northing = 0.0; + long Error_Code = AZEQ_NO_ERROR; + +// if (a <= 0.0) +// { /* Semi-major axis must be greater than zero */ +// Error_Code |= AZEQ_A_ERROR; +// } +// if ((inv_f < 250) || (inv_f > 350)) +// { /* Inverse flattening must be between 250 and 350 */ +// Error_Code |= AZEQ_INV_F_ERROR; +// } +// if ((Origin_Latitude < -PI_OVER_2) || (Origin_Latitude > PI_OVER_2)) +// { /* origin latitude out of range */ +// Error_Code |= AZEQ_ORIGIN_LAT_ERROR; +// } +// if ((Central_Meridian < -PI) || (Central_Meridian > TWO_PI)) +// { /* origin longitude out of range */ +// Error_Code |= AZEQ_CENT_MER_ERROR; +// } + if (!Error_Code) + { /* no errors */ + Azeq_a = a; + Azeq_f = f; + es2 = 2 * Azeq_f - Azeq_f * Azeq_f; + es4 = es2 * es2; + es6 = es4 * es2; + /* spherical radius */ + Ra = Azeq_a * (1.0 - es2 / 6.0 - 17.0 * es4 / 360.0 - 67.0 * es6 / 3024.0); + Azeq_Origin_Lat = Origin_Latitude; + Sin_Azeq_Origin_Lat = sin(Azeq_Origin_Lat); + Cos_Azeq_Origin_Lat = cos(Azeq_Origin_Lat); + abs_Azeq_Origin_Lat = fabs(Azeq_Origin_Lat); +// if (Central_Meridian > M_PI) +// Central_Meridian -= TWO_PI; + Azeq_Origin_Long = Central_Meridian; + Azeq_False_Northing = False_Northing; + Azeq_False_Easting = False_Easting; + + if (fabs(abs_Azeq_Origin_Lat - PI_OVER_2) < 1.0e-10) + { + Azeq_Delta_Northing = 20015110.0; + Azeq_Delta_Easting = 20015110.0; + } + else if (abs_Azeq_Origin_Lat >= 1.0e-10) + { + if (Azeq_Origin_Long > 0.0) + { + Convert_Geodetic_To_Azimuthal_Equidistant(-Azeq_Origin_Lat, + (Azeq_Origin_Long - M_PI - ONE), &Azeq_Delta_Easting, &temp_Northing); + } + else + { + Convert_Geodetic_To_Azimuthal_Equidistant(-Azeq_Origin_Lat, + (Azeq_Origin_Long + M_PI - ONE), &Azeq_Delta_Easting, &temp_Northing); + } + Azeq_Delta_Northing = 19903915.0; + } + else + { + Azeq_Delta_Northing = 19903915.0; + Azeq_Delta_Easting = 19903915.0; + } + } /* End if(!Error_Code) */ + return (Error_Code); +} /* End Set_Azimuthal_Equidistant_Parameters */ + + +void ossimAzimEquDistProjection::Get_Azimuthal_Equidistant_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const +{ +/* Begin Get_Azimuthal_Equidistant_Parameters */ +/* + * The function Get_Azimuthal_Equidistant_Parameters returns the current ellipsoid + * parameters and Azimuthal Equidistant projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at which the (output) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + + *a = Azeq_a; + *f = Azeq_f; + *Origin_Latitude = Azeq_Origin_Lat; + *Central_Meridian = Azeq_Origin_Long; + *False_Easting = Azeq_False_Easting; + *False_Northing = Azeq_False_Northing; + return; +} /* End Get_Azimuthal_Equidistant_Parameters */ + + +long ossimAzimEquDistProjection::Convert_Geodetic_To_Azimuthal_Equidistant (double Latitude, + double Longitude, + double *Easting, + double *Northing)const +{ +/* Begin Convert_Geodetic_To_Azimuthal_Equidistant */ +/* + * The function Convert_Geodetic_To_Azimuthal_Equidistant converts geodetic (latitude and + * longitude) coordinates to Azimuthal Equidistant projection (easting and northing) + * coordinates, according to the current ellipsoid and Azimuthal Equidistant projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise AZEQ_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + + double dlam; /* Longitude - Central Meridan */ + double k_prime; /* scale factor */ + double c; /* angular distance from center */ + double slat = sin(Latitude); + double clat = cos(Latitude); + double cos_c; + double sin_dlam, cos_dlam; + double Ra_kprime; + double Ra_PI_OVER_2_Lat; + long Error_Code = AZEQ_NO_ERROR; + +// if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2)) +// { /* Latitude out of range */ +// Error_Code |= AZEQ_LAT_ERROR; +// } +// if ((Longitude < -M_PI) || (Longitude > TWO_PI)) +// { /* Longitude out of range */ +// Error_Code |= AZEQ_LON_ERROR; +// } + if (!Error_Code) + { /* no errors */ + dlam = Longitude - Azeq_Origin_Long; + if (dlam > M_PI) + { + dlam -= TWO_PI; + } + if (dlam < -M_PI) + { + dlam += TWO_PI; + } + + sin_dlam = sin(dlam); + cos_dlam = cos(dlam); + if (fabs(abs_Azeq_Origin_Lat - PI_OVER_2) < 1.0e-10) + { + if (Azeq_Origin_Lat >= 0.0) + { + Ra_PI_OVER_2_Lat = Ra * (PI_OVER_2 - Latitude); + *Easting = Ra_PI_OVER_2_Lat * sin_dlam + Azeq_False_Easting; + *Northing = -1.0 * (Ra_PI_OVER_2_Lat * cos_dlam) + Azeq_False_Northing; + } + else + { + Ra_PI_OVER_2_Lat = Ra * (PI_OVER_2 + Latitude); + *Easting = Ra_PI_OVER_2_Lat * sin_dlam + Azeq_False_Easting; + *Northing = Ra_PI_OVER_2_Lat * cos_dlam + Azeq_False_Northing; + } + } + else if (abs_Azeq_Origin_Lat <= 1.0e-10) + { + cos_c = clat * cos_dlam; + if (fabs(fabs(cos_c) - 1.0) < 1.0e-14) + { + if (cos_c >= 0.0) + { + *Easting = Azeq_False_Easting; + *Northing = Azeq_False_Northing; + } + else + { + /* if cos_c == -1 */ + Error_Code |= AZEQ_PROJECTION_ERROR; + } + } + else + { + c = acos(cos_c); + k_prime = c / sin(c); + Ra_kprime = Ra * k_prime; + *Easting = Ra_kprime * clat * sin_dlam + Azeq_False_Easting; + *Northing = Ra_kprime * slat + Azeq_False_Northing; + } + } + else + { + cos_c = (Sin_Azeq_Origin_Lat * slat) + (Cos_Azeq_Origin_Lat * clat * cos_dlam); + if (fabs(fabs(cos_c) - 1.0) < 1.0e-14) + { + if (cos_c >= 0.0) + { + *Easting = Azeq_False_Easting; + *Northing = Azeq_False_Northing; + } + else + { + /* if cos_c == -1 */ + Error_Code |= AZEQ_PROJECTION_ERROR; + } + } + else + { + c = acos(cos_c); + k_prime = c / sin(c); + Ra_kprime = Ra * k_prime; + *Easting = Ra_kprime * clat * sin_dlam + Azeq_False_Easting; + *Northing = Ra_kprime * (Cos_Azeq_Origin_Lat * slat - Sin_Azeq_Origin_Lat * clat * cos_dlam) + Azeq_False_Northing; + } + } + } + return (Error_Code); +} /* End Convert_Geodetic_To_Azimuthal_Equidistant */ + + +long ossimAzimEquDistProjection::Convert_Azimuthal_Equidistant_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const +{ /* Begin Convert_Azimuthal_Equidistant_To_Geodetic */ +/* + * The function Convert_Azimuthal_Equidistant_To_Geodetic converts Azimuthal_Equidistant projection + * (easting and northing) coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Azimuthal_Equidistant projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise AZEQ_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + + double dx, dy; + double rho; /* height above ellipsoid */ + double c; /* angular distance from center */ + double sin_c, cos_c, dy_sinc; + long Error_Code = AZEQ_NO_ERROR; + +// if ((Easting < (Azeq_False_Easting - Azeq_Delta_Easting)) +// || (Easting > (Azeq_False_Easting + Azeq_Delta_Easting))) +// { /* Easting out of range */ +// Error_Code |= AZEQ_EASTING_ERROR; +// } +// if ((Northing < (Azeq_False_Northing - Azeq_Delta_Northing)) +// || (Northing > (Azeq_False_Northing + Azeq_Delta_Northing))) +// { /* Northing out of range */ +// Error_Code |= AZEQ_NORTHING_ERROR; +// } + + if (!Error_Code) + { + dy = Northing - Azeq_False_Northing; + dx = Easting - Azeq_False_Easting; + rho = sqrt(dx * dx + dy * dy); + if (fabs(rho) <= 1.0e-10) + { + *Latitude = Azeq_Origin_Lat; + *Longitude = Azeq_Origin_Long; + } + else + { + c = rho / Ra; + sin_c = sin(c); + cos_c = cos(c); + dy_sinc = dy * sin_c; + *Latitude = asin((cos_c * Sin_Azeq_Origin_Lat) + ((dy_sinc * Cos_Azeq_Origin_Lat) / rho)); + if (fabs(abs_Azeq_Origin_Lat - PI_OVER_2) < 1.0e-10) + { + if (Azeq_Origin_Lat >= 0.0) + *Longitude = Azeq_Origin_Long + atan2(dx, -dy); + else + *Longitude = Azeq_Origin_Long + atan2(dx, dy); + } + else + *Longitude = Azeq_Origin_Long + atan2((dx * sin_c), ((rho * Cos_Azeq_Origin_Lat * cos_c) - (dy_sinc * Sin_Azeq_Origin_Lat))); + } + + if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */ + *Latitude = PI_OVER_2; + else if (*Latitude < -PI_OVER_2) + *Latitude = -PI_OVER_2; + +// if (*Longitude > M_PI) +// *Longitude -= TWO_PI; +// if (*Longitude < -M_PI) +// *Longitude += TWO_PI; + + if (*Longitude > M_PI) /* force distorted values to 180, -180 degrees */ + *Longitude = M_PI; + else if (*Longitude < -M_PI) + *Longitude = -M_PI; + + } + return (Error_Code); +} /* End Convert_Azimuthal_Equidistant_To_Geodetic */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimAzimEquDistProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimAzimEquDistProjection.h new file mode 100644 index 0000000000..3747d63248 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimAzimEquDistProjection.h @@ -0,0 +1,197 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Equidistant Cylinder projection code. +//******************************************************************* +// $Id: ossimAzimEquDistProjection.h,v 1.4 2005/09/09 19:23:58 gpotts Exp $ + +#ifndef ossimAzimEquDistProjection_HEADER +#define ossimAzimEquDistProjection_HEADER + +#include "ossimMapProjection.h" + +class ossimAzimEquDistProjection : public ossimMapProjection +{ +public: + ossimAzimEquDistProjection(const ossimEllipsoid& ellipsoid = ossimEllipsoid(), + const ossimGpt& origin = ossimGpt()); + + ossimAzimEquDistProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double falseEasting, + double falseNorthing); + + ossimAzimEquDistProjection(const ossimAzimEquDistProjection& rhs) + { + *this = rhs; + } + virtual ~ossimAzimEquDistProjection(){} + virtual ossimObject *dup()const + { + return new ossimAzimEquDistProjection(*this); + } + + virtual ossimGpt inverse(const ossimDpt &eastingNorthing)const; + virtual ossimDpt forward(const ossimGpt &latLon)const; + virtual void update(); + + double getFalseEasting()const{return Azeq_False_Easting;} + double getFalseNorthing()const{return Azeq_False_Northing;} + + /*! + * SetFalseEasting. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEasting(double falseEasting); + + /*! + * SetFalseNorthing. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseNorthing(double falseNorthing); + + /*! + * Sets both false easting and northing values. The values are + * expected to be in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEastingNorthing(double falseEasting, double falseNorthing); + + /*! + * Will initialize all parameters to a default values and then call + * update for pre-computations. + */ + void setDefaults(); + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); +protected: + mutable double abs_Azeq_Origin_Lat; + mutable double Azeq_a; /* Semi-major axis of ellipsoid in meters */ + mutable double Azeq_f; /* Flattening of ellipsoid */ + mutable double Ra; /* Spherical Radius */ + mutable double Sin_Azeq_Origin_Lat; + mutable double Cos_Azeq_Origin_Lat; + mutable double Azeq_Origin_Lat; /* Latitude of origin in radians */ + mutable double Azeq_Origin_Long; /* Longitude of origin in radians */ + mutable double Azeq_False_Northing; /* False northing in meters */ + mutable double Azeq_False_Easting; /* False easting in meters */ + + mutable double Azeq_Delta_Northing; + mutable double Azeq_Delta_Easting; +/*! + * The function Set_Azimuthal_Equidistant_Parameters receives the ellipsoid + * parameters and projection parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the function, + * otherwise AZEQ_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at which the (input) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + long Set_Azimuthal_Equidistant_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing); + +/*! + * The function Get_Azimuthal_Equidistant_Parameters returns the current ellipsoid + * parameters and Azimuthal Equidistant projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at which the (output) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + void Get_Azimuthal_Equidistant_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const; + + +/*! + * The function Convert_Geodetic_To_Azimuthal_Equidistant converts geodetic (latitude and + * longitude) coordinates to Azimuthal Equidistant projection (easting and northing) + * coordinates, according to the current ellipsoid and Azimuthal Equidistant projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise AZEQ_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + long Convert_Geodetic_To_Azimuthal_Equidistant (double Latitude, + double Longitude, + double *Easting, + double *Northing)const; + +/*! + * The function Convert_Azimuthal_Equidistant_To_Geodetic converts Azimuthal Equidistant + * projection (easting and northing) coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Azimuthal Equidistant projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise AZEQ_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + long Convert_Azimuthal_Equidistant_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const; + + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimBngProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimBngProjection.cpp new file mode 100644 index 0000000000..91b27cfadf --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimBngProjection.cpp @@ -0,0 +1,761 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//******************************************************************* +// $Id: ossimBngProjection.cpp,v 1.16 2004/06/23 20:12:57 dburken Exp $ +#include <projections/map_projections/ossimBngProjection.h> +#include <projections/map_projections/ossimTranmerc.h> +#include <base/factory/ossimDatumFactory.h> +#include <base/factory/ossimEllipsoidFactory.h> +#include <base/common/ossimKeywordNames.h> +#include <elevation/ossimElevManager.h> + +#include <string.h> +#include <stdio.h> + +#define BNG_NO_ERROR 0x0000 +#define BNG_LAT_ERROR 0x0001 +#define BNG_LON_ERROR 0x0002 +#define BNG_EASTING_ERROR 0x0004 +#define BNG_NORTHING_ERROR 0x0008 +#define BNG_INVALID_AREA_ERROR 0x0010 +#define BNG_STRING_ERROR 0x0020 +#define BNG_ELLIPSOID_ERROR 0x0040 + +#define PI_OVER_2 (M_PI / 2.0e0) /* PI over 2 */ +#define MAX_LAT (61.5 * M_PI / 180.0) /* 61.5 degrees */ +#define MIN_LAT (49.5 * M_PI / 180.0) /* 49.5 degrees */ +#define MAX_LON (3.5 * M_PI / 180.0) /* 3.5 degrees */ +#define MIN_LON (-10.0 * M_PI / 180.0) /* -10 degrees */ +#define BNG500GRID "STNOHJ" /* 500,000 unit square identifications */ +#define BNG100GRID "VWXYZQRSTULMNOPFGHJKABCDE" /* 100,000 unit square identifications */ +static double BNG_Max_Easting = 759961.0; +static double BNG_Max_Northing = 1257875.0; +static double BNG_Min_Easting = -133134.0; +static double BNG_Min_Northing = -14829.0; + +static char BNG_Letters[3] = "SV"; +static double BNG_Easting = 0.0; +static double BNG_Northing = 0.0; +static const char* Airy = "AA"; +static char BNG_Ellipsoid_Code[3] = "AA"; + +RTTI_DEF1(ossimBngProjection, "ossimBngProjection", ossimMapProjection); + +ossimBngProjection::ossimBngProjection() + :ossimMapProjection(*ossimEllipsoidFactory::instance()->create("AA"), + ossimGpt(49.0, -2.0, OSSIM_DBL_NAN, ossimDatumFactory::instance()->create("OGB-M"))) +{ + string_Broken = 0; + theDatum = ossimDatumFactory::instance()->create("OGB-M"); + update(); +} + + +ossimGpt ossimBngProjection::inverse(const ossimDpt &eastingNorthing)const +{ + char s[100]; + double lat; + double lon; + + string_Broken = 0; + Set_Transverse_Mercator_Parameters(BNG_a, BNG_f, BNG_Origin_Lat, + BNG_Origin_Long, BNG_False_Easting, + BNG_False_Northing, BNG_Scale_Factor); + + Convert_Transverse_Mercator_To_BNG(eastingNorthing.x, + eastingNorthing.y, + 5, + s); + Convert_BNG_To_Geodetic(s, + &lat, + &lon); + ossimGpt result(49, -2, OSSIM_DBL_NAN,theDatum); + result.latr(lat); + result.lonr(lon); + + return result; +} + +ossimDpt ossimBngProjection::forward(const ossimGpt &latLon)const +{ + char BNG[100]; + + string_Broken = 0; + Set_Transverse_Mercator_Parameters(BNG_a, BNG_f, BNG_Origin_Lat, + BNG_Origin_Long, BNG_False_Easting, + BNG_False_Northing, BNG_Scale_Factor); + + Convert_Geodetic_To_BNG (latLon.latr(), + latLon.lonr(), + 5, + BNG); + + ossimDpt en; + + Convert_BNG_To_Transverse_Mercator(BNG, + &en.x, + &en.y); + + return en; +} + +void ossimBngProjection::update() +{ + BNG_Origin_Lat = (49.0 * M_PI / 180.0); + BNG_Origin_Long = (-2.0 * M_PI / 180.0); + BNG_False_Northing = -100000.0; + BNG_False_Easting = 400000.0; + BNG_Scale_Factor = .9996012717; + BNG_a = 6377563.396; + BNG_f = 1 / 299.324964600; + + // ossimString code = theDatum->code(); + // if(code.upcase().contains("OGB")) + // { + theOrigin = ossimGpt(49.0, -2.0, OSSIM_DBL_NAN, theDatum); + // } + // else +// { +// theOrigin = ossimGpt(49.0, -2.0, OSSIM_DBL_NAN, ossimDatumFactory::instance()->create("OGB-7")); +// } + + ossimMapProjection::update(); +} + +/*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ +bool ossimBngProjection::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + ossimKeywordNames::TYPE_KW, + getClassName(), + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_EASTING_KW, + BNG_False_Easting, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_NORTHING_KW, + BNG_False_Northing, + true); + + kwl.add(prefix, + ossimKeywordNames::SCALE_FACTOR_KW, + BNG_Scale_Factor, + true); + + return ossimMapProjection::saveState(kwl, prefix); +} + +/*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ +bool ossimBngProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + + ossimMapProjection::loadState(kwl, + prefix); + + update(); + + return true; +} + + +long ossimBngProjection::Find_Index (char letter, + const char* letter_Array, + long *index)const +{ +/* + * The function Find_Index searches for a given letter in an array. + * It returns the index of the letter in the array if the letter is found. + * If the letter is not found, an error code is returned, otherwise + * BNG_NO_ERROR is returned. + * + * letter : Letter being searched for + * letter_Array : Array being searched + * index : Index of letter in array + */ + long i = 0; + long not_Found = 1; + long length = strlen(letter_Array); + long Error_Code = BNG_NO_ERROR; + + while ((i < length) && (not_Found)) + { + if (letter == letter_Array[i]) + { + *index = i; + not_Found = 0; + } + i++; + } + if (not_Found) + Error_Code = BNG_STRING_ERROR; + + return Error_Code; +} + +long ossimBngProjection::Round_BNG (double value)const +/* Round value to nearest integer, using standard engineering rule */ +{ /* Round_BNG */ + double ivalue; + long ival; + double fraction = modf (value, &ivalue); + ival = (long)(ivalue); + if ((fraction > 0.5) || ((fraction == 0.5) && (ival%2 == 1))) + ival++; + + return (ival); +} + +long ossimBngProjection::Make_BNG_String (char ltrnum[4], + long Easting, + long Northing, + char* BNG, + long Precision)const + +{ /* Make_BNG_String */ +/* Construct a BNG string from its component parts */ + double divisor; + long east; + long north; + long i; + long j; + double unitInterval; + long error_code = BNG_NO_ERROR; + + i = 0; + for (j = 0; j < 3; j++) + { + BNG[i++] = ltrnum[j]; + } + + divisor = pow ((double)10.0,(double) (5 - Precision)); + unitInterval = pow ((double)10.0, (double)Precision); + east = Round_BNG (Easting/divisor); + if (east == unitInterval) + east -= 1; + if ((Precision == 0) && (east == 1)) + east = 0; + i += sprintf (BNG + i, "%*.*ld",(int) Precision,(int) Precision, east); + + north = Round_BNG (Northing/divisor); + if (north == unitInterval) + north -= 1; + if ((Precision == 0) && (north == 1)) + north = 0; + i += sprintf (BNG + i, "%*.*ld",(int) Precision,(int) Precision, north); + + return (error_code); +} /* Make_BNG_String */ + +long ossimBngProjection::Break_BNG_String (char* BNG, + char Letters[3], + double* Easting, + double* Northing, + long* Precision)const +/* Break down a BNG string into its component parts */ +{ /* Break_BNG_String */ + long i = 0; + long j; + long num_digits = 0; + long num_letters; + long temp_error = 0; + long length = strlen(BNG); + long error_code = BNG_NO_ERROR; + + string_Broken = 1; + while (BNG[i] == ' ') + i++; /* skip any leading blanks */ + j = i; + while (isalpha(BNG[i])) + i++; + num_letters = i - j; + if (num_letters == 2) + { + /* get letters */ + Letters[0] = (char)toupper(BNG[j]); + Letters[1] = (char)toupper(BNG[j+1]); + Letters[2] = 0; + } + else + error_code |= BNG_STRING_ERROR; + if (!error_code) + { + error_code |= Check_Out_Of_Area(Letters[0], Letters[1]); + while (BNG[i] == ' ') + i++; + j = i; + if (BNG[length-1] == ' ') + length --; + while ((i < length) && (!temp_error)) + { + if (isdigit(BNG[i])) + i++; + else + { + temp_error = BNG_STRING_ERROR; + } + } + if (temp_error) + error_code |= temp_error; + if (!error_code) + { + num_digits = i - j; + if ((num_digits <= 10) && (num_digits%2 == 0)) + { + long n; + char east_string[6]; + char north_string[6]; + long east; + long north; + double multiplier; + + /* get easting & northing */ + n = num_digits / 2; + *Precision = n; + if (n > 0) + { + strncpy (east_string, BNG+j, n); + east_string[n] = 0; + sscanf (east_string, "%ld", &east); + strncpy (north_string, BNG+j+n, n); + north_string[n] = 0; + sscanf (north_string, "%ld", &north); + multiplier = pow ((double)10.0,(double)( 5 - n)); + *Easting = east * multiplier; + *Northing = north * multiplier; + } + else + { + *Easting = 0.0; + *Northing = 0.0; + } + } + else + error_code |= BNG_STRING_ERROR; + } + } + return (error_code); +} /* Break_BNG_String */ + +long ossimBngProjection::Check_Out_Of_Area(char BNG500, + char BNG100)const + +{ /* BEGIN Check_Out_Of_Area */ +/* + * The function Check_Out_Of_Area checks if the 500,000 and + * 100,000 unit square identifications are within the valid area. If + * they are not, an error code is returned, otherwise BNG_NO_ERROR + * is returned. + * + * BNG500 : 500,000 square unit identification + * BNG100 : 100,000 square unit identification + */ + + long Error_Code = BNG_NO_ERROR; + + switch (BNG500) + { + case 'S': + switch (BNG100) + { + case 'A': + case 'F': + case 'L': + Error_Code |= BNG_INVALID_AREA_ERROR; + break; + default: + break; + } + break; + case 'N': + switch (BNG100) + { + case 'V': + Error_Code |= BNG_INVALID_AREA_ERROR; + break; + default: + break; + } + break; + + case 'H': + if (BNG100 < 'L') + Error_Code |= BNG_INVALID_AREA_ERROR; + break; + case 'T': + switch (BNG100) + { + case 'D': + case 'E': + case 'J': + case 'K': + case 'O': + case 'P': + case 'T': + case 'U': + case 'X': + case 'Y': + case 'Z': + Error_Code |= BNG_INVALID_AREA_ERROR; + break; + default: + break; + } + break; + case 'O': + switch (BNG100) + { + case 'C': + case 'D': + case 'E': + case 'J': + case 'K': + case 'O': + case 'P': + case 'T': + case 'U': + case 'Y': + case 'Z': + Error_Code |= BNG_INVALID_AREA_ERROR; + break; + default: + break; + } + break; + case 'J': + switch (BNG100) + { + case 'L': + case 'M': + case 'Q': + case 'R': + case 'V': + case 'W': + Error_Code = BNG_NO_ERROR; + break; + default: + Error_Code |= BNG_INVALID_AREA_ERROR; + break; + } + break; + default: + Error_Code |= BNG_INVALID_AREA_ERROR; + break; + } + return Error_Code; +} /* END OF Check_Out_Of_Area */ + +long ossimBngProjection::Set_BNG_Parameters(char *Ellipsoid_Code) + +{ /* BEGIN Set_BNG_Parameters */ +/* + * The function Set_BNG_Parameters receives the ellipsoid code and sets + * the corresponding state variables. If any errors occur, the error code(s) + * are returned by the function, otherwise BNG_NO_ERROR is returned. + * + * Ellipsoid_Code : 2-letter code for ellipsoid (input) + */ + + long Error_Code = BNG_NO_ERROR; + + if (strcmp(Ellipsoid_Code, Airy) != 0) + { /* Ellipsoid must be Airy */ + Error_Code |= BNG_ELLIPSOID_ERROR; + } + + if (!Error_Code) + { /* no errors */ + strcpy(BNG_Ellipsoid_Code, Ellipsoid_Code); + string_Broken = 0; + + Set_Transverse_Mercator_Parameters(BNG_a, BNG_f, BNG_Origin_Lat, + BNG_Origin_Long, BNG_False_Easting, + BNG_False_Northing, BNG_Scale_Factor); + } + return (Error_Code); +} /* END of Set_BNG_Parameters */ + +void ossimBngProjection::Get_BNG_Parameters(char *Ellipsoid_Code) + +{ /* BEGIN Get_BNG_Parameters */ +/* + * The function Get_BNG_Parameters returns the current ellipsoid + * code. + * + * Ellipsoid_Code : 2-letter code for ellipsoid (output) + */ + + strcpy(Ellipsoid_Code, BNG_Ellipsoid_Code); + + return; +} /* END OF Get_BNG_Parameters */ + +long ossimBngProjection::Convert_Geodetic_To_BNG (double Latitude, + double Longitude, + long Precision, + char* BNG)const + +{ /* BEGIN Convert_Geodetic_To_BNG */ +/* + * The function Convert_Geodetic_To_BNG converts geodetic (latitude and + * longitude) coordinates to a BNG coordinate string, according to the + * current ellipsoid parameters. If any errors occur, the error code(s) + * are returned by the function, otherwise BNG_NO_ERROR is returned. + * + * Latitude : Latitude, in radians (input) + * Longitude : Longitude, in radians (input) + * Precision : Precision level of BNG string (input) + * BNG : British National Grid coordinate string (output) + * + */ + double TMEasting, TMNorthing; + long Error_Code = BNG_NO_ERROR; + + if ((Latitude < MIN_LAT) || (Latitude > MAX_LAT)) + { /* Latitude out of range */ + Error_Code|= BNG_LAT_ERROR; + } + if ((Longitude < MIN_LON) || (Longitude > MAX_LON)) + { /* Longitude out of range */ + Error_Code|= BNG_LON_ERROR; + } + + if (!Error_Code) + { /* no errors */ + + Error_Code |= Convert_Geodetic_To_Transverse_Mercator(Latitude, Longitude, &TMEasting, &TMNorthing); + + if ((TMEasting < 0.0) && (TMEasting > -2.0)) + TMEasting = 0.0; + if ((TMNorthing < 0.0) && (TMNorthing > -2.0)) + TMNorthing = 0.0; + + if ((TMEasting < BNG_Min_Easting) || (TMEasting > BNG_Max_Easting)) + Error_Code |= BNG_INVALID_AREA_ERROR; + if ((TMNorthing < BNG_Min_Northing) || (TMNorthing > BNG_Max_Northing)) + Error_Code |= BNG_INVALID_AREA_ERROR; + + if (!Error_Code) + Error_Code |= Convert_Transverse_Mercator_To_BNG(TMEasting, TMNorthing, Precision, BNG); + } + return Error_Code; +} /* END OF Convert_Geodetic_To_BNG */ + +long ossimBngProjection::Convert_BNG_To_Geodetic (char *BNG, + double *Latitude, + double *Longitude)const + +{ /* Convert_BNG_To_Geodetic */ +/* + * The function Convert_BNG_To_Geodetic converts a BNG coordinate string + * to geodetic (latitude and longitude) coordinates, according to the current + * ellipsoid parameters. If any errors occur, the error code(s) are returned + * by the function, otherwise BNG_NO_ERROR is returned. + * + * BNG : British National Grid coordinate string (input) + * Latitude : Latitude, in radians (output) + * Longitude : Longitude, in radians (output) + * + */ + + double TMEasting, TMNorthing; + long in_Precision; + long temp_Error = 0; + long Error_Code = BNG_NO_ERROR; + + Error_Code |= Break_BNG_String(BNG, BNG_Letters, &BNG_Easting, &BNG_Northing, &in_Precision); + + if(!Error_Code) + { + Error_Code |= Convert_BNG_To_Transverse_Mercator(BNG, &TMEasting, &TMNorthing); + + if ((TMEasting < BNG_Min_Easting) || (TMEasting > BNG_Max_Easting)) + Error_Code |= BNG_INVALID_AREA_ERROR; + if ((TMNorthing < BNG_Min_Northing) || (TMNorthing > BNG_Max_Northing)) + Error_Code |= BNG_INVALID_AREA_ERROR; + + if(!Error_Code) + { + temp_Error |= Convert_Transverse_Mercator_To_Geodetic(TMEasting, TMNorthing, Latitude, Longitude); + + if (temp_Error & TRANMERC_EASTING_ERROR) + Error_Code |= BNG_EASTING_ERROR; + if (temp_Error & TRANMERC_NORTHING_ERROR) + Error_Code |= BNG_NORTHING_ERROR; + + if ((*Latitude < MIN_LAT) || (*Latitude > MAX_LAT)) + Error_Code|= BNG_INVALID_AREA_ERROR; + if ((*Longitude < MIN_LON) || (*Longitude > MAX_LON)) + Error_Code|= BNG_INVALID_AREA_ERROR; + } + } + return Error_Code; +} /* END OF Convert_BNG_To_Geodetic */ + + +long ossimBngProjection::Convert_Transverse_Mercator_To_BNG(double Easting, + double Northing, + long Precision, + char *BNG)const + +{/* BEGIN Convert_Transverse_Mercator_To_BNG */ +/* + * The function Convert_Transverse_Mercator_To_BNG converts Transverse Mercator + * (easting and northing) coordinates to a BNG coordinate string, according + * to the current ellipsoid parameters. If any errors occur, the error code(s) + * are returned by the function, otherwise BNG_NO_ERROR is returned. + * + * Easting : Easting (X), in meters (input) + * Northing : Northing (Y), in meters (input) + * Precision : Precision level of BNG string (input) + * BNG : British National Grid coordinate string (output) + */ + + char letters[4]; + long x, y; + long index; + long temp_Easting, temp_Northing; + long Error_Code = BNG_NO_ERROR; + + if ((Easting < BNG_Min_Easting) || (Easting > BNG_Max_Easting)) + { /* Easting out of range */ + Error_Code |= BNG_EASTING_ERROR; + } + if ((Northing < BNG_Min_Northing) || (Northing > BNG_Max_Northing)) + { /* Northing out of range */ + Error_Code |= BNG_NORTHING_ERROR; + } + + if (!Error_Code) + { /* no errors */ + temp_Easting = Round_BNG(Easting); + temp_Northing = Round_BNG(Northing); + + temp_Easting += 1000000; + temp_Northing += 500000; + + x = temp_Easting / 500000; + y = temp_Northing / 500000; + + index = y * 5 + x; + if ((index >= 0) && (index < 25)) + { + letters[0] = BNG100GRID[index]; + temp_Easting %= 500000; + temp_Northing %= 500000; + x = temp_Easting / 100000; + y = temp_Northing / 100000; + index = y * 5 + x; + if ((index >= 0) && (index < 25)) + { + letters[1] = BNG100GRID[index]; + Error_Code |= Check_Out_Of_Area(letters[0], letters[1]); + if (!Error_Code) + { + letters[2] = ' '; + letters[3] = 0; + temp_Easting %= 100000; + temp_Northing %= 100000; + Make_BNG_String(letters, temp_Easting, temp_Northing, BNG, Precision); + } + } + else + { + long five_y = 5 * y; + if ((x >= (25 - five_y)) || (x < -five_y)) + Error_Code |= BNG_EASTING_ERROR; + if ((five_y >= (25 - x)) || (five_y < -x)) + Error_Code |= BNG_NORTHING_ERROR; + } + } + else + { + long five_y = 5 * y; + if ((x >= (25 - five_y)) || (x < -five_y)) + Error_Code |= BNG_EASTING_ERROR; + if ((five_y >= (25 - x)) || (five_y < -x)) + Error_Code |= BNG_NORTHING_ERROR; + } + } + return Error_Code; +} /* END OF Convert_Transverse_Mercator_To_BNG */ + + +long ossimBngProjection::Convert_BNG_To_Transverse_Mercator(char *BNG, + double *Easting, + double *Northing)const + +{ /* Convert_BNG_To_Transverse_Mercator */ +/* + * The function Convert_BNG_To_Transverse_Mercator converts a BNG coordinate string + * to Transverse Mercator projection (easting and northing) coordinates + * according to the current ellipsoid parameters. If any errors occur, + * the error code(s) are returned by the function, otherwise BNG_NO_ERROR + * is returned. + * + * BNG : British National Grid coordinate string (input) + * Easting : Easting (X), in meters (output) + * Northing : Northing (Y), in meters (output) + */ + long northing_Offset, easting_Offset; + long i = 0; + long j = 0; + long in_Precision; + long Error_Code = BNG_NO_ERROR; + + if (!string_Broken) + { + Error_Code |= Break_BNG_String(BNG, BNG_Letters, &BNG_Easting, &BNG_Northing, &in_Precision); + } + if (!Error_Code) + { + Error_Code |= Find_Index(BNG_Letters[0], BNG500GRID, &i); + if (!Error_Code) + { + northing_Offset = 500000 * (i / 2); + easting_Offset = 500000 * (i % 2); + + Error_Code |= Find_Index(BNG_Letters[1], BNG100GRID, &j); + if (!Error_Code) + { + northing_Offset += 100000 * (j / 5); + easting_Offset += 100000 * (j % 5); + + *Easting = BNG_Easting + easting_Offset; + *Northing = BNG_Northing + northing_Offset; + } + } + } + return Error_Code; +} /* END OF Convert_BNG_To_Transverse_Mercator */ + + + diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimBngProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimBngProjection.h new file mode 100644 index 0000000000..084711d163 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimBngProjection.h @@ -0,0 +1,159 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +//******************************************************************* +// $Id: ossimBngProjection.h,v 1.5 2005/09/09 19:23:58 gpotts Exp $ +#include <projections/map_projections/ossimMapProjection.h> + +class OSSIMDLLEXPORT ossimBngProjection : public ossimMapProjection +{ +public: + ossimBngProjection(); + + virtual ossimObject* dup()const + { + return new ossimBngProjection(*this); + } + + virtual ossimGpt inverse(const ossimDpt &eastingNorthing)const; + virtual ossimDpt forward(const ossimGpt &latLon)const; + virtual void update(); + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +protected: + +/* Ellipsoid Parameters, must be Airy */ + double BNG_a; /* Semi-major axis of ellipsoid, in meters */ + double BNG_f; /* Flattening of ellipsoid */ + +/* BNG projection Parameters */ + double BNG_Origin_Lat; /* Latitude of origin, in radians */ + double BNG_Origin_Long; /* Longitude of origin, in radians */ + double BNG_False_Northing; /* False northing, in meters */ + double BNG_False_Easting; /* False easting, in meters */ + double BNG_Scale_Factor; /* Scale factor */ + mutable long string_Broken; + + long Find_Index (char letter, + const char* letter_Array, + long *index)const; + + long Round_BNG (double value)const; + + long Make_BNG_String (char ltrnum[4], + long Easting, + long Northing, + char* BNG, + long Precision)const; + + long Break_BNG_String (char* BNG, + char Letters[3], + double* Easting, + double* Northing, + long* Precision)const; + + long Check_Out_Of_Area(char BNG500, + char BNG100)const; + + long Set_BNG_Parameters(char *Ellipsoid_Code); + void Get_BNG_Parameters(char *Ellipsoid_Code); + +/*! + * The function Convert_Geodetic_To_BNG converts geodetic (latitude and + * longitude) coordinates to a BNG coordinate string, according to the + * current ellipsoid parameters. If any errors occur, the error code(s) + * are returned by the function, otherwise BNG_NO_ERROR is returned. + * + * Latitude : Latitude, in radians (input) + * Longitude : Longitude, in radians (input) + * Precision : Precision level of BNG string (input) + * BNG : British National Grid coordinate string (output) + * + */ + long Convert_Geodetic_To_BNG (double Latitude, + double Longitude, + long Precision, + char* BNG)const; + + + +/*! + * The function Convert_BNG_To_Geodetic converts a BNG coordinate string + * to geodetic (latitude and longitude) coordinates, according to the current + * ellipsoid parameters. If any errors occur, the error code(s) are returned + * by the function, otherwise BNG_NO_ERROR is returned. + * + * BNG : British National Grid coordinate string (input) + * Latitude : Latitude, in radians (output) + * Longitude : Longitude, in radians (output) + * + */ + long Convert_BNG_To_Geodetic (char *BNG, + double *Latitude, + double *Longitude)const; + + +/*! + * The function Convert_Transverse_Mercator_To_BNG converts Transverse Mercator + * (easting and northing) coordinates to a BNG coordinate string, according + * to the current ellipsoid parameters. If any errors occur, the error code(s) + * are returned by the function, otherwise BNG_NO_ERROR is returned. + * + * Easting : Easting (X), in meters (input) + * Northing : Northing (Y), in meters (input) + * Precision : Precision level of BNG string (input) + * BNG : British National Grid coordinate string (output) + */ + long Convert_Transverse_Mercator_To_BNG(double Easting, + double Northing, + long Precision, + char *BNG)const; + + + +/*! + * The function Convert_BNG_To_Transverse_Mercator converts a BNG coordinate string + * to Transverse Mercator projection (easting and northing) coordinates + * according to the current ellipsoid parameters. If any errors occur, + * the error code(s) are returned by the function, otherwise BNG_NO_ERROR + * is returned. + * + * BNG : British National Grid coordinate string (input) + * Easting : Easting (X), in meters (output) + * Northing : Northing (Y), in meters (output) + */ + long Convert_BNG_To_Transverse_Mercator(char *BNG, + double *Easting, + double *Northing)const; + +TYPE_DATA +}; diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimBonneProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimBonneProjection.cpp new file mode 100644 index 0000000000..d03c08590e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimBonneProjection.cpp @@ -0,0 +1,541 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Bonne projection code. +//******************************************************************* +// $Id: ossimBonneProjection.cpp,v 1.12 2004/01/08 21:49:21 jlargent Exp $ +#include "ossimBonneProjection.h" +#include "ossimSinusoid.h" +#include "base/common/ossimKeywordNames.h" + +RTTI_DEF1(ossimBonneProjection, "ossimBonneProjection", ossimMapProjection) + + +/***************************************************************************/ +/* + * DEFINES + */ +#define BONN_NO_ERROR 0x0000 +#define BONN_LAT_ERROR 0x0001 +#define BONN_LON_ERROR 0x0002 +#define BONN_EASTING_ERROR 0x0004 +#define BONN_NORTHING_ERROR 0x0008 +#define BONN_ORIGIN_LAT_ERROR 0x0010 +#define BONN_CENT_MER_ERROR 0x0020 +#define BONN_A_ERROR 0x0040 +#define BONN_B_ERROR 0x0080 +#define BONN_A_LESS_B_ERROR 0x0100 + +#define PI_OVER_2 (M_PI / 2.0) +#define BONN_m(coslat,sinlat) (coslat/sqrt(1.0 - es2*sinlat*sinlat)) +#define BONN_M(c0lat,c1s2lat,c2s4lat,c3s6lat) (Bonn_a*(c0lat-c1s2lat+c2s4lat-c3s6lat)) +#define COEFF_TIMES_BONN_SIN(coeff,x,latit) (coeff*(sin(x * latit))) +#define FLOAT_EQ(x,v,epsilon) (((v - epsilon) < x) && (x < (v + epsilon))) + +ossimBonneProjection::ossimBonneProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + :ossimMapProjection(ellipsoid, origin) +{ + setDefaults(); + update(); +} + +ossimBonneProjection::ossimBonneProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + const double falseEasting, + const double falseNorthing) + :ossimMapProjection(ellipsoid, origin) +{ + Bonn_False_Easting = falseEasting; + Bonn_False_Northing = falseNorthing; + Bonn_Delta_Northing = 25000000.0; + + update(); +} + +void ossimBonneProjection::update() +{ + Set_Bonne_Parameters(theEllipsoid.getA(), + theEllipsoid.getFlattening(), + theOrigin.latr(), + theOrigin.lonr(), + Bonn_False_Easting, + Bonn_False_Northing); + + ossimMapProjection::update(); +} + +void ossimBonneProjection::setFalseEasting(double falseEasting) +{ + Bonn_False_Easting = falseEasting; + update(); +} + +void ossimBonneProjection::setFalseNorthing(double falseNorthing) +{ + Bonn_False_Northing = falseNorthing; + update(); +} + +void ossimBonneProjection::setFalseEastingNorthing(double falseEasting, + double falseNorthing) +{ + Bonn_False_Easting = falseEasting; + Bonn_False_Northing = falseNorthing; + update(); +} + +void ossimBonneProjection::setDefaults() +{ + + Bonn_False_Easting = 0.0; + Bonn_False_Northing = 0.0; + Bonn_Delta_Northing = 25000000.0; + if(theOrigin.latd() == 0.0) + { + // we can't have the origin of lat 0 for Bonne + // so bump it up an arc second. + // + theOrigin.latd(1.0/3600.0); + } +} + +ossimGpt ossimBonneProjection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat, lon; + + Convert_Bonne_To_Geodetic(eastingNorthing.x, + eastingNorthing.y, + &lat, + &lon); + return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0, theDatum); +} + +ossimDpt ossimBonneProjection::forward(const ossimGpt &latLon)const +{ + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + Convert_Geodetic_To_Bonne(gpt.latr(), + gpt.lonr(), + &easting, + &northing); + return ossimDpt(easting, northing); +} + +bool ossimBonneProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const +{ + kwl.add(prefix, + ossimKeywordNames::FALSE_EASTING_KW, + Bonn_False_Easting, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_NORTHING_KW, + Bonn_False_Northing, + true); + + return ossimMapProjection::saveState(kwl, prefix); +} + +bool ossimBonneProjection::loadState(const ossimKeywordlist& kwl, const char* prefix) +{ + bool flag = ossimMapProjection::loadState(kwl, prefix); + + const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + const char* falseEasting = kwl.find(prefix, ossimKeywordNames::FALSE_EASTING_KW); + const char* falseNorthing = kwl.find(prefix, ossimKeywordNames::FALSE_NORTHING_KW); + setDefaults(); + if(ossimString(type) == STATIC_TYPE_NAME(ossimBonneProjection)) + { + if(falseEasting) + { + Bonn_False_Easting = ossimString(falseEasting).toDouble(); + } + if(falseNorthing) + { + Bonn_False_Northing = ossimString(falseNorthing).toDouble(); + } + } + + update(); + return flag; +} + + +/* + * These state variables are for optimization purposes. The only function + * that should modify them is Set_Bonne_Parameters. + */ + + +/***************************************************************************/ +/* + * FUNCTIONS + */ + + +long ossimBonneProjection::Set_Bonne_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing) +{ /* Begin Set_Bonne_Parameters */ +/* + * The function Set_Bonne_Parameters receives the ellipsoid parameters and + * Bonne projection parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the + * function, otherwise BONN_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at which the (input) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + + double j, three_es4; + double x,e1,e2,e3,e4; + double clat; + double sin2lat, sin4lat, sin6lat, lat; +// double inv_f = 1 / f; + long Error_Code = BONN_NO_ERROR; + +// if (a <= 0.0) +// { /* Semi-major axis must be greater than zero */ +// Error_Code |= BONN_A_ERROR; +// } +// if ((inv_f < 250) || (inv_f > 350)) +// { /* Inverse flattening must be between 250 and 350 */ +// Error_Code |= BONN_INV_F_ERROR; +// } +// if ((Origin_Latitude < -PI_OVER_2) || (Origin_Latitude > PI_OVER_2)) +// { /* origin latitude out of range */ +// Error_Code |= BONN_ORIGIN_LAT_ERROR; +// } +// if ((Central_Meridian < -PI) || (Central_Meridian > TWO_PI)) +// { /* origin longitude out of range */ +// Error_Code |= BONN_CENT_MER_ERROR; +// } + if (!Error_Code) + { /* no errors */ + Bonn_a = a; + Bonn_f = f; + Bonn_Origin_Lat = Origin_Latitude; +// if (Central_Meridian > PI) +// Central_Meridian -= TWO_PI; + Bonn_Origin_Long = Central_Meridian; + Bonn_False_Northing = False_Northing; + Bonn_False_Easting = False_Easting; + if (Bonn_Origin_Lat == 0.0) + { + if (Bonn_Origin_Long > 0) + { + Bonn_Max_Easting = 19926189.0; + Bonn_Min_Easting = -20037509.0; + } + else if (Bonn_Origin_Long < 0) + { + Bonn_Max_Easting = 20037509.0; + Bonn_Min_Easting = -19926189.0; + } + else + { + Bonn_Max_Easting = 20037509.0; + Bonn_Min_Easting = -20037509.0; + } + Bonn_Delta_Northing = 10001966.0; + Set_Sinusoidal_Parameters(Bonn_a, Bonn_f, Bonn_Origin_Long, Bonn_False_Easting, Bonn_False_Northing); + } + else + { + Sin_Bonn_Origin_Lat = sin(Bonn_Origin_Lat); + + es2 = 2 * Bonn_f - Bonn_f * Bonn_f; + es4 = es2 * es2; + es6 = es4 * es2; + j = 45.0 * es6 / 1024.0; + three_es4 = 3.0 * es4; + c0 = 1 - es2 / 4.0 - three_es4 / 64.0 - 5.0 * es6 / 256.0; + c1 = 3.0 * es2 / 8.0 + three_es4 / 32.0 + j; + c2 = 15.0 * es4 / 256.0 + j; + c3 = 35.0 * es6 / 3072.0; + + clat = cos(Bonn_Origin_Lat); + m1 = BONN_m(clat, Sin_Bonn_Origin_Lat); + + lat = c0 * Bonn_Origin_Lat; + sin2lat = COEFF_TIMES_BONN_SIN(c1, 2.0, Bonn_Origin_Lat); + sin4lat = COEFF_TIMES_BONN_SIN(c2, 4.0, Bonn_Origin_Lat); + sin6lat = COEFF_TIMES_BONN_SIN(c3, 6.0, Bonn_Origin_Lat); + M1 = BONN_M(lat, sin2lat, sin4lat, sin6lat); + + x = sqrt (1.0 - es2); + e1 = (1.0 - x) / (1.0 + x); + e2 = e1 * e1; + e3 = e2 * e1; + e4 = e3 * e1; + a0 = 3.0 * e1 / 2.0 - 27.0 * e3 / 32.0; + a1 = 21.0 * e2 / 16.0 - 55.0 * e4 / 32.0; + a2 = 151.0 * e3 / 96.0; + a3 = 1097.0 * e4 / 512.0; + if (Sin_Bonn_Origin_Lat == 0.0) + Bonn_am1sin = 0.0; + else + Bonn_am1sin = Bonn_a * m1 / Sin_Bonn_Origin_Lat; + + Bonn_Max_Easting = 20027474.0; + Bonn_Min_Easting = -20027474.0; + Bonn_Delta_Northing = 20003932.0; + + } + + } /* End if(!Error_Code) */ + return (Error_Code); +} /* End Set_Bonne_Parameters */ + + +void ossimBonneProjection::Get_Bonne_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const +{ /* Begin Get_Bonne_Parameters */ +/* + * The function Get_Bonne_Parameters returns the current ellipsoid + * parameters and Bonne projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at which the (output) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + + *a = Bonn_a; + *f = Bonn_f; + *Origin_Latitude = Bonn_Origin_Lat; + *Central_Meridian = Bonn_Origin_Long; + *False_Easting = Bonn_False_Easting; + *False_Northing = Bonn_False_Northing; + return; +} /* End Get_Bonne_Parameters */ + + +long ossimBonneProjection::Convert_Geodetic_To_Bonne (double Latitude, + double Longitude, + double *Easting, + double *Northing)const +{ /* Begin Convert_Geodetic_To_Bonne */ +/* + * The function Convert_Geodetic_To_Bonne converts geodetic (latitude and + * longitude) coordinates to Bonne projection (easting and northing) + * coordinates, according to the current ellipsoid and Bonne projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise BONN_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + + double dlam; /* Longitude - Central Meridan */ + double mm; + double MM; + double rho; + double EE; + double clat = cos(Latitude); + double slat = sin(Latitude); + double lat, sin2lat, sin4lat, sin6lat; + long Error_Code = BONN_NO_ERROR; + +// if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2)) +// { /* Latitude out of range */ +// Error_Code |= BONN_LAT_ERROR; +// } +// if ((Longitude < -PI) || (Longitude > TWO_PI)) +// { /* Longitude out of range */ +// Error_Code |= BONN_LON_ERROR; +// } + if (!Error_Code) + { /* no errors */ + if (Bonn_Origin_Lat == 0.0) + Convert_Geodetic_To_Sinusoidal(Latitude, Longitude, Easting, Northing); + else + { + dlam = Longitude - Bonn_Origin_Long; + if (dlam > M_PI) + { + dlam -= TWO_PI; + } + if (dlam < -M_PI) + { + dlam += TWO_PI; + } + if ((Latitude - Bonn_Origin_Lat) == 0.0 && FLOAT_EQ(fabs(Latitude),PI_OVER_2,.00001)) + { + *Easting = 0.0; + *Northing = 0.0; + } + else + { + mm = BONN_m(clat, slat); + + lat = c0 * Latitude; + sin2lat = COEFF_TIMES_BONN_SIN(c1, 2.0, Latitude); + sin4lat = COEFF_TIMES_BONN_SIN(c2, 4.0, Latitude); + sin6lat = COEFF_TIMES_BONN_SIN(c3, 6.0, Latitude); + MM = BONN_M(lat, sin2lat, sin4lat, sin6lat); + + rho = Bonn_am1sin + M1 - MM; + if (rho == 0) + EE = 0; + else + EE = Bonn_a * mm * dlam / rho; + *Easting = rho * sin(EE) + Bonn_False_Easting; + *Northing = Bonn_am1sin - rho * cos(EE) + Bonn_False_Northing; + } + } + } + return (Error_Code); +} /* End Convert_Geodetic_To_Bonne */ + + +long ossimBonneProjection::Convert_Bonne_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const +{ /* Begin Convert_Bonne_To_Geodetic */ +/* + * The function Convert_Bonne_To_Geodetic converts Bonne projection + * (easting and northing) coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Bonne projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise BONN_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + + double dx; /* Delta easting - Difference in easting (easting-FE) */ + double dy; /* Delta northing - Difference in northing (northing-FN) */ + double mu; + double MM; + double mm; + double am1sin_dy; + double rho; + double sin2mu, sin4mu, sin6mu, sin8mu; + double clat, slat; + long Error_Code = BONN_NO_ERROR; + +// if ((Easting < (Bonn_False_Easting + Bonn_Min_Easting)) +// || (Easting > (Bonn_False_Easting + Bonn_Max_Easting))) +// { /* Easting out of range */ +// Error_Code |= BONN_EASTING_ERROR; +// } +// if ((Northing < (Bonn_False_Northing - Bonn_Delta_Northing)) +// || (Northing > (Bonn_False_Northing + Bonn_Delta_Northing))) +// { /* Northing out of range */ +// Error_Code |= BONN_NORTHING_ERROR; +// } + if (!Error_Code) + { /* no errors */ + if (Bonn_Origin_Lat == 0.0) + Convert_Sinusoidal_To_Geodetic(Easting, Northing, Latitude, Longitude); + else + { + dy = Northing - Bonn_False_Northing; + dx = Easting - Bonn_False_Easting; + am1sin_dy = Bonn_am1sin - dy; + rho = sqrt(dx * dx + am1sin_dy * am1sin_dy); + if (Bonn_Origin_Lat < 0.0) + rho = -rho; + MM = Bonn_am1sin + M1 - rho; + + mu = MM / (Bonn_a * c0); + sin2mu = COEFF_TIMES_BONN_SIN(a0, 2.0, mu); + sin4mu = COEFF_TIMES_BONN_SIN(a1, 4.0, mu); + sin6mu = COEFF_TIMES_BONN_SIN(a2, 6.0, mu); + sin8mu = COEFF_TIMES_BONN_SIN(a3, 8.0, mu); + *Latitude = mu + sin2mu + sin4mu + sin6mu + sin8mu; + + if (FLOAT_EQ(fabs(*Latitude),PI_OVER_2,.00001)) + { + *Longitude = Bonn_Origin_Long; + } + else + { + clat = cos(*Latitude); + slat = sin(*Latitude); + mm = BONN_m(clat, slat); + + if (Bonn_Origin_Lat < 0.0) + { + dx = -dx; + am1sin_dy = -am1sin_dy; + } + *Longitude = Bonn_Origin_Long + rho * (atan2(dx, am1sin_dy)) / + (Bonn_a * mm); + } + + if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */ + *Latitude = PI_OVER_2; + else if (*Latitude < -PI_OVER_2) + *Latitude = -PI_OVER_2; + +// if (*Longitude > PI) +// *Longitude -= TWO_PI; +// if (*Longitude < -PI) +// *Longitude += TWO_PI; + + if (*Longitude > M_PI)/* force distorted values to 180, -180 degrees */ + *Longitude = M_PI; + else if (*Longitude < -M_PI) + *Longitude = -M_PI; + } + } + return (Error_Code); +} /* End Convert_Bonne_To_Geodetic */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimBonneProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimBonneProjection.h new file mode 100644 index 0000000000..71065d95f0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimBonneProjection.h @@ -0,0 +1,215 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Bonne projection code. +//******************************************************************* +// $Id: ossimBonneProjection.h,v 1.5 2005/09/09 19:23:58 gpotts Exp $ +#ifndef ossimBonneProjection_HEADER +#define ossimBonneProjection_HEADER + +#include "ossimMapProjection.h" + +class ossimBonneProjection : public ossimMapProjection +{ +public: + + ossimBonneProjection(const ossimEllipsoid& ellipsoid = ossimEllipsoid(), + const ossimGpt& origin = ossimGpt()); + ossimBonneProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + const double falseEasting, + const double falseNorthing); + ~ossimBonneProjection(){} + virtual ossimObject *dup()const{return new ossimBonneProjection(*this);} + + virtual ossimDpt forward(const ossimGpt &worldPoint) const; + virtual ossimGpt inverse(const ossimDpt &projectedPoint)const; + virtual void update(); + + /*! + * SetFalseEasting. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEasting(double falseEasting); + + /*! + * SetFalseNorthing. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseNorthing(double falseNorthing); + + /*! + * Sets both false easting and northing values. The values are + * expected to be in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEastingNorthing(double falseEasting, double falseNorthing); + + double getFalseEasting()const{return Bonn_False_Easting;} + double getFalseNorthing()const{return Bonn_False_Northing;} + + /*! + * Initialize all pramters to default and calls update for + * pre-computations. + */ + void setDefaults(); + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + + +private: + + + mutable double Bonn_a; /* Semi-major axis of ellipsoid in meters */ + mutable double Bonn_f; /* Flattening of ellipsoid */ + mutable double es2; /* Eccentricity (0.08181919084262188000) squared */ + mutable double es4; /* es2 * es2 */ + mutable double es6; /* es4 * es2 */ + mutable double M1; /* Bonn_M(Bonna,c0lat,c1s2lat,c2s4lat,c3s6lat) */ + mutable double m1; /* Bonn_m(coslat,sinlat,es2) */ + mutable double c0; /* 1 - es2 / 4.0 - 3.0 * es4 / 64.0 - 5.0 * es6 / 256.0 */ + mutable double c1; /* 3.0 * es2 / 8.0 + 3.0 * es4 / 32.0 + 45.0 * es6 / 1024.0 */ + mutable double c2; /* 15.0 * es4 / 256.0 + 45.0 * es6 / 1024.0 */ + mutable double c3; /* 35.0 * es6 / 3072.0 */ + mutable double a0; /* 3.0 * e1 / 2.0 - 27.0 * e3 / 32.0 */ + mutable double a1; /* 21.0 * e2 / 16.0 - 55.0 * e4 / 32.0 */ + mutable double a2; /* 151.0 * e3 / 96.0 */ + mutable double a3; /* 1097.0 * e4 / 512.0 */ + + +/* Bonne projection Parameters */ + mutable double Bonn_Origin_Lat; /* Latitude of origin in radians */ + mutable double Bonn_Origin_Long; /* Longitude of origin in radians */ + mutable double Bonn_False_Northing; /* False northing in meters */ + mutable double Bonn_False_Easting; /* False easting in meters */ + mutable double Sin_Bonn_Origin_Lat; /* sin(Bonn_Origin_Lat) */ + mutable double Bonn_am1sin; /* Bonn_a * m1 / Sin_Bonn_Origin_Lat */ + +/* Maximum variance for easting and northing values for WGS 84. + */ + mutable double Bonn_Max_Easting; + mutable double Bonn_Min_Easting; + mutable double Bonn_Delta_Northing; + +/*! + * The function Set_Bonne_Parameters receives the ellipsoid parameters and + * Bonne projcetion parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the + * function, otherwise BONN_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at which the (input) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + long Set_Bonne_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing); + + +/*! + * The function Get_Bonne_Parameters returns the current ellipsoid + * parameters and Bonne projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at which the (output) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + void Get_Bonne_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const; + + +/*! + * The function Convert_Geodetic_To_Bonne converts geodetic (latitude and + * longitude) coordinates to Bonne projection easting, and northing + * coordinates, according to the current ellipsoid and Bonne projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise BONN_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + long Convert_Geodetic_To_Bonne (double Latitude, + double Longitude, + double *Easting, + double *Northing)const; + + +/*! + * The function Convert_Bonne_To_Geodetic converts Bonne projection + * easting and northing coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Bonne projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise BONN_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + long Convert_Bonne_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const; + +/*! + * RTTI found in data_types/rtti.h + */ +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimCadrgProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimCadrgProjection.cpp new file mode 100644 index 0000000000..583698fae3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimCadrgProjection.cpp @@ -0,0 +1,417 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimCadrgProjection.cpp,v 1.12 2005/09/09 19:23:58 gpotts Exp $ +#include "ossimCadrgProjection.h" +#include "base/common/ossimKeywordNames.h" +#include "base/data_types/ossimKeywordlist.h" +#include "base/common/ossimTrace.h" +#include "elevation/ossimElevManager.h" +#include "base/data_types/datum/ossimDatum.h" + +RTTI_DEF1(ossimCadrgProjection, "ossimCadrgProjection", ossimMapProjection) + +double ossimCadrgProjection::theOldZoneExtents[] = {0.0, 32.0, 48.0, 56.0, 64.0, + 68.0, 72.0, 76.0, 80.0, 90.0}; +double ossimCadrgProjection::theCadrgArcA[] = { 369664, 302592, 245760, 199168, + 163328, 137216, 110080, 82432 }; + +double ossimCadrgProjection::theNorthLimit = 90.0*M_PI/180.0; +double ossimCadrgProjection::theSouthLimit = -90.0*M_PI/180.0; + +ossimCadrgProjection::ossimCadrgProjection() + :ossimMapProjection(ossimEllipsoid(), ossimGpt()), + theCadrgZone(1), + theMapScale(5000000), + theWidth(0.0), + theHeight(0.0) +{ + computeParameters(); +} + +ossimCadrgProjection::~ossimCadrgProjection() +{ + +} + +ossimObject *ossimCadrgProjection::dup()const +{ + return new ossimCadrgProjection(*this); +} + + +ossimDpt ossimCadrgProjection::worldToLineSample(const ossimGpt &worldPoint) const +{ + ossimDpt lineSample; + + worldToLineSample(worldPoint, lineSample); + + return lineSample; +} + +ossimGpt ossimCadrgProjection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat=0.0; + double lon=0.0; + + return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum); +} + +ossimDpt ossimCadrgProjection::forward(const ossimGpt &latLon)const +{ + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + return ossimDpt(easting, northing); +} + +ossimGpt ossimCadrgProjection::lineSampleToWorld(const ossimDpt &projectedPoint)const +{ + ossimGpt worldPoint; + + lineSampleToWorld(projectedPoint, worldPoint); + + return worldPoint; +} + +void ossimCadrgProjection::worldToLineSample(const ossimGpt &worldPoint, + ossimDpt& lineSample)const +{ + double lat = worldPoint.latd(); + double lon = worldPoint.lond(); + double centerLat = theOrigin.latd(); + double centerLon = theOrigin.lond()*DEG_PER_RAD; + + lineSample.y = (centerLat - lat)/90.0*thePixelConstant.y; + lineSample.x = (lon - centerLon)/360.0*thePixelConstant.x; + + lineSample = lineSample - theUlLineSample; +} + +void ossimCadrgProjection::lineSampleToWorld(const ossimDpt &projectedPoint, + ossimGpt& gpt)const +{ + gpt = theOrigin; + + + ossimDpt adjustedPixel(projectedPoint.x + theUlLineSample.x, + projectedPoint.y + theUlLineSample.y); + +// double lat = gpt.latd() - (90/thePixelConstant.y)*adjustedPixel.y; +// double lon = gpt.lond() + (360/thePixelConstant.x)*adjustedPixel.x; + double lat = gpt.latd() - (90/thePixelConstant.y)*adjustedPixel.y; + double lon = gpt.lond() + (360/thePixelConstant.x)*adjustedPixel.x; + + gpt.latd(lat); + gpt.lond(lon); + + gpt.clampLat(-90, 90); + gpt.clampLon(-180, 180); +} + +double ossimCadrgProjection::computeXPixConstant(double scale, + long zone)const +{ + double adrgscale = 1000000/scale; + + // E-W pixel constant + double x_pix = (double) adrgscale*theCadrgArcA[zone-1] / 512.0; + + // Increase, if necessary, to the next highest integer value + x_pix = ceil(x_pix); + x_pix = x_pix * 1.33333;//(512*100)/(150*256); + + // Round the final result. + x_pix = irint(x_pix); + + return x_pix*256.0; + +} + +double ossimCadrgProjection::computeYPixConstant(double scale)const +{ + double adrgscale = 1000000/scale; + const long CADRG_ARC_B = 400384; + + double y_pix = (double) adrgscale * CADRG_ARC_B / 512.0; + + // Increase, if necessary, to the next highest integer value + y_pix = ceil(y_pix); + + y_pix = y_pix * 0.33333;//(512*100)/(4*150*256); + + // Round the final result. + y_pix = irint(y_pix); + + return y_pix*256.0; +} + +void ossimCadrgProjection::computeParameters() +{ + theUlLineSample = ossimDpt(0,0); + + thePixelConstant.y = computeYPixConstant(theMapScale); + thePixelConstant.x = computeXPixConstant(theMapScale, + theCadrgZone); + double height = theHeight; + double width = theWidth; + + if(width > thePixelConstant.x) + { + width = thePixelConstant.x; + } + + if(height > thePixelConstant.y) + { + height = thePixelConstant.y; + } + + + theUlLineSample.x = -width/2.0; + theUlLineSample.y = -height/2.0; +} + +bool ossimCadrgProjection::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + bool result = ossimProjection::saveState(kwl, prefix); + + kwl.add(prefix, + ossimKeywordNames::ZONE_KW, + theCadrgZone, + true); + + kwl.add(prefix, + "map_scale", + theMapScale, + true); + + kwl.add(prefix, + ossimKeywordNames::NUMBER_LINES_KW, + theHeight, + true); + + kwl.add(prefix, + ossimKeywordNames::NUMBER_SAMPLES_KW, + theWidth, + true); + + kwl.add(prefix, + ossimKeywordNames::UL_LAT_KW, + theUlGpt.latd(), + true); + + kwl.add(prefix, + ossimKeywordNames::UL_LON_KW, + theUlGpt.lond(), + true); + + kwl.add(prefix, + ossimKeywordNames::LL_LAT_KW, + theLlGpt.latd(), + true); + + kwl.add(prefix, + ossimKeywordNames::LL_LON_KW, + theLlGpt.lond(), + true); + + kwl.add(prefix, + ossimKeywordNames::LR_LAT_KW, + theLrGpt.latd(), + true); + + kwl.add(prefix, + ossimKeywordNames::LR_LON_KW, + theLrGpt.lond(), + true); + + kwl.add(prefix, + ossimKeywordNames::UR_LAT_KW, + theUrGpt.latd(), + true); + + kwl.add(prefix, + ossimKeywordNames::UR_LON_KW, + theUrGpt.lond(), + true); + + + + if(theDatum) + { + kwl.add(prefix, + ossimKeywordNames::DATUM_KW, + theDatum->code(), + true); + } + + return result; +} + + +bool ossimCadrgProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimProjection::loadState(kwl, prefix); + + + const char* lookup = kwl.find(prefix, ossimKeywordNames::UL_LAT_KW); + if(lookup) + { + theUlGpt.latd(ossimString(lookup).toDouble()); + } + else + { + theUlGpt.latd(90.0); + } + + lookup = kwl.find(prefix, ossimKeywordNames::UL_LON_KW); + if(lookup) + { + theUlGpt.lond(ossimString(lookup).toDouble()); + } + else + { + theUlGpt.lond(-180.0); + } + + lookup = kwl.find(prefix, ossimKeywordNames::LL_LAT_KW); + if(lookup) + { + theLlGpt.latd(ossimString(lookup).toDouble()); + } + else + { + theLlGpt.latd(0.0); + } + + lookup = kwl.find(prefix, ossimKeywordNames::LL_LON_KW); + if(lookup) + { + theLlGpt.lond(ossimString(lookup).toDouble()); + } + else + { + theLlGpt.lond(-180.0); + } + + lookup = kwl.find(prefix, ossimKeywordNames::LR_LAT_KW); + if(lookup) + { + theLrGpt.latd(ossimString(lookup).toDouble()); + } + else + { + theLrGpt.latd(0.0); + } + + lookup = kwl.find(prefix, ossimKeywordNames::LR_LON_KW); + if(lookup) + { + theLrGpt.lond(ossimString(lookup).toDouble()); + } + else + { + theLrGpt.lond(180.0); + } + + lookup = kwl.find(prefix, ossimKeywordNames::LR_LAT_KW); + if(lookup) + { + theLrGpt.latd(ossimString(lookup).toDouble()); + } + else + { + theLrGpt.latd(0.0); + } + + lookup = kwl.find(prefix, ossimKeywordNames::LR_LON_KW); + if(lookup) + { + theLrGpt.lond(ossimString(lookup).toDouble()); + } + else + { + theLrGpt.lond(180.0); + } + + lookup = kwl.find(prefix, ossimKeywordNames::UR_LAT_KW); + if(lookup) + { + theUrGpt.latd(ossimString(lookup).toDouble()); + } + else + { + theUrGpt.latd(90.0); + } + + lookup = kwl.find(prefix, ossimKeywordNames::UR_LON_KW); + if(lookup) + { + theUrGpt.lond(ossimString(lookup).toDouble()); + } + else + { + theUrGpt.lond(180.0); + } + + const char* zone = kwl.find(prefix, + ossimKeywordNames::ZONE_KW); + if(zone) + { + theCadrgZone = ossimString(zone).toLong(); + } + const char* mapScale = kwl.find(prefix, + "map_scale"); + if(mapScale) + { + theMapScale = ossimString(mapScale).toDouble(); + } + const char *height = kwl.find(prefix, + ossimKeywordNames::NUMBER_LINES_KW); + const char *width = kwl.find(prefix, + ossimKeywordNames::NUMBER_SAMPLES_KW); + if(height) + { + theHeight = ossimString(height).toDouble(); + } + + if(width) + { + theWidth = ossimString(width).toDouble(); + } + + computeParameters(); + + return true; +} diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimCadrgProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimCadrgProjection.h new file mode 100644 index 0000000000..e764c74ded --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimCadrgProjection.h @@ -0,0 +1,101 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimCadrgProjection.h,v 1.9 2005/09/09 19:23:58 gpotts Exp $ +#ifndef ossimCadrgProjection_HEADER +#define ossimCadrgProjection_HEADER +#include "ossimMapProjection.h" + +class ossimCadrgProjection : public ossimMapProjection +{ +public: + ossimCadrgProjection(); + + + virtual ~ossimCadrgProjection(); + virtual ossimObject *dup()const; + virtual ossimGpt inverse(const ossimDpt &eastingNorthing)const; + virtual ossimDpt forward(const ossimGpt &latLon)const; + + virtual ossimDpt worldToLineSample(const ossimGpt &worldPoint) const; + virtual ossimGpt lineSampleToWorld(const ossimDpt &projectedPoint)const; + virtual void worldToLineSample(const ossimGpt &worldPoint, + ossimDpt& lineSample)const; + virtual void lineSampleToWorld(const ossimDpt &projectedPoint, + ossimGpt& gpt)const; + + double computeXPixConstant(double scale, long zone)const; + double computeYPixConstant(double scale)const; + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + + ossimString getProjectionName()const + { + return getClassName(); + } + +protected: + /* + * Are from the ADRG Mil spec for 1:1,000,000 and + * are scales for each zone. + */ + static double theCadrgArcA[8]; + + + static double theOldZoneExtents[10]; + + static double theNorthLimit; + static double theSouthLimit; + + long theCadrgZone; + + ossimDpt thePixelConstant; + double theMapScale; + + double theWidth; + double theHeight; + + ossimDpt theUlLineSample; + + ossimGpt theUlGpt; + ossimGpt theLlGpt; + ossimGpt theLrGpt; + ossimGpt theUrGpt; + + void computeParameters(); +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimCassiniProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimCassiniProjection.cpp new file mode 100644 index 0000000000..05b76cc526 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimCassiniProjection.cpp @@ -0,0 +1,546 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Cassini projection code. +//******************************************************************* +// $Id: ossimCassiniProjection.cpp,v 1.11 2004/01/08 21:49:21 jlargent Exp $ + +#include <math.h> +#include "ossimCassiniProjection.h" +#include "base/common/ossimKeywordNames.h" + +RTTI_DEF1(ossimCassiniProjection, "ossimCassiniProjection", ossimMapProjection) + + + +/***************************************************************************/ +/* + * DEFINES + */ + +#ifdef PI_OVER_2 +# undef PI_OVER_2 +#endif + +#define CASS_NO_ERROR 0x0000 +#define CASS_LAT_ERROR 0x0001 +#define CASS_LON_ERROR 0x0002 +#define CASS_EASTING_ERROR 0x0004 +#define CASS_NORTHING_ERROR 0x0008 +#define CASS_ORIGIN_LAT_ERROR 0x0010 +#define CASS_CENT_MER_ERROR 0x0020 +#define CASS_A_ERROR 0x0040 +#define CASS_B_ERROR 0x0080 +#define CASS_A_LESS_B_ERROR 0x0100 +#define CASS_LON_WARNING 0x0200 + +#define PI_OVER_2 ( M_PI / 2.0) +#define CASS_M(c0lat, c1s2lat, c2s4lat, c3s6lat) (Cass_a*(c0lat-c1s2lat+c2s4lat-c3s6lat)) +#define CASS_RD(sinlat) (sqrt(1.0 - es2 * (sinlat * sinlat))) +#define CASS_COEFF_TIMES_SIN(coeff, x, latit) (coeff * (sin (x * latit))) +#define FLOAT_EQ(x,v,epsilon) (((v - epsilon) < x) && (x < (v + epsilon))) +#define THIRTY_ONE (31.0 * M_PI / 180.0) /* 31 degrees in radians */ + + + +ossimCassiniProjection::ossimCassiniProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + :ossimMapProjection(ellipsoid, origin) +{ + setDefaults(); + update(); +} + +ossimCassiniProjection::ossimCassiniProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + const double falseEasting, + const double falseNorthing) + :ossimMapProjection(ellipsoid, origin) +{ + Cass_False_Easting = falseEasting; + Cass_False_Northing = falseNorthing; + Cass_Min_Easting = -20037508.4; + Cass_Max_Easting = 20037508.4; + Cass_Min_Northing = -56575846.0; + Cass_Max_Northing = 56575846.0; + + update(); +} + +void ossimCassiniProjection::update() +{ + Set_Cassini_Parameters(theEllipsoid.getA(), + theEllipsoid.getFlattening(), + theOrigin.latr(), + theOrigin.lonr(), + Cass_False_Easting, + Cass_False_Northing); + + ossimMapProjection::update(); +} + +void ossimCassiniProjection::setFalseEasting(double falseEasting) +{ + Cass_False_Easting = falseEasting; + update(); +} + +void ossimCassiniProjection::setFalseNorthing(double falseNorthing) +{ + Cass_False_Northing = falseNorthing; + update(); +} + +void ossimCassiniProjection::setFalseEastingNorthing(double falseEasting, + double falseNorthing) +{ + Cass_False_Easting = falseEasting; + Cass_False_Northing = falseNorthing; + update(); +} + +void ossimCassiniProjection::setDefaults() +{ + + Cass_Min_Easting = -20037508.4; + Cass_Max_Easting = 20037508.4; + Cass_Min_Northing = -56575846.0; + Cass_Max_Northing = 56575846.0; + Cass_False_Easting = 0.0; + Cass_False_Northing = 0.0; +} + +ossimGpt ossimCassiniProjection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat = 0.0; + double lon = 0.0; + + Convert_Cassini_To_Geodetic(eastingNorthing.x, + eastingNorthing.y, + &lat, + &lon); + + return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0, theDatum); +} + +ossimDpt ossimCassiniProjection::forward(const ossimGpt &latLon)const +{ + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + Convert_Geodetic_To_Cassini(gpt.latr(), + gpt.lonr(), + &easting, + &northing); + return ossimDpt(easting, northing); + +} + +bool ossimCassiniProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const +{ + kwl.add(prefix, + ossimKeywordNames::FALSE_EASTING_KW, + Cass_False_Easting, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_NORTHING_KW, + Cass_False_Northing, + true); + + return ossimMapProjection::saveState(kwl, prefix); +} + +bool ossimCassiniProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + bool flag = ossimMapProjection::loadState(kwl, prefix); + + const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + const char* falseEasting = kwl.find(prefix, ossimKeywordNames::FALSE_EASTING_KW); + const char* falseNorthing = kwl.find(prefix, ossimKeywordNames::FALSE_NORTHING_KW); + + setDefaults(); + + if(ossimString(type) == STATIC_TYPE_NAME(ossimCassiniProjection)) + { + if(falseEasting) + { + Cass_False_Easting = ossimString(falseEasting).toDouble(); + } + if(falseNorthing) + { + Cass_False_Northing = ossimString(falseNorthing).toDouble(); + } + } + + update(); + + return flag; +} + +/***************************************************************************/ +/* + * FUNCTIONS + */ + + +long ossimCassiniProjection::Set_Cassini_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing) +{ /* Begin Set_Cassini_Parameters */ +/* + * The function Set_Cassini_Parameters receives the ellipsoid parameters and + * Cassini projection parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the + * function, otherwise CASS_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at which the (input) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + + double j,three_es4; + double x, e1, e2, e3, e4; + double lat, sin2lat, sin4lat, sin6lat; + double temp; +// double inv_f = 1 / f; + long Error_Code = CASS_NO_ERROR; + +// if (a <= 0.0) +// { /* Semi-major axis must be greater than zero */ +// Error_Code |= CASS_A_ERROR; +// } +// if ((inv_f < 250) || (inv_f > 350)) +// { /* Inverse flattening must be between 250 and 350 */ +// Error_Code |= CASS_INV_F_ERROR; +// } +// if ((Origin_Latitude < -PI_OVER_2) || (Origin_Latitude > PI_OVER_2)) +// { /* origin latitude out of range */ +// Error_Code |= CASS_ORIGIN_LAT_ERROR; +// } +// if ((Central_Meridian < -PI) || (Central_Meridian > TWO_PI)) +// { /* origin longitude out of range */ +// Error_Code |= CASS_CENT_MER_ERROR; +// } + if (!Error_Code) + { /* no errors */ + Cass_a = a; + Cass_f = f; + Cass_Origin_Lat = Origin_Latitude; +// if (Central_Meridian > PI) +// Central_Meridian -= TWO_PI; + Cass_Origin_Long = Central_Meridian; + Cass_False_Northing = False_Northing; + Cass_False_Easting = False_Easting; + es2 = 2 * Cass_f - Cass_f * Cass_f; + es4 = es2 * es2; + es6 = es4 * es2; + j = 45.0 * es6 / 1024.0; + three_es4 = 3.0 * es4; + c0 = 1 - es2 / 4.0 - three_es4 / 64.0 - 5.0 * es6 / 256.0; + c1 = 3.0 * es2 /8.0 + three_es4 / 32.0 + j; + c2 = 15.0 * es4 / 256.0 + j; + c3 = 35.0 * es6 / 3072.0; + lat = c0 * Cass_Origin_Lat; + sin2lat = CASS_COEFF_TIMES_SIN(c1, 2.0, Cass_Origin_Lat); + sin4lat = CASS_COEFF_TIMES_SIN(c2, 4.0, Cass_Origin_Lat); + sin6lat = CASS_COEFF_TIMES_SIN(c3, 6.0, Cass_Origin_Lat); + M0 = CASS_M(lat, sin2lat, sin4lat, sin6lat); + + One_Minus_es2 = 1.0 - es2; + x = sqrt (One_Minus_es2); + e1 = (1 - x) / (1 + x); + e2 = e1 * e1; + e3 = e2 * e1; + e4 = e3 * e1; + a0 = 3.0 * e1 / 2.0 - 27.0 * e3 / 32.0; + a1 = 21.0 * e2 / 16.0 - 55.0 * e4 / 32.0; + a2 = 151.0 * e3 / 96.0; + a3 = 1097.0 * e4 /512.0; + + if (Cass_Origin_Long > 0) + { + Convert_Geodetic_To_Cassini(THIRTY_ONE, Cass_Origin_Long - M_PI, &temp, &Cass_Max_Northing); + Convert_Geodetic_To_Cassini(-THIRTY_ONE, Cass_Origin_Long - M_PI, &temp, &Cass_Min_Northing); + Cass_Max_Easting = 19926188.9; + Cass_Min_Easting = -20037508.4; + } + else if (Cass_Origin_Long < 0) + { + Convert_Geodetic_To_Cassini(THIRTY_ONE, M_PI + Cass_Origin_Long, &temp, &Cass_Max_Northing); + Convert_Geodetic_To_Cassini(-THIRTY_ONE, M_PI + Cass_Origin_Long, &temp, &Cass_Min_Northing); + Cass_Max_Easting = 20037508.4; + Cass_Min_Easting = -19926188.9; + } + else + { + Convert_Geodetic_To_Cassini(THIRTY_ONE, M_PI, &temp, &Cass_Max_Northing); + Convert_Geodetic_To_Cassini(-THIRTY_ONE, M_PI , &temp, &Cass_Min_Northing); + Cass_Max_Easting = 20037508.4; + Cass_Min_Easting = -20037508.4; + } + + } /* End if(!Error_Code) */ + return (Error_Code); +} /* End Set_Cassini_Parameters */ + + +void ossimCassiniProjection::Get_Cassini_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const +{ /* Begin Get_Cassini_Parameters */ +/* + * The function Get_Cassini_Parameters returns the current ellipsoid + * parameters, Cassini projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at which the (output) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + + *a = Cass_a; + *f = Cass_f; + *Origin_Latitude = Cass_Origin_Lat; + *Central_Meridian = Cass_Origin_Long; + *False_Easting = Cass_False_Easting; + *False_Northing = Cass_False_Northing; + + return; +} /* End Get_Cassini_Parameters */ + + +long ossimCassiniProjection::Convert_Geodetic_To_Cassini (double Latitude, + double Longitude, + double *Easting, + double *Northing)const +{ /* Begin Convert_Geodetic_To_Cassini */ +/* + * The function Convert_Geodetic_To_Cassini converts geodetic (latitude and + * longitude) coordinates to Cassini projection (easting and northing) + * coordinates, according to the current ellipsoid and Cassini projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise CASS_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + + double lat, sin2lat, sin4lat, sin6lat; + double RD; + double tlat = tan(Latitude); + double clat = cos(Latitude); + double slat = sin(Latitude); + double dlam; /* Longitude - Central Meridan */ + double NN; + double TT; + double AA, A2, A3, A4, A5; + double CC; + double MM; + long Error_Code = CASS_NO_ERROR; + +// if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2)) +// { /* Latitude out of range */ +// Error_Code |= CASS_LAT_ERROR; +// } +// if ((Longitude < -PI) || (Longitude > TWO_PI)) +// { /* Longitude out of range */ +// Error_Code |= CASS_LON_ERROR; +// } + if (!Error_Code) + { /* no errors */ + dlam = Longitude - Cass_Origin_Long; + + if (fabs(dlam) > (4.0 * M_PI / 180.0)) + { /* Distortion will result if Longitude is more than 4 degrees from the Central Meridian */ + Error_Code |= CASS_LON_WARNING; + } + + if (dlam > M_PI) + { + dlam -= TWO_PI; + } + if (dlam < -M_PI) + { + dlam += TWO_PI; + } + RD = CASS_RD(slat); + NN = Cass_a / RD; + TT = tlat * tlat; + AA = dlam * clat; + A2 = AA * AA; + A3 = AA * A2; + A4 = AA * A3; + A5 = AA * A4; + CC = es2 * clat * clat / One_Minus_es2; + lat = c0 * Latitude; + sin2lat = CASS_COEFF_TIMES_SIN(c1, 2.0, Latitude); + sin4lat = CASS_COEFF_TIMES_SIN(c2, 4.0, Latitude); + sin6lat = CASS_COEFF_TIMES_SIN(c3, 6.0, Latitude); + MM = CASS_M(lat, sin2lat, sin4lat, sin6lat); + + *Easting = NN * (AA - (TT * A3 / 6.0) - (8.0 - TT + 8.0 * CC) * + (TT * A5 / 120.0)) + Cass_False_Easting; + *Northing = MM - M0 + NN * tlat * ((A2 / 2.0) + (5.0 - TT + + 6.0 * CC) * A4 / 24.0) + Cass_False_Northing; + } + return (Error_Code); +} /* End Convert_Geodetic_To_Cassini */ + + +long ossimCassiniProjection::Convert_Cassini_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const +{ /* Begin Convert_Cassini_To_Geodetic */ +/* + * The function Convert_Cassini_To_Geodetic converts Cassini projection + * (easting and northing) coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Cassini projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise CASS_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + + double dx; /* Delta easting - Difference in easting (easting-FE) */ + double dy; /* Delta northing - Difference in northing (northing-FN) */ + double mu1; + double sin2mu, sin4mu, sin6mu, sin8mu; + double M1; + double phi1; + double tanphi1, sinphi1, cosphi1; + double T1, T; + double N1; + double RD, R1; + double DD, D2, D3, D4, D5; +// const double epsilon = 1.0e-1; + long Error_Code = CASS_NO_ERROR; + +// if ((Easting < (Cass_False_Easting + Cass_Min_Easting)) +// || (Easting > (Cass_False_Easting + Cass_Max_Easting))) +// { /* Easting out of range */ +// Error_Code |= CASS_EASTING_ERROR; +// } +// if ((Northing < (Cass_False_Northing + Cass_Min_Northing - epsilon)) +// || (Northing > (Cass_False_Northing + Cass_Max_Northing + epsilon))) +// { /* Northing out of range */ +// Error_Code |= CASS_NORTHING_ERROR; +// } + if (!Error_Code) + { /* no errors */ + dy = Northing - Cass_False_Northing; + dx = Easting - Cass_False_Easting; + M1 = M0 + dy; + mu1 = M1 / (Cass_a * c0); + + sin2mu = CASS_COEFF_TIMES_SIN(a0, 2.0, mu1); + sin4mu = CASS_COEFF_TIMES_SIN(a1, 4.0, mu1); + sin6mu = CASS_COEFF_TIMES_SIN(a2, 6.0, mu1); + sin8mu = CASS_COEFF_TIMES_SIN(a3, 8.0, mu1); + phi1 = mu1 + sin2mu + sin4mu + sin6mu + sin8mu; + + if (FLOAT_EQ(phi1,PI_OVER_2,.00001)) + { + *Latitude = PI_OVER_2; + *Longitude = Cass_Origin_Long; + } + else if (FLOAT_EQ(phi1,-PI_OVER_2,.00001)) + { + *Latitude = -PI_OVER_2; + *Longitude = Cass_Origin_Long; + } + else + { + tanphi1 = tan(phi1); + sinphi1 = sin(phi1); + cosphi1 = cos(phi1); + T1 = tanphi1 * tanphi1; + RD = CASS_RD(sinphi1); + N1 = Cass_a / RD; + R1 = N1 * One_Minus_es2 / (RD * RD); + DD = dx / N1; + D2 = DD * DD; + D3 = D2 * DD; + D4 = D3 * DD; + D5 = D4 * DD; + T = (1.0 + 3.0 * T1); + *Latitude = phi1 - (N1 * tanphi1 / R1) * (D2 / 2.0 - T * D4 / 24.0); + + *Longitude = Cass_Origin_Long + (DD - T1 * D3 / 3.0 + T * T1 * D5 / 15.0) / cosphi1; + + if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */ + *Latitude = PI_OVER_2; + else if (*Latitude < -PI_OVER_2) + *Latitude = -PI_OVER_2; + +// if (*Longitude > PI) +// *Longitude -= TWO_PI; +// if (*Longitude < -PI) +// *Longitude += TWO_PI; + + if (*Longitude > M_PI) /* force distorted values to 180, -180 degrees */ + *Longitude = M_PI; + else if (*Longitude < -M_PI) + *Longitude = -M_PI; + } + if (fabs(*Longitude - Cass_Origin_Long) > (4.0 * M_PI / 180.0)) + { /* Distortion will result if Longitude is more than 4 degrees from the Central Meridian */ + Error_Code |= CASS_LON_WARNING; + } + } + return (Error_Code); +} /* End Convert_Cassini_To_Geodetic */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimCassiniProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimCassiniProjection.h new file mode 100644 index 0000000000..23c2b9cb7f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimCassiniProjection.h @@ -0,0 +1,208 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Cassini projection code. +//******************************************************************* +// $Id: ossimCassiniProjection.h,v 1.5 2005/09/09 19:23:58 gpotts Exp $ + +#ifndef ossimCassiniProjection_HEADER +#define ossimCassiniProjection_HEADER + +#include "ossimMapProjection.h" + +class ossimCassiniProjection : public ossimMapProjection +{ +public: + ossimCassiniProjection(const ossimEllipsoid& ellipsoid = ossimEllipsoid(), + const ossimGpt& origin = ossimGpt()); + ossimCassiniProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + const double falseEasting, + const double falseNorthing); + ~ossimCassiniProjection(){} + virtual ossimObject *dup()const{return new ossimCassiniProjection(*this);} + + virtual ossimDpt forward(const ossimGpt &worldPoint) const; + virtual ossimGpt inverse(const ossimDpt &projectedPoint)const; + virtual void update(); + /*! + * SetFalseEasting. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEasting(double falseEasting); + + /*! + * SetFalseNorthing. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseNorthing(double falseNorthing); + + /*! + * Sets both false easting and northing values. The values are + * expected to be in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEastingNorthing(double falseEasting, double falseNorthing); + + double getFalseEasting()const{return Cass_False_Easting;} + double getFalseNorthing()const{return Cass_False_Northing;} + + /*! + * Initialize all pramters to default and calls update for + * pre-computations. + */ + void setDefaults(); + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +private: + + //_____________________GETRANS STUFF_____________________ + + mutable double Cass_a; /* Semi-major axis of ellipsoid in meters */ + mutable double Cass_f; /* Flattening of ellipsoid */ + mutable double es2; /* Eccentricity (0.08181919084262188000) squared */ + mutable double es4; /* es2 * es2 */ + mutable double es6; /* es4 * es2 */ + mutable double M0; + mutable double c0; /* 1 - es2 / 4.0 - 3.0 * es4 / 64.0 - 5.0 * es6 / 256.0 */ + mutable double c1; /* 3.0 * es2 / 8.0 + 3.0 * es4 / 32.0 + 45.0 * es6 / 1024.0 */ + mutable double c2; /* 15.0 * es4 / 256.0 + 45.0 * es6 / 1024.0 */ + mutable double c3; /* 35.0 * es6 / 3072.0 */ + mutable double One_Minus_es2; /* 1.0 - es2 */ + mutable double a0; /* 3.0 * e1 / 2.0 - 27.0 * e3 / 32.0 */ + mutable double a1; /* 21.0 * e2 / 16.0 - 55.0 * e4 / 32.0 */ + mutable double a2; /* 151.0 * e3 / 96.0 */ + mutable double a3; /* 1097.0 * e4 /512.0 */ + +/* Cassini projection Parameters */ + mutable double Cass_Origin_Lat; /* Latitude of origin in radians */ + mutable double Cass_Origin_Long; /* Longitude of origin in radians */ + mutable double Cass_False_Northing; /* False northing in meters */ + mutable double Cass_False_Easting; /* False easting in meters */ + + /* Maximum variance for easting and northing values for WGS 84. + */ + mutable double Cass_Min_Easting; + mutable double Cass_Max_Easting; + mutable double Cass_Min_Northing; + mutable double Cass_Max_Northing; + +/*! + * The function Set_Cassini_Parameters receives the ellipsoid parameters and + * Cassini projcetion parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the + * function, otherwise CASS_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at which the (input) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + long Set_Cassini_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing); + + +/*! + * The function Get_Cassini_Parameters returns the current ellipsoid + * parameters, and Cassini projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at which the (output) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + void Get_Cassini_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const; + + +/*! + * The function Convert_Geodetic_To_Cassini converts geodetic (latitude and + * longitude) coordinates to Cassini projection easting, and northing + * coordinates, according to the current ellipsoid and Cassini projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise CASS_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + long Convert_Geodetic_To_Cassini (double Latitude, + double Longitude, + double *Easting, + double *Northing)const; + + +/*! + * The function Convert_Cassini_To_Geodetic converts Cassini projection + * easting and northing coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Cassini projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise CASS_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + long Convert_Cassini_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimCylEquAreaProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimCylEquAreaProjection.cpp new file mode 100644 index 0000000000..08fbe53752 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimCylEquAreaProjection.cpp @@ -0,0 +1,467 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Cylinder Equal Area projection code. +//******************************************************************* +// $Id: ossimCylEquAreaProjection.cpp,v 1.11 2004/01/08 21:49:21 jlargent Exp $ +#include "ossimCylEquAreaProjection.h" +#include "base/common/ossimKeywordNames.h" + +RTTI_DEF1(ossimCylEquAreaProjection, "ossimCylEquAreaProjection", ossimMapProjection) + +/***************************************************************************/ +/* + * DEFINES + */ + +#define CYEQ_NO_ERROR 0x0000 +#define CYEQ_LAT_ERROR 0x0001 +#define CYEQ_LON_ERROR 0x0002 +#define CYEQ_EASTING_ERROR 0x0004 +#define CYEQ_NORTHING_ERROR 0x0008 +#define CYEQ_ORIGIN_LAT_ERROR 0x0010 +#define CYEQ_CENT_MER_ERROR 0x0020 +#define CYEQ_A_ERROR 0x0040 +#define CYEQ_B_ERROR 0x0080 +#define CYEQ_A_LESS_B_ERROR 0x0100 + +/***************************************************************************/ +/* + * DEFINES + */ + +#ifndef PI_OVER_2 +# define PI_OVER_2 ( M_PI / 2.0) +#endif +#ifndef TWO_PI +# define TWO_PI (2.0 * M_PI) +#endif +#define CYLEQAR_Q(slat, x) (1.0-es2)*(slat/(1.0-x*x)-(1.0/(2.0*es))* \ + log((1.0-x)/(1.0+x))) +#define CYEQ_COEFF_TIMES_SIN(coeff, c, Beta) (coeff * sin(c * Beta)) +#define ONE (1.0 * M_PI / 180.0) /* 1 degree in radians */ + + +ossimCylEquAreaProjection::ossimCylEquAreaProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + :ossimMapProjection(ellipsoid, origin) +{ + setDefaults(); + update(); +} + +ossimCylEquAreaProjection::ossimCylEquAreaProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double falseEasting, + double falseNorthing) + :ossimMapProjection(ellipsoid, origin) +{ + Cyeq_False_Easting = falseEasting; + Cyeq_False_Northing = falseNorthing; + Cyeq_Max_Easting = 20037509.0; + Cyeq_Min_Easting = -20037509.0; + Cyeq_Delta_Northing = 6363886.0; + + update(); +} + +void ossimCylEquAreaProjection::setFalseEasting(double falseEasting) +{ + Cyeq_False_Easting = falseEasting; + update(); +} + +void ossimCylEquAreaProjection::setFalseNorthing(double falseNorthing) +{ + Cyeq_False_Northing = falseNorthing; + update(); +} + +void ossimCylEquAreaProjection::setFalseEastingNorthing(double falseEasting, + double falseNorthing) +{ + Cyeq_False_Easting = falseEasting; + Cyeq_False_Northing = falseNorthing; + update(); +} + +void ossimCylEquAreaProjection::setDefaults() +{ + Cyeq_False_Easting = 0.0; + Cyeq_False_Northing = 0.0; + Cyeq_Max_Easting = 20037509.0; + Cyeq_Min_Easting = -20037509.0; + Cyeq_Delta_Northing = 6363886.0; +} + +void ossimCylEquAreaProjection::update() +{ + Cyeq_Max_Easting = 20037509.0; + Cyeq_Min_Easting = -20037509.0; + Cyeq_Delta_Northing = 6363886.0; + + Set_Cyl_Eq_Area_Parameters(theEllipsoid.getA(), + theEllipsoid.getFlattening(), + theOrigin.latr(), + theOrigin.lonr(), + Cyeq_False_Easting, + Cyeq_False_Northing); + + ossimMapProjection::update(); +} + + +ossimGpt ossimCylEquAreaProjection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat = 0.0; + double lon = 0.0; + + Convert_Cyl_Eq_Area_To_Geodetic(eastingNorthing.x, + eastingNorthing.y, + &lat, + &lon); + return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0, theDatum); +} + +ossimDpt ossimCylEquAreaProjection::forward(const ossimGpt &latLon)const +{ + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + Convert_Geodetic_To_Cyl_Eq_Area(gpt.latr(), + gpt.lonr(), + &easting, + &northing); + + return ossimDpt(easting, northing); + +} + +bool ossimCylEquAreaProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const +{ + kwl.add(prefix, + ossimKeywordNames::FALSE_EASTING_KW, + Cyeq_False_Easting, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_NORTHING_KW, + Cyeq_False_Northing, + true); + + return ossimMapProjection::saveState(kwl, prefix); +} + +bool ossimCylEquAreaProjection::loadState(const ossimKeywordlist& kwl, const char* prefix) +{ + bool flag = ossimMapProjection::loadState(kwl, prefix); + + const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + const char* falseEasting = kwl.find(prefix, ossimKeywordNames::FALSE_EASTING_KW); + const char* falseNorthing = kwl.find(prefix, ossimKeywordNames::FALSE_NORTHING_KW); + + setDefaults(); + + if(ossimString(type) == STATIC_TYPE_NAME(ossimCylEquAreaProjection)) + { + if(falseEasting) + { + Cyeq_False_Easting = ossimString(falseEasting).toDouble(); + } + if(falseNorthing) + { + Cyeq_False_Northing = ossimString(falseNorthing).toDouble(); + } + } + + update(); + + return flag; +} + +/***************************************************************************/ +/* + * FUNCTIONS + */ + + +long ossimCylEquAreaProjection::Set_Cyl_Eq_Area_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing) +{ /* Begin Set_Cyl_Eq_Area_Parameters */ +/* + * The function Set_Cyl_Eq_Area_Parameters receives the ellipsoid parameters and + * Cylindrical Equal Area projcetion parameters as inputs, and sets the corresponding + * state variables. If any errors occur, the error code(s) are returned by the + * function, otherwise CYEQ_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at which the (input) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + + double Sin_Cyeq_Origin_Lat; + double temp; +// double inv_f = 1 / f; + long Error_Code = CYEQ_NO_ERROR; + +// if (a <= 0.0) +// { /* Semi-major axis must be greater than zero */ +// Error_Code |= CYEQ_A_ERROR; +// } +// if ((inv_f < 250) || (inv_f > 350)) +// { /* Inverse flattening must be between 250 and 350 */ +// Error_Code |= CYEQ_INV_F_ERROR; +// } +// if ((Origin_Latitude < -PI_OVER_2) || (Origin_Latitude > PI_OVER_2)) +// { /* origin latitude out of range */ +// Error_Code |= CYEQ_ORIGIN_LAT_ERROR; +// } +// if ((Central_Meridian < -PI) || (Central_Meridian > TWO_PI)) +// { /* origin longitude out of range */ +// Error_Code |= CYEQ_CENT_MER_ERROR; +// } + if (!Error_Code) + { /* no errors */ + Cyeq_a = a; + Cyeq_f = f; + Cyeq_Origin_Lat = Origin_Latitude; + if (Central_Meridian > M_PI) + Central_Meridian -= TWO_PI; + Cyeq_Origin_Long = Central_Meridian; + Cyeq_False_Northing = False_Northing; + Cyeq_False_Easting = False_Easting; + es2 = 2 * Cyeq_f - Cyeq_f * Cyeq_f; + es4 = es2 * es2; + es6 = es4 * es2; + es = sqrt(es2); + c0 = es2 / 3.0 + 31.0 * es4 / 180.0 + 517.0 * es6 / 5040.0; + c1 = 23.0 * es4 / 360.0 + 251.0 * es6 / 3780.0; + c2 = 761.0 * es6 / 45360.0; + Sin_Cyeq_Origin_Lat = sin(Cyeq_Origin_Lat); + k0 = cos(Cyeq_Origin_Lat) / sqrt(1.0 - es2 * Sin_Cyeq_Origin_Lat * Sin_Cyeq_Origin_Lat); + Cyeq_a_k0 = Cyeq_a * k0; + two_k0 = 2.0 * k0; + + if (Cyeq_Origin_Long > 0) + { + Convert_Geodetic_To_Cyl_Eq_Area(PI_OVER_2, Cyeq_Origin_Long - M_PI - ONE, &Cyeq_Max_Easting, &temp); + Convert_Geodetic_To_Cyl_Eq_Area(PI_OVER_2, Cyeq_Origin_Long - M_PI, &Cyeq_Min_Easting, &temp); + Convert_Geodetic_To_Cyl_Eq_Area(PI_OVER_2, M_PI, &temp, &Cyeq_Delta_Northing); + } + else if (Cyeq_Origin_Long < 0) + { + Convert_Geodetic_To_Cyl_Eq_Area(PI_OVER_2, Cyeq_Origin_Long + M_PI, &Cyeq_Max_Easting, &temp); + Convert_Geodetic_To_Cyl_Eq_Area(PI_OVER_2, Cyeq_Origin_Long + M_PI + ONE, &Cyeq_Min_Easting, &temp); + Convert_Geodetic_To_Cyl_Eq_Area(PI_OVER_2, M_PI, &temp, &Cyeq_Delta_Northing); + } + else + { + Convert_Geodetic_To_Cyl_Eq_Area(PI_OVER_2, M_PI, &Cyeq_Max_Easting, &Cyeq_Delta_Northing); + Cyeq_Min_Easting = -Cyeq_Max_Easting; + } + + } /* End if(!Error_Code) */ + return (Error_Code); +} /* End Set_Cyl_Eq_Area_Parameters */ + + +void ossimCylEquAreaProjection::Get_Cyl_Eq_Area_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const +{ /* Begin Get_Cyl_Eq_Area_Parameters */ +/* + * The function Get_Cyl_Eq_Area_Parameters returns the current ellipsoid + * parameters, and Cylindrical Equal Area projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at which the (output) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + + *a = Cyeq_a; + *f = Cyeq_f; + *Origin_Latitude = Cyeq_Origin_Lat; + *Central_Meridian = Cyeq_Origin_Long; + *False_Easting = Cyeq_False_Easting; + *False_Northing = Cyeq_False_Northing; + return; +} /* End Get_Cyl_Eq_Area_Parameters */ + + +long ossimCylEquAreaProjection::Convert_Geodetic_To_Cyl_Eq_Area (double Latitude, + double Longitude, + double *Easting, + double *Northing)const +{ /* Begin Convert_Geodetic_To_Cyl_Eq_Area */ +/* + * The function Convert_Geodetic_To_Cyl_Eq_Area converts geodetic (latitude and + * longitude) coordinates to Cylindrical Equal Area projection (easting and northing) + * coordinates, according to the current ellipsoid and Cylindrical Equal Area projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise CYEQ_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + + double dlam; /* Longitude - Central Meridan */ + double qq; + double x; + double sin_lat = sin(Latitude); + long Error_Code = CYEQ_NO_ERROR; + +// if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2)) +// { /* Latitude out of range */ +// Error_Code |= CYEQ_LAT_ERROR; +// } +// if ((Longitude < -PI) || (Longitude > TWO_PI)) +// { /* Longitude out of range */ +// Error_Code |= CYEQ_LON_ERROR; +// } + if (!Error_Code) + { /* no errors */ + dlam = Longitude - Cyeq_Origin_Long; +// if (dlam > PI) +// { +// dlam -= TWO_PI; +// } +// if (dlam < -PI) +// { +// dlam += TWO_PI; +// } + x = es * sin_lat; + qq = CYLEQAR_Q(sin_lat,x); + *Easting = Cyeq_a_k0 * dlam + Cyeq_False_Easting; + *Northing = Cyeq_a * qq / two_k0 + Cyeq_False_Northing; + } + return (Error_Code); +} /* End Convert_Geodetic_To_Cyl_Eq_Area */ + + +long ossimCylEquAreaProjection::Convert_Cyl_Eq_Area_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const +{ /* Begin Convert_Cyl_Eq_Area_To_Geodetic */ +/* + * The function Convert_Cyl_Eq_Area_To_Geodetic converts + * Cylindrical Equal Area projection (easting and northing) coordinates + * to geodetic (latitude and longitude) coordinates, according to the + * current ellipsoid and Cylindrical Equal Area projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise CYEQ_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + + double sin2beta, sin4beta, sin6beta; + double dx; /* Delta easting - Difference in easting (easting-FE) */ + double dy; /* Delta northing - Difference in northing (northing-FN) */ + double qp; + double beta; + double sin_lat = sin(PI_OVER_2); + double i; + double x; + long Error_Code = CYEQ_NO_ERROR; + +// if ((Easting < (Cyeq_False_Easting + Cyeq_Min_Easting)) +// || (Easting > (Cyeq_False_Easting + Cyeq_Max_Easting))) +// { /* Easting out of range */ +// Error_Code |= CYEQ_EASTING_ERROR; +// } +// if ((Northing < (Cyeq_False_Northing - fabs(Cyeq_Delta_Northing))) +// || (Northing > (Cyeq_False_Northing + fabs(Cyeq_Delta_Northing)))) +// { /* Northing out of range */ +// Error_Code |= CYEQ_NORTHING_ERROR; +// } + if (!Error_Code) + { /* no errors */ + dy = Northing - Cyeq_False_Northing; + dx = Easting - Cyeq_False_Easting; + x = es * sin_lat; + qp = CYLEQAR_Q(sin_lat,x); + i = two_k0 * dy / (Cyeq_a * qp); + if (i > 1.0) + i = 1.0; + else if (i < -1.0) + i = -1.0; + beta = asin(i); + sin2beta = CYEQ_COEFF_TIMES_SIN(c0, 2.0, beta); + sin4beta = CYEQ_COEFF_TIMES_SIN(c1, 4.0, beta); + sin6beta = CYEQ_COEFF_TIMES_SIN(c2, 6.0, beta); + *Latitude = beta + sin2beta + sin4beta + sin6beta; + *Longitude = Cyeq_Origin_Long + dx / Cyeq_a_k0; + +// if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */ +// *Latitude = PI_OVER_2; +// else if (*Latitude < -PI_OVER_2) +// *Latitude = -PI_OVER_2; + +// if (*Longitude > PI) +// *Longitude -= TWO_PI; +// if (*Longitude < -PI) +// *Longitude += TWO_PI; + +// if (*Longitude > PI) /* force distorted values to 180, -180 degrees */ +// *Longitude = PI; +// else if (*Longitude < -PI) +// *Longitude = -PI; + + + } + return (Error_Code); +} /* End Convert_Cyl_Eq_Area_To_Geodetic */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimCylEquAreaProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimCylEquAreaProjection.h new file mode 100644 index 0000000000..5db0607841 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimCylEquAreaProjection.h @@ -0,0 +1,211 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Cylinder Equal Area projection code. +//******************************************************************* +// $Id: ossimCylEquAreaProjection.h,v 1.5 2005/09/09 19:23:58 gpotts Exp $ + +#ifndef ossimCylEquAreaProjection_HEADER +#define ossimCylEquAreaProjection_HEADER + +#include "ossimMapProjection.h" + +class ossimCylEquAreaProjection : public ossimMapProjection +{ +public: + ossimCylEquAreaProjection(const ossimEllipsoid& ellipsoid = ossimEllipsoid(), + const ossimGpt& origin = ossimGpt()); + ossimCylEquAreaProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double falseEasting, + double falseNorthing); + ~ossimCylEquAreaProjection(){} + virtual ossimObject *dup()const + { + return new ossimCylEquAreaProjection(*this); + } + + virtual ossimDpt forward(const ossimGpt &worldPoint) const; + virtual ossimGpt inverse(const ossimDpt &projectedPoint)const; + virtual void update(); + + /*! + * SetFalseEasting. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEasting(double falseEasting); + + /*! + * SetFalseNorthing. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseNorthing(double falseNorthing); + + /*! + * Sets both false easting and northing values. The values are + * expected to be in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEastingNorthing(double falseEasting, double falseNorthing); + + double getFalseEasting()const{return Cyeq_False_Easting;} + double getFalseNorthing()const{return Cyeq_False_Northing;} + + /*! + * Initialize all pramters to default and calls update for + * pre-computations. + */ + void setDefaults(); + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +private: + + +/* Ellipsoid Parameters, default to WGS 84 */ + mutable double Cyeq_a; /* Semi-major axis of ellipsoid in meters */ + mutable double Cyeq_f; /* Flattening of ellipsoid */ + mutable double es2; /* Eccentricity (0.08181919084262188000) squared */ + mutable double es; /* Sqrt(es2) */ + mutable double es4; /* es2 * es2 */ + mutable double es6; /* es4 * es2 */ + mutable double k0; + mutable double Cyeq_a_k0; /* Cyeq_a * k0 */ + mutable double two_k0; /* 2.0 * k0 */ + mutable double c0; /* es2 / 3.0 + 31.0 * es4 / 180.0 + 517.0 * es6 / 5040.0 */ + mutable double c1; /* 23.0 es4 / 360.0 + 251.0 * es6 / 3780.0 */ + mutable double c2; /* 761.0 * es6 / 45360.0 */ + +/* Cylindrical Equal Area projection Parameters */ + mutable double Cyeq_Origin_Lat; /* Latitude of origin in radians */ + mutable double Cyeq_Origin_Long; /* Longitude of origin in radians */ + mutable double Cyeq_False_Northing; /* False northing in meters */ + mutable double Cyeq_False_Easting; /* False easting in meters */ + +/* Maximum variance for easting and northing values for WGS 84. + */ + mutable double Cyeq_Max_Easting; + mutable double Cyeq_Min_Easting; + mutable double Cyeq_Delta_Northing; + +/*! + * The function Set_Cyl_Eq_Area_Parameters receives the ellipsoid parameters and + * Cylindrical Equal Area projcetion parameters as inputs, and sets the corresponding + * state variables. If any errors occur, the error code(s) are returned by the + * function, otherwise CYEQ_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at which the (input) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + long Set_Cyl_Eq_Area_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing); + + +/*! + * The function Get_Cyl_Eq_Area_Parameters returns the current ellipsoid + * parameters and Cylindrical Equal Area projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at which the (output) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ void Get_Cyl_Eq_Area_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const; + + + +/*! + * The function Convert_Geodetic_To_Cyl_Eq_Area converts geodetic (latitude and + * longitude) coordinates to Cylindrical Equal Area projection easting, and northing + * coordinates, according to the current ellipsoid and Cylindrical Equal Area projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise CYEQ_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + long Convert_Geodetic_To_Cyl_Eq_Area (double Latitude, + double Longitude, + double *Easting, + double *Northing)const; + + +/*! + * The function Convert_Cyl_Eq_Area_To_Geodetic converts Cylindrical Equal Area projection + * easting and northing coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Cylindrical Equal Area projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise CYEQ_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + long Convert_Cyl_Eq_Area_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const; + +/*! + * RTTI information found in data_types/rtti.h + */ +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimEckert4Projection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimEckert4Projection.cpp new file mode 100644 index 0000000000..681dbf40f5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimEckert4Projection.cpp @@ -0,0 +1,462 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Eckert4 projection code. +//******************************************************************* +// $Id: ossimEckert4Projection.cpp,v 1.11 2004/01/08 21:49:21 jlargent Exp $ +#include "ossimEckert4Projection.h" + +#include "base/common/ossimKeywordNames.h" + +RTTI_DEF1(ossimEckert4Projection, "ossimEckert4Projection", ossimMapProjection) + + +/***************************************************************************/ +/* + * DEFINES + */ + +#ifndef PI_OVER_2 +# define PI_OVER_2 ( M_PI / 2.0) +#endif +#ifndef TWO_PI +# define TWO_PI (2.0 * M_PI) +#endif +#define NUM(Theta, SinTheta, CosTheta) (Theta + SinTheta * CosTheta + 2.0 * SinTheta) + + +#define ECK4_NO_ERROR 0x0000 +#define ECK4_LAT_ERROR 0x0001 +#define ECK4_LON_ERROR 0x0002 +#define ECK4_EASTING_ERROR 0x0004 +#define ECK4_NORTHING_ERROR 0x0008 +#define ECK4_CENT_MER_ERROR 0x0020 +#define ECK4_A_ERROR 0x0040 +#define ECK4_B_ERROR 0x0080 +#define ECK4_A_LESS_B_ERROR 0x0100 + +/***************************************************************************/ +/* + * GLOBALS + */ + +const double two_PLUS_PI_OVER_2 = (2.0 + M_PI / 2.0); + +ossimEckert4Projection::ossimEckert4Projection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + :ossimMapProjection(ellipsoid, origin) +{ + setDefaults(); + update(); +} + +ossimEckert4Projection::ossimEckert4Projection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double falseEasting, + double falseNorthing) + :ossimMapProjection(ellipsoid, origin) +{ + + Eck4_False_Easting = falseEasting; + Eck4_False_Northing = falseNorthing; + Eck4_Delta_Northing = 8451144.0; + Eck4_Max_Easting = 16902288.0; + Eck4_Min_Easting = -16902288.0; + + update(); +} + + +void ossimEckert4Projection::update() +{ + + Set_Eckert4_Parameters(theEllipsoid.getA(), + theEllipsoid.getFlattening(), + theOrigin.lonr(), + Eck4_False_Easting, + Eck4_False_Northing); + + ossimMapProjection::update(); +} + +ossimGpt ossimEckert4Projection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat = 0.0; + double lon = 0.0; + + Convert_Eckert4_To_Geodetic(eastingNorthing.x, + eastingNorthing.y, + &lat, + &lon); + + return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum); +} + +ossimDpt ossimEckert4Projection::forward(const ossimGpt &latLon)const +{ + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + Convert_Geodetic_To_Eckert4(gpt.latr(), + gpt.lonr(), + &easting, + &northing); + + return ossimDpt(easting, northing); +} + +void ossimEckert4Projection::setFalseEasting(double falseEasting) +{ + Eck4_False_Easting = falseEasting; + update(); +} + +void ossimEckert4Projection::setFalseNorthing(double falseNorthing) +{ + Eck4_False_Northing = falseNorthing; + update(); +} + +void ossimEckert4Projection::setFalseEastingNorthing(double falseEasting, + double falseNorthing) +{ + Eck4_False_Easting = falseEasting; + Eck4_False_Northing = falseNorthing; + update(); +} + +void ossimEckert4Projection::setDefaults() +{ + Eck4_Delta_Northing = 8451144.0; + Eck4_Max_Easting = 16902288.0; + Eck4_Min_Easting = -16902288.0; + Eck4_False_Easting = 0.0; + Eck4_False_Northing = 0.0; +} + +bool ossimEckert4Projection::saveState(ossimKeywordlist& kwl, const char* prefix) const +{ + kwl.add(prefix, + ossimKeywordNames::FALSE_EASTING_KW, + Eck4_False_Easting, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_NORTHING_KW, + Eck4_False_Northing, + true); + + return ossimMapProjection::saveState(kwl, prefix); +} + +bool ossimEckert4Projection::loadState(const ossimKeywordlist& kwl, const char* prefix) +{ + bool flag = ossimMapProjection::loadState(kwl, prefix); + + const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + const char* falseEasting = kwl.find(prefix, ossimKeywordNames::FALSE_EASTING_KW); + const char* falseNorthing = kwl.find(prefix, ossimKeywordNames::FALSE_NORTHING_KW); + + setDefaults(); + + if(ossimString(type) == STATIC_TYPE_NAME(ossimEckert4Projection)) + { + if(falseEasting) + { + Eck4_False_Easting = ossimString(falseEasting).toDouble(); + } + if(falseNorthing) + { + Eck4_False_Northing = ossimString(falseNorthing).toDouble(); + } + } + + update(); + + return flag; +} + +/***************************************************************************/ +/* + * FUNCTIONS + */ + + +long ossimEckert4Projection::Set_Eckert4_Parameters(double a, + double f, + double Central_Meridian, + double False_Easting, + double False_Northing) + +{ /* Begin Set_Eckert4_Parameters */ +/* + * The function Set_Eckert4_Parameters receives the ellipsoid parameters and + * projection parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the + * function, otherwise ECK4_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + + double Ra; /* Spherical radius */ +// double inv_f = 1 / f; + long Error_Code = ECK4_NO_ERROR; + +// if (a <= 0.0) +// { /* Semi-major axis must be greater than zero */ +// Error_Code |= ECK4_A_ERROR; +// } +// if ((inv_f < 250) || (inv_f > 350)) +// { /* Inverse flattening must be between 250 and 350 */ +// Error_Code |= ECK4_INV_F_ERROR; +// } +// if ((Central_Meridian < -PI) || (Central_Meridian > TWO_PI)) +// { /* origin longitude out of range */ +// Error_Code |= ECK4_CENT_MER_ERROR; +// } + if (!Error_Code) + { /* no errors */ + Eck4_a = a; + Eck4_f = f; + es2 = 2 * Eck4_f - Eck4_f * Eck4_f; + es4 = es2 * es2; + es6 = es4 * es2; + /* spherical radius */ + Ra = Eck4_a * (1.0 - es2 / 6.0 - 17.0 * es4 / 360.0 - 67.0 * es6 / 3024.0); + Ra0 = 0.4222382 * Ra; + Ra1 = 1.3265004 * Ra; +// if (Central_Meridian > PI) +// Central_Meridian -= TWO_PI; + Eck4_Origin_Long = Central_Meridian; + Eck4_False_Easting = False_Easting; + Eck4_False_Northing = False_Northing; + if (Eck4_Origin_Long > 0) + { + Eck4_Max_Easting = 16808386.0; + Eck4_Min_Easting = -16902288.0; + } + else if (Eck4_Origin_Long < 0) + { + Eck4_Max_Easting = 16902288.0; + Eck4_Min_Easting = -16808386.0; + } + else + { + Eck4_Max_Easting = 16902288.0; + Eck4_Min_Easting = -16902288.0; + } + + } /* End if(!Error_Code) */ + return (Error_Code); +} /* End Set_Eckert4_Parameters */ + + +void ossimEckert4Projection::Get_Eckert4_Parameters(double *a, + double *f, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const +{ /* Begin Get_Eckert4_Parameters */ +/* + * The function Get_Eckert4_Parameters returns the current ellipsoid + * parameters and Eckert IV projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + + *a = Eck4_a; + *f = Eck4_f; + *Central_Meridian = Eck4_Origin_Long; + *False_Easting = Eck4_False_Easting; + *False_Northing = Eck4_False_Northing; + return; +} /* End Get_Eckert4_Parameters */ + + +long ossimEckert4Projection::Convert_Geodetic_To_Eckert4 (double Latitude, + double Longitude, + double *Easting, + double *Northing)const + +{ /* Begin Convert_Geodetic_To_Eckert4 */ +/* + * The function Convert_Geodetic_To_Eckert4 converts geodetic (latitude and + * longitude) coordinates to Eckert IV projection (easting and northing) + * coordinates, according to the current ellipsoid, spherical radius and + * Eckert IV projection parameters. + * If any errors occur, the error code(s) are returned by the + * function, otherwise ECK4_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + + double slat = sin(Latitude); + double sin_theta, cos_theta; + double num; + double dlam; /* Longitude - Central Meridan */ + double theta = Latitude / 2.0; + double delta_theta = 1.0; + double dt_tolerance = 4.85e-10; /* approximately 1/1000th of + an arc second or 1/10th meter */ + long Error_Code = ECK4_NO_ERROR; + +// if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2)) +// { /* Latitude out of range */ +// Error_Code |= ECK4_LAT_ERROR; +// } +// if ((Longitude < -PI) || (Longitude > TWO_PI)) +// { /* Longitude out of range */ +// Error_Code|= ECK4_LON_ERROR; +// } + + if (!Error_Code) + { /* no errors */ + + dlam = Longitude - Eck4_Origin_Long; +// if (dlam > PI) +// { +// dlam -= TWO_PI; +// } +// if (dlam < -PI) +// { +// dlam += TWO_PI; +// } + while (fabs(delta_theta) > dt_tolerance) + { + sin_theta = sin(theta); + cos_theta = cos(theta); + num = NUM(theta, sin_theta, cos_theta); + delta_theta = -(num - two_PLUS_PI_OVER_2 * slat) / + (2.0 * cos_theta * (1.0 + cos_theta)); + theta += delta_theta; + } + *Easting = Ra0 * dlam * (1.0 + cos(theta)) + Eck4_False_Easting; + *Northing = Ra1 * sin(theta) + Eck4_False_Northing; + } + + return (Error_Code); + +} /* End Convert_Geodetic_To_Eckert4 */ + + +long ossimEckert4Projection::Convert_Eckert4_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const +{ /* Begin Convert_Eckert4_To_Geodetic */ +/* + * The function Convert_Eckert4_To_Geodetic converts Eckert IV projection + * (easting and northing) coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid, spherical radius and + * Eckert IV projection coordinates. + * If any errors occur, the error code(s) are returned by the + * function, otherwise ECK4_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + + double theta; + double sin_theta, cos_theta; + double num; + double dx, dy; + double i; + + long Error_Code = ECK4_NO_ERROR; + +// if ((Easting < (Eck4_False_Easting + Eck4_Min_Easting)) +// || (Easting > (Eck4_False_Easting + Eck4_Max_Easting))) +// { /* Easting out of range */ +// Error_Code |= ECK4_EASTING_ERROR; +// } +// if ((Northing < (Eck4_False_Northing - Eck4_Delta_Northing)) +// || (Northing > (Eck4_False_Northing + Eck4_Delta_Northing))) +// { /* Northing out of range */ +// Error_Code |= ECK4_NORTHING_ERROR; +// } + + if (!Error_Code) + { + dy = Northing - Eck4_False_Northing; + dx = Easting - Eck4_False_Easting; + i = dy / Ra1; + if (i > 1.0) + i = 1.0; + else if (i < -1.0) + i = -1.0; + + theta = asin(i); + sin_theta = sin(theta); + cos_theta = cos(theta); + num = NUM(theta, sin_theta, cos_theta); + + *Latitude = asin(num / two_PLUS_PI_OVER_2); + *Longitude = Eck4_Origin_Long + dx / (Ra0 * (1 + cos_theta)); + +// if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */ +// *Latitude = PI_OVER_2; +// else if (*Latitude < -PI_OVER_2) +// *Latitude = -PI_OVER_2; + +// if (*Longitude > PI) +// *Longitude -= TWO_PI; +// if (*Longitude < -PI) +// *Longitude += TWO_PI; + +// if (*Longitude > PI) /* force distorted values to 180, -180 degrees */ +// *Longitude = PI; +// else if (*Longitude < -PI) +// *Longitude = -PI; + + } + return (Error_Code); + +} /* End Convert_Eckert4_To_Geodetic */ + diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimEckert4Projection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimEckert4Projection.h new file mode 100644 index 0000000000..f3e314b723 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimEckert4Projection.h @@ -0,0 +1,193 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Eckert4 projection code. +//******************************************************************* +// $Id: ossimEckert4Projection.h,v 1.5 2005/09/09 19:23:58 gpotts Exp $ +#ifndef ossimEcker4Projection_HEADER +#define ossimEcker4Projection_HEADER +#include "ossimMapProjection.h" + +class ossimEckert4Projection : public ossimMapProjection +{ +public: + + ossimEckert4Projection(const ossimEllipsoid& ellipsoid = ossimEllipsoid(), + const ossimGpt& origin = ossimGpt()); + ossimEckert4Projection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double falseEasting, + double falseNorthing); + ~ossimEckert4Projection(){} + virtual ossimObject *dup()const + { + return new ossimEckert4Projection(*this); + } + + virtual ossimDpt forward(const ossimGpt &worldPoint) const; + virtual ossimGpt inverse(const ossimDpt &projectedPoint) const; + virtual void update(); + /*! + * SetFalseEasting. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEasting(double falseEasting); + + /*! + * SetFalseNorthing. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseNorthing(double falseNorthing); + + /*! + * Sets both false easting and northing values. The values are + * expected to be in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEastingNorthing(double falseEasting, double falseNorthing); + + double getFalseEasting()const{return Eck4_False_Easting;} + double getFalseNorthing()const{return Eck4_False_Northing;} + + /*! + * Initialize all pramters to default and calls update for + * pre-computations. + */ + void setDefaults(); + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +private: +/* Ellipsoid Parameters, default to WGS 84 */ + mutable double Eck4_a; /* Semi-major axis of ellipsoid in meters */ + mutable double Eck4_f; /* Flattening of ellipsoid */ + mutable double es2; /* Eccentricity (0.08181919084262188000) squared */ + mutable double es4; /* es2 * es2 */ + mutable double es6; /* es4 * es2 */ + + mutable double Ra0; /* 0.4222382 * Sperical Radius (6371007.1810824) */ + mutable double Ra1; /* 1.3265004 * Sperical Radius (6371007.1810824) */ + +/* Eckert4 projection Parameters */ + mutable double Eck4_Origin_Long; /* Longitude of origin in radians */ + mutable double Eck4_False_Easting; + mutable double Eck4_False_Northing; + mutable double Eck4_Delta_Northing; + mutable double Eck4_Max_Easting; + mutable double Eck4_Min_Easting; + +/*! + * The function Set_Eckert4_Parameters receives the ellipsoid parameters and + * Eckert IV projection parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the + * function, otherwise ECK4_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + long Set_Eckert4_Parameters(double a, + double f, + double Central_Meridian, + double False_Easting, + double False_Northing); + + +/*! + * The function Get_Eckert4_Parameters returns the current ellipsoid + * parameters and EckertIV projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + void Get_Eckert4_Parameters(double *a, + double *f, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const; + + +/*! + * The function Convert_Geodetic_To_Eckert4 converts geodetic (latitude and + * longitude) coordinates to Eckert IV projection easting, and northing + * coordinates, according to the current ellipsoid and Eckert IV projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise ECK4_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + long Convert_Geodetic_To_Eckert4 (double Latitude, + double Longitude, + double *Easting, + double *Northing)const; + + +/*! + * The function Convert_Eckert4_To_Geodetic converts Eckert IV projection + * easting and northing coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Eckert IV projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise ECK4_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + long Convert_Eckert4_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const; + +/*! + * RTTI information + */ +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimEckert6Projection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimEckert6Projection.cpp new file mode 100644 index 0000000000..1c1cb65a78 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimEckert6Projection.cpp @@ -0,0 +1,445 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Eckert6 projection code. +//******************************************************************* +// $Id: ossimEckert6Projection.cpp,v 1.10 2004/01/08 21:49:21 jlargent Exp $ + +/***************************************************************************/ +/* + * DEFINES + */ +#include "ossimEckert6Projection.h" + +#include "base/common/ossimKeywordNames.h" + +RTTI_DEF1(ossimEckert6Projection, "ossimEckert6Projection", ossimMapProjection) + +#define ECK6_NO_ERROR 0x0000 +#define ECK6_LAT_ERROR 0x0001 +#define ECK6_LON_ERROR 0x0002 +#define ECK6_EASTING_ERROR 0x0004 +#define ECK6_NORTHING_ERROR 0x0008 +#define ECK6_CENT_MER_ERROR 0x0020 +#define ECK6_A_ERROR 0x0040 +#define ECK6_B_ERROR 0x0080 +#define ECK6_A_LESS_B_ERROR 0x0100 + +#ifndef PI_OVER_2 +# define PI_OVER_2 ( M_PI / 2.0) +#endif +#ifndef TWO_PI +# define TWO_PI (2.0 * M_PI) +#endif + +#define MAX_LAT ( (M_PI * 90.0) / 180.0 ) /* 90 degrees in radians */ + +/***************************************************************************/ +/* + * GLOBALS + */ + +const double one_PLUS_PI_OVER_2 = (1.0 + M_PI / 2.0); + +ossimEckert6Projection::ossimEckert6Projection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + :ossimMapProjection(ellipsoid, origin) +{ + setDefaults(); +} + +ossimEckert6Projection::ossimEckert6Projection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double falseEasting, + double falseNorthing) + :ossimMapProjection(ellipsoid, origin) +{ + Eck6_False_Easting = falseEasting; + Eck6_False_Northing = falseNorthing; + Eck6_Delta_Northing = 8451144.0; + Eck6_Max_Easting = 16902288.0; + Eck6_Min_Easting = -16902288.0; + + update(); +} + +void ossimEckert6Projection::update() +{ + Set_Eckert6_Parameters(theEllipsoid.getA(), + theEllipsoid.getFlattening(), + theOrigin.lonr(), + Eck6_False_Easting, + Eck6_False_Northing); + + ossimMapProjection::update(); +} + +ossimGpt ossimEckert6Projection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat = 0.0; + double lon = 0.0; + + Convert_Eckert6_To_Geodetic(eastingNorthing.x, + eastingNorthing.y, + &lat, + &lon); + + return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum); +} + +ossimDpt ossimEckert6Projection::forward(const ossimGpt &latLon)const +{ + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + Convert_Geodetic_To_Eckert6(gpt.latr(), + gpt.lonr(), + &easting, + &northing); + + return ossimDpt(easting, northing); +} +void ossimEckert6Projection::setFalseEasting(double falseEasting) +{ + Eck6_False_Easting = falseEasting; + update(); +} + +void ossimEckert6Projection::setFalseNorthing(double falseNorthing) +{ + Eck6_False_Northing = falseNorthing; + update(); +} + +void ossimEckert6Projection::setFalseEastingNorthing(double falseEasting, + double falseNorthing) +{ + Eck6_False_Easting = falseEasting; + Eck6_False_Northing = falseNorthing; + update(); +} + +void ossimEckert6Projection::setDefaults() +{ + Eck6_Delta_Northing = 8451144.0; + Eck6_Max_Easting = 16902288.0; + Eck6_Min_Easting = -16902288.0; + Eck6_False_Easting = 0.0; + Eck6_False_Northing = 0.0; + + update(); +} + +bool ossimEckert6Projection::saveState(ossimKeywordlist& kwl, const char* prefix) const +{ + kwl.add(prefix, + ossimKeywordNames::FALSE_EASTING_KW, + Eck6_False_Easting, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_NORTHING_KW, + Eck6_False_Northing, + true); + + return ossimMapProjection::saveState(kwl, prefix); +} + +bool ossimEckert6Projection::loadState(const ossimKeywordlist& kwl, const char* prefix) +{ + bool flag = ossimMapProjection::loadState(kwl, prefix); + + const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + const char* falseEasting = kwl.find(prefix, ossimKeywordNames::FALSE_EASTING_KW); + const char* falseNorthing = kwl.find(prefix, ossimKeywordNames::FALSE_NORTHING_KW); + + setDefaults(); + + if(ossimString(type) == STATIC_TYPE_NAME(ossimEckert6Projection)) + { + if(falseEasting) + { + Eck6_False_Easting = ossimString(falseEasting).toDouble(); + } + if(falseNorthing) + { + Eck6_False_Northing = ossimString(falseNorthing).toDouble(); + } + } + + update(); + + return flag; +} + +/***************************************************************************/ +/* + * FUNCTIONS + */ + + +long ossimEckert6Projection::Set_Eckert6_Parameters(double a, + double f, + double Central_Meridian, + double False_Easting, + double False_Northing) +{ /* Begin Set_Eckert6_Parameters */ +/* + * The function Set_Eckert6_Parameters receives the ellipsoid parameters and + * Eckert VI projection parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the + * function, otherwise ECK6_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + + double Ra; /* Spherical radius */ +// double inv_f = 1 / f; + long Error_Code = ECK6_NO_ERROR; + +// if (a <= 0.0) +// { /* Semi-major axis must be greater than zero */ +// Error_Code |= ECK6_A_ERROR; +// } +// if ((inv_f < 250) || (inv_f > 350)) +// { /* Inverse flattening must be between 250 and 350 */ +// Error_Code |= ECK6_INV_F_ERROR; +// } +// if ((Central_Meridian < -PI) || (Central_Meridian > TWO_PI)) +// { /* origin longitude out of range */ +// Error_Code |= ECK6_CENT_MER_ERROR; +// } + if (!Error_Code) + { /* no errors */ + Eck6_a = a; + Eck6_f = f; + es2 = 2 * Eck6_f - Eck6_f * Eck6_f; + es4 = es2 * es2; + es6 = es4 * es2; + /* spherical radius */ + Ra = Eck6_a * (1.0 - es2 / 6.0 - 17.0 * es4 / 360.0 - 67.0 * es6 /3024.0); + Ra_Over_Sqrt_Two_Plus_PI = Ra / (sqrt(2.0 + M_PI)); + Inv_Ra_Over_Sqrt_Two_Plus_PI = 1 / Ra_Over_Sqrt_Two_Plus_PI; +// if (Central_Meridian > PI) +// Central_Meridian -= TWO_PI; + Eck6_Origin_Long = Central_Meridian; + Eck6_False_Easting = False_Easting; + Eck6_False_Northing = False_Northing; + if (Eck6_Origin_Long > 0) + { + Eck6_Max_Easting = 17555761.0; + Eck6_Min_Easting = -17653839.0; + } + else if (Eck6_Origin_Long < 0) + { + Eck6_Max_Easting = 17653838.0; + Eck6_Min_Easting = -17555761.0; + } + else + { + Eck6_Max_Easting = 17653838.0; + Eck6_Min_Easting = -17653838.0; + } + + } /* End if(!Error_Code) */ + return (Error_Code); +} /* End Set_Eckert6_Parameters */ + + +void ossimEckert6Projection::Get_Eckert6_Parameters(double *a, + double *f, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const +{ /* Begin Get_Eckert6_Parameters */ +/* + * The function Get_Eckert6_Parameters returns the current ellipsoid + * parameters and Eckert VI projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + + *a = Eck6_a; + *f = Eck6_f; + *Central_Meridian = Eck6_Origin_Long; + *False_Easting = Eck6_False_Easting; + *False_Northing = Eck6_False_Northing; + + return; +} /* End Get_Eckert6_Parameters */ + + +long ossimEckert6Projection::Convert_Geodetic_To_Eckert6 (double Latitude, + double Longitude, + double *Easting, + double *Northing)const + +{ /* Begin Convert_Geodetic_To_Eckert6 */ +/* + * The function Convert_Geodetic_To_Eckert6 converts geodetic (latitude and + * longitude) coordinates to Eckert VI projection (easting and northing) + * coordinates, according to the current ellipsoid and Eckert VI projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise ECK6_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + + double slat = sin(Latitude); + double dlam; /* Longitude - Central Meridan */ + double theta = Latitude; + double delta_theta = 1.0; + double dt_tolerance = 4.85e-10; /* approximately 1/1000th of + an arc second or 1/10th meter */ + long Error_Code = ECK6_NO_ERROR; + +// if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2)) +// { /* Latitude out of range */ +// Error_Code |= ECK6_LAT_ERROR; +// } +// if ((Longitude < -PI) || (Longitude > TWO_PI)) +// { /* Longitude out of range */ +// Error_Code|= ECK6_LON_ERROR; +// } + + if (!Error_Code) + { /* no errors */ + + dlam = Longitude - Eck6_Origin_Long; +// if (dlam > PI) +// { +// dlam -= TWO_PI; +// } +// if (dlam < -PI) +// { +// dlam += TWO_PI; +// } + while (fabs(delta_theta) > dt_tolerance) + { + delta_theta = -(theta + sin(theta) - one_PLUS_PI_OVER_2 * + slat) / (1.0 + cos(theta)); + theta += delta_theta; + } + *Easting = Ra_Over_Sqrt_Two_Plus_PI * dlam * (1.0 + cos(theta)) + + Eck6_False_Easting; + *Northing = 2.0 * Ra_Over_Sqrt_Two_Plus_PI * theta + Eck6_False_Northing; + + } + return (Error_Code); + +} /* End Convert_Geodetic_To_Eckert6 */ + + +long ossimEckert6Projection::Convert_Eckert6_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const +{ /* Begin Convert_Eckert6_To_Geodetic */ +/* + * The function Convert_Eckert6_To_Geodetic converts Eckert VI projection + * (easting and northing) coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Eckert VI projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise ECK6_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + + double dx, dy; + double theta; + double i; + + long Error_Code = ECK6_NO_ERROR; + +// if ((Easting < (Eck6_False_Easting + Eck6_Min_Easting)) +// || (Easting > (Eck6_False_Easting + Eck6_Max_Easting))) +// { /* Easting out of range */ +// Error_Code |= ECK6_EASTING_ERROR; +// } +// if ((Northing < (Eck6_False_Northing - Eck6_Delta_Northing)) +// || (Northing > (Eck6_False_Northing + Eck6_Delta_Northing))) +// { /* Northing out of range */ +// Error_Code |= ECK6_NORTHING_ERROR; +// } + + if (!Error_Code) + { + dy = Northing - Eck6_False_Northing; + dx = Easting - Eck6_False_Easting; + theta = Inv_Ra_Over_Sqrt_Two_Plus_PI * dy / 2.0; + i = (theta + sin(theta)) / one_PLUS_PI_OVER_2; + if (i > 1.0) + *Latitude = MAX_LAT; + else if (i < -1.0) + *Latitude = -MAX_LAT; + else + *Latitude = asin(i); + *Longitude = Eck6_Origin_Long + Inv_Ra_Over_Sqrt_Two_Plus_PI * dx / (1 + cos(theta)); + +// if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */ +// *Latitude = PI_OVER_2; +// else if (*Latitude < -PI_OVER_2) +// *Latitude = -PI_OVER_2; + +// if (*Longitude > PI) +// *Longitude -= TWO_PI; +// if (*Longitude < -PI) +// *Longitude += TWO_PI; + +// if (*Longitude > PI) /* force distorted values to 180, -180 degrees */ +// *Longitude = PI; +// else if (*Longitude < -PI) +// *Longitude = -PI; + + } + return (Error_Code); + +} /* End Convert_Eckert6_To_Geodetic */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimEckert6Projection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimEckert6Projection.h new file mode 100644 index 0000000000..74db055c2f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimEckert6Projection.h @@ -0,0 +1,193 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Eckert6 projection code. +//******************************************************************* +// $Id: ossimEckert6Projection.h,v 1.5 2005/09/09 19:23:58 gpotts Exp $ + +#ifndef ossimEckert6Projection_HEADER +#define ossimEckert6Projection_HEADER + +#include "ossimMapProjection.h" + +class ossimEckert6Projection : public ossimMapProjection +{ +public: + ossimEckert6Projection(const ossimEllipsoid& ellipsoid = ossimEllipsoid(), + const ossimGpt& origin = ossimGpt()); + ossimEckert6Projection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double falseEasting, + double falseNorthing); + ~ossimEckert6Projection(){} + virtual ossimObject *dup()const{return new ossimEckert6Projection(*this);} + + virtual ossimGpt inverse(const ossimDpt &eastingNorthing)const; + virtual ossimDpt forward(const ossimGpt &latLon)const; + virtual void update(); + + /*! + * SetFalseEasting. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEasting(double falseEasting); + + /*! + * SetFalseNorthing. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseNorthing(double falseNorthing); + + /*! + * Sets both false easting and northing values. The values are + * expected to be in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEastingNorthing(double falseEasting, double falseNorthing); + + double getFalseEasting()const{return Eck6_False_Easting;} + double getFalseNorthing()const{return Eck6_False_Northing;} + + /*! + * Initialize all pramters to default and calls update for + * pre-computations. + */ + void setDefaults(); + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +private: + + //__________________GEOTRANS STUFF____________________ + + mutable double Eck6_a; /* Semi-major axis of ellipsoid in meters */ + mutable double Eck6_f; /* Flattening of ellipsoid */ + mutable double es2; /* Eccentricity (0.08181919084262188000) squared */ + mutable double es4; /* es2 * es2 */ + mutable double es6; /* es4 * es2 */ + mutable double Ra_Over_Sqrt_Two_Plus_PI; /* Ra(6371007.1810824)/Sqrt(2.0 + PI) */ + mutable double Inv_Ra_Over_Sqrt_Two_Plus_PI; /* Sqrt(2.0 + PI)/Ra(6371007.1810824) */ + + +/* Eckert6 projection Parameters */ + mutable double Eck6_Origin_Long; /* Longitude of origin in radians */ + mutable double Eck6_False_Easting; + mutable double Eck6_False_Northing; + mutable double Eck6_Delta_Northing; + mutable double Eck6_Max_Easting; + mutable double Eck6_Min_Easting; + + +/*! + * The function Set_Eckert6_Parameters receives the ellipsoid parameters and + * Eckert VI projection parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the + * function, otherwise ECK6_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + long Set_Eckert6_Parameters(double a, + double f, + double Central_Meridian, + double False_Easting, + double False_Northing); + + +/*! + * The function Get_Eckert6_Parameters returns the current ellipsoid + * parameters and Eckert VI projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + void Get_Eckert6_Parameters(double *a, + double *f, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const; + + +/*! + * The function Convert_Geodetic_To_Eckert6 converts geodetic (latitude and + * longitude) coordinates to Eckert VI projection easting, and northing + * coordinates, according to the current ellipsoid and Eckert VI projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise ECK6_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + long Convert_Geodetic_To_Eckert6 (double Latitude, + double Longitude, + double *Easting, + double *Northing)const; + + +/*! + * The function Convert_Eckert6_To_Geodetic converts Eckert VI projection + * easting and northing coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Eckert VI projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise ECK6_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + long Convert_Eckert6_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const; + + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimEquDistCylProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimEquDistCylProjection.cpp new file mode 100644 index 0000000000..ce9e2a9fe8 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimEquDistCylProjection.cpp @@ -0,0 +1,466 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Equidistant Cylinder projection code. +//******************************************************************* +// $Id: ossimEquDistCylProjection.cpp,v 1.24 2005/02/10 12:15:59 gpotts Exp $ + +#include <projections/map_projections/ossimEquDistCylProjection.h> +#include <base/common/ossimKeywordNames.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/common/ossimTrace.h> +#include <base/data_types/datum/ossimDatum.h> +#include <base/context/ossimNotifyContext.h> + +static ossimTrace traceDebug("ossimEquDistCylProjection:debug"); + +RTTI_DEF1(ossimEquDistCylProjection, + "ossimEquDistCylProjection", + ossimLlxyProjection) + +/***************************************************************************/ +/* + * DEFINES + */ + +#ifndef PI_OVER_2 +# define PI_OVER_2 ( M_PI / 2.0) +#endif +#ifndef TWO_PI +# define TWO_PI (2.0 * M_PI) +#endif +#define ONE (1.0 * M_PI / 180.0) /* 1 degree in radians*/ + +#define EQCY_NO_ERROR 0x0000 +#define EQCY_LAT_ERROR 0x0001 +#define EQCY_LON_ERROR 0x0002 +#define EQCY_EASTING_ERROR 0x0004 +#define EQCY_NORTHING_ERROR 0x0008 +#define EQCY_ORIGIN_LAT_ERROR 0x0010 +#define EQCY_CENT_MER_ERROR 0x0020 +#define EQCY_A_ERROR 0x0040 +#define EQCY_B_ERROR 0x0080 +#define EQCY_A_LESS_B_ERROR 0x0100 + + +ossimEquDistCylProjection::ossimEquDistCylProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + :ossimLlxyProjection(ellipsoid, origin) +{ + setDefaults(); + update(); +} + +ossimEquDistCylProjection::ossimEquDistCylProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double falseEasting, + double falseNorthing) + :ossimLlxyProjection(ellipsoid, origin) +{ + Eqcy_False_Easting = falseEasting; + Eqcy_False_Northing = falseNorthing; + + Eqcy_Delta_Northing = 10007555.0; + Eqcy_Max_Easting = 20015110.0; + Eqcy_Min_Easting = -20015110.0; + + update(); +} + +void ossimEquDistCylProjection::update() +{ + + Set_Equidistant_Cyl_Parameters(theEllipsoid.getA(), + theEllipsoid.getFlattening(), + theOrigin.latr(), + theOrigin.lonr(), + Eqcy_False_Easting, + Eqcy_False_Northing); + + ossimMapProjection::update(); +} + +void ossimEquDistCylProjection::setFalseEasting(double falseEasting) +{ + Eqcy_False_Easting = falseEasting; + update(); +} + +void ossimEquDistCylProjection::setFalseNorthing(double falseNorthing) +{ + Eqcy_False_Northing = falseNorthing; + update(); +} + +void ossimEquDistCylProjection::setFalseEastingNorthing(double falseEasting, + double falseNorthing) +{ + Eqcy_False_Easting = falseEasting; + Eqcy_False_Northing = falseNorthing; + + update(); +} + +void ossimEquDistCylProjection::setDefaults() +{ + Eqcy_False_Easting = 0.0; + Eqcy_False_Northing = 0.0; + Eqcy_Delta_Northing = 10007555.0; + Eqcy_Max_Easting = 20015110.0; + Eqcy_Min_Easting = -20015110.0; +} + +ossimGpt ossimEquDistCylProjection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat = 0.0; + double lon = 0.0; + + Convert_Equidistant_Cyl_To_Geodetic(eastingNorthing.x, + eastingNorthing.y, + &lat, + &lon); + + return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum); +} + +ossimDpt ossimEquDistCylProjection::forward(const ossimGpt &latLon)const +{ + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + Convert_Geodetic_To_Equidistant_Cyl(gpt.latr(), + gpt.lonr(), + &easting, + &northing); + + return ossimDpt(easting, northing); +} + + + +bool ossimEquDistCylProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const +{ + ossimMapProjection::saveState(kwl, prefix); + + + kwl.add(prefix, + ossimKeywordNames::FALSE_EASTING_KW, + Eqcy_False_Easting, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_NORTHING_KW, + Eqcy_False_Northing, + true); + + return true; +} + +bool ossimEquDistCylProjection::loadState(const ossimKeywordlist& kwl, const char* prefix) +{ + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimEquDistCylProjection::loadState: Input keyword list is \n" << kwl << endl; + } + + ossimLlxyProjection::loadState(kwl, prefix); + + const char* falseEasting = kwl.find(prefix, + ossimKeywordNames::FALSE_EASTING_KW); + const char* falseNorthing = kwl.find(prefix, + ossimKeywordNames::FALSE_NORTHING_KW); + + const char* type = kwl.find(prefix, + ossimKeywordNames::TYPE_KW); + + setDefaults(); + // make sure we are of the same type. If we are then the easting + // northing values will make since + // + if(ossimString(type) == STATIC_TYPE_NAME(ossimEquDistCylProjection)) + { + if(falseEasting) + { + Eqcy_False_Easting = ossimString(falseEasting).toDouble(); + } + if(falseNorthing) + { + Eqcy_False_Northing = ossimString(falseNorthing).toDouble(); + } + } + else + { + theUlEastingNorthing.makeNan(); + } + // finalize the initialization. + update(); + + return true; +} + +/***************************************************************************/ +/* + * FUNCTIONS + */ + + +long ossimEquDistCylProjection::Set_Equidistant_Cyl_Parameters(double a, + double f, + double Std_Parallel, + double Central_Meridian, + double False_Easting, + double False_Northing) +{ /* Begin Set_Equidistant_Cyl_Parameters */ +/* + * The function Set_Equidistant_Cyl_Parameters receives the ellipsoid parameters and + * projection parameters as inputs, and sets the corresponding state + * variables. It also calculates the spherical radius of the sphere having + * the same area as the ellipsoid. If any errors occur, the error code(s) + * are returned by the function, otherwise EQCY_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Std_Parallel : Latitude in radians at which the (input) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * standard parallel of the projection (input) + */ + + double temp; +// double inv_f = 1 / f; + long Error_Code = EQCY_NO_ERROR; + +// if (a <= 0.0) +// { /* Semi-major axis must be greater than zero */ +// Error_Code |= EQCY_A_ERROR; +// } +// if ((inv_f < 250) || (inv_f > 350)) +// { /* Inverse flattening must be between 250 and 350 */ +// Error_Code |= EQCY_INV_F_ERROR; +// } +// if ((Std_Parallel < -PI_OVER_2) || (Std_Parallel > PI_OVER_2)) +// { /* standard parallel out of range */ +// Error_Code |= EQCY_STDP_ERROR; +// } +// if ((Central_Meridian < -PI) || (Central_Meridian > TWO_PI)) +// { /* origin longitude out of range */ +// Error_Code |= EQCY_CENT_MER_ERROR; +// } + if (!Error_Code) + { /* no errors */ + Eqcy_a = a; + Eqcy_f = f; + es2 = 2 * Eqcy_f - Eqcy_f * Eqcy_f; + es4 = es2 * es2; + es6 = es4 * es2; + /* spherical radius */ + Ra = Eqcy_a * (1.0 - es2 / 6.0 - 17.0 * es4 / 360.0 - 67.0 * es6 /3024.0); + Eqcy_Std_Parallel = Std_Parallel; + Cos_Eqcy_Std_Parallel = cos(Eqcy_Std_Parallel); + Ra_Cos_Eqcy_Std_Parallel = Ra * Cos_Eqcy_Std_Parallel; +// if (Central_Meridian > M_PI) +// Central_Meridian -= TWO_PI; + Eqcy_Origin_Long = Central_Meridian; + Eqcy_False_Easting = False_Easting; + Eqcy_False_Northing = False_Northing; + if (Eqcy_Origin_Long > 0) + { + Convert_Geodetic_To_Equidistant_Cyl(PI_OVER_2, Eqcy_Origin_Long - M_PI - ONE, &Eqcy_Max_Easting, &temp); + Convert_Geodetic_To_Equidistant_Cyl(PI_OVER_2, Eqcy_Origin_Long - M_PI, &Eqcy_Min_Easting, &temp); + } + else if (Eqcy_Origin_Long < 0) + { + Convert_Geodetic_To_Equidistant_Cyl(PI_OVER_2, Eqcy_Origin_Long + M_PI, &Eqcy_Max_Easting, &temp); + Convert_Geodetic_To_Equidistant_Cyl(PI_OVER_2, Eqcy_Origin_Long + M_PI + ONE, &Eqcy_Min_Easting, &temp); + } + else + { + Convert_Geodetic_To_Equidistant_Cyl(PI_OVER_2, M_PI, &Eqcy_Max_Easting, &temp); + Eqcy_Min_Easting = -Eqcy_Max_Easting; + } + } /* End if(!Error_Code) */ + return (Error_Code); +} /* End Set_Equidistant_Cyl_Parameters */ + + +void ossimEquDistCylProjection::Get_Equidistant_Cyl_Parameters(double *a, + double *f, + double *Std_Parallel, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const +{ /* Begin Get_Equidistant_Cyl_Parameters */ +/* + * The function Get_Equidistant_Cyl_Parameters returns the current ellipsoid + * parameters and Equidistant Cylindrical projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Std_Parallel : Latitude in radians at which the (output) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * standard parallel of the projection (output) + */ + + *a = Eqcy_a; + *f = Eqcy_f; + *Std_Parallel = Eqcy_Std_Parallel; + *Central_Meridian = Eqcy_Origin_Long; + *False_Easting = Eqcy_False_Easting; + *False_Northing = Eqcy_False_Northing; + return; +} /* End Get_Equidistant_Cyl_Parameters */ + + +long ossimEquDistCylProjection::Convert_Geodetic_To_Equidistant_Cyl (double Latitude, + double Longitude, + double *Easting, + double *Northing)const + +{ /* Begin Convert_Geodetic_To_Equidistant_Cyl */ +/* + * The function Convert_Geodetic_To_Equidistant_Cyl converts geodetic (latitude and + * longitude) coordinates to Equidistant Cylindrical projection (easting and northing) + * coordinates, according to the current ellipsoid, spherical radiius + * and Equidistant Cylindrical projection parameters. + * If any errors occur, the error code(s) are returned by the + * function, otherwise EQCY_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + + double dlam; /* Longitude - Central Meridan */ + long Error_Code = EQCY_NO_ERROR; + +// if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2)) +// { /* Latitude out of range */ +// Error_Code |= EQCY_LAT_ERROR; +// } +// if ((Longitude < -M_PI) || (Longitude > TWO_PI)) +// { /* Longitude out of range */ +// Error_Code|= EQCY_LON_ERROR; +// } + + if (!Error_Code) + { /* no errors */ + dlam = Longitude - Eqcy_Origin_Long; + if (dlam > M_PI) + { + dlam -= TWO_PI; + } + if (dlam < -M_PI) + { + dlam += TWO_PI; + } + + *Easting = Ra_Cos_Eqcy_Std_Parallel * dlam + Eqcy_False_Easting; + *Northing = Ra * Latitude + Eqcy_False_Northing; + + } + return (Error_Code); + +} /* End Convert_Geodetic_To_Equidistant_Cyl */ + + +long ossimEquDistCylProjection::Convert_Equidistant_Cyl_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const +{ /* Begin Convert_Equidistant_Cyl_To_Geodetic */ +/* + * The function Convert_Equidistant_Cyl_To_Geodetic converts Equidistant Cylindrical projection + * (easting and northing) coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid, spherical radius + * and Equidistant Cylindrical projection coordinates. + * If any errors occur, the error code(s) are returned by the + * function, otherwise EQCY_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + + double dx, dy; + long Error_Code = EQCY_NO_ERROR; + +// if ((Easting < (Eqcy_False_Easting + Eqcy_Min_Easting)) +// || (Easting > (Eqcy_False_Easting + Eqcy_Max_Easting))) +// { /* Easting out of range */ +// Error_Code |= EQCY_EASTING_ERROR; +// } +// if ((Northing < (Eqcy_False_Northing - Eqcy_Delta_Northing)) +// || (Northing > (Eqcy_False_Northing + Eqcy_Delta_Northing))) +// { /* Northing out of range */ +// Error_Code |= EQCY_NORTHING_ERROR; +// } + + if (!Error_Code) + { + dy = Northing - Eqcy_False_Northing; + dx = Easting - Eqcy_False_Easting; + *Latitude = dy / Ra; + + if (Ra_Cos_Eqcy_Std_Parallel == 0) + *Longitude = 0; + else + *Longitude = Eqcy_Origin_Long + dx / Ra_Cos_Eqcy_Std_Parallel; + +// if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */ +// *Latitude = PI_OVER_2; +// else if (*Latitude < -PI_OVER_2) +// *Latitude = -PI_OVER_2; + +// if (*Longitude > PI) +// *Longitude -= TWO_PI; +// if (*Longitude < -PI) +// *Longitude += TWO_PI; + +// if (*Longitude > PI) /* force distorted values to 180, -180 degrees */ +// *Longitude = PI; +// else if (*Longitude < -PI) +// *Longitude = -PI; + + } + return (Error_Code); + +} /* End Convert_Equidistant_Cyl_To_Geodetic */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimEquDistCylProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimEquDistCylProjection.h new file mode 100644 index 0000000000..a6ac5b76ce --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimEquDistCylProjection.h @@ -0,0 +1,209 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Equidistant Cylinder projection code. +//******************************************************************* +// $Id: ossimEquDistCylProjection.h,v 1.18 2005/09/09 19:23:58 gpotts Exp $ + +#ifndef ossimEquDistCylProjection_HEADER +#define ossimEquDistCylProjection_HEADER + +#include <projections/map_projections/ossimLlxyProjection.h> + +class OSSIMDLLEXPORT ossimEquDistCylProjection : public ossimLlxyProjection +{ +public: + ossimEquDistCylProjection(const ossimEllipsoid& ellipsoid = ossimEllipsoid(), + const ossimGpt& origin = ossimGpt()); + ossimEquDistCylProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double falseEasting, + double falseNorthing); + + ossimEquDistCylProjection(const ossimEquDistCylProjection& rhs) + :ossimLlxyProjection(rhs) + { + *this = rhs; + } + + ~ossimEquDistCylProjection(){} + virtual ossimObject *dup()const + { + return new ossimEquDistCylProjection(*this); + } + + virtual ossimGpt inverse(const ossimDpt &eastingNorthing)const; + virtual ossimDpt forward(const ossimGpt &latLon)const; + virtual void update(); + + /*! + * SetFalseEasting. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEasting(double falseEasting); + + /*! + * SetFalseNorthing. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseNorthing(double falseNorthing); + + /*! + * Sets both false easting and northing values. The values are + * expected to be in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEastingNorthing(double falseEasting, double falseNorthing); + + double getFalseEasting()const{return Eqcy_False_Easting;} + double getFalseNorthing()const{return Eqcy_False_Northing;} + + virtual bool isGeographic()const + { + return true; + } + void setDefaults(); +// virtual void setMetersPerPixel(const ossimDpt& pt); + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + +private: + //---------------------GEOTRANS------------------------------- + mutable double Eqcy_a; /* Semi-major axis of ellipsoid in meters */ + mutable double Eqcy_f; /* Flattening of ellipsoid */ + mutable double es2; /* Eccentricity (0.08181919084262188000) squared */ + mutable double es4; /* es2 * es2 */ + mutable double es6; /* es4 * es2 */ + mutable double Ra; /* Spherical Radius */ + +/* Equidistant Cylindrical projection Parameters */ + mutable double Eqcy_Std_Parallel; /* Latitude of standard parallel in radians */ + mutable double Cos_Eqcy_Std_Parallel; /* cos(Eqcy_Std_Parallel) */ + mutable double Eqcy_Origin_Long; /* Longitude of origin in radians */ + mutable double Eqcy_False_Easting; + mutable double Eqcy_False_Northing; + mutable double Eqcy_Delta_Northing; + mutable double Eqcy_Max_Easting; + mutable double Eqcy_Min_Easting; + mutable double Ra_Cos_Eqcy_Std_Parallel; /* Ra * Cos_Eqcy_Std_Parallel */ + +/*! + * The function Set_Equidistant_Cyl_Parameters receives the ellipsoid parameters and + * projection parameters as inputs, and sets the corresponding state + * variables. It also calculates the spherical radius of the sphere having + * the same area as the ellipsoid. If any errors occur, the error code(s) + * are returned by the function, otherwise EQCY_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Std_Parallel : Latitude in radians at which the (input) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * standard parallel of the projection (input) + */ + long Set_Equidistant_Cyl_Parameters(double a, + double f, + double Std_Parallel, + double Central_Meridian, + double False_Easting, + double False_Northing); + + +/*! + * The function Get_Equidistant_Cyl_Parameters returns the current ellipsoid + * parameters and Equidistant Cylindrical projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Std_Parallel : Latitude in radians at which the (output) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * standard parallel of the projection (output) + */ + void Get_Equidistant_Cyl_Parameters(double *a, + double *f, + double *Std_Parallel, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const; + + +/*! + * The function Convert_Geodetic_To_Equidistant_Cyl converts geodetic (latitude and + * longitude) coordinates to Equidistant Cylindrical projection easting, and northing + * coordinates, according to the current ellipsoid and Equidistant Cylindrical projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise EQCY_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + long Convert_Geodetic_To_Equidistant_Cyl (double Latitude, + double Longitude, + double *Easting, + double *Northing)const; + + +/*! + * The function Convert_Equidistant_Cyl_To_Geodetic converts Equidistant Cylindrical projection + * easting and northing coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Equidistant Cylindrical projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise EQCY_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + long Convert_Equidistant_Cyl_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimGnomonicProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimGnomonicProjection.cpp new file mode 100644 index 0000000000..0ca8208579 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimGnomonicProjection.cpp @@ -0,0 +1,459 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimGnomonicProjection.cpp,v 1.5 2004/01/08 21:49:21 jlargent Exp $ +#include "ossimGnomonicProjection.h" +#include "base/common/ossimKeywordNames.h" + +RTTI_DEF1(ossimGnomonicProjection, "ossimGnomonicProjection", ossimMapProjection) + +#ifndef PI_OVER_2 +# define PI_OVER_2 ( M_PI / 2.0) +#endif +#ifndef TWO_PI +# define TWO_PI (2.0 * M_PI) +#endif + +#define GNOM_NO_ERROR 0x0000 +#define GNOM_LAT_ERROR 0x0001 +#define GNOM_LON_ERROR 0x0002 +#define GNOM_EASTING_ERROR 0x0004 +#define GNOM_NORTHING_ERROR 0x0008 +#define GNOM_ORIGIN_LAT_ERROR 0x0010 +#define GNOM_CENT_MER_ERROR 0x0020 +#define GNOM_A_ERROR 0x0040 +#define GNOM_INV_F_ERROR 0x0080 + +ossimGnomonicProjection::ossimGnomonicProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + :ossimMapProjection(ellipsoid, origin) +{ + setDefaults(); + update(); +} + +ossimGnomonicProjection::ossimGnomonicProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double falseEasting, + double falseNorthing) + :ossimMapProjection(ellipsoid, origin) +{ + Gnom_False_Easting = falseEasting; + Gnom_False_Northing = falseNorthing; + + update(); +} + +void ossimGnomonicProjection::update() +{ + Set_Gnomonic_Parameters(theEllipsoid.getA(), + theEllipsoid.getFlattening(), + theOrigin.latr(), + theOrigin.lonr(), + Gnom_False_Easting, + Gnom_False_Northing); + + ossimMapProjection::update(); +} + +void ossimGnomonicProjection::setFalseEasting(double falseEasting) +{ + Gnom_False_Easting = falseEasting; + + update(); +} + +void ossimGnomonicProjection::setFalseNorthing(double falseNorthing) +{ + Gnom_False_Northing = falseNorthing; + + update(); +} + +void ossimGnomonicProjection::setDefaults() +{ + Gnom_False_Easting = 0.0; + Gnom_False_Northing = 0.0; + Gnom_Delta_Northing = 40000000; + Gnom_Delta_Easting = 40000000; +} + +void ossimGnomonicProjection::setFalseEastingNorthing(double falseEasting, + double falseNorthing) +{ + Gnom_False_Easting = falseEasting; + Gnom_False_Northing = falseNorthing; + + update(); +} + +ossimGpt ossimGnomonicProjection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat = 0.0; + double lon = 0.0; + + Convert_Gnomonic_To_Geodetic(eastingNorthing.x, + eastingNorthing.y, + &lat, + &lon); + + return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum); +} + +ossimDpt ossimGnomonicProjection::forward(const ossimGpt &latLon)const +{ + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + Convert_Geodetic_To_Gnomonic(gpt.latr(), + gpt.lonr(), + &easting, + &northing); + + return ossimDpt(easting, northing); +} + +bool ossimGnomonicProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const +{ + kwl.add(prefix, + ossimKeywordNames::FALSE_EASTING_KW, + Gnom_False_Easting, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_NORTHING_KW, + Gnom_False_Northing, + true); + + return ossimMapProjection::saveState(kwl, prefix); +} + +bool ossimGnomonicProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + bool flag = ossimMapProjection::loadState(kwl, prefix); + const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + const char* falseEasting = kwl.find(prefix, ossimKeywordNames::FALSE_EASTING_KW); + const char* falseNorthing = kwl.find(prefix, ossimKeywordNames::FALSE_NORTHING_KW); + + setDefaults(); + if(ossimString(type) == STATIC_TYPE_NAME(ossimGnomonicProjection)) + { + if(falseEasting) + { + Gnom_False_Easting = ossimString(falseEasting).toDouble(); + } + if(falseNorthing) + { + Gnom_False_Northing = ossimString(falseNorthing).toDouble(); + } + } + + update(); + + return flag; + +} + +/***************************************************************************/ +/* + * FUNCTIONS + */ + +long ossimGnomonicProjection::Set_Gnomonic_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing) +{ /* BEGIN Set_Gnomonic_Parameters */ +/* + * The function Set_Gnomonic_Parameters receives the ellipsoid parameters and + * projection parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the function, + * otherwise GNOM_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at which the (input) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + + double es2, es4, es6; +// double inv_f = 1 / f; + long Error_Code = GNOM_NO_ERROR; + +// if (a <= 0.0) +// { /* Semi-major axis must be greater than zero */ +// Error_Code |= GNOM_A_ERROR; +// } +// if ((inv_f < 250) || (inv_f > 350)) +// { /* Inverse flattening must be between 250 and 350 */ +// Error_Code |= GNOM_INV_F_ERROR; +// } +// if ((Origin_Latitude < -PI_OVER_2) || (Origin_Latitude > PI_OVER_2)) +// { /* origin latitude out of range */ +// Error_Code |= GNOM_ORIGIN_LAT_ERROR; +// } +// if ((Central_Meridian < -PI) || (Central_Meridian > TWO_PI)) +// { /* origin longitude out of range */ +// Error_Code |= GNOM_CENT_MER_ERROR; +// } + if (!Error_Code) + { /* no errors */ + Gnom_a = a; + Gnom_f = f; + es2 = 2 * Gnom_f - Gnom_f * Gnom_f; + es4 = es2 * es2; + es6 = es4 * es2; + /* spherical radius */ + Ra = Gnom_a * (1.0 - es2 / 6.0 - 17.0 * es4 / 360.0 - 67.0 * es6 / 3024.0); + Gnom_Origin_Lat = Origin_Latitude; + Sin_Gnom_Origin_Lat = sin(Gnom_Origin_Lat); + Cos_Gnom_Origin_Lat = cos(Gnom_Origin_Lat); + abs_Gnom_Origin_Lat = fabs(Gnom_Origin_Lat); +// if (Central_Meridian > PI) +// Central_Meridian -= TWO_PI; + Gnom_Origin_Long = Central_Meridian; + Gnom_False_Northing = False_Northing; + Gnom_False_Easting = False_Easting; + } /* End if(!Error_Code) */ + return (Error_Code); +} /* End Set_Gnomonic_Parameters */ + + +void ossimGnomonicProjection::Get_Gnomonic_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const +{ /* Begin Get_Gnomonic_Parameters */ +/* + * The function Get_Gnomonic_Parameters returns the current ellipsoid + * parameters and Gnomonic projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at which the (output) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + + *a = Gnom_a; + *f = Gnom_f; + *Origin_Latitude = Gnom_Origin_Lat; + *Central_Meridian = Gnom_Origin_Long; + *False_Easting = Gnom_False_Easting; + *False_Northing = Gnom_False_Northing; + + return; +} /* End Get_Gnomonic_Parameters */ + + +long ossimGnomonicProjection::Convert_Geodetic_To_Gnomonic (double Latitude, + double Longitude, + double *Easting, + double *Northing)const +{ /* Begin Convert_Geodetic_To_Gnomonic */ +/* + * The function Convert_Geodetic_To_Gnomonic converts geodetic (latitude and + * longitude) coordinates to Gnomonic projection (easting and northing) + * coordinates, according to the current ellipsoid and Gnomonic projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise GNOM_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + + double dlam; /* Longitude - Central Meridan */ + double cos_c; + double k_prime; /* scale factor */ + double Ra_kprime; + double slat = sin(Latitude); + double clat = cos(Latitude); + double Ra_cotlat; + double sin_dlam, cos_dlam; + double temp_Easting, temp_Northing; + long Error_Code = GNOM_NO_ERROR; + +// if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2)) +// { /* Latitude out of range */ +// Error_Code |= GNOM_LAT_ERROR; +// } +// if ((Longitude < -PI) || (Longitude > TWO_PI)) +// { /* Longitude out of range */ +// Error_Code |= GNOM_LON_ERROR; +// } + dlam = Longitude - Gnom_Origin_Long; + sin_dlam = sin(dlam); + cos_dlam = cos(dlam); + cos_c = Sin_Gnom_Origin_Lat * slat + Cos_Gnom_Origin_Lat * clat * cos_dlam; + if (cos_c <= 1.0e-10) + { /* Point is out of view. Will return longitude out of range message + since no point out of view is implemented. */ + Error_Code |= GNOM_LON_ERROR; + } + if (!Error_Code) + { /* no errors */ +// if (dlam > PI) +// { +// dlam -= TWO_PI; +// } +// if (dlam < -PI) +// { +// dlam += TWO_PI; +// } + if (fabs(abs_Gnom_Origin_Lat - PI_OVER_2) < 1.0e-10) + { + Ra_cotlat = Ra * (clat / slat); + temp_Easting = Ra_cotlat * sin_dlam; + temp_Northing = Ra_cotlat * cos_dlam; + if (Gnom_Origin_Lat >= 0.0) + { + *Easting = temp_Easting + Gnom_False_Easting; + *Northing = -1.0 * temp_Northing + Gnom_False_Northing; + } + else + { + *Easting = -1.0 * temp_Easting + Gnom_False_Easting; + *Northing = temp_Northing + Gnom_False_Northing; + } + } + else if (abs_Gnom_Origin_Lat <= 1.0e-10) + { + *Easting = Ra * tan(dlam) + Gnom_False_Easting; + *Northing = Ra * tan(Latitude) / cos_dlam + Gnom_False_Northing; + } + else + { + k_prime = 1 / cos_c; + Ra_kprime = Ra * k_prime; + *Easting = Ra_kprime * clat * sin_dlam + Gnom_False_Easting; + *Northing = Ra_kprime * (Cos_Gnom_Origin_Lat * slat - Sin_Gnom_Origin_Lat * clat * cos_dlam) + Gnom_False_Northing; + } + } + return (Error_Code); +} /* End Convert_Geodetic_To_Gnomonic */ + + +long ossimGnomonicProjection::Convert_Gnomonic_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const +{ /* Begin Convert_Gnomonic_To_Geodetic */ +/* + * The function Convert_Gnomonic_To_Geodetic converts Gnomonic projection + * (easting and northing) coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Gnomonic projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise GNOM_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + + double dx, dy; + double rho; + double c; + double sin_c, cos_c; + double dy_sinc; + long Error_Code = GNOM_NO_ERROR; + +// if ((Easting < (Gnom_False_Easting - Gnom_Delta_Easting)) +// || (Easting > (Gnom_False_Easting + Gnom_Delta_Easting))) +// { /* Easting out of range */ +// Error_Code |= GNOM_EASTING_ERROR; +// } +// if ((Northing < (Gnom_False_Northing - Gnom_Delta_Northing)) +// || (Northing > (Gnom_False_Northing + Gnom_Delta_Northing))) +// { /* Northing out of range */ +// Error_Code |= GNOM_NORTHING_ERROR; +// } + if (!Error_Code) + { + dy = Northing - Gnom_False_Northing; + dx = Easting - Gnom_False_Easting; + rho = sqrt(dx * dx + dy * dy); + if (fabs(rho) <= 1.0e-10) + { + *Latitude = Gnom_Origin_Lat; + *Longitude = Gnom_Origin_Long; + } + else + { + c = atan(rho / Ra); + sin_c = sin(c); + cos_c = cos(c); + dy_sinc = dy * sin_c; + *Latitude = asin((cos_c * Sin_Gnom_Origin_Lat) + ((dy_sinc * Cos_Gnom_Origin_Lat) / rho)); + if (fabs(abs_Gnom_Origin_Lat - PI_OVER_2) < 1.0e-10) + { + if (Gnom_Origin_Lat >= 0.0) + *Longitude = Gnom_Origin_Long + atan2(dx, -dy); + else + *Longitude = Gnom_Origin_Long + atan2(dx, dy); + } + else + *Longitude = Gnom_Origin_Long + atan2((dx * sin_c), (rho * Cos_Gnom_Origin_Lat * cos_c - dy_sinc * Sin_Gnom_Origin_Lat)); + } +// if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */ +// *Latitude = PI_OVER_2; +// else if (*Latitude < -PI_OVER_2) +// *Latitude = -PI_OVER_2; +// if (*Longitude > PI) +// *Longitude -= TWO_PI; +// if (*Longitude < -PI) +// *Longitude += TWO_PI; +// if (*Longitude > PI) /* force distorted values to 180, -180 degrees */ +// *Longitude = PI; +// else if (*Longitude < -PI) +// *Longitude = -PI; + } + return (Error_Code); +} /* End Convert_Gnomonic_To_Geodetic */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimGnomonicProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimGnomonicProjection.h new file mode 100644 index 0000000000..40c4188e92 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimGnomonicProjection.h @@ -0,0 +1,193 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimGnomonicProjection.h,v 1.2 2005/09/09 19:23:58 gpotts Exp $ +#ifndef ossimGnomonicProjection_HEADER +#define ossimGnomonicProjection_HEADER + +#include "ossimMapProjection.h" + +class ossimGnomonicProjection : public ossimMapProjection +{ +public: + ossimGnomonicProjection(const ossimEllipsoid& ellipsoid = ossimEllipsoid(), + const ossimGpt& origin = ossimGpt()); + ossimGnomonicProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + const double falseEasting, + const double falseNorthing); + ~ossimGnomonicProjection(){} + virtual ossimObject *dup()const + { + return new ossimGnomonicProjection(*this); + } + + virtual ossimGpt inverse(const ossimDpt &eastingNorthing)const; + virtual ossimDpt forward(const ossimGpt &latLon)const; + virtual void update(); + + + /*! + * SetFalseEasting. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEasting(double falseEasting); + + /*! + * SetFalseNorthing. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseNorthing(double falseNorthing); + + /*! + * Sets both false easting and northing values. The values are + * expected to be in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEastingNorthing(double falseEasting, double falseNorthing); + + void setDefaults(); + + double getFalseEasting()const{return Gnom_False_Easting;} + double getFalseNorthing()const{return Gnom_False_Northing;} + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +protected: + + //__________________________GEOTRANS________________________ + mutable double Gnom_a; /* Semi-major axis of ellipsoid in meters */ + mutable double Gnom_f; /* Flattening of ellipsoid */ + mutable double Ra; /* Spherical Radius */ + mutable double Sin_Gnom_Origin_Lat; + mutable double Cos_Gnom_Origin_Lat; + +/* Gnomonic projection Parameters */ + mutable double Gnom_Origin_Lat; /* Latitude of origin in radians */ + mutable double Gnom_Origin_Long; /* Longitude of origin in radians */ + mutable double Gnom_False_Northing; /* False northing in meters */ + mutable double Gnom_False_Easting; /* False easting in meters */ + mutable double abs_Gnom_Origin_Lat; + + mutable double Gnom_Delta_Northing; + mutable double Gnom_Delta_Easting; + +/* + * The function Set_Gnomonic_Parameters receives the ellipsoid parameters and + * projection parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the function, + * otherwise GNOM_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at which the (input) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + long Set_Gnomonic_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing); + +/*! + * The function Get_Gnomonic_Parameters returns the current ellipsoid + * parameters and Gnomonic projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at which the (output) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + void Get_Gnomonic_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const; + + +/*! + * The function Convert_Geodetic_To_Gnomonic converts geodetic (latitude and + * longitude) coordinates to Gnomonic projection (easting and northing) + * coordinates, according to the current ellipsoid and Gnomonic projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise GNOM_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + long Convert_Geodetic_To_Gnomonic (double Latitude, + double Longitude, + double *Easting, + double *Northing)const; + + +/*! + * The function Convert_Gnomonic_To_Geodetic converts Gnomonic projection + * (easting and northing) coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Gnomonic projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise GNOM_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + long Convert_Gnomonic_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const; + + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimLambertConformalConicProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimLambertConformalConicProjection.cpp new file mode 100644 index 0000000000..d3a29e0e30 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimLambertConformalConicProjection.cpp @@ -0,0 +1,647 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Lamberts Conformal Conic projection code. +//******************************************************************* +// $Id: ossimLambertConformalConicProjection.cpp,v 1.14 2005/09/09 19:23:58 gpotts Exp $ + +#include "ossimLambertConformalConicProjection.h" +#include "base/common/ossimKeywordNames.h" + +RTTI_DEF1(ossimLambertConformalConicProjection, "ossimLambertConformalConicProjection", ossimMapProjection) + +/***************************************************************************/ +/* DEFINES + * + */ +#ifndef PI_OVER_2 +# define PI_OVER_2 ( M_PI / 2.0) +#endif +#ifndef TWO_PI +# define TWO_PI (2.0 * M_PI) +#endif +#define MAX_LAT (( M_PI * 89.99972222222222) / 180.0) /* 89 59 59.0 degrees in radians */ +#define LAMBERT_m(clat,essin) (clat / sqrt(1.0 - essin * essin)) +#define LAMBERT_t(lat,essin) tan(PI_OVER_4 - lat / 2) / \ + pow((1.0 - essin) / (1.0 + essin), es_OVER_2) +#define ES_SIN(sinlat) (es * sinlat) +/**************************************************************************/ +/* GLOBAL DECLARATIONS + * + */ + +const double PI_OVER_4 = (M_PI / 4.0); + +#define LAMBERT_NO_ERROR 0x0000 +#define LAMBERT_LAT_ERROR 0x0001 +#define LAMBERT_LON_ERROR 0x0002 +#define LAMBERT_EASTING_ERROR 0x0004 +#define LAMBERT_NORTHING_ERROR 0x0008 +#define LAMBERT_FIRST_STDP_ERROR 0x0010 +#define LAMBERT_SECOND_STDP_ERROR 0x0020 +#define LAMBERT_ORIGIN_LAT_ERROR 0x0040 +#define LAMBERT_CENT_MER_ERROR 0x0080 +#define LAMBERT_A_ERROR 0x0100 +#define LAMBERT_B_ERROR 0x0200 +#define LAMBERT_A_LESS_B_ERROR 0x0400 +#define LAMBERT_HEMISPHERE_ERROR 0x0800 +#define LAMBERT_FIRST_SECOND_ERROR 0x1000 + +ossimLambertConformalConicProjection::ossimLambertConformalConicProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + :ossimMapProjection(ellipsoid, origin) +{ + setDefaults(); + update(); +} + +ossimLambertConformalConicProjection::ossimLambertConformalConicProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double stdParallel1, + double stdParallel2, + double falseEasting, + double falseNorthing) + :ossimMapProjection(ellipsoid, origin) +{ + Lambert_Std_Parallel_1 = stdParallel1; + Lambert_Std_Parallel_2 = stdParallel2; + Lambert_False_Easting = falseEasting; + Lambert_False_Northing = falseNorthing; + + update(); +} + +ossimLambertConformalConicProjection::~ossimLambertConformalConicProjection() +{ +} + +ossimObject* ossimLambertConformalConicProjection::dup()const +{ + return new ossimLambertConformalConicProjection(*this); +} + +void ossimLambertConformalConicProjection::update() +{ + Set_Lambert_Parameters(theEllipsoid.getA(), + theEllipsoid.getFlattening(), + theOrigin.latr(), + theOrigin.lonr(), + Lambert_Std_Parallel_1, + Lambert_Std_Parallel_2, + Lambert_False_Easting, + Lambert_False_Northing); + + ossimMapProjection::update(); +} + +void ossimLambertConformalConicProjection::setStandardParallel1(double degree) +{ + Lambert_Std_Parallel_1 = degree*RAD_PER_DEG; + update(); +} + +void ossimLambertConformalConicProjection::setStandardParallel2(double degree) +{ + Lambert_Std_Parallel_2 = degree*RAD_PER_DEG; + update(); +} + +void ossimLambertConformalConicProjection::setStandardParallels(double parallel1Degree, + double parallel2Degree) +{ + Lambert_Std_Parallel_1 = parallel1Degree*RAD_PER_DEG; + Lambert_Std_Parallel_2 = parallel2Degree*RAD_PER_DEG; + update(); + +} + +void ossimLambertConformalConicProjection::setFalseEasting(double falseEasting) +{ + Lambert_False_Easting = falseEasting; + update(); +} + +void ossimLambertConformalConicProjection::setFalseNorthing(double falseNorthing) +{ + Lambert_False_Northing = falseNorthing; + update(); +} + +void ossimLambertConformalConicProjection::setFalseEastingNorthing(double falseEasting, + double falseNorthing) +{ + Lambert_False_Easting = falseEasting; + Lambert_False_Northing = falseNorthing; + update(); +} + +void ossimLambertConformalConicProjection::setParameters(double parallel1, + double parallel2, + double falseEasting, + double falseNorthing) +{ + Lambert_False_Easting = falseEasting; + Lambert_False_Northing = falseNorthing; + Lambert_Std_Parallel_1 = parallel1*RAD_PER_DEG; + Lambert_Std_Parallel_2 = parallel2*RAD_PER_DEG; + update(); +} + + +void ossimLambertConformalConicProjection::setDefaults() +{ + Lambert_Std_Parallel_1 = 40*RAD_PER_DEG; + Lambert_Std_Parallel_2 = 50*RAD_PER_DEG; + Lambert_False_Northing = 0.0; + Lambert_False_Easting = 0.0; +} + +ossimGpt ossimLambertConformalConicProjection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat = 0.0; + double lon = 0.0; + + Convert_Lambert_To_Geodetic(eastingNorthing.x, + eastingNorthing.y, + &lat, + &lon); + + return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum); +} + +ossimDpt ossimLambertConformalConicProjection::forward(const ossimGpt &latLon)const +{ + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + Convert_Geodetic_To_Lambert(gpt.latr(), + gpt.lonr(), + &easting, + &northing); + + return ossimDpt(easting, northing); +} + +bool ossimLambertConformalConicProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const +{ + kwl.add(prefix, + ossimKeywordNames::STD_PARALLEL_1_KW, + Lambert_Std_Parallel_1*DEG_PER_RAD, + true); + + kwl.add(prefix, + ossimKeywordNames::STD_PARALLEL_2_KW, + Lambert_Std_Parallel_2*DEG_PER_RAD, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_EASTING_KW, + Lambert_False_Easting, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_NORTHING_KW, + Lambert_False_Northing, + true); + + return ossimMapProjection::saveState(kwl, prefix); +} + +bool ossimLambertConformalConicProjection::loadState(const ossimKeywordlist& kwl, const char* prefix) +{ + bool flag = ossimMapProjection::loadState(kwl, prefix); + + const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + const char* falseEasting = kwl.find(prefix, ossimKeywordNames::FALSE_EASTING_KW); + const char* falseNorthing = kwl.find(prefix, ossimKeywordNames::FALSE_NORTHING_KW); + const char* stdParallel1 = kwl.find(prefix, ossimKeywordNames::STD_PARALLEL_1_KW); + const char* stdParallel2 = kwl.find(prefix, ossimKeywordNames::STD_PARALLEL_2_KW); + + setDefaults(); + + if(ossimString(type) == STATIC_TYPE_NAME(ossimLambertConformalConicProjection)) + { + if(falseEasting) + { + Lambert_False_Easting = ossimString(falseEasting).toDouble(); + } + if(falseNorthing) + { + Lambert_False_Northing = ossimString(falseNorthing).toDouble(); + } + if(stdParallel1) + { + Lambert_Std_Parallel_1 = ossimString(stdParallel1).toDouble()*RAD_PER_DEG; + } + if(stdParallel2) + { + Lambert_Std_Parallel_2 = ossimString(stdParallel2).toDouble()*RAD_PER_DEG; + } + } + update(); + return flag; +} + +/************************************************************************/ +/* FUNCTIONS + * + */ + +long ossimLambertConformalConicProjection::Set_Lambert_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double Std_Parallel_1, + double Std_Parallel_2, + double False_Easting, + double False_Northing) + +{ /* BEGIN Set_Lambert_Parameters */ +/* + * The function Set_Lambert_Parameters receives the ellipsoid parameters and + * Lambert Conformal Conic projection parameters as inputs, and sets the + * corresponding state variables. If any errors occur, the error code(s) + * are returned by the function, otherwise LAMBERT_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude of origin, in radians (input) + * Central_Meridian : Longitude of origin, in radians (input) + * Std_Parallel_1 : First standard parallel, in radians (input) + * Std_Parallel_2 : Second standard parallel, in radians (input) + * False_Easting : False easting, in meters (input) + * False_Northing : False northing, in meters (input) + */ + + double slat, slat1, clat; + double es_sin; + double t0, t1, t2; + double m1, m2; +// double inv_f = 1 / f; + long Error_Code = LAMBERT_NO_ERROR; + +// if (a <= 0.0) +// { /* Semi-major axis must be greater than zero */ +// Error_Code |= LAMBERT_A_ERROR; +// } +// if ((inv_f < 250) || (inv_f > 350)) +// { /* Inverse flattening must be between 250 and 350 */ +// Error_Code |= LAMBERT_INV_F_ERROR; +// } +// if ((Origin_Latitude < -MAX_LAT) || (Origin_Latitude > MAX_LAT)) +// { /* Origin Latitude out of range */ +// Error_Code |= LAMBERT_ORIGIN_LAT_ERROR; +// } +// if ((Std_Parallel_1 < -MAX_LAT) || (Std_Parallel_1 > MAX_LAT)) +// { /* First Standard Parallel out of range */ +// Error_Code |= LAMBERT_FIRST_STDP_ERROR; +// } +// if ((Std_Parallel_2 < -MAX_LAT) || (Std_Parallel_2 > MAX_LAT)) +// { /* Second Standard Parallel out of range */ +// Error_Code |= LAMBERT_SECOND_STDP_ERROR; +// } +// if ((Std_Parallel_1 == 0) && (Std_Parallel_2 == 0)) +// { /* First & Second Standard Parallels are both 0 */ +// Error_Code |= LAMBERT_FIRST_SECOND_ERROR; +// } +// if (Std_Parallel_1 == -Std_Parallel_2) +// { /* Parallels are the negation of each other */ +// Error_Code |= LAMBERT_HEMISPHERE_ERROR; +// } +// if ((Central_Meridian < -PI) || (Central_Meridian > TWO_PI)) +// { /* Origin Longitude out of range */ +// Error_Code |= LAMBERT_CENT_MER_ERROR; +// } + + if (!Error_Code) + { /* no errors */ + + Lambert_a = a; + Lambert_f = f; + Lambert_Origin_Lat = Origin_Latitude; + Lambert_Std_Parallel_1 = Std_Parallel_1; + Lambert_Std_Parallel_2 = Std_Parallel_2; +// if (Central_Meridian > PI) +// Central_Meridian -= TWO_PI; + Lambert_Origin_Long = Central_Meridian; + Lambert_False_Easting = False_Easting; + Lambert_False_Northing = False_Northing; + + es2 = 2 * Lambert_f - Lambert_f * Lambert_f; + es = sqrt(es2); + es_OVER_2 = es / 2.0; + + slat = sin(Lambert_Origin_Lat); + es_sin = ES_SIN(slat); + t0 = LAMBERT_t(Lambert_Origin_Lat, es_sin); + + slat1 = sin(Lambert_Std_Parallel_1); + clat = cos(Lambert_Std_Parallel_1); + es_sin = ES_SIN(slat1); + m1 = LAMBERT_m(clat, es_sin); + t1 = LAMBERT_t(Lambert_Std_Parallel_1, es_sin); + + + if (fabs(Lambert_Std_Parallel_1 - Lambert_Std_Parallel_2) > 1.0e-10) + { + slat = sin(Lambert_Std_Parallel_2); + clat = cos(Lambert_Std_Parallel_2); + es_sin = ES_SIN(slat); + m2 = LAMBERT_m(clat, es_sin); + t2 = LAMBERT_t(Lambert_Std_Parallel_2, es_sin); + n = log(m1 / m2) / log(t1 / t2); + } + else + n = slat1; + F = m1 / (n * pow(t1, n)); + Lambert_aF = Lambert_a * F; + if ((t0 == 0) && (n < 0)) + rho0 = 0.0; + else + rho0 = Lambert_aF * pow(t0, n); + + } + return (Error_Code); +} /* END OF Set_Lambert_Parameters */ + + +void ossimLambertConformalConicProjection::Get_Lambert_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *Std_Parallel_1, + double *Std_Parallel_2, + double *False_Easting, + double *False_Northing)const + +{ /* BEGIN Get_Lambert_Parameters */ +/* + * The function Get_Lambert_Parameters returns the current ellipsoid + * parameters and Lambert Conformal Conic projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude of origin, in radians (output) + * Central_Meridian : Longitude of origin, in radians (output) + * Std_Parallel_1 : First standard parallel, in radians (output) + * Std_Parallel_2 : Second standard parallel, in radians (output) + * False_Easting : False easting, in meters (output) + * False_Northing : False northing, in meters (output) + */ + + + *a = Lambert_a; + *f = Lambert_f; + *Std_Parallel_1 = Lambert_Std_Parallel_1; + *Std_Parallel_2 = Lambert_Std_Parallel_2; + *Origin_Latitude = Lambert_Origin_Lat; + *Central_Meridian = Lambert_Origin_Long; + *False_Easting = Lambert_False_Easting; + *False_Northing = Lambert_False_Northing; + + return; +} /* END OF Get_Lambert_Parameters */ + + +long ossimLambertConformalConicProjection::Convert_Geodetic_To_Lambert (double Latitude, + double Longitude, + double *Easting, + double *Northing)const + +{ /* BEGIN Convert_Geodetic_To_Lambert */ +/* + * The function Convert_Geodetic_To_Lambert converts Geodetic (latitude and + * longitude) coordinates to Lambert Conformal Conic projection (easting + * and northing) coordinates, according to the current ellipsoid and + * Lambert Conformal Conic projection parameters. If any errors occur, the + * error code(s) are returned by the function, otherwise LAMBERT_NO_ERROR is + * returned. + * + * Latitude : Latitude, in radians (input) + * Longitude : Longitude, in radians (input) + * Easting : Easting (X), in meters (output) + * Northing : Northing (Y), in meters (output) + */ + + double slat; + double es_sin; + double t; + double rho; + double dlam; + double theta; + long Error_Code = LAMBERT_NO_ERROR; + +// if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2)) +// { /* Latitude out of range */ +// Error_Code|= LAMBERT_LAT_ERROR; +// } +// if ((Longitude < -PI) || (Longitude > TWO_PI)) +// { /* Longitude out of range */ +// Error_Code|= LAMBERT_LON_ERROR; +// } + + if (!Error_Code) + { /* no errors */ + + if (fabs(fabs(Latitude) - PI_OVER_2) > 1.0e-10) + { + slat = sin(Latitude); + es_sin = ES_SIN(slat); + t = LAMBERT_t(Latitude, es_sin); + rho = Lambert_aF * pow(t, n); + } + else + { + if ((Latitude * n) <= 0) + { /* Point can not be projected */ + Error_Code |= LAMBERT_LAT_ERROR; + return (Error_Code); + } + rho = 0.0; + } + + dlam = Longitude - Lambert_Origin_Long; + +// if (dlam > PI) +// { +// dlam -= TWO_PI; +// } +// if (dlam < -PI) +// { +// dlam += TWO_PI; +// } + + theta = n * dlam; + + *Easting = rho * sin(theta) + Lambert_False_Easting; + *Northing = rho0 - rho * cos(theta) + Lambert_False_Northing; + + } + return (Error_Code); +} /* END OF Convert_Geodetic_To_Lambert */ + + + +long ossimLambertConformalConicProjection::Convert_Lambert_To_Geodetic (double Easting, + double Northing, + double *Latitude, + double *Longitude)const + +{ /* BEGIN Convert_Lambert_To_Geodetic */ +/* + * The function Convert_Lambert_To_Geodetic converts Lambert Conformal + * Conic projection (easting and northing) coordinates to Geodetic + * (latitude and longitude) coordinates, according to the current ellipsoid + * and Lambert Conformal Conic projection parameters. If any errors occur, + * the error code(s) are returned by the function, otherwise LAMBERT_NO_ERROR + * is returned. + * + * Easting : Easting (X), in meters (input) + * Northing : Northing (Y), in meters (input) + * Latitude : Latitude, in radians (output) + * Longitude : Longitude, in radians (output) + */ + + + double dy, dx; + double rho, rho0_MINUS_dy; + double t; + double PHI; + double tempPHI = 0.0; + double sin_PHI; + double es_sin; + double theta = 0.0; + double tolerance = 4.85e-10; + long Error_Code = LAMBERT_NO_ERROR; + +// if ((Easting < (Lambert_False_Easting - Lambert_Delta_Easting)) +// ||(Easting > (Lambert_False_Easting + Lambert_Delta_Easting))) +// { /* Easting out of range */ +// Error_Code |= LAMBERT_EASTING_ERROR; +// } +// if ((Northing < (Lambert_False_Northing - Lambert_Delta_Northing)) +// || (Northing > (Lambert_False_Northing + Lambert_Delta_Northing))) +// { /* Northing out of range */ +// Error_Code |= LAMBERT_NORTHING_ERROR; +// } + + if (!Error_Code) + { /* no errors */ + + dy = Northing - Lambert_False_Northing; + dx = Easting - Lambert_False_Easting; + rho0_MINUS_dy = rho0 - dy; + rho = sqrt(dx * dx + (rho0_MINUS_dy) * (rho0_MINUS_dy)); + + if (n < 0.0) + { + rho *= -1.0; + dy *= -1.0; + dx *= -1.0; + rho0_MINUS_dy *= -1.0; + } + + if (rho != 0.0) + { + theta = atan2(dx, rho0_MINUS_dy); + t = pow(rho / (Lambert_aF) , 1.0 / n); + PHI = PI_OVER_2 - 2.0 * atan(t); + while (fabs(PHI - tempPHI) > tolerance) + { + tempPHI = PHI; + sin_PHI = sin(PHI); + es_sin = ES_SIN(sin_PHI); + PHI = PI_OVER_2 - 2.0 * atan(t * pow((1.0 - es_sin) / (1.0 + es_sin), es_OVER_2)); + } + *Latitude = PHI; + *Longitude = theta / n + Lambert_Origin_Long; + + if (fabs(*Latitude) < 2.0e-7) /* force lat to 0 to avoid -0 degrees */ + *Latitude = 0.0; + if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */ + *Latitude = PI_OVER_2; + else if (*Latitude < -PI_OVER_2) + *Latitude = -PI_OVER_2; + + if (*Longitude > M_PI) + { + if (*Longitude - M_PI < 3.5e-6) + *Longitude = M_PI; +// else +// *Longitude -= TWO_PI; + } + if (*Longitude < -M_PI) + { + if (fabs(*Longitude + M_PI) < 3.5e-6) + *Longitude = -M_PI; +// else +// *Longitude += TWO_PI; + } + + if (fabs(*Longitude) < 2.0e-7) /* force lon to 0 to avoid -0 degrees */ + *Longitude = 0.0; + if (*Longitude > M_PI) /* force distorted values to 180, -180 degrees */ + *Longitude = M_PI; + else if (*Longitude < -M_PI) + *Longitude = -M_PI; + } + else + { + if (n > 0.0) + *Latitude = PI_OVER_2; + else + *Latitude = -PI_OVER_2; + *Longitude = Lambert_Origin_Long; + } + } + return (Error_Code); +} /* END OF Convert_Lambert_To_Geodetic */ + +double ossimLambertConformalConicProjection::getStandardParallel1()const +{ + return Lambert_Std_Parallel_1; +} + +double ossimLambertConformalConicProjection::getStandardParallel2()const +{ + return Lambert_Std_Parallel_2; +} + +double ossimLambertConformalConicProjection::getFalseEasting()const +{ + return Lambert_False_Easting; +} + +double ossimLambertConformalConicProjection::getFalseNorthing()const +{ + return Lambert_False_Northing; +} + diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimLambertConformalConicProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimLambertConformalConicProjection.h new file mode 100644 index 0000000000..89d864def8 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimLambertConformalConicProjection.h @@ -0,0 +1,230 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Lamberts Conformal Conic projection code. +//******************************************************************* +// $Id: ossimLambertConformalConicProjection.h,v 1.6 2005/09/09 19:23:58 gpotts Exp $ + +#ifndef ossimLambertConformalConicProjection_HEADER +#define ossimLambertConformalConicProjection_HEADER +#include "ossimMapProjection.h" + +class ossimLambertConformalConicProjection : public ossimMapProjection +{ +public: + ossimLambertConformalConicProjection(const ossimEllipsoid& ellipsoid = ossimEllipsoid(), + const ossimGpt& origin = ossimGpt()); + + ossimLambertConformalConicProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double stdParallel1, + double stdParallel2, + double falseEasting, + double falseNorthing); + + virtual ~ossimLambertConformalConicProjection(); + + virtual ossimObject *dup()const; + + virtual ossimGpt inverse(const ossimDpt &eastingNorthing)const; + virtual ossimDpt forward(const ossimGpt &latLon)const; + virtual void update(); + + /*! + * The passed in Argument is in degrees and will convert it to radians + * for Geotrans. Update is then called so we can pre-compute paramters. + */ + void setStandardParallel1(double degree); + + /*! + * The passed in Argument is in degrees and will convert it to radians + * for Geotrans. Update is then called so we can pre-compute paramters + */ + void setStandardParallel2(double degree); + + /*! + * Will allow you to set both parallels. both are passed in degrees. + */ + void setStandardParallels(double parallel1Degree, + double prallel2Degree); + + /*! + * SetFalseEasting. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEasting(double falseEasting); + + /*! + * SetFalseNorthing. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseNorthing(double falseNorthing); + + /*! + * Sets both false easting and northing values. The values are + * expected to be in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEastingNorthing(double falseEasting, double falseNorthing); + + /*! + * Allows one to set all parameters for this projections. parallels are in + * degrees and easting northings are in meters. + * Update is then called so we can pre-compute paramters. + */ + void setParameters(double parallel1, + double parallel2, + double falseEasting, + double falseNorthing); + + virtual double getStandardParallel1() const; + virtual double getStandardParallel2() const; + virtual double getFalseEasting() const; + virtual double getFalseNorthing() const; + + void setDefaults(); + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +private: + + //_______________GEOTRANS____________________ + mutable double Lambert_a; /* Semi-major axis of ellipsoid, in meters */ + mutable double Lambert_f; /* Flattening of ellipsoid */ + mutable double es; /* Eccentricity of ellipsoid */ + mutable double es2; /* Eccentricity squared */ + mutable double es_OVER_2; /* Eccentricity / 2.0 */ + mutable double n; /* Ratio of angle between meridians */ + mutable double F; /* Flattening of ellipsoid */ + mutable double rho0; /* Height above ellipsoid */ + mutable double Lambert_aF; /* Lambert_a * F */ + +/* Lambert_Conformal_Conic projection Parameters */ + mutable double Lambert_Std_Parallel_1; /* Lower std. parallel, in radians */ + mutable double Lambert_Std_Parallel_2; /* Upper std. parallel, in radians */ + mutable double Lambert_Origin_Lat; /* Latitude of origin, in radians */ + mutable double Lambert_Origin_Long; /* Longitude of origin, in radians */ + mutable double Lambert_False_Northing; /* False northing, in meters */ + mutable double Lambert_False_Easting; /* False easting, in meters */ + +/*! + * The function Set_Lambert_Parameters receives the ellipsoid parameters and + * Lambert Conformal Conic projection parameters as inputs, and sets the + * corresponding state variables. If any errors occur, the error code(s) + * are returned by the function, otherwise LAMBERT_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude of origin in radians (input) + * Central_Meridian : Longitude of origin in radians (input) + * Std_Parallel_1 : First standard parallel (input) + * Std_Parallel_2 : Second standard parallel (input) + * False_Easting : False easting in meters (input) + * False_Northing : False northing in meters (input) + */ + long Set_Lambert_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double Std_Parallel_1, + double Std_Parallel_2, + double False_Easting, + double False_Northing); + + + + +/*! + * The function Get_Lambert_Parameters returns the current ellipsoid + * parameters and Lambert Conformal Conic projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude of origin, in radians (output) + * Central_Meridian : Longitude of origin, in radians (output) + * Std_Parallel_1 : First standard parallel (output) + * Std_Parallel_2 : Second standard parallel (output) + * False_Easting : False easting, in meters (output) + * False_Northing : False northing, in meters (output) + */ + void Get_Lambert_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *Std_Parallel_1, + double *Std_Parallel_2, + double *False_Easting, + double *False_Northing)const; + +/*! + * The function Convert_Geodetic_To_Lambert converts Geodetic (latitude and + * longitude) coordinates to Lambert Conformal Conic projection (easting + * and northing) coordinates, according to the current ellipsoid and + * Lambert Conformal Conic projection parameters. If any errors occur, the + * error code(s) are returned by the function, otherwise LAMBERT_NO_ERROR is + * returned. + * + * Latitude : Latitude in radians (input) + * Longitude : Longitude in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + long Convert_Geodetic_To_Lambert (double Latitude, + double Longitude, + double *Easting, + double *Northing)const; + +/*! + * The function Convert_Lambert_To_Geodetic converts Lambert Conformal + * Conic projection (easting and northing) coordinates to Geodetic + * (latitude and longitude) coordinates, according to the current ellipsoid + * and Lambert Conformal Conic projection parameters. If any errors occur, + * the error code(s) are returned by the function, otherwise LAMBERT_NO_ERROR + * is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude in radians (output) + * Longitude : Longitude in radians (output) + */ + long Convert_Lambert_To_Geodetic (double Easting, + double Northing, + double *Latitude, + double *Longitude)const; + + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimLlxyProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimLlxyProjection.cpp new file mode 100644 index 0000000000..ae60abf0af --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimLlxyProjection.cpp @@ -0,0 +1,323 @@ +//******************************************************************* +// Copyright (C) 2002 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class definition for ossimLlxy. This is a simple "latitude / +// longitude to x / y" projection. +// +//******************************************************************* +// $Id: ossimLlxyProjection.cpp,v 1.24 2005/09/09 19:23:58 gpotts Exp $ + +#include <projections/map_projections/ossimLlxyProjection.h> +#include <elevation/ossimElevManager.h> +#include <base/common/ossimKeywordNames.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/datum/ossimDatum.h> + +// RTTI information for the ossimMapProjection +RTTI_DEF1(ossimLlxyProjection, "ossimLlxyProjection" , ossimMapProjection); + +ossimLlxyProjection::ossimLlxyProjection() +{ + theDeltaLatPerPixel = 1.0; + theDeltaLonPerPixel = 1.0; + theUlEastingNorthing.y = OSSIM_DBL_NAN; + theUlEastingNorthing.x = OSSIM_DBL_NAN; + computeMetersPerPixel(theOrigin, + theDeltaLatPerPixel, + theDeltaLonPerPixel, + theMetersPerPixel); +} + +ossimLlxyProjection::ossimLlxyProjection(const ossimLlxyProjection& rhs) + : + ossimMapProjection(rhs) +{ + theOrigin = rhs.theOrigin; + theUlGpt = rhs.theUlGpt; + theUlEastingNorthing.y = OSSIM_DBL_NAN; + theUlEastingNorthing.x = OSSIM_DBL_NAN; + theDatum = theOrigin.datum(); + theEllipsoid = *(theDatum->ellipsoid()); + theDeltaLatPerPixel = rhs.theDeltaLatPerPixel; + theDeltaLonPerPixel = rhs.theDeltaLonPerPixel; + computeMetersPerPixel(theOrigin, + theDeltaLatPerPixel, + theDeltaLonPerPixel, + theMetersPerPixel); +} + +ossimLlxyProjection::ossimLlxyProjection(const ossimGpt& origin, + double latSpacing, + double lonSpacing) + : + ossimMapProjection() +{ + theOrigin = origin; + theUlGpt = origin; + theUlEastingNorthing.y = 0.0; + theUlEastingNorthing.x = 0.0; + theDatum = theOrigin.datum(); + theEllipsoid = *(theDatum->ellipsoid()); + theDeltaLatPerPixel = latSpacing; + theDeltaLonPerPixel = lonSpacing; + computeMetersPerPixel(theOrigin, + theDeltaLatPerPixel, + theDeltaLonPerPixel, + theMetersPerPixel); +} + +ossimLlxyProjection::ossimLlxyProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + :ossimMapProjection(ellipsoid, origin) +{ + theDeltaLatPerPixel = 1.0; + theDeltaLonPerPixel = 1.0; + theUlEastingNorthing.y = OSSIM_DBL_NAN; + theUlEastingNorthing.x = OSSIM_DBL_NAN; + computeMetersPerPixel(theOrigin, + theDeltaLatPerPixel, + theDeltaLonPerPixel, + theMetersPerPixel); +} + +ossimLlxyProjection::~ossimLlxyProjection() +{ +} + +ossimObject* ossimLlxyProjection::dup()const +{ + return new ossimLlxyProjection(*this); +} + +//***************************************************************************** +// METHOD: ossimMapProjection::computeDegreesPerPixel +// +//***************************************************************************** +void ossimLlxyProjection::computeDegreesPerPixel(const ossimGpt& ground, + const ossimDpt& metersPerPixel, + double &deltaLat, + double &deltaLon) +{ + ossimDpt mpd = ground.metersPerDegree(); + ossimDpt dpm(1.0/mpd.x, + 1.0/mpd.y); + deltaLat = metersPerPixel.y*dpm.y; + deltaLon = metersPerPixel.x*dpm.x; +} + +//***************************************************************************** +// METHOD: ossimMapProjection::computeMetersPerPixel +// +//***************************************************************************** +void ossimLlxyProjection::computeMetersPerPixel(const ossimGpt& center, + double deltaDegreesPerPixelLat, + double deltaDegreesPerPixelLon, + ossimDpt &metersPerPixel) +{ + metersPerPixel = center.metersPerDegree(); + metersPerPixel.x *= deltaDegreesPerPixelLon; + metersPerPixel.y *= deltaDegreesPerPixelLat; +} + +void ossimLlxyProjection::worldToLineSample(const ossimGpt& worldPoint, + ossimDpt& lineSampPt) const +{ + ossimGpt gpt = worldPoint; + + if (theOrigin.datum() != gpt.datum()) + { + // Apply datum shift if it's not the same. + gpt.changeDatum(theOrigin.datum()); + } + + lineSampPt.line = (theUlGpt.latd() - gpt.latd()) / theDeltaLatPerPixel; + lineSampPt.samp = (gpt.lond() - theUlGpt.lond()) / theDeltaLonPerPixel; +} + +void ossimLlxyProjection::lineSampleToWorld(const ossimDpt& lineSampPt, + ossimGpt& worldPt) const +{ + // Start with the origin. This will keep the origin's datum. + worldPt = theUlGpt; + + double lat = theUlGpt.latd() - (lineSampPt.line * theDeltaLatPerPixel); + double lon = theUlGpt.lond() + (lineSampPt.samp * theDeltaLonPerPixel); + + //--- + // Assuming the origin had a lon between -180 and 180 and lat between -90 + // and 90. + //--- +// if (lon > 180.0) +// { +// lon -= 360.0; +// } +// else if (lon < -180.0) +// { +// lon += 360.0; +// } +// if (lat > 90.0) +// { +// lat -= 90.0; +// } +// else if (lat < -90.0) +// { +// lat = -180.0 - lat; +// } + + worldPt.latd(lat); + worldPt.lond(lon); + worldPt.hgt = ossimElevManager::instance()->getHeightAboveEllipsoid(worldPt); +} + +std::ostream& ossimLlxyProjection::print(std::ostream& out) const +{ + out << setiosflags(ios::fixed) << setprecision(15) + << "ossimLlxyProjection dump:" + << "\norigin: " << theOrigin + << "\nlatitude spacing in decimal degrees: " << theDeltaLatPerPixel + << "\nlongitude spacing in decimal degrees: " << theDeltaLonPerPixel + << "\n\nossimMapProjection dump:\n" << endl; + + return ossimMapProjection::print(out); +} + +void ossimLlxyProjection::setMetersPerPixel(const ossimDpt& pt) +{ + ossimMapProjection::setMetersPerPixel(pt); + computeDegreesPerPixel(theOrigin, + theMetersPerPixel, + theDeltaLatPerPixel, + theDeltaLonPerPixel); +} + +bool ossimLlxyProjection::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + // Base class... + ossimMapProjection::saveState(kwl, prefix); + + return true; +} + +bool ossimLlxyProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + // Base class... + ossimMapProjection::loadState(kwl, prefix); + + const char* deltaLat = kwl.find(prefix, ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LAT); + const char* deltaLon = kwl.find(prefix, ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LON); + const char* deltaX = kwl.find(prefix, ossimKeywordNames::METERS_PER_PIXEL_X_KW); + const char* deltaY = kwl.find(prefix, ossimKeywordNames::METERS_PER_PIXEL_Y_KW); + + if (deltaLat&&deltaLon) + { + theDeltaLatPerPixel = ossimString(deltaLat).toDouble(); + theDeltaLonPerPixel = ossimString(deltaLon).toDouble(); + computeMetersPerPixel(theOrigin, + theDeltaLatPerPixel, + theDeltaLonPerPixel, + theMetersPerPixel); + } + else if(deltaX&&deltaY) + { + theMetersPerPixel.x = ossimString(deltaX).toDouble(); + theMetersPerPixel.y = ossimString(deltaY).toDouble(); + + computeDegreesPerPixel(theOrigin, + theMetersPerPixel, + theDeltaLatPerPixel, + theDeltaLonPerPixel); + } + if(!deltaLat&&!deltaLon&&!deltaX&&!deltaY) + { + theDeltaLatPerPixel = 1.0; + theDeltaLonPerPixel = 1.0; + computeMetersPerPixel(theOrigin, + theDeltaLatPerPixel, + theDeltaLonPerPixel, + theMetersPerPixel); + } + + return true; +} + +bool ossimLlxyProjection::operator==(const ossimProjection& projection) const +{ + const ossimLlxyProjection* proj + = PTR_CAST(ossimLlxyProjection, &projection); + + if(!proj) + { + return false; + } + + return ( // (theOrigin == proj->theOrigin) && // tmp... fix gpt! + (theDeltaLatPerPixel == proj->theDeltaLatPerPixel) && + (theDeltaLonPerPixel == proj->theDeltaLonPerPixel) ); +} + + +ossimDpt ossimLlxyProjection::forward(const ossimGpt &worldPoint) const +{ + ossimDpt result; + + worldToLineSample(worldPoint, result); + + return result; +} + +ossimGpt ossimLlxyProjection::inverse(const ossimDpt &projectedPoint) const +{ + ossimGpt result; + + lineSampleToWorld(projectedPoint, result); + + return result; +} + +void ossimLlxyProjection::setLatSpacing(double spacing) +{ + theDeltaLatPerPixel = spacing; + + // Update the meters per pixel. + ossimDpt pt = ossimGpt(0.0, 0.0).metersPerDegree(); + theMetersPerPixel.y = pt.y * theDeltaLatPerPixel; +} + +void ossimLlxyProjection::setLonSpacing(double spacing) +{ + theDeltaLonPerPixel = spacing; + + // Update the meters per pixel. + ossimDpt pt = ossimGpt(0.0, 0.0).metersPerDegree(); + theMetersPerPixel.x = pt.x * theDeltaLonPerPixel; +} + +bool ossimLlxyProjection::isGeographic() const +{ + return true; +} + +void ossimLlxyProjection::setOrigin(const ossimGpt& origin) +{ + theOrigin = origin; +} + +double ossimLlxyProjection::getLatSpacing() const +{ + return theDeltaLatPerPixel; +} + +double ossimLlxyProjection::getLonSpacing() const +{ + return theDeltaLonPerPixel; +} diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimLlxyProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimLlxyProjection.h new file mode 100644 index 0000000000..6c121addfa --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimLlxyProjection.h @@ -0,0 +1,146 @@ +//******************************************************************* +// Copyright (C) 2002 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: David Burken +// +// Description: +// +// Contains class declaration for ossimLlxy. This is a simple "latitude / +// longitude to x / y" projection. Note that "origin" and "tie_point" are +// synonymous in this projection. +// +//******************************************************************* +// $Id: ossimLlxyProjection.h,v 1.13 2005/09/09 19:23:58 gpotts Exp $ + +#ifndef ossimLlxyProjection_HEADER +#define ossimLlxyProjection_HEADER + +#include "ossimMapProjection.h" + +class OSSIMDLLEXPORT ossimLlxyProjection : public ossimMapProjection +{ +public: + ossimLlxyProjection(); + ossimLlxyProjection(const ossimLlxyProjection& rhs); + ossimLlxyProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin); + ossimLlxyProjection(const ossimGpt& origin, + double latSpacing, // decimal degrees + double lonSpacing); + + virtual ~ossimLlxyProjection(); + + virtual ossimObject *dup()const; + + virtual bool isGeographic()const; + + virtual ossimDpt forward(const ossimGpt &worldPoint) const; + virtual ossimGpt inverse(const ossimDpt &projectedPoint) const; + + /*! + * METHOD: setOrigin(const ossimGpt& origin) + * Set the origin of the projection. + */ + virtual void setOrigin(const ossimGpt& origin); + + /*! + * METHOD: getLatSpacing() + * Returns the latitude spacing as a double representing decimal degrees. + */ + virtual double getLatSpacing() const; + + /*! + * METHOD: getLonSpacing() + * Returns the longitude spacing as a double representing decimal degrees. + */ + virtual double getLonSpacing() const; + + /*! + * METHOD: setLatSpacing(double spacing) + * Set the latitude spacing as a double representing decimal degrees. + */ + virtual void setLatSpacing(double spacing); + + /*! + * METHOD: setLonSpacing(double spacing) + * Set the latitude spacing as a double representing decimal degrees. + */ + virtual void setLonSpacing(double spacing); + + /*! + * METHOD: worldToLineSample() + * Performs the forward projection from ground point to line, sample. + */ + virtual void worldToLineSample(const ossimGpt& worldPoint, + ossimDpt& lineSampPt) const; + + /*! + * METHOD: lineSampleToWorld() + * Performs the inverse projection from line, sample to ground (world): + */ + virtual void lineSampleToWorld(const ossimDpt& lineSampPt, + ossimGpt& worldPt) const; + + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual std::ostream& print(std::ostream& out) const; + + virtual bool operator==(const ossimProjection& projection) const; + + // virtual ossimDpt getMetersPerPixel() const; + virtual void setMetersPerPixel(const ossimDpt& pt); + /*! + * This will go from the ground point and give + * you an approximate lat and lon per pixel. the Delta Lat + * and delta lon will be in degrees. + */ + virtual void computeDegreesPerPixel(const ossimGpt& ground, + const ossimDpt& metersPerPixel, + double &deltaLat, + double &deltaLon); + + + /*! + * This will go from the ground point and give + * you an approximate meters per pixel. the Delta Lat + * and delta lon will be in degrees. + */ + virtual void computeMetersPerPixel(const ossimGpt& center, + double deltaDegreesPerPixelLat, + double deltaDegreesPerPixelLon, + ossimDpt &metersPerPixel); + +private: + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMapProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMapProjection.cpp new file mode 100644 index 0000000000..d8ebaa55e6 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMapProjection.cpp @@ -0,0 +1,1054 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +// Base class for all map projections. +// +//******************************************************************* +// $Id: ossimMapProjection.cpp,v 1.108 2005/12/25 17:11:52 dburken Exp $ + +#include <iostream> +#include <iomanip> + +#include <projections/map_projections/ossimMapProjection.h> +#include <base/common/ossimKeywordNames.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/factory/ossimDatumFactory.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimGpt.h> +#include <base/data_types/datum/ossimDatum.h> +#include <base/data_types/ellipse/ossimEllipsoid.h> +#include <base/data_types/ossimString.h> +#include <elevation/ossimElevManager.h> +#include <base/data_types/ossimMatrix3x3.h> +#include <base/misc/ossimUnitConversionTool.h> + +// RTTI information for the ossimMapProjection +RTTI_DEF1(ossimMapProjection, "ossimMapProjection" , ossimProjection); + + +ossimMapProjection::ossimMapProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + :theEllipsoid(ellipsoid), + theOrigin(origin), + theDatum(origin.datum()), // force no shifting + theMetersPerPixel(1, 1), + theUlGpt(0, 0), + theUlEastingNorthing(0, 0), + theDeltaLatPerPixel(OSSIM_DBL_NAN), + theDeltaLonPerPixel(OSSIM_DBL_NAN) +{ + theUlGpt = theOrigin; + theUlEastingNorthing.makeNan(); + + thePcsCode = 0; +} + +ossimMapProjection::ossimMapProjection(const ossimMapProjection& src) + : ossimProjection(src), + theEllipsoid(src.theEllipsoid), + theOrigin(src.theOrigin), + theDatum(src.theDatum), + theMetersPerPixel(src.theMetersPerPixel), + theUlGpt(src.theUlGpt), + theUlEastingNorthing(src.theUlEastingNorthing), + theDeltaLatPerPixel(src.theDeltaLatPerPixel), + theDeltaLonPerPixel(src.theDeltaLonPerPixel), + thePcsCode(src.thePcsCode) +{ +} + + +ossimMapProjection::~ossimMapProjection() +{ +} + +ossimGpt ossimMapProjection::origin()const +{ + return theOrigin; +} + +void ossimMapProjection::setPcsCode(ossim_uint16 pcsCode) +{ + thePcsCode = pcsCode; +} + +ossim_uint16 ossimMapProjection::getPcsCode()const +{ + return thePcsCode; +} + +ossimString ossimMapProjection::getProjectionName() const +{ + return getClassName(); +} + +double ossimMapProjection::getA() const +{ + return theEllipsoid.getA(); +} + +double ossimMapProjection::getB() const +{ + return theEllipsoid.getB(); +} + +double ossimMapProjection::getF() const +{ + return theEllipsoid.getFlattening(); +} + +ossimDpt ossimMapProjection::getMetersPerPixel() const +{ + return theMetersPerPixel; +} + +ossimDpt ossimMapProjection::getDecimalDegreesPerPixel() const +{ + return ossimDpt(theDeltaLonPerPixel, theDeltaLatPerPixel); +} + +const ossimDpt& ossimMapProjection::getUlEastingNorthing() const +{ + return theUlEastingNorthing; +} + +const ossimGpt& ossimMapProjection::getUlGpt() const +{ + return theUlGpt; +} + +const ossimDatum* ossimMapProjection::getDatum() const +{ + return theDatum; +} + +bool ossimMapProjection::isGeographic()const +{ + return false; +} + +void ossimMapProjection::setEllipsoid(const ossimEllipsoid& ellipsoid) +{ + theEllipsoid = ellipsoid; update(); +} + +void ossimMapProjection::setAB(double a, double b) +{ + theEllipsoid.setA(a); theEllipsoid.setB(b); update(); +} + +void ossimMapProjection::setDatum(const ossimDatum* datum) +{ + if(datum) + { + theDatum = datum; setEllipsoid( *(datum->ellipsoid())); + } +} + +void ossimMapProjection::setOrigin(const ossimGpt& origin) +{ + theOrigin = origin; update(); +} + +//***************************************************************************** +// METHOD: ossimMapProjection::assign +// +//***************************************************************************** +void ossimMapProjection::assign(const ossimProjection &aProjection) +{ + if(&aProjection!=this) + { + ossimKeywordlist kwl; + + aProjection.saveState(kwl); + loadState(kwl); + } +} + +//***************************************************************************** +// METHOD: ossimMapProjection::update +// +//***************************************************************************** +void ossimMapProjection::update() +{ + // if the delta lat and lon per pixel is set then + // check to see if the meters were set. + // + if((theDeltaLatPerPixel != OSSIM_DBL_NAN)&& + (theDeltaLonPerPixel != OSSIM_DBL_NAN)) + { + if(theMetersPerPixel.hasNans()) + { + computeMetersPerPixel(theDeltaLatPerPixel, + theDeltaLonPerPixel, + theMetersPerPixel); + } + } + else if(!theMetersPerPixel.hasNans()) + { + computeDegreesPerPixel(theOrigin, + theMetersPerPixel, + theDeltaLatPerPixel, + theDeltaLonPerPixel); + } + + // compute the tie points if not already computed + // + if((theUlGpt.latd()==OSSIM_DBL_NAN)|| + (theUlGpt.lond()==OSSIM_DBL_NAN)) + { + theUlGpt = theOrigin; + } + if(theUlEastingNorthing.hasNans()) + { +// theUlEastingNorthing.x = 0.0; +// theUlEastingNorthing.y = 0.0; + if((theUlGpt.latd()!=OSSIM_DBL_NAN)&& + (theUlGpt.lond()!=OSSIM_DBL_NAN)) + { + theUlEastingNorthing = forward(theUlGpt); + } + } +} + +void ossimMapProjection::applyScale(const ossimDpt& scale, + bool recenterTiePoint) +{ + if (!recenterTiePoint) + { + theDeltaLonPerPixel *= scale.x; + theDeltaLatPerPixel *= scale.y; + theMetersPerPixel.x *= scale.x; + theMetersPerPixel.y *= scale.y; + } + else + { + if (isGeographic()) + { + // Get the current tie. + ossimGpt tie = getUlGpt(); + + // Shift it to the upper left edge of the pixel. + tie.lond( tie.lond() - theDeltaLonPerPixel/2.0); + tie.latd( tie.latd() + theDeltaLatPerPixel/2.0); + + // Apply the scale. + theDeltaLonPerPixel *= scale.x; + theDeltaLatPerPixel *= scale.y; + theMetersPerPixel.x *= scale.x; + theMetersPerPixel.y *= scale.y; + + // Now shift it back to center of the new tie. + tie.lond( tie.lond() + theDeltaLonPerPixel/2.0); + tie.latd( tie.latd() - theDeltaLatPerPixel/2.0); + + // Set the tie to new point. + setUlGpt(tie); + } + else + { + // Get the current tie point. + ossimDpt tie = getUlEastingNorthing(); + + // Shift it to the upper left edge of the pixel. + tie.x -= theMetersPerPixel.x/2.0; + tie.y += theMetersPerPixel.y/2.0; + + // Apply the scale. + theMetersPerPixel.x *= scale.x; + theMetersPerPixel.y *= scale.y; + theDeltaLonPerPixel *= scale.x; + theDeltaLatPerPixel *= scale.y; + + // Now shift it back to center of the new tie. + tie.x += theMetersPerPixel.x/2.0; + tie.y -= theMetersPerPixel.y/2.0; + + // Set the tie to new point. + setUlEastingNorthing(tie); + } + } +} + +//***************************************************************************** +// METHOD: ossimMapProjection::worldToLineSample +// +//***************************************************************************** +ossimDpt ossimMapProjection::worldToLineSample(const ossimGpt &worldPoint)const +{ + ossimDpt result; + + worldToLineSample(worldPoint, result); + + return result; +} + +//***************************************************************************** +// METHOD: ossimMapProjection::lineSampleToWorld +// +//***************************************************************************** +ossimGpt ossimMapProjection::lineSampleToWorld(const ossimDpt &lineSample)const +{ + ossimGpt result; + + lineSampleToWorld(lineSample, result); + + return result; +} + +//***************************************************************************** +// METHOD: ossimMapProjection::worldToLineSample +// +//***************************************************************************** +void ossimMapProjection::worldToLineSample(const ossimGpt &worldPoint, + ossimDpt& lineSample)const +{ + // make sure our tie point is good and world point + // is good. + // + if(theUlEastingNorthing.isNan()|| + worldPoint.isLatNan() || worldPoint.isLonNan()) + { + lineSample.makeNan(); + return; + } + // initialize line sample + // lineSample = ossimDpt(0,0); + + // I am commenting this code out because I am going to + // move it to the ossimImageViewProjectionTransform. + // + // see if we have a datum set and if so + // shift the world to our datum. If not then + // find the easting northing value for the world + // point. + if(theDatum) + { + ossimGpt gpt = worldPoint; + + gpt.changeDatum(theDatum); + + // lineSample is currently in easting northing + // and will need to be converted to line sample. + lineSample = forward(gpt); + } + else + { + // lineSample is currently in easting northing + // and will need to be converted to line sample. + lineSample = forward(worldPoint); + } + + // check the final result to make sure there were no + // problems. + // + if(!lineSample.isNan()) + { +// if(!isIdentityMatrix()) +// { +// ossimDpt temp = lineSample; + +// lineSample.x = theInverseTrans[0][0]*temp.x+ +// theInverseTrans[0][1]*temp.y+ +// theInverseTrans[0][2]; + +// lineSample.y = theInverseTrans[1][0]*temp.x+ +// theInverseTrans[1][1]*temp.y+ +// theInverseTrans[1][2]; +// } +// else + { + lineSample.x = ((lineSample.x - theUlEastingNorthing.x)/theMetersPerPixel.x); + + // We must remember that the Northing is negative since the positive + // axis for an image is assumed to go down since it's image space. + lineSample.y = (-(lineSample.y - theUlEastingNorthing.y)/theMetersPerPixel.y); + } + } +} + +//***************************************************************************** +// METHOD: ossimMapProjection::lineSampleHeightToWorld +// +//***************************************************************************** +void ossimMapProjection::lineSampleHeightToWorld(const ossimDpt &lineSample, + const double& hgtEllipsoid, + ossimGpt& gpt)const +{ + // + // make sure that the passed in lineSample is good and + // check to make sure our easting northing is good so + // we can compute the line sample. + // + // + if(lineSample.hasNans()||theUlEastingNorthing.hasNans()) + { + gpt.makeNan(); + return; + } + ossimDpt eastingNorthing; + + eastingNorthing = (theUlEastingNorthing); + + eastingNorthing.x += (lineSample.x*theMetersPerPixel.x); + + // + // Note: the Northing is positive up. In image space + // the positive axis is down so we must multiply by + // -1 + // + eastingNorthing.y += (-lineSample.y*theMetersPerPixel.y); + + + // + // now invert the meters into a ground point. + // + gpt = inverse(eastingNorthing); + gpt.datum(theDatum); + + if(gpt.isLatNan() && gpt.isLonNan()) + { + gpt.makeNan(); + } + else + { + gpt.clampLat(-90, 90); + gpt.clampLon(-180, 180); + + // Finally assign the specified height: + gpt.hgt = hgtEllipsoid; + } +} + +//***************************************************************************** +// METHOD: ossimMapProjection::lineSampleToWorld +// +// Implements the base class pure virtual. Simply calls lineSampleToWorld() +// and assigns argument height to the resultant groundpoint. +// +//***************************************************************************** +void ossimMapProjection::lineSampleToWorld (const ossimDpt& lineSampPt, + ossimGpt& worldPt) const +{ + double null_elev = OSSIM_DBL_NAN; + + lineSampleHeightToWorld(lineSampPt, null_elev, worldPt); + + worldPt.hgt = ossimElevManager::instance()->getHeightAboveEllipsoid(worldPt); +} + +//***************************************************************************** +// METHOD: ossimMapProjection::lineSampleToEastingNorthing +// +//***************************************************************************** +void ossimMapProjection::lineSampleToEastingNorthing(const ossimDpt& lineSample, + ossimDpt& eastingNorthing)const +{ + // make sure that the passed in lineSample is good and + // check to make sure our easting northing is good so + // we can compute the line sample. + // + if(lineSample.hasNans()||theUlEastingNorthing.hasNans()) + { + eastingNorthing.makeNan(); + return; + } + ossimDpt deltaPoint = lineSample; + + eastingNorthing.x = theUlEastingNorthing.x + deltaPoint.x*theMetersPerPixel.x; + eastingNorthing.y = theUlEastingNorthing.y + (-deltaPoint.y)*theMetersPerPixel.y ; + + // eastingNorthing.x += (lineSample.x*theMetersPerPixel.x); + + // Note: the Northing is positive up. In image space + // the positive axis is down so we must multiply by + // -1 + // eastingNorthing.y += (-lineSample.y*theMetersPerPixel.y); +} + +void ossimMapProjection::setMetersPerPixel(const ossimDpt& gsd) +{ + theMetersPerPixel=gsd; + computeDegreesPerPixel(theOrigin, + theMetersPerPixel, + theDeltaLatPerPixel, + theDeltaLonPerPixel); +} + +void ossimMapProjection::setDecimalDegreesPerPixel(const ossimDpt& gsd) +{ + theDeltaLatPerPixel = gsd.lat; + theDeltaLonPerPixel = gsd.lon; + + computeMetersPerPixel(theOrigin, + gsd.lat, + gsd.lon, + theMetersPerPixel); +} + +void ossimMapProjection::eastingNorthingToWorld(const ossimDpt& eastingNorthing, + ossimGpt& worldPt)const +{ + ossimDpt lineSample; + eastingNorthingToLineSample(eastingNorthing, lineSample); + lineSampleToWorld(lineSample, worldPt); +} + + +//***************************************************************************** +// METHOD: ossimMapProjection::eastingNorthingToLineSample +// +//***************************************************************************** +void ossimMapProjection::eastingNorthingToLineSample(const ossimDpt& eastingNorthing, + ossimDpt& lineSample)const +{ + if(eastingNorthing.hasNans()) + { + lineSample.makeNan(); + return; + } + // check the final result to make sure there were no + // problems. + // + if(!eastingNorthing.isNan()) + { + lineSample.x = (eastingNorthing.x - theUlEastingNorthing.x)/theMetersPerPixel.x; + + // We must remember that the Northing is negative since the positive + // axis for an image is assumed to go down since it's image space. + lineSample.y = (-(eastingNorthing.y-theUlEastingNorthing.y))/theMetersPerPixel.y; + } +} + +//***************************************************************************** +// METHOD: ossimMapProjection::setUlEastingNorthing +// +//***************************************************************************** +void ossimMapProjection::setUlEastingNorthing(const ossimDpt& ulEastingNorthing) +{ + theUlEastingNorthing = ulEastingNorthing; +} + +//***************************************************************************** +// METHOD: ossimMapProjection::setUlGpt +// +//***************************************************************************** +void ossimMapProjection::setUlGpt(const ossimGpt& ulGpt) +{ + theUlGpt = ulGpt; +} + +//***************************************************************************** +// METHOD: ossimMapProjection::saveState +// +//***************************************************************************** +bool ossimMapProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const +{ + ossimProjection::saveState(kwl, prefix); + + kwl.add(prefix, + ossimKeywordNames::ORIGIN_LATITUDE_KW, + theOrigin.latd(), + true); + + kwl.add(prefix, + ossimKeywordNames::CENTRAL_MERIDIAN_KW, + theOrigin.lond(), + true); + + if(isGeographic()) + { + kwl.add(prefix, + ossimKeywordNames::TIE_POINT_LAT_KW, + theUlGpt.latd(), + true); + + kwl.add(prefix, + ossimKeywordNames::TIE_POINT_LON_KW, + theUlGpt.lond(), + true); + } + + theEllipsoid.saveState(kwl, prefix); + + if(!ossimIsNan(theDeltaLatPerPixel)&&isGeographic()) + { + kwl.add(prefix, + ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LAT, + theDeltaLatPerPixel, + true); + } + + if(!ossimIsNan(theDeltaLonPerPixel)&&isGeographic()) + { + kwl.add(prefix, + ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LON, + theDeltaLonPerPixel, + true); + } + + if(theDatum) + { + kwl.add(prefix, + ossimKeywordNames::DATUM_KW, + theDatum->code(), + true); + } + + if(!theMetersPerPixel.isNan()&&!isGeographic()) + { + kwl.add(prefix, + ossimKeywordNames::METERS_PER_PIXEL_X_KW, + theMetersPerPixel.x, + true); + + kwl.add(prefix, + ossimKeywordNames::METERS_PER_PIXEL_Y_KW, + theMetersPerPixel.y, + true); + } + + if(!theUlEastingNorthing.isNan()&&!isGeographic()) + { + kwl.add(prefix, + ossimKeywordNames::TIE_POINT_EASTING_KW, + theUlEastingNorthing.x, + true); + + kwl.add(prefix, + ossimKeywordNames::TIE_POINT_NORTHING_KW, + theUlEastingNorthing.y, + true); + } + + if(thePcsCode != 0) + { + kwl.add(prefix, + ossimKeywordNames::PCS_CODE_KW, + thePcsCode, + true); + } + + return true; +} + +//***************************************************************************** +// METHOD: ossimMapProjection::loadState +// +//***************************************************************************** +bool ossimMapProjection::loadState(const ossimKeywordlist& kwl, const char* prefix) +{ + ossimProjection::loadState(kwl, prefix); + + const char* scale_x = kwl.find(prefix, ossimKeywordNames::SCALE_X_KW); + const char* scale_y = kwl.find(prefix, ossimKeywordNames::SCALE_Y_KW); + const char* trans_x = kwl.find(prefix, ossimKeywordNames::TRANSLATION_X_KW); + const char* trans_y = kwl.find(prefix, ossimKeywordNames::TRANSLATION_Y_KW); + const char* rotation = kwl.find(prefix, ossimKeywordNames::ROTATION_KW); + const char* pcs_code = kwl.find(prefix, ossimKeywordNames::PCS_CODE_KW); + ossimDpt scale(1.0, 1.0); + ossimDpt trans(0.0, 0.0); + double rot = 0.0; + + if(scale_x) + scale.x = ossimString(scale_x).toDouble(); + + if(scale_y) + scale.y = ossimString(scale_y).toDouble(); + + if(trans_x) + trans.x = ossimString(trans_x).toDouble(); + + if(trans_y) + trans.y = ossimString(trans_y).toDouble(); + + if(rotation) + rot = ossimString(rotation).toDouble(); + + if(pcs_code) + { + thePcsCode = (ossim_uint16)ossimString(pcs_code).toULong(); + } + else + { + thePcsCode = 0; + } + + const char *lookup; + + // Get the latitude of the origin. + lookup = kwl.find(prefix, ossimKeywordNames::ORIGIN_LATITUDE_KW); + if (lookup) + { + theOrigin.latd(ossimString(lookup).toDouble()); + } + + // Get the central meridian. + lookup = kwl.find(prefix, ossimKeywordNames::CENTRAL_MERIDIAN_KW); + if (lookup) + { + theOrigin.lond(ossimString(lookup).toDouble()); + } + + theEllipsoid.loadState(kwl, prefix); + + //*** + // Call the virtual method "updateState" to allow derived classes to + // verify/update their state. + //*** + lookup = kwl.find(prefix, ossimKeywordNames::DATUM_KW); + if(lookup) + { + theDatum = ossimDatumFactory::instance()->create(lookup); + if(theDatum) + { + const ossimEllipsoid* ellipse = theDatum->ellipsoid(); + if(ellipse) + { + theEllipsoid = *ellipse; + } + } + } + else + { + theDatum = ossimDatumFactory::instance()->wgs84(); + } + + if(theDatum) + { + theOrigin.datum(theDatum); + theUlGpt.datum(theDatum); + } + + lookup = kwl.find(prefix, ossimKeywordNames::METERS_PER_PIXEL_X_KW); + if(lookup) + { + theMetersPerPixel.x = fabs(ossimString(lookup).toDouble()); + } + else + { + theMetersPerPixel.x = OSSIM_DBL_NAN; + } + + lookup = kwl.find(prefix, ossimKeywordNames::METERS_PER_PIXEL_Y_KW); + if(lookup) + { + theMetersPerPixel.y = fabs(ossimString(lookup).toDouble()); + } + else + { + theMetersPerPixel.y = OSSIM_DBL_NAN; + } + + theUlEastingNorthing.makeNan(); + theUlGpt.makeNan(); + + const char* easting = kwl.find(prefix, ossimKeywordNames::TIE_POINT_EASTING_KW); + if(easting) + { + theUlEastingNorthing.x = (ossimString(easting).toDouble()); + } + + const char* northing = kwl.find(prefix, ossimKeywordNames::TIE_POINT_NORTHING_KW); + if(northing) + { + theUlEastingNorthing.y = (ossimString(northing).toDouble()); + } + const char* tie_lat = NULL; + const char* tie_lon = NULL; + + + tie_lat = kwl.find(prefix, ossimKeywordNames::TIE_POINT_LAT_KW); + tie_lon = kwl.find(prefix, ossimKeywordNames::TIE_POINT_LON_KW); + + if(tie_lat && tie_lon ) + { + theUlGpt.latd(ossimString(tie_lat).toDouble()); + theUlGpt.lond(ossimString(tie_lon).toDouble()); + } + else + { + theUlGpt.makeNan(); + } + + const char* deg_per_lat = kwl.find(prefix, ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LAT); + const char* deg_per_lon = kwl.find(prefix, ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LON); + + if(deg_per_lat) + { + theDeltaLatPerPixel = fabs(ossimString(deg_per_lat).toDouble()); + } + else + { + theDeltaLatPerPixel = OSSIM_DBL_NAN; + } + if(deg_per_lon) + { + theDeltaLonPerPixel = fabs(ossimString(deg_per_lon).toDouble()); + } + else + { + theDeltaLonPerPixel = OSSIM_DBL_NAN; + } + + if((theDeltaLonPerPixel!=OSSIM_DBL_NAN)&& + (theDeltaLatPerPixel!=OSSIM_DBL_NAN)&& + theMetersPerPixel.hasNans()) + { + theMetersPerPixel = theOrigin.metersPerDegree(); + theMetersPerPixel.x *= theDeltaLonPerPixel; + theMetersPerPixel.y *= theDeltaLatPerPixel; + } + + ossimString pixelType = kwl.find(prefix, ossimKeywordNames::PIXEL_TYPE_KW); + pixelType=pixelType.trim(); + if(pixelType!="") + { + pixelType.downcase(); + if(pixelType.contains("area")) + { + if((theMetersPerPixel.x != OSSIM_DBL_NAN)&& + (theMetersPerPixel.y != OSSIM_DBL_NAN)) + { + if(!theUlEastingNorthing.hasNans()) + { + theUlEastingNorthing.x += theMetersPerPixel.x; + theUlEastingNorthing.y -= theMetersPerPixel.y; + } + } + if((theDeltaLatPerPixel != OSSIM_DBL_NAN)&& + (theDeltaLonPerPixel != OSSIM_DBL_NAN)) + { + theUlGpt.latd( theUlGpt.latd() - theDeltaLatPerPixel); + theUlGpt.lond( theUlGpt.lond() + theDeltaLonPerPixel); + } + } + } + return true; +} + +//***************************************************************************** +// METHOD: ossimMapProjection::print +//***************************************************************************** +std::ostream& ossimMapProjection::print(std::ostream& out) const +{ + const char MODULE[] = "ossimMapProjection::print"; + + out << setiosflags(ios::fixed) << setprecision(15) + << "\n// " << MODULE + << "\n" << ossimKeywordNames::TYPE_KW << ": " + << getClassName() + << "\n" << ossimKeywordNames::MAJOR_AXIS_KW << ": " + << theEllipsoid.getA() + << "\n" << ossimKeywordNames::MINOR_AXIS_KW << ": " + << theEllipsoid.getB() + << "\n" << ossimKeywordNames::ORIGIN_LATITUDE_KW << ": " + << theOrigin.latd() + << "\n" << ossimKeywordNames::CENTRAL_MERIDIAN_KW << ": " + << theOrigin.lond() + << "\n" << ossimKeywordNames::DATUM_KW << ": " + << (theDatum?theDatum->code().c_str():"unknown") + << "\n" << ossimKeywordNames::METERS_PER_PIXEL_X_KW << ": " + << (ossimIsNan(theMetersPerPixel.x)?ossimString("nan"):ossimString::toString(theMetersPerPixel.x, 15)) + << "\n" << ossimKeywordNames::METERS_PER_PIXEL_Y_KW << ": " + << (ossimIsNan(theMetersPerPixel.y)?ossimString("nan"):ossimString::toString(theMetersPerPixel.y, 15)) + << std::endl; + return ossimProjection::print(out); +} + +//***************************************************************************** +// METHOD: ossimMapProjection::computeDegreesPerPixel +// +//***************************************************************************** +void ossimMapProjection::computeDegreesPerPixel(const ossimGpt& ground, + const ossimDpt& metersPerPixel, + double &deltaLat, + double &deltaLon) +{ +// ossimDpt mpd = ground.metersPerDegree(); +// ossimDpt dpm(1.0/mpd.x, +// 1.0/mpd.y); +// deltaLat = metersPerPixel.y*dpm.y; +// deltaLon = metersPerPixel.x*dpm.x; + ossimDpt eastNorthGround = forward(ground); + ossimDpt rightEastNorth = eastNorthGround; + ossimDpt downEastNorth = eastNorthGround; + rightEastNorth.x += metersPerPixel.x; + downEastNorth.y -= metersPerPixel.y; + + ossimGpt rightGpt = inverse(rightEastNorth); + ossimGpt downGpt = inverse(downEastNorth); + + // use euclidean distance to get length along the horizontal (lon) + // and vertical (lat) directions + // + double tempDeltaLat = rightGpt.latd() - ground.latd(); + double tempDeltaLon = rightGpt.lond() - ground.lond(); + deltaLon = sqrt(tempDeltaLat*tempDeltaLat + tempDeltaLon*tempDeltaLon); + + tempDeltaLat = downGpt.latd() - ground.latd(); + tempDeltaLon = downGpt.lond() - ground.lond(); + deltaLat = sqrt(tempDeltaLat*tempDeltaLat + tempDeltaLon*tempDeltaLon); + +} + +//***************************************************************************** +// METHOD: ossimMapProjection::computeMetersPerPixel +// +//***************************************************************************** +void ossimMapProjection::computeMetersPerPixel(const ossimGpt& center, + double deltaDegreesPerPixelLat, + double deltaDegreesPerPixelLon, + ossimDpt &metersPerPixel) +{ +// metersPerPixel = center.metersPerDegree(); +// metersPerPixel.x *= deltaDegreesPerPixelLon; +// metersPerPixel.y *= deltaDegreesPerPixelLat; + + ossimGpt right=center; + ossimGpt down=center; + + down.latd(center.latd() + deltaDegreesPerPixelLat); + right.lond(center.lond() + deltaDegreesPerPixelLon); + + ossimDpt centerMeters = forward(center); + ossimDpt rightMeters = forward(right); + ossimDpt downMeters = forward(down); + + + metersPerPixel.x = (rightMeters - centerMeters).length(); + metersPerPixel.y = (downMeters - centerMeters).length(); + +} + +//***************************************************************************** +// METHOD: ossimMapProjection::computeMetersPerPixel +// +//***************************************************************************** +void ossimMapProjection::computeMetersPerPixel(double deltaDegreesPerPixelLat, + double deltaDegreesPerPixelLon, + ossimDpt &metersPerPixel) +{ + computeMetersPerPixel(theOrigin, + deltaDegreesPerPixelLat, + deltaDegreesPerPixelLon, + metersPerPixel); +} + +//***************************************************************************** +// METHOD: ossimMapProjection::operator== +// +//***************************************************************************** +bool ossimMapProjection::operator==(const ossimProjection& projection) const +{ + const ossimMapProjection* mapProj = PTR_CAST(ossimMapProjection, &projection); + + if(!mapProj) + { + return false; + } + + if( (theDatum == mapProj->theDatum) && + (getClassName() == mapProj->getClassName())&& + (theOrigin == mapProj->theOrigin)) + { + if(isGeographic()) + { + return ( (theDeltaLatPerPixel == mapProj->theDeltaLatPerPixel) && + (theDeltaLonPerPixel == mapProj->theDeltaLonPerPixel) && + (theUlGpt == mapProj->theUlGpt)); + } + else + { + return ( (theMetersPerPixel == mapProj->theMetersPerPixel) && + (theUlEastingNorthing == mapProj->theUlEastingNorthing)); + } + } + + return false; +} + +double ossimMapProjection::getFalseEasting() const +{ + return 0.0; +} + +double ossimMapProjection::getFalseNorthing() const +{ + return 0.0; +} + +double ossimMapProjection::getStandardParallel1() const +{ + return 0.0; +} + +double ossimMapProjection::getStandardParallel2() const +{ + return 0.0; +} + +void ossimMapProjection::snaptTiePointTo(ossim_float64 multiple, + ossimUnitType unitType) +{ + ossim_float64 convertedMultiple = multiple; + + if (isGeographic() && (unitType != OSSIM_DEGREES) ) + { + // Convert to degrees. + ossimUnitConversionTool convertor; + convertor.setOrigin(theOrigin); + convertor.setValue(multiple, unitType); + convertedMultiple = convertor.getDegrees(); + } + else if ( !isGeographic() && (unitType != OSSIM_METERS) ) + { + // Convert to meters. + ossimUnitConversionTool convertor; + convertor.setOrigin(theOrigin); + convertor.setValue(multiple, unitType); + convertedMultiple = convertor.getMeters(); + } + + // cout << "multiple: " << convertedMultiple << endl; + + // Convert the tie point. + if (isGeographic()) + { + // Snap the latitude. + ossim_float64 d = theUlGpt.latd(); + d = irint(d / convertedMultiple) * convertedMultiple; + theUlGpt.latd(d); + + // Snap the longitude. + d = theUlGpt.lond(); + d = irint(d / convertedMultiple) * convertedMultiple; + theUlGpt.lond(d); + + // Adjust the stored easting / northing. + theUlEastingNorthing = forward(theUlGpt); + } + else + { + // Snap the easting. + ossim_float64 d = theUlEastingNorthing.x; + d = irint(d / convertedMultiple) * convertedMultiple; + theUlEastingNorthing.x = d; + + // Snap the northing. + d = theUlEastingNorthing.y; + d = irint(d / convertedMultiple) * convertedMultiple; + theUlEastingNorthing.y = d; + + // Adjust the stored upper left ground point. + theUlGpt = inverse(theUlEastingNorthing); + } +} diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMapProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMapProjection.h new file mode 100644 index 0000000000..e70bc2e349 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMapProjection.h @@ -0,0 +1,295 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +// Base class for all map projections. +// +//******************************************************************* +// $Id: ossimMapProjection.h,v 1.51 2005/12/25 17:11:52 dburken Exp $ + +#ifndef ossimMapProjection_HEADER +#define ossimMapProjection_HEADER + +#include <projections/ossimProjection.h> +#include <base/common/ossimConstants.h> +#include <base/data_types/ossimGpt.h> +#include <base/data_types/ossimKeyword.h> +#include <base/data_types/ossimString.h> +#include <base/data_types/ellipse/ossimEllipsoid.h> +#include <base/data_types/datum/ossimDatum.h> +#include <base/data_types/ossimDrect.h> +#include <iostream> +using namespace std; + +#include <matrix/newmat.h> +#include <matrix/newmatio.h> + +class ossimKeywordlist; + +class OSSIMDLLEXPORT ossimMapProjection : public ossimProjection +{ +public: + ossimMapProjection(const ossimEllipsoid& ellipsoid = ossimEllipsoid(), + const ossimGpt& origin=ossimGpt()); + + ossimMapProjection(const ossimMapProjection& src); + virtual ~ossimMapProjection(); + + virtual ossimGpt origin()const; + + /** + * All map projections will convert the world coordinate to an easting + * northing (Meters). + */ + virtual ossimDpt forward(const ossimGpt &worldPoint) const = 0; + + /** + * Will take a point in meters and convert it to ground. + */ + virtual ossimGpt inverse(const ossimDpt &projectedPoint)const = 0; + + virtual ossimDpt worldToLineSample(const ossimGpt &worldPoint)const; + virtual void worldToLineSample(const ossimGpt &worldPoint, + ossimDpt& lineSample)const; + + virtual ossimGpt lineSampleToWorld(const ossimDpt &projectedPoint)const; + virtual void lineSampleToWorld(const ossimDpt &projectedPoint, + ossimGpt& gpt)const; + /** + * This is the pure virtual that projects the image point to the given + * elevation above ellipsoid, thereby bypassing reference to a DEM. Useful + * for projections that are sensitive to elevation. + */ + virtual void lineSampleHeightToWorld(const ossimDpt& lineSampPt, + const double& heightAboveEllipsoid, + ossimGpt& worldPt) const; + + virtual void lineSampleToEastingNorthing(const ossimDpt& liineSample, + ossimDpt& eastingNorthing)const; + + virtual void eastingNorthingToLineSample(const ossimDpt& eastingNorthing, + ossimDpt& lineSample)const; + + virtual void eastingNorthingToWorld(const ossimDpt& eastingNorthing, + ossimGpt& worldPt)const; + + + /** + * Derived classes should implement as needed. + * This implementation returns 0.0. + * + * @return The false easting. + * + * @note At some point we should make theFalseEasting a data member and + * change derived classes to use it. + */ + virtual double getFalseEasting() const; + + /** + * Derived classes should implement as needed. + * This implementation returns 0.0. + * + * @return The false northing. + * + * @note At some point we should make theFalseEasting a data member and + * change derived classes to use it. + */ + virtual double getFalseNorthing() const; + + /** + * Derived classes should implement as needed. + * This implementation returns 0.0. + * + * @return The first standard parallel. + */ + virtual double getStandardParallel1() const; + + /** + * Derived classes should implement as needed. + * This implementation returns 0.0. + * + * @return The second standard parallel. + */ + virtual double getStandardParallel2() const; + + virtual void update(); + + virtual void setPcsCode(ossim_uint16 pcsCode); + virtual ossim_uint16 getPcsCode()const; + + /** + * Returns the projection name. + */ + virtual ossimString getProjectionName() const; + + /** + * ACCESS METHODS: + */ + virtual double getA() const; + virtual double getB() const; + virtual double getF() const; + + virtual ossimDpt getMetersPerPixel() const; + + /** + * Returns decimal degrees per pixel as an ossimDpt with + * "x" representing longitude and "y" representing latitude. + */ + virtual ossimDpt getDecimalDegreesPerPixel() const; + + virtual const ossimDpt& getUlEastingNorthing() const; + virtual const ossimGpt& getUlGpt() const; + virtual const ossimDatum* getDatum() const; + + virtual bool isGeographic()const; + + /** + * Applies scale to theDeltaLonPerPixel, theDeltaLatPerPixel and + * theMetersPerPixel data members (eg: theDeltaLonPerPixel *= scale.x). + * + * @param scale Multiplier to be applied to theDeltaLonPerPixel, + * theDeltaLatPerPixel and theMetersPerPixel + * + * @param recenterTiePoint If true the will adjust the tie point by + * shifting the original tie to the upper left corner, applying scale, + * then shifting back by half of either the new + * theDeltaLat/lon or theMetersPerPixel depending on if projection + * isGeographic. + */ + virtual void applyScale(const ossimDpt& scale, bool recenterTiePoint); + + /** + * SET METHODS: + */ + virtual void setEllipsoid(const ossimEllipsoid& ellipsoid); + virtual void setAB(double a, double b); + virtual void setDatum(const ossimDatum* datum); + virtual void setOrigin(const ossimGpt& origin); + virtual void setMetersPerPixel(const ossimDpt& gsd); + virtual void setDecimalDegreesPerPixel(const ossimDpt& gsd); + virtual void setUlEastingNorthing(const ossimDpt& ulEastingNorthing); + virtual void setUlGpt(const ossimGpt& ulGpt); + virtual void assign( const ossimProjection &aProjection); + + /** + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0) const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * Prints data members to stream. Returns stream&. + */ + virtual std::ostream& print(std::ostream& out) const; + + virtual bool operator==(const ossimProjection& projection) const; + + /** + * This will go from the ground point and give + * you an approximate lat and lon per pixel. the Delta Lat + * and delta lon will be in degrees. + */ + virtual void computeDegreesPerPixel(const ossimGpt& ground, + const ossimDpt& metersPerPixel, + double &deltaLat, + double &deltaLon); + + + /** + * This will go from the ground point and give + * you an approximate meters per pixel. the Delta Lat + * and delta lon will be in degrees. + */ + virtual void computeMetersPerPixel(const ossimGpt& center, + double deltaDegreesPerPixelLat, + double deltaDegreesPerPixelLon, + ossimDpt &metersPerPixel); + + /** + * This will go from its internal origin of latitude and longitude and give + * you an approximate meters per pixel. the Delta Lat + * and delta lon will be in degrees. + */ + virtual void computeMetersPerPixel(double deltaDegreesPerPixelLat, + double deltaDegreesPerPixelLon, + ossimDpt &metersPerPixel); + + void setMatrix(double rotation, + const ossimDpt& scale, + const ossimDpt& translation); + + void setMatrixScale(const ossimDpt& scale); + + void setMatrixRotation(double rotation); + + void setMatrixTranslation(const ossimDpt& translation); + + /** + * Utility method to snap the tie point to some multiple. + * + * This is used to overcome inaccuracies in formats like NITF's rpc tag + * witch has a four digit decimal degree precision for the lat/lon offset. + * + * @param multiple Value to snap tie point to like 1.0. + * + * @param unitType OSSIM_METERS or OSSIM_DEGREES. + * + * EXAMPLE1: + * projection: ossimUtmProjection + * tie point is: 551634.88, 4492036.16 + * multiple: 1.0 + * unitType: OSSIM_METERS + * new tie point: 551635.00, 4492036.00 + * + * EXAMPLE2: + * projection: ossimEquDistCylProjection + * tie point is: -90.3246343 42.0297589 + * multiple: 0.0001 + * unitType: OSSIM_DEGREES + * new tie point: -90.3246 42.0298 + */ + void snaptTiePointTo(ossim_float64 multiple, ossimUnitType unitType); + + +protected: + ossimEllipsoid theEllipsoid; + ossimGpt theOrigin; + + /** + * This is only set if we want to have built in datum shifting + */ + const ossimDatum* theDatum; + + /** + * Holds the number of meters per sample. + */ + ossimDpt theMetersPerPixel; + + ossimGpt theUlGpt; + ossimDpt theUlEastingNorthing; + + double theDeltaLatPerPixel; + double theDeltaLonPerPixel; + + ossim_uint16 thePcsCode; + +TYPE_DATA +}; + + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMapProjectionInfo.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMapProjectionInfo.cpp new file mode 100644 index 0000000000..0c67a1d1c3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMapProjectionInfo.cpp @@ -0,0 +1,548 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// Class for encapsulate projection info given a projection, datum, and +// output rectangle. +// +// NOTE: +// - Output rectangle should be relative to the center of pixels. +// Shifts will be made for "pixel is area" internally. +// +//******************************************************************* +// $Id: ossimMapProjectionInfo.cpp,v 1.30 2005/10/13 15:04:06 dburken Exp $ + +#include <fstream> +#include <time.h> + +using namespace std; + +#include <projections/map_projections/ossimMapProjectionInfo.h> +#include <projections/map_projections/ossimMapProjection.h> +#include <base/common/ossimTrace.h> +#include <base/common/ossimCommon.h> +#include <base/data_types/ossimFilename.h> +#include <base/data_types/datum/ossimDatum.h> +#include <base/data_types/ellipse/ossimEllipsoid.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/ossimDrect.h> +#include <base/common/ossimKeywordNames.h> +#include <base/context/ossimNotifyContext.h> + +//*** +// Static trace for debugging. +//*** +static ossimTrace traceDebug("ossimMapProjectionInfo::debug"); + +//*** +// Keywords for getStateFrom/saveStateTo. +//*** +const char* ossimMapProjectionInfo::OUTPUT_US_FT_INFO_KW = +"viewinfo.output_readme_in_us_ft_flag"; + +const char* ossimMapProjectionInfo::PIXEL_TYPE_KW = "viewinfo.pixel_type"; + +const char* ossimMapProjectionInfo::README_IMAGE_STRING_KW = +"viewinfo.readme_image_string"; + +ossimMapProjectionInfo::ossimMapProjectionInfo(const ossimMapProjection* proj, + const ossimDrect& output_rect) + : + theProjection (proj), + theErrorStatus (false), + theLinesPerImage (0), + thePixelsPerLine (0), + theCornerGroundPt (), + theCornerEastingNorthingPt (), + theCenterGroundPt (), + theCenterEastingNorthingPt (0.0, 0.0), + thePixelType (OSSIM_PIXEL_IS_POINT), + theOutputInfoInFeetFlag (false), + theImageInfoString () +{ + if (!theProjection) + { + theErrorStatus = true; + ossimNotify(ossimNotifyLevel_FATAL) + << "FATAL ossimMapProjectionInfo::ossimMapProjectionInfo: " + << "Null projection pointer passed to constructor!" + << "\nError status has been set. Returning..." + << std::endl; + return; + } + + initializeMembers(output_rect); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimMapProjectionInfo::ossimMapProjectionInfo:\n" + << "output_rect: " << output_rect << "\n" + << *this << std::endl; + } +} + +ossimMapProjectionInfo::~ossimMapProjectionInfo() +{ +} + +bool ossimMapProjectionInfo::errorStatus() const +{ + return theErrorStatus; +} + +void ossimMapProjectionInfo::initializeMembers(const ossimDrect& rect) +{ + theBoundingRect = rect; + theLinesPerImage = irint(rect.height()); + thePixelsPerLine = irint(rect.width()); + + theProjection->lineSampleToWorld(rect.ul(), + theCornerGroundPt[0]); + + theProjection->lineSampleToWorld(rect.ur(), + theCornerGroundPt[1]); + + theProjection->lineSampleToWorld(rect.lr(), + theCornerGroundPt[2]); + + + theProjection->lineSampleToWorld(rect.ll(), + theCornerGroundPt[3]); + + theProjection->lineSampleToEastingNorthing(rect.ul(), + theCornerEastingNorthingPt[0]); + + theProjection->lineSampleToEastingNorthing(rect.ur(), + theCornerEastingNorthingPt[1]); + + theProjection->lineSampleToEastingNorthing(rect.lr(), + theCornerEastingNorthingPt[2]); + + theProjection->lineSampleToEastingNorthing(rect.ll(), + theCornerEastingNorthingPt[3]); + + theCenterEastingNorthingPt.x = (theCornerEastingNorthingPt[0].x + + theCornerEastingNorthingPt[1].x + + theCornerEastingNorthingPt[2].x + + theCornerEastingNorthingPt[3].x) / 4.0; + + theCenterEastingNorthingPt.y = (theCornerEastingNorthingPt[0].y + + theCornerEastingNorthingPt[1].y + + theCornerEastingNorthingPt[2].y + + theCornerEastingNorthingPt[3].y) / 4.0; + + theCenterGroundPt = theProjection->inverse(theCenterEastingNorthingPt); +} + + +void ossimMapProjectionInfo::getGeom(ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimDpt dpt = ulEastingNorthingPt(); + ossimGpt gpt = ulGroundPt(); + + theProjection->saveState(kwl, prefix); + + if(!theProjection->isGeographic()) + { + kwl.add(prefix, + ossimKeywordNames::TIE_POINT_EASTING_KW, + dpt.x, + true); + kwl.add(prefix, + ossimKeywordNames::TIE_POINT_NORTHING_KW, + dpt.y, + true); + } + else + { + kwl.add(prefix, + ossimKeywordNames::TIE_POINT_LAT_KW, + gpt.latd(), + true); + kwl.add(prefix, + ossimKeywordNames::TIE_POINT_LON_KW, + gpt.lond(), + true); + } +} + +std::ostream& ossimMapProjectionInfo::print(std::ostream& os) const +{ + if (!os) + { + return os; + } + + os << setiosflags(ios::left) + << setiosflags(ios::fixed) + << "ossimMapProjectionInfo Data Members:\n" + << "Projection name: " << theProjection->getProjectionName() + << setw(30) << "\nOutput pixel type:" + << ((getPixelType() == OSSIM_PIXEL_IS_POINT) ? "pixel is point" : + "pixel is area") + << setw(30) << "\nMeters per pixel:" + << getMetersPerPixel() + << setw(30) << "\nUS survey feet per pixel:" + << getUsSurveyFeetPerPixel() + << setw(30) << "\nDecimal degrees per pixel:" + << getDecimalDegreesPerPixel() + << setw(30) << "\nNumber of lines:" + << theLinesPerImage + << setw(30) << "\nNumber of pixels:" + << thePixelsPerLine + << setw(30) << "\nUpper left ground point:" + << theCornerGroundPt[0] + << setw(30) << "\nUpper right ground point:" + << theCornerGroundPt[1] + << setw(30) << "\nLower right ground point:" + << theCornerGroundPt[2] + << setw(30) << "\nLower left ground point:" + << theCornerGroundPt[3] + << setw(30) << "\nUpper left easting_northing:" + << theCornerEastingNorthingPt[0] + << setw(30) << "\nUpper right easting_northing:" + << theCornerEastingNorthingPt[1] + << setw(30) << "\nLower right easting_northing:" + << theCornerEastingNorthingPt[2] + << setw(30) << "\nLower left easting_northing:" + << theCornerEastingNorthingPt[3] + << setw(30) << "\nCenter ground point:" + << theCenterGroundPt + << setw(30) << "\nCenter easting_northing:" + << theCenterEastingNorthingPt + << "\nMap Projection dump:"; + theProjection->print(os); + + return os; +} + +void ossimMapProjectionInfo::setPixelType (ossimPixelType type) +{ + thePixelType = type; +} + +ossimPixelType ossimMapProjectionInfo::getPixelType () const +{ + return thePixelType; +} + +void ossimMapProjectionInfo::setOutputFeetFlag (bool flag) +{ + theOutputInfoInFeetFlag = flag; +} + +bool ossimMapProjectionInfo::unitsInFeet() const +{ + return theOutputInfoInFeetFlag; +} + +ossimString ossimMapProjectionInfo::getImageInfoString () const +{ + return theImageInfoString; +} + +void ossimMapProjectionInfo::setImageInfoString (const ossimString& string) +{ + theImageInfoString = string; +} + +const ossimMapProjection* ossimMapProjectionInfo::getProjection() const +{ + return theProjection; +} + +ossimDpt ossimMapProjectionInfo::ulEastingNorthingPt( ) const +{ + if (getPixelType() == OSSIM_PIXEL_IS_AREA) + { + ossimDpt mpp = getMetersPerPixel(); + ossimDpt pt; + pt.x = theCornerEastingNorthingPt[0].x - (mpp.x / 2.0); + pt.y = theCornerEastingNorthingPt[0].y + (mpp.y / 2.0); + return pt; + } + else + { + return theCornerEastingNorthingPt[0]; + } +} + +ossimDpt ossimMapProjectionInfo::urEastingNorthingPt( ) const +{ + if (getPixelType() == OSSIM_PIXEL_IS_AREA) + { + ossimDpt mpp = getMetersPerPixel(); + ossimDpt pt; + pt.x = theCornerEastingNorthingPt[1].x + (mpp.x / 2.0); + pt.y = theCornerEastingNorthingPt[1].y + (mpp.y / 2.0); + return pt; + } + else + { + return theCornerEastingNorthingPt[1]; + } +} + +ossimDpt ossimMapProjectionInfo::lrEastingNorthingPt( ) const +{ + if (getPixelType() == OSSIM_PIXEL_IS_AREA) + { + ossimDpt mpp = getMetersPerPixel(); + ossimDpt pt; + pt.x = theCornerEastingNorthingPt[2].x + (mpp.x / 2.0); + pt.y = theCornerEastingNorthingPt[2].y - (mpp.y / 2.0); + return pt; + } + else + { + return theCornerEastingNorthingPt[2]; + } +} + +ossimDpt ossimMapProjectionInfo::llEastingNorthingPt( ) const +{ + if (getPixelType() == OSSIM_PIXEL_IS_AREA) + { + ossimDpt mpp = getMetersPerPixel(); + ossimDpt pt; + pt.x = theCornerEastingNorthingPt[3].x - (mpp.x / 2.0); + pt.y = theCornerEastingNorthingPt[3].y - (mpp.y / 2.0); + return pt; + } + else + { + return theCornerEastingNorthingPt[3]; + } +} + +ossimGpt ossimMapProjectionInfo::ulGroundPt( ) const +{ + if (getPixelType() == OSSIM_PIXEL_IS_AREA) + { + ossimDpt ddpp = getDecimalDegreesPerPixel(); + ossimGpt gpt; + gpt.latd(theCornerGroundPt[0].latd() + (ddpp.y / 2.0)); + gpt.lond(theCornerGroundPt[0].lond() - (ddpp.x / 2.0)); + return gpt; + } + else + { + return theCornerGroundPt[0]; + } +} + +ossimGpt ossimMapProjectionInfo::urGroundPt( ) const +{ + if (getPixelType() == OSSIM_PIXEL_IS_AREA) + { + ossimDpt ddpp = getDecimalDegreesPerPixel(); + ossimGpt gpt; + gpt.latd(theCornerGroundPt[1].latd() + (ddpp.y / 2.0)); + gpt.lond(theCornerGroundPt[1].lond() + (ddpp.x / 2.0)); + return gpt; + } + else + { + return theCornerGroundPt[1]; + } +} + +ossimGpt ossimMapProjectionInfo::lrGroundPt( ) const +{ + if (getPixelType() == OSSIM_PIXEL_IS_AREA) + { + ossimDpt ddpp = getDecimalDegreesPerPixel(); + ossimGpt gpt; + gpt.latd(theCornerGroundPt[2].latd() - (ddpp.y / 2.0)); + gpt.lond(theCornerGroundPt[2].lond() + (ddpp.x / 2.0)); + return gpt; + } + else + { + return theCornerGroundPt[2]; + } +} + +ossimGpt ossimMapProjectionInfo::llGroundPt( ) const +{ + if (getPixelType() == OSSIM_PIXEL_IS_AREA) + { + ossimDpt ddpp = getDecimalDegreesPerPixel(); + ossimGpt gpt; + gpt.latd(theCornerGroundPt[3].latd() - (ddpp.y / 2.0)); + gpt.lond(theCornerGroundPt[3].lond() - (ddpp.x / 2.0)); + return gpt; + } + else + { + return theCornerGroundPt[3]; + } +} + +ossimGpt ossimMapProjectionInfo::centerGroundPt( ) const +{ + // Center is simply center, no shift for pixel is area... + return theCenterGroundPt; +} + +ossimDpt ossimMapProjectionInfo::centerEastingNorthingPt() const +{ + return theCenterEastingNorthingPt; +} + +ossim_int32 ossimMapProjectionInfo::linesPerImage() const +{ + return theLinesPerImage; +} + +ossim_int32 ossimMapProjectionInfo::pixelsPerLine() const +{ + return thePixelsPerLine; +} + +bool ossimMapProjectionInfo::loadState(const ossimKeywordlist& kwl, + const char* ) +{ + const char* lookupReturn = kwl.find(README_IMAGE_STRING_KW); + + //*** + // "theImageInfoString" goes in the README file "Image:" field and can + // be used to identify the image. + //*** + if (lookupReturn) theImageInfoString = lookupReturn; + + lookupReturn = kwl.find(ossimKeywordNames::PIXEL_TYPE_KW); + + if (lookupReturn) + { + ossimString tmp = lookupReturn; + + tmp.downcase(); + + if (tmp.contains("area")) + { + thePixelType = OSSIM_PIXEL_IS_AREA; + } + else + { + thePixelType = OSSIM_PIXEL_IS_POINT; + } + } + + lookupReturn = kwl.find(OUTPUT_US_FT_INFO_KW); + + if (lookupReturn) + { + int tmp = atoi(lookupReturn); + + if (tmp) + { + theOutputInfoInFeetFlag = true; + } + else + { + theOutputInfoInFeetFlag = false; + } + } + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimMapProjectionInfo::loadState:" + << "\ntheImageInfoString: " << theImageInfoString + << "\nthePixelType: " << int(thePixelType) + << "\ntheOutputInfoInFeetFlag: " << theOutputInfoInFeetFlag + << endl; + } + + return true; +} + +bool ossimMapProjectionInfo::saveState(ossimKeywordlist& kwl, + const char* ) const +{ + kwl.add(README_IMAGE_STRING_KW, + theImageInfoString.chars()); + + ossimString tmp; + + if (thePixelType == OSSIM_PIXEL_IS_POINT) + { + tmp = "point"; + } + else + { + tmp = "area"; + } + + kwl.add(PIXEL_TYPE_KW, + tmp.chars()); + + kwl.add(OUTPUT_US_FT_INFO_KW, + int(theOutputInfoInFeetFlag)); + + return true; +} + +ossimDpt ossimMapProjectionInfo::ulEastingNorthingPtInFt() const +{ + ossimDpt pt = ulEastingNorthingPt(); + + pt.x = mtrs2usft(pt.x); + + pt.y = mtrs2usft(pt.y); + + return pt; +} + +ossimDpt ossimMapProjectionInfo::urEastingNorthingPtInFt() const +{ + ossimDpt pt = urEastingNorthingPt(); + pt.x = mtrs2usft(pt.x); + pt.y = mtrs2usft(pt.y); + return pt; +} + +ossimDpt ossimMapProjectionInfo::lrEastingNorthingPtInFt() const +{ + ossimDpt pt = lrEastingNorthingPt(); + pt.x = mtrs2usft(pt.x); + pt.y = mtrs2usft(pt.y); + return pt; +} + +ossimDpt ossimMapProjectionInfo::llEastingNorthingPtInFt() const +{ + ossimDpt pt = llEastingNorthingPt(); + pt.x = mtrs2usft(pt.x); + pt.y = mtrs2usft(pt.y); + return pt; +} + +ossimDpt ossimMapProjectionInfo::getMetersPerPixel() const +{ + return theProjection->getMetersPerPixel(); +} + +ossimDpt ossimMapProjectionInfo::getUsSurveyFeetPerPixel() const +{ + ossimDpt pt = getMetersPerPixel(); + + pt.x = mtrs2usft(pt.x); + pt.y = mtrs2usft(pt.y); + + return pt; +} + +ossimDpt ossimMapProjectionInfo::getDecimalDegreesPerPixel() const +{ + return theProjection->getDecimalDegreesPerPixel(); +} diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMapProjectionInfo.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMapProjectionInfo.h new file mode 100644 index 0000000000..719257b3a1 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMapProjectionInfo.h @@ -0,0 +1,277 @@ +//******************************************************************* +// Copyright (C) 2001 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: David Burken +// +// Description: +// Class for encapsulate projection info given a projection, datum, and +// output rectangle. +// +// NOTE: +// - Output rectangle should be relative to the center of pixels. +// Shifts will be made for "pixel is area" internally. +// +//******************************************************************* +// $Id: ossimMapProjectionInfo.h,v 1.13 2005/10/13 15:04:06 dburken Exp $ + +#ifndef ossimMapProjectionInfo_HEADER +#define ossimMapProjectionInfo_HEADER + +#include <base/common/ossimObject.h> +#include <base/common/ossimConstants.h> +#include <base/data_types/ossimGpt.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimDrect.h> + +class ossimMapProjection; +class ossimFilename; +class ossimDrect; +class ossimImageChain; + +class OSSIMDLLEXPORT ossimMapProjectionInfo : public ossimObject +{ +public: + + ossimMapProjectionInfo(const ossimMapProjection* proj, + const ossimDrect& output_rect); + + virtual ~ossimMapProjectionInfo(); + + /** + * Returns true on error false if ok. + */ + bool errorStatus() const; + + /** + * Adds tie point to keyword list. This will be latitude, longitude if + * projection is geographic; else, easting, northing. + */ + void getGeom(ossimKeywordlist& kwl, const char* prefix=NULL)const; + + /** + * Returns the pixel size in meters. + * x = sample direction + * y = line direction + */ + ossimDpt getMetersPerPixel() const; + + /** + * Returns the pixel size in U.S. Survey feet. + * x = sample direction + * y = line direction + * + * NOTE: + * The US survey feet per meter converion (0.3048006096 feet per meter) + * is NOT the same as the standard feet per meter conversion + * (0.3048 feet per meter). + */ + ossimDpt getUsSurveyFeetPerPixel() const; + + /** + * Returns the decimal degrees per pixel. + * x = sample direction + * y = line direction + */ + ossimDpt getDecimalDegreesPerPixel() const; + + /** + * Returns the upper left easting and northing as a ossimDpt. + * The easting is "u" and the northing is "v". Units are in meters. + */ + ossimDpt ulEastingNorthingPt() const; + + /** + * Returns the upper right easting and northing as a ossimDpt. + * The easting is "u" and the northing is "v". Units are in meters. + */ + ossimDpt urEastingNorthingPt() const; + + /** + * Returns the lower right easting and northing as a ossimDpt. + * The easting is "u" and the northing is "v". Units are in meters. + */ + ossimDpt lrEastingNorthingPt() const; + + /** + * Returns the lower left easting and northing as a ossimDpt. + * The easting is "u" and the northing is "v". Units are in meters. + */ + ossimDpt llEastingNorthingPt() const; + + /** + * Returns the upper left easting and northing as a ossimDpt. + * The easting is "u" and the northing is "v". + * Units are in U.S. Survey feet. + */ + ossimDpt ulEastingNorthingPtInFt() const; + + /** + * Returns the upper right easting and northing as a ossimDpt. + * The easting is "u" and the northing is "v". + * Units are in U.S. Survey feet. + */ + ossimDpt urEastingNorthingPtInFt() const; + + /** + * Returns the lower right easting and northing as a ossimDpt. + * The easting is "u" and the northing is "v". + * Units are in U.S. Survey feet. + */ + ossimDpt lrEastingNorthingPtInFt() const; + + /** + * Returns the lower left easting and northing as a ossimDpt. + * The easting is "u" and the northing is "v". + * Units are in U.S. Survey feet. + */ + ossimDpt llEastingNorthingPtInFt() const; + + /** + * Returns the upper left ground point. + */ + ossimGpt ulGroundPt() const; + + /** + * Returns the upper right ground point. + */ + ossimGpt urGroundPt() const; + + /** + * Returns the lower right ground point. + */ + ossimGpt lrGroundPt() const; + + /** + * Returns the lower left ground point. + */ + ossimGpt llGroundPt() const; + + /** + * Returns the center ground point. + */ + ossimGpt centerGroundPt() const; + + /** @return The center ground point. */ + ossimDpt centerEastingNorthingPt() const; + + /** @return The lines per image. */ + ossim_int32 linesPerImage() const; + + /** @return The pixels per line (samples). */ + ossim_int32 pixelsPerLine() const; + + /** + * Formatted print of data members. Used by operator <<. + */ + std::ostream& print(std::ostream& os) const; + + /** + * Sets the data member "thePixelType". + * NOTE: + * PIXEL_IS_POINT (ennumerated to a "0"): + * Corner coordinates are relative to the center of pixel. + * PIXEL_IS_AREA (ennumerated to a "1"): + * Corner coordinates are relative to the outer edge of the pixel. + */ + void setPixelType (ossimPixelType type); + + /** + * Returns data member "thePixelType". + * NOTE: + * OSSIM_PIXEL_IS_POINT (ennumerated to a "0"): + * Corner coordinates are relative to the center of pixel. + * OSSIM_PIXEL_IS_AREA (ennumerated to a "1"): + * Corner coordinates are relative to the outer of the pixel. + */ + ossimPixelType getPixelType () const; + + /** + * Sets the data member "theOutputInfoInFeetFlag". + */ + void setOutputFeetFlag (bool flag); + + /** + * Returns the data member "theOutputInfoInFeetFlag". + * True = feet, false = meters. + */ + bool unitsInFeet() const; + + /** + * Returns theImageInfoString. + */ + ossimString getImageInfoString () const; + + /** + * Used to set data member "theImageInfoString". This will be output + * in the "Image: " field of the README file. + */ + void setImageInfoString (const ossimString& string); + + /** + * Returns reference to "theProjection". + */ + const ossimMapProjection* getProjection() const; + + //**** + // Keywords for getStateFrom/saveStateTo. + //*** + static const char* README_IMAGE_STRING_KW; + static const char* PIXEL_TYPE_KW; + static const char* OUTPUT_US_FT_INFO_KW; + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix = 0); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix = 0) const; + +private: + + // Do not permit construction with void args. + ossimMapProjectionInfo(); + ossimMapProjectionInfo& operator=(const ossimMapProjectionInfo&); + + void initializeMembers(const ossimDrect& output_rect); + + const ossimMapProjection* theProjection; + mutable bool theErrorStatus; + int theLinesPerImage; + int thePixelsPerLine; + ossimGpt theCornerGroundPt[4]; + ossimDpt theCornerEastingNorthingPt[4]; + ossimGpt theCenterGroundPt; + ossimDpt theCenterEastingNorthingPt; + ossimDrect theBoundingRect; + + /** + * "thePixelType" defines whether the tie point coordinates are + * relative to the center of the pixel(which is PIXEL_IS_POINT) or + * the upper left corner of the pixel(PIXEL_IS_AREA). The default + * pixle type is PIXEL_IS_POINT. + */ + ossimPixelType thePixelType; + + /** + * If "theOutputInfoInFeetFlag" is true the readme file tie point + * info will be output in both meters and U.S. feet. + * NOTE: + * U.S. feet conversion is "meters/0.3048006096" not the standard + * "meters/0.3048". + * Reference for U.S. feet value: + * U.S.G.S. "Map Projections - A Working Manual" USGS Professional + * paper 1395 page 51. + */ + bool theOutputInfoInFeetFlag; + + /** + * "theImageInfoString" goes in the README file "Image:" field + * to identify the image. + */ + ossimString theImageInfoString; +}; + +#endif /* End of #ifndef ossimMapProjectionInfo_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMercatorProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMercatorProjection.cpp new file mode 100644 index 0000000000..8d4c09a8d2 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMercatorProjection.cpp @@ -0,0 +1,462 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Mercator projection code. +//******************************************************************* +// $Id: ossimMercatorProjection.cpp,v 1.10 2004/01/08 21:49:21 jlargent Exp $ + +#include <math.h> +#include "ossimMercatorProjection.h" +#include "base/common/ossimKeywordNames.h" + +RTTI_DEF1(ossimMercatorProjection, "ossimMercatorProjection", ossimMapProjection) +/***************************************************************************/ +/* + * DEFINES + */ + +#define PI 3.14159265358979323e0 /* PI */ +#define PI_OVER_2 ( PI / 2.0e0) +#define MAX_LAT ( (PI * 89.5) / 180.0 ) /* 89.5 degrees in radians */ + +#define MERC_NO_ERROR 0x0000 +#define MERC_LAT_ERROR 0x0001 +#define MERC_LON_ERROR 0x0002 +#define MERC_EASTING_ERROR 0x0004 +#define MERC_NORTHING_ERROR 0x0008 +#define MERC_ORIGIN_LAT_ERROR 0x0010 +#define MERC_CENT_MER_ERROR 0x0020 +#define MERC_A_ERROR 0x0040 +#define MERC_B_ERROR 0x0080 +#define MERC_A_LESS_B_ERROR 0x0100 + +ossimMercatorProjection::ossimMercatorProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + :ossimMapProjection(ellipsoid, origin) +{ + setDefaults(); + update(); +} + +ossimMercatorProjection::ossimMercatorProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double falseEasting, + double falseNorthing, + double scaleFactor) + :ossimMapProjection(ellipsoid, origin) +{ + Merc_False_Easting = falseEasting; + Merc_False_Northing = falseNorthing; + Merc_Scale_Factor = scaleFactor; + Merc_Delta_Easting = 20237883.0; + Merc_Delta_Northing = 23421740.0; + + update(); +} + +void ossimMercatorProjection::update() +{ + + Set_Mercator_Parameters(theEllipsoid.getA(), + theEllipsoid.getFlattening(), + theOrigin.latr(), + theOrigin.lonr(), + Merc_False_Easting, + Merc_False_Northing, + &Merc_Scale_Factor); + + ossimMapProjection::update(); +} + +void ossimMercatorProjection::setFalseEasting(double falseEasting) +{ + Merc_False_Easting = falseEasting; + update(); +} + +void ossimMercatorProjection::setFalseNorthing(double falseNorthing) +{ + Merc_False_Northing = falseNorthing; + update(); +} + +void ossimMercatorProjection::setScaleFactor(double scaleFactor) +{ + Merc_Scale_Factor = scaleFactor; + update(); +} + +void ossimMercatorProjection::setFalseEastingNorthing(double falseEasting, + double falseNorthing) +{ + Merc_False_Easting = falseEasting; + Merc_False_Northing = falseNorthing; + update(); +} + +void ossimMercatorProjection::setParameters(double falseEasting, + double falseNorthing, + double scaleFactor) +{ + Merc_False_Easting = falseEasting; + Merc_False_Northing = falseNorthing; + Merc_Scale_Factor = scaleFactor; + + update(); +} + +void ossimMercatorProjection::setDefaults() +{ + Merc_Delta_Easting = 20237883.0; + Merc_Delta_Northing = 23421740.0; + Merc_Scale_Factor = 1.0; +} + +ossimGpt ossimMercatorProjection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat = 0.0; + double lon = 0.0; + + Convert_Mercator_To_Geodetic(eastingNorthing.x, + eastingNorthing.y, + &lat, + &lon); + + return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum); +} + +ossimDpt ossimMercatorProjection::forward(const ossimGpt &latLon)const +{ + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + Convert_Geodetic_To_Mercator(gpt.latr(), + gpt.lonr(), + &easting, + &northing); + + return ossimDpt(easting, northing); +} + + +bool ossimMercatorProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const +{ + kwl.add(prefix, + ossimKeywordNames::FALSE_EASTING_KW, + Merc_False_Easting, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_NORTHING_KW, + Merc_False_Northing, + true); + + kwl.add(prefix, + ossimKeywordNames::SCALE_FACTOR_KW, + Merc_Scale_Factor, + true); + + return ossimMapProjection::saveState(kwl, prefix); +} + +bool ossimMercatorProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + bool flag = ossimMapProjection::loadState(kwl, prefix); + + const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + const char* falseEasting = kwl.find(prefix, ossimKeywordNames::FALSE_EASTING_KW); + const char* falseNorthing = kwl.find(prefix, ossimKeywordNames::FALSE_NORTHING_KW); + const char* scaleFactor = kwl.find(prefix, ossimKeywordNames::SCALE_FACTOR_KW); + + setDefaults(); + if(ossimString(type) == STATIC_TYPE_NAME(ossimMercatorProjection)) + { + if(falseEasting) + { + Merc_False_Easting = ossimString(falseEasting).toDouble(); + } + if(falseNorthing) + { + Merc_False_Northing = ossimString(falseNorthing).toDouble(); + } + if(scaleFactor) + { + Merc_Scale_Factor = ossimString(scaleFactor).toDouble(); + } + } + update(); + + return flag; +} + + +/***************************************************************************/ +/* + * FUNCTIONS + */ + + +long ossimMercatorProjection::Set_Mercator_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing, + double *Scale_Factor) +{ /* BEGIN Set_Mercator_Parameters */ +/* + * The function Set_Mercator_Parameters receives the ellipsoid parameters and + * Mercator projection parameters as inputs, and sets the corresponding state + * variables. It calculates and returns the scale factor. If any errors + * occur, the error code(s) are returned by the function, otherwise Merc_NO_ERROR + * is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at which the (input) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + * Scale_Factor : Multiplier which reduces distances in the + * projection to the actual distance on the + * ellipsoid (output) + */ + + double es2; /* Eccentricity squared of ellipsoid to the second power */ + double es3; /* Eccentricity squared of ellipsoid to the third power */ + double es4; /* Eccentricity squared of ellipsoid to the fourth power */ + double sin_olat; /* sin(Origin_Latitude), temp variable */ +// double inv_f = 1 / f; + long Error_Code = MERC_NO_ERROR; + +// if (a <= 0.0) +// { /* Semi-major axis must be greater than zero */ +// Error_Code |= MERC_A_ERROR; +// } +// if ((inv_f < 250) || (inv_f > 350)) +// { /* Inverse flattening must be between 250 and 350 */ +// Error_Code |= MERC_INV_F_ERROR; +// } +// if ((Origin_Latitude < -MAX_LAT) || (Origin_Latitude > MAX_LAT)) +// { /* origin latitude out of range */ +// Error_Code |= MERC_ORIGIN_LAT_ERROR; +// } +// if ((Central_Meridian < -PI) || (Central_Meridian > (2*PI))) +// { /* origin longitude out of range */ +// Error_Code |= MERC_CENT_MER_ERROR; +// } + if (!Error_Code) + { /* no errors */ + Merc_a = a; + Merc_f = f; + Merc_Origin_Lat = Origin_Latitude; +// if (Central_Meridian > PI) +// Central_Meridian -= (2*PI); + Merc_Origin_Long = Central_Meridian; + Merc_False_Northing = False_Northing; + Merc_False_Easting = False_Easting; + Merc_es = 2 * Merc_f - Merc_f * Merc_f; + Merc_e = sqrt(Merc_es); + sin_olat = sin(Origin_Latitude); + Merc_Scale_Factor = 1.0 / ( sqrt(1.e0 - Merc_es * sin_olat * sin_olat) + / cos(Origin_Latitude) ); + es2 = Merc_es * Merc_es; + es3 = es2 * Merc_es; + es4 = es3 * Merc_es; + Merc_ab = Merc_es / 2.e0 + 5.e0 * es2 / 24.e0 + es3 / 12.e0 + + 13.e0 * es4 / 360.e0; + Merc_bb = 7.e0 * es2 / 48.e0 + 29.e0 * es3 / 240.e0 + + 811.e0 * es4 / 11520.e0; + Merc_cb = 7.e0 * es3 / 120.e0 + 81.e0 * es4 / 1120.e0; + Merc_db = 4279.e0 * es4 / 161280.e0; + *Scale_Factor = Merc_Scale_Factor; + Convert_Geodetic_To_Mercator( MAX_LAT, (Merc_Origin_Long + PI), + &Merc_Delta_Easting, &Merc_Delta_Northing); + if (Merc_Delta_Easting < 0) + Merc_Delta_Easting = -Merc_Delta_Easting; + Merc_Delta_Easting *= 1.01; + Merc_Delta_Easting -= Merc_False_Easting; + Merc_Delta_Northing *= 1.01; + Merc_Delta_Northing -= Merc_False_Northing; + } /* END OF if(!Error_Code) */ + return (Error_Code); +} /* END OF Set_Mercator_Parameters */ + + +void ossimMercatorProjection::Get_Mercator_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *False_Easting, + double *False_Northing, + double *Scale_Factor)const +{ /* BEGIN Get_Mercator_Parameters */ +/* + * The function Get_Mercator_Parameters returns the current ellipsoid + * parameters, Mercator projection parameters, and scale factor. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at which the (output) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + * Scale_Factor : Multiplier which reduces distances in the + * projection to the actual distance on the + * ellipsoid (output) + */ + + *a = Merc_a; + *f = Merc_f; + *Origin_Latitude = Merc_Origin_Lat; + *Central_Meridian = Merc_Origin_Long; + *False_Easting = Merc_False_Easting; + *False_Northing = Merc_False_Northing; + *Scale_Factor = Merc_Scale_Factor; + + return; +} /* END OF Get_Mercator_Parameters */ + + +long ossimMercatorProjection::Convert_Geodetic_To_Mercator (double Latitude, + double Longitude, + double *Easting, + double *Northing)const +{ /* BEGIN Convert_Geodetic_To_Mercator */ +/* + * The function Convert_Geodetic_To_Mercator converts geodetic (latitude and + * longitude) coordinates to Mercator projection (easting and northing) + * coordinates, according to the current ellipsoid and Mercator projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise MERC_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + + double ctanz2; /* Cotangent of z/2 - z - Isometric colatitude */ + double e_x_sinlat; /* e * sin(Latitude) */ + double Delta_Long; /* Difference in origin longitude and longitude */ + double tan_temp; + double pow_temp; + + long Error_Code = MERC_NO_ERROR; + +// if ((Latitude < -MAX_LAT) || (Latitude > MAX_LAT)) +// { /* Latitude out of range */ +// Error_Code |= MERC_LAT_ERROR; +// } +// if ((Longitude < -PI) || (Longitude > (2*PI))) +// { /* Longitude out of range */ +// Error_Code |= MERC_LON_ERROR; +// } + if (!Error_Code) + { /* no errors */ + if (Longitude > PI) + Longitude -= (2*PI); + e_x_sinlat = Merc_e * sin(Latitude); + tan_temp = tan(PI / 4.e0 + Latitude / 2.e0); + pow_temp = pow( ((1.e0 - e_x_sinlat) / (1.e0 + e_x_sinlat)), + (Merc_e / 2.e0) ); + ctanz2 = tan_temp * pow_temp; + *Northing = Merc_Scale_Factor * Merc_a * log(ctanz2) + Merc_False_Northing; + Delta_Long = Longitude - Merc_Origin_Long; +// if (Delta_Long > PI) +// Delta_Long -= (2 * PI); +// if (Delta_Long < -PI) +// Delta_Long += (2 * PI); + *Easting = Merc_Scale_Factor * Merc_a * Delta_Long + + Merc_False_Easting; + } + return (Error_Code); +} /* END OF Convert_Geodetic_To_Mercator */ + + +long ossimMercatorProjection::Convert_Mercator_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const +{ /* BEGIN Convert_Mercator_To_Geodetic */ +/* + * The function Convert_Mercator_To_Geodetic converts Mercator projection + * (easting and northing) coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Mercator projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise MERC_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + + double dx; /* Delta easting - Difference in easting (easting-FE) */ + double dy; /* Delta northing - Difference in northing (northing-FN) */ + double xphi; /* Isometric latitude */ + long Error_Code = MERC_NO_ERROR; + +// if ((Easting < (Merc_False_Easting - Merc_Delta_Easting)) +// || (Easting > (Merc_False_Easting + Merc_Delta_Easting))) +// { /* Easting out of range */ +// Error_Code |= MERC_EASTING_ERROR; +// } +// if ((Northing < (Merc_False_Northing - Merc_Delta_Northing)) +// || (Northing > (Merc_False_Northing + Merc_Delta_Northing))) +// { /* Northing out of range */ +// Error_Code |= MERC_NORTHING_ERROR; +// } + if (!Error_Code) + { /* no errors */ + dy = Northing - Merc_False_Northing; + dx = Easting - Merc_False_Easting; + *Longitude = Merc_Origin_Long + dx / (Merc_Scale_Factor * Merc_a); + xphi = PI / 2.e0 + - 2.e0 * atan(1.e0 / exp(dy / (Merc_Scale_Factor * Merc_a))); + *Latitude = xphi + Merc_ab * sin(2.e0 * xphi) + Merc_bb * sin(4.e0 * xphi) + + Merc_cb * sin(6.e0 * xphi) + Merc_db * sin(8.e0 * xphi); +// if (*Longitude > PI) +// *Longitude -= (2 * PI); +// if (*Longitude < -PI) +// *Longitude += (2 * PI); + } + return (Error_Code); +} /* END OF Convert_Mercator_To_Geodetic */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMercatorProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMercatorProjection.h new file mode 100644 index 0000000000..b702ff257c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMercatorProjection.h @@ -0,0 +1,224 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Mercator projection code. +//******************************************************************* +// $Id: ossimMercatorProjection.h,v 1.5 2005/09/09 19:23:58 gpotts Exp $ + +#ifndef ossimMercatorProjection_HEADER +#define ossimMercatorProjection_HEADER + +#include "ossimMapProjection.h" + +class ossimMercatorProjection : public ossimMapProjection +{ +public: + + ossimMercatorProjection(const ossimEllipsoid& ellipsoid = ossimEllipsoid(), + const ossimGpt& origin = ossimGpt()); + + ossimMercatorProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double falseEasting, + double falseNorthing, + double scaleFactor); + ~ossimMercatorProjection(){} + virtual ossimObject *dup()const{return new ossimMercatorProjection(*this);} + + virtual ossimGpt inverse(const ossimDpt &eastingNorthing)const; + virtual ossimDpt forward(const ossimGpt &latLon)const; + virtual void update(); + /*! + * SetFalseEasting. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEasting(double falseEasting); + + /*! + * SetFalseNorthing. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseNorthing(double falseNorthing); + + /*! + * Sets both false easting and northing values. The values are + * expected to be in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEastingNorthing(double falseEasting, double falseNorthing); + + /*! + * sets the scale. + */ + void setScaleFactor(double scaleFactor); + + /*! + * Allows one to set all parameters for this projections. parallels are in + * degrees and easting northings are in meters. + * Update is then called so we can pre-compute paramters. + */ + void setParameters(double falseEasting, + double falseNorthing, + double scaleFactor); + void setDefaults(); + + double getFalseEasting()const{return Merc_False_Easting;} + double getFalseNorthing()const{return Merc_False_Northing;} + double getScaleFactor()const{return Merc_Scale_Factor;} + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +private: + //_________________GEOTRANS STUFF____________________________ + + mutable double Merc_a; /* Semi-major axis of ellipsoid in meters */ + mutable double Merc_f; /* Flattening of ellipsoid */ + mutable double Merc_e; /* Eccentricity of ellipsoid */ + mutable double Merc_es; /* Eccentricity squared */ + +/* Mercator projection Parameters */ + mutable double Merc_Origin_Lat; /* Latitude of origin in radians */ + mutable double Merc_Origin_Long; /* Longitude of origin in radians */ + mutable double Merc_False_Northing; /* False northing in meters */ + mutable double Merc_False_Easting; /* False easting in meters */ + mutable double Merc_Scale_Factor; /* Scale factor */ + +/* Isometric to geodetic latitude parameters, default to WGS 84 */ + mutable double Merc_ab; + mutable double Merc_bb; + mutable double Merc_cb; + mutable double Merc_db; + +/* Maximum variance for easting and northing values for WGS 84. + */ + mutable double Merc_Delta_Easting; + mutable double Merc_Delta_Northing; + + +/*! + * The function Set_Mercator_Parameters receives the ellipsoid parameters and + * Mercator projcetion parameters as inputs, and sets the corresponding state + * variables. It calculates and returns the scale factor. If any errors + * occur, the error code(s) are returned by the function, otherwise + * MERC_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at which the (input) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + * Scale_Factor : Multiplier which reduces distances in the + * projection to the actual distance on the + * ellipsoid (output) + */ + long Set_Mercator_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing, + double *Scale_Factor); + + +/*! + * The function Get_Mercator_Parameters returns the current ellipsoid + * parameters, Mercator projection parameters, and scale factor. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at which the (output) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + * Scale_Factor : Multiplier which reduces distances in the + * projection to the actual distance on the + * ellipsoid (output) + */ + void Get_Mercator_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *False_Easting, + double *False_Northing, + double *Scale_Factor)const; + + +/*! + * The function Convert_Geodetic_To_Mercator converts geodetic (latitude and + * longitude) coordinates to Mercator projection easting, and northing + * coordinates, according to the current ellipsoid and Mercator projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise MERC_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + long Convert_Geodetic_To_Mercator (double Latitude, + double Longitude, + double *Easting, + double *Northing)const; + + +/*! + * The function Convert_Mercator_To_Geodetic converts Mercator projection + * easting and northing coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Mercator projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise MERC_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + long Convert_Mercator_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMgrs.c b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMgrs.c new file mode 100644 index 0000000000..6516908346 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMgrs.c @@ -0,0 +1,1325 @@ +/***************************************************************************/ +/* RSC IDENTIFIER: MGRS + * + * ABSTRACT + * + * This component converts between geodetic coordinates (latitude and + * longitude) and Military Grid Reference System (MGRS) coordinates. + * + * ERROR HANDLING + * + * This component checks parameters for valid values. If an invalid value + * is found, the error code is combined with the current error code using + * the bitwise or. This combining allows multiple error codes to be + * returned. The possible error codes are: + * + * MGRS_NO_ERROR : No errors occurred in function + * MGRS_LAT_ERROR : Latitude outside of valid range + * (-90 to 90 degrees) + * MGRS_LON_ERROR : Longitude outside of valid range + * (-180 to 360 degrees) + * MGRS_STR_ERROR : An MGRS string error: string too long, + * too short, or badly formed + * MGRS_PRECISION_ERROR : The precision must be between 0 and 5 + * inclusive. + * MGRS_A_ERROR : Semi-major axis less than or equal to zero + * MGRS_INV_F_ERROR : Inverse flattening outside of valid range + * (250 to 350) + * MGRS_EASTING_ERROR : Easting outside of valid range + * (100,000 to 900,000 meters for UTM) + * (0 to 4,000,000 meters for UPS) + * MGRS_NORTHING_ERROR : Northing outside of valid range + * (0 to 10,000,000 meters for UTM) + * (0 to 4,000,000 meters for UPS) + * MGRS_ZONE_ERROR : Zone outside of valid range (1 to 60) + * MGRS_HEMISPHERE_ERROR : Invalid hemisphere ('N' or 'S') + * + * REUSE NOTES + * + * MGRS is intended for reuse by any application that does conversions + * between geodetic coordinates and MGRS coordinates. + * + * REFERENCES + * + * Further information on MGRS can be found in the Reuse Manual. + * + * MGRS originated from : U.S. Army Topographic Engineering Center + * Geospatial Information Division + * 7701 Telegraph Road + * Alexandria, VA 22310-3864 + * + * LICENSES + * + * None apply to this component. + * + * RESTRICTIONS + * + * + * ENVIRONMENT + * + * MGRS was tested and certified in the following environments: + * + * 1. Solaris 2.5 with GCC version 2.8.1 + * 2. Windows 95 with MS Visual C++ version 6 + * + * MODIFICATIONS + * + * Date Description + * ---- ----------- + * 16-11-94 Original Code + * 15-09-99 Reengineered upper layers + * + */ + + +/***************************************************************************/ +/* + * INCLUDES + */ +#include <ctype.h> +#include <math.h> +#include <stdio.h> +#include <string.h> +#include "ossimUps.h" +#include "ossimUtm.h" +#include "ossimMgrs.h" + +/* + * ctype.h - Standard C character handling library + * math.h - Standard C math library + * stdio.h - Standard C input/output library + * string.h - Standard C string handling library + * ups.h - Universal Polar Stereographic (UPS) projection + * utm.h - Universal Transverse Mercator (UTM) projection + * mgrs.h - function prototype error checking + */ + + +/***************************************************************************/ +/* + * GLOBAL DECLARATIONS + */ +#define DEGRAD 0.017453292519943295 /* PI/180 */ +#define R3 0.052359877559829890 /* RADIANS FOR 3 DEGREES */ +#define R8 0.139626340159546400 /* RADIANS FOR 8 DEGREES */ +#define R9 0.157079632679489700 /* RADIANS FOR 9 DEGREES */ +#define R21 0.366519142918809200 /* RADIANS FOR 21 DEGREES */ +#define R33 0.575958653158128800 /* RADIANS FOR 33 DEGREES */ +#define R56 0.977384381116824600 /* RADIANS FOR 56 DEGREES */ +#define R64 1.117010721276371000 /* RADIANS FOR 64 DEGREES */ +#define R72 1.256637061435917000 /* RADIANS FOR 72 DEGREES */ +#define R80 1.396263401595464000 /* RADIANS FOR 80 DEGREES */ +#define UPS_SOUTH 3 /* UPS COORDINATE IN SOUTHERN HEMISPHERE */ +#define UPS_NORTH 2 /* UPS COORDINATE IN NORTHERN HEMISPHERE */ +#define UTM 1 /* UTM COORDINATE */ +#define ALBET "ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* ALPHABET */ +#define LETTER_A 0 /* ARRAY INDEX FOR LETTER A */ +#define LETTER_B 1 /* ARRAY INDEX FOR LETTER B */ +#define LETTER_C 2 /* ARRAY INDEX FOR LETTER C */ +#define LETTER_D 3 /* ARRAY INDEX FOR LETTER D */ +#define LETTER_E 4 /* ARRAY INDEX FOR LETTER E */ +#define LETTER_H 7 /* ARRAY INDEX FOR LETTER H */ +#define LETTER_I 8 /* ARRAY INDEX FOR LETTER I */ +#define LETTER_J 9 /* ARRAY INDEX FOR LETTER J */ +#define LETTER_L 11 /* ARRAY INDEX FOR LETTER L */ +#define LETTER_M 12 /* ARRAY INDEX FOR LETTER M */ +#define LETTER_N 13 /* ARRAY INDEX FOR LETTER N */ +#define LETTER_O 14 /* ARRAY INDEX FOR LETTER O */ +#define LETTER_P 15 /* ARRAY INDEX FOR LETTER P */ +#define LETTER_Q 16 /* ARRAY INDEX FOR LETTER Q */ +#define LETTER_R 17 /* ARRAY INDEX FOR LETTER R */ +#define LETTER_S 18 /* ARRAY INDEX FOR LETTER S */ +#define LETTER_U 20 /* ARRAY INDEX FOR LETTER U */ +#define LETTER_V 21 /* ARRAY INDEX FOR LETTER V */ +#define LETTER_W 22 /* ARRAY INDEX FOR LETTER W */ +#define LETTER_X 23 /* ARRAY INDEX FOR LETTER X */ +#define LETTER_Y 24 /* ARRAY INDEX FOR LETTER Y */ +#define LETTER_Z 25 /* ARRAY INDEX FOR LETTER Z */ +#define RND1 0.1e0 /* ROUND TO NEAREST .1 */ +#define RND5 0.5e0 /* ROUND TO NEAREST .5 */ +#define EOLN '\0' /* END OF STRING CHARACTER */ +#define BLANK ' ' /* BLANK CHARACTER */ +#define OSSIM_MGRS_LETTERS 3 /* NUMBER OF LETTERS IN MGRS */ +#define NUM_OFFSET 48 /* USED TO CONVERT NUMBERS TO LETTERS */ +#define ONEHT 100000.e0 /* ONE HUNDRED THOUSAND */ +#define TWOMIL 2000000.e0 /* TWO MILLION */ +#define EIGHT 800000.e0 /* EIGHT HUNDRED THOUSAND */ +#define ONE3HT 1300000.e0 /* ONE MILLION THREE HUNDRED THOUSAND */ +#define ZERO 0.e0 /* ZERO */ +#define TEN 10.e0 /* TEN */ +#define TRUE 1 /* CONSTANT VALUE FOR TRUE VALUE */ +#define FALSE 0 /* CONSTANT VALUE FOR FALSE VALUE */ +#define PI 3.14159265358979323e0 /* PI */ +#define PI_OVER_2 (PI / 2.0e0) +#define NUM "01234567890" /* NUMBERS */ +#define MAXALBET 25 /* LAST INDEX IN ALPHABET ARRAY(0-25) */ +#define MAXNUMBER 10 /* LAST INDEX IN NUMBER ARRAY(0-9) */ +#define OSSIM_MGRS_ZONE_AND_LETTERS 5 /* NUM. OF CHARS. IN ZONE AND LETTERS */ +#define OSSIM_MGRS_MINIMUM 9 /* MINIMUM NUMBER OF CHARS FOR MGRS */ +#define OSSIM_MGRS_MAXIMUM 15 /* MAXIMUM NUMBER OF CHARS FOR MGRS */ + +#define MIN_EASTING 100000 +#define MAX_EASTING 900000 +#define MIN_NORTHING 0 +#define MAX_NORTHING 10000000 +#define MAX_PRECISION 5 /* Maximum precision of easting & northing */ +#define MIN_UTM_LAT ( (-80 * PI) / 180.0 ) /* -80 degrees in radians */ +#define MAX_UTM_LAT ( (84 * PI) / 180.0 ) /* 84 degrees in radians */ + +#define MIN_EAST_NORTH 0 +#define MAX_EAST_NORTH 4000000 + +/* Ellipsoid parameters, default to WGS 84 */ +double OSSIM_MGRS_a = 6378137.0; /* Semi-major axis of ellipsoid in meters */ +double OSSIM_MGRS_f = 1 / 298.257223563; /* Flattening of ellipsoid */ +double OSSIM_MGRS_recpf = 298.257223563; +char OSSIM_MGRS_Ellipsoid_Code[3] = {'W','E',0}; + +const char* OSSIM_CLARKE_1866 = "CC"; +const char* OSSIM_CLARKE_1880 = "CD"; +const char* OSSIM_BESSEL_1841 = "BR"; +/* + * OSSIM_CLARKE_1866 : Ellipsoid code for OSSIM_CLARKE_1866 + * OSSIM_CLARKE_1880 : Ellipsoid code for OSSIM_CLARKE_1880 + * OSSIM_BESSEL_1841 : Ellipsoid code for OSSIM_BESSEL_1841 + */ + + +/***************************************************************************/ +/* + * FUNCTIONS + */ + + +void UTMSET (long izone, + long* ltrlow, + long* ltrhi, + double *fnltr) +{ /* BEGIN UTMSET */ + /* + * izone : Zone number + * ltrlow : 2nd letter low number + * ltrhi : 2nd letter high number + * fnltr : False northing + */ + long iset; /* Set number (1-6) based on UTM zone number */ + long igroup; /* Group number (1-2) based on ellipsoid code and zone */ + iset = 1; + while (((izone-iset) / 6) * 6 + iset != izone) + { + iset = iset +1; + if (iset > 6) + { + return; + } + } + igroup = 1; + if (!strcmp(OSSIM_MGRS_Ellipsoid_Code,OSSIM_CLARKE_1866) || !strcmp(OSSIM_MGRS_Ellipsoid_Code, OSSIM_CLARKE_1880) || !strcmp(OSSIM_MGRS_Ellipsoid_Code,OSSIM_BESSEL_1841)) + { + igroup = 2; + } + else if (!strcmp(OSSIM_MGRS_Ellipsoid_Code, OSSIM_CLARKE_1866) && (izone >= 47) && (izone <= 55 )) + { + igroup = 1; + } + if ((iset == 1) || (iset == 4)) + { + *ltrlow = LETTER_A; + *ltrhi = LETTER_H; + } + else if ((iset == 2) || (iset == 5)) + { + *ltrlow = LETTER_J; + *ltrhi = LETTER_R; + } + else if ((iset == 3) || (iset == 6)) + { + *ltrlow = LETTER_S; + *ltrhi = LETTER_Z; + } + if (igroup == 1) + { + *fnltr = ZERO; + if ((iset % 2) == 0) + { + *fnltr = 1500000.e0; + } + } + else if (igroup == 2) + { + *fnltr = 1000000.0e0; + if ((iset % 2) == 0) + { + *fnltr = 500000.e0; + } + } + return; +} /* END OF UTMSET */ + + +void UTMLIM (long* n, + double sphi, + long izone, + double *spsou, + double *spnor, + double *sleast, + double *slwest) +{ /* BEGIN UTMLIM */ + /* + * n : 1st letter number for MGRS + * sphi : Latitude in radians + * izone : Zone number + * spsou : South latitude limit + * spnor : North latitude limit + * sleast : East longitude limit + * slwest : West longitude limit + */ + double slcm; /* Central meridian - Longitude of origin */ + double temp; /* Temporary variable */ + long icm; /* Central meridian */ + long isphi; /* South latitude limit */ + if (*n <= LETTER_A) + { + temp = ((sphi + R80) / (R8)) + 2; + temp = temp + .00000001; + *n = (long)temp; + if (*n > LETTER_H) + { + *n = *n + 1; + } + if (*n > LETTER_N) + { + *n = *n + 1; + } + if (*n >= LETTER_Y) + { + *n = LETTER_X; + } + if ((*n == LETTER_M) && (sphi == ZERO )) + { + *n = LETTER_N; + } + isphi = (*n - 3) * 8 - 80; + } + else + { + isphi = (*n - 3) * 8 - 80; + *n = *n - 1; + } + if (*n > LETTER_H) + { + isphi = isphi - 8; + } + if (*n > LETTER_N) + { + isphi = isphi - 8; + } + *spsou = (double)(isphi) * DEGRAD; + *spnor = *spsou + R8; + if (*n == LETTER_X) + { + *spnor = *spsou + 12.e0 * DEGRAD; + } + icm = izone * 6 - 183; + slcm = (double) icm * DEGRAD; + *sleast = slcm + R3; + *slwest = slcm - R3; + if ((izone < 31) || (izone > 37)) + { + return; + } + if (*n < LETTER_V) + { + return; + } + if ((*n == LETTER_V) && (izone == 31)) + { + *sleast = R3; + } + if ((*n == LETTER_V) && (izone == 32)) + { + *slwest = R3; + } + if (*n < LETTER_X) + { + return; + } + if (izone == 31) + { + *sleast = R9; + } + if (izone == 33) + { + *slwest = R9; + *sleast = R21; + } + if (izone == 35) + { + *slwest = R21; + *sleast = R33; + } + if (izone == 37) + { + *slwest = R33; + } + return; +} /* END OF UTMLIM */ + + +void UTMOSSIM_MGRS (long izone, + long* ltrnum, + double sphi, + double x, + double y) +{ /* BEGIN UTMMGRS */ + /* + * izone : Zone number. + * ltrnum : Values of letters in the MGRS coordinate. + * sphi : Latitude in radians. + * x : Easting. + * y : Northing. + * + * UTMMGRS CALLS THE FOLLOWING ROUTINES: + * + * GPTUTM + * UTMLIM + * UTMSET + */ + double fnltr; /* False northing for 3rd letter */ + double slcm; /* Central meridian - longitude of origin */ + double sleast; /* Longitude east limit - UTM */ + double slwest; /* Longitude west limit -UTM */ + double spnor; /* MGRS north latitude limits based on 1st letter */ + double spsou; /* MGRS south latitude limits based on 1st letter */ + double xltr; /* Easting used to derive 2nd letter of MGRS */ + double yltr; /* Northing used to derive 3rd letter of MGRS */ + long ltrlow; /* 2nd letter range - low number */ + long ltrhi; /* 2nd letter range - high number */ + char hemisphere; + + UTMSET(izone, <rlow, <rhi, &fnltr); + ltrnum[0] = LETTER_A; + UTMLIM(<rnum[0], sphi, izone, &spsou, &spnor, &sleast, &slwest); + slcm = (double)(izone * 6 - 183) * DEGRAD; + /* + GPTUTM(a, recf, spsou, slcm, &izone, &yltr, &xltr, (long)1); + */ + Set_UTM_Parameters(OSSIM_MGRS_a,OSSIM_MGRS_f,izone); + Convert_Geodetic_To_UTM(spsou,slcm,&izone,&hemisphere,&xltr,&yltr); + + yltr = (double)((long)(y + RND5)); + if (((double)((long)(yltr + RND5))) == ((double)((long)(1.e7 + RND5)))) + { + yltr = (double)((long)(yltr - 1.e0 + RND5)); + } + while (yltr >= TWOMIL) + { + yltr = yltr - TWOMIL; + } + yltr = yltr - fnltr; + if (yltr < ZERO) + { + yltr = yltr + TWOMIL; + } + ltrnum[2] = (long)((yltr + RND1) / ONEHT); + if (ltrnum[2] > LETTER_H) + { + ltrnum[2] = ltrnum[2] + 1; + } + if (ltrnum[2] > LETTER_N) + { + ltrnum[2] = ltrnum[2] + 1; + } + xltr = (double)((long)(x)); + if (((ltrnum[0] == LETTER_V) && (izone == 31)) && + (((double)((long)(xltr + RND5))) == ((double)((long)(5.e5 + RND5))))) + { + xltr = (double)((long)(xltr - 1.e0 + RND5)); /* SUBTRACT 1 METER */ + } + ltrnum[1] = ltrlow + ((long)((xltr + RND1) / ONEHT) -1); + if ((ltrlow == LETTER_J) && (ltrnum[1] > LETTER_N)) + { + ltrnum[1] = ltrnum[1] + 1; + } + return; +} /* END UTMMGRS */ + + +void UPSSET (long n, + long* ltrlow, + long* ltrhi, + double *feltr, + double *fnltr, + long* ltrhy) +{ /* BEGIN UPSSET */ + /* + * n : Value of 1st letter in MGRS coordinate. + * ltrlow : Low number for 2nd letter. + * ltrhi : High number for 2nd letter. + * feltr : False easting. + * fnltr : False northing. + * ltrhy : High number for 3rd letter. + */ + if (n == LETTER_Z) /* EASTERN HEMISPHERE-NORTH ZONE */ + { + *ltrlow = LETTER_A; + *ltrhi = LETTER_J; + *feltr = TWOMIL; + *fnltr = ONE3HT; + *ltrhy = LETTER_P; + } + else if (n == LETTER_Y) /* WESTERN HEMISPHERE-NORTH ZONE */ + { + *ltrlow = LETTER_J; + *ltrhi = LETTER_Z; + *feltr = EIGHT; + *fnltr = ONE3HT; + *ltrhy = LETTER_P; + } + else if (n == LETTER_B) /* ** EASTERN HEMISPHERE - SOUTH ZONE */ + { + *ltrlow = LETTER_A; + *ltrhi = LETTER_R; + *feltr = TWOMIL; + *fnltr = EIGHT; + *ltrhy = LETTER_Z; + } + else if (n == LETTER_A) /* ** WESTERN HEMISPHERE - SOUTH ZONE */ + { + *ltrlow = LETTER_J; + *ltrhi = LETTER_Z; + *feltr = EIGHT; + *fnltr = EIGHT; + *ltrhy = LETTER_Z; + } + return; +} /* END OF UPSSET */ + + +void UPS (char* mgrs, + long* ltrnum, + double x, + double y, + long iarea) +{ /* BEGIN UPS */ + /* + * mgrs : MGRS coordinate. + * ltrnum : Values of the letters in the MGRS coordinate. + * x : Easting. + * y : Northing. + * iarea : Set to UPS_NORTH or UPS_SOUTH. + * + * UPS CALLS THE FOLLOWING ROUTINES: + * + * UPSSET + */ + double feltr; /* False easting for 2nd letter */ + double fnltr; /* False northing for 3rd letter */ + double xltr; /* Easting used to derive 2nd letter of MGRS */ + double yltr; /* Northing used to derive 3rd letter of MGRS */ + long ltrlow; /* 2nd letter range - low number */ + long ltrhi; /* 2nd letter range - high number */ + long ltrhy; /* 3rd letter range - high number (UPS) */ + if (iarea == UPS_NORTH) + { + ltrnum[0] = LETTER_Y; + if (((double)((long)(x + RND5))) >= TWOMIL) + { + ltrnum[0] = LETTER_Z; + } + } + else if (iarea == UPS_SOUTH) + { + ltrnum[0] = LETTER_A; + if (((double)((long)(x + RND5))) >= TWOMIL) + { + ltrnum[0] = LETTER_B; + } + } + UPSSET(ltrnum[0], <rlow, <rhi, &feltr, &fnltr, <rhy); + mgrs[0] = BLANK; + mgrs[1] = BLANK; + yltr = (double)((long)(y + RND5)); + yltr = yltr - fnltr; + ltrnum[2] = (long)((yltr + RND1) / ONEHT); + if (ltrnum[2] > LETTER_H) + { + ltrnum[2] = ltrnum[2] + 1; + } + if (ltrnum[2] > LETTER_N) + { + ltrnum[2] = ltrnum[2] + 1; + } + xltr = (double)((long)(x + RND5)); + xltr = xltr - feltr; + ltrnum[1] = ltrlow + ((long)((xltr + RND1) / ONEHT)); + if (x < TWOMIL) + { + if (ltrnum[1] > LETTER_L) + { + ltrnum[1] = ltrnum[1] + 3; + } + if (ltrnum[1] > LETTER_U) + { + ltrnum[1] = ltrnum[1] + 2; + } + } + if (x >= TWOMIL) + { + if (ltrnum[1] > LETTER_C) + { + ltrnum[1] = ltrnum[1] + 2; + } + if (ltrnum[1] > LETTER_H) + { + ltrnum[1] = ltrnum[1] + 1; + } + if (ltrnum[1] > LETTER_L) + { + ltrnum[1] = ltrnum[1] + 3; + } + } + return; +} /* END OF UPS */ + + +void LTR2UPS (long* ltrnum, + long ltrlow, + long ltrhi, + long ltrhy, + long* ierr, + double *xltr, + double *yltr, + double fnltr, + double feltr, + double *x, + double *y, + double sign) +{ /* BEGIN LTR2UPS */ + /* + * ltrnum : Values of the letters in the MGRS coordinate + * ltrlow : Low number + * ltrhi : High number-2nd letter + * ltrhy : High number-3rd letter + * ierr : Error code + * xltr : Easting for 100,000 meter grid square + * yltr : Northing for 100,000 meter grid square + * fnltr : False northing for 3rd letter + * feltr : False easting for 2nd letter + * x : Easting + * y : Northing + * sign : Set to either positive or negative + */ + if (ltrnum[1] < ltrlow) + { + *ierr = TRUE; + return; + } + if (ltrnum[1] > ltrhi) + { + *ierr = TRUE; + return; + } + if (ltrnum[2] > ltrhy) + { + *ierr = TRUE; + return; + } + if ((ltrnum[1] == LETTER_D) || (ltrnum[1] == LETTER_E) || + (ltrnum[1] == LETTER_M) || (ltrnum[1] == LETTER_N) || + (ltrnum[1] == LETTER_V) || (ltrnum[1] == LETTER_W)) + { + *ierr = TRUE; + return; + } + *yltr = (double)ltrnum[2] * ONEHT + fnltr; + if (ltrnum[2] > LETTER_I) + { + *yltr = *yltr - ONEHT; + } + if (ltrnum[2] > LETTER_O) + { + *yltr = *yltr - ONEHT; + } + *xltr = (double)((ltrnum[1]) - ltrlow) * ONEHT + feltr; + if (ltrlow != LETTER_A) + { + if (ltrnum[1] > LETTER_L) + { + *xltr = *xltr - 3.e0 * ONEHT; + } + if (ltrnum[1] > LETTER_U) + { + *xltr = *xltr - 2.e0 * ONEHT; + } + } + else if (ltrlow == LETTER_A) + { + if (ltrnum[1] > LETTER_C) + { + *xltr = *xltr - 2.e0 * ONEHT; + } + if (ltrnum[1] > LETTER_I) + { + *xltr = *xltr - ONEHT; + } + if (ltrnum[1] > LETTER_L) + { + *xltr = *xltr - 3.e0 * ONEHT ; + } + } + *x = *xltr; + *y = *yltr * sign; + return; +} /* END OF LTR2UPS */ + + +void GRID_UPS (long *Letters, + char *Hemisphere, + double *Easting, + double *Northing, + long *Error) +{ /* BEGIN GRID_UPS */ + double feltr; /* False easting for 2nd letter */ + double fnltr; /* False northing for 3rd letter */ + double sleast; /* Longitude east limit - UTM */ + double slwest; /* Longitude west limit -UTM */ + double spnor; /* North latitude limits based on 1st letter */ + double spsou; /* South latitude limits based on 1st letter */ + double x; /* easting */ + double xltr; /* easting for 100,000 meter grid square */ + double xnum; /* easting part of MGRS */ + double y; /* northing */ + double yltr; /* northing for 100,000 meter grid square */ + double ynum; /* northing part of MGRS */ + long izone; /* Zone number */ + long ltrhi; /* 2nd letter range - high number */ + long ltrhy; /* 3rd letter range - high number (UPS) */ + long ltrlow; /* 2nd letter range - low number */ + long sign; + double sphi; + double slam; + if ((Letters[0] == LETTER_Y) || (Letters[0] == LETTER_Z)) + { + spsou = MAX_UTM_LAT; + sign = 1; + } + else + { + spsou = MIN_UTM_LAT; + sign = -1; + } + slam = PI / 2.e0; + if ((Letters[0] == LETTER_Y) || (Letters[0] == LETTER_A)) + { + slam = -slam; + } + izone = 0; + sphi = spsou; + Set_UPS_Parameters(OSSIM_MGRS_a,OSSIM_MGRS_f); + Convert_Geodetic_To_UPS(sphi,slam,Hemisphere,&x,&y); + spnor = sphi; + sleast = slam; + slwest = slam; + UPSSET(Letters[0], <rlow, <rhi, &feltr, &fnltr, <rhy); + LTR2UPS(Letters, ltrlow, ltrhi, ltrhy, Error, &xltr, &yltr, fnltr, feltr, + &x, &y, sign); + xnum = *Easting; + ynum = *Northing; + y = (yltr + ynum); + x = xltr + xnum; + *Easting = x; + *Northing = y; + return; +} /* END OF GRID_UPS */ + + +void LTR2UTM (long* ltrnum, + long ltrlow, + long ltrhi, + long* ierr, + double *xltr, + double *yltr, + double fnltr, + double yslow, + double ylow) +{ /* BEGIN LTR2UTM */ + /* + * xltr : Easting for 100,000 meter grid square. + * yltr : Northing for 100,000 meter grid square. + * ierr : Error code. + * ltrnum : Values of the letters in the OSSIM_MGRS coordinate. + * ltrlow : Low number. + * ltrhi : High number. + * fnltr : False northing for 3rd letter. + * yslow : Northing scaled down to less than 2 million. + * ylow : Lowest northing of area to nearest 100,000. + */ + if (ltrnum[1] < ltrlow) + { + *ierr = TRUE; + return; + } + if (ltrnum[1] > ltrhi) + { + *ierr = TRUE; + return; + } + if (ltrnum[2] > LETTER_V) + { + *ierr = TRUE; + return; + } + *yltr = (double)(ltrnum[2]) * ONEHT + fnltr; + *xltr = (double)((ltrnum[1]) - ltrlow + 1) * ONEHT; + if ((ltrlow == LETTER_J) && (ltrnum[1] > LETTER_O)) + { + *xltr = *xltr - ONEHT; + } + if (ltrnum[2] > LETTER_O) + { + *yltr = *yltr - ONEHT; + } + if (ltrnum[2] > LETTER_I) + { + *yltr = *yltr - ONEHT; + } + if (((double)((long)(*yltr + RND5))) >= ((double)((long)(TWOMIL + RND5)))) + { + *yltr = *yltr - TWOMIL; + } + *yltr = ((double)((long)(*yltr + RND5))); + *yltr = *yltr - yslow; + if (*yltr < ZERO) + { + *yltr = *yltr + TWOMIL; + } + *yltr = ((double)((long)(ylow + *yltr + RND5))); + return; +} /* END OF LTR2UTM */ + + +void GRID_UTM (long *Zone, + long *Letters, + char *Hemisphere, + double *Easting, + double *Northing, + long In_Precision, + long *Error) +{ /* BEGIN GRID_UTM */ + double fnltr; /* False northing for 3rd letter */ + long ltrhi; /* 2nd letter range - High number */ + long ltrlow; /* 2nd letter range - Low number */ + long number; /* Value of ltrnum[0] + 1 */ +/* double slam;*/ + double slcm; /* Central meridian */ + double sleast; /* Longitude east limit - UTM */ + double slwest; /* Longitude west limit -UTM */ + double sphi; /* Latitude (needed by UTMLIM) */ + double spnor; /* North latitude limits based on 1st letter */ + double spsou; /* South latitude limits based on 1st letter */ + double xltr; /* Easting for 100,000 meter grid square */ + double ylow; /* Lowest northing of area to nearest 100,000 */ + double yltr; /* Northing for 100,000 meter grid square */ + double yslow; /* Northing scaled down to less than 2 million*/ + double Latitude = 0.0; + double Longitude = 0.0; + double divisor = 1.0; + if ((*Zone == 32) && (Letters[0] == LETTER_X)) + { + *Error = TRUE; + return; + } + if ((*Zone == 34) && (Letters[0] == LETTER_X)) + { + *Error = TRUE; + return; + } + if ((*Zone == 36) && (Letters[0] == LETTER_X)) + { + *Error = TRUE; + return; + } + number = Letters[0] + 1; + sphi = 0.0; + UTMLIM(&number,sphi,*Zone,&spsou,&spnor,&sleast,&slwest); + Set_UTM_Parameters(OSSIM_MGRS_a,OSSIM_MGRS_f,*Zone); + slcm = (double)(*Zone * 6 - 183) * DEGRAD; + Convert_Geodetic_To_UTM(spsou,slcm,Zone,Hemisphere,&xltr,&yltr); + ylow = ((double)((long)((double)((long)(yltr / ONEHT)) * ONEHT))); + yslow = ylow; + while (yslow >= TWOMIL) + { + yslow = yslow - TWOMIL; + } + yslow = ((double)((long)(yslow))); + UTMSET(*Zone, <rlow, <rhi, &fnltr); + LTR2UTM(Letters, ltrlow, ltrhi, Error, &xltr, &yltr, fnltr, yslow, ylow); + *Easting = xltr + *Easting; + *Northing = yltr + *Northing; + /* check that point is within Zone Letter bounds */ + Convert_UTM_To_Geodetic(*Zone,*Hemisphere,*Easting,*Northing,&Latitude,&Longitude); + divisor = pow (10.0, In_Precision); + if (((spsou - DEGRAD/divisor) <= Latitude) && (Latitude <= (spnor + DEGRAD/divisor))) + return; + else + *Error = TRUE; + return; +}/* END OF GRID_UTM */ + + +long Round_OSSIM_MGRS (double value) +/* Round value to nearest integer, using standard engineering rule */ +{ /* Round_OSSIM_MGRS */ + double ivalue; + long ival; + double fraction = modf (value, &ivalue); + ival = (long)(ivalue); + if ((fraction > 0.5) || ((fraction == 0.5) && (ival%2 == 1))) + ival++; + return (ival); +} /* Round_OSSIM_MGRS */ + + +long Make_OSSIM_MGRS_String (char* OSSIM_MGRS, + long Zone, + long ltrnum[OSSIM_MGRS_LETTERS], + double Easting, + double Northing, + long Precision) +/* Construct an OSSIM_MGRS string from its component parts */ +{ /* Make_OSSIM_MGRS_String */ + int i; + int j; + int error_code = OSSIM_MGRS_NO_ERROR; + double divisor; + long int east; /* double data type? (drb) */ + long int north; /* double data type? (drb) */ + i = 0; + if (Zone) + i = sprintf (OSSIM_MGRS+i,"%2.2ld",Zone); + for (j=0;j<3;j++) + OSSIM_MGRS[i++] = ALBET[ltrnum[j]]; + divisor = pow (10.0, (5 - Precision)); + Easting = fmod (Easting, 100000.0); + if (Easting >= 99999.5) + Easting = 99999.0; + east = (long int)(Easting/divisor); + i += sprintf (OSSIM_MGRS+i, "%*.*ld", (int)Precision, (int)Precision, east); + Northing = fmod (Northing, 100000.0); + if (Northing >= 99999.5) + Northing = 99999.0; + north = (long int)(Northing/divisor); + i += sprintf (OSSIM_MGRS+i, "%*.*ld", (int)Precision, (int)Precision, north); + return (error_code); +} /* Make_OSSIM_MGRS_String */ + + +long Break_OSSIM_MGRS_String (char* OSSIM_MGRS, + long* Zone, + long Letters[OSSIM_MGRS_LETTERS], + double* Easting, + double* Northing, + long* Precision) +/* Break down an OSSIM_MGRS string into its component parts */ +{ /* Break_OSSIM_MGRS_String */ + long error_code = OSSIM_MGRS_NO_ERROR; + long i = 0; + long j; + long num_digits; + long num_letters; + while (OSSIM_MGRS[i] == ' ') + i++; /* skip any leading blanks */ + j = i; + while (isdigit(OSSIM_MGRS[i])) + i++; + num_digits = i - j; + if (num_digits <= 2) + if (num_digits > 0) + { + char zone_string[3]; + /* get zone */ + strncpy (zone_string, OSSIM_MGRS+j, 2); + zone_string[2] = 0; + sscanf (zone_string, "%ld", Zone); + if ((*Zone < 1) || (*Zone > 60)) + error_code |= OSSIM_MGRS_STRING_ERROR; + } + else + *Zone = 0; + else + error_code |= OSSIM_MGRS_STRING_ERROR; + j = i; + while (isalpha(OSSIM_MGRS[i])) + i++; + num_letters = i - j; + if (num_letters == 3) + { + /* get letters */ + Letters[0] = (toupper(OSSIM_MGRS[j]) - (long)'A'); + if ((Letters[0] == LETTER_I) || (Letters[0] == LETTER_O)) + error_code |= OSSIM_MGRS_STRING_ERROR; + Letters[1] = (toupper(OSSIM_MGRS[j+1]) - (long)'A'); + if ((Letters[1] == LETTER_I) || (Letters[1] == LETTER_O)) + error_code |= OSSIM_MGRS_STRING_ERROR; + Letters[2] = (toupper(OSSIM_MGRS[j+2]) - (long)'A'); + if ((Letters[2] == LETTER_I) || (Letters[2] == LETTER_O)) + error_code |= OSSIM_MGRS_STRING_ERROR; + } + else + error_code |= OSSIM_MGRS_STRING_ERROR; + j = i; + while (isdigit(OSSIM_MGRS[i])) + i++; + num_digits = i - j; + if ((num_digits <= 10) && (num_digits%2 == 0)) + { + long n; + char east_string[6]; + char north_string[6]; + long east; + long north; + double multiplier; + /* get easting & northing */ + n = num_digits/2; + *Precision = n; + if (n > 0) + { + strncpy (east_string, OSSIM_MGRS+j, n); + east_string[n] = 0; + sscanf (east_string, "%ld", &east); + strncpy (north_string, OSSIM_MGRS+j+n, n); + north_string[n] = 0; + sscanf (north_string, "%ld", &north); + multiplier = pow (10.0, 5 - n); + *Easting = east * multiplier; + *Northing = north * multiplier; + } + else + { + *Easting = 0.0; + *Northing = 0.0; + } + } + else + error_code |= OSSIM_MGRS_STRING_ERROR; + return (error_code); +} /* Break_OSSIM_MGRS_String */ + + +long Set_OSSIM_MGRS_Parameters (double a, + double f, + char *Ellipsoid_Code) +/* + * The function SET_OSSIM_MGRS_PARAMETERS receives the ellipsoid parameters and sets + * the corresponding state variables. If any errors occur, the error code(s) + * are returned by the function, otherwise OSSIM_MGRS_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid in meters (input) + * f : Flattening of ellipsoid (input) + * Ellipsoid_Code : 2-letter code for ellipsoid (input) + */ +{ /* Set_OSSIM_MGRS_Parameters */ + + double inv_f = 1 / f; + long Error_Code = OSSIM_MGRS_NO_ERROR; + + if (a <= 0.0) + { /* Semi-major axis must be greater than zero */ + Error_Code |= OSSIM_MGRS_A_ERROR; + } + if ((inv_f < 250) || (inv_f > 350)) + { /* Inverse flattening must be between 250 and 350 */ + Error_Code |= OSSIM_MGRS_INV_F_ERROR; + } + if (!Error_Code) + { /* no errors */ + OSSIM_MGRS_a = a; + OSSIM_MGRS_f = f; + OSSIM_MGRS_recpf = inv_f; + strcpy (OSSIM_MGRS_Ellipsoid_Code, Ellipsoid_Code); + } + return (Error_Code); +} /* Set_OSSIM_MGRS_Parameters */ + + + +void Get_OSSIM_MGRS_Parameters (double *a, + double *f, + char* Ellipsoid_Code) +/* + * The function Get_OSSIM_MGRS_Parameters returns the current ellipsoid + * parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Ellipsoid_Code : 2-letter code for ellipsoid (output) + */ +{ /* Get_OSSIM_MGRS_Parameters */ + *a = OSSIM_MGRS_a; + *f = OSSIM_MGRS_f; + strcpy (Ellipsoid_Code, OSSIM_MGRS_Ellipsoid_Code); + return; +} /* Get_OSSIM_MGRS_Parameters */ + + +long Convert_Geodetic_To_OSSIM_MGRS (double Latitude, + double Longitude, + long Precision, + char* OSSIM_MGRS) +/* + * Latitude : Latitude in radians (input) + * Longitude : Longitude in radians (input) + * OSSIM_MGRS : OSSIM_MGRS coordinate string (output) + * + */ +{ /* Convert_Geodetic_To_OSSIM_MGRS */ + long error_code = OSSIM_MGRS_NO_ERROR; + long zone; + char hemisphere; + double easting; + double northing; + if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2)) + { /* Latitude out of range */ + error_code |= OSSIM_MGRS_LAT_ERROR; + } + if ((Longitude < -PI) || (Longitude > (2*PI))) + { /* Longitude out of range */ + error_code |= OSSIM_MGRS_LON_ERROR; + } + if ((Precision < 0) || (Precision > MAX_PRECISION)) + error_code |= OSSIM_MGRS_PRECISION_ERROR; + if (!error_code) + { + if ((Latitude < MIN_UTM_LAT) || (Latitude > MAX_UTM_LAT)) + { + Set_UPS_Parameters (OSSIM_MGRS_a, OSSIM_MGRS_f); + error_code |= Convert_Geodetic_To_UPS (Latitude, Longitude, &hemisphere, &easting, &northing); + error_code |= Convert_UPS_To_OSSIM_MGRS (hemisphere, easting, northing, Precision, OSSIM_MGRS); + } + else + { + Set_UTM_Parameters (OSSIM_MGRS_a, OSSIM_MGRS_f, 0); + error_code |= Convert_Geodetic_To_UTM (Latitude, Longitude, &zone, &hemisphere, &easting, &northing); + error_code |= Convert_UTM_To_OSSIM_MGRS (zone, hemisphere, easting, northing, Precision, OSSIM_MGRS); + } + } + return (error_code); +} /* Convert_Geodetic_To_OSSIM_MGRS */ + + +long Convert_OSSIM_MGRS_To_Geodetic (char* OSSIM_MGRS, + double *Latitude, + double *Longitude) +/* + * OSSIM_MGRS : OSSIM_MGRS coordinate string (output) + * Latitude : Latitude in radians (input) + * Longitude : Longitude in radians (input) + * + */ +{ /* Convert_OSSIM_MGRS_To_Geodetic */ + long error_code = OSSIM_MGRS_NO_ERROR; + long Zone; + long Letters[OSSIM_MGRS_LETTERS]; + char Hemisphere; + double Easting; + double Northing; + long In_Precision; + error_code = Break_OSSIM_MGRS_String (OSSIM_MGRS, &Zone, Letters, &Easting, &Northing, &In_Precision); + if (!error_code) + { + if (Zone) + { + error_code |= Convert_OSSIM_MGRS_To_UTM (OSSIM_MGRS, &Zone, &Hemisphere, &Easting, &Northing); + Set_UTM_Parameters (OSSIM_MGRS_a, OSSIM_MGRS_f, 0); + error_code |= Convert_UTM_To_Geodetic (Zone, Hemisphere, Easting, Northing, Latitude, Longitude); + } + else + { + error_code |= Convert_OSSIM_MGRS_To_UPS (OSSIM_MGRS, &Hemisphere, &Easting, &Northing); + Set_UPS_Parameters (OSSIM_MGRS_a, OSSIM_MGRS_f); + error_code |= Convert_UPS_To_Geodetic (Hemisphere, Easting, Northing, Latitude, Longitude); + } + } + return (error_code); +} /* END OF Convert_OSSIM_MGRS_To_Geodetic */ + + + +long Convert_UTM_To_OSSIM_MGRS (long Zone, + char Hemisphere, + double Easting, + double Northing, + long Precision, + char* OSSIM_MGRS) +/* + * The function Convert_UTM_To_OSSIM_MGRS converts UTM (zone, easting, and + * northing) coordinates to an OSSIM_MGRS coordinate string, according to the + * current ellipsoid parameters. If any errors occur, the error code(s) + * are returned by the function, otherwise OSSIM_MGRS_NO_ERROR is returned. + * + * Zone : UTM zone (input) + * Hemisphere : North or South hemisphere (input) + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Precision : Precision level of OSSIM_MGRS string (input) + * OSSIM_MGRS : OSSIM_MGRS coordinate string (output) + */ +{ /* Convert_UTM_To_OSSIM_MGRS */ + long error_code = OSSIM_MGRS_NO_ERROR; + long temp_error = OSSIM_MGRS_NO_ERROR; + long Letters[OSSIM_MGRS_LETTERS]; /* Number location of 3 letters in alphabet */ + double Latitude; /* Latitude of UTM point */ + double Longitude; /* Longitude of UTM point */ + double divisor; + if ((Zone < 1) || (Zone > 60)) + error_code |= OSSIM_MGRS_ZONE_ERROR; + if ((Hemisphere != 'S') && (Hemisphere != 'N')) + error_code |= OSSIM_MGRS_HEMISPHERE_ERROR; + if ((Easting < MIN_EASTING) || (Easting > MAX_EASTING)) + error_code |= OSSIM_MGRS_EASTING_ERROR; + if ((Northing < MIN_NORTHING) || (Northing > MAX_NORTHING)) + error_code |= OSSIM_MGRS_NORTHING_ERROR; + if ((Precision < 0) || (Precision > MAX_PRECISION)) + error_code |= OSSIM_MGRS_PRECISION_ERROR; + if (!error_code) + { + Set_UTM_Parameters (OSSIM_MGRS_a, OSSIM_MGRS_f,0); + temp_error = Convert_UTM_To_Geodetic (Zone, Hemisphere, Easting, Northing, &Latitude, &Longitude); + if (temp_error & UTM_NORTHING_ERROR) + error_code |= OSSIM_MGRS_NORTHING_ERROR; + else + { + /* Round easting and northing values */ + divisor = pow (10.0, (5 - Precision)); + Easting = Round_OSSIM_MGRS (Easting/divisor) * divisor; + Northing = Round_OSSIM_MGRS (Northing/divisor) * divisor; + UTMOSSIM_MGRS (Zone, Letters, Latitude, Easting, Northing); + /* UTM checks - these should be done in UTMOSSIM_MGRS */ + if ((Zone == 31) && (Letters[0] == LETTER_V)) + if (Easting > 500000) + Easting = 500000; + if (Northing > 10000000) + Northing = 10000000; + Make_OSSIM_MGRS_String (OSSIM_MGRS, Zone, Letters, Easting, Northing, Precision); + } + } + return (error_code); +} /* Convert_UTM_To_OSSIM_MGRS */ + + +long Convert_OSSIM_MGRS_To_UTM (char *OSSIM_MGRS, + long *Zone, + char *Hemisphere, + double *Easting, + double *Northing) +/* + * The function Convert_OSSIM_MGRS_To_UTM converts an OSSIM_MGRS coordinate string + * to UTM projection (zone, hemisphere, easting and northing) coordinates + * according to the current ellipsoid parameters. If any errors occur, + * the error code(s) are returned by the function, otherwise UTM_NO_ERROR + * is returned. + * + * OSSIM_MGRS : OSSIM_MGRS coordinate string (input) + * Zone : UTM zone (output) + * Hemisphere : North or South hemisphere (output) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ +{ /* Convert_OSSIM_MGRS_To_UTM */ + long error_code = OSSIM_MGRS_NO_ERROR; + long Letters[OSSIM_MGRS_LETTERS]; + long In_Precision; + long Error = 0; + error_code = Break_OSSIM_MGRS_String (OSSIM_MGRS, Zone, Letters, Easting, Northing, &In_Precision); + if (!*Zone) + error_code |= OSSIM_MGRS_STRING_ERROR; + if (!error_code) + { + GRID_UTM (Zone, Letters, Hemisphere, Easting, Northing, In_Precision, &Error); + if (Error) + error_code = OSSIM_MGRS_STRING_ERROR; + } + return (error_code); +} /* Convert_OSSIM_MGRS_To_UTM */ + + +long Convert_UPS_To_OSSIM_MGRS (char Hemisphere, + double Easting, + double Northing, + long Precision, + char* OSSIM_MGRS) +/* + * The function Convert_UPS_To_OSSIM_MGRS converts UPS (hemisphere, easting, + * and northing) coordinates to an OSSIM_MGRS coordinate string according to + * the current ellipsoid parameters. If any errors occur, the error + * code(s) are returned by the function, otherwise UPS_NO_ERROR is + * returned. + * + * Hemisphere : Hemisphere either 'N' or 'S' (input) + * Easting : Easting/X in meters (input) + * Northing : Northing/Y in meters (input) + * Precision : Precision level of OSSIM_MGRS string (input) + * OSSIM_MGRS : OSSIM_MGRS coordinate string (output) + */ +{ /* Convert_UPS_To_OSSIM_MGRS */ + double divisor; + long error_code = OSSIM_MGRS_NO_ERROR; + long ltrnum[OSSIM_MGRS_LETTERS]; /* Number location of 3 letters in alphabet */ + if ((Hemisphere != 'N') && (Hemisphere != 'S')) + error_code |= OSSIM_MGRS_HEMISPHERE_ERROR; + if ((Easting < MIN_EAST_NORTH) || (Easting > MAX_EAST_NORTH)) + error_code |= OSSIM_MGRS_EASTING_ERROR; + if ((Northing < MIN_EAST_NORTH) || (Northing > MAX_EAST_NORTH)) + error_code |= OSSIM_MGRS_NORTHING_ERROR; + if ((Precision < 0) || (Precision > MAX_PRECISION)) + error_code |= OSSIM_MGRS_PRECISION_ERROR; + if (!error_code) + { + divisor = pow (10.0, (5 - Precision)); + Easting = Round_OSSIM_MGRS (Easting/divisor) * divisor; + Northing = Round_OSSIM_MGRS (Northing/divisor) * divisor; + if (Hemisphere == 'S') + UPS (OSSIM_MGRS, ltrnum, Easting, Northing, UPS_SOUTH); + else + UPS (OSSIM_MGRS, ltrnum, Easting, Northing, UPS_NORTH); + Make_OSSIM_MGRS_String (OSSIM_MGRS, 0, ltrnum, Easting, Northing, Precision); + } + return (error_code); +} /* Convert_UPS_To_OSSIM_MGRS */ + + +long Convert_OSSIM_MGRS_To_UPS ( char *OSSIM_MGRS, + char *Hemisphere, + double *Easting, + double *Northing) +/* + * The function Convert_OSSIM_MGRS_To_UPS converts an OSSIM_MGRS coordinate string + * to UPS (hemisphere, easting, and northing) coordinates, according + * to the current ellipsoid parameters. If any errors occur, the error + * code(s) are returned by the function, otherwide UPS_NO_ERROR is returned. + * + * OSSIM_MGRS : OSSIM_MGRS coordinate string (input) + * Hemisphere : Hemisphere either 'N' or 'S' (output) + * Easting : Easting/X in meters (output) + * Northing : Northing/Y in meters (output) + */ +{ /* Convert_OSSIM_MGRS_To_UPS */ + long error_code = OSSIM_MGRS_NO_ERROR; + long Error = 0; + long Zone; + long Letters[OSSIM_MGRS_LETTERS]; + long In_Precision; + error_code = Break_OSSIM_MGRS_String (OSSIM_MGRS, &Zone, Letters, Easting, Northing, &In_Precision); + if (Zone) + error_code |= OSSIM_MGRS_STRING_ERROR; + if (!error_code) + { + GRID_UPS (Letters, Hemisphere, Easting, Northing, &Error); + if (Error) + error_code = OSSIM_MGRS_STRING_ERROR; + } + return (error_code); +} /* Convert_OSSIM_MGRS_To_UPS */ + + diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMgrs.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMgrs.h new file mode 100644 index 0000000000..582ce57772 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMgrs.h @@ -0,0 +1,252 @@ +#ifndef MGRS_H + #define MGRS_H + +/***************************************************************************/ +/* RSC IDENTIFIER: MGRS + * + * ABSTRACT + * + * This component converts between geodetic coordinates (latitude and + * longitude) and Military Grid Reference System (MGRS) coordinates. + * + * ERROR HANDLING + * + * This component checks parameters for valid values. If an invalid value + * is found, the error code is combined with the current error code using + * the bitwise or. This combining allows multiple error codes to be + * returned. The possible error codes are: + * + * MGRS_NO_ERROR : No errors occurred in function + * MGRS_LAT_ERROR : Latitude outside of valid range + * (-90 to 90 degrees) + * MGRS_LON_ERROR : Longitude outside of valid range + * (-180 to 360 degrees) + * MGRS_STR_ERROR : An MGRS string error: string too long, + * too short, or badly formed + * MGRS_PRECISION_ERROR : The precision must be between 0 and 5 + * inclusive. + * MGRS_A_ERROR : Semi-major axis less than or equal to zero + * MGRS_INV_F_ERROR : Inverse flattening outside of valid range + * (250 to 350) + * MGRS_EASTING_ERROR : Easting outside of valid range + * (100,000 to 900,000 meters for UTM) + * (0 to 4,000,000 meters for UPS) + * MGRS_NORTHING_ERROR : Northing outside of valid range + * (0 to 10,000,000 meters for UTM) + * (0 to 4,000,000 meters for UPS) + * MGRS_ZONE_ERROR : Zone outside of valid range (1 to 60) + * MGRS_HEMISPHERE_ERROR : Invalid hemisphere ('N' or 'S') + * + * REUSE NOTES + * + * MGRS is intended for reuse by any application that does conversions + * between geodetic coordinates and MGRS coordinates. + * + * REFERENCES + * + * Further information on MGRS can be found in the Reuse Manual. + * + * MGRS originated from : U.S. Army Topographic Engineering Center + * Geospatial Information Division + * 7701 Telegraph Road + * Alexandria, VA 22310-3864 + * + * LICENSES + * + * None apply to this component. + * + * RESTRICTIONS + * + * + * ENVIRONMENT + * + * MGRS was tested and certified in the following environments: + * + * 1. Solaris 2.5 with GCC version 2.8.1 + * 2. Windows 95 with MS Visual C++ version 6 + * + * MODIFICATIONS + * + * Date Description + * ---- ----------- + * 16-11-94 Original Code + * 15-09-99 Reengineered upper layers + * + */ + + +/***************************************************************************/ +/* + * DEFINES + */ + +#define OSSIM_MGRS_NO_ERROR 0x0000 +#define OSSIM_MGRS_LAT_ERROR 0x0001 +#define OSSIM_MGRS_LON_ERROR 0x0002 +#define OSSIM_MGRS_STRING_ERROR 0x0004 +#define OSSIM_MGRS_PRECISION_ERROR 0x0008 +#define OSSIM_MGRS_A_ERROR 0x0010 +#define OSSIM_MGRS_INV_F_ERROR 0x0020 +#define OSSIM_MGRS_EASTING_ERROR 0x0040 +#define OSSIM_MGRS_NORTHING_ERROR 0x0080 +#define OSSIM_MGRS_ZONE_ERROR 0x0100 +#define OSSIM_MGRS_HEMISPHERE_ERROR 0x0200 + + +/***************************************************************************/ +/* + * FUNCTION PROTOTYPES + */ + +/* ensure proper linkage to c++ programs */ + #ifdef __cplusplus +extern "C" { + #endif + + + long Set_OSSIM_MGRS_Parameters(double a, + double f, + char *Ellipsoid_Code); +/* + * The function Set_MGRS_Parameters receives the ellipsoid parameters and sets + * the corresponding state variables. If any errors occur, the error code(s) + * are returned by the function, otherwise MGRS_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid in meters (input) + * f : Flattening of ellipsoid (input) + * Ellipsoid_Code : 2-letter code for ellipsoid (input) + */ + + + void Get_OSSIM_MGRS_Parameters(double *a, + double *f, + char *Ellipsoid_Code); +/* + * The function Get_MGRS_Parameters returns the current ellipsoid + * parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Ellipsoid_Code : 2-letter code for ellipsoid (output) + */ + + + long Convert_Geodetic_To_OSSIM_MGRS (double Latitude, + double Longitude, + long Precision, + char *MGRS); +/* + * The function Convert_Geodetic_To_MGRS converts geodetic (latitude and + * longitude) coordinates to an MGRS coordinate string, according to the + * current ellipsoid parameters. If any errors occur, the error code(s) + * are returned by the function, otherwise MGRS_NO_ERROR is returned. + * + * Latitude : Latitude in radians (input) + * Longitude : Longitude in radians (input) + * Precision : Precision level of MGRS string (input) + * MGRS : MGRS coordinate string (output) + * + */ + + + long Convert_OSSIM_MGRS_To_Geodetic (char *MGRS, + double *Latitude, + double *Longitude); +/* + * This function converts an MGRS coordinate string to Geodetic (latitude + * and longitude in radians) coordinates. If any errors occur, the error + * code(s) are returned by the function, otherwise MGRS_NO_ERROR is returned. + * + * MGRS : MGRS coordinate string (input) + * Latitude : Latitude in radians (output) + * Longitude : Longitude in radians (output) + * + */ + + + long Convert_UTM_To_OSSIM_MGRS (long Zone, + char Hemisphere, + double Easting, + double Northing, + long Precision, + char *MGRS); +/* + * The function Convert_UTM_To_MGRS converts UTM (zone, easting, and + * northing) coordinates to an MGRS coordinate string, according to the + * current ellipsoid parameters. If any errors occur, the error code(s) + * are returned by the function, otherwise MGRS_NO_ERROR is returned. + * + * Zone : UTM zone (input) + * Hemisphere : North or South hemisphere (input) + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Precision : Precision level of MGRS string (input) + * MGRS : MGRS coordinate string (output) + */ + + + long Convert_OSSIM_MGRS_To_UTM (char *MGRS, + long *Zone, + char *Hemisphere, + double *Easting, + double *Northing); +/* + * The function Convert_MGRS_To_UTM converts an MGRS coordinate string + * to UTM projection (zone, hemisphere, easting and northing) coordinates + * according to the current ellipsoid parameters. If any errors occur, + * the error code(s) are returned by the function, otherwise UTM_NO_ERROR + * is returned. + * + * MGRS : MGRS coordinate string (input) + * Zone : UTM zone (output) + * Hemisphere : North or South hemisphere (output) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + + + + long Convert_UPS_To_OSSIM_MGRS ( char Hemisphere, + double Easting, + double Northing, + long Precision, + char *MGRS); + +/* + * The function Convert_UPS_To_MGRS converts UPS (hemisphere, easting, + * and northing) coordinates to an MGRS coordinate string according to + * the current ellipsoid parameters. If any errors occur, the error + * code(s) are returned by the function, otherwise UPS_NO_ERROR is + * returned. + * + * Hemisphere : Hemisphere either 'N' or 'S' (input) + * Easting : Easting/X in meters (input) + * Northing : Northing/Y in meters (input) + * Precision : Precision level of MGRS string (input) + * MGRS : MGRS coordinate string (output) + */ + + + long Convert_OSSIM_MGRS_To_UPS ( char *MGRS, + char *Hemisphere, + double *Easting, + double *Northing); +/* + * The function Convert_MGRS_To_UPS converts an MGRS coordinate string + * to UPS (hemisphere, easting, and northing) coordinates, according + * to the current ellipsoid parameters. If any errors occur, the error + * code(s) are returned by the function, otherwide UPS_NO_ERROR is returned. + * + * MGRS : MGRS coordinate string (input) + * Hemisphere : Hemisphere either 'N' or 'S' (output) + * Easting : Easting/X in meters (output) + * Northing : Northing/Y in meters (output) + */ + + + + #ifdef __cplusplus +} + #endif + +#endif /* MGRS_H */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMillerProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMillerProjection.cpp new file mode 100644 index 0000000000..5a884bd695 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMillerProjection.cpp @@ -0,0 +1,411 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Miller projection code. +//******************************************************************* +// $Id: ossimMillerProjection.cpp,v 1.12 2004/01/08 21:49:22 jlargent Exp $ + +#include <math.h> +#include "ossimMillerProjection.h" +#include "base/common/ossimKeywordNames.h" + +RTTI_DEF1(ossimMillerProjection, "ossimMillerProjection", ossimMapProjection) +/***************************************************************************/ +/* + * DEFINES + */ + +#ifndef PI_OVER_2 +# define PI_OVER_2 ( M_PI / 2.0) +#endif +#ifndef TWO_PI +# define TWO_PI (2.0 * M_PI) +#endif + +#define MILL_NO_ERROR 0x0000 +#define MILL_LAT_ERROR 0x0001 +#define MILL_LON_ERROR 0x0002 +#define MILL_EASTING_ERROR 0x0004 +#define MILL_NORTHING_ERROR 0x0008 +#define MILL_CENT_MER_ERROR 0x0020 +#define MILL_A_ERROR 0x0040 +#define MILL_B_ERROR 0x0080 +#define MILL_A_LESS_B_ERROR 0x0100 + +ossimMillerProjection::ossimMillerProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + :ossimMapProjection(ellipsoid, origin) +{ + setDefaults(); + update(); +// Mill_Delta_Northing = 14675058.0; +// Mill_Max_Easting = 20015110.0; +// Mill_Min_Easting = -20015110.0; +} + +ossimMillerProjection::ossimMillerProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double falseEasting, + double falseNorthing) + :ossimMapProjection(ellipsoid, origin) +{ + + Mill_False_Easting = falseEasting; + Mill_False_Northing = falseNorthing; + Mill_Delta_Northing = 14675058.0; + Mill_Max_Easting = 20015110.0; + Mill_Min_Easting = -20015110.0; + + update(); +} + +void ossimMillerProjection::update() +{ + Set_Miller_Parameters(theEllipsoid.getA(), + theEllipsoid.getFlattening(), + theOrigin.lonr(), + Mill_False_Easting, + Mill_False_Northing); + + ossimMapProjection::update(); +} + +void ossimMillerProjection::setFalseEasting(double falseEasting) +{ + Mill_False_Easting = falseEasting; + update(); +} + +void ossimMillerProjection::setFalseNorthing(double falseNorthing) +{ + Mill_False_Northing = falseNorthing; + update(); +} + +void ossimMillerProjection::setDefaults() +{ + Mill_False_Easting = 0.0; + Mill_False_Northing = 0.0; + Mill_Delta_Northing = 14675058.0; + Mill_Max_Easting = 20015110.0; + Mill_Min_Easting = -20015110.0; +} + +void ossimMillerProjection::setFalseEastingNorthing(double falseEasting, + double falseNorthing) +{ + Mill_False_Easting = falseEasting; + Mill_False_Northing = falseNorthing; + + update(); +} + +ossimGpt ossimMillerProjection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat = 0.0; + double lon = 0.0; + + Convert_Miller_To_Geodetic(eastingNorthing.x, + eastingNorthing.y, + &lat, + &lon); + + return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum); +} + +ossimDpt ossimMillerProjection::forward(const ossimGpt &latLon)const +{ + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + Convert_Geodetic_To_Miller(gpt.latr(), + gpt.lonr(), + &easting, + &northing); + + return ossimDpt(easting, northing); +} + +bool ossimMillerProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const +{ + kwl.add(prefix, + ossimKeywordNames::FALSE_EASTING_KW, + Mill_False_Easting, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_NORTHING_KW, + Mill_False_Northing, + true); + + return ossimMapProjection::saveState(kwl, prefix); +} + +bool ossimMillerProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + bool flag = ossimMapProjection::loadState(kwl, prefix); + + const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + const char* falseEasting = kwl.find(prefix, ossimKeywordNames::FALSE_EASTING_KW); + const char* falseNorthing = kwl.find(prefix, ossimKeywordNames::FALSE_NORTHING_KW); + setDefaults(); + if(ossimString(type) == STATIC_TYPE_NAME(ossimMillerProjection)) + { + if(falseEasting) + { + Mill_False_Easting = ossimString(falseEasting).toDouble(); + } + if(falseNorthing) + { + Mill_False_Northing = ossimString(falseNorthing).toDouble(); + } + } + update(); + + return flag; +} + +/***************************************************************************/ +/* + * FUNCTIONS + */ + +long ossimMillerProjection::Set_Miller_Parameters(double a, + double f, + double Central_Meridian , + double False_Easting, + double False_Northing) +{ /* Begin Set_Miller_Parameters */ +/* + * The function Set_Miller_Parameters receives the ellipsoid parameters and + * Miller Cylindrical projcetion parameters as inputs, and sets the corresponding + * state variables. If any errors occur, the error code(s) are returned by the + * function, otherwise MILL_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + +// double inv_f = 1 / f; + long Error_Code = MILL_NO_ERROR; + +// if (a <= 0.0) +// { /* Semi-major axis must be greater than zero */ +// Error_Code |= MILL_A_ERROR; +// } +// if ((inv_f < 250) || (inv_f > 350)) +// { /* Inverse flattening must be between 250 and 350 */ +// Error_Code |= MILL_INV_F_ERROR; +// } +// if ((Central_Meridian < -PI) || (Central_Meridian > TWO_PI)) +// { /* origin longitude out of range */ +// Error_Code |= MILL_CENT_MER_ERROR; +// } + if (!Error_Code) + { /* no errors */ + Mill_a = a; + Mill_f = f; + es2 = 2 * Mill_f - Mill_f * Mill_f; + es4 = es2 * es2; + es6 = es4 * es2; + /* spherical radius */ + Ra = Mill_a * (1.0 - es2 / 6.0 - 17.0 * es4 / 360.0 - 67.0 * es6 /3024.0); +// if (Central_Meridian > PI) +// Central_Meridian -= TWO_PI; + Mill_Origin_Long = Central_Meridian; + Mill_False_Easting = False_Easting; + Mill_False_Northing = False_Northing; + if (Mill_Origin_Long > 0) + { + Mill_Max_Easting = 19903915.0; + Mill_Min_Easting = -20015110.0; + } + else if (Mill_Origin_Long < 0) + { + Mill_Max_Easting = 20015110.0; + Mill_Min_Easting = -19903915.0; + } + else + { + Mill_Max_Easting = 20015110.0; + Mill_Min_Easting = -20015110.0; + } + } /* End if(!Error_Code) */ + return (Error_Code); +} /* End Set_Miller_Parameters */ + + +void ossimMillerProjection::Get_Miller_Parameters(double *a, + double *f, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const +{ /* Begin Get_Miller_Parameters */ +/* + * The function Get_Miller_Parameters returns the current ellipsoid + * parameters and Miller Cylindrical projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + + *a = Mill_a; + *f = Mill_f; + *Central_Meridian = Mill_Origin_Long; + *False_Easting = Mill_False_Easting; + *False_Northing = Mill_False_Northing; + + return; +} /* End Get_Miller_Parameters */ + + +long ossimMillerProjection::Convert_Geodetic_To_Miller (double Latitude, + double Longitude, + double *Easting, + double *Northing)const + +{ /* Begin Convert_Geodetic_To_Miller */ +/* + * The function Convert_Geodetic_To_Miller converts geodetic (latitude and + * longitude) coordinates to Miller Cylindrical projection (easting and northing) + * coordinates, according to the current ellipsoid and Miller Cylindrical projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise MILL_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + + double slat = sin(0.8 * Latitude); + double dlam; /* Longitude - Central Meridan */ + + long Error_Code = MILL_NO_ERROR; + +// if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2)) +// { /* Latitude out of range */ +// Error_Code |= MILL_LAT_ERROR; +// } +// if ((Longitude < -PI) || (Longitude > TWO_PI)) +// { /* Longitude out of range */ +// Error_Code|= MILL_LON_ERROR; +// } + + if (!Error_Code) + { /* no errors */ + dlam = Longitude - Mill_Origin_Long; +// if (dlam > PI) +// { +// dlam -= TWO_PI; +// } +// if (dlam < -PI) +// { +// dlam += TWO_PI; +// } + *Easting = Ra * dlam + Mill_False_Easting; + *Northing = (Ra / 1.6) * log((1.0 + slat) / + (1.0 - slat)) + Mill_False_Northing; + } + return (Error_Code); +} /* End Convert_Geodetic_To_Miller */ + + +long ossimMillerProjection::Convert_Miller_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const +{ /* Begin Convert_Miller_To_Geodetic */ +/* + * The function Convert_Miller_To_Geodetic converts Miller Cylindrical projection + * (easting and northing) coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Miller Cylindrical projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise MILL_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + + double dx, dy; + long Error_Code = MILL_NO_ERROR; + +// if ((Easting < (Mill_False_Easting + Mill_Min_Easting)) +// || (Easting > (Mill_False_Easting + Mill_Max_Easting))) +// { /* Easting out of range */ +// Error_Code |= MILL_EASTING_ERROR; +// } +// if ((Northing < (Mill_False_Northing - Mill_Delta_Northing)) || +// (Northing > (Mill_False_Northing + Mill_Delta_Northing) )) +// { /* Northing out of range */ +// Error_Code |= MILL_NORTHING_ERROR; +// } + + if (!Error_Code) + { + dy = Northing - Mill_False_Northing; + dx = Easting - Mill_False_Easting; + *Latitude = atan(sinh(0.8 * dy / Ra)) / 0.8; + *Longitude = Mill_Origin_Long + dx / Ra; + +// if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */ +// *Latitude = PI_OVER_2; +// else if (*Latitude < -PI_OVER_2) +// *Latitude = -PI_OVER_2; + +// if (*Longitude > PI) +// *Longitude -= TWO_PI; +// if (*Longitude < -PI) +// *Longitude += TWO_PI; + +// if (*Longitude > PI) /* force distorted values to 180, -180 degrees */ +// *Longitude = PI; +// else if (*Longitude < -PI) +// *Longitude = -PI; + + } + return (Error_Code); +} /* End Convert_Miller_To_Geodetic */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMillerProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMillerProjection.h new file mode 100644 index 0000000000..01e97cd045 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMillerProjection.h @@ -0,0 +1,186 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Miller projection code. +//******************************************************************* +// $Id: ossimMillerProjection.h,v 1.5 2005/09/09 19:23:58 gpotts Exp $ + +#ifndef ossimMillerProjection_HEADER +#define ossimMillerProjection_HEADER + +#include "ossimMapProjection.h" + +class ossimMillerProjection : public ossimMapProjection +{ +public: + ossimMillerProjection(const ossimEllipsoid& ellipsoid = ossimEllipsoid(), + const ossimGpt& origin = ossimGpt()); + ossimMillerProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + const double falseEasting, + const double falseNorthing); + + ~ossimMillerProjection(){} + + virtual ossimObject *dup()const{return new ossimMillerProjection(*this);} + + virtual ossimGpt inverse(const ossimDpt &eastingNorthing)const; + virtual ossimDpt forward(const ossimGpt &latLon)const; + virtual void update(); + + /*! + * SetFalseEasting. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEasting(double falseEasting); + + /*! + * SetFalseNorthing. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseNorthing(double falseNorthing); + + /*! + * Sets both false easting and northing values. The values are + * expected to be in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEastingNorthing(double falseEasting, double falseNorthing); + + void setDefaults(); + + double getFalseEasting()const{return Mill_False_Easting;} + double getFalseNorthing()const{return Mill_False_Northing;} + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +private: + + //________________GEOTRANS STUFF___________________ + + mutable double Mill_a; /* Semi-major axis of ellipsoid in meters */ + mutable double Mill_f; /* Flattening of ellipsoid */ + mutable double es2; /* Eccentricity (0.08181919084262188000) squared */ + mutable double es4; /* es2 * es2 */ + mutable double es6; /* es4 * es2 */ + mutable double Ra; /* Spherical Radius */ + +/* Miller projection Parameters */ + mutable double Mill_Origin_Long; /* Longitude of origin in radians */ + mutable double Mill_False_Easting; + mutable double Mill_False_Northing; + mutable double Mill_Delta_Northing; + mutable double Mill_Max_Easting; + mutable double Mill_Min_Easting; + +/*! + * The function Set_Miller_Parameters receives the ellipsoid parameters and + * Miller Cylindrical projcetion parameters as inputs, and sets the corresponding + * state variables. If any errors occur, the error code(s) are returned by the + * function, otherwise MILL_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + long Set_Miller_Parameters(double a, + double f, + double Central_Meridian, + double False_Easting, + double False_Northing); + + +/*! + * The function Get_Miller_Parameters returns the current ellipsoid + * parameters and Miller Cylindrical projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + void Get_Miller_Parameters(double *a, + double *f, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const; + + +/*! + * The function Convert_Geodetic_To_Miller converts geodetic (latitude and + * longitude) coordinates to Miller Cylindrical projection easting, and northing + * coordinates, according to the current ellipsoid and Miller Cylindrical projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise MILL_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + long Convert_Geodetic_To_Miller (double Latitude, + double Longitude, + double *Easting, + double *Northing)const; + + +/*! + * The function Convert_Miller_To_Geodetic converts Miller Cylindrical projection + * easting and northing coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Miller Cylindrical projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise MILL_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + long Convert_Miller_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMollweidProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMollweidProjection.cpp new file mode 100644 index 0000000000..4be11722eb --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMollweidProjection.cpp @@ -0,0 +1,453 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Mollweid projection code. +//******************************************************************* +// $Id: ossimMollweidProjection.cpp,v 1.11 2004/01/08 21:49:22 jlargent Exp $ +#include <math.h> +#include "ossimMollweidProjection.h" +#include "base/common/ossimKeywordNames.h" + +RTTI_DEF1(ossimMollweidProjection, "ossimMollweidProjection", ossimMapProjection) + +/***************************************************************************/ +/* + * DEFINES + */ +#ifndef PI_OVER_2 +# define PI_OVER_2 ( M_PI / 2.0) +#endif +#ifndef TWO_PI +# define TWO_PI (2.0 * M_PI) +#endif +#define MAX_LAT ( (M_PI * 90.0) / 180.0 ) /* 90 degrees in radians */ + +#define MOLL_NO_ERROR 0x0000 +#define MOLL_LAT_ERROR 0x0001 +#define MOLL_LON_ERROR 0x0002 +#define MOLL_EASTING_ERROR 0x0004 +#define MOLL_NORTHING_ERROR 0x0008 +#define MOLL_CENT_MER_ERROR 0x0020 +#define MOLL_A_ERROR 0x0040 +#define MOLL_B_ERROR 0x0080 +#define MOLL_A_LESS_B_ERROR 0x0100 + +ossimMollweidProjection::ossimMollweidProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + :ossimMapProjection(ellipsoid, origin) +{ + setDefaults(); + update(); +} + +ossimMollweidProjection::ossimMollweidProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double falseEasting, + double falseNorthing) + :ossimMapProjection(ellipsoid, origin) +{ + + Moll_False_Easting = falseEasting; + Moll_False_Northing = falseNorthing; + Moll_Delta_Northing = 9009965.0; + Moll_Max_Easting = 18019930.0; + Moll_Min_Easting = -18019930.0; + + update(); +} + +void ossimMollweidProjection::update() +{ + + Set_Mollweide_Parameters(theEllipsoid.getA(), + theEllipsoid.getFlattening(), + theOrigin.lonr(), + Moll_False_Easting, + Moll_False_Northing); + + ossimMapProjection::update(); +} + +void ossimMollweidProjection::setFalseEasting(double falseEasting) +{ + Moll_False_Easting = falseEasting; + update(); +} + +void ossimMollweidProjection::setFalseNorthing(double falseNorthing) +{ + Moll_False_Northing = falseNorthing; + update(); +} + +void ossimMollweidProjection::setDefaults() +{ + Moll_False_Easting = 0.0; + Moll_False_Northing = 0.0; + Moll_Delta_Northing = 9009965.0; + Moll_Max_Easting = 18019930.0; + Moll_Min_Easting = -18019930.0; +} + +void ossimMollweidProjection::setFalseEastingNorthing(double falseEasting, + double falseNorthing) +{ + Moll_False_Easting = falseEasting; + Moll_False_Northing = falseNorthing; + + update(); +} + +ossimGpt ossimMollweidProjection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat = 0.0; + double lon = 0.0; + + Convert_Mollweide_To_Geodetic(eastingNorthing.x, + eastingNorthing.y, + &lat, + &lon); + + return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum); +} + +ossimDpt ossimMollweidProjection::forward(const ossimGpt &latLon)const +{ + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + Convert_Geodetic_To_Mollweide(gpt.latr(), + gpt.lonr(), + &easting, + &northing); + + return ossimDpt(easting, northing); +} + +bool ossimMollweidProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const +{ + kwl.add(prefix, + ossimKeywordNames::FALSE_EASTING_KW, + Moll_False_Easting, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_NORTHING_KW, + Moll_False_Northing, + true); + + return ossimMapProjection::saveState(kwl, prefix); + +} + +bool ossimMollweidProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + bool flag = ossimMapProjection::loadState(kwl, prefix); + + const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + const char* falseEasting = kwl.find(prefix, ossimKeywordNames::FALSE_EASTING_KW); + const char* falseNorthing = kwl.find(prefix, ossimKeywordNames::FALSE_NORTHING_KW); + setDefaults(); + if(ossimString(type) == STATIC_TYPE_NAME(ossimMollweidProjection)) + { + if(falseEasting) + { + Moll_False_Easting = ossimString(falseEasting).toDouble(); + } + if(falseNorthing) + { + Moll_False_Northing = ossimString(falseNorthing).toDouble(); + } + } + update(); + + return flag; +} + +/***************************************************************************/ +/* + * FUNCTIONS + */ + + +long ossimMollweidProjection::Set_Mollweide_Parameters(double a, + double f, + double Central_Meridian, + double False_Easting, + double False_Northing) +{ /* Begin Set_Mollweide_Parameters */ +/* + * The function Set_Mollweide_Parameters receives the ellipsoid parameters and + * Mollweide projcetion parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the + * function, otherwise MOLL_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + + double Ra; /* Spherical Radius */ +// double inv_f = 1 / f; + long Error_Code = MOLL_NO_ERROR; + +// if (a <= 0.0) +// { /* Semi-major axis must be greater than zero */ +// Error_Code |= MOLL_A_ERROR; +// } +// if ((inv_f < 250) || (inv_f > 350)) +// { /* Inverse flattening must be between 250 and 350 */ +// Error_Code |= MOLL_INV_F_ERROR; +// } +// if ((Central_Meridian < -PI) || (Central_Meridian > TWO_PI)) +// { /* origin longitude out of range */ +// Error_Code |= MOLL_CENT_MER_ERROR; +// } + if (!Error_Code) + { /* no errors */ + Moll_a = a; + Moll_f = f; + es2 = 2 * Moll_f - Moll_f * Moll_f; + es4 = es2 * es2; + es6 = es4 * es2; + /* spherical radius */ + Ra = Moll_a * (1.0 - es2 / 6.0 - 17.0 * es4 / 360.0 - 67.0 * es6 / 3024.0); + Sqrt2_Ra = sqrt(2.0) * Ra; + Sqrt8_Ra = sqrt(8.0) * Ra; +// if (Central_Meridian > PI) +// Central_Meridian -= TWO_PI; + Moll_Origin_Long = Central_Meridian; + Moll_False_Easting = False_Easting; + Moll_False_Northing = False_Northing; + + if (Moll_Origin_Long > 0) + { + Moll_Max_Easting = 17919819.0; + Moll_Min_Easting = -18019930.0; + } + else if (Moll_Origin_Long < 0) + { + Moll_Max_Easting = 18019930.0; + Moll_Min_Easting = -17919819.0; + } + else + { + Moll_Max_Easting = 18019930.0; + Moll_Min_Easting = -18019930.0; + } + + } /* End if(!Error_Code) */ + return (Error_Code); +} /* End Set_Mollweide_Parameters */ + + +void ossimMollweidProjection::Get_Mollweide_Parameters(double *a, + double *f, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const +{ /* Begin Get_Mollweide_Parameters */ +/* + * The function Get_Mollweide_Parameters returns the current ellipsoid + * parameters and Mollweide projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + + *a = Moll_a; + *f = Moll_f; + *Central_Meridian = Moll_Origin_Long; + *False_Easting = Moll_False_Easting; + *False_Northing = Moll_False_Northing; + + return; +} /* End Get_Mollweide_Parameters */ + + +long ossimMollweidProjection::Convert_Geodetic_To_Mollweide (double Latitude, + double Longitude, + double *Easting, + double *Northing)const + +{ /* Begin Convert_Geodetic_To_Mollweide */ +/* + * The function Convert_Geodetic_To_Mollweide converts geodetic (latitude and + * longitude) coordinates to Mollweide projection (easting and northing) + * coordinates, according to the current ellipsoid and Mollweide projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise MOLL_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + + double PI_Sin_Latitude = M_PI * sin(Latitude); + double dlam; /* Longitude - Central Meridan */ + double theta; + double theta_primed = Latitude; + double delta_theta_primed = 0.1745329; /* arbitrarily initialized to 10 deg */ + double dtp_tolerance = 4.85e-10; /* approximately 1/1000th of + an arc second or 1/10th meter */ + long Error_Code = MOLL_NO_ERROR; + +// if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2)) +// { /* Latitude out of range */ +// Error_Code |= MOLL_LAT_ERROR; +// } +// if ((Longitude < -PI) || (Longitude > TWO_PI)) +// { /* Longitude out of range */ +// Error_Code|= MOLL_LON_ERROR; +// } + + if (!Error_Code) + { /* no errors */ + dlam = Longitude - Moll_Origin_Long; +// if (dlam > PI) +// { +// dlam -= TWO_PI; +// } +// if (dlam < -PI) +// { +// dlam += TWO_PI; +// } + while (fabs(delta_theta_primed) > dtp_tolerance) + { + delta_theta_primed = -(theta_primed + sin(theta_primed) - + PI_Sin_Latitude) / (1.0 + cos(theta_primed)); + theta_primed += delta_theta_primed; + } + theta = theta_primed / 2.0; + *Easting = (Sqrt8_Ra / M_PI ) * dlam * cos(theta) + + Moll_False_Easting; + *Northing = Sqrt2_Ra * sin(theta) + Moll_False_Northing; + + } + return (Error_Code); + +} /* End Convert_Geodetic_To_Mollweide */ + + +long ossimMollweidProjection::Convert_Mollweide_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const +{ /* Begin Convert_Mollweide_To_Geodetic */ +/* + * The function Convert_Mollweide_To_Geodetic converts Mollweide projection + * (easting and northing) coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Mollweide projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise MOLL_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + + double dx, dy; + double theta = 0.0; + double two_theta; + double i; + + long Error_Code = MOLL_NO_ERROR; + +// if ((Easting < (Moll_False_Easting + Moll_Min_Easting)) +// || (Easting > (Moll_False_Easting + Moll_Max_Easting))) +// { /* Easting out of range */ +// Error_Code |= MOLL_EASTING_ERROR; +// } +// if ((Northing < (Moll_False_Northing - Moll_Delta_Northing)) || +// (Northing >(Moll_False_Northing + Moll_Delta_Northing) )) +// { /* Northing out of range */ +// Error_Code |= MOLL_NORTHING_ERROR; +// } + + if (!Error_Code) + { + dy = Northing - Moll_False_Northing; + dx = Easting - Moll_False_Easting; + i = dy / Sqrt2_Ra; + if (fabs(i) > 1.0) + { + *Latitude = MAX_LAT; + if (Northing < 0.0) + *Latitude *= -1.0; + } + + else + { + theta = asin(i); + two_theta = 2.0 * theta; + *Latitude = asin((two_theta + sin(two_theta)) / M_PI); + + if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */ + *Latitude = PI_OVER_2; + else if (*Latitude < -PI_OVER_2) + *Latitude = -PI_OVER_2; + + } + if (fabs(fabs(*Latitude) - MAX_LAT) < 1.0e-10) + *Longitude = Moll_Origin_Long; + else + *Longitude = Moll_Origin_Long + M_PI * dx / + (Sqrt8_Ra * cos(theta)); + +// if (*Longitude > PI) +// *Longitude -= TWO_PI; +// if (*Longitude < -PI) +// *Longitude += TWO_PI; + +// if (*Longitude > PI) /* force distorted values to 180, -180 degrees */ +// *Longitude = PI; +// else if (*Longitude < -PI) +// *Longitude = -PI; + + + } + return (Error_Code); + +} /* End Convert_Mollweide_To_Geodetic */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMollweidProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMollweidProjection.h new file mode 100644 index 0000000000..07a9a18a60 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimMollweidProjection.h @@ -0,0 +1,188 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Mollweid projection code. +//******************************************************************* +// $Id: ossimMollweidProjection.h,v 1.5 2005/09/09 19:23:58 gpotts Exp $ + +#ifndef ossimMollweidProojection_HEADER +#define ossimMollweidProojection_HEADER + +#include "ossimMapProjection.h" + +class ossimMollweidProjection : public ossimMapProjection +{ +public: + ossimMollweidProjection(const ossimEllipsoid& ellipsoid = ossimEllipsoid(), + const ossimGpt& origin = ossimGpt()); + ossimMollweidProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + const double falseEasting, + const double falseNorthing); + + ~ossimMollweidProjection(){} + + virtual ossimObject *dup()const{return new ossimMollweidProjection(*this);} + + virtual ossimGpt inverse(const ossimDpt &eastingNorthing)const; + virtual ossimDpt forward(const ossimGpt &latLon)const; + virtual void update(); + + /*! + * SetFalseEasting. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEasting(double falseEasting); + + /*! + * SetFalseNorthing. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseNorthing(double falseNorthing); + + /*! + * Sets both false easting and northing values. The values are + * expected to be in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEastingNorthing(double falseEasting, double falseNorthing); + + void setDefaults(); + + double getFalseEasting()const{return Moll_False_Easting;} + double getFalseNorthing()const{return Moll_False_Northing;} + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +private: + + //__________________GEOTRANS______________________ + mutable double Moll_a; /* Semi-major axis of ellipsoid in meters */ + mutable double Moll_f; /* Flattening of ellipsoid */ + mutable double es2; /* Eccentricity (0.08181919084262188000) squared */ + mutable double es4; /* es2 * es2 */ + mutable double es6; /* es4 * es2 */ + mutable double Sqrt2_Ra; /* sqrt(2.0) * Spherical Radius(6371007.1810824) */ + mutable double Sqrt8_Ra; /* sqrt(8.0) * Spherical Radius(6371007.1810824) */ + +/* Mollweide projection Parameters */ + mutable double Moll_Origin_Long; /* Longitude of origin in radians */ + mutable double Moll_False_Easting; + mutable double Moll_False_Northing; + mutable double Moll_Delta_Northing; + mutable double Moll_Max_Easting; + mutable double Moll_Min_Easting; + +/*! + * The function Set_Mollweide_Parameters receives the ellipsoid parameters and + * Mollweide projcetion parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the + * function, otherwise MOLL_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + long Set_Mollweide_Parameters(double a, + double f, + double Central_Meridian, + double False_Easting, + double False_Northing); + + +/*! + * The function Get_Mollweide_Parameters returns the current ellipsoid + * parameters and Mollweide projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + void Get_Mollweide_Parameters(double *a, + double *f, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const; + + +/*! + * The function Convert_Geodetic_To_Mollweide converts geodetic (latitude and + * longitude) coordinates to Mollweide projection easting, and northing + * coordinates, according to the current ellipsoid and Mollweide projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise MOLL_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + long Convert_Geodetic_To_Mollweide (double Latitude, + double Longitude, + double *Easting, + double *Northing)const; + + +/*! + * The function Convert_Mollweide_To_Geodetic converts Mollweide projection + * easting and northing coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Mollweide projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise MOLL_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + long Convert_Mollweide_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const; + + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimNewZealandMapGridProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimNewZealandMapGridProjection.cpp new file mode 100644 index 0000000000..2556f1b17e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimNewZealandMapGridProjection.cpp @@ -0,0 +1,434 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimNewZealandMapGridProjection.cpp,v 1.7 2004/04/07 19:44:55 gpotts Exp $ +#include <projections/map_projections/ossimNewZealandMapGridProjection.h> +#include <base/factory/ossimEllipsoidFactory.h> +#include <base/factory/ossimDatumFactory.h> +#include <base/common/ossimKeywordNames.h> +#include <base/context/ossimNotifyContext.h> + +RTTI_DEF1(ossimNewZealandMapGridProjection, "ossimNewZealandMapGridProjection", ossimMapProjection) + +#ifndef PI_OVER_2 +# define PI_OVER_2 ( M_PI / 2.0) +#endif +#ifndef TWO_PI +# define TWO_PI (2.0 * M_PI) +#endif + +#define MAX_LAT (-33.5 * M_PI / 180.0) /* -33.5 degrees */ +#define MIN_LAT (-48.5 * M_PI / 180.0) /* -48.5 degrees */ +#define MAX_LON (180.0 * M_PI / 180.0) /* 180 degrees */ +#define MIN_LON (165.5 * M_PI / 180.0) /* 165.5 degrees */ + +#define NZMG_NO_ERROR 0x0000 +#define NZMG_LAT_ERROR 0x0001 +#define NZMG_LON_ERROR 0x0002 +#define NZMG_EASTING_ERROR 0x0004 +#define NZMG_NORTHING_ERROR 0x0008 +#define NZMG_ELLIPSOID_ERROR 0x0010 + +typedef struct ComplexNumber +{ + double real; + double imag; +} Complex; + +static double A[] = { 0.6399175073, -0.1358797613, 0.063294409, + -0.02526853, 0.0117879, -0.0055161, + 0.0026906, -0.001333, 0.00067, -0.00034 }; + +static Complex B[] = { { 0.7557853228, 0.0 }, + { 0.249204646, 0.003371507 }, + { -0.001541739, 0.041058560 }, + { -0.10162907, 0.01727609 }, + { -0.26623489, -0.36249218 }, + { -0.6870983, -1.1651967 } }; + +static Complex C[] = { { 1.3231270439, 0.0 }, + { -0.577245789, -0.007809598 }, + { 0.508307513, -0.112208952 }, + { -0.15094762, 0.18200602 }, + { 1.01418179, 1.64497696 }, + { 1.9660549, 2.5127645 } }; + +static double D[] = { 1.5627014243, 0.5185406398, -0.03333098, + -0.1052906, -0.0368594, 0.007317, + 0.01220, 0.00394, -0.0013 }; + +/* These state variables are for optimization purposes. The only function + * that should modify them is Set_NZMG_Parameters. */ + +/************************************************************************/ +/* FUNCTIONS + * + */ + +/* Add two complex numbers */ +static Complex Add(Complex z1, Complex z2) +{ + Complex z; + + z.real = z1.real + z2.real; + z.imag = z1.imag + z2.imag; + + return z; +} + + +/* Multiply two complex numbers */ +static Complex Multiply(Complex z1, Complex z2) +{ + Complex z; + + z.real = z1.real * z2.real - z1.imag * z2.imag; + z.imag = z1.imag * z2.real + z1.real * z2.imag; + + return z; +} + + +/* Divide two complex numbers */ +static Complex Divide(Complex z1, Complex z2) +{ + Complex z; + double denom; + + denom = z2.real * z2.real + z2.imag * z2.imag; + z.real = (z1.real * z2.real + z1.imag * z2.imag) / denom; + z.imag = (z1.imag * z2.real - z1.real * z2.imag) / denom; + + return z; +} + +ossimNewZealandMapGridProjection::ossimNewZealandMapGridProjection() + :ossimMapProjection(*ossimEllipsoidFactory::instance()->create("IN"), + ossimGpt(-41, 173.0)) +{ + setDefaults(); + update(); +} + +ossimNewZealandMapGridProjection::~ossimNewZealandMapGridProjection() +{ +} + +void ossimNewZealandMapGridProjection::setFalseEasting(double falseEasting) +{ + NZMG_False_Easting = falseEasting; + update(); +} + +void ossimNewZealandMapGridProjection::setFalseNorthing(double falseNorthing) +{ + NZMG_False_Northing = falseNorthing; + update(); +} + +void ossimNewZealandMapGridProjection::setFalseEastingNorthing(double falseEasting, double falseNorthing) +{ + NZMG_False_Easting = falseEasting; + NZMG_False_Northing = falseNorthing; + + update(); +} + +void ossimNewZealandMapGridProjection::setDefaults() +{ + theOrigin.latd(-41.0); + theOrigin.lond(173.0); + + // origin of lat needs to be in degrees + NZMG_Origin_Lat = theOrigin.latd(); + + // origin of lon is in radians + NZMG_Origin_Long = theOrigin.lonr(); + NZMG_Max_Easting = 3170000.0; + NZMG_Max_Northing = 6900000.0; + NZMG_Min_Easting = 1810000.0; + NZMG_Min_Northing = 5160000.0; + + NZMG_False_Easting = 2510000.0; + NZMG_False_Northing = 6023150.0; +} + +void ossimNewZealandMapGridProjection::update() +{ + theOrigin = ossimGpt(-41, 173); + + // create the new zealand datum. + theDatum = ossimDatumFactory::instance()->create("GEO"); + + if(theDatum) + { + theEllipsoid = *(theDatum->ellipsoid()); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) << "WARNING ossimNewZealandMapGridProjection::update(): Was unable to locate the newzealand datum!" << std::endl; + } + + NZMG_Origin_Lat = theOrigin.latd(); + NZMG_Origin_Long = theOrigin.lonr(); + NZMG_a = theEllipsoid.getA(); + + ossimMapProjection::update(); +} + +ossimGpt ossimNewZealandMapGridProjection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat = 0.0; + double lon = 0.0; + + Convert_NZMG_To_Geodetic(eastingNorthing.x, + eastingNorthing.y, + &lat, + &lon); + + return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum); +} + +ossimDpt ossimNewZealandMapGridProjection::forward(const ossimGpt &latLon)const +{ + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + Convert_Geodetic_To_NZMG(gpt.latr(), + gpt.lonr(), + &easting, + &northing); + + return ossimDpt(easting, northing); +} + +bool ossimNewZealandMapGridProjection::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimMapProjection::saveState(kwl, prefix); + + return true; +} + +bool ossimNewZealandMapGridProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimKeywordlist newKwl = kwl; + + // force a New Zealand Datum and the origin of lat and lon + // to the New Zealand. + newKwl.add(prefix, + ossimKeywordNames::DATUM_KW, + "GEO", + true); + + newKwl.add(prefix, + ossimKeywordNames::ORIGIN_LATITUDE_KW, + -41, + true); + + newKwl.add(prefix, + ossimKeywordNames::CENTRAL_MERIDIAN_KW, + 173.0, + true); + + setDefaults(); + + ossimMapProjection::loadState(newKwl, prefix); + update(); + + return true; +} + +long ossimNewZealandMapGridProjection::Convert_Geodetic_To_NZMG (double Latitude, + double Longitude, + double *Easting, + double *Northing)const + +{ /* BEGIN Convert_Geodetic_To_NZMG */ +/* + * The function Convert_Geodetic_To_NZMG converts geodetic (latitude and + * longitude) coordinates to New Zealand Map Grid projection (easting and northing) + * coordinates, according to the current ellipsoid and New Zealand Map Grid + * projection parameters. If any errors occur, the error code(s) are returned + * by the function, otherwise NZMG_NO_ERROR is returned. + * + * Latitude : Latitude (phi), in radians (input) + * Longitude : Longitude (lambda), in radians (input) + * Easting : Easting (X), in meters (output) + * Northing : Northing (Y), in meters (output) + */ + + Complex Zeta, z; + int n; + double dphi; + double du, dlam; + long Error_Code = NZMG_NO_ERROR; + +// if ((Latitude < MIN_LAT) || (Latitude > MAX_LAT)) +// { /* Latitude out of range */ +// Error_Code|= NZMG_LAT_ERROR; +// } +// if ((Longitude < MIN_LON) || (Longitude > MAX_LON)) +// { /* Longitude out of range */ +// Error_Code|= NZMG_LON_ERROR; +// } + + if (!Error_Code) + { /* no errors */ + dphi = (Latitude * (180.0 / M_PI) - NZMG_Origin_Lat) * 3600.0 * 1.0e-5; + du = A[9]; + for (n = 8; n >= 0; n--) + du = du * dphi + A[n]; + du *= dphi; + + dlam = Longitude - NZMG_Origin_Long; + + Zeta.real = du; + Zeta.imag = dlam; + + z.real = B[5].real; + z.imag = B[5].imag; + for (n = 4; n >= 0; n--) + { + z = Multiply(z, Zeta); + z = Add(B[n], z); + } + z = Multiply(z, Zeta); + + *Easting = (z.imag * NZMG_a) + NZMG_False_Easting; + *Northing = (z.real * NZMG_a) + NZMG_False_Northing; + +// if ((*Easting < NZMG_Min_Easting) || (*Easting > NZMG_Max_Easting)) +// Error_Code |= NZMG_EASTING_ERROR; +// if ((*Northing < NZMG_Min_Northing) || (*Northing > NZMG_Max_Northing)) +// Error_Code |= NZMG_NORTHING_ERROR; + } + return (Error_Code); +} /* END OF Convert_Geodetic_To_NZMG */ + + +long ossimNewZealandMapGridProjection::Convert_NZMG_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const + +{ /* Begin Convert_NZMG_To_Geodetic */ +/* + * The function Convert_NZMG_To_Geodetic converts New Zealand Map Grid projection + * (easting and northing) coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and New Zealand Map Grid projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise NZMG_NO_ERROR is returned. + * + * Easting : Easting (X), in meters (input) + * Northing : Northing (Y), in meters (input) + * Latitude : Latitude (phi), in radians (output) + * Longitude : Longitude (lambda), in radians (output) + */ + + int i, n; + Complex coeff; + Complex z, Zeta, Zeta_Numer, Zeta_Denom, Zeta_sqr; + double dphi; + long Error_Code = NZMG_NO_ERROR; + +// if ((Easting < NZMG_Min_Easting) || (Easting > NZMG_Max_Easting)) +// { /* Easting out of range */ +// Error_Code |= NZMG_EASTING_ERROR; +// } +// if ((Northing < NZMG_Min_Northing) || (Northing > NZMG_Max_Northing)) +// { /* Northing out of range */ +// Error_Code |= NZMG_NORTHING_ERROR; +// } + + if (!Error_Code) + { /* no errors */ + z.real = (Northing - NZMG_False_Northing) / NZMG_a; + z.imag = (Easting - NZMG_False_Easting) / NZMG_a; + + Zeta.real = C[5].real; + Zeta.imag = C[5].imag; + for (n = 4; n >= 0; n--) + { + Zeta = Multiply(Zeta, z); + Zeta = Add(C[n], Zeta); + } + Zeta = Multiply(Zeta, z); + + for (i = 0; i < 2; i++) + { + Zeta_Numer.real = 5.0 * B[5].real; + Zeta_Numer.imag = 5.0 * B[5].imag; + Zeta_Denom.real = 6.0 * B[5].real; + Zeta_Denom.imag = 6.0 * B[5].imag; + for (n = 4; n >= 1; n--) + { + Zeta_Numer = Multiply(Zeta_Numer, Zeta); + coeff.real = n * B[n].real; + coeff.imag = n * B[n].imag; + Zeta_Numer = Add(coeff, Zeta_Numer); + + Zeta_Denom = Multiply(Zeta_Denom, Zeta); + coeff.real = (n+1) * B[n].real; + coeff.imag = (n+1) * B[n].imag; + Zeta_Denom = Add(coeff, Zeta_Denom); + } + Zeta_sqr = Multiply(Zeta, Zeta); + + Zeta_Numer = Multiply(Zeta_Numer, Zeta_sqr); + Zeta_Numer = Add(z, Zeta_Numer); + + Zeta_Denom = Multiply(Zeta_Denom, Zeta); + Zeta_Denom = Add(B[0], Zeta_Denom); + + Zeta = Divide(Zeta_Numer, Zeta_Denom); + } + dphi = D[8]; + for (n = 7; n >= 0; n--) + dphi = dphi * Zeta.real + D[n]; + dphi *= Zeta.real; + + *Latitude = NZMG_Origin_Lat + (dphi * 1.0e5 / 3600.0); + *Latitude *= M_PI / 180.0; + *Longitude = NZMG_Origin_Long + Zeta.imag; + +// if ((*Longitude > M_PI) && (*Longitude - M_PI < 1.0e-6)) +// *Longitude = M_PI; + +// if ((*Latitude < MIN_LAT) || (*Latitude > MAX_LAT)) +// Error_Code|= NZMG_LAT_ERROR; +// if ((*Longitude < MIN_LON) || (*Longitude > MAX_LON)) +// Error_Code|= NZMG_LON_ERROR; + } + return (Error_Code); +} /* END OF Convert_NZMG_To_Geodetic */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimNewZealandMapGridProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimNewZealandMapGridProjection.h new file mode 100644 index 0000000000..c5b68dd44d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimNewZealandMapGridProjection.h @@ -0,0 +1,135 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimNewZealandMapGridProjection.h,v 1.3 2005/09/09 19:23:58 gpotts Exp $ +#ifndef ossimNewZealandMapGridProjection_HEADER +#define ossimNewZealandMapGridProjection_HEADER + +#include "ossimMapProjection.h" + + +class ossimNewZealandMapGridProjection : public ossimMapProjection +{ +public: + ossimNewZealandMapGridProjection(); + ~ossimNewZealandMapGridProjection(); + virtual ossimObject* dup()const + { + return new ossimNewZealandMapGridProjection(*this); + } + virtual void update(); + + virtual ossimGpt inverse(const ossimDpt &eastingNorthing)const; + virtual ossimDpt forward(const ossimGpt &latLon)const; + /*! + * SetFalseEasting. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEasting(double falseEasting); + + /*! + * SetFalseNorthing. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseNorthing(double falseNorthing); + + /*! + * Sets both false easting and northing values. The values are + * expected to be in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEastingNorthing(double falseEasting, double falseNorthing); + + void setDefaults(); + + double getFalseEasting()const{return NZMG_False_Easting;} + double getFalseNorthing()const{return NZMG_False_Northing;} + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); +protected: + + // these should be set to constant values that never change. The origin + // will be fixed and the false easting northings will also be fixed. + // + mutable double NZMG_Origin_Lat; /* Latitude of origin, in radians */ + mutable double NZMG_Origin_Long; /* Longitude of origin, in radians */ + mutable double NZMG_False_Northing; /* False northing, in meters */ + mutable double NZMG_False_Easting; /* False easting, in meters */ + mutable double NZMG_a; +/* Maximum variance for easting and northing values for International. */ + mutable double NZMG_Max_Easting; + mutable double NZMG_Max_Northing; + mutable double NZMG_Min_Easting; + mutable double NZMG_Min_Northing; + +/*! + * The function Convert_Geodetic_To_NZMG converts geodetic (latitude and + * longitude) coordinates to New Zealand Map Grid projection (easting and northing) + * coordinates, according to the current ellipsoid and New Zealand Map Grid + * projection parameters. If any errors occur, the error code(s) are returned + * by the function, otherwise NZMG_NO_ERROR is returned. + * + * Latitude : Latitude (phi), in radians (input) + * Longitude : Longitude (lambda), in radians (input) + * Easting : Easting (X), in meters (output) + * Northing : Northing (Y), in meters (output) + */ + long Convert_Geodetic_To_NZMG (double Latitude, + double Longitude, + double *Easting, + double *Northing)const; + + + +/*! + * The function Convert_NZMG_To_Geodetic converts New Zealand Map Grid projection + * (easting and northing) coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and New Zealand Map Grid projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise NZMG_NO_ERROR is returned. + * + * Easting : Easting (X), in meters (input) + * Northing : Northing (Y), in meters (input) + * Latitude : Latitude (phi), in radians (output) + * Longitude : Longitude (lambda), in radians (output) + */ + long Convert_NZMG_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const; + +TYPE_DATA +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimObliqueMercatorProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimObliqueMercatorProjection.cpp new file mode 100644 index 0000000000..5d1f2dd691 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimObliqueMercatorProjection.cpp @@ -0,0 +1,734 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimObliqueMercatorProjection.cpp,v 1.5 2004/01/08 21:49:22 jlargent Exp $ +#include "ossimObliqueMercatorProjection.h" +#include "base/common/ossimKeywordNames.h" + +#define OMERC_NO_ERROR 0x0000 +#define OMERC_LAT_ERROR 0x0001 +#define OMERC_LON_ERROR 0x0002 +#define OMERC_ORIGIN_LAT_ERROR 0x0004 +#define OMERC_LAT1_ERROR 0x0008 +#define OMERC_LAT2_ERROR 0x0010 +#define OMERC_LON1_ERROR 0x0020 +#define OMERC_LON2_ERROR 0x0040 +#define OMERC_LAT1_LAT2_ERROR 0x0080 +#define OMERC_DIFF_HEMISPHERE_ERROR 0x0100 +#define OMERC_EASTING_ERROR 0x0200 +#define OMERC_NORTHING_ERROR 0x0400 +#define OMERC_A_ERROR 0x0800 +#define OMERC_INV_F_ERROR 0x1000 +#define OMERC_SCALE_FACTOR_ERROR 0x2000 +#define OMERC_LON_WARNING 0x4000 + +RTTI_DEF1(ossimObliqueMercatorProjection, "ossimObliqueMercatorProjection", ossimMapProjection) + +#ifndef PI_OVER_2 +# define PI_OVER_2 ( M_PI / 2.0) +#endif +#ifndef PI_OVER_4 +# define PI_OVER_4 ( M_PI / 4.0) +#endif +#ifndef TWO_PI +# define TWO_PI (2.0 * M_PI) +#endif +#define MIN_SCALE_FACTOR 0.3 +#define MAX_SCALE_FACTOR 3.0 + +#define OMERC_t(lat, e_sinlat, e_over_2) (tan(PI_OVER_4 - lat / 2.0)) / \ + (pow((1 - e_sinlat) / (1 + e_sinlat), e_over_2)) + + +ossimObliqueMercatorProjection::ossimObliqueMercatorProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + : ossimMapProjection(ellipsoid, origin) +{ + setDefaults(); + update(); +} + +ossimObliqueMercatorProjection::ossimObliqueMercatorProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + const ossimGpt& point1, + const ossimGpt& point2, + double falseEasting, + double falseNorthing, + double scaleFactor) + : ossimMapProjection(ellipsoid, origin) +{ + setParameters(point1, point2, falseEasting, falseNorthing, scaleFactor); +} + +void ossimObliqueMercatorProjection::update() +{ + Set_Oblique_Mercator_Parameters(theEllipsoid.getA(), + theEllipsoid.getFlattening(), + theOrigin.latr(), + theCentralPoint1.latr(), + theCentralPoint1.lonr(), + theCentralPoint2.latr(), + theCentralPoint2.lonr(), + OMerc_False_Easting, + OMerc_False_Northing, + OMerc_Scale_Factor); + + ossimMapProjection::update(); +} + +void ossimObliqueMercatorProjection::setFalseEasting(double falseEasting) +{ + OMerc_False_Easting = falseEasting; + update(); +} + +void ossimObliqueMercatorProjection::setFalseNorthing(double falseNorthing) +{ + OMerc_False_Northing = falseNorthing; + update(); +} + +void ossimObliqueMercatorProjection::setFalseEastingNorthing(double falseEasting, double falseNorthing) +{ + OMerc_False_Easting = falseEasting; + OMerc_False_Northing = falseNorthing; + update(); + +} + +void ossimObliqueMercatorProjection::setCentralPoint1(const ossimGpt& point) +{ + theCentralPoint1 = point; + + update(); +} + +void ossimObliqueMercatorProjection::setCentralPoint2(const ossimGpt& point) +{ + theCentralPoint2 = point; + update(); +} + +void ossimObliqueMercatorProjection::setScaleFactor(double scaleFactor) +{ + OMerc_Scale_Factor = scaleFactor; + update(); +} + +void ossimObliqueMercatorProjection::setParameters(const ossimGpt& point1, + const ossimGpt& point2, + double falseEasting, + double falseNorthing, + double scaleFactor) +{ + theCentralPoint1 = point1; + theCentralPoint2 = point2; + OMerc_False_Easting = falseEasting; + OMerc_False_Northing = falseNorthing; + OMerc_Scale_Factor = scaleFactor; + + update(); +} + +void ossimObliqueMercatorProjection::setDefaults() +{ + // initialize the central points to be 5 degrees about the origin. + OMerc_Delta_Northing = 40000000.0; + OMerc_Delta_Easting = 40000000.0; + + theCentralPoint1.latd(theOrigin.latd() - 5.0); + theCentralPoint1.lond(theOrigin.lond() - 5.0); + theCentralPoint2.latd(theOrigin.latd() + 5.0); + theCentralPoint2.lond(theOrigin.lond() + 5.0); + + theCentralPoint1.clampLat(-90.0, 90.0); + theCentralPoint1.clampLon(-180.0, 180.0); + theCentralPoint2.clampLat(-90.0, 90.0); + theCentralPoint2.clampLon(-180.0, 180.0); + + OMerc_False_Easting = 0.0; + OMerc_False_Northing = 0.0; + + OMerc_Scale_Factor = 1.0; +} + + +ossimGpt ossimObliqueMercatorProjection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat = 0.0; + double lon = 0.0; + + Convert_Oblique_Mercator_To_Geodetic(eastingNorthing.x, + eastingNorthing.y, + &lat, + &lon); + + return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum); +} + +ossimDpt ossimObliqueMercatorProjection::forward(const ossimGpt &latLon)const +{ + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + Convert_Geodetic_To_Oblique_Mercator(gpt.latr(), + gpt.lonr(), + &easting, + &northing); + return ossimDpt(easting, northing); +} + +bool ossimObliqueMercatorProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const +{ + kwl.add(prefix, + ossimKeywordNames::FALSE_EASTING_KW, + OMerc_False_Easting, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_NORTHING_KW, + OMerc_False_Northing, + true); + + kwl.add(prefix, + ossimKeywordNames::SCALE_FACTOR_KW, + OMerc_Scale_Factor, + true); + + kwl.add(prefix, + ossimKeywordNames::CENTRAL_POINT1_LAT_KW, + theCentralPoint1.latd(), + true); + + kwl.add(prefix, + ossimKeywordNames::CENTRAL_POINT1_LON_KW, + theCentralPoint1.lond(), + true); + + kwl.add(prefix, + ossimKeywordNames::CENTRAL_POINT2_LAT_KW, + theCentralPoint2.latd(), + true); + + kwl.add(prefix, + ossimKeywordNames::CENTRAL_POINT2_LON_KW, + theCentralPoint2.lond(), + true); + + + return ossimMapProjection::saveState(kwl, prefix); +} + +bool ossimObliqueMercatorProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + bool flag = ossimMapProjection::loadState(kwl, prefix); + const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + const char* falseEasting = kwl.find(prefix, ossimKeywordNames::FALSE_EASTING_KW); + const char* falseNorthing = kwl.find(prefix, ossimKeywordNames::FALSE_NORTHING_KW); + const char* point1Lat = kwl.find(prefix, ossimKeywordNames::CENTRAL_POINT1_LAT_KW); + const char* point1Lon = kwl.find(prefix, ossimKeywordNames::CENTRAL_POINT1_LON_KW); + const char* point2Lat = kwl.find(prefix, ossimKeywordNames::CENTRAL_POINT2_LAT_KW); + const char* point2Lon = kwl.find(prefix, ossimKeywordNames::CENTRAL_POINT2_LON_KW); + const char* scale = kwl.find(prefix, ossimKeywordNames::SCALE_FACTOR_KW); + + setDefaults(); + if(ossimString(type) == STATIC_TYPE_NAME(ossimObliqueMercatorProjection)) + { + if(falseEasting) + { + OMerc_False_Easting = ossimString(falseEasting).toDouble(); + } + if(falseNorthing) + { + OMerc_False_Northing = ossimString(falseNorthing).toDouble(); + } + if(point1Lat&&point1Lon&&point2Lat&&point2Lon) + { + theCentralPoint1.latd(ossimString(point1Lat).toDouble()); + theCentralPoint1.lond(ossimString(point1Lon).toDouble()); + theCentralPoint2.latd(ossimString(point2Lat).toDouble()); + theCentralPoint2.lond(ossimString(point2Lon).toDouble()); + } + if(scale) + { + OMerc_Scale_Factor = ossimString(scale).toDouble(); + } + } + + update(); + + return flag; + +} + +/* + * FUNCTIONS + */ + +long ossimObliqueMercatorProjection::Set_Oblique_Mercator_Parameters(double a, + double f, + double Origin_Latitude, + double Latitude_1, + double Longitude_1, + double Latitude_2, + double Longitude_2, + double False_Easting, + double False_Northing, + double Scale_Factor) +{ /* BEGIN Set_Oblique_Mercator_Parameters */ +/* + * The function Set_Oblique_Mercator_Parameters receives the ellipsoid parameters and + * projection parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the function, + * otherwise OMERC_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude, in radians, at which the (input) + * point scale factor is 1.0 + * Latitude_1 : Latitude, in radians, of first point lying on + * central line (input) + * Longitude_1 : Longitude, in radians, of first point lying on + * central line (input) + * Latitude_2 : Latitude, in radians, of second point lying on + * central line (input) + * Longitude_2 : Longitude, in radians, of second point lying on + * central line (input) + * False_Easting : A coordinate value, in meters, assigned to the + * central meridian of the projection (input) + * False_Northing : A coordinate value, in meters, assigned to the + * origin latitude of the projection (input) + * Scale_Factor : Multiplier which reduces distances in the + * projection to the actual distance on the + * ellipsoid (input) + */ + +// double inv_f = 1 / f; + double es2, one_MINUS_es2; + double cos_olat, cos_olat2; + double sin_olat, sin_olat2, es2_sin_olat2; + double t0, t1, t2; + double D, D2, D2_MINUS_1, sqrt_D2_MINUS_1; + double H, L, LH; + double E2; + double F, G, J, P; + double dlon; + long Error_Code = OMERC_NO_ERROR; + +// if (a <= 0.0) +// { /* Semi-major axis must be greater than zero */ +// Error_Code |= OMERC_A_ERROR; +// } +// if ((inv_f < 250) || (inv_f > 350)) +// { /* Inverse flattening must be between 250 and 350 */ +// Error_Code |= OMERC_INV_F_ERROR; +// } +// if ((Origin_Latitude <= -PI_OVER_2) || (Origin_Latitude >= PI_OVER_2)) +// { /* origin latitude out of range - can not be at a pole */ +// Error_Code |= OMERC_ORIGIN_LAT_ERROR; +// } +// if ((Latitude_1 <= -PI_OVER_2) || (Latitude_1 >= PI_OVER_2)) +// { /* first latitude out of range - can not be at a pole */ +// Error_Code |= OMERC_LAT1_ERROR; +// } +// if ((Latitude_2 <= -PI_OVER_2) || (Latitude_2 >= PI_OVER_2)) +// { /* second latitude out of range - can not be at a pole */ +// Error_Code |= OMERC_LAT2_ERROR; +// } +// if (Latitude_1 == 0.0) +// { /* first latitude can not be at the equator */ +// Error_Code |= OMERC_LAT1_ERROR; +// } +// if (Latitude_1 == Latitude_2) +// { /* first and second latitudes can not be equal */ +// Error_Code |= OMERC_LAT1_LAT2_ERROR; +// } +// if (((Latitude_1 < 0.0) && (Latitude_2 > 0.0)) || +// ((Latitude_1 > 0.0) && (Latitude_2 < 0.0))) +// { /*first and second points can not be in different hemispheres */ +// Error_Code |= OMERC_DIFF_HEMISPHERE_ERROR; +// } +// if ((Longitude_1 < -PI) || (Longitude_1 > TWO_PI)) +// { /* first longitude out of range */ +// Error_Code |= OMERC_LON1_ERROR; +// } +// if ((Longitude_2 < -PI) || (Longitude_2 > TWO_PI)) +// { /* first longitude out of range */ +// Error_Code |= OMERC_LON2_ERROR; +// } +// if ((Scale_Factor < MIN_SCALE_FACTOR) || (Scale_Factor > MAX_SCALE_FACTOR)) +// { /* scale factor out of range */ +// Error_Code |= OMERC_SCALE_FACTOR_ERROR; +// } + if (!Error_Code) + { /* no errors */ + + OMerc_a = a; + OMerc_f = f; + OMerc_Origin_Lat = Origin_Latitude; + OMerc_Lat_1 = Latitude_1; + OMerc_Lat_2 = Latitude_2; + OMerc_Lon_1 = Longitude_1; + OMerc_Lon_2 = Longitude_2; + OMerc_Scale_Factor = Scale_Factor; + OMerc_False_Northing = False_Northing; + OMerc_False_Easting = False_Easting; + + es2 = 2 * OMerc_f - OMerc_f * OMerc_f; + es = sqrt(es2); + one_MINUS_es2 = 1 - es2; + es_OVER_2 = es / 2.0; + + cos_olat = cos(OMerc_Origin_Lat); + cos_olat2 = cos_olat * cos_olat; + sin_olat = sin(OMerc_Origin_Lat); + sin_olat2 = sin_olat * sin_olat; + es2_sin_olat2 = es2 * sin_olat2; + + OMerc_B = sqrt(1 + (es2 * cos_olat2 * cos_olat2) / one_MINUS_es2); + OMerc_A = (OMerc_a * OMerc_B * OMerc_Scale_Factor * sqrt(one_MINUS_es2)) / (1.0 - es2_sin_olat2); + A_over_B = OMerc_A / OMerc_B; + B_over_A = OMerc_B / OMerc_A; + + t0 = OMERC_t(OMerc_Origin_Lat, es * sin_olat, es_OVER_2); + t1 = OMERC_t(OMerc_Lat_1, es * sin(OMerc_Lat_1), es_OVER_2); + t2 = OMERC_t(OMerc_Lat_2, es * sin(OMerc_Lat_2), es_OVER_2); + + D = (OMerc_B * sqrt(one_MINUS_es2)) / (cos_olat * sqrt(1.0 - es2_sin_olat2)); + D2 = D * D; + if (D2 < 1.0) + D2 = 1.0; + D2_MINUS_1 = D2 - 1.0; + sqrt_D2_MINUS_1 = sqrt(D2_MINUS_1); + if (D2_MINUS_1 > 1.0e-10) + { + if (OMerc_Origin_Lat >= 0.0) + OMerc_E = (D + sqrt_D2_MINUS_1) * pow(t0, OMerc_B); + else + OMerc_E = (D - sqrt_D2_MINUS_1) * pow(t0, OMerc_B); + } + else + OMerc_E = D * pow(t0, OMerc_B); + H = pow(t1, OMerc_B); + L = pow(t2, OMerc_B); + F = OMerc_E / H; + G = (F - 1.0 / F) / 2.0; + E2 = OMerc_E * OMerc_E; + LH = L * H; + J = (E2 - LH) / (E2 + LH); + P = (L - H) / (L + H); + + dlon = OMerc_Lon_1 - OMerc_Lon_2; + if (dlon < -M_PI ) + OMerc_Lon_2 -= TWO_PI; + if (dlon > M_PI) + OMerc_Lon_2 += TWO_PI; + dlon = OMerc_Lon_1 - OMerc_Lon_2; + OMerc_Origin_Long = (OMerc_Lon_1 + OMerc_Lon_2) / 2.0 - (atan(J * tan(OMerc_B * dlon / 2.0) / P)) / OMerc_B; + + dlon = OMerc_Lon_1 - OMerc_Origin_Long; +// if (dlon < -M_PI ) +// OMerc_Origin_Long -= TWO_PI; +// if (dlon > M_PI) +// OMerc_Origin_Long += TWO_PI; + + dlon = OMerc_Lon_1 - OMerc_Origin_Long; + OMerc_gamma = atan(sin(OMerc_B * dlon) / G); + cos_gamma = cos(OMerc_gamma); + sin_gamma = sin(OMerc_gamma); + + OMerc_azimuth = asin(D * sin_gamma); + cos_azimuth = cos(OMerc_azimuth); + sin_azimuth = sin(OMerc_azimuth); + + if (OMerc_Origin_Lat >= 0) + OMerc_u = A_over_B * atan(sqrt_D2_MINUS_1/cos_azimuth); + else + OMerc_u = -A_over_B * atan(sqrt_D2_MINUS_1/cos_azimuth); + + } /* End if(!Error_Code) */ + return (Error_Code); +} /* End Set_Oblique_Mercator_Parameters */ + +void ossimObliqueMercatorProjection::Get_Oblique_Mercator_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Latitude_1, + double *Longitude_1, + double *Latitude_2, + double *Longitude_2, + double *False_Easting, + double *False_Northing, + double *Scale_Factor)const +{ /* Begin Get_Oblique_Mercator_Parameters */ +/* + * The function Get_Oblique_Mercator_Parameters returns the current ellipsoid + * parameters and Oblique Mercator projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude, in radians, at which the (output) + * point scale factor is 1.0 + * Latitude_1 : Latitude, in radians, of first point lying on + * central line (output) + * Longitude_1 : Longitude, in radians, of first point lying on + * central line (output) + * Latitude_2 : Latitude, in radians, of second point lying on + * central line (output) + * Longitude_2 : Longitude, in radians, of second point lying on + * central line (output) + * False_Easting : A coordinate value, in meters, assigned to the + * central meridian of the projection (output) + * False_Northing : A coordinate value, in meters, assigned to the + * origin latitude of the projection (output) + * Scale_Factor : Multiplier which reduces distances in the + * projection to the actual distance on the + * ellipsoid (output) + */ + + *a = OMerc_a; + *f = OMerc_f; + *Origin_Latitude = OMerc_Origin_Lat; + *Latitude_1 = OMerc_Lat_1; + *Longitude_1 = OMerc_Lon_1; + *Latitude_2 = OMerc_Lat_2; + *Longitude_2 = OMerc_Lon_2; + *Scale_Factor = OMerc_Scale_Factor; + *False_Easting = OMerc_False_Easting; + *False_Northing = OMerc_False_Northing; + + return; +} /* End Get_Azimuthal_Equidistant_Parameters */ + +long ossimObliqueMercatorProjection::Convert_Geodetic_To_Oblique_Mercator(double Latitude, + double Longitude, + double *Easting, + double *Northing)const +{ /* BEGIN Convert_Geodetic_To_Oblique_Mercator */ +/* + * The function Convert_Geodetic_To_Oblique_Mercator converts geodetic (latitude and + * longitude) coordinates to Oblique Mercator projection (easting and + * northing) coordinates, according to the current ellipsoid and Oblique Mercator + * projection parameters. If any errors occur, the error code(s) are returned + * by the function, otherwise OMERC_NO_ERROR is returned. + * + * Latitude : Latitude (phi), in radians (input) + * Longitude : Longitude (lambda), in radians (input) + * Easting : Easting (X), in meters (output) + * Northing : Northing (Y), in meters (output) + */ + + double dlam, B_dlam, cos_B_dlam; + double t, S, T, V, U; + double Q, Q_inv; + /* Coordinate axes defined with respect to the azimuth of the center line */ + /* Natural origin*/ + double v = 0; + double u = 0; + long Error_Code = OMERC_NO_ERROR; + +// if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2)) +// { /* Latitude out of range */ +// Error_Code |= OMERC_LAT_ERROR; +// } +// if ((Longitude < -M_PI) || (Longitude > TWO_PI)) +// { /* Longitude out of range */ +// Error_Code |= OMERC_LON_ERROR; +// } + if (!Error_Code) + { /* no errors */ + dlam = Longitude - OMerc_Origin_Long; + +// if (fabs(dlam) >= PI_OVER_2) +// { /* Distortion will result if Longitude is 90 degrees or more from the Central Meridian */ +// Error_Code |= OMERC_LON_WARNING; +// } + +// if (dlam > M_PI) +// { +// dlam -= TWO_PI; +// } +// if (dlam < -M_PI) +// { +// dlam += TWO_PI; +// } + + if (fabs(fabs(Latitude) - PI_OVER_2) > 1.0e-10) + { + t = OMERC_t(Latitude, es * sin(Latitude), es_OVER_2); + Q = OMerc_E / pow(t, OMerc_B); + Q_inv = 1.0 / Q; + S = (Q - Q_inv) / 2.0; + T = (Q + Q_inv) / 2.0; + B_dlam = OMerc_B * dlam; + V = sin(B_dlam); + U = ((-1.0 * V * cos_gamma) + (S * sin_gamma)) / T; + if (fabs(fabs(U) - 1.0) < 1.0e-10) + { /* Point projects into infinity */ + Error_Code |= OMERC_LON_ERROR; + } + else + { + v = A_over_B * log((1.0 - U) / (1.0 + U)) / 2.0; + cos_B_dlam = cos(B_dlam); + if (fabs(cos_B_dlam) < 1.0e-10) + u = OMerc_A * B_dlam; + else + u = A_over_B * atan(((S * cos_gamma) + (V * sin_gamma)) / cos_B_dlam); + } + } + else + { + if (Latitude > 0.0) + v = A_over_B * log(tan(PI_OVER_4 - (OMerc_gamma / 2.0))); + else + v = A_over_B * log(tan(PI_OVER_4 + (OMerc_gamma / 2.0))); + u = A_over_B * Latitude; + } + + + u = u - OMerc_u; + + *Easting = OMerc_False_Easting + v * cos_azimuth + u * sin_azimuth; + *Northing = OMerc_False_Northing + u * cos_azimuth - v * sin_azimuth; + + } + return (Error_Code); +} /* End Convert_Geodetic_To_Oblique_Mercator */ + + +long ossimObliqueMercatorProjection::Convert_Oblique_Mercator_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const +{ /* Begin Convert_Oblique_Mercator_To_Geodetic */ +/* + * The function Convert_Oblique_Mercator_To_Geodetic converts Oblique Mercator projection + * (easting and northing) coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Oblique Mercator projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise OMERC_NO_ERROR is returned. + * + * Easting : Easting (X), in meters (input) + * Northing : Northing (Y), in meters (input) + * Latitude : Latitude (phi), in radians (output) + * Longitude : Longitude (lambda), in radians (output) + */ + + double dx, dy; + /* Coordinate axes defined with respect to the azimuth of the center line */ + /* Natural origin*/ + double u, v; + double Q_prime, Q_prime_inv; + double S_prime, T_prime, V_prime, U_prime; + double t; + double es_sin; + double u_B_over_A; + double phi; + double temp_phi = 0.0; + long Error_Code = OMERC_NO_ERROR; + +// if ((Easting < (OMerc_False_Easting - OMerc_Delta_Easting)) +// || (Easting > (OMerc_False_Easting + OMerc_Delta_Easting))) +// { /* Easting out of range */ +// Error_Code |= OMERC_EASTING_ERROR; +// } +// if ((Northing < (OMerc_False_Northing - OMerc_Delta_Northing)) +// || (Northing > (OMerc_False_Northing + OMerc_Delta_Northing))) +// { /* Northing out of range */ +// Error_Code |= OMERC_NORTHING_ERROR; +// } + + if (!Error_Code) + { + dy = Northing - OMerc_False_Northing; + dx = Easting - OMerc_False_Easting; + v = dx * cos_azimuth - dy * sin_azimuth; + u = dy * cos_azimuth + dx * sin_azimuth; + u = u + OMerc_u; + Q_prime = exp(-1.0 * (v * B_over_A )); + Q_prime_inv = 1.0 / Q_prime; + S_prime = (Q_prime - Q_prime_inv) / 2.0; + T_prime = (Q_prime + Q_prime_inv) / 2.0; + u_B_over_A = u * B_over_A; + V_prime = sin(u_B_over_A); + U_prime = (V_prime * cos_gamma + S_prime * sin_gamma) / T_prime; + if (fabs(fabs(U_prime) - 1.0) < 1.0e-10) + { + if (U_prime > 0) + *Latitude = PI_OVER_2; + else + *Latitude = -PI_OVER_2; + *Longitude = OMerc_Origin_Long; + } + else + { + t = pow(OMerc_E / sqrt((1.0 + U_prime) / (1.0 - U_prime)), 1.0 / OMerc_B); + phi = PI_OVER_2 - 2.0 * atan(t); + while (fabs(phi - temp_phi) > 1.0e-10) + { + temp_phi = phi; + es_sin = es * sin(phi); + phi = PI_OVER_2 - 2.0 * atan(t * pow((1.0 - es_sin) / (1.0 + es_sin), es_OVER_2)); + } + *Latitude = phi; + *Longitude = OMerc_Origin_Long - atan2((S_prime * cos_gamma - V_prime * sin_gamma), cos(u_B_over_A)) / OMerc_B; + } + +// if (fabs(*Latitude) < 2.0e-7) /* force lat to 0 to avoid -0 degrees */ +// *Latitude = 0.0; +// if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */ +// *Latitude = PI_OVER_2; +// else if (*Latitude < -PI_OVER_2) +// *Latitude = -PI_OVER_2; + +// if (*Longitude > PI) +// *Longitude -= TWO_PI; +// if (*Longitude < -PI) +// *Longitude += TWO_PI; + +// if (fabs(*Longitude) < 2.0e-7) /* force lon to 0 to avoid -0 degrees */ +// *Longitude = 0.0; +// if (*Longitude > PI) /* force distorted values to 180, -180 degrees */ +// *Longitude = PI; +// else if (*Longitude < -PI) +// *Longitude = -PI; + +// if (fabs(*Longitude - OMerc_Origin_Long) >= PI_OVER_2) +// { /* Distortion will result if Longitude is 90 degrees or more from the Central Meridian */ +// Error_Code |= OMERC_LON_WARNING; +// } + + } + return (Error_Code); +} /* End Convert_Oblique_Mercator_To_Geodetic */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimObliqueMercatorProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimObliqueMercatorProjection.h new file mode 100644 index 0000000000..c8dd252d79 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimObliqueMercatorProjection.h @@ -0,0 +1,256 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimObliqueMercatorProjection.h,v 1.2 2005/09/09 19:23:58 gpotts Exp $ + +#ifndef ossimObliqueMercatorProjection_HEADER +#define ossimObliqueMercatorProjection_HEADER + +#include "ossimMapProjection.h" + +class ossimObliqueMercatorProjection : public ossimMapProjection +{ +public: + ossimObliqueMercatorProjection(const ossimEllipsoid& ellipsoid = ossimEllipsoid(), + const ossimGpt& origin = ossimGpt()); + + /*! + * Points 1 and 2 lie along the central line. + */ + ossimObliqueMercatorProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + const ossimGpt& point1, + const ossimGpt& point2, + double falseEasting, + double falseNorthing, + double scaleFactor); + + ~ossimObliqueMercatorProjection(){} + virtual ossimObject *dup()const + { + return new ossimObliqueMercatorProjection(*this); + } + + virtual ossimGpt inverse(const ossimDpt &eastingNorthing)const; + virtual ossimDpt forward(const ossimGpt &latLon)const; + virtual void update(); + + /*! + * SetFalseEasting. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEasting(double falseEasting); + + /*! + * SetFalseNorthing. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseNorthing(double falseNorthing); + + void setCentralPoint1(const ossimGpt& point); + void setCentralPoint2(const ossimGpt& point); + void setScaleFactor(double scaleFactor); + + void setParameters(const ossimGpt& point1, + const ossimGpt& point2, + double falseEasting, + double falseNorthing, + double scaleFactor); + /*! + * Sets both false easting and northing values. The values are + * expected to be in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEastingNorthing(double falseEasting, double falseNorthing); + + void setDefaults(); + + double getFalseEasting()const{return OMerc_False_Easting;} + double getFalseNorthing()const{return OMerc_False_Northing;} + const ossimGpt& getCentralPoint1()const{return theCentralPoint1;} + const ossimGpt& getCentralPoint2()const{return theCentralPoint2;} + double getScaleFactor()const{return OMerc_Scale_Factor;} + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); +protected: + + ossimGpt theCentralPoint1; + ossimGpt theCentralPoint2; + +//________________________GEOTRANS STUFF_____________________________________ + + mutable double OMerc_a; /* Semi-major axis of ellipsoid, in meters */ + mutable double OMerc_f; /* Flattening of ellipsoid */ + mutable double es; + mutable double es_OVER_2; + mutable double OMerc_A; + mutable double OMerc_B; + mutable double OMerc_E; + mutable double OMerc_gamma; + mutable double OMerc_azimuth; /* Azimuth of central line as it crosses origin lat */ + mutable double OMerc_Origin_Long; /* Longitude at center of projection */ + mutable double cos_gamma; + mutable double sin_gamma; + mutable double sin_azimuth; + mutable double cos_azimuth; + mutable double A_over_B; + mutable double B_over_A; + mutable double OMerc_u; /* Coordinates for center point (uc , vc), vc = 0 */ + /* at center lat and lon */ +/* Oblique Mercator projection Parameters */ + mutable double OMerc_Origin_Lat;/* Latitude of projection center, in radians */ + mutable double OMerc_Lat_1; /* Latitude of first point lying on central line */ + mutable double OMerc_Lon_1; /* Longitude of first point lying on central line */ + mutable double OMerc_Lat_2; /* Latitude of second point lying on central line */ + mutable double OMerc_Lon_2; /* Longitude of second point lying on central line */ + mutable double OMerc_Scale_Factor; /* Scale factor at projection center */ + mutable double OMerc_False_Northing; /* False northing, in meters, at projection center */ + mutable double OMerc_False_Easting; /* False easting, in meters, at projection center */ + + mutable double OMerc_Delta_Northing; + mutable double OMerc_Delta_Easting; + +/*! + * The function Set_Oblique_Mercator_Parameters receives the ellipsoid parameters and + * projection parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the function, + * otherwise OMERC_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude, in radians, at which the (input) + * point scale factor is 1.0 + * Latitude_1 : Latitude, in radians, of first point lying on + * central line (input) + * Longitude_1 : Longitude, in radians, of first point lying on + * central line (input) + * Latitude_2 : Latitude, in radians, of second point lying on + * central line (input) + * Longitude_2 : Longitude, in radians, of second point lying on + * central line (input) + * False_Easting : A coordinate value, in meters, assigned to the + * central meridian of the projection (input) + * False_Northing : A coordinate value, in meters, assigned to the + * origin latitude of the projection (input) + * Scale_Factor : Multiplier which reduces distances in the + * projection to the actual distance on the + * ellipsoid (input) + */ + long Set_Oblique_Mercator_Parameters(double a, + double f, + double Origin_Latitude, + double Latitude_1, + double Longitude_1, + double Latitude_2, + double Longitude_2, + double False_Easting, + double False_Northing, + double Scale_Factor); + + +/*! + * The function Get_Oblique_Mercator_Parameters returns the current ellipsoid + * parameters and Oblique Mercator projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude, in radians, at which the (output) + * point scale factor is 1.0 + * Latitude_1 : Latitude, in radians, of first point lying on + * central line (output) + * Longitude_1 : Longitude, in radians, of first point lying on + * central line (output) + * Latitude_2 : Latitude, in radians, of second point lying on + * central line (output) + * Longitude_2 : Longitude, in radians, of second point lying on + * central line (output) + * False_Easting : A coordinate value, in meters, assigned to the + * central meridian of the projection (output) + * False_Northing : A coordinate value, in meters, assigned to the + * origin latitude of the projection (output) + * Scale_Factor : Multiplier which reduces distances in the + * projection to the actual distance on the + * ellipsoid (output) + */ + void Get_Oblique_Mercator_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Latitude_1, + double *Longitude_1, + double *Latitude_2, + double *Longitude_2, + double *False_Easting, + double *False_Northing, + double *Scale_Factor)const; + + +/*! + * The function Convert_Geodetic_To_Oblique_Mercator converts geodetic (latitude and + * longitude) coordinates to Oblique Mercator projection (easting and + * northing) coordinates, according to the current ellipsoid and Oblique Mercator + * projection parameters. If any errors occur, the error code(s) are returned + * by the function, otherwise OMERC_NO_ERROR is returned. + * + * Latitude : Latitude (phi), in radians (input) + * Longitude : Longitude (lambda), in radians (input) + * Easting : Easting (X), in meters (output) + * Northing : Northing (Y), in meters (output) + */ + long Convert_Geodetic_To_Oblique_Mercator(double Latitude, + double Longitude, + double *Easting, + double *Northing)const; + + +/*! + * The function Convert_Oblique_Mercator_To_Geodetic converts Oblique Mercator projection + * (easting and northing) coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Oblique Mercator projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise OMERC_NO_ERROR is returned. + * + * Easting : Easting (X), in meters (input) + * Northing : Northing (Y), in meters (input) + * Latitude : Latitude (phi), in radians (output) + * Longitude : Longitude (lambda), in radians (output) + */ + long Convert_Oblique_Mercator_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimOrthoGraphicProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimOrthoGraphicProjection.cpp new file mode 100644 index 0000000000..9e34b03eab --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimOrthoGraphicProjection.cpp @@ -0,0 +1,501 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans OrthoGraphic projection code. +//******************************************************************* +// $Id: ossimOrthoGraphicProjection.cpp,v 1.12 2005/09/28 19:23:17 gpotts Exp $ + +#include <math.h> +#include "ossimOrthoGraphicProjection.h" +#include "base/common/ossimKeywordNames.h" + +RTTI_DEF1(ossimOrthoGraphicProjection, "ossimOrthoGraphicProjection", ossimMapProjection) +/***************************************************************************/ +/* + * DEFINES + */ +#ifndef PI_OVER_2 +# define PI_OVER_2 ( M_PI / 2.0) +#endif +#ifndef TWO_PI +# define TWO_PI (2.0 * M_PI) +#endif +#define MAX_LAT ( (M_PI * 90) / 180.0 ) /* 90 degrees in radians */ + + +#define ORTH_NO_ERROR 0x0000 +#define ORTH_LAT_ERROR 0x0001 +#define ORTH_LON_ERROR 0x0002 +#define ORTH_EASTING_ERROR 0x0004 +#define ORTH_NORTHING_ERROR 0x0008 +#define ORTH_ORIGIN_LAT_ERROR 0x0010 +#define ORTH_CENT_MER_ERROR 0x0020 +#define ORTH_A_ERROR 0x0040 +#define ORTH_B_ERROR 0x0080 +#define ORTH_A_LESS_B_ERROR 0x0100 +#define ORTH_RADIUS_ERROR 0x0200 + + +ossimOrthoGraphicProjection::ossimOrthoGraphicProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + :ossimMapProjection(ellipsoid, origin) +{ + setDefaults(); + update(); +} + +ossimOrthoGraphicProjection::ossimOrthoGraphicProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double falseEasting, + double falseNorthing) + :ossimMapProjection(ellipsoid, origin) +{ + Orth_False_Easting = falseEasting; + Orth_False_Northing = falseNorthing; + + update(); +} + +void ossimOrthoGraphicProjection::update() +{ + Set_Orthographic_Parameters(theEllipsoid.getA(), + theEllipsoid.getFlattening(), + theOrigin.latr(), + theOrigin.lonr(), + Orth_False_Easting, + Orth_False_Northing); + + ossimMapProjection::update(); +} + +void ossimOrthoGraphicProjection::setFalseEasting(double falseEasting) +{ + Orth_False_Easting = falseEasting; + update(); +} + +void ossimOrthoGraphicProjection::setFalseNorthing(double falseNorthing) +{ + Orth_False_Northing = falseNorthing; + update(); +} + +void ossimOrthoGraphicProjection::setDefaults() +{ + Orth_False_Easting = 0.0; + Orth_False_Northing = 0.0; +} + +void ossimOrthoGraphicProjection::setFalseEastingNorthing(double falseEasting, + double falseNorthing) +{ + Orth_False_Easting = falseEasting; + Orth_False_Northing = falseNorthing; + + update(); +} + +void ossimOrthoGraphicProjection::getGroundClipPoints(ossimGeoPolygon& gpts)const +{ + + gpts.addPoint(ossimGpt(theOrigin.latd(), + theOrigin.lond()-90.0, + 0.0, + theDatum)); + gpts.addPoint(ossimGpt(theOrigin.latd()+90.0, + theOrigin.lond(), + 0.0, + theDatum)); + gpts.addPoint(ossimGpt(theOrigin.latd(), + theOrigin.lond()+90.0, + 0.0, + theDatum)); + gpts.addPoint(ossimGpt(theOrigin.latd()-90.0, + theOrigin.lond(), + 0.0, + theDatum)); + + +} + +ossimGpt ossimOrthoGraphicProjection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat = 0.0; + double lon = 0.0; + ossimGpt result; + if(Convert_Orthographic_To_Geodetic(eastingNorthing.x, + eastingNorthing.y, + &lat, + &lon)==ORTH_NO_ERROR) + { + result.datum(theDatum); + result.latr(lat); + result.lonr(lon); + } + else + { + result.makeNan(); + } + + return result; +} + +ossimDpt ossimOrthoGraphicProjection::forward(const ossimGpt &latLon)const +{ + + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + ossimDpt result; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + if(Convert_Geodetic_To_Orthographic(gpt.latr(), + gpt.lonr(), + &easting, + &northing) == ORTH_NO_ERROR) + { + result = ossimDpt(easting, northing); + } + else + { + result.makeNan(); + } + + return result; +} + +bool ossimOrthoGraphicProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const +{ + kwl.add(prefix, + ossimKeywordNames::FALSE_EASTING_KW, + Orth_False_Easting, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_NORTHING_KW, + Orth_False_Northing, + true); + + return ossimMapProjection::saveState(kwl, prefix); +} + +bool ossimOrthoGraphicProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + bool flag = ossimMapProjection::loadState(kwl, prefix); + const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + const char* falseEasting = kwl.find(prefix, ossimKeywordNames::FALSE_EASTING_KW); + const char* falseNorthing = kwl.find(prefix, ossimKeywordNames::FALSE_NORTHING_KW); + + setDefaults(); + if(ossimString(type) == STATIC_TYPE_NAME(ossimOrthoGraphicProjection)) + { + if(falseEasting) + { + Orth_False_Easting = ossimString(falseEasting).toDouble(); + } + if(falseNorthing) + { + Orth_False_Northing = ossimString(falseNorthing).toDouble(); + } + } + update(); + + return flag; +} + +/***************************************************************************/ +/* + * FUNCTIONS + */ + + +long ossimOrthoGraphicProjection::Set_Orthographic_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing) +{ /* BEGIN Set_Orthographic_Parameters */ +/* + * The function Set_Orthographic_Parameters receives the ellipsoid parameters and + * projection parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the function, + * otherwise ORTH_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at which the (input) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + +// double inv_f = 1 / f; + long Error_Code = ORTH_NO_ERROR; + + if (a <= 0.0) + { /* Semi-major axis must be greater than zero */ + Error_Code |= ORTH_A_ERROR; + } +// if ((inv_f < 250) || (inv_f > 350)) +// { /* Inverse flattening must be between 250 and 350 */ +// Error_Code |= ORTH_INV_F_ERROR; +// } + if ((Origin_Latitude < -PI_OVER_2) || (Origin_Latitude > PI_OVER_2)) + { /* origin latitude out of range */ + Error_Code |= ORTH_ORIGIN_LAT_ERROR; + } + if ((Central_Meridian < -M_PI) || (Central_Meridian > TWO_PI)) + { /* origin longitude out of range */ + Error_Code |= ORTH_CENT_MER_ERROR; + } + if (!Error_Code) + { /* no errors */ + Orth_a = a; + Orth_f = f; + es2 = 2 * Orth_f - Orth_f * Orth_f; + es4 = es2 * es2; + es6 = es4 * es2; + Ra = Orth_a * (1.0 - es2 / 6.0 - 17.0 * es4 / 360.0 - 67.0 * es6 /3024.0); + Orth_Origin_Lat = Origin_Latitude; + Sin_Orth_Origin_Lat = sin(Orth_Origin_Lat); + Cos_Orth_Origin_Lat = cos(Orth_Origin_Lat); +// if (Central_Meridian > M_PI) +// Central_Meridian -= TWO_PI; + Orth_Origin_Long = Central_Meridian; + Orth_False_Easting = False_Easting; + Orth_False_Northing = False_Northing; + + } /* END OF if(!Error_Code) */ + + return (Error_Code); +} /* END OF Set_Orthographic_Parameters */ + + +void ossimOrthoGraphicProjection::Get_Orthographic_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const +{ /* BEGIN Get_Orthographic_Parameters */ +/* + * The function Get_Orthographic_Parameters returns the current ellipsoid + * parameters and Orthographic projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at which the (output) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + + *a = Orth_a; + *f = Orth_f; + *Origin_Latitude = Orth_Origin_Lat; + *Central_Meridian = Orth_Origin_Long; + *False_Easting = Orth_False_Easting; + *False_Northing = Orth_False_Northing; + + return; +} /* END OF Get_Orthographic_Parameters */ + + +long ossimOrthoGraphicProjection::Convert_Geodetic_To_Orthographic (double Latitude, + double Longitude, + double *Easting, + double *Northing)const + +{ /* BEGIN Convert_Geodetic_To_Orthographic */ +/* + * The function Convert_Geodetic_To_Orthographic converts geodetic (latitude and + * longitude) coordinates to Orthographic projection (easting and northing) + * coordinates, according to the current ellipsoid and Orthographic projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise ORTH_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + + double slat = sin(Latitude); + double clat = cos(Latitude); + double dlam; /* Longitude - Central Meridan */ + double clat_cdlam; + double cos_c; /* Value used to determine whether the point is beyond + viewing. If zero or positive, the point is within view. */ + long Error_Code = ORTH_NO_ERROR; + + if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2)) + { /* Latitude out of range */ + Error_Code |= ORTH_LAT_ERROR; + } + if ((Longitude < -M_PI) || (Longitude > TWO_PI)) + { /* Longitude out of range */ + Error_Code|= ORTH_LON_ERROR; + } + dlam = Longitude - Orth_Origin_Long; + clat_cdlam = clat * cos(dlam); + cos_c = Sin_Orth_Origin_Lat * slat + Cos_Orth_Origin_Lat * clat_cdlam; + if (cos_c < 0.0) + { /* Point is out of view. Will return longitude out of range message + since no point out of view is implemented. */ + Error_Code |= ORTH_LON_ERROR; + } + + if (!Error_Code) + { /* no errors */ + if (dlam > M_PI) + { + dlam -= TWO_PI; + } + if (dlam < -M_PI) + { + dlam += TWO_PI; + } + *Easting = Ra * clat * sin(dlam) + Orth_False_Easting; + *Northing = Ra * (Cos_Orth_Origin_Lat * slat - Sin_Orth_Origin_Lat * clat_cdlam) + + Orth_False_Northing; + } + return (Error_Code); + +} /* END OF Convert_Geodetic_To_Orthographic */ + + +long ossimOrthoGraphicProjection::Convert_Orthographic_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const +{ /* BEGIN Convert_Orthographic_To_Geodetic */ +/* + * The function Convert_Orthographic_To_Geodetic converts Orthographic projection + * (easting and northing) coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Orthographic projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise ORTH_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + + double cc; + double cos_cc, sin_cc; + double rho; + double dx, dy; + double atan_dx_over_dy; +// double temp; + double rho_OVER_Ra; + long Error_Code = ORTH_NO_ERROR; + + if ((Easting > (Orth_False_Easting + Ra)) || + (Easting < (Orth_False_Easting - Ra))) + { /* Easting out of range */ + Error_Code |= ORTH_EASTING_ERROR; + } + if ((Northing > (Orth_False_Northing + Ra)) || + (Northing < (Orth_False_Northing - Ra))) + { /* Northing out of range */ + Error_Code |= ORTH_NORTHING_ERROR; + } + if (!Error_Code) + { + double temp = sqrt(Easting * Easting + Northing * Northing); + + if ((temp > (Orth_False_Easting + Ra)) || (temp > (Orth_False_Northing + Ra)) || + (temp < (Orth_False_Easting - Ra)) || (temp < (Orth_False_Northing - Ra))) + { /* Point is outside of projection area */ + Error_Code |= ORTH_RADIUS_ERROR; + } + } + + if (!Error_Code) + { + dx = Easting - Orth_False_Easting; + dy = Northing - Orth_False_Northing; + atan_dx_over_dy = atan(dx / dy); + rho = sqrt(dx * dx + dy * dy); + if (rho == 0.0) + { + *Latitude = Orth_Origin_Lat; + *Longitude = Orth_Origin_Long; + } + else + { + rho_OVER_Ra = rho / Ra; + + if (rho_OVER_Ra > 1.0) + rho_OVER_Ra = 1.0; + else if (rho_OVER_Ra < -1.0) + rho_OVER_Ra = -1.0; + + cc = asin(rho_OVER_Ra); + cos_cc = cos(cc); + sin_cc = sin(cc); + *Latitude = asin(cos_cc * Sin_Orth_Origin_Lat + (dy * sin_cc * Cos_Orth_Origin_Lat / rho)); + + if (Orth_Origin_Lat == MAX_LAT) + *Longitude = Orth_Origin_Long - atan_dx_over_dy; + else if (Orth_Origin_Lat == -MAX_LAT) + *Longitude = Orth_Origin_Long + atan_dx_over_dy; + else + *Longitude = Orth_Origin_Long + atan(dx * sin_cc / (rho * + Cos_Orth_Origin_Lat * cos_cc - dy * Sin_Orth_Origin_Lat * sin_cc)); + +// if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */ +// *Latitude = PI_OVER_2; +// else if (*Latitude < -PI_OVER_2) +// *Latitude = -PI_OVER_2; + +// if (*Longitude > M_PI) +// *Longitude -= TWO_PI; +// if (*Longitude < -M_PI) +// *Longitude += TWO_PI; + +// if (*Longitude > M_PI) /* force distorted values to 180, -180 degrees */ +// *Longitude = M_PI; +// else if (*Longitude < -M_PI) +// *Longitude = -M_PI; + } + } + return (Error_Code); +} /* END OF Convert_Orthographic_To_Geodetic */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimOrthoGraphicProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimOrthoGraphicProjection.h new file mode 100644 index 0000000000..74fe9ac9a0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimOrthoGraphicProjection.h @@ -0,0 +1,196 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans OrthoGraphic projection code. +//******************************************************************* +// $Id: ossimOrthoGraphicProjection.h,v 1.6 2005/09/28 19:23:17 gpotts Exp $ + +#ifndef ossimOrthoGraphicProjection_HEADER +#define ossimOrthoGraphicProjection_HEADER + +#include "ossimMapProjection.h" + +class ossimOrthoGraphicProjection : public ossimMapProjection +{ +public: + + ossimOrthoGraphicProjection(const ossimEllipsoid& ellipsoid = ossimEllipsoid(), + const ossimGpt& origin = ossimGpt()); + ossimOrthoGraphicProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + const double falseEasting, + const double falseNorthing); + ~ossimOrthoGraphicProjection(){} + + virtual ossimObject *dup()const + { + return new ossimOrthoGraphicProjection(*this); + } + virtual void getGroundClipPoints(ossimGeoPolygon& gpts)const; + virtual ossimGpt inverse(const ossimDpt &eastingNorthing)const; + virtual ossimDpt forward(const ossimGpt &latLon)const; + virtual void update(); + /*! + * SetFalseEasting. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEasting(double falseEasting); + + /*! + * SetFalseNorthing. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseNorthing(double falseNorthing); + + /*! + * Sets both false easting and northing values. The values are + * expected to be in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEastingNorthing(double falseEasting, double falseNorthing); + + void setDefaults(); + + double getFalseEasting()const{return Orth_False_Easting;} + double getFalseNorthing()const{return Orth_False_Northing;} + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +private: + + //___________________GEOTRANS_______________________ + mutable double Orth_a; /* Semi-major axis of ellipsoid in meters */ + mutable double Orth_f; /* Flattening of ellipsoid */ + mutable double es2; /* Eccentricity (0.08181919084262188000) squared */ + mutable double es4; /* es2 * es2 */ + mutable double es6; /* es4 * es2 */ + mutable double Ra; /* Spherical Radius */ + +/* Orthographic projection Parameters */ + mutable double Orth_Origin_Lat; /* Latitude of origin in radians */ + mutable double Orth_Origin_Long; /* Longitude of origin in radians */ + mutable double Orth_False_Easting; + mutable double Orth_False_Northing; + mutable double Sin_Orth_Origin_Lat; /* sin(Orth_Origin_Lat) */ + mutable double Cos_Orth_Origin_Lat; /* cos(Orth_Origin_Lat) */ + +/*! + * The function Set_Orthographic_Parameters receives the ellipsoid parameters and + * Orthographic projcetion parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the function, + * otherwise ORTH_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at which the (input) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + long Set_Orthographic_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing); + + + +/*! + * The function Get_Orthographic_Parameters returns the current ellipsoid + * parameters and Orthographic projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at which the (output) + * point scale factor is 1.0 + * Origin_Longitude : Longitude in radians at the center of (output) + * the projection (central meridian) + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + void Get_Orthographic_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Origin_Longitude, + double *False_Easting, + double *False_Northing)const; + + + +/*! + * The function Convert_Geodetic_To_Orthographic converts geodetic (latitude and + * longitude) coordinates to Orthographic projection easting, and northing + * coordinates, according to the current ellipsoid and Orthographic projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise ORTH_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + long Convert_Geodetic_To_Orthographic (double Latitude, + double Longitude, + double *Easting, + double *Northing)const; + + +/*! + * The function Convert_Orthographic_To_Geodetic converts Orthographic projection + * easting and northing coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Orthographic projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise ORTH_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + long Convert_Orthographic_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimPolarStereoProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimPolarStereoProjection.cpp new file mode 100644 index 0000000000..ea9dede9af --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimPolarStereoProjection.cpp @@ -0,0 +1,562 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Polar Stereographic projection code. +//******************************************************************* +// $Id: ossimPolarStereoProjection.cpp,v 1.11 2004/01/08 21:49:22 jlargent Exp $ + +#include <math.h> +#include "ossimPolarStereoProjection.h" +#include "base/common/ossimKeywordNames.h" + +RTTI_DEF1(ossimPolarStereoProjection, "ossimPolarStereoProjection", ossimMapProjection) +/************************************************************************/ +/* DEFINES + * + */ + +#ifndef PI_OVER_2 +# define PI_OVER_2 ( M_PI / 2.0) +#endif +#ifndef TWO_PI +# define TWO_PI (2.0 * M_PI) +#endif +#define POLAR_POW(EsSin) pow((1.0 - EsSin) / (1.0 + EsSin), es_OVER_2) + +#define POLAR_NO_ERROR 0x0000 +#define POLAR_LAT_ERROR 0x0001 +#define POLAR_LON_ERROR 0x0002 +#define POLAR_ORIGIN_LAT_ERROR 0x0004 +#define POLAR_ORIGIN_LON_ERROR 0x0008 +#define POLAR_EASTING_ERROR 0x0010 +#define POLAR_NORTHING_ERROR 0x0020 +#define POLAR_A_ERROR 0x0040 +#define POLAR_B_ERROR 0x0080 +#define POLAR_A_LESS_B_ERROR 0x0100 +#define POLAR_RADIUS_ERROR 0x0200 + +/************************************************************************/ +/* GLOBAL DECLARATIONS + * + */ + +const double PI_Over_4 = (M_PI / 4.0); + +ossimPolarStereoProjection::ossimPolarStereoProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + :ossimMapProjection(ellipsoid, origin) +{ + setDefaults(); + update(); +// Polar_Delta_Easting = 12713601.0; +// Polar_Delta_Northing = 12713601.0; +} + +ossimPolarStereoProjection::ossimPolarStereoProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double falseEasting, + double falseNorthing) +{ + Polar_False_Easting = falseEasting; + Polar_False_Northing = falseNorthing; + Polar_Delta_Easting = 12713601.0; + Polar_Delta_Northing = 12713601.0; + + update(); +} + +void ossimPolarStereoProjection::update() +{ + Set_Polar_Stereographic_Parameters(theEllipsoid.getA(), + theEllipsoid.getFlattening(), + theOrigin.latr(), + theOrigin.lonr(), + Polar_False_Easting, + Polar_False_Northing); + + ossimMapProjection::update(); +} + +void ossimPolarStereoProjection::setFalseEasting(double falseEasting) +{ + Polar_False_Easting = falseEasting; + + update(); +} + +void ossimPolarStereoProjection::setFalseNorthing(double falseNorthing) +{ + Polar_False_Northing = falseNorthing; + + update(); +} + +void ossimPolarStereoProjection::setDefaults() +{ + Polar_False_Easting = 0.0; + Polar_False_Northing = 0.0; +} + +void ossimPolarStereoProjection::setFalseEastingNorthing(double falseEasting, + double falseNorthing) +{ + Polar_False_Easting = falseEasting; + Polar_False_Northing = falseNorthing; + + update(); +} + +ossimGpt ossimPolarStereoProjection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat = 0.0; + double lon = 0.0; + + Convert_Polar_Stereographic_To_Geodetic(eastingNorthing.x, + eastingNorthing.y, + &lat, + &lon); + + return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum); +} + +ossimDpt ossimPolarStereoProjection::forward(const ossimGpt &latLon)const +{ + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + Convert_Geodetic_To_Polar_Stereographic(gpt.latr(), + gpt.lonr(), + &easting, + &northing); + + return ossimDpt(easting, northing); +} + +bool ossimPolarStereoProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const +{ + kwl.add(prefix, + ossimKeywordNames::FALSE_EASTING_KW, + Polar_False_Easting, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_NORTHING_KW, + Polar_False_Northing, + true); + + return ossimMapProjection::saveState(kwl, prefix); +} + +bool ossimPolarStereoProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + bool flag = ossimMapProjection::loadState(kwl, prefix); + const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + const char* falseEasting = kwl.find(prefix, ossimKeywordNames::FALSE_EASTING_KW); + const char* falseNorthing = kwl.find(prefix, ossimKeywordNames::FALSE_NORTHING_KW); + + setDefaults(); + if(ossimString(type) == STATIC_TYPE_NAME(ossimPolarStereoProjection)) + { + if(falseEasting) + { + Polar_False_Easting = ossimString(falseEasting).toDouble(); + } + if(falseNorthing) + { + Polar_False_Northing = ossimString(falseNorthing).toDouble(); + } + } + + update(); + + return flag; +} + + +/************************************************************************/ +/* FUNCTIONS + * + */ + + +long ossimPolarStereoProjection::Set_Polar_Stereographic_Parameters (double a, + double f, + double Latitude_of_True_Scale, + double Longitude_Down_from_Pole, + double False_Easting, + double False_Northing) + +{ /* BEGIN Set_Polar_Stereographic_Parameters */ +/* + * The function Set_Polar_Stereographic_Parameters receives the ellipsoid + * parameters and Polar Stereograpic projection parameters as inputs, and + * sets the corresponding state variables. If any errors occur, error + * code(s) are returned by the function, otherwise POLAR_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Latitude_of_True_Scale : Latitude of true scale, in radians (input) + * Longitude_Down_from_Pole : Longitude down from pole, in radians (input) + * False_Easting : Easting (X) at center of projection, in meters (input) + * False_Northing : Northing (Y) at center of projection, in meters (input) + */ + + double es2; + double slat, clat; + double essin; + double one_PLUS_es, one_MINUS_es; + double pow_es; + double temp; +// double inv_f = 1 / f; + const double epsilon = 1.0e-2; + long Error_Code = POLAR_NO_ERROR; + +// if (a <= 0.0) +// { /* Semi-major axis must be greater than zero */ +// Error_Code |= POLAR_A_ERROR; +// } +// if ((inv_f < 250) || (inv_f > 350)) +// { /* Inverse flattening must be between 250 and 350 */ +// Error_Code |= POLAR_INV_F_ERROR; +// } +// if ((Latitude_of_True_Scale < -PI_OVER_2) || (Latitude_of_True_Scale > PI_OVER_2)) +// { /* Origin Latitude out of range */ +// Error_Code |= POLAR_ORIGIN_LAT_ERROR; +// } +// if ((Longitude_Down_from_Pole < -PI) || (Longitude_Down_from_Pole > TWO_PI)) +// { /* Origin Longitude out of range */ +// Error_Code |= POLAR_ORIGIN_LON_ERROR; +// } + + if (!Error_Code) + { /* no errors */ + + Polar_a = a; + two_Polar_a = 2.0 * Polar_a; + Polar_f = f; + + if (Longitude_Down_from_Pole > M_PI) + Longitude_Down_from_Pole -= TWO_PI; + if (Latitude_of_True_Scale < 0) + { + Southern_Hemisphere = 1; + Polar_Origin_Lat = -Latitude_of_True_Scale; + Polar_Origin_Long = -Longitude_Down_from_Pole; + } + else + { + Southern_Hemisphere = 0; + Polar_Origin_Lat = Latitude_of_True_Scale; + Polar_Origin_Long = Longitude_Down_from_Pole; + } + Polar_False_Easting = False_Easting; + Polar_False_Northing = False_Northing; + + es2 = 2 * Polar_f - Polar_f * Polar_f; + es = sqrt(es2); + es_OVER_2 = es / 2.0; + + if (fabs(fabs(Polar_Origin_Lat) - PI_OVER_2) > 1.0e-10) + { + slat = sin(Polar_Origin_Lat); + essin = es * slat; + pow_es = POLAR_POW(essin); + clat = cos(Polar_Origin_Lat); + mc = clat / sqrt(1.0 - essin * essin); + Polar_a_mc = Polar_a * mc; + tc = tan(PI_Over_4 - Polar_Origin_Lat / 2.0) / pow_es; + } + else + { + one_PLUS_es = 1.0 + es; + one_MINUS_es = 1.0 - es; + e4 = sqrt(pow(one_PLUS_es, one_PLUS_es) * pow(one_MINUS_es, one_MINUS_es)); + } + } + /* Calculate Radius */ + Convert_Geodetic_To_Polar_Stereographic(0, Polar_Origin_Long, + &temp, &Polar_Delta_Northing); + Polar_Delta_Northing = fabs(Polar_Delta_Northing) + epsilon; + Polar_Delta_Easting = Polar_Delta_Northing; + + + return (Error_Code); +} /* END OF Set_Polar_Stereographic_Parameters */ + + + +void ossimPolarStereoProjection::Get_Polar_Stereographic_Parameters (double *a, + double *f, + double *Latitude_of_True_Scale, + double *Longitude_Down_from_Pole, + double *False_Easting, + double *False_Northing)const + +{ /* BEGIN Get_Polar_Stereographic_Parameters */ +/* + * The function Get_Polar_Stereographic_Parameters returns the current + * ellipsoid parameters and Polar projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Latitude_of_True_Scale : Latitude of true scale, in radians (output) + * Longitude_Down_from_Pole : Longitude down from pole, in radians (output) + * False_Easting : Easting (X) at center of projection, in meters (output) + * False_Northing : Northing (Y) at center of projection, in meters (output) + */ + + *a = Polar_a; + *f = Polar_f; + *Latitude_of_True_Scale = Polar_Origin_Lat; + *Longitude_Down_from_Pole = Polar_Origin_Long; + *False_Easting = Polar_False_Easting; + *False_Northing = Polar_False_Northing; + + return; +} /* END OF Get_Polar_Stereographic_Parameters */ + + +long ossimPolarStereoProjection::Convert_Geodetic_To_Polar_Stereographic (double Latitude, + double Longitude, + double *Easting, + double *Northing)const + +{ /* BEGIN Convert_Geodetic_To_Polar_Stereographic */ + +/* + * The function Convert_Geodetic_To_Polar_Stereographic converts geodetic + * coordinates (latitude and longitude) to Polar Stereographic coordinates + * (easting and northing), according to the current ellipsoid + * and Polar Stereographic projection parameters. If any errors occur, error + * code(s) are returned by the function, otherwise POLAR_NO_ERROR is returned. + * + * Latitude : Latitude, in radians (input) + * Longitude : Longitude, in radians (input) + * Easting : Easting (X), in meters (output) + * Northing : Northing (Y), in meters (output) + */ + + double dlam; + double slat; + double essin; + double t; + double rho; + double pow_es; + long Error_Code = POLAR_NO_ERROR; + +// if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2)) +// { /* Latitude out of range */ +// Error_Code |= POLAR_LAT_ERROR; +// } +// if ((Latitude < 0) && (Southern_Hemisphere == 0)) +// { /* Latitude and Origin Latitude in different hemispheres */ +// Error_Code |= POLAR_LAT_ERROR; +// } +// if ((Latitude > 0) && (Southern_Hemisphere == 1)) +// { /* Latitude and Origin Latitude in different hemispheres */ +// Error_Code |= POLAR_LAT_ERROR; +// } +// if ((Longitude < -PI) || (Longitude > TWO_PI)) +// { /* Longitude out of range */ +// Error_Code |= POLAR_LON_ERROR; +// } + + + if (!Error_Code) + { /* no errors */ + + if (fabs(fabs(Latitude) - PI_OVER_2) < 1.0e-10) + { + *Easting = 0.0; + *Northing = 0.0; + } + else + { + if (Southern_Hemisphere != 0) + { + Longitude *= -1.0; + Latitude *= -1.0; + } + dlam = Longitude - Polar_Origin_Long; +// if (dlam > M_PI) +// { +// dlam -= TWO_PI; +// } +// if (dlam < -M_PI) +// { +// dlam += TWO_PI; +// } + slat = sin(Latitude); + essin = es * slat; + pow_es = POLAR_POW(essin); + t = tan(PI_Over_4 - Latitude / 2.0) / pow_es; + + if (fabs(fabs(Polar_Origin_Lat) - PI_OVER_2) > 1.0e-10) + rho = Polar_a_mc * t / tc; + else + rho = two_Polar_a * t / e4; + + *Easting = rho * sin(dlam) + Polar_False_Easting; + + if (Southern_Hemisphere != 0) + { + *Easting *= -1.0; + *Northing = rho * cos(dlam) + Polar_False_Northing; + } + else + *Northing = -rho * cos(dlam) + Polar_False_Northing; + + } + } + return (Error_Code); +} /* END OF Convert_Geodetic_To_Polar_Stereographic */ + + +long ossimPolarStereoProjection::Convert_Polar_Stereographic_To_Geodetic (double Easting, + double Northing, + double *Latitude, + double *Longitude)const + +{ /* BEGIN Convert_Polar_Stereographic_To_Geodetic */ +/* + * The function Convert_Polar_Stereographic_To_Geodetic converts Polar + * Stereographic coordinates (easting and northing) to geodetic + * coordinates (latitude and longitude) according to the current ellipsoid + * and Polar Stereographic projection Parameters. If any errors occur, the + * code(s) are returned by the function, otherwise POLAR_NO_ERROR + * is returned. + * + * Easting : Easting (X), in meters (input) + * Northing : Northing (Y), in meters (input) + * Latitude : Latitude, in radians (output) + * Longitude : Longitude, in radians (output) + * + */ + + double dy, dx; + double rho; + double t; + double PHI, sin_PHI; + double tempPHI = 0.0; + double essin; + double pow_es; +// double temp; + long Error_Code = POLAR_NO_ERROR; + +// if ((Easting > (Polar_False_Easting + Polar_Delta_Easting)) || +// (Easting < (Polar_False_Easting - Polar_Delta_Easting))) +// { /* Easting out of range */ +// Error_Code |= POLAR_EASTING_ERROR; +// } +// if ((Northing > (Polar_False_Northing + Polar_Delta_Northing)) || +// (Northing < (Polar_False_Northing - Polar_Delta_Northing))) +// { /* Northing out of range */ +// Error_Code |= POLAR_NORTHING_ERROR; +// } +// if (!Error_Code) +// { +// temp = sqrt(Easting * Easting + Northing * Northing); + +// if ((temp > (Polar_False_Easting + Polar_Delta_Easting)) || +// (temp > (Polar_False_Northing + Polar_Delta_Northing)) || +// (temp < (Polar_False_Easting - Polar_Delta_Easting)) || +// (temp < (Polar_False_Northing - Polar_Delta_Northing))) +// { /* Point is outside of projection area */ +// Error_Code |= POLAR_RADIUS_ERROR; +// } +// } + + if (!Error_Code) + { /* no errors */ + + dy = Northing - Polar_False_Northing; + dx = Easting - Polar_False_Easting; + if ((dy == 0.0) && (dx == 0.0)) + { + *Latitude = PI_OVER_2; + *Longitude = Polar_Origin_Long; + + } + else + { + if (Southern_Hemisphere != 0) + { + dy *= -1.0; + dx *= -1.0; + } + + rho = sqrt(dx * dx + dy * dy); + if (fabs(fabs(Polar_Origin_Lat) - PI_OVER_2) > 1.0e-10) + t = rho * tc / (Polar_a_mc); + else + t = rho * e4 / (two_Polar_a); + PHI = PI_OVER_2 - 2.0 * atan(t); + while (fabs(PHI - tempPHI) > 1.0e-10) + { + tempPHI = PHI; + sin_PHI = sin(PHI); + essin = es * sin_PHI; + pow_es = POLAR_POW(essin); + PHI = PI_OVER_2 - 2.0 * atan(t * pow_es); + } + *Latitude = PHI; + *Longitude = Polar_Origin_Long + atan2(dx, -dy); + +// if (*Longitude > M_PI) +// *Longitude -= TWO_PI; +// else if (*Longitude < -M_PI) +// *Longitude += TWO_PI; + + +// if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */ +// *Latitude = PI_OVER_2; +// else if (*Latitude < -PI_OVER_2) +// *Latitude = -PI_OVER_2; + +// if (*Longitude > M_PI) /* force distorted values to 180, -180 degrees */ +// *Longitude = M_PI; +// else if (*Longitude < -M_PI) +// *Longitude = -M_PI; + + } + if (Southern_Hemisphere != 0) + { + *Latitude *= -1.0; + *Longitude *= -1.0; + } + + } + return (Error_Code); +} /* END OF Convert_Polar_Stereographic_To_Geodetic */ + + + diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimPolarStereoProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimPolarStereoProjection.h new file mode 100644 index 0000000000..eceb760510 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimPolarStereoProjection.h @@ -0,0 +1,192 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Polar Stereographic projection code. +//******************************************************************* +// $Id: ossimPolarStereoProjection.h,v 1.5 2005/09/09 19:23:58 gpotts Exp $ + +#ifndef ossimPolarStereoProjection_HEADER +#define ossimPolarStereoProjection_HEADER + +#include "ossimMapProjection.h" + +class ossimPolarStereoProjection : public ossimMapProjection +{ +public: + ossimPolarStereoProjection(const ossimEllipsoid& ellipsoid = ossimEllipsoid(), + const ossimGpt& origin = ossimGpt()); + ossimPolarStereoProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + const double falseEasting, + const double falseNorthing); + ~ossimPolarStereoProjection(){} + + virtual ossimObject *dup()const{return new ossimPolarStereoProjection(*this);} + + virtual ossimGpt inverse(const ossimDpt &eastingNorthing)const; + virtual ossimDpt forward(const ossimGpt &latLon)const; + virtual void update(); + + /*! + * SetFalseEasting. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEasting(double falseEasting); + + /*! + * SetFalseNorthing. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseNorthing(double falseNorthing); + + /*! + * Sets both false easting and northing values. The values are + * expected to be in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEastingNorthing(double falseEasting, double falseNorthing); + + void setDefaults(); + + double getFalseEasting()const{return Polar_False_Easting;} + double getFalseNorthing()const{return Polar_False_Northing;} + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +private: + + mutable double Polar_a; /* Semi-major axis of ellipsoid in meters */ + mutable double Polar_f; /* Flattening of ellipsoid */ + mutable double es; /* Eccentricity of ellipsoid */ + mutable double es_OVER_2; /* es / 2.0 */ + mutable double Southern_Hemisphere; /* Flag variable */ + mutable double mc; + mutable double tc; + mutable double e4; + mutable double Polar_a_mc; /* Polar_a * mc */ + mutable double two_Polar_a; /* 2.0 * Polar_a */ + +/* Polar Stereographic projection Parameters */ + mutable double Polar_Origin_Lat; /* Latitude of origin in radians */ + mutable double Polar_Origin_Long; /* Longitude of origin in radians */ + mutable double Polar_False_Easting; /* False easting in meters */ + mutable double Polar_False_Northing; /* False northing in meters */ + +/* Maximum variance for easting and northing values for WGS 84. */ + mutable double Polar_Delta_Easting; + mutable double Polar_Delta_Northing; + +/*! + * The function Set_Polar_Stereographic_Parameters receives the ellipsoid + * parameters and Polar Stereograpic projection parameters as inputs, and + * sets the corresponding state variables. If any errors occur, error + * code(s) are returned by the function, otherwise POLAR_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Latitude_of_True_Scale : Latitude of true scale, in radians (input) + * Longitude_Down_from_Pole : Longitude down from pole, in radians (input) + * False_Easting : Easting (X) at center of projection, in meters (input) + * False_Northing : Northing (Y) at center of projection, in meters (input) + */ + long Set_Polar_Stereographic_Parameters (double a, + double f, + double Latitude_of_True_Scale, + double Longitude_Down_from_Pole, + double False_Easting, + double False_Northing); + + +/*! + * The function Get_Polar_Stereographic_Parameters returns the current + * ellipsoid parameters and Polar projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Latitude_of_True_Scale : Latitude of true scale, in radians (output) + * Longitude_Down_from_Pole : Longitude down from pole, in radians (output) + * False_Easting : Easting (X) at center of projection, in meters (output) + * False_Northing : Northing (Y) at center of projection, in meters (output) + */ + void Get_Polar_Stereographic_Parameters (double *a, + double *f, + double *Latitude_of_True_Scale, + double *Longitude_Down_from_Pole, + double *False_Easting, + double *False_Northing)const; + + +/*! + * The function Convert_Geodetic_To_Polar_Stereographic converts geodetic + * coordinates (latitude and longitude) to Polar Stereographic coordinates + * (easting and northing), according to the current ellipsoid + * and Polar Stereographic projection parameters. If any errors occur, error + * code(s) are returned by the function, otherwise POLAR_NO_ERROR is returned. + * + * Latitude : Latitude, in radians (input) + * Longitude : Longitude, in radians (input) + * Easting : Easting (X), in meters (output) + * Northing : Northing (Y), in meters (output) + */ + long Convert_Geodetic_To_Polar_Stereographic (double Latitude, + double Longitude, + double *Easting, + double *Northing)const; + + + +/*! + * The function Convert_Polar_Stereographic_To_Geodetic converts Polar + * Stereographic coordinates (easting and northing) to geodetic + * coordinates (latitude and longitude) according to the current ellipsoid + * and Polar Stereographic projection Parameters. If any errors occur, the + * code(s) are returned by the function, otherwise POLAR_NO_ERROR + * is returned. + * + * Easting : Easting (X), in meters (input) + * Northing : Northing (Y), in meters (input) + * Latitude : Latitude, in radians (output) + * Longitude : Longitude, in radians (output) + * + */ + long Convert_Polar_Stereographic_To_Geodetic (double Easting, + double Northing, + double *Latitude, + double *Longitude)const; + + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimPolarst.c b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimPolarst.c new file mode 100644 index 0000000000..04c9ce96e4 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimPolarst.c @@ -0,0 +1,505 @@ +/***************************************************************************/ +/* RSC IDENTIFIER: POLAR STEREOGRAPHIC + * + * + * ABSTRACT + * + * This component provides conversions between geodetic (latitude and + * longitude) coordinates and Polar Stereographic (easting and northing) + * coordinates. + * + * ERROR HANDLING + * + * This component checks parameters for valid values. If an invalid + * value is found the error code is combined with the current error code + * using the bitwise or. This combining allows multiple error codes to + * be returned. The possible error codes are: + * + * POLAR_NO_ERROR : No errors occurred in function + * POLAR_LAT_ERROR : Latitude outside of valid range + * (-90 to 90 degrees) + * POLAR_LON_ERROR : Longitude outside of valid range + * (-180 to 360 degrees) + * POLAR_ORIGIN_LAT_ERROR : Latitude of true scale outside of valid + * range (-90 to 90 degrees) + * POLAR_ORIGIN_LON_ERROR : Longitude down from pole outside of valid + * range (-180 to 360 degrees) + * POLAR_EASTING_ERROR : Easting outside of valid range, + * depending on ellipsoid and + * projection parameters + * POLAR_NORTHING_ERROR : Northing outside of valid range, + * depending on ellipsoid and + * projection parameters + * POLAR_RADIUS_ERROR : Coordinates too far from pole, + * depending on ellipsoid and + * projection parameters + * POLAR_A_ERROR : Semi-major axis less than or equal to zero + * POLAR_INV_F_ERROR : Inverse flattening outside of valid range + * (250 to 350) + * + * + * REUSE NOTES + * + * POLAR STEREOGRAPHIC is intended for reuse by any application that + * performs a Polar Stereographic projection. + * + * + * REFERENCES + * + * Further information on POLAR STEREOGRAPHIC can be found in the + * Reuse Manual. + * + * + * POLAR STEREOGRAPHIC originated from : + * U.S. Army Topographic Engineering Center + * Geospatial Information Division + * 7701 Telegraph Road + * Alexandria, VA 22310-3864 + * + * + * LICENSES + * + * None apply to this component. + * + * + * RESTRICTIONS + * + * POLAR STEREOGRAPHIC has no restrictions. + * + * + * ENVIRONMENT + * + * POLAR STEREOGRAPHIC was tested and certified in the following + * environments: + * + * 1. Solaris 2.5 with GCC, version 2.8.1 + * 2. Window 95 with MS Visual C++, version 6 + * + * + * MODIFICATIONS + * + * Date Description + * ---- ----------- + * 06-11-95 Original Code + * 03-01-97 Original Code + * + * + */ + + +/************************************************************************/ +/* + * INCLUDES + */ + +#include <math.h> +#include "ossimPolarst.h" + +/* + * math.h - Standard C math library + * polarst.h - Is for prototype error checking + */ + + +/************************************************************************/ +/* DEFINES + * + */ + + +#define PI 3.14159265358979323e0 /* PI */ +#define PI_OVER_2 (PI / 2.0) +#define TWO_PI (2.0 * PI) +#define POLAR_POW(EsSin) pow((1.0 - EsSin) / (1.0 + EsSin), es_OVER_2) + +/************************************************************************/ +/* GLOBAL DECLARATIONS + * + */ + +const double PI_Over_4 = (PI / 4.0); + +/* Ellipsoid Parameters, default to WGS 84 */ +static double Polar_a = 6378137.0; /* Semi-major axis of ellipsoid in meters */ +static double Polar_f = 1 / 298.257223563; /* Flattening of ellipsoid */ +static double es = 0.08181919084262188000; /* Eccentricity of ellipsoid */ +static double es_OVER_2 = .040909595421311; /* es / 2.0 */ +static double Southern_Hemisphere = 0; /* Flag variable */ +static double mc = 1.0; +static double tc = 1.0; +static double e4 = 1.0033565552493; +static double Polar_a_mc = 6378137.0; /* Polar_a * mc */ +static double two_Polar_a = 12756274.0; /* 2.0 * Polar_a */ + +/* Polar Stereographic projection Parameters */ +static double Polar_Origin_Lat = ((PI * 90) / 180); /* Latitude of origin in radians */ +static double Polar_Origin_Long = 0.0; /* Longitude of origin in radians */ +static double Polar_False_Easting = 0.0; /* False easting in meters */ +static double Polar_False_Northing = 0.0; /* False northing in meters */ + +/* Maximum variance for easting and northing values for WGS 84. */ +static double Polar_Delta_Easting = 12713601.0; +static double Polar_Delta_Northing = 12713601.0; + +/* These state variables are for optimization purposes. The only function + * that should modify them is Set_Polar_Stereographic_Parameters. + */ + + +/************************************************************************/ +/* FUNCTIONS + * + */ + + +long Set_Polar_Stereographic_Parameters (double a, + double f, + double Latitude_of_True_Scale, + double Longitude_Down_from_Pole, + double False_Easting, + double False_Northing) + +{ /* BEGIN Set_Polar_Stereographic_Parameters */ +/* + * The function Set_Polar_Stereographic_Parameters receives the ellipsoid + * parameters and Polar Stereograpic projection parameters as inputs, and + * sets the corresponding state variables. If any errors occur, error + * code(s) are returned by the function, otherwise POLAR_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Latitude_of_True_Scale : Latitude of true scale, in radians (input) + * Longitude_Down_from_Pole : Longitude down from pole, in radians (input) + * False_Easting : Easting (X) at center of projection, in meters (input) + * False_Northing : Northing (Y) at center of projection, in meters (input) + */ + + double es2; + double slat, clat; + double essin; + double one_PLUS_es, one_MINUS_es; + double pow_es; + double temp; + double inv_f = 1 / f; + const double epsilon = 1.0e-2; + long Error_Code = POLAR_NO_ERROR; + + if (a <= 0.0) + { /* Semi-major axis must be greater than zero */ + Error_Code |= POLAR_A_ERROR; + } + if ((inv_f < 250) || (inv_f > 350)) + { /* Inverse flattening must be between 250 and 350 */ + Error_Code |= POLAR_INV_F_ERROR; + } + if ((Latitude_of_True_Scale < -PI_OVER_2) || (Latitude_of_True_Scale > PI_OVER_2)) + { /* Origin Latitude out of range */ + Error_Code |= POLAR_ORIGIN_LAT_ERROR; + } + if ((Longitude_Down_from_Pole < -PI) || (Longitude_Down_from_Pole > TWO_PI)) + { /* Origin Longitude out of range */ + Error_Code |= POLAR_ORIGIN_LON_ERROR; + } + + if (!Error_Code) + { /* no errors */ + + Polar_a = a; + two_Polar_a = 2.0 * Polar_a; + Polar_f = f; + + if (Longitude_Down_from_Pole > PI) + Longitude_Down_from_Pole -= TWO_PI; + if (Latitude_of_True_Scale < 0) + { + Southern_Hemisphere = 1; + Polar_Origin_Lat = -Latitude_of_True_Scale; + Polar_Origin_Long = -Longitude_Down_from_Pole; + } + else + { + Southern_Hemisphere = 0; + Polar_Origin_Lat = Latitude_of_True_Scale; + Polar_Origin_Long = Longitude_Down_from_Pole; + } + Polar_False_Easting = False_Easting; + Polar_False_Northing = False_Northing; + + es2 = 2 * Polar_f - Polar_f * Polar_f; + es = sqrt(es2); + es_OVER_2 = es / 2.0; + + if (fabs(fabs(Polar_Origin_Lat) - PI_OVER_2) > 1.0e-10) + { + slat = sin(Polar_Origin_Lat); + essin = es * slat; + pow_es = POLAR_POW(essin); + clat = cos(Polar_Origin_Lat); + mc = clat / sqrt(1.0 - essin * essin); + Polar_a_mc = Polar_a * mc; + tc = tan(PI_Over_4 - Polar_Origin_Lat / 2.0) / pow_es; + } + else + { + one_PLUS_es = 1.0 + es; + one_MINUS_es = 1.0 - es; + e4 = sqrt(pow(one_PLUS_es, one_PLUS_es) * pow(one_MINUS_es, one_MINUS_es)); + } + } + /* Calculate Radius */ + Convert_Geodetic_To_Polar_Stereographic(0, Polar_Origin_Long, + &temp, &Polar_Delta_Northing); + Polar_Delta_Northing = fabs(Polar_Delta_Northing) + epsilon; + Polar_Delta_Easting = Polar_Delta_Northing; + + + return (Error_Code); +} /* END OF Set_Polar_Stereographic_Parameters */ + + + +void Get_Polar_Stereographic_Parameters (double *a, + double *f, + double *Latitude_of_True_Scale, + double *Longitude_Down_from_Pole, + double *False_Easting, + double *False_Northing) + +{ /* BEGIN Get_Polar_Stereographic_Parameters */ +/* + * The function Get_Polar_Stereographic_Parameters returns the current + * ellipsoid parameters and Polar projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Latitude_of_True_Scale : Latitude of true scale, in radians (output) + * Longitude_Down_from_Pole : Longitude down from pole, in radians (output) + * False_Easting : Easting (X) at center of projection, in meters (output) + * False_Northing : Northing (Y) at center of projection, in meters (output) + */ + + *a = Polar_a; + *f = Polar_f; + *Latitude_of_True_Scale = Polar_Origin_Lat; + *Longitude_Down_from_Pole = Polar_Origin_Long; + *False_Easting = Polar_False_Easting; + *False_Northing = Polar_False_Northing; + return; +} /* END OF Get_Polar_Stereographic_Parameters */ + + +long Convert_Geodetic_To_Polar_Stereographic (double Latitude, + double Longitude, + double *Easting, + double *Northing) + +{ /* BEGIN Convert_Geodetic_To_Polar_Stereographic */ + +/* + * The function Convert_Geodetic_To_Polar_Stereographic converts geodetic + * coordinates (latitude and longitude) to Polar Stereographic coordinates + * (easting and northing), according to the current ellipsoid + * and Polar Stereographic projection parameters. If any errors occur, error + * code(s) are returned by the function, otherwise POLAR_NO_ERROR is returned. + * + * Latitude : Latitude, in radians (input) + * Longitude : Longitude, in radians (input) + * Easting : Easting (X), in meters (output) + * Northing : Northing (Y), in meters (output) + */ + + double dlam; + double slat; + double essin; + double t; + double rho; + double pow_es; + long Error_Code = POLAR_NO_ERROR; + + if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2)) + { /* Latitude out of range */ + Error_Code |= POLAR_LAT_ERROR; + } + if ((Latitude < 0) && (Southern_Hemisphere == 0)) + { /* Latitude and Origin Latitude in different hemispheres */ + Error_Code |= POLAR_LAT_ERROR; + } + if ((Latitude > 0) && (Southern_Hemisphere == 1)) + { /* Latitude and Origin Latitude in different hemispheres */ + Error_Code |= POLAR_LAT_ERROR; + } + if ((Longitude < -PI) || (Longitude > TWO_PI)) + { /* Longitude out of range */ + Error_Code |= POLAR_LON_ERROR; + } + + + if (!Error_Code) + { /* no errors */ + + if (fabs(fabs(Latitude) - PI_OVER_2) < 1.0e-10) + { + *Easting = 0.0; + *Northing = 0.0; + } + else + { + if (Southern_Hemisphere != 0) + { + Longitude *= -1.0; + Latitude *= -1.0; + } + dlam = Longitude - Polar_Origin_Long; + if (dlam > PI) + { + dlam -= TWO_PI; + } + if (dlam < -PI) + { + dlam += TWO_PI; + } + slat = sin(Latitude); + essin = es * slat; + pow_es = POLAR_POW(essin); + t = tan(PI_Over_4 - Latitude / 2.0) / pow_es; + + if (fabs(fabs(Polar_Origin_Lat) - PI_OVER_2) > 1.0e-10) + rho = Polar_a_mc * t / tc; + else + rho = two_Polar_a * t / e4; + + *Easting = rho * sin(dlam) + Polar_False_Easting; + + if (Southern_Hemisphere != 0) + { + *Easting *= -1.0; + *Northing = rho * cos(dlam) + Polar_False_Northing; + } + else + *Northing = -rho * cos(dlam) + Polar_False_Northing; + + } + } + return (Error_Code); +} /* END OF Convert_Geodetic_To_Polar_Stereographic */ + + +long Convert_Polar_Stereographic_To_Geodetic (double Easting, + double Northing, + double *Latitude, + double *Longitude) + +{ /* BEGIN Convert_Polar_Stereographic_To_Geodetic */ +/* + * The function Convert_Polar_Stereographic_To_Geodetic converts Polar + * Stereographic coordinates (easting and northing) to geodetic + * coordinates (latitude and longitude) according to the current ellipsoid + * and Polar Stereographic projection Parameters. If any errors occur, the + * code(s) are returned by the function, otherwise POLAR_NO_ERROR + * is returned. + * + * Easting : Easting (X), in meters (input) + * Northing : Northing (Y), in meters (input) + * Latitude : Latitude, in radians (output) + * Longitude : Longitude, in radians (output) + * + */ + + double dy, dx; + double rho; + double t; + double PHI, sin_PHI; + double tempPHI = 0.0; + double essin; + double pow_es; + double temp; + long Error_Code = POLAR_NO_ERROR; + + if ((Easting > (Polar_False_Easting + Polar_Delta_Easting)) || + (Easting < (Polar_False_Easting - Polar_Delta_Easting))) + { /* Easting out of range */ + Error_Code |= POLAR_EASTING_ERROR; + } + if ((Northing > (Polar_False_Northing + Polar_Delta_Northing)) || + (Northing < (Polar_False_Northing - Polar_Delta_Northing))) + { /* Northing out of range */ + Error_Code |= POLAR_NORTHING_ERROR; + } + if (!Error_Code) + { + temp = sqrt(Easting * Easting + Northing * Northing); + + if ((temp > (Polar_False_Easting + Polar_Delta_Easting)) || + (temp > (Polar_False_Northing + Polar_Delta_Northing)) || + (temp < (Polar_False_Easting - Polar_Delta_Easting)) || + (temp < (Polar_False_Northing - Polar_Delta_Northing))) + { /* Point is outside of projection area */ + Error_Code |= POLAR_RADIUS_ERROR; + } + } + + if (!Error_Code) + { /* no errors */ + + dy = Northing - Polar_False_Northing; + dx = Easting - Polar_False_Easting; + if ((dy == 0.0) && (dx == 0.0)) + { + *Latitude = PI_OVER_2; + *Longitude = Polar_Origin_Long; + + } + else + { + if (Southern_Hemisphere != 0) + { + dy *= -1.0; + dx *= -1.0; + } + + rho = sqrt(dx * dx + dy * dy); + if (fabs(fabs(Polar_Origin_Lat) - PI_OVER_2) > 1.0e-10) + t = rho * tc / (Polar_a_mc); + else + t = rho * e4 / (two_Polar_a); + PHI = PI_OVER_2 - 2.0 * atan(t); + while (fabs(PHI - tempPHI) > 1.0e-10) + { + tempPHI = PHI; + sin_PHI = sin(PHI); + essin = es * sin_PHI; + pow_es = POLAR_POW(essin); + PHI = PI_OVER_2 - 2.0 * atan(t * pow_es); + } + *Latitude = PHI; + *Longitude = Polar_Origin_Long + atan2(dx, -dy); + + if (*Longitude > PI) + *Longitude -= TWO_PI; + else if (*Longitude < -PI) + *Longitude += TWO_PI; + + + if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */ + *Latitude = PI_OVER_2; + else if (*Latitude < -PI_OVER_2) + *Latitude = -PI_OVER_2; + + if (*Longitude > PI) /* force distorted values to 180, -180 degrees */ + *Longitude = PI; + else if (*Longitude < -PI) + *Longitude = -PI; + + } + if (Southern_Hemisphere != 0) + { + *Latitude *= -1.0; + *Longitude *= -1.0; + } + + } + return (Error_Code); +} /* END OF Convert_Polar_Stereographic_To_Geodetic */ + + + diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimPolarst.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimPolarst.h new file mode 100644 index 0000000000..60b8aa00c9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimPolarst.h @@ -0,0 +1,202 @@ +#ifndef POLARST_H + #define POLARST_H +/***************************************************************************/ +/* RSC IDENTIFIER: POLAR STEREOGRAPHIC + * + * + * ABSTRACT + * + * This component provides conversions between geodetic (latitude and + * longitude) coordinates and Polar Stereographic (easting and northing) + * coordinates. + * + * ERROR HANDLING + * + * This component checks parameters for valid values. If an invalid + * value is found the error code is combined with the current error code + * using the bitwise or. This combining allows multiple error codes to + * be returned. The possible error codes are: + * + * POLAR_NO_ERROR : No errors occurred in function + * POLAR_LAT_ERROR : Latitude outside of valid range + * (-90 to 90 degrees) + * POLAR_LON_ERROR : Longitude outside of valid range + * (-180 to 360 degrees) + * POLAR_ORIGIN_LAT_ERROR : Latitude of true scale outside of valid + * range (-90 to 90 degrees) + * POLAR_ORIGIN_LON_ERROR : Longitude down from pole outside of valid + * range (-180 to 360 degrees) + * POLAR_EASTING_ERROR : Easting outside of valid range, + * depending on ellipsoid and + * projection parameters + * POLAR_NORTHING_ERROR : Northing outside of valid range, + * depending on ellipsoid and + * projection parameters + * POLAR_RADIUS_ERROR : Coordinates too far from pole, + * depending on ellipsoid and + * projection parameters + * POLAR_A_ERROR : Semi-major axis less than or equal to zero + * POLAR_INV_F_ERROR : Inverse flattening outside of valid range + * (250 to 350) + * + * + * REUSE NOTES + * + * POLAR STEREOGRAPHIC is intended for reuse by any application that + * performs a Polar Stereographic projection. + * + * + * REFERENCES + * + * Further information on POLAR STEREOGRAPHIC can be found in the + * Reuse Manual. + * + * + * POLAR STEREOGRAPHIC originated from : + * U.S. Army Topographic Engineering Center + * Geospatial Information Division + * 7701 Telegraph Road + * Alexandria, VA 22310-3864 + * + * + * LICENSES + * + * None apply to this component. + * + * + * RESTRICTIONS + * + * POLAR STEREOGRAPHIC has no restrictions. + * + * + * ENVIRONMENT + * + * POLAR STEREOGRAPHIC was tested and certified in the following + * environments: + * + * 1. Solaris 2.5 with GCC, version 2.8.1 + * 2. Window 95 with MS Visual C++, version 6 + * + * + * MODIFICATIONS + * + * Date Description + * ---- ----------- + * 06-11-95 Original Code + * 03-01-97 Original Code + * + * + */ + + +/**********************************************************************/ +/* + * DEFINES + */ + + #define POLAR_NO_ERROR 0x0000 + #define POLAR_LAT_ERROR 0x0001 + #define POLAR_LON_ERROR 0x0002 + #define POLAR_ORIGIN_LAT_ERROR 0x0004 + #define POLAR_ORIGIN_LON_ERROR 0x0008 + #define POLAR_EASTING_ERROR 0x0010 + #define POLAR_NORTHING_ERROR 0x0020 + #define POLAR_A_ERROR 0x0040 + #define POLAR_INV_F_ERROR 0x0080 + #define POLAR_RADIUS_ERROR 0x0100 + +/**********************************************************************/ +/* + * FUNCTION PROTOTYPES + */ + +/* ensure proper linkage to c++ programs */ + #ifdef __cplusplus +extern "C" { + #endif + + long Set_Polar_Stereographic_Parameters (double a, + double f, + double Latitude_of_True_Scale, + double Longitude_Down_from_Pole, + double False_Easting, + double False_Northing); +/* + * The function Set_Polar_Stereographic_Parameters receives the ellipsoid + * parameters and Polar Stereograpic projection parameters as inputs, and + * sets the corresponding state variables. If any errors occur, error + * code(s) are returned by the function, otherwise POLAR_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Latitude_of_True_Scale : Latitude of true scale, in radians (input) + * Longitude_Down_from_Pole : Longitude down from pole, in radians (input) + * False_Easting : Easting (X) at center of projection, in meters (input) + * False_Northing : Northing (Y) at center of projection, in meters (input) + */ + + + void Get_Polar_Stereographic_Parameters (double *a, + double *f, + double *Latitude_of_True_Scale, + double *Longitude_Down_from_Pole, + double *False_Easting, + double *False_Northing); +/* + * The function Get_Polar_Stereographic_Parameters returns the current + * ellipsoid parameters and Polar projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Latitude_of_True_Scale : Latitude of true scale, in radians (output) + * Longitude_Down_from_Pole : Longitude down from pole, in radians (output) + * False_Easting : Easting (X) at center of projection, in meters (output) + * False_Northing : Northing (Y) at center of projection, in meters (output) + */ + + + long Convert_Geodetic_To_Polar_Stereographic (double Latitude, + double Longitude, + double *Easting, + double *Northing); +/* + * The function Convert_Geodetic_To_Polar_Stereographic converts geodetic + * coordinates (latitude and longitude) to Polar Stereographic coordinates + * (easting and northing), according to the current ellipsoid + * and Polar Stereographic projection parameters. If any errors occur, error + * code(s) are returned by the function, otherwise POLAR_NO_ERROR is returned. + * + * Latitude : Latitude, in radians (input) + * Longitude : Longitude, in radians (input) + * Easting : Easting (X), in meters (output) + * Northing : Northing (Y), in meters (output) + */ + + + + long Convert_Polar_Stereographic_To_Geodetic (double Easting, + double Northing, + double *Latitude, + double *Longitude); + +/* + * The function Convert_Polar_Stereographic_To_Geodetic converts Polar + * Stereographic coordinates (easting and northing) to geodetic + * coordinates (latitude and longitude) according to the current ellipsoid + * and Polar Stereographic projection Parameters. If any errors occur, the + * code(s) are returned by the function, otherwise POLAR_NO_ERROR + * is returned. + * + * Easting : Easting (X), in meters (input) + * Northing : Northing (Y), in meters (input) + * Latitude : Latitude, in radians (output) + * Longitude : Longitude, in radians (output) + * + */ + + #ifdef __cplusplus +} + #endif + +#endif /* POLARST_H */ + diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimPolyconicProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimPolyconicProjection.cpp new file mode 100644 index 0000000000..c3af40d504 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimPolyconicProjection.cpp @@ -0,0 +1,529 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Polyconic projection code. +//******************************************************************* +// $Id: ossimPolyconicProjection.cpp,v 1.12 2004/01/08 21:49:22 jlargent Exp $ + +#include <math.h> +#include "ossimPolyconicProjection.h" +#include "base/common/ossimKeywordNames.h" + +RTTI_DEF1(ossimPolyconicProjection, "ossimPolyconicProjection", ossimMapProjection) +/***************************************************************************/ +/* + * DEFINES + */ +#ifndef PI_OVER_2 +# define PI_OVER_2 ( M_PI / 2.0) +#endif +#ifndef TWO_PI +# define TWO_PI (2.0 * M_PI) +#endif +#define POLY_COEFF_TIMES_SIN(coeff, x, latit) (coeff * (sin (x * latit))) +#define POLY_M(c0lat,c1s2lat,c2s4lat,c3s6lat) (Poly_a*(c0lat - c1s2lat + c2s4lat - c3s6lat)) +#define FLOAT_EQ(x,v,epsilon) (((v - epsilon) < x) && (x < (v + epsilon))) +#define FOURTY_ONE (41.0 * M_PI / 180.0) /* 41 degrees in radians */ + +#define POLY_NO_ERROR 0x0000 +#define POLY_LAT_ERROR 0x0001 +#define POLY_LON_ERROR 0x0002 +#define POLY_EASTING_ERROR 0x0004 +#define POLY_NORTHING_ERROR 0x0008 +#define POLY_ORIGIN_LAT_ERROR 0x0010 +#define POLY_CENT_MER_ERROR 0x0020 +#define POLY_A_ERROR 0x0040 +#define POLY_B_ERROR 0x0080 +#define POLY_A_LESS_B_ERROR 0x0100 +#define POLY_LON_WARNING 0x0200 + +ossimPolyconicProjection::ossimPolyconicProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + :ossimMapProjection(ellipsoid, origin) +{ + setDefaults(); + update(); +} + +ossimPolyconicProjection::ossimPolyconicProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double falseEasting, + double falseNorthing) + :ossimMapProjection(ellipsoid, origin) +{ + Poly_False_Easting = falseEasting; + Poly_False_Northing = falseNorthing; + Poly_Max_Easting = 20037509.0; + Poly_Max_Northing = 15348215.0; + Poly_Min_Easting = -20037509.0; + Poly_Min_Northing = -15348215.0; + + update(); +} + +void ossimPolyconicProjection::update() +{ + Set_Polyconic_Parameters(theEllipsoid.getA(), + theEllipsoid.getFlattening(), + theOrigin.latr(), + theOrigin.lonr(), + Poly_False_Easting, + Poly_False_Northing); + + ossimMapProjection::update(); +} + +void ossimPolyconicProjection::setFalseEasting(double falseEasting) +{ + Poly_False_Easting = falseEasting; + + update(); +} + +void ossimPolyconicProjection::setFalseNorthing(double falseNorthing) +{ + Poly_False_Northing = falseNorthing; + + update(); +} + +void ossimPolyconicProjection::setDefaults() +{ + Poly_False_Easting = 0.0; + Poly_False_Northing = 0.0; + Poly_Max_Easting = 20037509.0; + Poly_Max_Northing = 15348215.0; + Poly_Min_Easting = -20037509.0; + Poly_Min_Northing = -15348215.0; +} + +void ossimPolyconicProjection::setFalseEastingNorthing(double falseEasting, + double falseNorthing) +{ + Poly_False_Easting = falseEasting; + Poly_False_Northing = falseNorthing; + + update(); +} + +ossimGpt ossimPolyconicProjection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat = 0.0; + double lon = 0.0; + + Convert_Polyconic_To_Geodetic(eastingNorthing.x, + eastingNorthing.y, + &lat, + &lon); + + return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum); +} + +ossimDpt ossimPolyconicProjection::forward(const ossimGpt &latLon)const +{ + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + Convert_Geodetic_To_Polyconic(gpt.latr(), + gpt.lonr(), + &easting, + &northing); + + return ossimDpt(easting, northing); +} + +bool ossimPolyconicProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const +{ + kwl.add(prefix, + ossimKeywordNames::FALSE_EASTING_KW, + Poly_False_Easting, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_NORTHING_KW, + Poly_False_Northing, + true); + + return ossimMapProjection::saveState(kwl, prefix); +} + +bool ossimPolyconicProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + bool flag = ossimMapProjection::loadState(kwl, prefix); + const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + const char* falseEasting = kwl.find(prefix, ossimKeywordNames::FALSE_EASTING_KW); + const char* falseNorthing = kwl.find(prefix, ossimKeywordNames::FALSE_NORTHING_KW); + + setDefaults(); + if(ossimString(type) == STATIC_TYPE_NAME(ossimPolyconicProjection)) + { + if(falseEasting) + { + Poly_False_Easting = ossimString(falseEasting).toDouble(); + } + if(falseNorthing) + { + Poly_False_Northing = ossimString(falseNorthing).toDouble(); + } + } + + update(); + + return flag; +} + +/***************************************************************************/ +/* + * FUNCTIONS + */ + + +long ossimPolyconicProjection::Set_Polyconic_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing) + +{ /* BEGIN Set_Polyconic_Parameters */ +/* + * The function Set_Polyconic_Parameters receives the ellipsoid parameters and + * Polyconic projection parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the function, + * otherwise POLY_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at which the (input) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + + double j, three_es4; + double lat, sin2lat, sin4lat, sin6lat; + double temp; +// double inv_f = 1 / f; + long Error_Code = POLY_NO_ERROR; + +// if (a <= 0.0) +// { /* Semi-major axis must be greater than zero */ +// Error_Code |= POLY_A_ERROR; +// } +// if ((inv_f < 250) || (inv_f > 350)) +// { /* Inverse flattening must be between 250 and 350 */ +// Error_Code |= POLY_INV_F_ERROR; +// } +// if ((Origin_Latitude < -PI_OVER_2) || (Origin_Latitude > PI_OVER_2)) +// { /* origin latitude out of range */ +// Error_Code |= POLY_ORIGIN_LAT_ERROR; +// } +// if ((Central_Meridian < -M_PI) || (Central_Meridian > TWO_PI)) +// { /* origin longitude out of range */ +// Error_Code |= POLY_CENT_MER_ERROR; +// } + if (!Error_Code) + { /* no errors */ + Poly_a = a; + Poly_f = f; + Poly_Origin_Lat = Origin_Latitude; +// if (Central_Meridian > M_PI) +// Central_Meridian -= TWO_PI; + Poly_Origin_Long = Central_Meridian; + Poly_False_Northing = False_Northing; + Poly_False_Easting = False_Easting; + es2 = 2 * Poly_f - Poly_f * Poly_f; + es4 = es2 * es2; + es6 = es4 * es2; + + j = 45.0 * es6 / 1024.0; + three_es4 = 3.0 * es4; + c0 = 1.0 - es2 / 4.0 - three_es4 / 64.0 - 5.0 * es6 / 256.0; + c1 = 3.0 * es2 / 8.0 + three_es4 / 32.0 + j; + c2 = 15.0 * es4 / 256.0 + j; + c3 = 35.0 * es6 / 3072.0; + + lat = c0 * Poly_Origin_Lat; + sin2lat = POLY_COEFF_TIMES_SIN(c1, 2.0, Poly_Origin_Lat); + sin4lat = POLY_COEFF_TIMES_SIN(c2, 4.0, Poly_Origin_Lat); + sin6lat = POLY_COEFF_TIMES_SIN(c3, 6.0, Poly_Origin_Lat); + M0 = POLY_M(lat, sin2lat, sin4lat, sin6lat); + + if (Poly_Origin_Long > 0) + { + Convert_Geodetic_To_Polyconic(FOURTY_ONE, Poly_Origin_Long - M_PI, &temp, &Poly_Max_Northing); + Convert_Geodetic_To_Polyconic(-FOURTY_ONE, Poly_Origin_Long - M_PI, &temp, &Poly_Min_Northing); + Poly_Max_Easting = 19926189.0; + Poly_Min_Easting = -20037509.0; + } + else if (Poly_Origin_Long < 0) + { + Convert_Geodetic_To_Polyconic(FOURTY_ONE, Poly_Origin_Long + M_PI, &temp, &Poly_Max_Northing); + Convert_Geodetic_To_Polyconic(-FOURTY_ONE, Poly_Origin_Long + M_PI, &temp, &Poly_Min_Northing); + Poly_Max_Easting = 20037509.0; + Poly_Min_Easting = -19926189.0; + } + else + { + Convert_Geodetic_To_Polyconic(FOURTY_ONE, M_PI, &temp, &Poly_Max_Northing); + Convert_Geodetic_To_Polyconic(-FOURTY_ONE, M_PI, &temp, &Poly_Min_Northing); + Poly_Max_Easting = 20037509.0; + Poly_Min_Easting = -20037509.0; + } + + } /* END OF if(!Error_Code) */ + return (Error_Code); +} /* END OF Set_Polyconic_Parameters */ + +void ossimPolyconicProjection::Get_Polyconic_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const + +{ /* BEGIN Get_Polyconic_Parameters */ +/* + * The function Get_Polyconic_Parameters returns the current ellipsoid + * parameters, and Polyconic projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at which the (output) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + + *a = Poly_a; + *f = Poly_f; + *Origin_Latitude = Poly_Origin_Lat; + *Central_Meridian = Poly_Origin_Long; + *False_Easting = Poly_False_Easting; + *False_Northing = Poly_False_Northing; + + return; +} /* END OF Get_Polyconic_Parameters */ + + +long ossimPolyconicProjection::Convert_Geodetic_To_Polyconic (double Latitude, + double Longitude, + double *Easting, + double *Northing)const +{ /* BEGIN Convert_Geodetic_To_Polyconic */ +/* + * The function Convert_Geodetic_To_Polyconic converts geodetic (latitude and + * longitude) coordinates to Polyconic projection (easting and northing) + * coordinates, according to the current ellipsoid and Polyconic projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise POLY_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + + double slat = sin(Latitude); + double lat, sin2lat, sin4lat, sin6lat; + double dlam; /* Longitude - Central Meridan */ + double NN; + double NN_OVER_tlat; + double MM; + double EE; + long Error_Code = POLY_NO_ERROR; + +// if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2)) +// { /* Latitude out of range */ +// Error_Code |= POLY_LAT_ERROR; +// } +// if ((Longitude < -M_PI) || (Longitude > TWO_PI)) +// { /* Longitude out of range */ +// Error_Code |= POLY_LON_ERROR; +// } + if (!Error_Code) + { /* no errors */ + dlam = Longitude - Poly_Origin_Long; + if (fabs(dlam) > (M_PI / 2.0)) + { /* Distortion will result if Longitude is more than 90 degrees from the Central Meridian */ + Error_Code |= POLY_LON_WARNING; + } +// if (dlam > M_PI) +// { +// dlam -= TWO_PI; +// } +// if (dlam < -M_PI) +// { +// dlam += TWO_PI; +// } + if (Latitude == 0.0) + { + *Easting = Poly_a * dlam + Poly_False_Easting; + *Northing = -M0 + Poly_False_Northing; + } + else + { + NN = Poly_a / sqrt(1.0 - es2 * (slat * slat)); + NN_OVER_tlat = NN / tan(Latitude); + lat = c0 * Latitude; + sin2lat = POLY_COEFF_TIMES_SIN(c1, 2.0, Latitude); + sin4lat = POLY_COEFF_TIMES_SIN(c2, 4.0, Latitude); + sin6lat = POLY_COEFF_TIMES_SIN(c3, 6.0, Latitude); + MM = POLY_M(lat, sin2lat, sin4lat, sin6lat); + EE = dlam * slat; + *Easting = NN_OVER_tlat * sin(EE) + Poly_False_Easting; + *Northing = MM - M0 + NN_OVER_tlat * (1.0 - cos(EE)) + + Poly_False_Northing; + } + } + return (Error_Code); +} /* END OF Convert_Geodetic_To_Polyconic */ + + +long ossimPolyconicProjection::Convert_Polyconic_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const +{ /* BEGIN Convert_Polyconic_To_Geodetic */ +/* + * The function Convert_Polyconic_To_Geodetic converts Polyconic projection + * (easting and northing) coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Polyconic projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise POLY_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + + double dx; /* Delta easting - Difference in easting (easting-FE) */ + double dy; /* Delta northing - Difference in northing (northing-FN) */ + double dx_OVER_Poly_a; + double AA; + double BB; + double CC = 0.0; + double PHIn, Delta_PHI = 1.0; + double sin_PHIn; + double PHI, sin2PHI,sin4PHI, sin6PHI; + double Mn, Mn_prime, Ma; + double AA_Ma; + double Ma2_PLUS_BB; + double AA_MINUS_Ma; + double tolerance = 1.0e-12; /* approximately 1/1000th of + an arc second or 1/10th meter */ + long Error_Code = POLY_NO_ERROR; + +// if ((Easting < (Poly_False_Easting + Poly_Min_Easting)) +// || (Easting > (Poly_False_Easting + Poly_Max_Easting))) +// { /* Easting out of range */ +// Error_Code |= POLY_EASTING_ERROR; +// } +// if ((Northing < (Poly_False_Northing + Poly_Min_Northing)) +// || (Northing > (Poly_False_Northing + Poly_Max_Northing))) +// { /* Northing out of range */ +// Error_Code |= POLY_NORTHING_ERROR; +// } + if (!Error_Code) + { /* no errors */ + dy = Northing - Poly_False_Northing; + dx = Easting - Poly_False_Easting; + dx_OVER_Poly_a = dx / Poly_a; + if (FLOAT_EQ(dy,-M0,1)) + { + *Latitude = 0.0; + *Longitude = dx_OVER_Poly_a + Poly_Origin_Long; + } + else + { + AA = (M0 + dy) / Poly_a; + BB = dx_OVER_Poly_a * dx_OVER_Poly_a + (AA * AA); + PHIn = AA; + + while (fabs(Delta_PHI) > tolerance) + { + sin_PHIn = sin(PHIn); + CC = sqrt(1.0 - es2 * sin_PHIn * sin_PHIn) * tan(PHIn); + PHI = c0 * PHIn; + sin2PHI = POLY_COEFF_TIMES_SIN(c1, 2.0, PHIn); + sin4PHI = POLY_COEFF_TIMES_SIN(c2, 4.0, PHIn); + sin6PHI = POLY_COEFF_TIMES_SIN(c3, 6.0, PHIn); + Mn = POLY_M(PHI, sin2PHI, sin4PHI, sin6PHI); + Mn_prime = c0 - 2.0 * c1 * cos(2.0 * PHIn) + 4.0 * c2 * cos(4.0 * PHIn) - + 6.0 * c3 * cos(6.0 * PHIn); + Ma = Mn / Poly_a; + AA_Ma = AA * Ma; + Ma2_PLUS_BB = Ma * Ma + BB; + AA_MINUS_Ma = AA - Ma; + Delta_PHI = (AA_Ma * CC + AA_MINUS_Ma - 0.5 * (Ma2_PLUS_BB) * CC) / + (es2 * sin2PHI * (Ma2_PLUS_BB - 2.0 * AA_Ma) / + 4.0 * CC + (AA_MINUS_Ma) * (CC * Mn_prime - 2.0 / sin2PHI) - Mn_prime); + PHIn -= Delta_PHI; + } + *Latitude = PHIn; + +// if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */ +// *Latitude = PI_OVER_2; +// else if (*Latitude < -PI_OVER_2) +// *Latitude = -PI_OVER_2; + + if (FLOAT_EQ(fabs(*Latitude),PI_OVER_2,.00001) || (*Latitude == 0)) + *Longitude = Poly_Origin_Long; + + else + { + *Longitude = (asin(dx_OVER_Poly_a * CC)) / sin(*Latitude) + + Poly_Origin_Long; + } + } +// if (*Longitude > M_PI) +// *Longitude -= TWO_PI; +// if (*Longitude < -M_PI) +// *Longitude += TWO_PI; + +// if (*Longitude > M_PI) /* force distorted values to 180, -180 degrees */ +// *Longitude = M_PI; +// else if (*Longitude < -M_PI) +// *Longitude = -M_PI; + + } + return (Error_Code); +} /* END OF Convert_Polyconic_To_Geodetic */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimPolyconicProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimPolyconicProjection.h new file mode 100644 index 0000000000..d45236a668 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimPolyconicProjection.h @@ -0,0 +1,203 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Polyconic projection code. +//******************************************************************* +// $Id: ossimPolyconicProjection.h,v 1.5 2005/09/09 19:23:58 gpotts Exp $ + +#ifndef ossimPolyconicProjection_HEADER +#define ossimPolyconicProjection_HEADER + +#include "ossimMapProjection.h" + +class ossimPolyconicProjection : public ossimMapProjection +{ +public: + ossimPolyconicProjection(const ossimEllipsoid& ellipsoid = ossimEllipsoid(), + const ossimGpt& origin = ossimGpt()); + ossimPolyconicProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + const double falseEasting, + const double falseNorthing); + ~ossimPolyconicProjection(){} + virtual ossimObject *dup()const + { + return new ossimPolyconicProjection(*this); + } + + virtual ossimGpt inverse(const ossimDpt &eastingNorthing)const; + virtual ossimDpt forward(const ossimGpt &latLon)const; + virtual void update(); + + /*! + * SetFalseEasting. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEasting(double falseEasting); + + /*! + * SetFalseNorthing. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseNorthing(double falseNorthing); + + /*! + * Sets both false easting and northing values. The values are + * expected to be in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEastingNorthing(double falseEasting, double falseNorthing); + + void setDefaults(); + + double getFalseEasting()const{return Poly_False_Easting;} + double getFalseNorthing()const{return Poly_False_Northing;} + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); +private: + + mutable double Poly_a; /* Semi-major axis of ellipsoid in meters */ + mutable double Poly_f; /* Flattening of ellipsoid */ + mutable double es2; /* Eccentricity (0.08181919084262188000) squared */ + mutable double es4; /* es2 * es2 */ + mutable double es6; /* es4 * es2 */ + mutable double M0; + mutable double c0; /* 1 - es2 / 4.0 - 3.0 * es4 / 64.0 - 5.0 * es6 / 256.0 */ + mutable double c1; /* 3.0 * es2 / 8.0 + 3.0 * es4 / 32.0 + 45.0 * es6 / 1024.0 */ + mutable double c2; /* 15.0 * es4 / 256.0 + 45.0 * es6 / 1024.0 */ + mutable double c3; /* 35.0 * es6 / 3072.0 */ + +/* Polyconic projection Parameters */ + mutable double Poly_Origin_Lat; /* Latitude of origin in radians */ + mutable double Poly_Origin_Long; /* Longitude of origin in radians */ + mutable double Poly_False_Northing; /* False northing in meters */ + mutable double Poly_False_Easting; /* False easting in meters */ + +/* Maximum variance for easting and northing values for WGS 84. + */ + mutable double Poly_Max_Easting; + mutable double Poly_Max_Northing; + mutable double Poly_Min_Easting; + mutable double Poly_Min_Northing; + +/*! + * The function Set_Polyconic_Parameters receives the ellipsoid parameters and + * Polyconic projcetion parameters as inputs, and sets the corresponding state + * variables.If any errors + * occur, the error code(s) are returned by the function, otherwise + * POLY_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at which the (input) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + long Set_Polyconic_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing); + + + +/*! + * The function Get_Polyconic_Parameters returns the current ellipsoid + * parameters, and Polyconic projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at which the (output) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + void Get_Polyconic_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const; + + + +/*! + * The function Convert_Geodetic_To_Polyconic converts geodetic (latitude and + * longitude) coordinates to Polyconic projection easting, and northing + * coordinates, according to the current ellipsoid and Polyconic projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise POLY_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + long Convert_Geodetic_To_Polyconic (double Latitude, + double Longitude, + double *Easting, + double *Northing)const; + + +/*! + * The function Convert_Polyconic_To_Geodetic converts Polyconic projection + * easting and northing coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Polyconic projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise POLY_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + long Convert_Polyconic_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimSinusoid.c b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimSinusoid.c new file mode 100644 index 0000000000..f50d76a4d8 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimSinusoid.c @@ -0,0 +1,388 @@ +/***************************************************************************/ +/* RSC IDENTIFIER: SINUSOIDAL + * + * ABSTRACT + * + * This component provides conversions between Geodetic coordinates + * (latitude and longitude in radians) and Sinusoid projection coordinates + * (easting and northing in meters). + * + * ERROR HANDLING + * + * This component checks parameters for valid values. If an invalid value + * is found, the error code is combined with the current error code using + * the bitwise or. This combining allows multiple error codes to be + * returned. The possible error codes are: + * + * SINU_NO_ERROR : No errors occurred in function + * SINU_LAT_ERROR : Latitude outside of valid range + * (-90 to 90 degrees) + * SINU_LON_ERROR : Longitude outside of valid range + * (-180 to 360 degrees) + * SINU_EASTING_ERROR : Easting outside of valid range + * (False_Easting +/- ~20,000,000 m, + * depending on ellipsoid parameters) + * SINU_NORTHING_ERROR : Northing outside of valid range + * (False_Northing +/- ~10,000,000 m, + * depending on ellipsoid parameters) + * SINU_CENT_MER_ERROR : Origin longitude outside of valid range + * (-180 to 360 degrees) + * SINU_A_ERROR : Semi-major axis less than or equal to zero + * SINU_INV_F_ERROR : Inverse flattening outside of valid range + * (250 to 350) + * + * REUSE NOTES + * + * SINUSOIDAL is intended for reuse by any application that performs a + * Sinusoid projection or its inverse. + * + * REFERENCES + * + * Further information on SINUSOIDAL can be found in the Reuse Manual. + * + * SINUSOIDAL originated from : U.S. Army Topographic Engineering Center + * Geospatial Information Division + * 7701 Telegraph Road + * Alexandria, VA 22310-3864 + * + * LICENSES + * + * None apply to this component. + * + * RESTRICTIONS + * + * SINUSOIDAL has no restrictions. + * + * ENVIRONMENT + * + * SINUSOIDAL was tested and certified in the following environments: + * + * 1. Solaris 2.5 with GCC, version 2.8.1 + * 2. Windows 95 with MS Visual C++, version 6 + * + * MODIFICATIONS + * + * Date Description + * ---- ----------- + * 7-15-99 Original Code + * + */ + + +/***************************************************************************/ +/* + * INCLUDES + */ + +#include <math.h> +#include "ossimSinusoid.h" + +/* + * math.h - Standard C math library + * sinusoid.h - Is for prototype error checking + */ + + +/***************************************************************************/ +/* + * DEFINES + */ + +#define PI 3.14159265358979323e0 /* PI */ +#define PI_OVER_2 (PI / 2.0) +#define TWO_PI (2.0 * PI) +#define SINU_COEFF_TIMES_SIN(coeff, x, latit) (coeff * sin(x * latit)) +#define FLOAT_EQ(x,v,epsilon) (((v - epsilon) < x) && (x < (v + epsilon))) + + +/***************************************************************************/ +/* + * GLOBALS + */ + +/* Ellipsoid Parameters, default to WGS 84 */ +static double Sinu_a = 6378137.0; /* Semi-major axis of ellipsoid in meters */ +static double Sinu_f = 1 / 298.257223563; /* Flattening of ellipsoid */ +static double es2 = 0.0066943799901413800; /* Eccentricity (0.08181919084262188000) squared */ +static double es4 = 4.4814723452405e-005; /* es2 * es2 */ +static double es6 = 3.0000678794350e-007; /* es4 * es2 */ +static double c0 = .99832429845280; /* 1 - es2 / 4.0 - 3.0 * es4 / 64.0 - 5.0 * es6 / 256.0 */ +static double c1 = .0025146070605187; /* 3.0 * es2 / 8.0 + 3.0 * es4 / 32.0 + 45.0 * es6 / 1024.0 */ +static double c2 = 2.6390465943377e-006; /* 15.0 * es4 / 256.0 + 45.0 * es6 / 1024.0 */ +static double c3 = 3.4180460865959e-009; /* 35.0 * es6 / 3072.0 */ +static double a0 = .0025188265843907; /* 3.0 * e1 / 2.0 - 27.0 * e3 / 32.0 */ +static double a1 = 3.7009490356205e-006; /* 21.0 * e2 / 16.0 - 55.0 * e4 / 32.0 */ +static double a2 = 7.4478137675038e-009; /* 151.0 * e3 / 96.0 */ +static double a3 = 1.7035993238596e-011; /* 1097.0 * e4 / 512.0 */ + +/* Sinusoid projection Parameters */ +static double Sinu_Origin_Long = 0.0; /* Longitude of origin in radians */ +static double Sinu_False_Northing = 0.0; /* False northing in meters */ +static double Sinu_False_Easting = 0.0; /* False easting in meters */ + +/* Maximum variance for easting and northing values for WGS 84. + */ +static double Sinu_Max_Easting = 20037509.0; +static double Sinu_Min_Easting = -20037509.0; +static double Sinu_Delta_Northing = 10001966.0; +/* + * These state variables are for optimization purposes. The only function + * that should modify them is Set_Sinusoidal_Parameters. + */ + + +/***************************************************************************/ +/* + * FUNCTIONS + */ + + +long Set_Sinusoidal_Parameters(double a, + double f, + double Central_Meridian, + double False_Easting, + double False_Northing) +{ /* BEGIN Set_Sinusoidal_Parameters */ +/* + * The function Set_Sinusoidal_Parameters receives the ellipsoid parameters and + * Sinusoidal projection parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the function, + * otherwise SINU_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + + double j; + double One_MINUS_es2, Sqrt_One_MINUS_es2, e1, e2, e3, e4; + double inv_f = 1 / f; + long Error_Code = SINU_NO_ERROR; + + if (a <= 0.0) + { /* Semi-major axis must be greater than zero */ + Error_Code |= SINU_A_ERROR; + } + if ((inv_f < 250) || (inv_f > 350)) + { /* Inverse flattening must be between 250 and 350 */ + Error_Code |= SINU_INV_F_ERROR; + } + if ((Central_Meridian < -PI) || (Central_Meridian > TWO_PI)) + { /* origin longitude out of range */ + Error_Code |= SINU_CENT_MER_ERROR; + } + if (!Error_Code) + { /* no errors */ + Sinu_a = a; + Sinu_f = f; + es2 = 2 * Sinu_f - Sinu_f * Sinu_f; + es4 = es2 * es2; + es6 = es4 * es2; + j = 45.0 * es6 / 1024.0; + c0 = 1.0 - es2 / 4.0 - 3.0 * es4 / 64.0 - 5.0 * es6 / 256.0; + c1 = 3.0 * es2 / 8.0 + 3.0 * es4 / 32.0 + j; + c2 = 15.0 * es4 / 256.0 + j; + c3 = 35.0 * es6 / 3072.0; + One_MINUS_es2 = 1.0 - es2; + Sqrt_One_MINUS_es2 = sqrt(One_MINUS_es2); + e1 = (1.0 - Sqrt_One_MINUS_es2) / (1.0 + Sqrt_One_MINUS_es2); + e2 = e1 * e1; + e3 = e2 * e1; + e4 = e3 * e1; + a0 = 3.0 * e1 / 2.0 - 27.0 * e3 / 32.0 ; + a1 = 21.0 * e2 / 16.0 - 55.0 * e4 / 32.0; + a2 = 151.0 * e3 / 96.0; + a3 = 1097.0 * e4 / 512.0; + if (Central_Meridian > PI) + Central_Meridian -= TWO_PI; + Sinu_Origin_Long = Central_Meridian; + Sinu_False_Northing = False_Northing; + Sinu_False_Easting = False_Easting; + + if (Sinu_Origin_Long > 0) + { + Sinu_Max_Easting = 19926189.0; + Sinu_Min_Easting = -20037509.0; + } + else if (Sinu_Origin_Long < 0) + { + Sinu_Max_Easting = 20037509.0; + Sinu_Min_Easting = -19926189.0; + } + else + { + Sinu_Max_Easting = 20037509.0; + Sinu_Min_Easting = -20037509.0; + } + } /* END OF if(!Error_Code) */ + return (Error_Code); +} /* END OF Set_Sinusoidal_Parameters */ + +void Get_Sinusoidal_Parameters(double *a, + double *f, + double *Central_Meridian, + double *False_Easting, + double *False_Northing) +{ /* BEGIN Get_Sinusoidal_Parameters */ +/* + * The function Get_Sinusoidal_Parameters returns the current ellipsoid + * parameters, and Sinusoidal projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + + *a = Sinu_a; + *f = Sinu_f; + *Central_Meridian = Sinu_Origin_Long; + *False_Easting = Sinu_False_Easting; + *False_Northing = Sinu_False_Northing; + return; +} /* END OF Get_Sinusoidal_Parameters */ + + +long Convert_Geodetic_To_Sinusoidal (double Latitude, + double Longitude, + double *Easting, + double *Northing) +{ /* BEGIN Convert_Geodetic_To_Sinusoidal */ +/* + * The function Convert_Geodetic_To_Sinusoidal converts geodetic (latitude and + * longitude) coordinates to Sinusoidal projection (easting and northing) + * coordinates, according to the current ellipsoid and Sinusoidal projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise SINU_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + + double slat = sin(Latitude); + double sin2lat, sin4lat, sin6lat; + double dlam; /* Longitude - Central Meridan */ + double mm; + double MM; + long Error_Code = SINU_NO_ERROR; + + if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2)) + { /* Latitude out of range */ + Error_Code |= SINU_LAT_ERROR; + } + if ((Longitude < -PI) || (Longitude > TWO_PI)) + { /* Longitude out of range */ + Error_Code |= SINU_LON_ERROR; + } + if (!Error_Code) + { /* no errors */ + dlam = Longitude - Sinu_Origin_Long; + if (dlam > PI) + { + dlam -= TWO_PI; + } + if (dlam < -PI) + { + dlam += TWO_PI; + } + mm = sqrt(1.0 - es2 * slat * slat); + + sin2lat = SINU_COEFF_TIMES_SIN(c1, 2.0, Latitude); + sin4lat = SINU_COEFF_TIMES_SIN(c2, 4.0, Latitude); + sin6lat = SINU_COEFF_TIMES_SIN(c3, 6.0, Latitude); + MM = Sinu_a * (c0 * Latitude - sin2lat + sin4lat - sin6lat); + + *Easting = Sinu_a * dlam * cos(Latitude) / mm + Sinu_False_Easting; + *Northing = MM + Sinu_False_Northing; + } + return (Error_Code); +} /* END OF Convert_Geodetic_To_Sinusoidal */ + + +long Convert_Sinusoidal_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude) +{ /* BEGIN Convert_Sinusoidal_To_Geodetic */ +/* + * The function Convert_Sinusoidal_To_Geodetic converts Sinusoidal projection + * (easting and northing) coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Sinusoidal projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise SINU_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + + double dx; /* Delta easting - Difference in easting (easting-FE) */ + double dy; /* Delta northing - Difference in northing (northing-FN) */ + double mu; + double sin2mu, sin4mu, sin6mu, sin8mu; + double sin_lat; + long Error_Code = SINU_NO_ERROR; + + if ((Easting < (Sinu_False_Easting + Sinu_Min_Easting)) + || (Easting > (Sinu_False_Easting + Sinu_Max_Easting))) + { /* Easting out of range */ + Error_Code |= SINU_EASTING_ERROR; + } + if ((Northing < (Sinu_False_Northing - Sinu_Delta_Northing)) + || (Northing > (Sinu_False_Northing + Sinu_Delta_Northing))) + { /* Northing out of range */ + Error_Code |= SINU_NORTHING_ERROR; + } + if (!Error_Code) + { /* no errors */ + dy = Northing - Sinu_False_Northing; + dx = Easting - Sinu_False_Easting; + + mu = dy / (Sinu_a * c0); + sin2mu = SINU_COEFF_TIMES_SIN(a0, 2.0, mu); + sin4mu = SINU_COEFF_TIMES_SIN(a1, 4.0, mu); + sin6mu = SINU_COEFF_TIMES_SIN(a2, 6.0, mu); + sin8mu = SINU_COEFF_TIMES_SIN(a3, 8.0, mu); + *Latitude = mu + sin2mu + sin4mu + sin6mu + sin8mu; + + if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */ + *Latitude = PI_OVER_2; + else if (*Latitude < -PI_OVER_2) + *Latitude = -PI_OVER_2; + + if (FLOAT_EQ(fabs(*Latitude),PI_OVER_2,1.0e-8)) + *Longitude = Sinu_Origin_Long; + else + { + sin_lat = sin(*Latitude); + *Longitude = Sinu_Origin_Long + dx * sqrt(1.0 - es2 * + sin_lat * sin_lat) / (Sinu_a * cos(*Latitude)); + + + if (*Longitude > PI) + *Longitude -= TWO_PI; + if (*Longitude < -PI) + *Longitude += TWO_PI; + + if (*Longitude > PI) /* force distorted values to 180, -180 degrees */ + *Longitude = PI; + else if (*Longitude < -PI) + *Longitude = -PI; + + + } + } + return (Error_Code); +} /* END OF Convert_Sinusoidal_To_Geodetic */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimSinusoid.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimSinusoid.h new file mode 100644 index 0000000000..76d5e83c3e --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimSinusoid.h @@ -0,0 +1,185 @@ +#ifndef SINUSOID_H + #define SINUSOID_H + +/***************************************************************************/ +/* RSC IDENTIFIER: SINUSOIDAL + * + * ABSTRACT + * + * This component provides conversions between Geodetic coordinates + * (latitude and longitude in radians) and Sinusoid projection coordinates + * (easting and northing in meters). + * + * ERROR HANDLING + * + * This component checks parameters for valid values. If an invalid value + * is found, the error code is combined with the current error code using + * the bitwise or. This combining allows multiple error codes to be + * returned. The possible error codes are: + * + * SINU_NO_ERROR : No errors occurred in function + * SINU_LAT_ERROR : Latitude outside of valid range + * (-90 to 90 degrees) + * SINU_LON_ERROR : Longitude outside of valid range + * (-180 to 360 degrees) + * SINU_EASTING_ERROR : Easting outside of valid range + * (False_Easting +/- ~20,000,000 m, + * depending on ellipsoid parameters) + * SINU_NORTHING_ERROR : Northing outside of valid range + * (False_Northing +/- ~10,000,000 m, + * depending on ellipsoid parameters) + * SINU_CENT_MER_ERROR : Origin longitude outside of valid range + * (-180 to 360 degrees) + * SINU_A_ERROR : Semi-major axis less than or equal to zero + * SINU_INV_F_ERROR : Inverse flattening outside of valid range + * (250 to 350) + * + * REUSE NOTES + * + * SINUSOIDAL is intended for reuse by any application that performs a + * Sinusoid projection or its inverse. + * + * REFERENCES + * + * Further information on SINUSOIDAL can be found in the Reuse Manual. + * + * SINUSOIDAL originated from : U.S. Army Topographic Engineering Center + * Geospatial Information Division + * 7701 Telegraph Road + * Alexandria, VA 22310-3864 + * + * LICENSES + * + * None apply to this component. + * + * RESTRICTIONS + * + * SINUSOIDAL has no restrictions. + * + * ENVIRONMENT + * + * SINUSOIDAL was tested and certified in the following environments: + * + * 1. Solaris 2.5 with GCC, version 2.8.1 + * 2. Windows 95 with MS Visual C++, version 6 + * + * MODIFICATIONS + * + * Date Description + * ---- ----------- + * 7-15-99 Original Code + * + */ + + +/***************************************************************************/ +/* + * DEFINES + */ + + #define SINU_NO_ERROR 0x0000 + #define SINU_LAT_ERROR 0x0001 + #define SINU_LON_ERROR 0x0002 + #define SINU_EASTING_ERROR 0x0004 + #define SINU_NORTHING_ERROR 0x0008 + #define SINU_CENT_MER_ERROR 0x0020 + #define SINU_A_ERROR 0x0040 + #define SINU_INV_F_ERROR 0x0080 + + +/***************************************************************************/ +/* + * FUNCTION PROTOTYPES + * for SINUSOID.C + */ + +/* ensure proper linkage to c++ programs */ + #ifdef __cplusplus +extern "C" { + #endif + + long Set_Sinusoidal_Parameters(double a, + double f, + double Central_Meridian, + double False_Easting, + double False_Northing); + +/* + * The function Set_Sinusoidal_Parameters receives the ellipsoid parameters and + * Sinusoidal projcetion parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the function, + * otherwise SINU_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + + + void Get_Sinusoidal_Parameters(double *a, + double *f, + double *Central_Meridian, + double *False_Easting, + double *False_Northing); + +/* + * The function Get_Sinusoidal_Parameters returns the current ellipsoid + * parameters and Sinusoidal projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + + + long Convert_Geodetic_To_Sinusoidal (double Latitude, + double Longitude, + double *Easting, + double *Northing); +/* + * The function Convert_Geodetic_To_Sinusoidal converts geodetic (latitude and + * longitude) coordinates to Sinusoidal projection easting, and northing + * coordinates, according to the current ellipsoid and Sinusoidal projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise SINU_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + + + long Convert_Sinusoidal_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude); +/* + * The function Convert_Sinusoidal_To_Geodetic converts Sinusoidal projection + * easting and northing coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Sinusoida projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise SINU_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + + #ifdef __cplusplus +} + #endif + +#endif /* SINUSOID_H */ + diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimSinusoidalProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimSinusoidalProjection.cpp new file mode 100644 index 0000000000..bd51ee74fd --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimSinusoidalProjection.cpp @@ -0,0 +1,455 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Sinusoidal projection code. +//******************************************************************* +// $Id: ossimSinusoidalProjection.cpp,v 1.11 2004/01/08 21:49:22 jlargent Exp $ + +#include <math.h> +#include "ossimSinusoidalProjection.h" +#include "base/common/ossimKeywordNames.h" + +RTTI_DEF1(ossimSinusoidalProjection, "ossimSinusoidalProjection", ossimMapProjection) +/***************************************************************************/ +/* + * DEFINES + */ + +#define SINU_NO_ERROR 0x0000 +#define SINU_LAT_ERROR 0x0001 +#define SINU_LON_ERROR 0x0002 +#define SINU_EASTING_ERROR 0x0004 +#define SINU_NORTHING_ERROR 0x0008 +#define SINU_CENT_MER_ERROR 0x0020 +#define SINU_A_ERROR 0x0040 +#define SINU_B_ERROR 0x0080 +#define SINU_A_LESS_B_ERROR 0x0100 + +#ifndef PI_OVER_2 +# define PI_OVER_2 ( M_PI / 2.0) +#endif +#ifndef TWO_PI +# define TWO_PI (2.0 * M_PI) +#endif + +#define SINU_COEFF_TIMES_SIN(coeff, x, latit) (coeff * sin(x * latit)) +#define FLOAT_EQ(x,v,epsilon) (((v - epsilon) < x) && (x < (v + epsilon))) + +/***************************************************************************/ +/* + * FUNCTIONS + */ + +ossimSinusoidalProjection::ossimSinusoidalProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + :ossimMapProjection(ellipsoid, origin) +{ + setDefaults(); + update(); +} + +ossimSinusoidalProjection::ossimSinusoidalProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double falseEasting, + double falseNorthing) + :ossimMapProjection(ellipsoid, origin) +{ + Sinu_False_Easting = falseEasting; + Sinu_False_Northing = falseNorthing; + Sinu_Max_Easting = 20037509.0; + Sinu_Min_Easting = -20037509.0; + Sinu_Delta_Northing = 10001966.0; + + update(); +} + +void ossimSinusoidalProjection::update() +{ + Set_Sinusoidal_Parameters(theEllipsoid.getA(), + theEllipsoid.getFlattening(), + theOrigin.lonr(), + Sinu_False_Easting, + Sinu_False_Northing); + + ossimMapProjection::update(); +} + +void ossimSinusoidalProjection::setFalseEasting(double falseEasting) +{ + Sinu_False_Easting = falseEasting; + + update(); +} + +void ossimSinusoidalProjection::setFalseNorthing(double falseNorthing) +{ + Sinu_False_Northing = falseNorthing; + + update(); +} + +void ossimSinusoidalProjection::setDefaults() +{ + Sinu_Max_Easting = 20037509.0; + Sinu_Min_Easting = -20037509.0; + Sinu_Delta_Northing = 10001966.0; + Sinu_False_Easting = 0.0; + Sinu_False_Northing = 0.0; +} + +void ossimSinusoidalProjection::setFalseEastingNorthing(double falseEasting, + double falseNorthing) +{ + Sinu_False_Easting = falseEasting; + Sinu_False_Northing = falseNorthing; + + update(); +} + +ossimGpt ossimSinusoidalProjection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat = 0.0; + double lon = 0.0; + + Convert_Sinusoidal_To_Geodetic(eastingNorthing.x, + eastingNorthing.y, + &lat, + &lon); + return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum); +} + +ossimDpt ossimSinusoidalProjection::forward(const ossimGpt &latLon)const +{ + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + Convert_Geodetic_To_Sinusoidal(gpt.latr(), + gpt.lonr(), + &easting, + &northing); + return ossimDpt(easting, northing); +} + +bool ossimSinusoidalProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const +{ + kwl.add(prefix, + ossimKeywordNames::FALSE_EASTING_KW, + Sinu_False_Easting, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_NORTHING_KW, + Sinu_False_Northing, + true); + + return ossimMapProjection::saveState(kwl, prefix); +} + +bool ossimSinusoidalProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + bool flag = ossimMapProjection::loadState(kwl, prefix); + const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + const char* falseEasting = kwl.find(prefix, ossimKeywordNames::FALSE_EASTING_KW); + const char* falseNorthing = kwl.find(prefix, ossimKeywordNames::FALSE_NORTHING_KW); + + setDefaults(); + if(ossimString(type) == STATIC_TYPE_NAME(ossimSinusoidalProjection)) + { + if(falseEasting) + { + Sinu_False_Easting = ossimString(falseEasting).toDouble(); + } + if(falseNorthing) + { + Sinu_False_Northing = ossimString(falseNorthing).toDouble(); + } + } + + update(); + + return flag; +} + +/***************************************************************************/ +/* + * FUNCTIONS + */ + + +long ossimSinusoidalProjection::Set_Sinusoidal_Parameters(double a, + double f, + double Central_Meridian, + double False_Easting, + double False_Northing) +{ /* BEGIN Set_Sinusoidal_Parameters */ +/* + * The function Set_Sinusoidal_Parameters receives the ellipsoid parameters and + * Sinusoidal projection parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the function, + * otherwise SINU_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + + double j; + double One_MINUS_es2, Sqrt_One_MINUS_es2, e1, e2, e3, e4; +// double inv_f = 1 / f; + long Error_Code = SINU_NO_ERROR; + +// if (a <= 0.0) +// { /* Semi-major axis must be greater than zero */ +// Error_Code |= SINU_A_ERROR; +// } +// if ((inv_f < 250) || (inv_f > 350)) +// { /* Inverse flattening must be between 250 and 350 */ +// Error_Code |= SINU_INV_F_ERROR; +// } +// if ((Central_Meridian < -M_PI) || (Central_Meridian > TWO_PI)) +// { /* origin longitude out of range */ +// Error_Code |= SINU_CENT_MER_ERROR; +// } + if (!Error_Code) + { /* no errors */ + Sinu_a = a; + Sinu_f = f; + es2 = 2 * Sinu_f - Sinu_f * Sinu_f; + es4 = es2 * es2; + es6 = es4 * es2; + j = 45.0 * es6 / 1024.0; + c0 = 1.0 - es2 / 4.0 - 3.0 * es4 / 64.0 - 5.0 * es6 / 256.0; + c1 = 3.0 * es2 / 8.0 + 3.0 * es4 / 32.0 + j; + c2 = 15.0 * es4 / 256.0 + j; + c3 = 35.0 * es6 / 3072.0; + One_MINUS_es2 = 1.0 - es2; + Sqrt_One_MINUS_es2 = sqrt(One_MINUS_es2); + e1 = (1.0 - Sqrt_One_MINUS_es2) / (1.0 + Sqrt_One_MINUS_es2); + e2 = e1 * e1; + e3 = e2 * e1; + e4 = e3 * e1; + a0 = 3.0 * e1 / 2.0 - 27.0 * e3 / 32.0 ; + a1 = 21.0 * e2 / 16.0 - 55.0 * e4 / 32.0; + a2 = 151.0 * e3 / 96.0; + a3 = 1097.0 * e4 / 512.0; +// if (Central_Meridian > M_PI) +// Central_Meridian -= TWO_PI; + Sinu_Origin_Long = Central_Meridian; + Sinu_False_Northing = False_Northing; + Sinu_False_Easting = False_Easting; + + if (Sinu_Origin_Long > 0) + { + Sinu_Max_Easting = 19926189.0; + Sinu_Min_Easting = -20037509.0; + } + else if (Sinu_Origin_Long < 0) + { + Sinu_Max_Easting = 20037509.0; + Sinu_Min_Easting = -19926189.0; + } + else + { + Sinu_Max_Easting = 20037509.0; + Sinu_Min_Easting = -20037509.0; + } + } /* END OF if(!Error_Code) */ + return (Error_Code); +} /* END OF Set_Sinusoidal_Parameters */ + +void ossimSinusoidalProjection::Get_Sinusoidal_Parameters(double *a, + double *f, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const +{ /* BEGIN Get_Sinusoidal_Parameters */ +/* + * The function Get_Sinusoidal_Parameters returns the current ellipsoid + * parameters, and Sinusoidal projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + + *a = Sinu_a; + *f = Sinu_f; + *Central_Meridian = Sinu_Origin_Long; + *False_Easting = Sinu_False_Easting; + *False_Northing = Sinu_False_Northing; + + return; +} /* END OF Get_Sinusoidal_Parameters */ + + +long ossimSinusoidalProjection::Convert_Geodetic_To_Sinusoidal (double Latitude, + double Longitude, + double *Easting, + double *Northing)const +{ /* BEGIN Convert_Geodetic_To_Sinusoidal */ +/* + * The function Convert_Geodetic_To_Sinusoidal converts geodetic (latitude and + * longitude) coordinates to Sinusoidal projection (easting and northing) + * coordinates, according to the current ellipsoid and Sinusoidal projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise SINU_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + + double slat = sin(Latitude); + double sin2lat, sin4lat, sin6lat; + double dlam; /* Longitude - Central Meridan */ + double mm; + double MM; + long Error_Code = SINU_NO_ERROR; + +// if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2)) +// { /* Latitude out of range */ +// Error_Code |= SINU_LAT_ERROR; +// } +// if ((Longitude < -M_PI) || (Longitude > TWO_PI)) +// { /* Longitude out of range */ +// Error_Code |= SINU_LON_ERROR; +// } + if (!Error_Code) + { /* no errors */ + dlam = Longitude - Sinu_Origin_Long; +// if (dlam > M_PI) +// { +// dlam -= TWO_PI; +// } +// if (dlam < -M_PI) +// { +// dlam += TWO_PI; +// } + mm = sqrt(1.0 - es2 * slat * slat); + + sin2lat = SINU_COEFF_TIMES_SIN(c1, 2.0, Latitude); + sin4lat = SINU_COEFF_TIMES_SIN(c2, 4.0, Latitude); + sin6lat = SINU_COEFF_TIMES_SIN(c3, 6.0, Latitude); + MM = Sinu_a * (c0 * Latitude - sin2lat + sin4lat - sin6lat); + + *Easting = Sinu_a * dlam * cos(Latitude) / mm + Sinu_False_Easting; + *Northing = MM + Sinu_False_Northing; + } + return (Error_Code); +} /* END OF Convert_Geodetic_To_Sinusoidal */ + + +long ossimSinusoidalProjection::Convert_Sinusoidal_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const +{ /* BEGIN Convert_Sinusoidal_To_Geodetic */ +/* + * The function Convert_Sinusoidal_To_Geodetic converts Sinusoidal projection + * (easting and northing) coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Sinusoidal projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise SINU_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + + double dx; /* Delta easting - Difference in easting (easting-FE) */ + double dy; /* Delta northing - Difference in northing (northing-FN) */ + double mu; + double sin2mu, sin4mu, sin6mu, sin8mu; + double sin_lat; + long Error_Code = SINU_NO_ERROR; + +// if ((Easting < (Sinu_False_Easting + Sinu_Min_Easting)) +// || (Easting > (Sinu_False_Easting + Sinu_Max_Easting))) +// { /* Easting out of range */ +// Error_Code |= SINU_EASTING_ERROR; +// } +// if ((Northing < (Sinu_False_Northing - Sinu_Delta_Northing)) +// || (Northing > (Sinu_False_Northing + Sinu_Delta_Northing))) +// { /* Northing out of range */ +// Error_Code |= SINU_NORTHING_ERROR; +// } + if (!Error_Code) + { /* no errors */ + dy = Northing - Sinu_False_Northing; + dx = Easting - Sinu_False_Easting; + + mu = dy / (Sinu_a * c0); + sin2mu = SINU_COEFF_TIMES_SIN(a0, 2.0, mu); + sin4mu = SINU_COEFF_TIMES_SIN(a1, 4.0, mu); + sin6mu = SINU_COEFF_TIMES_SIN(a2, 6.0, mu); + sin8mu = SINU_COEFF_TIMES_SIN(a3, 8.0, mu); + *Latitude = mu + sin2mu + sin4mu + sin6mu + sin8mu; + + if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */ + *Latitude = PI_OVER_2; + else if (*Latitude < -PI_OVER_2) + *Latitude = -PI_OVER_2; + + if (FLOAT_EQ(fabs(*Latitude),PI_OVER_2,1.0e-8)) + *Longitude = Sinu_Origin_Long; + else + { + sin_lat = sin(*Latitude); + *Longitude = Sinu_Origin_Long + dx * sqrt(1.0 - es2 * + sin_lat * sin_lat) / (Sinu_a * cos(*Latitude)); + + +// if (*Longitude > M_PI) +// *Longitude -= TWO_PI; +// if (*Longitude < -M_PI) +// *Longitude += TWO_PI; + +// if (*Longitude > M_PI) /* force distorted values to 180, -180 degrees */ +// *Longitude = M_PI; +// else if (*Longitude < -M_PI) +// *Longitude = -M_PI; + } + } + return (Error_Code); +} /* END OF Convert_Sinusoidal_To_Geodetic */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimSinusoidalProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimSinusoidalProjection.h new file mode 100644 index 0000000000..6ab2f4462d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimSinusoidalProjection.h @@ -0,0 +1,201 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Sinusoidal projection code. +//******************************************************************* +// $Id: ossimSinusoidalProjection.h,v 1.5 2005/09/09 19:23:58 gpotts Exp $ + +#ifndef ossimSinusoidalProjection_HEADER +#define ossimSinusoidalProjection_HEADER + +#include "ossimMapProjection.h" + +class ossimSinusoidalProjection : public ossimMapProjection +{ +public: + ossimSinusoidalProjection(const ossimEllipsoid& ellipsoid = ossimEllipsoid(), + const ossimGpt& origin = ossimGpt()); + + ossimSinusoidalProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + const double falseEasting, + const double falseNorthing); + + ~ossimSinusoidalProjection(){} + + virtual ossimObject *dup()const{return new ossimSinusoidalProjection(*this);} + + + virtual ossimGpt inverse(const ossimDpt &eastingNorthing)const; + virtual ossimDpt forward(const ossimGpt &latLon)const; + virtual void update(); + + /*! + * SetFalseEasting. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEasting(double falseEasting); + + /*! + * SetFalseNorthing. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseNorthing(double falseNorthing); + + /*! + * Sets both false easting and northing values. The values are + * expected to be in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEastingNorthing(double falseEasting, double falseNorthing); + + void setDefaults(); + + double getFalseEasting()const{return Sinu_False_Easting;} + double getFalseNorthing()const{return Sinu_False_Northing;} + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +private: + + //_______________________GEOTRANS________________________ + mutable double Sinu_a; /* Semi-major axis of ellipsoid in meters */ + mutable double Sinu_f; /* Flattening of ellipsoid */ + mutable double es2; /* Eccentricity (0.08181919084262188000) squared */ + mutable double es4; /* es2 * es2 */ + mutable double es6; /* es4 * es2 */ + mutable double c0; /* 1 - es2 / 4.0 - 3.0 * es4 / 64.0 - 5.0 * es6 / 256.0 */ + mutable double c1; /* 3.0 * es2 / 8.0 + 3.0 * es4 / 32.0 + 45.0 * es6 / 1024.0 */ + mutable double c2; /* 15.0 * es4 / 256.0 + 45.0 * es6 / 1024.0 */ + mutable double c3; /* 35.0 * es6 / 3072.0 */ + mutable double a0; /* 3.0 * e1 / 2.0 - 27.0 * e3 / 32.0 */ + mutable double a1; /* 21.0 * e2 / 16.0 - 55.0 * e4 / 32.0 */ + mutable double a2; /* 151.0 * e3 / 96.0 */ + mutable double a3; /* 1097.0 * e4 / 512.0 */ + +/* Sinusoid projection Parameters */ + mutable double Sinu_Origin_Long; /* Longitude of origin in radians */ + mutable double Sinu_False_Northing; /* False northing in meters */ + mutable double Sinu_False_Easting; /* False easting in meters */ + +/* Maximum variance for easting and northing values for WGS 84. + */ + mutable double Sinu_Max_Easting; + mutable double Sinu_Min_Easting; + mutable double Sinu_Delta_Northing; + + +/*! + * The function Set_Sinusoidal_Parameters receives the ellipsoid parameters and + * Sinusoidal projcetion parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the function, + * otherwise SINU_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + long Set_Sinusoidal_Parameters(double a, + double f, + double Central_Meridian, + double False_Easting, + double False_Northing); + + + +/*! + * The function Get_Sinusoidal_Parameters returns the current ellipsoid + * parameters and Sinusoidal projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + void Get_Sinusoidal_Parameters(double *a, + double *f, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const; + + + +/*! + * The function Convert_Geodetic_To_Sinusoidal converts geodetic (latitude and + * longitude) coordinates to Sinusoidal projection easting, and northing + * coordinates, according to the current ellipsoid and Sinusoidal projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise SINU_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + long Convert_Geodetic_To_Sinusoidal (double Latitude, + double Longitude, + double *Easting, + double *Northing)const; + + +/*! + * The function Convert_Sinusoidal_To_Geodetic converts Sinusoidal projection + * easting and northing coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Sinusoida projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise SINU_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + long Convert_Sinusoidal_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimSpaceObliqueMercatorProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimSpaceObliqueMercatorProjection.cpp new file mode 100644 index 0000000000..c69615ddaa --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimSpaceObliqueMercatorProjection.cpp @@ -0,0 +1,408 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimSpaceObliqueMercatorProjection.cpp,v 1.14 2004/01/08 21:59:33 jlargent Exp $ +#include "ossimSpaceObliqueMercatorProjection.h" +#include <math.h> +#include "base/common/ossimConstants.h" + +#define PI_OVER_2 (M_PI/2) +#define PI (M_PI) +#define TWOPI (2*M_PI) +#define HALFPI (M_PI/2.0) +#define TOL 1e-7 +#define PI_HALFPI 4.71238898038468985766 +#define TWOPI_HALFPI 7.85398163397448309610 +#define ONE_TOL 1.00000000000001 +#define ATOL 1e-50 +#define FORTPI 0.78539816339744833 + +double aasin(double v) +{ + double av; + + if ((av = fabs(v)) >= 1.) + { + return (v < 0. ? -HALFPI : HALFPI); + } + return asin(v); +} +double aacos(double v) +{ + double av; + + if ((av = fabs(v)) >= 1.) + { + return (v < 0. ? PI : 0.); + } + return acos(v); +} +double asqrt(double v) +{ + return ((v <= 0) ? 0. : sqrt(v)); +} +double aatan2(double n, double d) +{ + return ((fabs(n) < ATOL && fabs(d) < ATOL) ? 0. : atan2(n,d)); +} + +static const char* PATH_KW = "path"; +static const char* SATELLITE_TYPE_KW = "satellite_type"; + +#if 0 +static const char* ANGLE_OF_INCLINATION_KW = "angle_of_inclination"; +static const char* REVOLUTION_TIME_KW = "earth_rev_time"; +static const char* EARTH_ROTATION_LENGTH_KW = "earth_rot_length"; +static const char* LONGITUDE_ASCENDING_NODE_KW = "lon_ascending_node"; +static const char* J_COEFFICIENT_KW = "j_coeff"; +static const char* W_COEFFICIENT_KW = "w_coeff"; +static const char* Q_COEFFICIENT_KW = "q_coeff"; +static const char* T_COEFFICIENT_KW = "t_coeff"; +static const char* A2_COEFFICIENT_KW = "a2_coeff"; +static const char* A4_COEFFICIENT_KW = "a4_coeff"; +static const char* B_COEFFICIENT_KW = "b_coeff"; +static const char* C1_COEFFICIENT_KW = "c1_coeff"; +static const char* C3_COEFFICIENT_KW = "c3_coeff"; +static const char* ECCENTRICITY_KW = "eccentricity"; +#endif + +RTTI_DEF1(ossimSpaceObliqueMercatorProjection, "ossimSpaceObliqueMercatorProjection", ossimMapProjection); + + +//***************************************************************************** +// CONSTRUCTOR +//***************************************************************************** +ossimSpaceObliqueMercatorProjection::ossimSpaceObliqueMercatorProjection + (ossimSatelliteType type, + double pathNumber, + const ossimEllipsoid& ellipsoid) + : + ossimMapProjection(ellipsoid) +{ + setParameters(type, pathNumber); +} + +//***************************************************************************** +// METHOD +//***************************************************************************** +void ossimSpaceObliqueMercatorProjection::setParameters(ossimSatelliteType type, + double path) +{ + thePath = path; + theSatelliteType = type; + double lam = 0.0; + double alf = 0.0; + double esc = 0.0; + double ess = 0.0; + + e = theEllipsoid.eccentricity(); + es = e*e; + one_es = 1- es; + rone_es = 1.0/one_es; + a = theEllipsoid.a(); + + switch(theSatelliteType) + { + case SOM_TYPE_LANDSAT_1: + case SOM_TYPE_LANDSAT_2: + case SOM_TYPE_LANDSAT_3: + { + lam0 = RAD_PER_DEG*(128.87 - (360.0/251.0)*path); + p22 = 103.2669323; + alf = RAD_PER_DEG * 99.092; + break; + } + case SOM_TYPE_LANDSAT_4: + case SOM_TYPE_LANDSAT_5: + case SOM_TYPE_LANDSAT_7: + { + + lam0 = RAD_PER_DEG*(129.305582487 - (360.0/233.0)*path); + p22 = 98.8841202; + alf = RAD_PER_DEG * 98.2; + break; + } + } + p22 /= 1440.; + sa = sin(alf); + ca = cos(alf); + if (fabs(ca) < 1e-9) + ca = 1e-9; + esc = es * ca * ca; + ess = es * sa * sa; + w = (1. - esc) * rone_es; + w = w * w - 1.; + q = ess * rone_es; + t = ess * (2. - es) * rone_es * rone_es; + u = esc * rone_es; + xj = one_es * one_es * one_es; + rlm = PI * (1. / 248. + .5161290322580645); + rlm2 = rlm + TWOPI; + a2 = a4 = b = c1 = c3 = 0.; + seraz0(0.0, 1.0); + for (lam = 9.; lam <= 81.0001; lam += 18.) + seraz0(lam, 4.0); + for (lam = 18; lam <= 72.0001; lam += 18.) + seraz0(lam, 2.0); + seraz0(90.0, 1.0); + a2 /= 30.0; + a4 /= 60.0; + b /= 30.0; + c1 /= 15.0; + c3 /= 45.0; + + update(); +} + +//***************************************************************************** +// METHOD +//***************************************************************************** +void ossimSpaceObliqueMercatorProjection::seraz0(double lam, + double mult) +{ + double sdsq, h, s, fc, sd, sq, d__1; + + lam *= RAD_PER_DEG; + sd = sin(lam); + sdsq = sd * sd; + s = p22 * sa * cos(lam) * sqrt((1. + t * sdsq) / (( + 1. + w * sdsq) * (1. + q * sdsq))); + d__1 = 1. + q * sdsq; + h = sqrt((1. + q * sdsq) / (1. + w * sdsq)) * ((1. + + w * sdsq) / (d__1 * d__1) - p22 * ca); + sq = sqrt(xj * xj + s * s); + b += fc = mult * (h * xj - s * s) / sq; + a2 += fc * cos(lam + lam); + a4 += fc * cos(lam * 4.); + fc = mult * s * (h + xj) / sq; + c1 += fc * cos(lam); + c3 += fc * cos(lam * 3.); + +} + +//***************************************************************************** +// METHOD +//***************************************************************************** +ossimDpt +ossimSpaceObliqueMercatorProjection::forward(const ossimGpt &worldPoint) const +{ + ossimGpt gpt = worldPoint; + + if (theDatum) + { + if (theDatum->code() != worldPoint.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + ossimDpt xy; + + int l, nn; + double lamt, xlam, sdsq, c, d, s, lamdp, phidp, lampp, tanph, + lamtp, cl, sd, sp, fac, sav, tanphi; + double phi = gpt.latr(); + double lam = gpt.lonr() - lam0; + + if (phi > HALFPI) + phi = HALFPI; + else if (phi < -HALFPI) + phi = -HALFPI; + lampp = phi >= 0. ? HALFPI : PI_HALFPI; + tanphi = tan(phi); + for (nn = 0;;) + { + sav = lampp; + lamtp = lam + p22 * lampp; + cl = cos(lamtp); + if (fabs(cl) < TOL) + lamtp -= TOL; + fac = lampp - sin(lampp) * (cl < 0. ? -HALFPI : HALFPI); + for (l = 50; l; --l) { + lamt = lam + p22 * sav; + if (fabs(c = cos(lamt)) < TOL) + lamt -= TOL; + xlam = (one_es * tanphi * sa + sin(lamt) * ca) / c; + lamdp = atan(xlam) + fac; + if (fabs(fabs(sav) - fabs(lamdp)) < TOL) + break; + sav = lamdp; + } + if (!l || ++nn >= 3 || (lamdp > rlm && lamdp < rlm2)) + break; + if (lamdp <= rlm) + lampp = TWOPI_HALFPI; + else if (lamdp >= rlm2) + lampp = HALFPI; + } + if (l) { + sp = sin(phi); + phidp = aasin((one_es * ca * sp - sa * cos(phi) * + sin(lamt)) / sqrt(1. - es * sp * sp)); + tanph = log(tan(FORTPI + .5 * phidp)); + sd = sin(lamdp); + sdsq = sd * sd; + s = p22 * sa * cos(lamdp) * sqrt((1. + t * sdsq) + / ((1. + w * sdsq) * (1. + q * sdsq))); + d = sqrt(xj * xj + s * s); + xy.x = b * lamdp + a2 * sin(2. * lamdp) + a4 * + sin(lamdp * 4.) - tanph * s / d; + xy.y = c1 * sd + c3 * sin(lamdp * 3.) + tanph * xj / d; + } + else + { + xy.x = xy.y = OSSIM_INFINITY; + } + + xy.x*=a; + xy.y*=a; + return xy; +} + +//***************************************************************************** +// METHOD +//***************************************************************************** +ossimGpt +ossimSpaceObliqueMercatorProjection::inverse(const ossimDpt &projectedPoint) + const +{ + int nn; + double lamt, sdsq, s, lamdp, phidp, sppsq, dd, sd, sl, fac, scl, sav, spp; + double lam, phi; + + ossimDpt xy = projectedPoint; + xy.x/=a; + xy.y/=a; + + lamdp = xy.x / b; + nn = 50; + do { + sav = lamdp; + sd = sin(lamdp); + sdsq = sd * sd; + s = p22 * sa * cos(lamdp) * sqrt((1. + t * sdsq) + / ((1. + w * sdsq) * (1. + q * sdsq))); + lamdp = xy.x + xy.y * s / xj - a2 * sin( + 2. * lamdp) - a4 * sin(lamdp * 4.) - s / xj * ( + c1 * sin(lamdp) + c3 * sin(lamdp * 3.)); + lamdp /= b; + } while (fabs(lamdp - sav) >= TOL && --nn); + sl = sin(lamdp); + fac = exp(sqrt(1. + s * s / xj / xj) * (xy.y - + c1 * sl - c3 * sin(lamdp * 3.))); + phidp = 2. * (atan(fac) - FORTPI); + dd = sl * sl; + if (fabs(cos(lamdp)) < TOL) + lamdp -= TOL; + spp = sin(phidp); + sppsq = spp * spp; + lamt = atan(((1. - sppsq * rone_es) * tan(lamdp) * ca - + spp * sa * sqrt((1. + q * dd) * (1. - sppsq) - sppsq * u) / + cos(lamdp)) / (1. - sppsq * (1. + u))); + sl = lamt >= 0. ? 1. : -1.; + scl = cos(lamdp) >= 0. ? 1. : -1; + lamt -= HALFPI * (1. - scl) * sl; + + lam = lamt - p22 * lamdp; + if (fabs(sa) < TOL) + phi = aasin(spp / sqrt(one_es * one_es + es * sppsq)); + else + phi = atan((tan(lamdp) * cos(lamt) - ca * sin(lamt)) / + (one_es * sa)); + return ossimGpt(phi*DEG_PER_RAD, + (lam+lam0)*DEG_PER_RAD, 0.0, theDatum); + +} + +//***************************************************************************** +// METHOD +//***************************************************************************** +void ossimSpaceObliqueMercatorProjection::update() +{ +// theMetersPerPixel.x = 1.0; +// theMetersPerPixel.y = 1.0; + +// theUlEastingNorthing.x = 0.0; +// theUlEastingNorthing.y = 0.0; +} + + +//***************************************************************************** +// METHOD +//***************************************************************************** +bool ossimSpaceObliqueMercatorProjection::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + kwl.add(prefix, + PATH_KW, + thePath, + true); + + kwl.add(prefix, + SATELLITE_TYPE_KW, + (int)theSatelliteType, + true); + return ossimMapProjection::saveState(kwl, prefix); +} + +//***************************************************************************** +// METHOD +//***************************************************************************** +bool ossimSpaceObliqueMercatorProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + bool result = true; + + const char* path = kwl.find(prefix, PATH_KW); + const char* type = kwl.find(prefix, SATELLITE_TYPE_KW); + + if(path) + { + thePath = ossimString(path).toDouble(); + } + else + { + result = false; + } + if(type) + { + theSatelliteType = (ossimSatelliteType)ossimString(type).toInt(); + } + else + { + result = false; + } + + setParameters(theSatelliteType, thePath); + + if(result) + { + result = ossimMapProjection::loadState(kwl, prefix); + } + else + { + ossimMapProjection::loadState(kwl, prefix); + } + + return result; +} diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimSpaceObliqueMercatorProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimSpaceObliqueMercatorProjection.h new file mode 100644 index 0000000000..e1d50a84b5 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimSpaceObliqueMercatorProjection.h @@ -0,0 +1,105 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimSpaceObliqueMercatorProjection.h,v 1.6 2005/09/09 19:23:58 gpotts Exp $ +#ifndef ossimSpaceObliqueMercatorProjection_HEADER +#define ossimSpaceObliqueMercatorProjection_HEADER +#include "ossimMapProjection.h" + +/*! + * This class implments the formulas for the ellipsoid and + * circular orbit. All formulas were directly taken from + * proj 4. Proj 4 implementation is from the following + * manual reference: + * + * Map Projections - A Working Manual + * by John Snyder + * Space Oblique Mercator p. 221. + * + * + */ +class ossimSpaceObliqueMercatorProjection : public ossimMapProjection +{ +public: + enum ossimSatelliteType + { + SOM_TYPE_LANDSAT_1 = 0, + SOM_TYPE_LANDSAT_2 = 1, + SOM_TYPE_LANDSAT_3 = 2, + SOM_TYPE_LANDSAT_4 = 3, + SOM_TYPE_LANDSAT_5 = 4, + SOM_TYPE_LANDSAT_7 = 5 + }; + + ossimSpaceObliqueMercatorProjection(ossimSatelliteType type=SOM_TYPE_LANDSAT_7, + double pathNumber=34, + const ossimEllipsoid& ellipsoid = ossimEllipsoid()); + + virtual ossimObject* dup()const{return new ossimSpaceObliqueMercatorProjection(*this);} + virtual ossimDpt forward(const ossimGpt &worldPoint) const; + virtual ossimGpt inverse(const ossimDpt &projectedPoint)const; + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0) const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual void setParameters(ossimSatelliteType type, + double path); + + virtual void update(); +protected: + + // proj 4 parameters that I bridge to. + // + double a2, a4, b, c1, c3; + double q, t, u, w, p22, sa, ca, xj, rlm, rlm2; + + // proj4 stuff + double lam0; + double es; + double e; + double one_es; + double rone_es; + double a; + + void seraz0(double lam, double mult); + + /*! + * Is the p variable in Map Projections a Working Manual. + */ + double thePath; + ossimSatelliteType theSatelliteType; + +TYPE_DATA +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimStereographicProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimStereographicProjection.cpp new file mode 100644 index 0000000000..f5fbcc3b6b --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimStereographicProjection.cpp @@ -0,0 +1,511 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimStereographicProjection.cpp,v 1.4 2004/01/08 21:49:22 jlargent Exp $ + +#include "ossimStereographicProjection.h" +#include "base/common/ossimKeywordNames.h" + +RTTI_DEF1(ossimStereographicProjection, "ossimStereographicProjection", ossimMapProjection) + +#ifndef PI_OVER_2 +# define PI_OVER_2 ( M_PI / 2.0) +#endif +#ifndef PI_OVER_4 +# define PI_OVER_4 ( M_PI / 4.0) +#endif +#ifndef TWO_PI +# define TWO_PI (2.0 * M_PI) +#endif +#define ONE (1.0 * M_PI / 180.0) /* 1 degree in radians*/ + +#define STEREO_NO_ERROR 0x0000 +#define STEREO_LAT_ERROR 0x0001 +#define STEREO_LON_ERROR 0x0002 +#define STEREO_ORIGIN_LAT_ERROR 0x0004 +#define STEREO_CENT_MER_ERROR 0x0008 +#define STEREO_EASTING_ERROR 0x0010 +#define STEREO_NORTHING_ERROR 0x0020 +#define STEREO_A_ERROR 0x0040 +#define STEREO_INV_F_ERROR 0x0080 + +ossimStereographicProjection::ossimStereographicProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + :ossimMapProjection(ellipsoid, origin) +{ + setDefaults(); + update(); +} + +ossimStereographicProjection::ossimStereographicProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double falseEasting, + double falseNorthing) + :ossimMapProjection(ellipsoid, origin) +{ + Stereo_False_Easting = falseEasting; + Stereo_False_Northing = falseNorthing; + Stereo_Delta_Easting = 1460090226.0; + Stereo_Delta_Northing = 1460090226.0; + + update(); +} + +void ossimStereographicProjection::update() +{ + Set_Stereographic_Parameters(theEllipsoid.getA(), + theEllipsoid.getFlattening(), + theOrigin.latr(), + theOrigin.lonr(), + Stereo_False_Easting, + Stereo_False_Northing); + + ossimMapProjection::update(); +} + +void ossimStereographicProjection::setFalseEasting(double falseEasting) +{ + Stereo_False_Easting = falseEasting; + + update(); +} + +void ossimStereographicProjection::setFalseNorthing(double falseNorthing) +{ + Stereo_False_Northing = falseNorthing; + + update(); +} + +void ossimStereographicProjection::setDefaults() +{ + Stereo_False_Easting = 0.0; + Stereo_False_Northing = 0.0; + Stereo_Delta_Easting = 1460090226.0; + Stereo_Delta_Northing = 1460090226.0; +} + +void ossimStereographicProjection::setFalseEastingNorthing(double falseEasting, + double falseNorthing) +{ + Stereo_False_Easting = falseEasting; + Stereo_False_Northing = falseNorthing; + + update(); +} + +ossimGpt ossimStereographicProjection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat = 0.0; + double lon = 0.0; + + Convert_Stereographic_To_Geodetic(eastingNorthing.x, + eastingNorthing.y, + &lat, + &lon); + + return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum); +} + +ossimDpt ossimStereographicProjection::forward(const ossimGpt &latLon)const +{ + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + Convert_Geodetic_To_Stereographic(gpt.latr(), + gpt.lonr(), + &easting, + &northing); + + return ossimDpt(easting, northing); +} + +bool ossimStereographicProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const +{ + kwl.add(prefix, + ossimKeywordNames::FALSE_EASTING_KW, + Stereo_False_Easting, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_NORTHING_KW, + Stereo_False_Northing, + true); + + return ossimMapProjection::saveState(kwl, prefix); +} + +bool ossimStereographicProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + bool flag = ossimMapProjection::loadState(kwl, prefix); + const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + const char* falseEasting = kwl.find(prefix, ossimKeywordNames::FALSE_EASTING_KW); + const char* falseNorthing = kwl.find(prefix, ossimKeywordNames::FALSE_NORTHING_KW); + + setDefaults(); + if(ossimString(type) == STATIC_TYPE_NAME(ossimStereographicProjection)) + { + if(falseEasting) + { + Stereo_False_Easting = ossimString(falseEasting).toDouble(); + } + if(falseNorthing) + { + Stereo_False_Northing = ossimString(falseNorthing).toDouble(); + } + } + + update(); + + return flag; +} +/************************************************************************/ +/* FUNCTIONS + * + */ + +long ossimStereographicProjection::Set_Stereographic_Parameters (double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing) + +{ /* BEGIN Set_Stereographic_Parameters */ +/* + * The function Set_Stereographic_Parameters receives the ellipsoid + * parameters and Stereograpic projection parameters as inputs, and + * sets the corresponding state variables. If any errors occur, error + * code(s) are returned by the function, otherwise STEREO_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude, in radians, at the center of (input) + * the projection + * Central_Meridian : Longitude, in radians, at the center of (input) + * the projection + * False_Easting : Easting (X) at center of projection, in meters (input) + * False_Northing : Northing (Y) at center of projection, in meters (input) + */ + + double es2, es4, es6; + double temp = 0; +// double inv_f = 1 / f; + long Error_Code = STEREO_NO_ERROR; + +// if (a <= 0.0) +// { /* Semi-major axis must be greater than zero */ +// Error_Code |= STEREO_A_ERROR; +// } +// if ((inv_f < 250) || (inv_f > 350)) +// { /* Inverse flattening must be between 250 and 350 */ +// Error_Code |= STEREO_INV_F_ERROR; +// } +// if ((Origin_Latitude < -PI_OVER_2) || (Origin_Latitude > PI_OVER_2)) +// { /* origin latitude out of range */ +// Error_Code |= STEREO_ORIGIN_LAT_ERROR; +// } +// if ((Central_Meridian < -M_PI) || (Central_Meridian > TWO_PI)) +// { /* origin longitude out of range */ +// Error_Code |= STEREO_CENT_MER_ERROR; +// } + if (!Error_Code) + { /* no errors */ + Stereo_a = a; + Stereo_f = f; + es2 = 2 * Stereo_f - Stereo_f * Stereo_f; + es4 = es2 * es2; + es6 = es4 * es2; + Stereo_Ra = Stereo_a * (1.0 - es2 / 6.0 - 17.0 * es4 / 360.0 - 67.0 * es6 /3024.0); + Two_Stereo_Ra = 2.0 * Stereo_Ra; + Stereo_Origin_Lat = Origin_Latitude; + Sin_Stereo_Origin_Lat = sin(Stereo_Origin_Lat); + Cos_Stereo_Origin_Lat = cos(Stereo_Origin_Lat); +// if (Central_Meridian > M_PI) +// Central_Meridian -= TWO_PI; + Stereo_Origin_Long = Central_Meridian; + Stereo_False_Easting = False_Easting; + Stereo_False_Northing = False_Northing; + if(fabs(fabs(Stereo_Origin_Lat) - PI_OVER_2) < 1.0e-10) + Stereo_At_Pole = 1; + else + Stereo_At_Pole = 0; + + if ((Stereo_At_Pole) || (fabs(Stereo_Origin_Lat) < 1.0e-10)) + { + Stereo_Delta_Easting = 1460090226.0; + } + else + { + if (Stereo_Origin_Long <= 0) + Convert_Geodetic_To_Stereographic(-Stereo_Origin_Lat, M_PI + Stereo_Origin_Long - ONE, &Stereo_Delta_Easting, &temp); + else + Convert_Geodetic_To_Stereographic(-Stereo_Origin_Lat, Stereo_Origin_Long - M_PI - ONE, &Stereo_Delta_Easting, &temp); + } + + } /* END OF if(!Error_Code) */ + return (Error_Code); +} /* END OF Set_Stereographic_Parameters */ + +void ossimStereographicProjection::Get_Stereographic_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const + +{ /* BEGIN Get_Stereographic_Parameters */ +/* + * The function Get_Stereographic_Parameters returns the current ellipsoid + * parameters and Stereographic projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude, in radians, at the center of (output) + * the projection + * Central_Meridian : Longitude, in radians, at the center of (output) + * the projection + * False_Easting : A coordinate value, in meters, assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value, in meters, assigned to the + * origin latitude of the projection (output) + */ + + *a = Stereo_a; + *f = Stereo_f; + *Origin_Latitude = Stereo_Origin_Lat; + *Central_Meridian = Stereo_Origin_Long; + *False_Easting = Stereo_False_Easting; + *False_Northing = Stereo_False_Northing; + + return; +} /* END OF Get_Stereographic_Parameters */ + +long ossimStereographicProjection::Convert_Geodetic_To_Stereographic (double Latitude, + double Longitude, + double *Easting, + double *Northing)const + +{ /* BEGIN Convert_Geodetic_To_Stereographic */ + +/* + * The function Convert_Geodetic_To_Stereographic converts geodetic + * coordinates (latitude and longitude) to Stereographic coordinates + * (easting and northing), according to the current ellipsoid + * and Stereographic projection parameters. If any errors occur, error + * code(s) are returned by the function, otherwise STEREO_NO_ERROR is returned. + * + * Latitude : Latitude, in radians (input) + * Longitude : Longitude, in radians (input) + * Easting : Easting (X), in meters (output) + * Northing : Northing (Y), in meters (output) + */ + + double g, k; + double num = 0; + double Ra_k = 0; + double slat = sin(Latitude); + double clat = cos(Latitude); + double dlam; /* Longitude - Central Meridan */ + double cos_dlam; + long Error_Code = STEREO_NO_ERROR; + +// if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2)) +// { /* Latitude out of range */ +// Error_Code |= STEREO_LAT_ERROR; +// } +// if ((Longitude < -M_PI) || (Longitude > TWO_PI)) +// { /* Longitude out of range */ +// Error_Code|= STEREO_LON_ERROR; +// } + if (!Error_Code) + { /* no errors */ + + + dlam = Longitude - Stereo_Origin_Long; +// if (dlam > M_PI) +// { +// dlam -= TWO_PI; +// } +// if (dlam < -M_PI) +// { +// dlam += TWO_PI; +// } + + cos_dlam = cos(dlam); + g = 1.0 + Sin_Stereo_Origin_Lat * slat + Cos_Stereo_Origin_Lat * clat * cos_dlam; + if (fabs(g) <= 1.0e-10) + { /* Point is out of view. Will return longitude out of range message + since no point out of view is implemented. */ + Error_Code |= STEREO_LON_ERROR; + } + else + { + if (Stereo_At_Pole) + { + if (fabs(fabs(Latitude) - PI_OVER_2) < 1.0e-10) + { + *Easting = Stereo_False_Easting; + *Northing = Stereo_False_Northing; + } + else + { + if (Stereo_Origin_Lat > 0) + { + num = Two_Stereo_Ra * tan(PI_OVER_4 - Latitude / 2.0); + *Easting = Stereo_False_Easting + num * sin(dlam); + *Northing = Stereo_False_Northing + (-num * cos_dlam); + } + else + { + num = Two_Stereo_Ra * tan(PI_OVER_4 + Latitude / 2.0); + *Easting = Stereo_False_Easting + num * sin(dlam); + *Northing = Stereo_False_Northing + num * cos_dlam; + } + } + } + else + { + if (fabs(Stereo_Origin_Lat) <= 1.0e-10) + { + k = 2.0 / (1.0 + clat * cos_dlam); + Ra_k = Stereo_Ra * k; + *Northing = Stereo_False_Northing + Ra_k * slat; + } + else + { + k = 2.0 / g; + Ra_k = Stereo_Ra * k; + *Northing = Stereo_False_Northing + Ra_k * (Cos_Stereo_Origin_Lat * slat - Sin_Stereo_Origin_Lat * clat * cos_dlam); + } + *Easting = Stereo_False_Easting + Ra_k * clat * sin(dlam); + } + } + } + return (Error_Code); +} /* END OF Convert_Geodetic_To_Stereographic */ + +long ossimStereographicProjection::Convert_Stereographic_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const +{ /* BEGIN Convert_Stereographic_To_Geodetic */ +/* + * The function Convert_Stereographic_To_Geodetic converts Stereographic projection + * (easting and northing) coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Stereographic projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise STEREO_NO_ERROR is returned. + * + * Easting : Easting (X), in meters (input) + * Northing : Northing (Y), in meters (input) + * Latitude : Latitude (phi), in radians (output) + * Longitude : Longitude (lambda), in radians (output) + */ + + double dx, dy; + double rho, c; + double sin_c, cos_c; + double dy_sin_c; + long Error_Code = STEREO_NO_ERROR; + +// if ((Easting < (Stereo_False_Easting - Stereo_Delta_Easting)) +// ||(Easting > (Stereo_False_Easting + Stereo_Delta_Easting))) +// { /* Easting out of range */ +// Error_Code |= STEREO_EASTING_ERROR; +// } +// if ((Northing < (Stereo_False_Northing - Stereo_Delta_Northing)) +// || (Northing > (Stereo_False_Northing + Stereo_Delta_Northing))) +// { /* Northing out of range */ +// Error_Code |= STEREO_NORTHING_ERROR; +// } + if (!Error_Code) + { /* no errors */ + + dy = Northing - Stereo_False_Northing; + dx = Easting - Stereo_False_Easting; + rho = sqrt(dx * dx + dy * dy); + if (fabs(rho) <= 1.0e-10) + { + *Latitude = Stereo_Origin_Lat; + *Longitude = Stereo_Origin_Long; + } + else + { + c = 2.0 * atan(rho / (Two_Stereo_Ra)); + sin_c = sin(c); + cos_c = cos(c); + dy_sin_c = dy * sin_c; + if (Stereo_At_Pole) + { + if (Stereo_Origin_Lat > 0) + *Longitude = Stereo_Origin_Long + atan2(dx, -dy); + else + *Longitude = Stereo_Origin_Long + atan2(dx, dy); + } + else + *Longitude = Stereo_Origin_Long + atan2(dx * sin_c, (rho * Cos_Stereo_Origin_Lat * cos_c - dy_sin_c * Sin_Stereo_Origin_Lat)); + *Latitude = asin(cos_c * Sin_Stereo_Origin_Lat + ((dy_sin_c * Cos_Stereo_Origin_Lat) / rho)); + } + +// if (fabs(*Latitude) < 2.2e-8) /* force lat to 0 to avoid -0 degrees */ +// *Latitude = 0.0; +// if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */ +// *Latitude = PI_OVER_2; +// else if (*Latitude < -PI_OVER_2) +// *Latitude = -PI_OVER_2; + +// if (*Longitude > M_PI) +// { +// if (*Longitude - M_PI < 3.5e-6) +// *Longitude = M_PI; +// else +// *Longitude -= TWO_PI; +// } +// if (*Longitude < -M_PI) +// { +// if (fabs(*Longitude + M_PI) < 3.5e-6) +// *Longitude = -M_PI; +// else +// *Longitude += TWO_PI; +// } +// +// if (fabs(*Longitude) < 2.0e-7) /* force lon to 0 to avoid -0 degrees */ +// *Longitude = 0.0; +// if (*Longitude > M_PI) /* force distorted values to 180, -180 degrees */ +// *Longitude = M_PI; +// else if (*Longitude < -M_PI) +// *Longitude = -M_PI; + } + return (Error_Code); +} /* END OF Convert_Stereographic_To_Geodetic */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimStereographicProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimStereographicProjection.h new file mode 100644 index 0000000000..cff7bcce8c --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimStereographicProjection.h @@ -0,0 +1,193 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimStereographicProjection.h,v 1.2 2005/09/09 19:23:58 gpotts Exp $ + +#ifndef ossimStereographicProjection_HEADER +#define ossimStereographicProjection_HEADER + +#include "ossimMapProjection.h" + +class ossimStereographicProjection : public ossimMapProjection +{ +public: + ossimStereographicProjection(const ossimEllipsoid& ellipsoid = ossimEllipsoid(), + const ossimGpt& origin = ossimGpt()); + ossimStereographicProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + const double falseEasting, + const double falseNorthing); + ~ossimStereographicProjection(){} + virtual ossimObject *dup()const + { + return new ossimStereographicProjection(*this); + } + + virtual void update(); + virtual ossimGpt inverse(const ossimDpt &eastingNorthing)const; + virtual ossimDpt forward(const ossimGpt &latLon)const; + + /*! + * SetFalseEasting. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEasting(double falseEasting); + + /*! + * SetFalseNorthing. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseNorthing(double falseNorthing); + + /*! + * Sets both false easting and northing values. The values are + * expected to be in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEastingNorthing(double falseEasting, double falseNorthing); + + void setDefaults(); + + double getFalseEasting()const{return Stereo_False_Easting;} + double getFalseNorthing()const{return Stereo_False_Northing;} + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); +private: + +/************************************************************************/ +/* GLOBAL DECLARATIONS + * + */ +/* Ellipsoid Parameters, default to WGS 84 */ +mutable double Stereo_a; /* Semi-major axis of ellipsoid, in meters */ +mutable double Stereo_f; /* Flattening of ellipsoid */ +mutable double Stereo_Ra; /* Spherical Radius */ +mutable double Two_Stereo_Ra; /* 2 * Spherical Radius */ +mutable long Stereo_At_Pole; /* Flag variable */ + +/* Stereographic projection Parameters */ +mutable double Stereo_Origin_Lat; /* Latitude of origin, in radians */ +mutable double Stereo_Origin_Long; /* Longitude of origin, in radians */ +mutable double Stereo_False_Easting; /* False easting, in meters */ +mutable double Stereo_False_Northing; /* False northing, in meters */ +mutable double Sin_Stereo_Origin_Lat; /* sin(Stereo_Origin_Lat) */ +mutable double Cos_Stereo_Origin_Lat; /* cos(Stereo_Origin_Lat) */ + +/* Maximum variance for easting and northing values for WGS 84. */ +mutable double Stereo_Delta_Easting; +mutable double Stereo_Delta_Northing; + +/*! + * The function Set_Stereographic_Parameters receives the ellipsoid + * parameters and Stereograpic projection parameters as inputs, and + * sets the corresponding state variables. If any errors occur, error + * code(s) are returned by the function, otherwise STEREO_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude, in radians, at the center of (input) + * the projection + * Central_Meridian : Longitude, in radians, at the center of (input) + * the projection + * False_Easting : Easting (X) at center of projection, in meters (input) + * False_Northing : Northing (Y) at center of projection, in meters (input) + */ +long Set_Stereographic_Parameters (double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing); + +/*! + * The function Get_Stereographic_Parameters returns the current ellipsoid + * parameters and Stereographic projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude, in radians, at the center of (output) + * the projection + * Central_Meridian : Longitude, in radians, at the center of (output) + * the projection + * False_Easting : A coordinate value, in meters, assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value, in meters, assigned to the + * origin latitude of the projection (output) + */ +void Get_Stereographic_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const; + +/*! + * The function Convert_Geodetic_To_Stereographic converts geodetic + * coordinates (latitude and longitude) to Stereographic coordinates + * (easting and northing), according to the current ellipsoid + * and Stereographic projection parameters. If any errors occur, error + * code(s) are returned by the function, otherwise STEREO_NO_ERROR is returned. + * + * Latitude : Latitude, in radians (input) + * Longitude : Longitude, in radians (input) + * Easting : Easting (X), in meters (output) + * Northing : Northing (Y), in meters (output) + */ +long Convert_Geodetic_To_Stereographic (double Latitude, + double Longitude, + double *Easting, + double *Northing)const; + +/*! + * The function Convert_Stereographic_To_Geodetic converts Stereographic projection + * (easting and northing) coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Stereographic projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise STEREO_NO_ERROR is returned. + * + * Easting : Easting (X), in meters (input) + * Northing : Northing (Y), in meters (input) + * Latitude : Latitude (phi), in radians (output) + * Longitude : Longitude (lambda), in radians (output) + */ +long Convert_Stereographic_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimTranmerc.c b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimTranmerc.c new file mode 100644 index 0000000000..cc9e0cecd0 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimTranmerc.c @@ -0,0 +1,625 @@ +/***************************************************************************/ +/* RSC IDENTIFIER: TRANSVERSE MERCATOR + * + * ABSTRACT + * + * This component provides conversions between Geodetic coordinates + * (latitude and longitude) and Transverse Mercator projection coordinates + * (easting and northing). + * + * ERROR HANDLING + * + * This component checks parameters for valid values. If an invalid value + * is found the error code is combined with the current error code using + * the bitwise or. This combining allows multiple error codes to be + * returned. The possible error codes are: + * + * TRANMERC_NO_ERROR : No errors occurred in function + * TRANMERC_LAT_ERROR : Latitude outside of valid range + * (-90 to 90 degrees) + * TRANMERC_LON_ERROR : Longitude outside of valid range + * (-180 to 360 degrees, and within + * +/-90 of Central Meridian) + * TRANMERC_EASTING_ERROR : Easting outside of valid range + * (depending on ellipsoid and + * projection parameters) + * TRANMERC_NORTHING_ERROR : Northing outside of valid range + * (depending on ellipsoid and + * projection parameters) + * TRANMERC_ORIGIN_LAT_ERROR : Origin latitude outside of valid range + * (-90 to 90 degrees) + * TRANMERC_CENT_MER_ERROR : Central meridian outside of valid range + * (-180 to 360 degrees) + * TRANMERC_A_ERROR : Semi-major axis less than or equal to zero + * TRANMERC_INV_F_ERROR : Inverse flattening outside of valid range + * (250 to 350) + * TRANMERC_SCALE_FACTOR_ERROR : Scale factor outside of valid + * range (0.3 to 3.0) + * TM_LON_WARNING : Distortion will result if longitude is more + * than 9 degrees from the Central Meridian + * + * REUSE NOTES + * + * TRANSVERSE MERCATOR is intended for reuse by any application that + * performs a Transverse Mercator projection or its inverse. + * + * REFERENCES + * + * Further information on TRANSVERSE MERCATOR can be found in the + * Reuse Manual. + * + * TRANSVERSE MERCATOR originated from : + * U.S. Army Topographic Engineering Center + * Geospatial Information Division + * 7701 Telegraph Road + * Alexandria, VA 22310-3864 + * + * LICENSES + * + * None apply to this component. + * + * RESTRICTIONS + * + * TRANSVERSE MERCATOR has no restrictions. + * + * ENVIRONMENT + * + * TRANSVERSE MERCATOR was tested and certified in the following + * environments: + * + * 1. Solaris 2.5 with GCC, version 2.8.1 + * 2. Windows 95 with MS Visual C++, version 6 + * + * MODIFICATIONS + * + * Date Description + * ---- ----------- + * 10-02-97 Original Code + * 03-02-97 Re-engineered Code + * + */ + + +/***************************************************************************/ +/* + * INCLUDES + */ + +#include <stdio.h> +#include <math.h> +#include "ossimTranmerc.h" +#include "base/common/ossimConstants.h" + +/* + * math.h - Standard C math library + * tranmerc.h - Is for prototype error checking + */ + + +/****************************** DEFINES ************************************/ + +#define MAX_LAT ((M_PI * 90.0)/180.0) /* 90 degrees in radians */ +#define MAX_DELTA_LONG ((M_PI * 90.0)/180.0) /* 90 degrees in radians */ +#define MIN_SCALE_FACTOR 0.3 +#define MAX_SCALE_FACTOR 3.0 + +#define SPHTMD(Latitude) ((double) (TranMerc_ap * Latitude \ + - TranMerc_bp * sin(2.e0 * Latitude) + TranMerc_cp * sin(4.e0 * Latitude) \ + - TranMerc_dp * sin(6.e0 * Latitude) + TranMerc_ep * sin(8.e0 * Latitude) ) ) + +#define SPHSN(Latitude) ((double) (TranMerc_a / sqrt( 1.e0 - TranMerc_es * \ + pow(sin(Latitude), 2)))) + +#define SPHSR(Latitude) ((double) (TranMerc_a * (1.e0 - TranMerc_es) / \ + pow(DENOM(Latitude), 3))) + +#define DENOM(Latitude) ((double) (sqrt(1.e0 - TranMerc_es * pow(sin(Latitude),2)))) + + +/**************************************************************************/ +/* GLOBAL DECLARATIONS + * + */ + +/* Ellipsoid Parameters, default to WGS 84 */ +static double TranMerc_a = 6378137.0; /* Semi-major axis of ellipsoid i meters */ +static double TranMerc_f = 1 / 298.257223563; /* Flattening of ellipsoid */ +static double TranMerc_es = 0.0066943799901413800; /* Eccentricity (0.08181919084262188000) squared */ +static double TranMerc_ebs = 0.0067394967565869; /* Second Eccentricity squared */ + +/* Transverse_Mercator projection Parameters */ +static double TranMerc_Origin_Lat = 0.0; /* Latitude of origin in radians */ +static double TranMerc_Origin_Long = 0.0; /* Longitude of origin in radians */ +static double TranMerc_False_Northing = 0.0; /* False northing in meters */ +static double TranMerc_False_Easting = 0.0; /* False easting in meters */ +static double TranMerc_Scale_Factor = 1.0; /* Scale factor */ + +/* Isometeric to geodetic latitude parameters, default to WGS 84 */ +static double TranMerc_ap = 6367449.1458008; +static double TranMerc_bp = 16038.508696861; +static double TranMerc_cp = 16.832613334334; +static double TranMerc_dp = 0.021984404273757; +static double TranMerc_ep = 3.1148371319283e-005; + +/* Maximum variance for easting and northing values for WGS 84. */ +static double TranMerc_Delta_Easting = 40000000.0; +static double TranMerc_Delta_Northing = 40000000.0; + +/* These state variables are for optimization purposes. The only function + * that should modify them is Set_Tranverse_Mercator_Parameters. */ + + +/************************************************************************/ +/* FUNCTIONS + * + */ + + +long Set_Transverse_Mercator_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing, + double Scale_Factor) + +{ /* BEGIN Set_Tranverse_Mercator_Parameters */ + /* + * The function Set_Tranverse_Mercator_Parameters receives the ellipsoid + * parameters and Tranverse Mercator projection parameters as inputs, and + * sets the corresponding state variables. If any errors occur, the error + * code(s) are returned by the function, otherwise TRANMERC_NO_ERROR is + * returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at the origin of the (input) + * projection + * Central_Meridian : Longitude in radians at the center of the (input) + * projection + * False_Easting : Easting/X at the center of the projection (input) + * False_Northing : Northing/Y at the center of the projection (input) + * Scale_Factor : Projection scale factor (input) + */ + + double tn; /* True Meridianal distance constant */ + double tn2; + double tn3; + double tn4; + double tn5; + double dummy_northing; + double TranMerc_b; /* Semi-minor axis of ellipsoid, in meters */ +/* double inv_f = 1 / f; */ + long Error_Code = TRANMERC_NO_ERROR; + +#if 0 + if (a <= 0.0) + { /* Semi-major axis must be greater than zero */ + Error_Code |= TRANMERC_A_ERROR; + } + if ((inv_f < 250) || (inv_f > 350)) + { /* Inverse flattening must be between 250 and 350 */ + Error_Code |= TRANMERC_INV_F_ERROR; + } + if ((Origin_Latitude < -MAX_LAT) || (Origin_Latitude > MAX_LAT)) + { /* origin latitude out of range */ + Error_Code |= TRANMERC_ORIGIN_LAT_ERROR; + } + if ((Central_Meridian < -M_PI) || (Central_Meridian > (TWO_PI))) + { /* origin longitude out of range */ + Error_Code |= TRANMERC_CENT_MER_ERROR; + } + if ((Scale_Factor < MIN_SCALE_FACTOR) || (Scale_Factor > MAX_SCALE_FACTOR)) + { + Error_Code |= TRANMERC_SCALE_FACTOR_ERROR; + } +#endif + if (!Error_Code) + { /* no errors */ + TranMerc_a = a; + TranMerc_f = f; + TranMerc_Origin_Lat = 0; + TranMerc_Origin_Long = 0; + TranMerc_False_Northing = 0; + TranMerc_False_Easting = 0; + TranMerc_Scale_Factor = 1; + + /* Eccentricity Squared */ + TranMerc_es = 2 * TranMerc_f - TranMerc_f * TranMerc_f; + /* Second Eccentricity Squared */ + TranMerc_ebs = (1 / (1 - TranMerc_es)) - 1; + + TranMerc_b = TranMerc_a * (1 - TranMerc_f); + /*True meridianal constants */ + tn = (TranMerc_a - TranMerc_b) / (TranMerc_a + TranMerc_b); + tn2 = tn * tn; + tn3 = tn2 * tn; + tn4 = tn3 * tn; + tn5 = tn4 * tn; + + TranMerc_ap = TranMerc_a * (1.e0 - tn + 5.e0 * (tn2 - tn3)/4.e0 + + 81.e0 * (tn4 - tn5)/64.e0 ); + TranMerc_bp = 3.e0 * TranMerc_a * (tn - tn2 + 7.e0 * (tn3 - tn4) + /8.e0 + 55.e0 * tn5/64.e0 )/2.e0; + TranMerc_cp = 15.e0 * TranMerc_a * (tn2 - tn3 + 3.e0 * (tn4 - tn5 )/4.e0) /16.0; + TranMerc_dp = 35.e0 * TranMerc_a * (tn3 - tn4 + 11.e0 * tn5 / 16.e0) / 48.e0; + TranMerc_ep = 315.e0 * TranMerc_a * (tn4 - tn5) / 512.e0; + Convert_Geodetic_To_Transverse_Mercator(MAX_LAT, + MAX_DELTA_LONG, + &TranMerc_Delta_Easting, + &TranMerc_Delta_Northing); + Convert_Geodetic_To_Transverse_Mercator(0, + MAX_DELTA_LONG, + &TranMerc_Delta_Easting, + &dummy_northing); + TranMerc_Origin_Lat = Origin_Latitude; + if (Central_Meridian > M_PI) + Central_Meridian -= (TWO_PI); + TranMerc_Origin_Long = Central_Meridian; + TranMerc_False_Northing = False_Northing; + TranMerc_False_Easting = False_Easting; + TranMerc_Scale_Factor = Scale_Factor; + } /* END OF if(!Error_Code) */ + + return (Error_Code); +} /* END of Set_Transverse_Mercator_Parameters */ + + +void Get_Transverse_Mercator_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *False_Easting, + double *False_Northing, + double *Scale_Factor) + +{ /* BEGIN Get_Tranverse_Mercator_Parameters */ + /* + * The function Get_Transverse_Mercator_Parameters returns the current + * ellipsoid and Transverse Mercator projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at the origin of the (output) + * projection + * Central_Meridian : Longitude in radians at the center of the (output) + * projection + * False_Easting : Easting/X at the center of the projection (output) + * False_Northing : Northing/Y at the center of the projection (output) + * Scale_Factor : Projection scale factor (output) + */ + + *a = TranMerc_a; + *f = TranMerc_f; + *Origin_Latitude = TranMerc_Origin_Lat; + *Central_Meridian = TranMerc_Origin_Long; + *False_Easting = TranMerc_False_Easting; + *False_Northing = TranMerc_False_Northing; + *Scale_Factor = TranMerc_Scale_Factor; + return; +} /* END OF Get_Tranverse_Mercator_Parameters */ + + + +long Convert_Geodetic_To_Transverse_Mercator (double Latitude, + double Longitude, + double *Easting, + double *Northing) + +{ /* BEGIN Convert_Geodetic_To_Transverse_Mercator */ + + /* + * The function Convert_Geodetic_To_Transverse_Mercator converts geodetic + * (latitude and longitude) coordinates to Transverse Mercator projection + * (easting and northing) coordinates, according to the current ellipsoid + * and Transverse Mercator projection coordinates. If any errors occur, the + * error code(s) are returned by the function, otherwise TRANMERC_NO_ERROR is + * returned. + * + * Latitude : Latitude in radians (input) + * Longitude : Longitude in radians (input) + * Easting : Easting/X in meters (output) + * Northing : Northing/Y in meters (output) + */ + + double c; /* Cosine of latitude */ + double c2; + double c3; + double c5; + double c7; + double dlam; /* Delta longitude - Difference in Longitude */ + double eta; /* constant - TranMerc_ebs *c *c */ + double eta2; + double eta3; + double eta4; + double s; /* Sine of latitude */ + double sn; /* Radius of curvature in the prime vertical */ + double t; /* Tangent of latitude */ + double tan2; + double tan3; + double tan4; + double tan5; + double tan6; + double t1; /* Term in coordinate conversion formula - GP to Y */ + double t2; /* Term in coordinate conversion formula - GP to Y */ + double t3; /* Term in coordinate conversion formula - GP to Y */ + double t4; /* Term in coordinate conversion formula - GP to Y */ + double t5; /* Term in coordinate conversion formula - GP to Y */ + double t6; /* Term in coordinate conversion formula - GP to Y */ + double t7; /* Term in coordinate conversion formula - GP to Y */ + double t8; /* Term in coordinate conversion formula - GP to Y */ + double t9; /* Term in coordinate conversion formula - GP to Y */ + double tmd; /* True Meridional distance */ + double tmdo; /* True Meridional distance for latitude of origin */ + long Error_Code = TRANMERC_NO_ERROR; +/* double temp_Origin; */ +/* double temp_Long; */ +#if 0 + if ((Latitude < -MAX_LAT) || (Latitude > MAX_LAT)) + { /* Latitude out of range */ + Error_Code|= TRANMERC_LAT_ERROR; + } + if (Longitude > M_PI) + Longitude -= (TWO_PI); + if ((Longitude < (TranMerc_Origin_Long - MAX_DELTA_LONG)) + || (Longitude > (TranMerc_Origin_Long + MAX_DELTA_LONG))) + { + if (Longitude < 0) + temp_Long = Longitude + TWO_PI; + else + temp_Long = Longitude; + if (TranMerc_Origin_Long < 0) + temp_Origin = TranMerc_Origin_Long + TWO_PI; + else + temp_Origin = TranMerc_Origin_Long; + if ((temp_Long < (temp_Origin - MAX_DELTA_LONG)) + || (temp_Long > (temp_Origin + MAX_DELTA_LONG))) + Error_Code|= TRANMERC_LON_ERROR; + } +#endif + + if (!Error_Code) + { /* no errors */ + + /* + * Delta Longitude + */ + dlam = Longitude - TranMerc_Origin_Long; + + if (fabs(dlam) > (9.0 * RAD_PER_DEG)) + { /* Distortion will result if Longitude is more than 9 degrees from the Central Meridian */ + Error_Code |= TRANMERC_LON_WARNING; + } + + if (dlam > M_PI) + dlam -= (TWO_PI); + if (dlam < -M_PI) + dlam += (TWO_PI); + if (fabs(dlam) < 2.e-10) + dlam = 0.0; + + s = sin(Latitude); + c = cos(Latitude); + c2 = c * c; + c3 = c2 * c; + c5 = c3 * c2; + c7 = c5 * c2; + t = tan (Latitude); + tan2 = t * t; + tan3 = tan2 * t; + tan4 = tan3 * t; + tan5 = tan4 * t; + tan6 = tan5 * t; + eta = TranMerc_ebs * c2; + eta2 = eta * eta; + eta3 = eta2 * eta; + eta4 = eta3 * eta; + + /* radius of curvature in prime vertical */ + sn = SPHSN(Latitude); + + /* True Meridianal Distances */ + tmd = SPHTMD(Latitude); + + /* Origin */ + tmdo = SPHTMD (TranMerc_Origin_Lat); + + /* northing */ + t1 = (tmd - tmdo) * TranMerc_Scale_Factor; + t2 = sn * s * c * TranMerc_Scale_Factor/ 2.e0; + t3 = sn * s * c3 * TranMerc_Scale_Factor * (5.e0 - tan2 + 9.e0 * eta + + 4.e0 * eta2) /24.e0; + + t4 = sn * s * c5 * TranMerc_Scale_Factor * (61.e0 - 58.e0 * tan2 + + tan4 + 270.e0 * eta - 330.e0 * tan2 * eta + 445.e0 * eta2 + + 324.e0 * eta3 -680.e0 * tan2 * eta2 + 88.e0 * eta4 + -600.e0 * tan2 * eta3 - 192.e0 * tan2 * eta4) / 720.e0; + + t5 = sn * s * c7 * TranMerc_Scale_Factor * (1385.e0 - 3111.e0 * + tan2 + 543.e0 * tan4 - tan6) / 40320.e0; + + *Northing = TranMerc_False_Northing + t1 + pow(dlam,2.e0) * t2 + + pow(dlam,4.e0) * t3 + pow(dlam,6.e0) * t4 + + pow(dlam,8.e0) * t5; + + /* Easting */ + t6 = sn * c * TranMerc_Scale_Factor; + t7 = sn * c3 * TranMerc_Scale_Factor * (1.e0 - tan2 + eta ) /6.e0; + t8 = sn * c5 * TranMerc_Scale_Factor * (5.e0 - 18.e0 * tan2 + tan4 + + 14.e0 * eta - 58.e0 * tan2 * eta + 13.e0 * eta2 + 4.e0 * eta3 + - 64.e0 * tan2 * eta2 - 24.e0 * tan2 * eta3 )/ 120.e0; + t9 = sn * c7 * TranMerc_Scale_Factor * ( 61.e0 - 479.e0 * tan2 + + 179.e0 * tan4 - tan6 ) /5040.e0; + + *Easting = TranMerc_False_Easting + dlam * t6 + pow(dlam,3.e0) * t7 + + pow(dlam,5.e0) * t8 + pow(dlam,7.e0) * t9; + } + return (Error_Code); +} /* END OF Convert_Geodetic_To_Transverse_Mercator */ + + +long Convert_Transverse_Mercator_To_Geodetic ( + double Easting, + double Northing, + double *Latitude, + double *Longitude) +{ /* BEGIN Convert_Transverse_Mercator_To_Geodetic */ + + /* + * The function Convert_Transverse_Mercator_To_Geodetic converts Transverse + * Mercator projection (easting and northing) coordinates to geodetic + * (latitude and longitude) coordinates, according to the current ellipsoid + * and Transverse Mercator projection parameters. If any errors occur, the + * error code(s) are returned by the function, otherwise TRANMERC_NO_ERROR is + * returned. + * + * Easting : Easting/X in meters (input) + * Northing : Northing/Y in meters (input) + * Latitude : Latitude in radians (output) + * Longitude : Longitude in radians (output) + */ + + double c; /* Cosine of latitude */ + double de; /* Delta easting - Difference in Easting (Easting-Fe) */ + double dlam; /* Delta longitude - Difference in Longitude */ + double eta; /* constant - TranMerc_ebs *c *c */ + double eta2; + double eta3; + double eta4; + double ftphi; /* Footpoint latitude */ + int i; /* Loop iterator */ + double s; /* Sine of latitude */ + double sn; /* Radius of curvature in the prime vertical */ + double sr; /* Radius of curvature in the meridian */ + double t; /* Tangent of latitude */ + double tan2; + double tan4; + double t10; /* Term in coordinate conversion formula - GP to Y */ + double t11; /* Term in coordinate conversion formula - GP to Y */ + double t12; /* Term in coordinate conversion formula - GP to Y */ + double t13; /* Term in coordinate conversion formula - GP to Y */ + double t14; /* Term in coordinate conversion formula - GP to Y */ + double t15; /* Term in coordinate conversion formula - GP to Y */ + double t16; /* Term in coordinate conversion formula - GP to Y */ + double t17; /* Term in coordinate conversion formula - GP to Y */ + double tmd; /* True Meridional distance */ + double tmdo; /* True Meridional distance for latitude of origin */ + long Error_Code = TRANMERC_NO_ERROR; + +#if 0 + if ((Easting < (TranMerc_False_Easting - TranMerc_Delta_Easting)) + ||(Easting > (TranMerc_False_Easting + TranMerc_Delta_Easting))) + { /* Easting out of range */ + Error_Code |= TRANMERC_EASTING_ERROR; + } + if ((Northing < (TranMerc_False_Northing - TranMerc_Delta_Northing)) + || (Northing > (TranMerc_False_Northing + TranMerc_Delta_Northing))) + { /* Northing out of range */ + Error_Code |= TRANMERC_NORTHING_ERROR; + } +#endif + + if (!Error_Code) + { + /* True Meridional Distances for latitude of origin */ + tmdo = SPHTMD(TranMerc_Origin_Lat); + + /* Origin */ + tmd = tmdo + (Northing - TranMerc_False_Northing) / TranMerc_Scale_Factor; + + /* First Estimate */ + sr = SPHSR(0.e0); + ftphi = tmd/sr; + + for (i = 0; i < 5 ; i++) + { + t10 = SPHTMD (ftphi); + sr = SPHSR(ftphi); + ftphi = ftphi + (tmd - t10) / sr; + } + + /* Radius of Curvature in the meridian */ + sr = SPHSR(ftphi); + + /* Radius of Curvature in the meridian */ + sn = SPHSN(ftphi); + + /* Sine Cosine terms */ + s = sin(ftphi); + c = cos(ftphi); + + /* Tangent Value */ + t = tan(ftphi); + tan2 = t * t; + tan4 = tan2 * tan2; + eta = TranMerc_ebs * pow(c,2); + eta2 = eta * eta; + eta3 = eta2 * eta; + eta4 = eta3 * eta; + de = Easting - TranMerc_False_Easting; + if (fabs(de) < 0.0001) + de = 0.0; + + /* Latitude */ + t10 = t / (2.e0 * sr * sn * pow(TranMerc_Scale_Factor, 2)); + t11 = t * (5.e0 + 3.e0 * tan2 + eta - 4.e0 * pow(eta,2) + - 9.e0 * tan2 * eta) / (24.e0 * sr * pow(sn,3) + * pow(TranMerc_Scale_Factor,4)); + t12 = t * (61.e0 + 90.e0 * tan2 + 46.e0 * eta + 45.E0 * tan4 + - 252.e0 * tan2 * eta - 3.e0 * eta2 + 100.e0 + * eta3 - 66.e0 * tan2 * eta2 - 90.e0 * tan4 + * eta + 88.e0 * eta4 + 225.e0 * tan4 * eta2 + + 84.e0 * tan2* eta3 - 192.e0 * tan2 * eta4) + / ( 720.e0 * sr * pow(sn,5) * pow(TranMerc_Scale_Factor, 6) ); + t13 = t * ( 1385.e0 + 3633.e0 * tan2 + 4095.e0 * tan4 + 1575.e0 + * pow(t,6))/ (40320.e0 * sr * pow(sn,7) * pow(TranMerc_Scale_Factor,8)); + *Latitude = ftphi - pow(de,2) * t10 + pow(de,4) * t11 - pow(de,6) * t12 + + pow(de,8) * t13; + + t14 = 1.e0 / (sn * c * TranMerc_Scale_Factor); + + t15 = (1.e0 + 2.e0 * tan2 + eta) / (6.e0 * pow(sn,3) * c * + pow(TranMerc_Scale_Factor,3)); + + t16 = (5.e0 + 6.e0 * eta + 28.e0 * tan2 - 3.e0 * eta2 + + 8.e0 * tan2 * eta + 24.e0 * tan4 - 4.e0 + * eta3 + 4.e0 * tan2 * eta2 + 24.e0 + * tan2 * eta3) / (120.e0 * pow(sn,5) * c + * pow(TranMerc_Scale_Factor,5)); + + t17 = (61.e0 + 662.e0 * tan2 + 1320.e0 * tan4 + 720.e0 + * pow(t,6)) / (5040.e0 * pow(sn,7) * c + * pow(TranMerc_Scale_Factor,7)); + + /* Difference in Longitude */ + dlam = de * t14 - pow(de,3) * t15 + pow(de,5) * t16 - pow(de,7) * t17; + + /* Longitude */ + (*Longitude) = TranMerc_Origin_Long + dlam; + while (*Latitude > (90.0 * RAD_PER_DEG)) + { + *Latitude = M_PI - *Latitude; + *Longitude += M_PI; + if (*Longitude > M_PI) + *Longitude -= (TWO_PI); + } + + while (*Latitude < (-90.0 * RAD_PER_DEG)) + { + *Latitude = - (*Latitude + M_PI); + *Longitude += M_PI; + if (*Longitude > M_PI) + *Longitude -= (TWO_PI); + } + if (*Longitude > (TWO_PI)) + *Longitude -= (TWO_PI); + if (*Longitude < -M_PI) + *Longitude += (TWO_PI); + + if (fabs(dlam) > (9.0 * RAD_PER_DEG)) + { /* Distortion will result if Longitude is more than 9 degrees from the Central Meridian */ + Error_Code |= TRANMERC_LON_WARNING; + } + } + return (Error_Code); +} /* END OF Convert_Transverse_Mercator_To_Geodetic */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimTranmerc.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimTranmerc.h new file mode 100644 index 0000000000..93e9a35e22 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimTranmerc.h @@ -0,0 +1,209 @@ +#ifndef TRANMERC_H +#define TRANMERC_H + +/***************************************************************************/ +/* RSC IDENTIFIER: TRANSVERSE MERCATOR + * + * ABSTRACT + * + * This component provides conversions between Geodetic coordinates + * (latitude and longitude) and Transverse Mercator projection coordinates + * (easting and northing). + * + * ERROR HANDLING + * + * This component checks parameters for valid values. If an invalid value + * is found the error code is combined with the current error code using + * the bitwise or. This combining allows multiple error codes to be + * returned. The possible error codes are: + * + * TRANMERC_NO_ERROR : No errors occurred in function + * TRANMERC_LAT_ERROR : Latitude outside of valid range + * (-90 to 90 degrees) + * TRANMERC_LON_ERROR : Longitude outside of valid range + * (-180 to 360 degrees, and within + * +/-90 of Central Meridian) + * TRANMERC_EASTING_ERROR : Easting outside of valid range + * (depending on ellipsoid and + * projection parameters) + * TRANMERC_NORTHING_ERROR : Northing outside of valid range + * (depending on ellipsoid and + * projection parameters) + * TRANMERC_ORIGIN_LAT_ERROR : Origin latitude outside of valid range + * (-90 to 90 degrees) + * TRANMERC_CENT_MER_ERROR : Central meridian outside of valid range + * (-180 to 360 degrees) + * TRANMERC_A_ERROR : Semi-major axis less than or equal to zero + * TRANMERC_INV_F_ERROR : Inverse flattening outside of valid range + * (250 to 350) + * TRANMERC_SCALE_FACTOR_ERROR : Scale factor outside of valid + * range (0.3 to 3.0) + * TM_LON_WARNING : Distortion will result if longitude is more + * than 9 degrees from the Central Meridian + * + * REUSE NOTES + * + * TRANSVERSE MERCATOR is intended for reuse by any application that + * performs a Transverse Mercator projection or its inverse. + * + * REFERENCES + * + * Further information on TRANSVERSE MERCATOR can be found in the + * Reuse Manual. + * + * TRANSVERSE MERCATOR originated from : + * U.S. Army Topographic Engineering Center + * Geospatial Information Division + * 7701 Telegraph Road + * Alexandria, VA 22310-3864 + * + * LICENSES + * + * None apply to this component. + * + * RESTRICTIONS + * + * TRANSVERSE MERCATOR has no restrictions. + * + * ENVIRONMENT + * + * TRANSVERSE MERCATOR was tested and certified in the following + * environments: + * + * 1. Solaris 2.5 with GCC, version 2.8.1 + * 2. Windows 95 with MS Visual C++, version 6 + * + * MODIFICATIONS + * + * Date Description + * ---- ----------- + * 10-02-97 Original Code + * 03-02-97 Re-engineered Code + * + */ + + +/***************************************************************************/ +/* + * DEFINES + */ + +#define TRANMERC_NO_ERROR 0x0000 +#define TRANMERC_LAT_ERROR 0x0001 +#define TRANMERC_LON_ERROR 0x0002 +#define TRANMERC_EASTING_ERROR 0x0004 +#define TRANMERC_NORTHING_ERROR 0x0008 +#define TRANMERC_ORIGIN_LAT_ERROR 0x0010 +#define TRANMERC_CENT_MER_ERROR 0x0020 +#define TRANMERC_A_ERROR 0x0040 +#define TRANMERC_INV_F_ERROR 0x0080 +#define TRANMERC_SCALE_FACTOR_ERROR 0x0100 +#define TRANMERC_LON_WARNING 0x0200 + + +/***************************************************************************/ +/* + * FUNCTION PROTOTYPES + * for TRANMERC.C + */ + +/* ensure proper linkage to c++ programs */ +#ifdef __cplusplus +extern "C" { +#endif + + + long Set_Transverse_Mercator_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing, + double Scale_Factor); +/* + * The function Set_Tranverse_Mercator_Parameters receives the ellipsoid + * parameters and Tranverse Mercator projection parameters as inputs, and + * sets the corresponding state variables. If any errors occur, the error + * code(s) are returned by the function, otherwise TRANMERC_NO_ERROR is + * returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at the origin of the (input) + * projection + * Central_Meridian : Longitude in radians at the center of the (input) + * projection + * False_Easting : Easting/X at the center of the projection (input) + * False_Northing : Northing/Y at the center of the projection (input) + * Scale_Factor : Projection scale factor (input) + */ + + + void Get_Transverse_Mercator_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *False_Easting, + double *False_Northing, + double *Scale_Factor); +/* + * The function Get_Transverse_Mercator_Parameters returns the current + * ellipsoid and Transverse Mercator projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at the origin of the (output) + * projection + * Central_Meridian : Longitude in radians at the center of the (output) + * projection + * False_Easting : Easting/X at the center of the projection (output) + * False_Northing : Northing/Y at the center of the projection (output) + * Scale_Factor : Projection scale factor (output) + */ + + + long Convert_Geodetic_To_Transverse_Mercator (double Latitude, + double Longitude, + double *Easting, + double *Northing); + +/* + * The function Convert_Geodetic_To_Transverse_Mercator converts geodetic + * (latitude and longitude) coordinates to Transverse Mercator projection + * (easting and northing) coordinates, according to the current ellipsoid + * and Transverse Mercator projection coordinates. If any errors occur, the + * error code(s) are returned by the function, otherwise TRANMERC_NO_ERROR is + * returned. + * + * Latitude : Latitude in radians (input) + * Longitude : Longitude in radians (input) + * Easting : Easting/X in meters (output) + * Northing : Northing/Y in meters (output) + */ + + + long Convert_Transverse_Mercator_To_Geodetic (double Easting, + double Northing, + double *Latitude, + double *Longitude); + +/* + * The function Convert_Transverse_Mercator_To_Geodetic converts Transverse + * Mercator projection (easting and northing) coordinates to geodetic + * (latitude and longitude) coordinates, according to the current ellipsoid + * and Transverse Mercator projection parameters. If any errors occur, the + * error code(s) are returned by the function, otherwise TRANMERC_NO_ERROR is + * returned. + * + * Easting : Easting/X in meters (input) + * Northing : Northing/Y in meters (input) + * Latitude : Latitude in radians (output) + * Longitude : Longitude in radians (output) + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* TRANMERC_H */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimTransCylEquAreaProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimTransCylEquAreaProjection.cpp new file mode 100644 index 0000000000..90673bb2db --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimTransCylEquAreaProjection.cpp @@ -0,0 +1,606 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Transverse Cylindrical Equal Area +// projection code. +//******************************************************************* +// $Id: ossimTransCylEquAreaProjection.cpp,v 1.11 2004/01/08 21:49:22 jlargent Exp $ + +#include <math.h> +#include "ossimTransCylEquAreaProjection.h" +#include "base/common/ossimKeywordNames.h" + +RTTI_DEF1(ossimTransCylEquAreaProjection, "ossimTransCylEquAreaProjection", ossimMapProjection) +/***************************************************************************/ +/* + * DEFINES + */ + +#ifndef PI_OVER_2 +# define PI_OVER_2 ( M_PI / 2.0) +#endif +#ifndef TWO_PI +# define TWO_PI (2.0 * M_PI) +#endif + +#define TCEA_Q(sinlat,x) (One_MINUS_es2*(sinlat/(1.0-es2*sinlat*sinlat)-One_OVER_2es*log((1-x)/(1+x)))) +#define TCEA_COEFF_TIMES_SIN(coeff,x,latit) (coeff * sin(x*latit)) +#define TCEA_M(c0lat,c1lat,c2lat,c3lat) (Tcea_a * (c0lat - c1lat + c2lat - c3lat)) +#define TCEA_L(Beta,c0lat,c1lat,c2lat) (Beta + c0lat + c1lat + c2lat) +#define MIN_SCALE_FACTOR 0.3 +#define MAX_SCALE_FACTOR 3.0 + +#define TCEA_NO_ERROR 0x0000 +#define TCEA_LAT_ERROR 0x0001 +#define TCEA_LON_ERROR 0x0002 +#define TCEA_EASTING_ERROR 0x0004 +#define TCEA_NORTHING_ERROR 0x0008 +#define TCEA_ORIGIN_LAT_ERROR 0x0010 +#define TCEA_CENT_MER_ERROR 0x0020 +#define TCEA_A_ERROR 0x0040 +#define TCEA_INV_F_ERROR 0x0080 +#define TCEA_SCALE_FACTOR_ERROR 0x0100 +#define TCEA_LON_WARNING 0x0200 + +ossimTransCylEquAreaProjection::ossimTransCylEquAreaProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + :ossimMapProjection(ellipsoid, origin) +{ + setDefaults(); + update(); +} + +ossimTransCylEquAreaProjection::ossimTransCylEquAreaProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double falseEasting, + double falseNorthing, + double scaleFactor) + :ossimMapProjection(ellipsoid, origin) +{ + Tcea_False_Easting = falseEasting; + Tcea_False_Northing = falseNorthing; + Tcea_Scale_Factor = scaleFactor; + Tcea_Min_Easting = -6398628.0; + Tcea_Max_Easting = 6398628.0; + Tcea_Min_Northing = -20003931.0; + Tcea_Max_Northing = 20003931.0; + + update(); +} + +void ossimTransCylEquAreaProjection::setFalseEasting(double falseEasting) +{ + Tcea_False_Easting = falseEasting; + + update(); +} + + +void ossimTransCylEquAreaProjection::setFalseNorthing(double falseNorthing) +{ + Tcea_False_Northing = falseNorthing; + + update(); +} + +void ossimTransCylEquAreaProjection::setFalseEastingNorthing(double falseEasting, + double falseNorthing) +{ + Tcea_False_Easting = falseEasting; + Tcea_False_Northing = falseNorthing; + + update(); +} + +void ossimTransCylEquAreaProjection::setScaleFactor(double scaleFactor) +{ + Tcea_Scale_Factor = scaleFactor; + + update(); +} + +void ossimTransCylEquAreaProjection::setParameters(double falseEasting, + double falseNorthing, + double scaleFactor) +{ + Tcea_False_Easting = falseEasting; + Tcea_False_Northing = falseNorthing; + Tcea_Scale_Factor = scaleFactor; + + update(); +} + +void ossimTransCylEquAreaProjection::setDefaults() +{ + Tcea_Scale_Factor = 1.0; + Tcea_False_Easting = 0.0; + Tcea_False_Northing = 0.0; + Tcea_Min_Easting = -6398628.0; + Tcea_Max_Easting = 6398628.0; + Tcea_Min_Northing = -20003931.0; + Tcea_Max_Northing = 20003931.0; +} + +void ossimTransCylEquAreaProjection::update() +{ + Set_Trans_Cyl_Eq_Area_Parameters(theEllipsoid.getA(), + theEllipsoid.getFlattening(), + theOrigin.latr(), + theOrigin.lonr(), + Tcea_False_Easting, + Tcea_False_Northing, + Tcea_Scale_Factor); + ossimMapProjection::update(); +} + + +ossimGpt ossimTransCylEquAreaProjection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat = 0.0; + double lon = 0.0; + + Convert_Trans_Cyl_Eq_Area_To_Geodetic(eastingNorthing.x, + eastingNorthing.y, + &lat, + &lon); + + return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum); +} + +ossimDpt ossimTransCylEquAreaProjection::forward(const ossimGpt &latLon)const +{ + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + Convert_Geodetic_To_Trans_Cyl_Eq_Area(gpt.latr(), + gpt.lonr(), + &easting, + &northing); + + return ossimDpt(easting, northing); +} + +bool ossimTransCylEquAreaProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const +{ + kwl.add(prefix, + ossimKeywordNames::FALSE_EASTING_KW, + Tcea_False_Easting, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_NORTHING_KW, + Tcea_False_Northing, + true); + + kwl.add(prefix, + ossimKeywordNames::SCALE_FACTOR_KW, + Tcea_Scale_Factor, + true); + + return ossimMapProjection::saveState(kwl, prefix); +} + +bool ossimTransCylEquAreaProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + bool flag = ossimMapProjection::loadState(kwl, prefix); + const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + const char* falseEasting = kwl.find(prefix, ossimKeywordNames::FALSE_EASTING_KW); + const char* falseNorthing = kwl.find(prefix, ossimKeywordNames::FALSE_NORTHING_KW); + const char* scaleFactor = kwl.find(prefix, ossimKeywordNames::SCALE_FACTOR_KW); + + setDefaults(); + if(ossimString(type) == STATIC_TYPE_NAME(ossimTransCylEquAreaProjection)) + { + if(falseEasting) + { + Tcea_False_Easting = ossimString(falseEasting).toDouble(); + } + if(falseNorthing) + { + Tcea_False_Northing = ossimString(falseNorthing).toDouble(); + } + if(scaleFactor) + { + Tcea_Scale_Factor = ossimString(scaleFactor).toDouble(); + } + } + + update(); + + return flag; +} + +long ossimTransCylEquAreaProjection::Set_Trans_Cyl_Eq_Area_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing, + double Scale_Factor) +{ /* BEGIN Set_Trans_Cyl_Eq_Area_Parameters */ +/* + * The function Set_Trans_Cyl_Eq_Area_Parameters receives the ellipsoid parameters and + * Transverse Cylindrical Equal Area projection parameters as inputs, and sets the + * corresponding state variables. If any errors occur, the error code(s) are returned + * by the function, otherwise TCEA_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at which the (input) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + * Scale_Factor : Multiplier which reduces distances in the + * projection to the actual distance on the + * ellipsoid (input) + */ + + double sin_lat_90 = sin(PI_OVER_2); + double x, j, three_es4; + double Sqrt_One_MINUS_es2; + double e1, e2, e3, e4; + double lat, sin2lat, sin4lat, sin6lat; + double temp, temp_northing; +// double inv_f = 1 / f; + long Error_Code = TCEA_NO_ERROR; + +// if (a <= 0.0) +// { /* Semi-major axis must be greater than zero */ +// Error_Code |= TCEA_A_ERROR; +// } +// if ((inv_f < 250) || (inv_f > 350)) +// { /* Inverse flattening must be between 250 and 350 */ +// Error_Code |= TCEA_INV_F_ERROR; +// } +// if ((Origin_Latitude < -PI_OVER_2) || (Origin_Latitude > PI_OVER_2)) +// { /* origin latitude out of range */ +// Error_Code |= TCEA_ORIGIN_LAT_ERROR; +// } +// if ((Central_Meridian < -M_PI) || (Central_Meridian > TWO_PI)) +// { /* origin longitude out of range */ +// Error_Code |= TCEA_CENT_MER_ERROR; +// } +// if ((Scale_Factor < MIN_SCALE_FACTOR) || (Scale_Factor > MAX_SCALE_FACTOR)) +// { +// Error_Code |= TCEA_SCALE_FACTOR_ERROR; +// } + + if (!Error_Code) + { /* no errors */ + Tcea_a = a; + Tcea_f = f; + Tcea_Origin_Lat = Origin_Latitude; + if (Central_Meridian > M_PI) + Central_Meridian -= TWO_PI; + Tcea_Origin_Long = Central_Meridian; + Tcea_False_Northing = False_Northing; + Tcea_False_Easting = False_Easting; + Tcea_Scale_Factor = Scale_Factor; + + es2 = 2 * Tcea_f - Tcea_f * Tcea_f; + es = sqrt(es2); + One_MINUS_es2 = 1.0 - es2; + Sqrt_One_MINUS_es2 = sqrt(One_MINUS_es2); + One_OVER_2es = 1.0 / (2.0 * es); + es4 = es2 * es2; + es6 = es4 * es2; + x = es * sin_lat_90; + qp = TCEA_Q(sin_lat_90,x); + + a0 = es2 / 3.0 + 31.0 * es4 / 180.0 + 517.0 * es6 / 5040.0; + a1 = 23.0 * es4 / 360.0 + 251.0 * es6 / 3780.0; + a2 = 761.0 * es6 / 45360.0; + + e1 = (1.0 - Sqrt_One_MINUS_es2) / (1.0 + Sqrt_One_MINUS_es2); + e2 = e1 * e1; + e3 = e2 * e1; + e4 = e3 * e1; + b0 = 3.0 * e1 / 2.0 - 27.0 * e3 / 32.0; + b1 = 21.0 * e2 / 16.0 - 55.0 * e4 / 32.0; + b2 = 151.0 * e3 / 96.0; + b3 = 1097.0 * e4 / 512.0; + + j = 45.0 * es6 / 1024.0; + three_es4 = 3.0 * es4; + c0 = 1.0 - es2 / 4.0 - three_es4 / 64.0 - 5.0 * es6 / 256.0; + c1 = 3.0 * es2 / 8.0 + three_es4 / 32.0 + j; + c2 = 15.0 * es4 / 256.0 + j; + c3 = 35.0 * es6 / 3072.0; + lat = c0 * Tcea_Origin_Lat; + sin2lat = TCEA_COEFF_TIMES_SIN(c1, 2.0, Tcea_Origin_Lat); + sin4lat = TCEA_COEFF_TIMES_SIN(c2, 4.0, Tcea_Origin_Lat); + sin6lat = TCEA_COEFF_TIMES_SIN(c3, 6.0, Tcea_Origin_Lat); + M0 = TCEA_M(lat, sin2lat, sin4lat, sin6lat); + Convert_Geodetic_To_Trans_Cyl_Eq_Area(PI_OVER_2, M_PI, &temp, &temp_northing); + if (temp_northing > 0) + { + Tcea_Min_Northing = temp_northing - 20003931.458986; + Tcea_Max_Northing = temp_northing; + } + else if (temp_northing < 0) + { + Tcea_Max_Northing = temp_northing + 20003931.458986; + Tcea_Min_Northing = temp_northing; + } + } /* END OF if(!Error_Code) */ + return (Error_Code); +} /* END OF Set_Trans_Cyl_Eq_Area_Parameters */ + +void ossimTransCylEquAreaProjection::Get_Trans_Cyl_Eq_Area_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *False_Easting, + double *False_Northing, + double *Scale_Factor)const +{ /* BEGIN Get_Trans_Cyl_Eq_Area_Parameters */ +/* + * The function Get_Trans_Cyl_Eq_Area_Parameters returns the current ellipsoid + * parameters, Transverse Cylindrical Equal Area projection parameters, and scale factor. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at which the (output) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + * Scale_Factor : Multiplier which reduces distances in the + * projection to the actual distance on the + * ellipsoid (output) + */ + + *a = Tcea_a; + *f = Tcea_f; + *Origin_Latitude = Tcea_Origin_Lat; + *Central_Meridian = Tcea_Origin_Long; + *False_Easting = Tcea_False_Easting; + *False_Northing = Tcea_False_Northing; + *Scale_Factor = Tcea_Scale_Factor; + + return; +} /* END OF Get_Trans_Cyl_Eq_Area_Parameters */ + + +long ossimTransCylEquAreaProjection::Convert_Geodetic_To_Trans_Cyl_Eq_Area (double Latitude, + double Longitude, + double *Easting, + double *Northing)const +{ /* BEGIN Convert_Geodetic_To_Trans_Cyl_Eq_Area */ +/* + * The function Convert_Geodetic_To_Trans_Cyl_Eq_Area converts geodetic (latitude and + * longitude) coordinates to Transverse Cylindrical Equal Area projection (easting and + * northing) coordinates, according to the current ellipsoid and Transverse Cylindrical + * Equal Area projection parameters. If any errors occur, the error code(s) are returned + * by the function, otherwise TCEA_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + + double x; + double dlam; /* Longitude - Central Meridan */ + double sin_lat = sin(Latitude); + double qq, qq_OVER_qp; + double beta, betac; + double sin2betac, sin4betac, sin6betac; + double PHIc; + double phi, sin2phi, sin4phi, sin6phi; + double sinPHIc; + double Mc; + long Error_Code = TCEA_NO_ERROR; + +// if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2)) +// { /* Latitude out of range */ +// Error_Code |= TCEA_LAT_ERROR; +// } +// if ((Longitude < -M_PI) || (Longitude > TWO_PI)) +// { /* Longitude out of range */ +// Error_Code |= TCEA_LON_ERROR; +// } + if (!Error_Code) + { /* no errors */ + dlam = Longitude - Tcea_Origin_Long; + if (fabs(dlam) >= (M_PI / 2.0)) + { /* Distortion will result if Longitude is more than 90 degrees from the Central Meridian */ + Error_Code |= TCEA_LON_WARNING; + } + + if (dlam > M_PI) + { + dlam -= TWO_PI; + } + if (dlam < -M_PI) + { + dlam += TWO_PI; + } + if (Latitude == PI_OVER_2) + { + qq = qp; + qq_OVER_qp = 1.0; + } + else + { + x = es * sin_lat; + qq = TCEA_Q(sin_lat, x); + qq_OVER_qp = qq / qp; + } + + + if (qq_OVER_qp > 1.0) + qq_OVER_qp = 1.0; + else if (qq_OVER_qp < -1.0) + qq_OVER_qp = -1.0; + + beta = asin(qq_OVER_qp); + betac = atan(tan(beta) / cos(dlam)); + + if ((fabs(betac) - PI_OVER_2) > 1.0e-8) + PHIc = betac; + else + { + sin2betac = TCEA_COEFF_TIMES_SIN(a0, 2.0, betac); + sin4betac = TCEA_COEFF_TIMES_SIN(a1, 4.0, betac); + sin6betac = TCEA_COEFF_TIMES_SIN(a2, 6.0, betac); + PHIc = TCEA_L(betac, sin2betac, sin4betac, sin6betac); + } + + sinPHIc = sin(PHIc); + *Easting = Tcea_a * cos(beta) * cos(PHIc) * sin(dlam) / + (Tcea_Scale_Factor * cos(betac) * sqrt(1.0 - es2 * + sinPHIc * sinPHIc)) + Tcea_False_Easting; + + phi = c0 * PHIc; + sin2phi = TCEA_COEFF_TIMES_SIN(c1, 2.0, PHIc); + sin4phi = TCEA_COEFF_TIMES_SIN(c2, 4.0, PHIc); + sin6phi = TCEA_COEFF_TIMES_SIN(c3, 6.0, PHIc); + Mc = TCEA_M(phi, sin2phi, sin4phi, sin6phi); + + *Northing = Tcea_Scale_Factor * (Mc - M0) + Tcea_False_Northing; + } + return (Error_Code); +} /* END OF Convert_Geodetic_To_Trans_Cyl_Eq_Area */ + + +long ossimTransCylEquAreaProjection::Convert_Trans_Cyl_Eq_Area_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const +{ /* BEGIN Convert_Trans_Cyl_Eq_Area_To_Geodetic */ +/* + * The function Convert_Trans_Cyl_Eq_Area_To_Geodetic converts Transverse + * Cylindrical Equal Area projection (easting and northing) coordinates + * to geodetic (latitude and longitude) coordinates, according to the + * current ellipsoid and Transverse Cylindrical Equal Area projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise TCEA_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + + double x; + double dx; /* Delta easting - Difference in easting (easting-FE) */ + double dy; /* Delta northing - Difference in northing (northing-FN) */ + double Mc; + double MUc; + double sin2mu, sin4mu, sin6mu, sin8mu; + double PHIc; + double Qc; + double sin_lat; + double beta, betac, beta_prime; + double sin2beta, sin4beta, sin6beta; + double cosbetac; + double Qc_OVER_qp; + double temp; + + long Error_Code = TCEA_NO_ERROR; + +// if ((Easting < (Tcea_False_Easting + Tcea_Min_Easting)) +// || (Easting > (Tcea_False_Easting + Tcea_Max_Easting))) +// { /* Easting out of range */ +// Error_Code |= TCEA_EASTING_ERROR; +// } +// if ((Northing < (Tcea_False_Northing + Tcea_Min_Northing)) +// || (Northing > (Tcea_False_Northing + Tcea_Max_Northing))) +// { /* Northing out of range */ +// Error_Code |= TCEA_NORTHING_ERROR; +// } + if (!Error_Code) + { /* no errors */ + dy = Northing - Tcea_False_Northing; + dx = Easting - Tcea_False_Easting; + Mc = M0 + dy / Tcea_Scale_Factor; + MUc = Mc / (Tcea_a * c0); + + sin2mu = TCEA_COEFF_TIMES_SIN(b0, 2.0, MUc); + sin4mu = TCEA_COEFF_TIMES_SIN(b1, 4.0, MUc); + sin6mu = TCEA_COEFF_TIMES_SIN(b2, 6.0, MUc); + sin8mu = TCEA_COEFF_TIMES_SIN(b3, 8.0, MUc); + PHIc = MUc + sin2mu + sin4mu + sin6mu + sin8mu; + + sin_lat = sin(PHIc); + x = es * sin_lat; + Qc = TCEA_Q(sin_lat, x); + Qc_OVER_qp = Qc / qp; + + if (Qc_OVER_qp < -1.0) + Qc_OVER_qp = -1.0; + else if (Qc_OVER_qp > 1.0) + Qc_OVER_qp = 1.0; + + betac = asin(Qc_OVER_qp); + cosbetac = cos(betac); + temp = Tcea_Scale_Factor * dx * cosbetac * sqrt(1.0 - + es2 * sin_lat * sin_lat) / (Tcea_a * cos(PHIc)); + if (temp > 1.0) + temp = 1.0; + else if (temp < -1.0) + temp = -1.0; + beta_prime = -asin(temp); + beta = asin(cos(beta_prime) * sin(betac)); + + sin2beta = TCEA_COEFF_TIMES_SIN(a0, 2.0, beta); + sin4beta = TCEA_COEFF_TIMES_SIN(a1, 4.0, beta); + sin6beta = TCEA_COEFF_TIMES_SIN(a2, 6.0, beta); + *Latitude = TCEA_L(beta, sin2beta, sin4beta, sin6beta); + + *Longitude = Tcea_Origin_Long - atan(tan(beta_prime) / cosbetac); + +// if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */ +// *Latitude = PI_OVER_2; +// else if (*Latitude < -PI_OVER_2) +// *Latitude = -PI_OVER_2; + +// if (*Longitude > M_PI) +// *Longitude -= TWO_PI; +// if (*Longitude < -M_PI) +// *Longitude += TWO_PI; + +// if (*Longitude > M_PI) /* force distorted values to 180, -180 degrees */ +// *Longitude = M_PI; +// else if (*Longitude < -M_PI) +// *Longitude = -M_PI; + } + return (Error_Code); +} /* END OF Convert_Trans_Cyl_Eq_Area_To_Geodetic */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimTransCylEquAreaProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimTransCylEquAreaProjection.h new file mode 100644 index 0000000000..3468a74ca2 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimTransCylEquAreaProjection.h @@ -0,0 +1,230 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Transverse Cylindrical Equal Area +// projection code. +//******************************************************************* +// $Id: ossimTransCylEquAreaProjection.h,v 1.5 2005/09/09 19:23:58 gpotts Exp $ +#ifndef ossimTransCylEquAreaProjection_HEADER +#define ossimTransCylEquAreaProjection_HEADER + +#include "ossimMapProjection.h" + +class ossimTransCylEquAreaProjection : public ossimMapProjection +{ +public: + ossimTransCylEquAreaProjection(const ossimEllipsoid& ellipsoid = ossimEllipsoid(6378137, 6356752.3142), + const ossimGpt& origin = ossimGpt()); + ossimTransCylEquAreaProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double falseEasting, + double falseNorthing, + double scaleFactor); + + ~ossimTransCylEquAreaProjection(){} + + virtual ossimObject *dup()const{return new ossimTransCylEquAreaProjection(*this);} + + virtual ossimGpt inverse(const ossimDpt &eastingNorthing)const; + virtual ossimDpt forward(const ossimGpt &latLon)const; + virtual void update(); + + /*! + * SetFalseEasting. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEasting(double falseEasting); + + /*! + * SetFalseNorthing. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseNorthing(double falseNorthing); + + /* + * Set's scale and then update. + */ + void setScaleFactor(double scaleFactor); + /*! + * Sets both false easting and northing values. The values are + * expected to be in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEastingNorthing(double falseEasting, double falseNorthing); + + void setParameters(double falseEasting, + double falseNorthing, + double scaleFactor); + + void setDefaults(); + + double getFalseEasting()const{return Tcea_False_Easting;} + double getFalseNorthing()const{return Tcea_False_Northing;} + double getScaleFactor()const{return Tcea_Scale_Factor;} + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +private: + + mutable double Tcea_a; /* Semi-major axis of ellipsoid in meters */ + mutable double Tcea_f; /* Flattening of ellipsoid */ + mutable double es2; /* Eccentricity (0.08181919084262188000) squared */ + mutable double es4; /* es2 * es2 */ + mutable double es6; /* es4 * es2 */ + mutable double es; /* sqrt(es2) */ + mutable double M0; + mutable double qp; + mutable double One_MINUS_es2; /* 1.0 - es2 */ + mutable double One_OVER_2es; /* 1.0 / (2.0 * es) */ + mutable double a0; /* es2 / 3.0 + 31.0 * es4 / 180.0 + 517.0 * es6 / 5040.0 */ + mutable double a1; /* 23.0 * es4 / 360.0 + 251.0 * es6 / 3780.0 */ + mutable double a2; /* 761.0 * es6 / 45360.0 */ + mutable double b0; /* 3.0 * e1 / 2.0 - 27.0 * e3 / 32.0 */ + mutable double b1; /* 21.0 * e2 / 16.0 - 55.0 * e4 / 32.0 */ + mutable double b2; /* 151.0 * e3 / 96.0 */ + mutable double b3; /* 1097.0 * e4 / 512.0 */ + mutable double c0;/* 1.0 - es2 / 4.0 - 3.0 * es4 / 64.0 - 5.0 * es6 / 256.0 */ + mutable double c1;/* 3.0 * es2 / 8.0 + 3.0 * es4 / 32.0 + 45.0 * es6 / 1024.0 */ + mutable double c2; /* 15.0 * es4 / 256.0 + 45.0 * es6 / 1024.0 */ + mutable double c3; /* 35.0 * es6 / 3072.0 */ + +/* Transverse Cylindrical Equal Area projection Parameters */ + mutable double Tcea_Origin_Lat; /* Latitude of origin in radians */ + mutable double Tcea_Origin_Long; /* Longitude of origin in radians */ + mutable double Tcea_False_Northing; /* False northing in meters */ + mutable double Tcea_False_Easting; /* False easting in meters */ + mutable double Tcea_Scale_Factor; /* Scale factor */ + +/* Maximum variance for easting and northing values for WGS 84. + */ + mutable double Tcea_Min_Easting; + mutable double Tcea_Max_Easting; + mutable double Tcea_Min_Northing; + mutable double Tcea_Max_Northing; + +/* + * The function Set_Trans_Cyl_Eq_Area_Parameters receives the ellipsoid parameters and + * Transverse Cylindrical Equal Area projcetion parameters as inputs, and sets the corresponding + * state variables. If any errors occur, the error code(s) are returned by the function, + * otherwise TCEA_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at which the (input) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + * Scale_Factor : Multiplier which reduces distances in the + * projection to the actual distance on the + * ellipsoid (input) + */ + long Set_Trans_Cyl_Eq_Area_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing, + double Scale_Factor); + + +/*! + * The function Get_Trans_Cyl_Eq_Area_Parameters returns the current ellipsoid + * parameters, Transverse Cylindrical Equal Area projection parameters, and scale factor. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at which the (output) + * point scale factor is 1.0 + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + * Scale_Factor : Multiplier which reduces distances in the + * projection to the actual distance on the + * ellipsoid (output) + */ + void Get_Trans_Cyl_Eq_Area_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *False_Easting, + double *False_Northing, + double *Scale_Factor)const; + + +/*! + * The function Convert_Geodetic_To_Trans_Cyl_Eq_Area converts geodetic (latitude and + * longitude) coordinates to Transverse Cylindrical Equal Area projection easting, and northing + * coordinates, according to the current ellipsoid and Transverse Cylindrical Equal Area projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise TCEA_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + long Convert_Geodetic_To_Trans_Cyl_Eq_Area (double Latitude, + double Longitude, + double *Easting, + double *Northing)const; + + +/*! + * The function Convert_Trans_Cyl_Eq_Area_To_Geodetic converts Transverse Cylindrical Equal Area + * projection easting and northing coordinates to geodetic (latitude and longitude) coordinates. + * coordinates, according to the current ellipsoid and Transverse Cylindrical Equal Area projection + * If any errors occur, the error code(s) are returned by the function, otherwise TCEA_NO_ERROR + * is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + long Convert_Trans_Cyl_Eq_Area_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimTransMercatorProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimTransMercatorProjection.cpp new file mode 100644 index 0000000000..f1b7348afe --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimTransMercatorProjection.cpp @@ -0,0 +1,743 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Transverse Mercator projection code. +//******************************************************************* +// $Id: ossimTransMercatorProjection.cpp,v 1.16 2004/06/14 17:33:59 dburken Exp $ +#include <cmath> +using namespace std; + +#include "ossimTransMercatorProjection.h" +#include "base/common/ossimKeywordNames.h" + +RTTI_DEF1(ossimTransMercatorProjection, "ossimTransMercatorProjection", ossimMapProjection) + +/******************************* DEFINES *********************************/ + +#define TRANMERC_NO_ERROR 0x0000 +#define TRANMERC_LAT_ERROR 0x0001 +#define TRANMERC_LON_ERROR 0x0002 +#define TRANMERC_EASTING_ERROR 0x0004 +#define TRANMERC_NORTHING_ERROR 0x0008 +#define TRANMERC_ORIGIN_LAT_ERROR 0x0010 +#define TRANMERC_CENT_MER_ERROR 0x0020 +#define TRANMERC_A_ERROR 0x0040 +#define TRANMERC_B_ERROR 0x0080 +#define TRANMERC_A_LESS_B_ERROR 0x0100 +#define TRANMERC_SCALE_FACTOR_ERROR 0x0200 +#define TRANMERC_LON_WARNING 0x0400 + +#define MAX_LAT ((M_PI * 90.0)/180.0) /* 90 degrees in radians */ +#define MAX_DELTA_LONG ((M_PI * 90.0)/180.0) /* 90 degrees in radians */ +#define MIN_SCALE_FACTOR 0.3 +#define MAX_SCALE_FACTOR 3.0 + +#define SPHTMD(Latitude) ((double) (TranMerc_ap * Latitude \ + - TranMerc_bp * sin(2.e0 * Latitude) + TranMerc_cp * sin(4.e0 * Latitude) \ + - TranMerc_dp * sin(6.e0 * Latitude) + TranMerc_ep * sin(8.e0 * Latitude) ) ) + +#define SPHSN(Latitude) ((double) (getA() / sqrt( 1.e0 - TranMerc_es * \ + pow(sin(Latitude), 2)))) + +#define SPHSR(Latitude) ((double) (getA() * (1.e0 - TranMerc_es) / \ + pow(DENOM(Latitude), 3))) + +#define DENOM(Latitude) ((double) (sqrt(1.e0 - TranMerc_es * pow(sin(Latitude),2)))) + +ossimTransMercatorProjection::ossimTransMercatorProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + : + ossimMapProjection(ellipsoid, origin), + TranMerc_a(6378137.0), + TranMerc_f(1.0/298.257223563), + TranMerc_es(0.0066943799901413800), + TranMerc_ebs(0.0067394967565869), + TranMerc_Origin_Lat(origin.latr()), + TranMerc_Origin_Long(origin.lonr()), + TranMerc_False_Northing(0.0), + TranMerc_False_Easting(0.0), + TranMerc_Scale_Factor(1.0), + TranMerc_ap(6367449.1458008), + TranMerc_bp(16038.508696861), + TranMerc_cp(16.832613334334), + TranMerc_dp(0.021984404273757), + TranMerc_Delta_Easting(40000000.0), + TranMerc_Delta_Northing(40000000.0) +{ + update(); +} + +ossimTransMercatorProjection::ossimTransMercatorProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double falseEasting, + double falseNorthing, + double scaleFactor) + : + ossimMapProjection(ellipsoid, origin), + TranMerc_a(6378137.0), + TranMerc_f(1.0/298.257223563), + TranMerc_es(0.0066943799901413800), + TranMerc_ebs(0.0067394967565869), + TranMerc_Origin_Lat(origin.latr()), + TranMerc_Origin_Long(origin.lonr()), + TranMerc_False_Northing(falseNorthing), + TranMerc_False_Easting(falseEasting), + TranMerc_Scale_Factor(scaleFactor), + TranMerc_ap(6367449.1458008), + TranMerc_bp(16038.508696861), + TranMerc_cp(16.832613334334), + TranMerc_dp(0.021984404273757), + TranMerc_Delta_Easting(40000000.0), + TranMerc_Delta_Northing(40000000.0) +{ + update(); +} + +void ossimTransMercatorProjection::update() +{ + Set_Transverse_Mercator_Parameters(theEllipsoid.getA(), + theEllipsoid.getFlattening(), + theOrigin.latr(), + theOrigin.lonr(), + TranMerc_False_Easting, + TranMerc_False_Northing, + TranMerc_Scale_Factor); + + ossimMapProjection::update(); +} + +void ossimTransMercatorProjection::setFalseEasting(double falseEasting) +{ + TranMerc_False_Easting = falseEasting; + + update(); +} + + +void ossimTransMercatorProjection::setFalseNorthing(double falseNorthing) +{ + TranMerc_False_Northing = falseNorthing; + + update(); +} + +void ossimTransMercatorProjection::setFalseEastingNorthing(double falseEasting, + double falseNorthing) +{ + TranMerc_False_Easting = falseEasting; + TranMerc_False_Northing = falseNorthing; + + update(); +} + +void ossimTransMercatorProjection::setScaleFactor(double scaleFactor) +{ + TranMerc_Scale_Factor = scaleFactor; + + update(); +} + +void ossimTransMercatorProjection::setParameters(double falseEasting, + double falseNorthing, + double scaleFactor) +{ + TranMerc_False_Easting = falseEasting; + TranMerc_False_Northing = falseNorthing; + TranMerc_Scale_Factor = scaleFactor; + + update(); +} + +void ossimTransMercatorProjection::setDefaults() +{ + TranMerc_False_Easting = 0.0; + TranMerc_False_Northing = 0.0; + TranMerc_Scale_Factor = 1.0; + TranMerc_Delta_Easting = 40000000.0; + TranMerc_Delta_Northing = 40000000.0; +} + +ossimGpt ossimTransMercatorProjection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat = 0.0; + double lon = 0.0; + + Convert_Transverse_Mercator_To_Geodetic(eastingNorthing.x, + eastingNorthing.y, + &lat, + &lon); + + return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum); +} + +ossimDpt ossimTransMercatorProjection::forward(const ossimGpt &latLon)const +{ + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + Convert_Geodetic_To_Transverse_Mercator(gpt.latr(), + gpt.lonr(), + &easting, + &northing); + + return ossimDpt(easting, northing); +} + +bool ossimTransMercatorProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const +{ + kwl.add(prefix, + ossimKeywordNames::FALSE_EASTING_KW, + TranMerc_False_Easting, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_NORTHING_KW, + TranMerc_False_Northing, + true); + + kwl.add(prefix, + ossimKeywordNames::SCALE_FACTOR_KW, + TranMerc_Scale_Factor, + true); + + return ossimMapProjection::saveState(kwl, prefix); +} + +bool ossimTransMercatorProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + bool flag = ossimMapProjection::loadState(kwl, prefix); + const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + const char* falseEasting = kwl.find(prefix, ossimKeywordNames::FALSE_EASTING_KW); + const char* falseNorthing = kwl.find(prefix, ossimKeywordNames::FALSE_NORTHING_KW); + const char* scaleFactor = kwl.find(prefix, ossimKeywordNames::SCALE_FACTOR_KW); + + setDefaults(); + if(ossimString(type) == STATIC_TYPE_NAME(ossimTransMercatorProjection)) + { + if(falseEasting) + { + TranMerc_False_Easting = ossimString(falseEasting).toDouble(); + } + if(falseNorthing) + { + TranMerc_False_Northing = ossimString(falseNorthing).toDouble(); + } + if(scaleFactor) + { + double d = ossimString(scaleFactor).toDouble(); + if (d > 0.0) // Check to avoid divide by zero. + { + TranMerc_Scale_Factor = d; + } + } + } + update(); + + return flag; +} + +/************************************************************************/ +/* FUNCTIONS + * + */ + + +long ossimTransMercatorProjection::Set_Transverse_Mercator_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing, + double Scale_Factor) + +{ /* BEGIN Set_Tranverse_Mercator_Parameters */ + /* + * The function Set_Tranverse_Mercator_Parameters receives the ellipsoid + * parameters and Tranverse Mercator projection parameters as inputs, and + * sets the corresponding state variables. If any errors occur, the error + * code(s) are returned by the function, otherwise TRANMERC_NO_ERROR is + * returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at the origin of the (input) + * projection + * Central_Meridian : Longitude in radians at the center of the (input) + * projection + * False_Easting : Easting/X at the center of the projection (input) + * False_Northing : Northing/Y at the center of the projection (input) + * Scale_Factor : Projection scale factor (input) + */ + + double tn; /* True Meridianal distance constant */ + double tn2; + double tn3; + double tn4; + double tn5; + double dummy_northing; + double TranMerc_b; /* Semi-minor axis of ellipsoid, in meters */ +// double inv_f = 1 / f; + long Error_Code = TRANMERC_NO_ERROR; + +// if (a <= 0.0) +// { /* Semi-major axis must be greater than zero */ +// Error_Code |= TRANMERC_A_ERROR; +// } +// if ((inv_f < 250) || (inv_f > 350)) +// { /* Inverse flattening must be between 250 and 350 */ +// Error_Code |= TRANMERC_INV_F_ERROR; +// } +// if ((Origin_Latitude < -MAX_LAT) || (Origin_Latitude > MAX_LAT)) +// { /* origin latitude out of range */ +// Error_Code |= TRANMERC_ORIGIN_LAT_ERROR; +// } +// if ((Central_Meridian < -M_PI) || (Central_Meridian > TWO_PI)) +// { /* origin longitude out of range */ +// Error_Code |= TRANMERC_CENT_MER_ERROR; +// } +// if ((Scale_Factor < MIN_SCALE_FACTOR) || (Scale_Factor > MAX_SCALE_FACTOR)) +// { +// Error_Code |= TRANMERC_SCALE_FACTOR_ERROR; +// } + if (!Error_Code) + { /* no errors */ + TranMerc_a = a; + TranMerc_f = f; + TranMerc_Origin_Lat = 0; + TranMerc_Origin_Long = 0; + TranMerc_False_Northing = 0; + TranMerc_False_Easting = 0; + TranMerc_Scale_Factor = 1; + + /* Eccentricity Squared */ + TranMerc_es = 2 * TranMerc_f - TranMerc_f * TranMerc_f; + /* Second Eccentricity Squared */ + TranMerc_ebs = (1 / (1 - TranMerc_es)) - 1; + + TranMerc_b = TranMerc_a * (1 - TranMerc_f); + /*True meridianal constants */ + tn = (TranMerc_a - TranMerc_b) / (TranMerc_a + TranMerc_b); + tn2 = tn * tn; + tn3 = tn2 * tn; + tn4 = tn3 * tn; + tn5 = tn4 * tn; + + TranMerc_ap = TranMerc_a * (1.e0 - tn + 5.e0 * (tn2 - tn3)/4.e0 + + 81.e0 * (tn4 - tn5)/64.e0 ); + TranMerc_bp = 3.e0 * TranMerc_a * (tn - tn2 + 7.e0 * (tn3 - tn4) + /8.e0 + 55.e0 * tn5/64.e0 )/2.e0; + TranMerc_cp = 15.e0 * TranMerc_a * (tn2 - tn3 + 3.e0 * (tn4 - tn5 )/4.e0) /16.0; + TranMerc_dp = 35.e0 * TranMerc_a * (tn3 - tn4 + 11.e0 * tn5 / 16.e0) / 48.e0; + TranMerc_ep = 315.e0 * TranMerc_a * (tn4 - tn5) / 512.e0; + Convert_Geodetic_To_Transverse_Mercator(MAX_LAT, + MAX_DELTA_LONG, + &TranMerc_Delta_Easting, + &TranMerc_Delta_Northing); + Convert_Geodetic_To_Transverse_Mercator(0, + MAX_DELTA_LONG, + &TranMerc_Delta_Easting, + &dummy_northing); + TranMerc_Origin_Lat = Origin_Latitude; + if (Central_Meridian > M_PI) + Central_Meridian -= TWO_PI; + TranMerc_Origin_Long = Central_Meridian; + TranMerc_False_Northing = False_Northing; + TranMerc_False_Easting = False_Easting; + TranMerc_Scale_Factor = Scale_Factor; + } /* END OF if(!Error_Code) */ + return (Error_Code); +} /* END of Set_Transverse_Mercator_Parameters */ + + +void ossimTransMercatorProjection::Get_Transverse_Mercator_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *False_Easting, + double *False_Northing, + double *Scale_Factor)const + +{ /* BEGIN Get_Tranverse_Mercator_Parameters */ + /* + * The function Get_Transverse_Mercator_Parameters returns the current + * ellipsoid and Transverse Mercator projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at the origin of the (output) + * projection + * Central_Meridian : Longitude in radians at the center of the (output) + * projection + * False_Easting : Easting/X at the center of the projection (output) + * False_Northing : Northing/Y at the center of the projection (output) + * Scale_Factor : Projection scale factor (output) + */ + + *a = TranMerc_a; + *f = TranMerc_f; + *Origin_Latitude = TranMerc_Origin_Lat; + *Central_Meridian = TranMerc_Origin_Long; + *False_Easting = TranMerc_False_Easting; + *False_Northing = TranMerc_False_Northing; + *Scale_Factor = TranMerc_Scale_Factor; + + return; +} /* END OF Get_Tranverse_Mercator_Parameters */ + + + +long ossimTransMercatorProjection::Convert_Geodetic_To_Transverse_Mercator (double Latitude, + double Longitude, + double *Easting, + double *Northing)const + +{ /* BEGIN Convert_Geodetic_To_Transverse_Mercator */ + + /* + * The function Convert_Geodetic_To_Transverse_Mercator converts geodetic + * (latitude and longitude) coordinates to Transverse Mercator projection + * (easting and northing) coordinates, according to the current ellipsoid + * and Transverse Mercator projection coordinates. If any errors occur, the + * error code(s) are returned by the function, otherwise TRANMERC_NO_ERROR is + * returned. + * + * Latitude : Latitude in radians (input) + * Longitude : Longitude in radians (input) + * Easting : Easting/X in meters (output) + * Northing : Northing/Y in meters (output) + */ + + double c; /* Cosine of latitude */ + double c2; + double c3; + double c5; + double c7; + double dlam; /* Delta longitude - Difference in Longitude */ + double eta; /* constant - TranMerc_ebs *c *c */ + double eta2; + double eta3; + double eta4; + double s; /* Sine of latitude */ + double sn; /* Radius of curvature in the prime vertical */ + double t; /* Tangent of latitude */ + double tan2; + double tan3; + double tan4; + double tan5; + double tan6; + double t1; /* Term in coordinate conversion formula - GP to Y */ + double t2; /* Term in coordinate conversion formula - GP to Y */ + double t3; /* Term in coordinate conversion formula - GP to Y */ + double t4; /* Term in coordinate conversion formula - GP to Y */ + double t5; /* Term in coordinate conversion formula - GP to Y */ + double t6; /* Term in coordinate conversion formula - GP to Y */ + double t7; /* Term in coordinate conversion formula - GP to Y */ + double t8; /* Term in coordinate conversion formula - GP to Y */ + double t9; /* Term in coordinate conversion formula - GP to Y */ + double tmd; /* True Meridional distance */ + double tmdo; /* True Meridional distance for latitude of origin */ + long Error_Code = TRANMERC_NO_ERROR; +// double temp_Origin; +// double temp_Long; + +// if ((Latitude < -MAX_LAT) || (Latitude > MAX_LAT)) +// { /* Latitude out of range */ +// Error_Code|= TRANMERC_LAT_ERROR; +// } + if (Longitude > M_PI) + Longitude -= TWO_PI; +// if ((Longitude < (TranMerc_Origin_Long - MAX_DELTA_LONG)) +// || (Longitude > (TranMerc_Origin_Long + MAX_DELTA_LONG))) +// { +// if (Longitude < 0) +// temp_Long = Longitude + TWO_PI; +// else +// temp_Long = Longitude; +// if (TranMerc_Origin_Long < 0) +// temp_Origin = TranMerc_Origin_Long + TWO_PI; +// else +// temp_Origin = TranMerc_Origin_Long; +// if ((temp_Long < (temp_Origin - MAX_DELTA_LONG)) +// || (temp_Long > (temp_Origin + MAX_DELTA_LONG))) +// Error_Code|= TRANMERC_LON_ERROR; +// } + if (!Error_Code) + { /* no errors */ + + /* + * Delta Longitude + */ + dlam = Longitude - TranMerc_Origin_Long; + +// if (fabs(dlam) > (9.0 * M_PI / 180)) +// { /* Distortion will result if Longitude is more than 9 degrees from the Central Meridian */ +// Error_Code |= TRANMERC_LON_WARNING; +// } + + if (dlam > M_PI) + dlam -= TWO_PI; + if (dlam < -M_PI) + dlam += TWO_PI; + if (fabs(dlam) < 2.e-10) + dlam = 0.0; + + s = sin(Latitude); + c = cos(Latitude); + c2 = c * c; + c3 = c2 * c; + c5 = c3 * c2; + c7 = c5 * c2; + t = tan (Latitude); + tan2 = t * t; + tan3 = tan2 * t; + tan4 = tan3 * t; + tan5 = tan4 * t; + tan6 = tan5 * t; + eta = TranMerc_ebs * c2; + eta2 = eta * eta; + eta3 = eta2 * eta; + eta4 = eta3 * eta; + + /* radius of curvature in prime vertical */ + sn = SPHSN(Latitude); + + /* True Meridianal Distances */ + tmd = SPHTMD(Latitude); + + /* Origin */ + tmdo = SPHTMD (TranMerc_Origin_Lat); + + /* northing */ + t1 = (tmd - tmdo) * TranMerc_Scale_Factor; + t2 = sn * s * c * TranMerc_Scale_Factor/ 2.e0; + t3 = sn * s * c3 * TranMerc_Scale_Factor * (5.e0 - tan2 + 9.e0 * eta + + 4.e0 * eta2) /24.e0; + + t4 = sn * s * c5 * TranMerc_Scale_Factor * (61.e0 - 58.e0 * tan2 + + tan4 + 270.e0 * eta - 330.e0 * tan2 * eta + 445.e0 * eta2 + + 324.e0 * eta3 -680.e0 * tan2 * eta2 + 88.e0 * eta4 + -600.e0 * tan2 * eta3 - 192.e0 * tan2 * eta4) / 720.e0; + + t5 = sn * s * c7 * TranMerc_Scale_Factor * (1385.e0 - 3111.e0 * + tan2 + 543.e0 * tan4 - tan6) / 40320.e0; + + *Northing = TranMerc_False_Northing + t1 + pow(dlam,2.e0) * t2 + + pow(dlam,4.e0) * t3 + pow(dlam,6.e0) * t4 + + pow(dlam,8.e0) * t5; + + /* Easting */ + t6 = sn * c * TranMerc_Scale_Factor; + t7 = sn * c3 * TranMerc_Scale_Factor * (1.e0 - tan2 + eta ) /6.e0; + t8 = sn * c5 * TranMerc_Scale_Factor * (5.e0 - 18.e0 * tan2 + tan4 + + 14.e0 * eta - 58.e0 * tan2 * eta + 13.e0 * eta2 + 4.e0 * eta3 + - 64.e0 * tan2 * eta2 - 24.e0 * tan2 * eta3 )/ 120.e0; + t9 = sn * c7 * TranMerc_Scale_Factor * ( 61.e0 - 479.e0 * tan2 + + 179.e0 * tan4 - tan6 ) /5040.e0; + + *Easting = TranMerc_False_Easting + dlam * t6 + pow(dlam,3.e0) * t7 + + pow(dlam,5.e0) * t8 + pow(dlam,7.e0) * t9; + } + return (Error_Code); +} /* END OF Convert_Geodetic_To_Transverse_Mercator */ + + +long ossimTransMercatorProjection::Convert_Transverse_Mercator_To_Geodetic (double Easting, + double Northing, + double *Latitude, + double *Longitude)const +{ /* BEGIN Convert_Transverse_Mercator_To_Geodetic */ + + /* + * The function Convert_Transverse_Mercator_To_Geodetic converts Transverse + * Mercator projection (easting and northing) coordinates to geodetic + * (latitude and longitude) coordinates, according to the current ellipsoid + * and Transverse Mercator projection parameters. If any errors occur, the + * error code(s) are returned by the function, otherwise TRANMERC_NO_ERROR is + * returned. + * + * Easting : Easting/X in meters (input) + * Northing : Northing/Y in meters (input) + * Latitude : Latitude in radians (output) + * Longitude : Longitude in radians (output) + */ + + double c; /* Cosine of latitude */ + double de; /* Delta easting - Difference in Easting (Easting-Fe) */ + double dlam; /* Delta longitude - Difference in Longitude */ + double eta; /* constant - TranMerc_ebs *c *c */ + double eta2; + double eta3; + double eta4; + double ftphi; /* Footpoint latitude */ + int i; /* Loop iterator */ + double s; /* Sine of latitude */ + double sn; /* Radius of curvature in the prime vertical */ + double sr; /* Radius of curvature in the meridian */ + double t; /* Tangent of latitude */ + double tan2; + double tan4; + double t10; /* Term in coordinate conversion formula - GP to Y */ + double t11; /* Term in coordinate conversion formula - GP to Y */ + double t12; /* Term in coordinate conversion formula - GP to Y */ + double t13; /* Term in coordinate conversion formula - GP to Y */ + double t14; /* Term in coordinate conversion formula - GP to Y */ + double t15; /* Term in coordinate conversion formula - GP to Y */ + double t16; /* Term in coordinate conversion formula - GP to Y */ + double t17; /* Term in coordinate conversion formula - GP to Y */ + double tmd; /* True Meridional distance */ + double tmdo; /* True Meridional distance for latitude of origin */ + long Error_Code = TRANMERC_NO_ERROR; + +// if ((Easting < (TranMerc_False_Easting - TranMerc_Delta_Easting)) +// ||(Easting > (TranMerc_False_Easting + TranMerc_Delta_Easting))) +// { /* Easting out of range */ +// Error_Code |= TRANMERC_EASTING_ERROR; +// } +// if ((Northing < (TranMerc_False_Northing - TranMerc_Delta_Northing)) +// || (Northing > (TranMerc_False_Northing + TranMerc_Delta_Northing))) +// { /* Northing out of range */ +// Error_Code |= TRANMERC_NORTHING_ERROR; +// } + + if (!Error_Code) + { + /* True Meridional Distances for latitude of origin */ + tmdo = SPHTMD(TranMerc_Origin_Lat); + + /* Origin */ + tmd = tmdo + (Northing - TranMerc_False_Northing) / TranMerc_Scale_Factor; + + /* First Estimate */ + sr = SPHSR(0.e0); + ftphi = tmd/sr; + + for (i = 0; i < 5 ; i++) + { + t10 = SPHTMD (ftphi); + sr = SPHSR(ftphi); + ftphi = ftphi + (tmd - t10) / sr; + } + + /* Radius of Curvature in the meridian */ + sr = SPHSR(ftphi); + + /* Radius of Curvature in the meridian */ + sn = SPHSN(ftphi); + + /* Sine Cosine terms */ + s = sin(ftphi); + c = cos(ftphi); + + /* Tangent Value */ + t = tan(ftphi); + tan2 = t * t; + tan4 = tan2 * tan2; + eta = TranMerc_ebs * pow(c,2); + eta2 = eta * eta; + eta3 = eta2 * eta; + eta4 = eta3 * eta; + de = Easting - TranMerc_False_Easting; + if (fabs(de) < 0.0001) + de = 0.0; + + /* Latitude */ + t10 = t / (2.e0 * sr * sn * pow(TranMerc_Scale_Factor, 2)); + t11 = t * (5.e0 + 3.e0 * tan2 + eta - 4.e0 * pow(eta,2) + - 9.e0 * tan2 * eta) / (24.e0 * sr * pow(sn,3) + * pow(TranMerc_Scale_Factor,4)); + t12 = t * (61.e0 + 90.e0 * tan2 + 46.e0 * eta + 45.E0 * tan4 + - 252.e0 * tan2 * eta - 3.e0 * eta2 + 100.e0 + * eta3 - 66.e0 * tan2 * eta2 - 90.e0 * tan4 + * eta + 88.e0 * eta4 + 225.e0 * tan4 * eta2 + + 84.e0 * tan2* eta3 - 192.e0 * tan2 * eta4) + / ( 720.e0 * sr * pow(sn,5) * pow(TranMerc_Scale_Factor, 6) ); + t13 = t * ( 1385.e0 + 3633.e0 * tan2 + 4095.e0 * tan4 + 1575.e0 + * pow(t,6))/ (40320.e0 * sr * pow(sn,7) * pow(TranMerc_Scale_Factor,8)); + *Latitude = ftphi - pow(de,2) * t10 + pow(de,4) * t11 - pow(de,6) * t12 + + pow(de,8) * t13; + + t14 = 1.e0 / (sn * c * TranMerc_Scale_Factor); + + t15 = (1.e0 + 2.e0 * tan2 + eta) / (6.e0 * pow(sn,3) * c * + pow(TranMerc_Scale_Factor,3)); + + t16 = (5.e0 + 6.e0 * eta + 28.e0 * tan2 - 3.e0 * eta2 + + 8.e0 * tan2 * eta + 24.e0 * tan4 - 4.e0 + * eta3 + 4.e0 * tan2 * eta2 + 24.e0 + * tan2 * eta3) / (120.e0 * pow(sn,5) * c + * pow(TranMerc_Scale_Factor,5)); + + t17 = (61.e0 + 662.e0 * tan2 + 1320.e0 * tan4 + 720.e0 + * pow(t,6)) / (5040.e0 * pow(sn,7) * c + * pow(TranMerc_Scale_Factor,7)); + + /* Difference in Longitude */ + dlam = de * t14 - pow(de,3) * t15 + pow(de,5) * t16 - pow(de,7) * t17; + + /* Longitude */ + (*Longitude) = TranMerc_Origin_Long + dlam; + while (*Latitude > (90.0 * RAD_PER_DEG)) + { + *Latitude = M_PI - *Latitude; + *Longitude += M_PI; + if (*Longitude > M_PI) + *Longitude -= TWO_PI; + } + + while (*Latitude < (-90.0 * RAD_PER_DEG)) + { + *Latitude = - (*Latitude + M_PI); + *Longitude += M_PI; + if (*Longitude > M_PI) + *Longitude -= TWO_PI; + } + if (*Longitude > TWO_PI) + *Longitude -= TWO_PI; + if (*Longitude < -M_PI) + *Longitude += TWO_PI; + +// if (fabs(dlam) > (9.0 * M_PI / 180)) +// { /* Distortion will result if Longitude is more than 9 degrees from the Central Meridian */ +// Error_Code |= TRANMERC_LON_WARNING; +// } + } + return (Error_Code); +} /* END OF Convert_Transverse_Mercator_To_Geodetic */ + +std::ostream& ossimTransMercatorProjection::print(std::ostream& out) const +{ + out << setiosflags(ios::fixed) << setprecision(15) + << "// ossimTransMercatorProjection::print\n" + << ossimKeywordNames::SCALE_FACTOR_KW << ": " << TranMerc_Scale_Factor + << endl; + return ossimMapProjection::print(out); +} diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimTransMercatorProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimTransMercatorProjection.h new file mode 100644 index 0000000000..d48a60ad80 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimTransMercatorProjection.h @@ -0,0 +1,220 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Geotrans Transverse Mercator projection code. +//******************************************************************* +// $Id: ossimTransMercatorProjection.h,v 1.8 2005/09/09 19:23:58 gpotts Exp $ + +#ifndef ossimTransMercatorProjection_HEADER +#define ossimTransMercatorProjection_HEADER + +#include "ossimMapProjection.h" + +class ossimTransMercatorProjection : public ossimMapProjection +{ +public: + ossimTransMercatorProjection(const ossimEllipsoid& ellipsoid = ossimEllipsoid(6378137, 6356752.3142), + const ossimGpt& origin = ossimGpt()); + ossimTransMercatorProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double falseEasting, + double falseNorthing, + double scaleFactor); + ~ossimTransMercatorProjection(){} + + virtual ossimObject *dup()const{return new ossimTransMercatorProjection(*this);} + virtual ossimGpt inverse(const ossimDpt &eastingNorthing)const; + virtual ossimDpt forward(const ossimGpt &latLon)const; + virtual void update(); + + /*! + * SetFalseEasting. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEasting(double falseEasting); + + /*! + * SetFalseNorthing. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseNorthing(double falseNorthing); + + /* + * Set's scale and then update. + */ + void setScaleFactor(double scaleFactor); + /*! + * Sets both false easting and northing values. The values are + * expected to be in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEastingNorthing(double falseEasting, double falseNorthing); + + void setParameters(double falseEasting, + double falseNorthing, + double scaleFactor); + + void setDefaults(); + + double getFalseEasting()const{return TranMerc_False_Easting;} + double getFalseNorthing()const{return TranMerc_False_Northing;} + double getScaleFactor()const{return TranMerc_Scale_Factor;} + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /*! + * Prints data members to stream. Returns stream&. + */ + virtual std::ostream& print(std::ostream& out) const; + +protected: + + //_____________GEOTRANS_______________ + + double TranMerc_a; /* Semi-major axis of ellipsoid i meters */ + double TranMerc_f; /* Flattening of ellipsoid */ + double TranMerc_es; /* Eccentricity (0.08181919084262188000) squared */ + double TranMerc_ebs; /* Second Eccentricity squared */ + +/* Transverse_Mercator projection Parameters */ + double TranMerc_Origin_Lat; /* Latitude of origin in radians */ + double TranMerc_Origin_Long; /* Longitude of origin in radians */ + double TranMerc_False_Northing; /* False northing in meters */ + double TranMerc_False_Easting; /* False easting in meters */ + double TranMerc_Scale_Factor; /* Scale factor */ + +/* Isometeric to geodetic latitude parameters, default to WGS 84 */ + double TranMerc_ap; + double TranMerc_bp; + double TranMerc_cp; + double TranMerc_dp; + double TranMerc_ep; + +/* Maximum variance for easting and northing values for WGS 84. */ + double TranMerc_Delta_Easting; + double TranMerc_Delta_Northing; + +/*! + * The function Set_Tranverse_Mercator_Parameters receives the ellipsoid + * parameters and Tranverse Mercator projection parameters as inputs, and + * sets the corresponding state variables. If any errors occur, the error + * code(s) are returned by the function, otherwise TRANMERC_NO_ERROR is + * returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at the origin of the (input) + * projection + * Central_Meridian : Longitude in radians at the center of the (input) + * projection + * False_Easting : Easting/X at the center of the projection (input) + * False_Northing : Northing/Y at the center of the projection (input) + * Scale_Factor : Projection scale factor (input) + */ + long Set_Transverse_Mercator_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing, + double Scale_Factor); + + +/*! + * The function Get_Transverse_Mercator_Parameters returns the current + * ellipsoid and Transverse Mercator projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at the origin of the (output) + * projection + * Central_Meridian : Longitude in radians at the center of the (output) + * projection + * False_Easting : Easting/X at the center of the projection (output) + * False_Northing : Northing/Y at the center of the projection (output) + * Scale_Factor : Projection scale factor (output) + */ + void Get_Transverse_Mercator_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *False_Easting, + double *False_Northing, + double *Scale_Factor)const; + + +/*! + * The function Convert_Geodetic_To_Transverse_Mercator converts geodetic + * (latitude and longitude) coordinates to Transverse Mercator projection + * (easting and northing) coordinates, according to the current ellipsoid + * and Transverse Mercator projection coordinates. If any errors occur, the + * error code(s) are returned by the function, otherwise TRANMERC_NO_ERROR is + * returned. + * + * Latitude : Latitude in radians (input) + * Longitude : Longitude in radians (input) + * Easting : Easting/X in meters (output) + * Northing : Northing/Y in meters (output) + */ + long Convert_Geodetic_To_Transverse_Mercator (double Latitude, + double Longitude, + double *Easting, + double *Northing)const; + + + +/*! + * The function Convert_Transverse_Mercator_To_Geodetic converts Transverse + * Mercator projection (easting and northing) coordinates to geodetic + * (latitude and longitude) coordinates, according to the current ellipsoid + * and Transverse Mercator projection parameters. If any errors occur, the + * error code(s) are returned by the function, otherwise TRANMERC_NO_ERROR is + * returned. + * + * Easting : Easting/X in meters (input) + * Northing : Northing/Y in meters (input) + * Latitude : Latitude in radians (output) + * Longitude : Longitude in radians (output) + */ + long Convert_Transverse_Mercator_To_Geodetic (double Easting, + double Northing, + double *Latitude, + double *Longitude)const; + + + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUps.c b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUps.c new file mode 100644 index 0000000000..717801fb6d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUps.c @@ -0,0 +1,310 @@ +/********************************************************************/ +/* RSC IDENTIFIER: UPS + * + * + * ABSTRACT + * + * This component provides conversions between geodetic (latitude + * and longitude) coordinates and Universal Polar Stereographic (UPS) + * projection (hemisphere, easting, and northing) coordinates. + * + * + * ERROR HANDLING + * + * This component checks parameters for valid values. If an + * invalid value is found the error code is combined with the + * current error code using the bitwise or. This combining allows + * multiple error codes to be returned. The possible error codes + * are: + * + * UPS_NO_ERROR : No errors occurred in function + * UPS_LAT_ERROR : Latitude outside of valid range + * (North Pole: 83.5 to 90, + * South Pole: -79.5 to -90) + * UPS_LON_ERROR : Longitude outside of valid range + * (-180 to 360 degrees) + * UPS_HEMISPHERE_ERROR : Invalid hemisphere ('N' or 'S') + * UPS_EASTING_ERROR : Easting outside of valid range, + * (0 to 4,000,000m) + * UPS_NORTHING_ERROR : Northing outside of valid range, + * (0 to 4,000,000m) + * UPS_A_ERROR : Semi-major axis less than or equal to zero + * UPS_INV_F_ERROR : Inverse flattening outside of valid range + * (250 to 350) + * + * + * REUSE NOTES + * + * UPS is intended for reuse by any application that performs a Universal + * Polar Stereographic (UPS) projection. + * + * + * REFERENCES + * + * Further information on UPS can be found in the Reuse Manual. + * + * UPS originated from : U.S. Army Topographic Engineering Center + * Geospatial Information Division + * 7701 Telegraph Road + * Alexandria, VA 22310-3864 + * + * + * LICENSES + * + * None apply to this component. + * + * + * RESTRICTIONS + * + * UPS has no restrictions. + * + * + * ENVIRONMENT + * + * UPS was tested and certified in the following environments: + * + * 1. Solaris 2.5 with GCC version 2.8.1 + * 2. Windows 95 with MS Visual C++ version 6 + * + * + * MODIFICATIONS + * + * Date Description + * ---- ----------- + * 06-11-95 Original Code + * 03-01-97 Original Code + * + * + */ + + +/************************************************************************/ +/* + * INCLUDES + */ + +#include <math.h> +#include "ossimPolarst.h" +#include "ossimUps.h" +/* + * math.h - Is needed to call the math functions. + * polar.h - Is used to convert polar stereographic coordinates + * ups.h - Defines the function prototypes for the ups module. + */ + + +/************************************************************************/ +/* GLOBAL DECLARATIONS + * + */ + +#define PI 3.14159265358979323e0 /* PI */ +#define PI_OVER (PI/2.0e0) /* PI over 2 */ +#define MAX_LAT ((PI * 90)/180.0) /* 90 degrees in radians */ +#define MAX_ORIGIN_LAT ((81.114528 * PI) / 180.0) +#define MIN_NORTH_LAT (83.5*PI/180.0) +#define MIN_SOUTH_LAT (-79.5*PI/180.0) +#define MIN_EAST_NORTH 0 +#define MAX_EAST_NORTH 4000000 + +/* Ellipsoid Parameters, default to WGS 84 */ +static double UPS_a = 6378137.0; /* Semi-major axis of ellipsoid in meters */ +static double UPS_f = 1 / 298.257223563; /* Flattening of ellipsoid */ +const double UPS_False_Easting = 2000000; +const double UPS_False_Northing = 2000000; +static double UPS_Origin_Latitude = MAX_ORIGIN_LAT; /*set default = North Hemisphere */ +static double UPS_Origin_Longitude = 0.0; +static double false_easting = 0.0; +static double false_northing = 0.0; +static double UPS_Easting = 0.0; +static double UPS_Northing = 0.0; + + +/************************************************************************/ +/* FUNCTIONS + * + */ + + +long Set_UPS_Parameters( double a, + double f) +{ +/* + * The function SET_UPS_PARAMETERS receives the ellipsoid parameters and sets + * the corresponding state variables. If any errors occur, the error code(s) + * are returned by the function, otherwise UPS_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid in meters (input) + * f : Flattening of ellipsoid (input) + */ + + double inv_f = 1 / f; + long Error_Code = UPS_NO_ERROR; + + if (a <= 0.0) + { /* Semi-major axis must be greater than zero */ + Error_Code |= UPS_A_ERROR; + } + if ((inv_f < 250) || (inv_f > 350)) + { /* Inverse flattening must be between 250 and 350 */ + Error_Code |= UPS_INV_F_ERROR; + } + + if (!Error_Code) + { /* no errors */ + UPS_a = a; + UPS_f = f; + } + return (Error_Code); +} /* END of Set_UPS_Parameters */ + + +void Get_UPS_Parameters( double *a, + double *f) +{ +/* + * The function Get_UPS_Parameters returns the current ellipsoid parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + */ + + *a = UPS_a; + *f = UPS_f; + return; +} /* END OF Get_UPS_Parameters */ + + +long Convert_Geodetic_To_UPS ( double Latitude, + double Longitude, + char *Hemisphere, + double *Easting, + double *Northing) +{ +/* + * The function Convert_Geodetic_To_UPS converts geodetic (latitude and + * longitude) coordinates to UPS (hemisphere, easting, and northing) + * coordinates, according to the current ellipsoid parameters. If any + * errors occur, the error code(s) are returned by the function, + * otherwide UPS_NO_ERROR is returned. + * + * Latitude : Latitude in radians (input) + * Longitude : Longitude in radians (input) + * Hemisphere : Hemisphere either 'N' or 'S' (output) + * Easting : Easting/X in meters (output) + * Northing : Northing/Y in meters (output) + */ + + double tempEasting, tempNorthing; + long Error_Code = UPS_NO_ERROR; + + if ((Latitude < -MAX_LAT) || (Latitude > MAX_LAT)) + { /* latitude out of range */ + Error_Code |= UPS_LAT_ERROR; + } + if ((Latitude < 0) && (Latitude > MIN_SOUTH_LAT)) + Error_Code |= UPS_LAT_ERROR; + if ((Latitude >= 0) && (Latitude < MIN_NORTH_LAT)) + Error_Code |= UPS_LAT_ERROR; + if ((Longitude < -PI) || (Longitude > (2 * PI))) + { /* slam out of range */ + Error_Code |= UPS_LON_ERROR; + } + + if (!Error_Code) + { /* no errors */ + if (Latitude < 0) + { + UPS_Origin_Latitude = -MAX_ORIGIN_LAT; + *Hemisphere = 'S'; + } + else + { + UPS_Origin_Latitude = MAX_ORIGIN_LAT; + *Hemisphere = 'N'; + } + + + Set_Polar_Stereographic_Parameters( UPS_a, + UPS_f, + UPS_Origin_Latitude, + UPS_Origin_Longitude, + false_easting, + false_northing); + + Convert_Geodetic_To_Polar_Stereographic(Latitude, + Longitude, + &tempEasting, + &tempNorthing); + + UPS_Easting = UPS_False_Easting + tempEasting; + UPS_Northing = UPS_False_Northing + tempNorthing; + + + *Easting = UPS_Easting; + *Northing = UPS_Northing; + } /* END of if(!Error_Code) */ + + return (Error_Code); +} /* END OF Convert_Geodetic_To_UPS */ + + +long Convert_UPS_To_Geodetic(char Hemisphere, + double Easting, + double Northing, + double *Latitude, + double *Longitude) +{ +/* + * The function Convert_UPS_To_Geodetic converts UPS (hemisphere, easting, + * and northing) coordinates to geodetic (latitude and longitude) coordinates + * according to the current ellipsoid parameters. If any errors occur, the + * error code(s) are returned by the function, otherwise UPS_NO_ERROR is + * returned. + * + * Hemisphere : Hemisphere either 'N' or 'S' (input) + * Easting : Easting/X in meters (input) + * Northing : Northing/Y in meters (input) + * Latitude : Latitude in radians (output) + * Longitude : Longitude in radians (output) + */ + + long Error_Code = UPS_NO_ERROR; + + if ((Hemisphere != 'N') && (Hemisphere != 'S')) + Error_Code |= UPS_HEMISPHERE_ERROR; + if ((Easting < MIN_EAST_NORTH) || (Easting > MAX_EAST_NORTH)) + Error_Code |= UPS_EASTING_ERROR; + if ((Northing < MIN_EAST_NORTH) || (Northing > MAX_EAST_NORTH)) + Error_Code |= UPS_NORTHING_ERROR; + + if (Hemisphere =='N') + {UPS_Origin_Latitude = MAX_ORIGIN_LAT;} + if (Hemisphere =='S') + {UPS_Origin_Latitude = -MAX_ORIGIN_LAT;} + + if (!Error_Code) + { /* no errors */ + Set_Polar_Stereographic_Parameters( UPS_a, + UPS_f, + UPS_Origin_Latitude, + UPS_Origin_Longitude, + UPS_False_Easting, + UPS_False_Northing); + + + + Convert_Polar_Stereographic_To_Geodetic( Easting, + Northing, + Latitude, + Longitude); + + + if ((*Latitude < 0) && (*Latitude > MIN_SOUTH_LAT)) + Error_Code |= UPS_LAT_ERROR; + if ((*Latitude >= 0) && (*Latitude < MIN_NORTH_LAT)) + Error_Code |= UPS_LAT_ERROR; + } /* END OF if(!Error_Code) */ + return (Error_Code); +} /* END OF Convert_UPS_To_Geodetic */ + diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUps.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUps.h new file mode 100644 index 0000000000..9f6c81722f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUps.h @@ -0,0 +1,175 @@ +#ifndef UPS_H + #define UPS_H +/********************************************************************/ +/* RSC IDENTIFIER: UPS + * + * + * ABSTRACT + * + * This component provides conversions between geodetic (latitude + * and longitude) coordinates and Universal Polar Stereographic (UPS) + * projection (hemisphere, easting, and northing) coordinates. + * + * + * ERROR HANDLING + * + * This component checks parameters for valid values. If an + * invalid value is found the error code is combined with the + * current error code using the bitwise or. This combining allows + * multiple error codes to be returned. The possible error codes + * are: + * + * UPS_NO_ERROR : No errors occurred in function + * UPS_LAT_ERROR : Latitude outside of valid range + * (North Pole: 83.5 to 90, + * South Pole: -79.5 to -90) + * UPS_LON_ERROR : Longitude outside of valid range + * (-180 to 360 degrees) + * UPS_HEMISPHERE_ERROR : Invalid hemisphere ('N' or 'S') + * UPS_EASTING_ERROR : Easting outside of valid range, + * (0 to 4,000,000m) + * UPS_NORTHING_ERROR : Northing outside of valid range, + * (0 to 4,000,000m) + * UPS_A_ERROR : Semi-major axis less than or equal to zero + * UPS_INV_F_ERROR : Inverse flattening outside of valid range + * (250 to 350) + * + * + * REUSE NOTES + * + * UPS is intended for reuse by any application that performs a Universal + * Polar Stereographic (UPS) projection. + * + * + * REFERENCES + * + * Further information on UPS can be found in the Reuse Manual. + * + * UPS originated from : U.S. Army Topographic Engineering Center + * Geospatial Information Division + * 7701 Telegraph Road + * Alexandria, VA 22310-3864 + * + * + * LICENSES + * + * None apply to this component. + * + * + * RESTRICTIONS + * + * UPS has no restrictions. + * + * + * ENVIRONMENT + * + * UPS was tested and certified in the following environments: + * + * 1. Solaris 2.5 with GCC version 2.8.1 + * 2. Windows 95 with MS Visual C++ version 6 + * + * + * MODIFICATIONS + * + * Date Description + * ---- ----------- + * 06-11-95 Original Code + * 03-01-97 Original Code + * + * + */ + + +/**********************************************************************/ +/* + * DEFINES + */ + + #define UPS_NO_ERROR 0x0000 + #define UPS_LAT_ERROR 0x0001 + #define UPS_LON_ERROR 0x0002 + #define UPS_HEMISPHERE_ERROR 0x0004 + #define UPS_EASTING_ERROR 0x0008 + #define UPS_NORTHING_ERROR 0x0010 + #define UPS_A_ERROR 0x0020 + #define UPS_INV_F_ERROR 0x0040 + + +/**********************************************************************/ +/* + * FUNCTION PROTOTYPES + * for UPS.C + */ + +/* ensure proper linkage to c++ programs */ + #ifdef __cplusplus +extern "C" { + #endif + + long Set_UPS_Parameters( double a, + double f); +/* + * The function SET_UPS_PARAMETERS receives the ellipsoid parameters and sets + * the corresponding state variables. If any errors occur, the error code(s) + * are returned by the function, otherwise UPS_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid in meters (input) + * f : Flattening of ellipsoid (input) + */ + + + void Get_UPS_Parameters( double *a, + double *f); +/* + * The function Get_UPS_Parameters returns the current ellipsoid parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + */ + + + long Convert_Geodetic_To_UPS ( double Latitude, + double Longitude, + char *Hemisphere, + double *Easting, + double *Northing); +/* + * The function Convert_Geodetic_To_UPS converts geodetic (latitude and + * longitude) coordinates to UPS (hemisphere, easting, and northing) + * coordinates, according to the current ellipsoid parameters. If any + * errors occur, the error code(s) are returned by the function, + * otherwide UPS_NO_ERROR is returned. + * + * Latitude : Latitude in radians (input) + * Longitude : Longitude in radians (input) + * Hemisphere : Hemisphere either 'N' or 'S' (output) + * Easting : Easting/X in meters (output) + * Northing : Northing/Y in meters (output) + */ + + + long Convert_UPS_To_Geodetic(char Hemisphere, + double Easting, + double Northing, + double *Latitude, + double *Longitude); + +/* + * The function Convert_UPS_To_Geodetic converts UPS (hemisphere, easting, + * and northing) coordinates to geodetic (latitude and longitude) coordinates + * according to the current ellipsoid parameters. If any errors occur, the + * error code(s) are returned by the function, otherwise UPS_NO_ERROR is + * returned. + * + * Hemisphere : Hemisphere either 'N' or 'S' (input) + * Easting : Easting/X in meters (input) + * Northing : Northing/Y in meters (input) + * Latitude : Latitude in radians (output) + * Longitude : Longitude in radians (output) + */ + + #ifdef __cplusplus +} + #endif + +#endif /* UPS_H */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUpsProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUpsProjection.cpp new file mode 100644 index 0000000000..dea1cab8fa --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUpsProjection.cpp @@ -0,0 +1,335 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimUpsProjection.cpp,v 1.4 2004/01/08 21:49:22 jlargent Exp $ +#include "ossimUpsProjection.h" +#include "ossimPolarst.h" + +#define PI 3.14159265358979323e0 /* PI */ +#define PI_OVER (PI/2.0e0) /* PI over 2 */ +#define MAX_LAT ((PI * 90)/180.0) /* 90 degrees in radians */ +#define MAX_ORIGIN_LAT ((81.114528 * PI) / 180.0) +#define MIN_NORTH_LAT (83.5*PI/180.0) +#define MIN_SOUTH_LAT (-79.5*PI/180.0) +#define MIN_EAST_NORTH 0 +#define MAX_EAST_NORTH 4000000 + +#define UPS_NO_ERROR 0x0000 +#define UPS_LAT_ERROR 0x0001 +#define UPS_LON_ERROR 0x0002 +#define UPS_HEMISPHERE_ERROR 0x0004 +#define UPS_EASTING_ERROR 0x0008 +#define UPS_NORTHING_ERROR 0x0010 +#define UPS_A_ERROR 0x0020 +#define UPS_INV_F_ERROR 0x0040 + +RTTI_DEF1(ossimUpsProjection, "ossimUpsProjection", ossimMapProjection); + +ossimUpsProjection::ossimUpsProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + :ossimMapProjection(ellipsoid, origin) +{ + setDefaults(); + update(); +} + + +void ossimUpsProjection::setDefaults() +{ + if(theOrigin.latd() >= -FLT_EPSILON) + { + UPS_Origin_Latitude = MAX_ORIGIN_LAT; + theHemisphere = 'N'; + } + else + { + UPS_Origin_Latitude = -MAX_ORIGIN_LAT; + theHemisphere = 'S'; + } + UPS_False_Easting = 2000000; + UPS_False_Northing = 2000000; + false_easting = 0.0; + false_northing = 0.0; + UPS_Easting = 0.0; + UPS_Northing = 0.0; + UPS_Origin_Longitude = 0.0; + theOrigin = ossimGpt(UPS_Origin_Latitude*DEG_PER_RAD, + 0.0,0.0); +} + +ossimGpt ossimUpsProjection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat = 0.0; + double lon = 0.0; + + Convert_UPS_To_Geodetic(theHemisphere, + eastingNorthing.x, + eastingNorthing.y, + &lat, + &lon); + + return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum); +} + +ossimDpt ossimUpsProjection::forward(const ossimGpt &latLon)const +{ + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + Convert_Geodetic_To_UPS(gpt.latr(), + gpt.lonr(), + &theHemisphere, + &easting, + &northing); + + return ossimDpt(easting, northing); +} + +void ossimUpsProjection::update() +{ + Set_UPS_Parameters(theEllipsoid.getA(), + theEllipsoid.getFlattening()); + + ossimMapProjection::update(); +} + +/*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ +bool ossimUpsProjection::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + return ossimMapProjection::saveState(kwl, prefix); +} + +/*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ +bool ossimUpsProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + setDefaults(); + + return ossimMapProjection::loadState(kwl, prefix); +} + +/************************************************************************/ +/* FUNCTIONS + * + */ + + +long ossimUpsProjection::Set_UPS_Parameters( double a, + double f) +{ +/* + * The function SET_UPS_PARAMETERS receives the ellipsoid parameters and sets + * the corresponding state variables. If any errors occur, the error code(s) + * are returned by the function, otherwise UPS_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid in meters (input) + * f : Flattening of ellipsoid (input) + */ + +// double inv_f = 1 / f; + long Error_Code = UPS_NO_ERROR; + +// if (a <= 0.0) +// { /* Semi-major axis must be greater than zero */ +// Error_Code |= UPS_A_ERROR; +// } +// if ((inv_f < 250) || (inv_f > 350)) +// { /* Inverse flattening must be between 250 and 350 */ +// Error_Code |= UPS_INV_F_ERROR; +// } + + if (!Error_Code) + { /* no errors */ + UPS_a = a; + UPS_f = f; + } + return (Error_Code); +} /* END of Set_UPS_Parameters */ + + +void ossimUpsProjection::Get_UPS_Parameters( double *a, + double *f)const +{ +/* + * The function Get_UPS_Parameters returns the current ellipsoid parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + */ + + *a = UPS_a; + *f = UPS_f; + + return; +} /* END OF Get_UPS_Parameters */ + + +long ossimUpsProjection::Convert_Geodetic_To_UPS ( double Latitude, + double Longitude, + char *Hemisphere, + double *Easting, + double *Northing)const +{ +/* + * The function Convert_Geodetic_To_UPS converts geodetic (latitude and + * longitude) coordinates to UPS (hemisphere, easting, and northing) + * coordinates, according to the current ellipsoid parameters. If any + * errors occur, the error code(s) are returned by the function, + * otherwide UPS_NO_ERROR is returned. + * + * Latitude : Latitude in radians (input) + * Longitude : Longitude in radians (input) + * Hemisphere : Hemisphere either 'N' or 'S' (output) + * Easting : Easting/X in meters (output) + * Northing : Northing/Y in meters (output) + */ + + double tempEasting, tempNorthing; + long Error_Code = UPS_NO_ERROR; + +// if ((Latitude < -MAX_LAT) || (Latitude > MAX_LAT)) +// { /* latitude out of range */ +// Error_Code |= UPS_LAT_ERROR; +// } +// if ((Latitude < 0) && (Latitude > MIN_SOUTH_LAT)) +// Error_Code |= UPS_LAT_ERROR; +// if ((Latitude >= 0) && (Latitude < MIN_NORTH_LAT)) +// Error_Code |= UPS_LAT_ERROR; +// if ((Longitude < -PI) || (Longitude > (2 * PI))) +// { /* slam out of range */ +// Error_Code |= UPS_LON_ERROR; +// } + + if (!Error_Code) + { /* no errors */ +// if (Latitude < 0) +// { +// UPS_Origin_Latitude = -MAX_ORIGIN_LAT; +// *Hemisphere = 'S'; +// } +// else +// { +// UPS_Origin_Latitude = MAX_ORIGIN_LAT; +// *Hemisphere = 'N'; +// } + + + Set_Polar_Stereographic_Parameters( UPS_a, + UPS_f, + UPS_Origin_Latitude, + UPS_Origin_Longitude, + false_easting, + false_northing); + + Convert_Geodetic_To_Polar_Stereographic(Latitude, + Longitude, + &tempEasting, + &tempNorthing); + + UPS_Easting = UPS_False_Easting + tempEasting; + UPS_Northing = UPS_False_Northing + tempNorthing; + + + *Easting = UPS_Easting; + *Northing = UPS_Northing; + } /* END of if(!Error_Code) */ + + return (Error_Code); +} /* END OF Convert_Geodetic_To_UPS */ + + +long ossimUpsProjection::Convert_UPS_To_Geodetic(char Hemisphere, + double Easting, + double Northing, + double *Latitude, + double *Longitude)const +{ +/* + * The function Convert_UPS_To_Geodetic converts UPS (hemisphere, easting, + * and northing) coordinates to geodetic (latitude and longitude) coordinates + * according to the current ellipsoid parameters. If any errors occur, the + * error code(s) are returned by the function, otherwise UPS_NO_ERROR is + * returned. + * + * Hemisphere : Hemisphere either 'N' or 'S' (input) + * Easting : Easting/X in meters (input) + * Northing : Northing/Y in meters (input) + * Latitude : Latitude in radians (output) + * Longitude : Longitude in radians (output) + */ + + long Error_Code = UPS_NO_ERROR; + +// if ((Hemisphere != 'N') && (Hemisphere != 'S')) +// Error_Code |= UPS_HEMISPHERE_ERROR; +// if ((Easting < MIN_EAST_NORTH) || (Easting > MAX_EAST_NORTH)) +// Error_Code |= UPS_EASTING_ERROR; +// if ((Northing < MIN_EAST_NORTH) || (Northing > MAX_EAST_NORTH)) +// Error_Code |= UPS_NORTHING_ERROR; + + if (Hemisphere =='N') + {UPS_Origin_Latitude = MAX_ORIGIN_LAT;} + if (Hemisphere =='S') + {UPS_Origin_Latitude = -MAX_ORIGIN_LAT;} + + if (!Error_Code) + { /* no errors */ + Set_Polar_Stereographic_Parameters( UPS_a, + UPS_f, + UPS_Origin_Latitude, + UPS_Origin_Longitude, + UPS_False_Easting, + UPS_False_Northing); + + + + Convert_Polar_Stereographic_To_Geodetic( Easting, + Northing, + Latitude, + Longitude); + + +// if ((*Latitude < 0) && (*Latitude > MIN_SOUTH_LAT)) +// Error_Code |= UPS_LAT_ERROR; +// if ((*Latitude >= 0) && (*Latitude < MIN_NORTH_LAT)) +// Error_Code |= UPS_LAT_ERROR; + } /* END OF if(!Error_Code) */ + return (Error_Code); +} /* END OF Convert_UPS_To_Geodetic */ + diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUpsProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUpsProjection.h new file mode 100644 index 0000000000..e1f3de04a9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUpsProjection.h @@ -0,0 +1,140 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +//******************************************************************* +// $Id: ossimUpsProjection.h,v 1.2 2005/09/09 19:23:58 gpotts Exp $ +#ifndef ossimUpsProjection_HEADER +#define ossimUpsProjection_HEADER +#include "ossimMapProjection.h" + +class ossimUpsProjection : public ossimMapProjection +{ +public: + ossimUpsProjection(const ossimEllipsoid& ellipsoid = ossimEllipsoid(), + const ossimGpt& origin = ossimGpt()); + + virtual ossimObject *dup()const{return new ossimUpsProjection(*this);} + + void setDefaults(); + + virtual ossimGpt inverse(const ossimDpt &eastingNorthing)const; + virtual ossimDpt forward(const ossimGpt &latLon)const; + virtual void update(); + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + double getFalseEasting()const{return UPS_False_Easting;} + double getFalseNorthing()const{return UPS_False_Northing;} + +protected: + mutable char theHemisphere; + + //___________________GEOTRANS__________________ + // + mutable double UPS_a; /* Semi-major axis of ellipsoid in meters */ + mutable double UPS_f; /* Flattening of ellipsoid */ + mutable double UPS_Origin_Latitude; /*set default = North Hemisphere */ + mutable double UPS_Origin_Longitude; + mutable double false_easting; + mutable double false_northing; + mutable double UPS_Easting; + mutable double UPS_Northing; + double UPS_False_Easting; + double UPS_False_Northing; + +/*! + * The function SET_UPS_PARAMETERS receives the ellipsoid parameters and sets + * the corresponding state variables. If any errors occur, the error code(s) + * are returned by the function, otherwise UPS_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid in meters (input) + * f : Flattening of ellipsoid (input) + */ + long Set_UPS_Parameters( double a, + double f); + + +/*! + * The function Get_UPS_Parameters returns the current ellipsoid parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + */ + void Get_UPS_Parameters( double *a, + double *f)const; + + +/*! + * The function Convert_Geodetic_To_UPS converts geodetic (latitude and + * longitude) coordinates to UPS (hemisphere, easting, and northing) + * coordinates, according to the current ellipsoid parameters. If any + * errors occur, the error code(s) are returned by the function, + * otherwide UPS_NO_ERROR is returned. + * + * Latitude : Latitude in radians (input) + * Longitude : Longitude in radians (input) + * Hemisphere : Hemisphere either 'N' or 'S' (output) + * Easting : Easting/X in meters (output) + * Northing : Northing/Y in meters (output) + */ + long Convert_Geodetic_To_UPS ( double Latitude, + double Longitude, + char *Hemisphere, + double *Easting, + double *Northing)const; + + +/*! + * The function Convert_UPS_To_Geodetic converts UPS (hemisphere, easting, + * and northing) coordinates to geodetic (latitude and longitude) coordinates + * according to the current ellipsoid parameters. If any errors occur, the + * error code(s) are returned by the function, otherwise UPS_NO_ERROR is + * returned. + * + * Hemisphere : Hemisphere either 'N' or 'S' (input) + * Easting : Easting/X in meters (input) + * Northing : Northing/Y in meters (input) + * Latitude : Latitude in radians (output) + * Longitude : Longitude in radians (output) + */ + long Convert_UPS_To_Geodetic(char Hemisphere, + double Easting, + double Northing, + double *Latitude, + double *Longitude)const; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUpspt.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUpspt.cpp new file mode 100644 index 0000000000..3f1a3c086a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUpspt.cpp @@ -0,0 +1,67 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// This is the Universal Polar Stereographic (UPS) point. Allows +// easy onversion between different coordinates. +//******************************************************************* +// $Id: ossimUpspt.cpp,v 1.2 2001/08/15 03:05:49 okramer Exp $ +#include "ossimUpspt.h" +#include "ossimUtmpt.h" +#include "ossimUps.h" + +#include "base/data_types/ossimGpt.h" +#include "base/data_types/ossimEcefPoint.h" +#include "base/data_types/ellipse/ossimEllipsoid.h" +#include "base/data_types/datum/ossimDatum.h" + +ossimUpspt::ossimUpspt(const ossimGpt &aPt) +{ + convertFromGeodetic(aPt); +} + +ossimUpspt::ossimUpspt(const ossimEcefPoint &aPt) +{ + convertFromGeodetic(ossimGpt(aPt)); +} + + +void ossimUpspt::convertFromGeodetic(const ossimGpt &aPt) +{ + const ossimDatum *aDatum = aPt.datum(); + + if(aDatum) + { + Set_UPS_Parameters(aDatum->ellipsoid()->a(), + aDatum->ellipsoid()->b()); + + Convert_Geodetic_To_UPS(aPt.latr(), + aPt.lonr(), + &theHemisphere, + &theEasting, + &theNorthing); + theDatum = const_cast<ossimDatum*>(aDatum); + } + else + { + //ERROR: should never happen + } +} diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUpspt.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUpspt.h new file mode 100644 index 0000000000..1b76b2066a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUpspt.h @@ -0,0 +1,56 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts(gpotts@imagelinks.com) +// +// Description: +// +// This is the Universal Polar Stereographic (UPS) point. Allows +// easy onversion between different coordinates. +//******************************************************************* +// $Id: ossimUpspt.h,v 1.2 2001/08/15 03:05:49 okramer Exp $ + +#ifndef ossimUpspt_HEADER +#define ossimUpspt_HEADER + +class ossimUtmpt; +class ossimGpt; +class ossimEcefPoint; +class ossimDatum; + +class ossimUpspt +{ +public: + ossimUpspt(const ossimGpt &aPt); + ossimUpspt(const ossimEcefPoint &aPt); + + char hemisphere()const{return theHemisphere;} + double easting()const {return theEasting;} + double northing()const{return theNorthing;} + const ossimDatum* datum()const{return theDatum;} + +private: + char theHemisphere; + double theEasting; + double theNorthing; + ossimDatum *theDatum; + + void convertFromGeodetic(const ossimGpt &aPt); +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUtm.c b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUtm.c new file mode 100644 index 0000000000..28867fdfb1 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUtm.c @@ -0,0 +1,337 @@ +/***************************************************************************/ +/* RSC IDENTIFIER: UTM + * + * ABSTRACT + * + * This component provides conversions between geodetic coordinates + * (latitude and longitudes) and Universal Transverse Mercator (UTM) + * projection (zone, hemisphere, easting, and northing) coordinates. + * + * ERROR HANDLING + * + * This component checks parameters for valid values. If an invalid value + * is found, the error code is combined with the current error code using + * the bitwise or. This combining allows multiple error codes to be + * returned. The possible error codes are: + * + * UTM_NO_ERROR : No errors occurred in function + * UTM_LAT_ERROR : Latitude outside of valid range + * (-80.5 to 84.5 degrees) + * UTM_LON_ERROR : Longitude outside of valid range + * (-180 to 360 degrees) + * UTM_EASTING_ERROR : Easting outside of valid range + * (100,000 to 900,000 meters) + * UTM_NORTHING_ERROR : Northing outside of valid range + * (0 to 10,000,000 meters) + * UTM_ZONE_ERROR : Zone outside of valid range (1 to 60) + * UTM_HEMISPHERE_ERROR : Invalid hemisphere ('N' or 'S') + * UTM_ZONE_OVERRIDE_ERROR: Zone outside of valid range + * (1 to 60) and within 1 of 'natural' zone + * UTM_A_ERROR : Semi-major axis less than or equal to zero + * UTM_INV_F_ERROR : Inverse flattening outside of valid range + * (250 to 350) + * + * REUSE NOTES + * + * UTM is intended for reuse by any application that performs a Universal + * Transverse Mercator (UTM) projection or its inverse. + * + * REFERENCES + * + * Further information on UTM can be found in the Reuse Manual. + * + * UTM originated from : U.S. Army Topographic Engineering Center + * Geospatial Information Division + * 7701 Telegraph Road + * Alexandria, VA 22310-3864 + * + * LICENSES + * + * None apply to this component. + * + * RESTRICTIONS + * + * UTM has no restrictions. + * + * ENVIRONMENT + * + * UTM was tested and certified in the following environments: + * + * 1. Solaris 2.5 with GCC, version 2.8.1 + * 2. MSDOS with MS Visual C++, version 6 + * + * MODIFICATIONS + * + * Date Description + * ---- ----------- + * 10-02-97 Original Code + * + */ + + +/***************************************************************************/ +/* + * INCLUDES + */ +#include "ossimTranmerc.h" +#include "ossimUtm.h" +/* + * tranmerc.h - Is used to convert transverse mercator coordinates + * utm.h - Defines the function prototypes for the utm module. + */ + + +/***************************************************************************/ +/* + * DEFINES + */ + +#define PI 3.14159265358979323e0 /* PI */ +#define MIN_LAT ( (-80.5 * PI) / 180.0 ) /* -80.5 degrees in radians */ +#define MAX_LAT ( (84.5 * PI) / 180.0 ) /* 84.5 degrees in radians */ +#define MIN_EASTING 100000 +#define MAX_EASTING 900000 +#define MIN_NORTHING 0 +#define MAX_NORTHING 10000000 + +/***************************************************************************/ +/* + * GLOBAL DECLARATIONS + */ + +static double UTM_a = 6378137.0; /* Semi-major axis of ellipsoid in meters */ +static double UTM_f = 1 / 298.257223563; /* Flattening of ellipsoid */ +static long UTM_Override = 0; /* Zone override flag */ + + +/***************************************************************************/ +/* + * FUNCTIONS + * + */ + +long Set_UTM_Parameters(double a, + double f, + long override) +{ +/* + * The function Set_UTM_Parameters receives the ellipsoid parameters and + * UTM zone override parameter as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the + * function, otherwise UTM_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * override : UTM override zone, zero indicates no override (input) + */ + + double inv_f = 1 / f; + long Error_Code = UTM_NO_ERROR; + + if (a <= 0.0) + { /* Semi-major axis must be greater than zero */ + Error_Code |= UTM_A_ERROR; + } + if ((inv_f < 250) || (inv_f > 350)) + { /* Inverse flattening must be between 250 and 350 */ + Error_Code |= UTM_INV_F_ERROR; + } + if ((override < 0) || (override > 60)) + { + Error_Code |= UTM_ZONE_OVERRIDE_ERROR; + } + if (!Error_Code) + { /* no errors */ + UTM_a = a; + UTM_f = f; + UTM_Override = override; + } + return (Error_Code); +} /* END OF Set_UTM_Parameters */ + + +void Get_UTM_Parameters(double *a, + double *f, + long *override) +{ +/* + * The function Get_UTM_Parameters returns the current ellipsoid + * parameters and UTM zone override parameter. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * override : UTM override zone, zero indicates no override (output) + */ + + *a = UTM_a; + *f = UTM_f; + *override = UTM_Override; +} /* END OF Get_UTM_Parameters */ + + +long Convert_Geodetic_To_UTM (double Latitude, + double Longitude, + long *Zone, + char *Hemisphere, + double *Easting, + double *Northing) +{ +/* + * The function Convert_Geodetic_To_UTM converts geodetic (latitude and + * longitude) coordinates to UTM projection (zone, hemisphere, easting and + * northing) coordinates according to the current ellipsoid and UTM zone + * override parameters. If any errors occur, the error code(s) are returned + * by the function, otherwise UTM_NO_ERROR is returned. + * + * Latitude : Latitude in radians (input) + * Longitude : Longitude in radians (input) + * Zone : UTM zone (output) + * Hemisphere : North or South hemisphere (output) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + + long Lat_Degrees; + long Long_Degrees; + long temp_zone; + long Error_Code = UTM_NO_ERROR; + double Origin_Latitude = 0; + double Central_Meridian = 0; + double False_Easting = 500000; + double False_Northing = 0; + double Scale = 0.9996; + + if ((Latitude < MIN_LAT) || (Latitude > MAX_LAT)) + { /* Latitude out of range */ + Error_Code |= UTM_LAT_ERROR; + } + if ((Longitude < -PI) || (Longitude > (2*PI))) + { /* Longitude out of range */ + Error_Code |= UTM_LON_ERROR; + } + if (!Error_Code) + { /* no errors */ + if (Longitude < 0) + Longitude += (2*PI); + Lat_Degrees = (long)(Latitude * 180.0 / PI); + Long_Degrees = (long)(Longitude * 180.0 / PI); + + if (Longitude < PI) + temp_zone = (long)(31 + ((Longitude * 180.0 / PI) / 6.0)); + else + temp_zone = (long)(((Longitude * 180.0 / PI) / 6.0) - 29); + if (temp_zone > 60) + temp_zone = 1; + /* UTM special cases */ + if ((Lat_Degrees > 55) && (Lat_Degrees < 64) && (Long_Degrees > -1) + && (Long_Degrees < 3)) + temp_zone = 31; + if ((Lat_Degrees > 55) && (Lat_Degrees < 64) && (Long_Degrees > 2) + && (Long_Degrees < 12)) + temp_zone = 32; + if ((Lat_Degrees > 71) && (Long_Degrees > -1) && (Long_Degrees < 9)) + temp_zone = 31; + if ((Lat_Degrees > 71) && (Long_Degrees > 8) && (Long_Degrees < 21)) + temp_zone = 33; + if ((Lat_Degrees > 71) && (Long_Degrees > 20) && (Long_Degrees < 33)) + temp_zone = 35; + if ((Lat_Degrees > 71) && (Long_Degrees > 32) && (Long_Degrees < 42)) + temp_zone = 37; + + if (UTM_Override) + { + if ((temp_zone == 1) && (UTM_Override == 60)) + temp_zone = UTM_Override; + else if ((temp_zone == 60) && (UTM_Override == 1)) + temp_zone = UTM_Override; + else if (((temp_zone-1) <= UTM_Override) && (UTM_Override <= (temp_zone+1))) + temp_zone = UTM_Override; + else + Error_Code = UTM_ZONE_OVERRIDE_ERROR; + } + if (!Error_Code) + { + if (temp_zone >= 31) + Central_Meridian = (6 * temp_zone - 183) * PI / 180.0; + else + Central_Meridian = (6 * temp_zone + 177) * PI / 180.0; + *Zone = temp_zone; + if (Latitude < 0) + { + False_Northing = 10000000; + *Hemisphere = 'S'; + } + else + *Hemisphere = 'N'; + Set_Transverse_Mercator_Parameters(UTM_a, UTM_f, Origin_Latitude, + Central_Meridian, False_Easting, False_Northing, Scale); + Convert_Geodetic_To_Transverse_Mercator(Latitude, Longitude, Easting, + Northing); + if ((*Easting < MIN_EASTING) || (*Easting > MAX_EASTING)) + Error_Code = UTM_EASTING_ERROR; + if ((*Northing < MIN_NORTHING) || (*Northing > MAX_NORTHING)) + Error_Code |= UTM_NORTHING_ERROR; + } + } /* END OF if (!Error_Code) */ + return (Error_Code); +} /* END OF Convert_Geodetic_To_UTM */ + + +long Convert_UTM_To_Geodetic(long Zone, + char Hemisphere, + double Easting, + double Northing, + double *Latitude, + double *Longitude) +{ +/* + * The function Convert_UTM_To_Geodetic converts UTM projection (zone, + * hemisphere, easting and northing) coordinates to geodetic(latitude + * and longitude) coordinates, according to the current ellipsoid + * parameters. If any errors occur, the error code(s) are returned + * by the function, otherwise UTM_NO_ERROR is returned. + * + * Zone : UTM zone (input) + * Hemisphere : North or South hemisphere (input) + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude in radians (output) + * Longitude : Longitude in radians (output) + */ + long Error_Code = UTM_NO_ERROR; + double Origin_Latitude = 0; + double Central_Meridian = 0; + double False_Easting = 500000; + double False_Northing = 0; + double Scale = 0.9996; + + if ((Zone < 1) || (Zone > 60)) + Error_Code |= UTM_ZONE_ERROR; + if ((Hemisphere != 'S') && (Hemisphere != 'N')) + Error_Code |= UTM_HEMISPHERE_ERROR; + if ((Easting < MIN_EASTING) || (Easting > MAX_EASTING)) + Error_Code |= UTM_EASTING_ERROR; + if ((Northing < MIN_NORTHING) || (Northing > MAX_NORTHING)) + Error_Code |= UTM_NORTHING_ERROR; + if (!Error_Code) + { /* no errors */ + if (Zone >= 31) + Central_Meridian = ((6 * Zone - 183) * PI / 180.0 + 0.00000005); + else + Central_Meridian = ((6 * Zone + 177) * PI / 180.0 + 0.00000005); + if (Hemisphere == 'S') + False_Northing = 10000000; + Set_Transverse_Mercator_Parameters(UTM_a, UTM_f, Origin_Latitude, + Central_Meridian, False_Easting, False_Northing, Scale); + if (Convert_Transverse_Mercator_To_Geodetic(Easting, + Northing, + Latitude, + Longitude)) + Error_Code |= UTM_NORTHING_ERROR; + if ((*Latitude < MIN_LAT) || (*Latitude > MAX_LAT)) + { /* Latitude out of range */ + Error_Code |= UTM_NORTHING_ERROR; + } + } + return (Error_Code); +} /* END OF Convert_UTM_To_Geodetic */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUtm.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUtm.h new file mode 100644 index 0000000000..0b32051b86 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUtm.h @@ -0,0 +1,178 @@ +#ifndef UTM_H + #define UTM_H + +/***************************************************************************/ +/* RSC IDENTIFIER: UTM + * + * ABSTRACT + * + * This component provides conversions between geodetic coordinates + * (latitude and longitudes) and Universal Transverse Mercator (UTM) + * projection (zone, hemisphere, easting, and northing) coordinates. + * + * ERROR HANDLING + * + * This component checks parameters for valid values. If an invalid value + * is found, the error code is combined with the current error code using + * the bitwise or. This combining allows multiple error codes to be + * returned. The possible error codes are: + * + * UTM_NO_ERROR : No errors occurred in function + * UTM_LAT_ERROR : Latitude outside of valid range + * (-80.5 to 84.5 degrees) + * UTM_LON_ERROR : Longitude outside of valid range + * (-180 to 360 degrees) + * UTM_EASTING_ERROR : Easting outside of valid range + * (100,000 to 900,000 meters) + * UTM_NORTHING_ERROR : Northing outside of valid range + * (0 to 10,000,000 meters) + * UTM_ZONE_ERROR : Zone outside of valid range (1 to 60) + * UTM_HEMISPHERE_ERROR : Invalid hemisphere ('N' or 'S') + * UTM_ZONE_OVERRIDE_ERROR: Zone outside of valid range + * (1 to 60) and within 1 of 'natural' zone + * UTM_A_ERROR : Semi-major axis less than or equal to zero + * UTM_INV_F_ERROR : Inverse flattening outside of valid range + * (250 to 350) + * + * REUSE NOTES + * + * UTM is intended for reuse by any application that performs a Universal + * Transverse Mercator (UTM) projection or its inverse. + * + * REFERENCES + * + * Further information on UTM can be found in the Reuse Manual. + * + * UTM originated from : U.S. Army Topographic Engineering Center + * Geospatial Information Division + * 7701 Telegraph Road + * Alexandria, VA 22310-3864 + * + * LICENSES + * + * None apply to this component. + * + * RESTRICTIONS + * + * UTM has no restrictions. + * + * ENVIRONMENT + * + * UTM was tested and certified in the following environments: + * + * 1. Solaris 2.5 with GCC, version 2.8.1 + * 2. MSDOS with MS Visual C++, version 6 + * + * MODIFICATIONS + * + * Date Description + * ---- ----------- + * 10-02-97 Original Code + * + */ + + +/***************************************************************************/ +/* + * DEFINES + */ + + #define UTM_NO_ERROR 0x0000 + #define UTM_LAT_ERROR 0x0001 + #define UTM_LON_ERROR 0x0002 + #define UTM_EASTING_ERROR 0x0004 + #define UTM_NORTHING_ERROR 0x0008 + #define UTM_ZONE_ERROR 0x0010 + #define UTM_HEMISPHERE_ERROR 0x0020 + #define UTM_ZONE_OVERRIDE_ERROR 0x0040 + #define UTM_A_ERROR 0x0080 + #define UTM_INV_F_ERROR 0x0100 + + +/***************************************************************************/ +/* + * FUNCTION PROTOTYPES + * for UTM.C + */ + +/* ensure proper linkage to c++ programs */ + #ifdef __cplusplus +extern "C" { + #endif + + long Set_UTM_Parameters(double a, + double f, + long override); +/* + * The function Set_UTM_Parameters receives the ellipsoid parameters and + * UTM zone override parameter as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the + * function, otherwise UTM_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * override : UTM override zone, zero indicates no override (input) + */ + + + void Get_UTM_Parameters(double *a, + double *f, + long *override); +/* + * The function Get_UTM_Parameters returns the current ellipsoid + * parameters and UTM zone override parameter. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * override : UTM override zone, zero indicates no override (output) + */ + + + long Convert_Geodetic_To_UTM (double Latitude, + double Longitude, + long *Zone, + char *Hemisphere, + double *Easting, + double *Northing); +/* + * The function Convert_Geodetic_To_UTM converts geodetic (latitude and + * longitude) coordinates to UTM projection (zone, hemisphere, easting and + * northing) coordinates according to the current ellipsoid and UTM zone + * override parameters. If any errors occur, the error code(s) are returned + * by the function, otherwise UTM_NO_ERROR is returned. + * + * Latitude : Latitude in radians (input) + * Longitude : Longitude in radians (input) + * Zone : UTM zone (output) + * Hemisphere : North or South hemisphere (output) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + + + long Convert_UTM_To_Geodetic(long Zone, + char Hemisphere, + double Easting, + double Northing, + double *Latitude, + double *Longitude); +/* + * The function Convert_UTM_To_Geodetic converts UTM projection (zone, + * hemisphere, easting and northing) coordinates to geodetic(latitude + * and longitude) coordinates, according to the current ellipsoid + * parameters. If any errors occur, the error code(s) are returned + * by the function, otherwise UTM_NO_ERROR is returned. + * + * Zone : UTM zone (input) + * Hemisphere : North or South hemisphere (input) + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude in radians (output) + * Longitude : Longitude in radians (output) + */ + + #ifdef __cplusplus +} + #endif + +#endif /* UTM_H */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUtmProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUtmProjection.cpp new file mode 100644 index 0000000000..4b6f66f70d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUtmProjection.cpp @@ -0,0 +1,892 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +// Calls Geotrans Utm projection code. +//******************************************************************* +// $Id: ossimUtmProjection.cpp,v 1.40 2005/09/09 19:23:58 gpotts Exp $ +#include <cmath> +using namespace std; + +#include <projections/map_projections/ossimUtmProjection.h> +#include <base/common/ossimKeywordNames.h> +#include <base/data_types/ossimKeywordlist.h> + +RTTI_DEF1(ossimUtmProjection, "ossimUtmProjection", ossimMapProjection) + +/******************************* DEFINES *********************************/ + +#define UTM_NO_ERROR 0x0000 +#define UTM_LAT_ERROR 0x0001 +#define UTM_LON_ERROR 0x0002 +#define UTM_EASTING_ERROR 0x0004 +#define UTM_NORTHING_ERROR 0x0008 +#define UTM_ZONE_ERROR 0x0010 +#define UTM_HEMISPHERE_ERROR 0x0020 +#define UTM_ZONE_OVERRIDE_ERROR 0x0040 +#define UTM_A_ERROR 0x0080 +#define UTM_B_ERROR 0x0100 +#define UTM_A_LESS_B_ERROR 0x0200 + +#define MIN_LAT ( (-80.5 * M_PI) / 180.0 ) /* -80.5 degrees in radians */ +#define MAX_LAT ( (84.5 * M_PI) / 180.0 ) /* 84.5 degrees in radians */ +#define MAX_DELTA_LONG ((M_PI * 90.0)/180.0) /* 90 degrees in radians */ +#define MIN_EASTING 100000 +#define MAX_EASTING 900000 +#define MIN_NORTHING 0 +#define MAX_NORTHING 10000000 +#define MIN_SCALE_FACTOR 0.3 +#define MAX_SCALE_FACTOR 3.0 + +#define SPHTMD(Latitude) ((double) (theTranMerc_ap * Latitude \ + - theTranMerc_bp * sin(2.e0 * Latitude) + theTranMerc_cp * sin(4.e0 * Latitude) \ + - theTranMerc_dp * sin(6.e0 * Latitude) + theTranMerc_ep * sin(8.e0 * Latitude) ) ) + +#define SPHSN(Latitude) ((double) (getA() / sqrt( 1.e0 - theTranMerc_es * \ + pow(sin(Latitude), 2)))) + +#define SPHSR(Latitude) ((double) (getA() * (1.e0 - theTranMerc_es) / \ + pow(DENOM(Latitude), 3))) + +#define DENOM(Latitude) ((double) (sqrt(1.e0 - theTranMerc_es * pow(sin(Latitude),2)))) + + +ossimUtmProjection::ossimUtmProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + : + ossimMapProjection(ellipsoid, origin), + theTranMerc_a(6378137.0), + theTranMerc_f(1.0/298.257223563), + theTranMerc_es(0.0066943799901413800), + theTranMerc_ebs(0.0067394967565869), + theTranMerc_Origin_Lat(0.0), + theTranMerc_Origin_Long(0.0), + theTranMerc_False_Northing(0.0), + theTranMerc_False_Easting(500000.0), + theTranMerc_Scale_Factor(0.9996), + theTranMerc_ap(6367449.1458008), + theTranMerc_bp(16038.508696861), + theTranMerc_cp(16.832613334334), + theTranMerc_dp(0.021984404273757), + theTranMerc_Delta_Easting(40000000.0), + theTranMerc_Delta_Northing(40000000.0), + theZone(1), + theHemisphere('N') + +{ + setZone(origin); + update(); +} + +ossimUtmProjection::ossimUtmProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + long zone, + char hemisphere) + : + ossimMapProjection(ellipsoid, origin), + theTranMerc_a(6378137.0), + theTranMerc_f(1.0/298.257223563), + theTranMerc_es(0.0066943799901413800), + theTranMerc_ebs(0.0067394967565869), + theTranMerc_Origin_Lat(0.0), + theTranMerc_Origin_Long(0.0), + theTranMerc_False_Northing(0.0), + theTranMerc_False_Easting(500000.0), + theTranMerc_Scale_Factor(0.9996), + theTranMerc_ap(6367449.1458008), + theTranMerc_bp(16038.508696861), + theTranMerc_cp(16.832613334334), + theTranMerc_dp(0.021984404273757), + theTranMerc_Delta_Easting(40000000.0), + theTranMerc_Delta_Northing(40000000.0), + theZone(zone), + theHemisphere('N') +{ + setZone(zone); + setHemisphere(hemisphere); + update(); +} + +ossimUtmProjection::ossimUtmProjection(long zone) + : + ossimMapProjection(), + theTranMerc_a(6378137.0), + theTranMerc_f(1.0/298.257223563), + theTranMerc_es(0.0066943799901413800), + theTranMerc_ebs(0.0067394967565869), + theTranMerc_Origin_Lat(0.0), + theTranMerc_Origin_Long(0.0), + theTranMerc_False_Northing(0.0), + theTranMerc_False_Easting(500000.0), + theTranMerc_Scale_Factor(0.9996), + theTranMerc_ap(6367449.1458008), + theTranMerc_bp(16038.508696861), + theTranMerc_cp(16.832613334334), + theTranMerc_dp(0.021984404273757), + theTranMerc_Delta_Easting(40000000.0), + theTranMerc_Delta_Northing(40000000.0), + theZone(zone), + theHemisphere('N') +{ + setZone(zone); + theOrigin.lond(computeZoneMeridian(theZone)); + update(); +} + +ossimUtmProjection::ossimUtmProjection(const ossimUtmProjection& src) + :ossimMapProjection(src), + theTranMerc_a(src.theTranMerc_a), + theTranMerc_f(src.theTranMerc_f), + theTranMerc_es(src.theTranMerc_es), + theTranMerc_ebs(src.theTranMerc_ebs), + theTranMerc_Origin_Lat(src.theTranMerc_Origin_Lat), + theTranMerc_Origin_Long(src.theTranMerc_Origin_Long), + theTranMerc_False_Northing(src.theTranMerc_False_Northing), + theTranMerc_False_Easting(src.theTranMerc_False_Easting), + theTranMerc_Scale_Factor(src.theTranMerc_Scale_Factor), + theTranMerc_ap(src.theTranMerc_ap), + theTranMerc_bp(src.theTranMerc_bp), + theTranMerc_cp(src.theTranMerc_cp), + theTranMerc_dp(src.theTranMerc_dp), + theTranMerc_Delta_Easting(src.theTranMerc_Delta_Easting), + theTranMerc_Delta_Northing(src.theTranMerc_Delta_Northing), + theZone(src.theZone), + theHemisphere(src.theHemisphere) +{ +} + +void ossimUtmProjection::update() +{ + Set_Transverse_Mercator_Parameters(theEllipsoid.getA(), + theEllipsoid.getFlattening(), + theOrigin.latr(), + theOrigin.lonr(), + theTranMerc_False_Easting, + theTranMerc_False_Northing, + theTranMerc_Scale_Factor); + + ossimMapProjection::update(); +} + +ossimGpt ossimUtmProjection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat = 0.0; + double lon = 0.0; + + Convert_Transverse_Mercator_To_Geodetic(eastingNorthing.x, + eastingNorthing.y, + &lat, + &lon); + + return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum); +} + +ossimDpt ossimUtmProjection::forward(const ossimGpt &latLon)const +{ + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + Convert_Geodetic_To_Transverse_Mercator(gpt.latr(), + gpt.lonr(), + &easting, + &northing); + + return ossimDpt(easting, northing); +} + +ossimObject* ossimUtmProjection::dup()const +{ + ossimUtmProjection* proj = new ossimUtmProjection(*this); + + //--- + // TEMP: + // Set the projection up correctly. + // Note: The setZone sets the origin, but does not set all parameter + // needed; hence, the setZone, setOrigin. + //--- + proj->setZone(theZone); + proj->setOrigin(proj->origin()); + proj->setUlGpt(proj->origin()); + return proj; +} + +long ossimUtmProjection::getZone() const +{ + return theZone; +} + +char ossimUtmProjection::getHemisphere() const +{ + return theHemisphere; +} + +void ossimUtmProjection::setZone(const ossimGpt& ground) +{ + theZone = computeZone(ground); + theOrigin.lond(computeZoneMeridian(theZone)); + theOrigin.latd(0.0); + theTranMerc_Origin_Long = theOrigin.lonr(); + char hemisphere = theOrigin.latd() < 0.0?'S':'N'; + setHemisphere(hemisphere); +} + +void ossimUtmProjection::setZone(long zone) +{ + if(ossimIsNan(zone)) + { + theZone = computeZone(theOrigin); + } + else + { + theZone = zone; + } + theOrigin.lond(computeZoneMeridian(theZone)); + theOrigin.latd(0); + theTranMerc_Origin_Long = theOrigin.lonr(); +} + +void ossimUtmProjection::setHemisphere(char hemisphere) +{ + hemisphere = toupper(hemisphere); + if((hemisphere != 'N') && + (hemisphere != 'S')) + { + theHemisphere = theOrigin.latd() < 0?'S':'N'; + } + else + { + theHemisphere = hemisphere; + } + + if (theHemisphere == 'N') + { + theTranMerc_False_Northing = 0.0; + } + else + { + theTranMerc_False_Northing = 10000000.0; + } +} + +long ossimUtmProjection::computeZone(const ossimGpt& ground) +{ + long result = 0; + + double longitude = ground.lonr(); + double lat_Degrees = (long)( (ground.latd()) + 0.00000005); + double long_Degrees = (long)( (ground.lond()) + 0.00000005); + + if (longitude < M_PI) + result = (long)( (31 + ((180 * longitude) / (6 * M_PI)) ) + 0.00000005); + else + result = (long)( (((180 * longitude) / (6 * M_PI)) - 29) + 0.00000005); + if (result > 60) + result = 1; + /* UTM special cases */ + if ((lat_Degrees > 55) && (lat_Degrees < 64) && (long_Degrees > -1) + && (long_Degrees < 3)) + result = 31; + if ((lat_Degrees > 55) && (lat_Degrees < 64) && (long_Degrees > 2) + && (long_Degrees < 12)) + result = 32; + if ((lat_Degrees > 71) && (long_Degrees > -1) && (long_Degrees < 9)) + result = 31; + if ((lat_Degrees > 71) && (long_Degrees > 8) && (long_Degrees < 21)) + result = 33; + if ((lat_Degrees > 71) && (long_Degrees > 20) && (long_Degrees < 33)) + result = 35; + if ((lat_Degrees > 71) && (long_Degrees > 32) && (long_Degrees < 42)) + result = 37; + + return result; +} + +double ossimUtmProjection::computeZoneMeridian(long zone) +{ + return (6.0 * zone - 183.0);; +} + +bool ossimUtmProjection::operator==(const ossimProjection& projection) const +{ + if(ossimMapProjection::operator==(projection)) + { + ossimUtmProjection* utm = PTR_CAST(ossimUtmProjection, &projection); + if(utm) + { + return ((theZone == utm->theZone)&& + (theHemisphere == utm->theHemisphere)); + } + } + + return false; +} + +bool ossimUtmProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + const char* zone = kwl.find(prefix, ossimKeywordNames::ZONE_KW); + const char* hemisphere = kwl.find(prefix, ossimKeywordNames::HEMISPHERE_KW); + + ossimMapProjection::loadState(kwl, prefix); + + // initialize zone to a dummy value. + // + theZone = OSSIM_LONG_NAN; +// if(ossimString(type) == STATIC_TYPE_NAME(ossimUtmProjection)) + { + if(!zone) + { + theZone = computeZone(theOrigin); + } + else if (zone) + { + theZone = atoi(zone); + + if(theZone < 1) + { + theZone = computeZone(theOrigin); + } + else + { +// if(!kwl.find(prefix, ossimKeywordNames::CENTRAL_MERIDIAN_KW)) +// { + theOrigin.lond(computeZoneMeridian(theZone)); +// } +// if(!kwl.find(prefix, ossimKeywordNames::ORIGIN_LATITUDE_KW)) +// { + theOrigin.latd(0); +// } + } + } + if (hemisphere) + { + ossimString s = hemisphere; + s = s.trim(); + s = s.upcase(); + + setHemisphere(*s.c_str()); + } + else + { + char hemisphere = theOrigin.latd()<0?'S':'N'; + setHemisphere(hemisphere); + } + } + + update(); + + return true; +} + +bool ossimUtmProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const +{ + kwl.add(prefix, + ossimKeywordNames::ZONE_KW, + theZone, + true); + + kwl.add(prefix, + ossimKeywordNames::HEMISPHERE_KW, + theHemisphere, + true); + + return ossimMapProjection::saveState(kwl, prefix); +} + +long ossimUtmProjection::Set_Transverse_Mercator_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing, + double Scale_Factor) + +{ /* BEGIN Set_Tranverse_Mercator_Parameters */ + /* + * The function Set_Tranverse_Mercator_Parameters receives the ellipsoid + * parameters and Tranverse Mercator projection parameters as inputs, and + * sets the corresponding state variables. If any errors occur, the error + * code(s) are returned by the function, otherwise UTM_NO_ERROR is + * returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at the origin of the (input) + * projection + * Central_Meridian : Longitude in radians at the center of the (input) + * projection + * False_Easting : Easting/X at the center of the projection (input) + * False_Northing : Northing/Y at the center of the projection (input) + * Scale_Factor : Projection scale factor (input) + */ + + double tn; /* True Meridianal distance constant */ + double tn2; + double tn3; + double tn4; + double tn5; + double dummy_northing; + double TranMerc_b; /* Semi-minor axis of ellipsoid, in meters */ +// double inv_f = 1 / f; + long Error_Code = UTM_NO_ERROR; + +// if (a <= 0.0) +// { /* Semi-major axis must be greater than zero */ +// Error_Code |= UTM_A_ERROR; +// } +// if ((inv_f < 250) || (inv_f > 350)) +// { /* Inverse flattening must be between 250 and 350 */ +// Error_Code |= UTM_INV_F_ERROR; +// } +// if ((Origin_Latitude < -MAX_LAT) || (Origin_Latitude > MAX_LAT)) +// { /* origin latitude out of range */ +// Error_Code |= UTM_ORIGIN_LAT_ERROR; +// } +// if ((Central_Meridian < -M_PI) || (Central_Meridian > TWO_PI)) +// { /* origin longitude out of range */ +// Error_Code |= UTM_CENT_MER_ERROR; +// } +// if ((Scale_Factor < MIN_SCALE_FACTOR) || (Scale_Factor > MAX_SCALE_FACTOR)) +// { +// Error_Code |= UTM_SCALE_FACTOR_ERROR; +// } + if (!Error_Code) + { /* no errors */ + theTranMerc_a = a; + theTranMerc_f = f; + theTranMerc_Origin_Lat = 0; + theTranMerc_Origin_Long = 0; + theTranMerc_False_Northing = 0; + theTranMerc_False_Easting = 0; + // theTranMerc_Scale_Factor = 1; + + /* Eccentricity Squared */ + theTranMerc_es = 2 * theTranMerc_f - theTranMerc_f * theTranMerc_f; + /* Second Eccentricity Squared */ + theTranMerc_ebs = (1 / (1 - theTranMerc_es)) - 1; + + TranMerc_b = theTranMerc_a * (1 - theTranMerc_f); + /*True meridianal constants */ + tn = (theTranMerc_a - TranMerc_b) / (theTranMerc_a + TranMerc_b); + tn2 = tn * tn; + tn3 = tn2 * tn; + tn4 = tn3 * tn; + tn5 = tn4 * tn; + + theTranMerc_ap = theTranMerc_a * (1.e0 - tn + 5.e0 * (tn2 - tn3)/4.e0 + + 81.e0 * (tn4 - tn5)/64.e0 ); + theTranMerc_bp = 3.e0 * theTranMerc_a * (tn - tn2 + 7.e0 * (tn3 - tn4) + /8.e0 + 55.e0 * tn5/64.e0 )/2.e0; + theTranMerc_cp = 15.e0 * theTranMerc_a * (tn2 - tn3 + 3.e0 * (tn4 - tn5 )/4.e0) /16.0; + theTranMerc_dp = 35.e0 * theTranMerc_a * (tn3 - tn4 + 11.e0 * tn5 / 16.e0) / 48.e0; + theTranMerc_ep = 315.e0 * theTranMerc_a * (tn4 - tn5) / 512.e0; + Convert_Geodetic_To_Transverse_Mercator(MAX_LAT, + MAX_DELTA_LONG, + &theTranMerc_Delta_Easting, + &theTranMerc_Delta_Northing); + Convert_Geodetic_To_Transverse_Mercator(0, + MAX_DELTA_LONG, + &theTranMerc_Delta_Easting, + &dummy_northing); + theTranMerc_Origin_Lat = Origin_Latitude; + if (Central_Meridian > M_PI) + Central_Meridian -= TWO_PI; + theTranMerc_Origin_Long = Central_Meridian; + theTranMerc_False_Northing = False_Northing; + theTranMerc_False_Easting = False_Easting; + // theTranMerc_Scale_Factor = Scale_Factor; + } /* END OF if(!Error_Code) */ + return (Error_Code); +} /* END of Set_Transverse_Mercator_Parameters */ + + +void ossimUtmProjection::Get_Transverse_Mercator_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *False_Easting, + double *False_Northing, + double *Scale_Factor)const + +{ /* BEGIN Get_Tranverse_Mercator_Parameters */ + /* + * The function Get_Transverse_Mercator_Parameters returns the current + * ellipsoid and Transverse Mercator projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at the origin of the (output) + * projection + * Central_Meridian : Longitude in radians at the center of the (output) + * projection + * False_Easting : Easting/X at the center of the projection (output) + * False_Northing : Northing/Y at the center of the projection (output) + * Scale_Factor : Projection scale factor (output) + */ + + *a = theTranMerc_a; + *f = theTranMerc_f; + *Origin_Latitude = theTranMerc_Origin_Lat; + *Central_Meridian = theTranMerc_Origin_Long; + *False_Easting = theTranMerc_False_Easting; + *False_Northing = theTranMerc_False_Northing; + *Scale_Factor = theTranMerc_Scale_Factor; + + return; +} /* END OF Get_Tranverse_Mercator_Parameters */ + + + +long ossimUtmProjection::Convert_Geodetic_To_Transverse_Mercator (double Latitude, + double Longitude, + double *Easting, + double *Northing)const + +{ /* BEGIN Convert_Geodetic_To_Transverse_Mercator */ + + /* + * The function Convert_Geodetic_To_Transverse_Mercator converts geodetic + * (latitude and longitude) coordinates to Transverse Mercator projection + * (easting and northing) coordinates, according to the current ellipsoid + * and Transverse Mercator projection coordinates. If any errors occur, the + * error code(s) are returned by the function, otherwise UTM_NO_ERROR is + * returned. + * + * Latitude : Latitude in radians (input) + * Longitude : Longitude in radians (input) + * Easting : Easting/X in meters (output) + * Northing : Northing/Y in meters (output) + */ + + double c; /* Cosine of latitude */ + double c2; + double c3; + double c5; + double c7; + double dlam; /* Delta longitude - Difference in Longitude */ + double eta; /* constant - theTranMerc_ebs *c *c */ + double eta2; + double eta3; + double eta4; + double s; /* Sine of latitude */ + double sn; /* Radius of curvature in the prime vertical */ + double t; /* Tangent of latitude */ + double tan2; + double tan3; + double tan4; + double tan5; + double tan6; + double t1; /* Term in coordinate conversion formula - GP to Y */ + double t2; /* Term in coordinate conversion formula - GP to Y */ + double t3; /* Term in coordinate conversion formula - GP to Y */ + double t4; /* Term in coordinate conversion formula - GP to Y */ + double t5; /* Term in coordinate conversion formula - GP to Y */ + double t6; /* Term in coordinate conversion formula - GP to Y */ + double t7; /* Term in coordinate conversion formula - GP to Y */ + double t8; /* Term in coordinate conversion formula - GP to Y */ + double t9; /* Term in coordinate conversion formula - GP to Y */ + double tmd; /* True Meridional distance */ + double tmdo; /* True Meridional distance for latitude of origin */ + long Error_Code = UTM_NO_ERROR; +// double temp_Origin; +// double temp_Long; + +// if ((Latitude < -MAX_LAT) || (Latitude > MAX_LAT)) +// { /* Latitude out of range */ +// Error_Code|= UTM_LAT_ERROR; +// } + if (Longitude > M_PI) + Longitude -= TWO_PI; +// if ((Longitude < (theTranMerc_Origin_Long - MAX_DELTA_LONG)) +// || (Longitude > (theTranMerc_Origin_Long + MAX_DELTA_LONG))) +// { +// if (Longitude < 0) +// temp_Long = Longitude + TWO_PI; +// else +// temp_Long = Longitude; +// if (theTranMerc_Origin_Long < 0) +// temp_Origin = theTranMerc_Origin_Long + TWO_PI; +// else +// temp_Origin = theTranMerc_Origin_Long; +// if ((temp_Long < (temp_Origin - MAX_DELTA_LONG)) +// || (temp_Long > (temp_Origin + MAX_DELTA_LONG))) +// Error_Code|= UTM_LON_ERROR; +// } + if (!Error_Code) + { /* no errors */ + + /* + * Delta Longitude + */ + dlam = Longitude - theTranMerc_Origin_Long; + +// if (fabs(dlam) > (9.0 * M_PI / 180)) +// { /* Distortion will result if Longitude is more than 9 degrees from the Central Meridian */ +// Error_Code |= UTM_LON_WARNING; +// } + + if (dlam > M_PI) + dlam -= TWO_PI; + if (dlam < -M_PI) + dlam += TWO_PI; + if (fabs(dlam) < 2.e-10) + dlam = 0.0; + + s = sin(Latitude); + c = cos(Latitude); + c2 = c * c; + c3 = c2 * c; + c5 = c3 * c2; + c7 = c5 * c2; + t = tan (Latitude); + tan2 = t * t; + tan3 = tan2 * t; + tan4 = tan3 * t; + tan5 = tan4 * t; + tan6 = tan5 * t; + eta = theTranMerc_ebs * c2; + eta2 = eta * eta; + eta3 = eta2 * eta; + eta4 = eta3 * eta; + + /* radius of curvature in prime vertical */ + sn = SPHSN(Latitude); + + /* True Meridianal Distances */ + tmd = SPHTMD(Latitude); + + /* Origin */ + tmdo = SPHTMD (theTranMerc_Origin_Lat); + + /* northing */ + t1 = (tmd - tmdo) * theTranMerc_Scale_Factor; + t2 = sn * s * c * theTranMerc_Scale_Factor/ 2.e0; + t3 = sn * s * c3 * theTranMerc_Scale_Factor * (5.e0 - tan2 + 9.e0 * eta + + 4.e0 * eta2) /24.e0; + + t4 = sn * s * c5 * theTranMerc_Scale_Factor * (61.e0 - 58.e0 * tan2 + + tan4 + 270.e0 * eta - 330.e0 * tan2 * eta + 445.e0 * eta2 + + 324.e0 * eta3 -680.e0 * tan2 * eta2 + 88.e0 * eta4 + -600.e0 * tan2 * eta3 - 192.e0 * tan2 * eta4) / 720.e0; + + t5 = sn * s * c7 * theTranMerc_Scale_Factor * (1385.e0 - 3111.e0 * + tan2 + 543.e0 * tan4 - tan6) / 40320.e0; + + *Northing = theTranMerc_False_Northing + t1 + pow(dlam,2.e0) * t2 + + pow(dlam,4.e0) * t3 + pow(dlam,6.e0) * t4 + + pow(dlam,8.e0) * t5; + + /* Easting */ + t6 = sn * c * theTranMerc_Scale_Factor; + t7 = sn * c3 * theTranMerc_Scale_Factor * (1.e0 - tan2 + eta ) /6.e0; + t8 = sn * c5 * theTranMerc_Scale_Factor * (5.e0 - 18.e0 * tan2 + tan4 + + 14.e0 * eta - 58.e0 * tan2 * eta + 13.e0 * eta2 + 4.e0 * eta3 + - 64.e0 * tan2 * eta2 - 24.e0 * tan2 * eta3 )/ 120.e0; + t9 = sn * c7 * theTranMerc_Scale_Factor * ( 61.e0 - 479.e0 * tan2 + + 179.e0 * tan4 - tan6 ) /5040.e0; + + *Easting = theTranMerc_False_Easting + dlam * t6 + pow(dlam,3.e0) * t7 + + pow(dlam,5.e0) * t8 + pow(dlam,7.e0) * t9; + } + return (Error_Code); +} /* END OF Convert_Geodetic_To_Transverse_Mercator */ + + +long ossimUtmProjection::Convert_Transverse_Mercator_To_Geodetic (double Easting, + double Northing, + double *Latitude, + double *Longitude)const +{ /* BEGIN Convert_Transverse_Mercator_To_Geodetic */ + + /* + * The function Convert_Transverse_Mercator_To_Geodetic converts Transverse + * Mercator projection (easting and northing) coordinates to geodetic + * (latitude and longitude) coordinates, according to the current ellipsoid + * and Transverse Mercator projection parameters. If any errors occur, the + * error code(s) are returned by the function, otherwise UTM_NO_ERROR is + * returned. + * + * Easting : Easting/X in meters (input) + * Northing : Northing/Y in meters (input) + * Latitude : Latitude in radians (output) + * Longitude : Longitude in radians (output) + */ + + double c; /* Cosine of latitude */ + double de; /* Delta easting - Difference in Easting (Easting-Fe) */ + double dlam; /* Delta longitude - Difference in Longitude */ + double eta; /* constant - theTranMerc_ebs *c *c */ + double eta2; + double eta3; + double eta4; + double ftphi; /* Footpoint latitude */ + int i; /* Loop iterator */ + double s; /* Sine of latitude */ + double sn; /* Radius of curvature in the prime vertical */ + double sr; /* Radius of curvature in the meridian */ + double t; /* Tangent of latitude */ + double tan2; + double tan4; + double t10; /* Term in coordinate conversion formula - GP to Y */ + double t11; /* Term in coordinate conversion formula - GP to Y */ + double t12; /* Term in coordinate conversion formula - GP to Y */ + double t13; /* Term in coordinate conversion formula - GP to Y */ + double t14; /* Term in coordinate conversion formula - GP to Y */ + double t15; /* Term in coordinate conversion formula - GP to Y */ + double t16; /* Term in coordinate conversion formula - GP to Y */ + double t17; /* Term in coordinate conversion formula - GP to Y */ + double tmd; /* True Meridional distance */ + double tmdo; /* True Meridional distance for latitude of origin */ + long Error_Code = UTM_NO_ERROR; + +// if ((Easting < (theTranMerc_False_Easting - theTranMerc_Delta_Easting)) +// ||(Easting > (theTranMerc_False_Easting + theTranMerc_Delta_Easting))) +// { /* Easting out of range */ +// Error_Code |= UTM_EASTING_ERROR; +// } +// if ((Northing < (theTranMerc_False_Northing - theTranMerc_Delta_Northing)) +// || (Northing > (theTranMerc_False_Northing + theTranMerc_Delta_Northing))) +// { /* Northing out of range */ +// Error_Code |= UTM_NORTHING_ERROR; +// } + + if (!Error_Code) + { + /* True Meridional Distances for latitude of origin */ + tmdo = SPHTMD(theTranMerc_Origin_Lat); + + /* Origin */ + tmd = tmdo + (Northing - theTranMerc_False_Northing) / theTranMerc_Scale_Factor; + + /* First Estimate */ + sr = SPHSR(0.e0); + ftphi = tmd/sr; + + for (i = 0; i < 5 ; i++) + { + t10 = SPHTMD (ftphi); + sr = SPHSR(ftphi); + ftphi = ftphi + (tmd - t10) / sr; + } + + /* Radius of Curvature in the meridian */ + sr = SPHSR(ftphi); + + /* Radius of Curvature in the meridian */ + sn = SPHSN(ftphi); + + /* Sine Cosine terms */ + s = sin(ftphi); + c = cos(ftphi); + + /* Tangent Value */ + t = tan(ftphi); + tan2 = t * t; + tan4 = tan2 * tan2; + eta = theTranMerc_ebs * pow(c,2); + eta2 = eta * eta; + eta3 = eta2 * eta; + eta4 = eta3 * eta; + de = Easting - theTranMerc_False_Easting; + if (fabs(de) < 0.0001) + de = 0.0; + + /* Latitude */ + t10 = t / (2.e0 * sr * sn * pow(theTranMerc_Scale_Factor, 2)); + t11 = t * (5.e0 + 3.e0 * tan2 + eta - 4.e0 * pow(eta,2) + - 9.e0 * tan2 * eta) / (24.e0 * sr * pow(sn,3) + * pow(theTranMerc_Scale_Factor,4)); + t12 = t * (61.e0 + 90.e0 * tan2 + 46.e0 * eta + 45.E0 * tan4 + - 252.e0 * tan2 * eta - 3.e0 * eta2 + 100.e0 + * eta3 - 66.e0 * tan2 * eta2 - 90.e0 * tan4 + * eta + 88.e0 * eta4 + 225.e0 * tan4 * eta2 + + 84.e0 * tan2* eta3 - 192.e0 * tan2 * eta4) + / ( 720.e0 * sr * pow(sn,5) * pow(theTranMerc_Scale_Factor, 6) ); + t13 = t * ( 1385.e0 + 3633.e0 * tan2 + 4095.e0 * tan4 + 1575.e0 + * pow(t,6))/ (40320.e0 * sr * pow(sn,7) * pow(theTranMerc_Scale_Factor,8)); + *Latitude = ftphi - pow(de,2) * t10 + pow(de,4) * t11 - pow(de,6) * t12 + + pow(de,8) * t13; + + t14 = 1.e0 / (sn * c * theTranMerc_Scale_Factor); + + t15 = (1.e0 + 2.e0 * tan2 + eta) / (6.e0 * pow(sn,3) * c * + pow(theTranMerc_Scale_Factor,3)); + + t16 = (5.e0 + 6.e0 * eta + 28.e0 * tan2 - 3.e0 * eta2 + + 8.e0 * tan2 * eta + 24.e0 * tan4 - 4.e0 + * eta3 + 4.e0 * tan2 * eta2 + 24.e0 + * tan2 * eta3) / (120.e0 * pow(sn,5) * c + * pow(theTranMerc_Scale_Factor,5)); + + t17 = (61.e0 + 662.e0 * tan2 + 1320.e0 * tan4 + 720.e0 + * pow(t,6)) / (5040.e0 * pow(sn,7) * c + * pow(theTranMerc_Scale_Factor,7)); + + /* Difference in Longitude */ + dlam = de * t14 - pow(de,3) * t15 + pow(de,5) * t16 - pow(de,7) * t17; + + /* Longitude */ + (*Longitude) = theTranMerc_Origin_Long + dlam; + while (*Latitude > (90.0 * RAD_PER_DEG)) + { + *Latitude = M_PI - *Latitude; + *Longitude += M_PI; + if (*Longitude > M_PI) + *Longitude -= TWO_PI; + } + + while (*Latitude < (-90.0 * RAD_PER_DEG)) + { + *Latitude = - (*Latitude + M_PI); + *Longitude += M_PI; + if (*Longitude > M_PI) + *Longitude -= TWO_PI; + } + if (*Longitude > TWO_PI) + *Longitude -= TWO_PI; + if (*Longitude < -M_PI) + *Longitude += TWO_PI; + +// if (fabs(dlam) > (9.0 * M_PI / 180)) +// { /* Distortion will result if Longitude is more than 9 degrees from the Central Meridian */ +// Error_Code |= UTM_LON_WARNING; +// } + } + return (Error_Code); +} /* END OF Convert_Transverse_Mercator_To_Geodetic */ + +std::ostream& ossimUtmProjection::print(std::ostream& out) const +{ + out << setiosflags(ios::fixed) << setprecision(15) + << "// ossimUtmProjection::print" + << "\ntheZone: " << theZone + << "\ntheHemisphere: " << theHemisphere + << endl; + return ossimMapProjection::print(out); +} + +double ossimUtmProjection::getFalseEasting() const +{ + return theTranMerc_False_Easting; +} + +double ossimUtmProjection::getFalseNorthing() const +{ + return theTranMerc_False_Northing; +} diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUtmProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUtmProjection.h new file mode 100644 index 0000000000..42ca953528 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUtmProjection.h @@ -0,0 +1,209 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +// Calls Geotrans Utm projection code. +//******************************************************************* +// $Id: ossimUtmProjection.h,v 1.18 2005/09/09 19:23:58 gpotts Exp $ +#ifndef ossimUtmProjection_HEADER +#define ossimUtmProjection_HEADER +#include <projections/map_projections/ossimMapProjection.h> + +class OSSIMDLLEXPORT ossimUtmProjection : public ossimMapProjection +{ +public: + ossimUtmProjection(const ossimEllipsoid& ellipsoid = ossimEllipsoid(), + const ossimGpt& origin = ossimGpt()); + + ossimUtmProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + long zone, + char hemisphere); + ossimUtmProjection(long zone); + ossimUtmProjection(const ossimUtmProjection& src); + + virtual ossimObject* dup()const; + + virtual ossimGpt inverse(const ossimDpt &eastingNorthing)const; + virtual ossimDpt forward(const ossimGpt &latLon)const; + virtual void update(); + void setZone(const ossimGpt& ground); + void setZone(long zone); + void setHemisphere(char hemisphere); + static long computeZone(const ossimGpt& gpt); + + /** + * Return in decimal degrees the zone meridian. + */ + static double computeZoneMeridian(long zone); + + long getZone()const; + + char getHemisphere()const; + + virtual bool operator==(const ossimProjection& projection) const; + + /** + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /** + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /** + * Prints data members to stream. Returns stream&. + */ + virtual std::ostream& print(std::ostream& out) const; + + /** + * @return The false easting. + */ + virtual double getFalseEasting() const; + + /** + * @return The false northing. + */ + virtual double getFalseNorthing() const; + +private: + /*_____________GEOTRANS_______________*/ + + /** + * The function Set_Tranverse_Mercator_Parameters receives the ellipsoid + * parameters and Tranverse Mercator projection parameters as inputs, and + * sets the corresponding state variables. If any errors occur, the error + * code(s) are returned by the function, otherwise TRANMERC_NO_ERROR is + * returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Origin_Latitude : Latitude in radians at the origin of the (input) + * projection + * Central_Meridian : Longitude in radians at the center of the (input) + * projection + * False_Easting : Easting/X at the center of the projection (input) + * False_Northing : Northing/Y at the center of the projection (input) + * Scale_Factor : Projection scale factor (input) + */ + long Set_Transverse_Mercator_Parameters(double a, + double f, + double Origin_Latitude, + double Central_Meridian, + double False_Easting, + double False_Northing, + double Scale_Factor); + /** + * The function Get_Transverse_Mercator_Parameters returns the current + * ellipsoid and Transverse Mercator projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Origin_Latitude : Latitude in radians at the origin of the (output) + * projection + * Central_Meridian : Longitude in radians at the center of the (output) + * projection + * False_Easting : Easting/X at the center of the projection (output) + * False_Northing : Northing/Y at the center of the projection (output) + * Scale_Factor : Projection scale factor (output) + */ + void Get_Transverse_Mercator_Parameters(double *a, + double *f, + double *Origin_Latitude, + double *Central_Meridian, + double *False_Easting, + double *False_Northing, + double *Scale_Factor)const; + + + /** + * The function Convert_Geodetic_To_Transverse_Mercator converts geodetic + * (latitude and longitude) coordinates to Transverse Mercator projection + * (easting and northing) coordinates, according to the current ellipsoid + * and Transverse Mercator projection coordinates. If any errors occur, the + * error code(s) are returned by the function, otherwise TRANMERC_NO_ERROR is + * returned. + * + * Latitude : Latitude in radians (input) + * Longitude : Longitude in radians (input) + * Easting : Easting/X in meters (output) + * Northing : Northing/Y in meters (output) + */ + long Convert_Geodetic_To_Transverse_Mercator (double Latitude, + double Longitude, + double *Easting, + double *Northing)const; + + + /** + * The function Convert_Transverse_Mercator_To_Geodetic converts Transverse + * Mercator projection (easting and northing) coordinates to geodetic + * (latitude and longitude) coordinates, according to the current ellipsoid + * and Transverse Mercator projection parameters. If any errors occur, the + * error code(s) are returned by the function, otherwise TRANMERC_NO_ERROR is + * returned. + * + * Easting : Easting/X in meters (input) + * Northing : Northing/Y in meters (input) + * Latitude : Latitude in radians (output) + * Longitude : Longitude in radians (output) + */ + long Convert_Transverse_Mercator_To_Geodetic (double Easting, + double Northing, + double *Latitude, + double *Longitude)const; + + double theTranMerc_a; /* Semi-major axis of ellipsoid i meters */ + double theTranMerc_f; /* Flattening of ellipsoid */ + + /* Eccentricity (0.08181919084262188000) squared */ + double theTranMerc_es; + + double theTranMerc_ebs; /* Second Eccentricity squared */ + + /* Transverse_Mercator projection Parameters */ + + double theTranMerc_Origin_Lat; /* Latitude of origin in radians */ + double theTranMerc_Origin_Long; /* Longitude of origin in radians */ + double theTranMerc_False_Northing; /* False northing in meters */ + double theTranMerc_False_Easting; /* False easting in meters */ + double theTranMerc_Scale_Factor; /* Scale factor */ + + /* Isometeric to geodetic latitude parameters, default to WGS 84 */ + double theTranMerc_ap; + double theTranMerc_bp; + double theTranMerc_cp; + double theTranMerc_dp; + double theTranMerc_ep; + + /* Maximum variance for easting and northing values for WGS 84. */ + double theTranMerc_Delta_Easting; + double theTranMerc_Delta_Northing; + + /** + * zone can be from 1 through 59 + */ + long theZone; + + /** + * can be N or S. + */ + char theHemisphere; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUtmpt.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUtmpt.cpp new file mode 100644 index 0000000000..0ab60fed04 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUtmpt.cpp @@ -0,0 +1,88 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +// This is the Universal Transverse Mercator (UTM) point. Allows +// easy onversion between different coordinates. +//******************************************************************* +// $Id: ossimUtmpt.cpp,v 1.5 2005/10/18 12:26:46 gpotts Exp $ + +#include "ossimUtmpt.h" +#include "base/data_types/ossimGpt.h" +#include "base/data_types/ossimEcefPoint.h" +#include "base/data_types/datum/ossimDatum.h" +#include "base/data_types/ellipse/ossimEllipsoid.h" +#include "projections/map_projections/ossimUtm.h" + +ossimUtmpt::ossimUtmpt(const ossimGpt &aPt) +{ + convertFromGround(aPt); +} + +ossimUtmpt::ossimUtmpt(const ossimEcefPoint &aPt) +{ + convertFromGround(ossimGpt(aPt)); +} + +ossimUtmpt::ossimUtmpt(long zone, + char hemisphere, // N or S + double easting, + double northing, + const ossimDatum* datum) + : + theZone (zone), + theHemisphere (hemisphere), + theEasting (easting), + theNorthing (northing), + theDatum (datum) +{} + +void ossimUtmpt::convertFromGround(const ossimGpt &aPt) +{ + const ossimDatum *aDatum = aPt.datum(); + + if(aDatum) + { + //call Geotrans init code + Set_UTM_Parameters(aDatum->ellipsoid()->a(), aDatum->ellipsoid()->flattening(), 0); + Convert_Geodetic_To_UTM(aPt.latr(), + aPt.lonr(), + &theZone, + &theHemisphere, + &theEasting, + &theNorthing); + theDatum = aDatum; + } + else + { + //ERROR: Should never happen + } +} + +void ossimUtmpt::convertToGround(ossimGpt &aPt) +{ + Set_UTM_Parameters( theDatum->ellipsoid()->a(), + theDatum->ellipsoid()->flattening(), + 0 ); + + double latitude = 0.0; + double longitude = 0.0; + + Convert_UTM_To_Geodetic( zone(), + hemisphere(), + easting(), + northing(), + &latitude, + &longitude ); + + aPt.latr(latitude); + aPt.lonr(longitude); + aPt.datum(theDatum); +} diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUtmpt.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUtmpt.h new file mode 100644 index 0000000000..23894f1a9a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimUtmpt.h @@ -0,0 +1,89 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +// This is the Universal Transverse Mercator (UTM) point. Allows +// easy onversion between different coordinates. +//******************************************************************* +// $Id: ossimUtmpt.h,v 1.5 2004/08/26 21:02:33 dburken Exp $ +#ifndef ossimUtmpt_HEADER +#define ossimUtmpt_HEADER + +#include <base/common/ossimConstants.h> + +class ossimGpt; +class ossimEcefPoint; +class ossimUpspt; +class ossimDatum; + +class OSSIMDLLEXPORT ossimUtmpt +{ +public: + ossimUtmpt(const ossimGpt &aPt); + ossimUtmpt(const ossimEcefPoint &aPt); + ossimUtmpt(long zone, + char hemisphere, // N or S + double easting, + double northing, + const ossimDatum* datum); + + // ossimUtmpt(const ossimUpspt &aPt); + + /** + * Return the zone for this utm point. + */ + long zone() const { return theZone; } + + /** + * Return the hemisphere ( Northern or Southern). + * We store this as a char value N or S. We store it + * like this because we are interfacing to geotrans + * and geotrans stores their values in this manner. + */ + char hemisphere() const { return theHemisphere; } + + /** + * return the easting value in meters. + */ + double easting() const { return theEasting; } + + /** + * return the northing value in meters. + */ + double northing() const { return theNorthing; } + + /** + * return the reference datum for this point. + */ + const ossimDatum* datum() const { return theDatum; } + + /** + * Initializes this point to utm coordinates for the ground point. + * + * @param aPt Ground point to initialize from. + */ + void convertFromGround(const ossimGpt &aPt); + + /** + * Initializes the ground point from the utm coordinates of this point. + * + * @param aPt Ground point to initialize. + */ + void convertToGround(ossimGpt &aPt); + +private: + long theZone; + char theHemisphere; + double theEasting; + double theNorthing; + const ossimDatum* theDatum; +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimVanDerGrintenProjection.cpp b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimVanDerGrintenProjection.cpp new file mode 100644 index 0000000000..1dfe423fc9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimVanDerGrintenProjection.cpp @@ -0,0 +1,529 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Grinten projection code. +//******************************************************************* +// $Id: ossimVanDerGrintenProjection.cpp,v 1.11 2004/01/08 21:49:22 jlargent Exp $ +#include "ossimVanDerGrintenProjection.h" +#include "base/common/ossimKeywordNames.h" + +RTTI_DEF1(ossimVanDerGrintenProjection, "ossimVanDerGrintenProjection", ossimMapProjection) + +/***************************************************************************/ +/* + * DEFINES + */ + +#ifndef PI_OVER_2 +# define PI_OVER_2 ( M_PI / 2.0) +#endif +#ifndef TWO_PI +# define TWO_PI (2.0 * M_PI) +#endif + +#define MAX_LAT ( 90.0 * (M_PI / 180.0) ) /* 90 degrees in radians */ +#define FLOAT_EQ(x,v,epsilon) (((v - epsilon) < x) && (x < (v + epsilon))) + +#define GRIN_NO_ERROR 0x0000 +#define GRIN_LAT_ERROR 0x0001 +#define GRIN_LON_ERROR 0x0002 +#define GRIN_EASTING_ERROR 0x0004 +#define GRIN_NORTHING_ERROR 0x0008 +#define GRIN_CENT_MER_ERROR 0x0020 +#define GRIN_A_ERROR 0x0040 +#define GRIN_B_ERROR 0x0080 +#define GRIN_A_LESS_B_ERROR 0x0100 +#define GRIN_RADIUS_ERROR 0x0200 + +/***************************************************************************/ +/* + * GLOBALS + */ + +const double TWO_OVER_PI = (2.0 / M_PI); +const double PI_OVER_3 = (M_PI / 3.0); +const double ONE_THIRD = (1.0 / 3.0); + + +ossimVanDerGrintenProjection::ossimVanDerGrintenProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin) + :ossimMapProjection(ellipsoid, origin) +{ + setDefaults(); + update(); +} + +ossimVanDerGrintenProjection::ossimVanDerGrintenProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + double falseEasting, + double falseNorthing) + :ossimMapProjection(ellipsoid, origin) +{ + Grin_False_Easting = falseEasting; + Grin_False_Northing = falseNorthing; + + update(); +} + +void ossimVanDerGrintenProjection::update() +{ + Set_Van_der_Grinten_Parameters(theEllipsoid.getA(), + theEllipsoid.getFlattening(), + theOrigin.lonr(), + Grin_False_Easting, + Grin_False_Northing); + + ossimMapProjection::update(); +} + +void ossimVanDerGrintenProjection::setFalseEasting(double falseEasting) +{ + Grin_False_Easting = falseEasting; + + update(); +} + +void ossimVanDerGrintenProjection::setFalseNorthing(double falseNorthing) +{ + Grin_False_Northing = falseNorthing; + + update(); +} + +void ossimVanDerGrintenProjection::setDefaults() +{ + Grin_False_Easting = 0.0; + Grin_False_Northing = 0.0; +} + +void ossimVanDerGrintenProjection::setFalseEastingNorthing(double falseEasting, + double falseNorthing) +{ + Grin_False_Easting = falseEasting; + Grin_False_Northing = falseNorthing; + + update(); +} + +ossimGpt ossimVanDerGrintenProjection::inverse(const ossimDpt &eastingNorthing)const +{ + double lat = 0.0; + double lon = 0.0; + + Convert_Van_der_Grinten_To_Geodetic(eastingNorthing.x, + eastingNorthing.y, + &lat, + &lon); + + return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum); +} + +ossimDpt ossimVanDerGrintenProjection::forward(const ossimGpt &latLon)const +{ + double easting = 0.0; + double northing = 0.0; + ossimGpt gpt = latLon; + + if (theDatum) + { + if (theDatum->code() != latLon.datum()->code()) + { + gpt.changeDatum(theDatum); // Shift to our datum. + } + } + + Convert_Geodetic_To_Van_der_Grinten(gpt.latr(), + gpt.lonr(), + &easting, + &northing); + return ossimDpt(easting, northing); +} + +bool ossimVanDerGrintenProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const +{ + kwl.add(prefix, + ossimKeywordNames::FALSE_EASTING_KW, + Grin_False_Easting, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_NORTHING_KW, + Grin_False_Northing, + true); + + return ossimMapProjection::saveState(kwl, prefix); +} + +bool ossimVanDerGrintenProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + bool flag = ossimMapProjection::loadState(kwl, prefix); + const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + const char* falseEasting = kwl.find(prefix, ossimKeywordNames::FALSE_EASTING_KW); + const char* falseNorthing = kwl.find(prefix, ossimKeywordNames::FALSE_NORTHING_KW); + + setDefaults(); + if(ossimString(type) == STATIC_TYPE_NAME(ossimVanDerGrintenProjection)) + { + if(falseEasting) + { + Grin_False_Easting = ossimString(falseEasting).toDouble(); + } + if(falseNorthing) + { + Grin_False_Northing = ossimString(falseNorthing).toDouble(); + } + } + + update(); + + return flag; + +} + +/***************************************************************************/ +/* + * FUNCTIONS + */ + + +long ossimVanDerGrintenProjection::Set_Van_der_Grinten_Parameters(double a, + double f, + double Central_Meridian, + double False_Easting, + double False_Northing) + +{ /* BEGIN Set_Van_der_Grinten_Parameters */ +/* + * The function Set_Van_der_Grinten_Parameters receives the ellipsoid parameters and + * projection parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the function, + * otherwise Grin_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + +// double inv_f = 1 / f; + long Error_Code = GRIN_NO_ERROR; + +// if (a <= 0.0) +// { /* Semi-major axis must be greater than zero */ +// Error_Code |= GRIN_A_ERROR; +// } +// if ((inv_f < 250) || (inv_f > 350)) +// { /* Inverse flattening must be between 250 and 350 */ +// Error_Code |= GRIN_INV_F_ERROR; +// } +// if ((Central_Meridian < -M_PI) || (Central_Meridian > TWO_PI)) +// { /* origin longitude out of range */ +// Error_Code |= GRIN_CENT_MER_ERROR; +// } + if (!Error_Code) + { /* no errors */ + Grin_a = a; + Grin_f = f; + es2 = 2 * Grin_f - Grin_f * Grin_f; + es4 = es2 * es2; + es6 = es4 * es2; + /* spherical radius */ + Ra = Grin_a * (1.0 - es2 / 6.0 - 17.0 * es4 / 360.0 - 67.0 * es6 /3024.0); + PI_Ra = M_PI * Ra; +// if (Central_Meridian > M_PI) +// Central_Meridian -= TWO_PI; + Grin_Origin_Long = Central_Meridian; + Grin_False_Easting = False_Easting; + Grin_False_Northing = False_Northing; + + } /* END OF if(!Error_Code) */ + return (Error_Code); +} /* END OF Set_Van_der_Grinten_Parameters */ + + +void ossimVanDerGrintenProjection::Get_Van_der_Grinten_Parameters(double *a, + double *f, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const + +{ /* BEGIN Get_Van_der_Grinten_Parameters */ +/* + * The function Get_Van_der_Grinten_Parameters returns the current ellipsoid + * parameters, and Van Der Grinten projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + + *a = Grin_a; + *f = Grin_f; + *Central_Meridian = Grin_Origin_Long; + *False_Easting = Grin_False_Easting; + *False_Northing = Grin_False_Northing; + + return; +} /* END OF Get_Van_der_Grinten_Parameters */ + + +long ossimVanDerGrintenProjection::Convert_Geodetic_To_Van_der_Grinten (double Latitude, + double Longitude, + double *Easting, + double *Northing)const + +{ /* BEGIN Convert_Geodetic_To_Van_der_Grinten */ +/* + * The function Convert_Geodetic_To_Van_der_Grinten converts geodetic (latitude and + * longitude) coordinates to Van Der Grinten projection (easting and northing) + * coordinates, according to the current ellipsoid and Van Der Grinten projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise GRIN_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + + double dlam; /* Longitude - Central Meridan */ + double aa, aasqr; + double gg; + double pp, ppsqr; + double gg_MINUS_ppsqr, ppsqr_PLUS_aasqr; + double in_theta; + double theta; + double sin_theta, cos_theta; + double qq; + long Error_Code = GRIN_NO_ERROR; + +// if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2)) +// { /* Latitude out of range */ +// Error_Code |= GRIN_LAT_ERROR; +// } +// if ((Longitude < -M_PI) || (Longitude > TWO_PI)) +// { /* Longitude out of range */ +// Error_Code|= GRIN_LON_ERROR; +// } + + if (!Error_Code) + { /* no errors */ + + dlam = Longitude - Grin_Origin_Long; +// if (dlam > M_PI) +// { +// dlam -= TWO_PI; +// } +// if (dlam < -M_PI) +// { +// dlam += TWO_PI; +// } + + if (Latitude == 0.0) + { + *Easting = Ra * dlam + Grin_False_Easting; + *Northing = 0.0; + } + else if (dlam == 0.0 || FLOAT_EQ(Latitude,MAX_LAT,.00001) || FLOAT_EQ(Latitude,-MAX_LAT,.00001)) + { + in_theta = fabs(TWO_OVER_PI * Latitude); + + if (in_theta > 1.0) + in_theta = 1.0; + else if (in_theta < -1.0) + in_theta = -1.0; + + theta = asin(in_theta); + *Easting = 0.0; + *Northing = PI_Ra * tan(theta / 2) + Grin_False_Northing; + if (Latitude < 0.0) + *Northing *= -1.0; + } + else + { + aa = 0.5 * fabs(M_PI / dlam - dlam / M_PI); + in_theta = fabs(TWO_OVER_PI * Latitude); + + if (in_theta > 1.0) + in_theta = 1.0; + else if (in_theta < -1.0) + in_theta = -1.0; + + theta = asin(in_theta); + sin_theta = sin(theta); + cos_theta = cos(theta); + gg = cos_theta / (sin_theta + cos_theta - 1); + pp = gg * (2 / sin_theta - 1); + aasqr = aa * aa; + ppsqr = pp * pp; + gg_MINUS_ppsqr = gg - ppsqr; + ppsqr_PLUS_aasqr = ppsqr + aasqr; + qq = aasqr + gg; + *Easting = PI_Ra * (aa * (gg_MINUS_ppsqr) + + sqrt(aasqr * (gg_MINUS_ppsqr) * (gg_MINUS_ppsqr) - + (ppsqr_PLUS_aasqr) * (gg * gg - ppsqr))) / + (ppsqr_PLUS_aasqr) + Grin_False_Easting; + if (dlam < 0.0) + *Easting *= -1.0; + *Northing = PI_Ra * (pp * qq - aa * sqrt ((aasqr + 1) * (ppsqr_PLUS_aasqr) - qq * qq)) / + (ppsqr_PLUS_aasqr) + Grin_False_Northing; + if (Latitude < 0.0) + *Northing *= -1.0; + } + } + return (Error_Code); + +} /* END OF Convert_Geodetic_To_Van_der_Grinten */ + + +long ossimVanDerGrintenProjection::Convert_Van_der_Grinten_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const +{ /* BEGIN Convert_Van_der_Grinten_To_Geodetic */ +/* + * The function Convert_Van_der_Grinten_To_Geodetic converts Grinten projection + * (easting and northing) coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Grinten projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise GRIN_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + + double dx, dy; + double xx, xxsqr; + double yy, yysqr, two_yysqr; + double xxsqr_PLUS_yysqr; + double c1; + double c2; + double c3, c3sqr; + double c2_OVER_3c3; + double dd; + double a1; + double m1; + double i; + double theta1; +// double temp; +// const double epsilon = 1.0e-2; + + long Error_Code = GRIN_NO_ERROR; + +// if ((Easting > (Grin_False_Easting + PI_Ra + epsilon)) || +// (Easting < (Grin_False_Easting - PI_Ra - epsilon))) +// { /* Easting out of range */ +// Error_Code |= GRIN_EASTING_ERROR; +// } +// if ((Northing > (Grin_False_Northing + PI_Ra + epsilon)) || +// (Northing < (Grin_False_Northing - PI_Ra - epsilon))) +// { /* Northing out of range */ +// Error_Code |= GRIN_NORTHING_ERROR; +// } +// if (!Error_Code) +// { +// temp = sqrt(Easting * Easting + Northing * Northing); + +// if ((temp > (Grin_False_Easting + PI_Ra + epsilon)) || +// (temp > (Grin_False_Northing + PI_Ra + epsilon)) || +// (temp < (Grin_False_Easting - PI_Ra - epsilon)) || +// (temp < (Grin_False_Northing - PI_Ra - epsilon))) +// { /* Point is outside of projection area */ +// Error_Code |= GRIN_RADIUS_ERROR; +// } +// } + + if (!Error_Code) + { + dy = Northing - Grin_False_Northing; + dx = Easting - Grin_False_Easting; + xx = dx / PI_Ra; + yy = dy / PI_Ra; + xxsqr = xx * xx; + yysqr = yy * yy; + xxsqr_PLUS_yysqr = xxsqr + yysqr; + two_yysqr = 2 * yysqr; + + if (Northing == 0.0) + *Latitude = 0.0; + + else + { + c1 = - fabs(yy) * (1 + xxsqr_PLUS_yysqr); + c2 = c1 - two_yysqr + xxsqr; + c3 = - 2 * c1 + 1 + two_yysqr + (xxsqr_PLUS_yysqr) * (xxsqr_PLUS_yysqr); + c2_OVER_3c3 = c2 / (3.0 * c3); + c3sqr = c3 * c3; + dd = yysqr / c3 + ((2 * c2 * c2 * c2) / (c3sqr * c3) - (9 * c1 * c2) / (c3sqr)) / 27; + a1 = (c1 - c2 * c2_OVER_3c3) /c3; + m1 = 2 * sqrt(-ONE_THIRD * a1); + i = 3 * dd/ (a1 * m1); + if ((i > 1.0)||(i < -1.0)) + *Latitude = MAX_LAT; + else + { + theta1 = ONE_THIRD * acos(3 * dd / (a1 * m1)); + *Latitude = M_PI * (-m1 * cos(theta1 + PI_OVER_3) - c2_OVER_3c3); + } + } + if (Northing < 0.0) + *Latitude *= -1.0; + + if (xx == 0.0) + *Longitude = Grin_Origin_Long; + else + { + *Longitude = M_PI * (xxsqr_PLUS_yysqr - 1 + + sqrt(1 + (2 * xxsqr - two_yysqr) + (xxsqr_PLUS_yysqr) * (xxsqr_PLUS_yysqr))) / + (2 * xx) + Grin_Origin_Long; + } +// if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */ +// *Latitude = PI_OVER_2; +// else if (*Latitude < -PI_OVER_2) +// *Latitude = -PI_OVER_2; + +// if (*Longitude > M_PI) +// *Longitude -= TWO_PI; +// if (*Longitude < -M_PI) +// *Longitude += TWO_PI; + +// if (*Longitude > M_PI) /* force distorted values to 180, -180 degrees */ +// *Longitude = M_PI; +// else if (*Longitude < -M_PI) +// *Longitude = -M_PI; + + } + return (Error_Code); + +} /* END OF Convert_Van_der_Grinten_To_Geodetic */ diff --git a/Utilities/OSSIM/ossim_core/projections/map_projections/ossimVanDerGrintenProjection.h b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimVanDerGrintenProjection.h new file mode 100644 index 0000000000..df6e0b3064 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/map_projections/ossimVanDerGrintenProjection.h @@ -0,0 +1,189 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: +// +// Calls Grinten projection code. +//******************************************************************* +// $Id: ossimVanDerGrintenProjection.h,v 1.5 2005/09/09 19:23:58 gpotts Exp $ +#ifndef ossimVanDerGrintenProjection_HEADER +#define ossimVanDerGrintenProjection_HEADER + +#include "ossimMapProjection.h" + +class ossimVanDerGrintenProjection : public ossimMapProjection +{ +public: + ossimVanDerGrintenProjection(const ossimEllipsoid& ellipsoid = ossimEllipsoid(), + const ossimGpt& origin = ossimGpt()); + ossimVanDerGrintenProjection(const ossimEllipsoid& ellipsoid, + const ossimGpt& origin, + const double falseEasting, + const double falseNorthing); + ~ossimVanDerGrintenProjection(){} + virtual ossimObject *dup()const + { + return new ossimVanDerGrintenProjection(*this); + } + + virtual ossimGpt inverse(const ossimDpt &eastingNorthing)const; + virtual ossimDpt forward(const ossimGpt &latLon)const; + virtual void update(); + + + /*! + * SetFalseEasting. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEasting(double falseEasting); + + /*! + * SetFalseNorthing. The value is in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseNorthing(double falseNorthing); + + /*! + * Sets both false easting and northing values. The values are + * expected to be in meters. + * Update is then called so we can pre-compute paramters + */ + void setFalseEastingNorthing(double falseEasting, double falseNorthing); + + void setDefaults(); + + double getFalseEasting()const{return Grin_False_Easting;} + double getFalseNorthing()const{return Grin_False_Northing;} + + /*! + * Method to save the state of an object to a keyword list. + * Return true if ok or false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + /*! + * Method to the load (recreate) the state of an object from a keyword + * list. Return true if ok or false on error. + */ + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + +protected: + + //________________GEOTRANS_____________ + + + mutable double Grin_a; /* Semi-major axis of ellipsoid in meters */ + mutable double Grin_f; /* Flattening of ellipsoid */ + mutable double es2; /* Eccentricity (0.08181919084262188000) squared */ + mutable double es4; /* es2 * es2 */ + mutable double es6; /* es4 * es2 */ + mutable double Ra; /* Spherical Radius */ + mutable double PI_Ra; + + mutable double Grin_Origin_Long; /* Longitude of origin in radians */ + mutable double Grin_False_Easting; + mutable double Grin_False_Northing; +/* Van Der Grinten projection Parameters */ + +/*! + * The function Set_Van_der_Grinten_Parameters receives the ellipsoid parameters and + * Van Der Grinten projcetion parameters as inputs, and sets the corresponding state + * variables. If any errors occur, the error code(s) are returned by the function, otherwise + * GRIN_NO_ERROR is returned. + * + * a : Semi-major axis of ellipsoid, in meters (input) + * f : Flattening of ellipsoid (input) + * Central_Meridian : Longitude in radians at the center of (input) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (input) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (input) + */ + long Set_Van_der_Grinten_Parameters(double a, + double f, + double Central_Meridian, + double False_Easting, + double False_Northing); + + + +/*! + * The function Get_Van_der_Grinten_Parameters returns the current ellipsoid + * parameters, and Van Der Grinten projection parameters. + * + * a : Semi-major axis of ellipsoid, in meters (output) + * f : Flattening of ellipsoid (output) + * Central_Meridian : Longitude in radians at the center of (output) + * the projection + * False_Easting : A coordinate value in meters assigned to the + * central meridian of the projection. (output) + * False_Northing : A coordinate value in meters assigned to the + * origin latitude of the projection (output) + */ + void Get_Van_der_Grinten_Parameters(double *a, + double *f, + double *Central_Meridian, + double *False_Easting, + double *False_Northing)const; + + + +/*! + * The function Convert_Geodetic_To_Van_der_Grinten converts geodetic (latitude and + * longitude) coordinates to Van Der Grinten projection easting, and northing + * coordinates, according to the current ellipsoid and Van Der Grinten projection + * parameters. If any errors occur, the error code(s) are returned by the + * function, otherwise GRIN_NO_ERROR is returned. + * + * Latitude : Latitude (phi) in radians (input) + * Longitude : Longitude (lambda) in radians (input) + * Easting : Easting (X) in meters (output) + * Northing : Northing (Y) in meters (output) + */ + long Convert_Geodetic_To_Van_der_Grinten (double Latitude, + double Longitude, + double *Easting, + double *Northing)const; + + +/*! + * The function Convert_Van_der_Grinten_To_Geodetic converts Van Der Grinten projection + * easting and northing coordinates to geodetic (latitude and longitude) + * coordinates, according to the current ellipsoid and Van Der Grinten projection + * coordinates. If any errors occur, the error code(s) are returned by the + * function, otherwise GRIN_NO_ERROR is returned. + * + * Easting : Easting (X) in meters (input) + * Northing : Northing (Y) in meters (input) + * Latitude : Latitude (phi) in radians (output) + * Longitude : Longitude (lambda) in radians (output) + */ + long Convert_Van_der_Grinten_To_Geodetic(double Easting, + double Northing, + double *Latitude, + double *Longitude)const; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/ossimAffineProjection.cpp b/Utilities/OSSIM/ossim_core/projections/ossimAffineProjection.cpp new file mode 100644 index 0000000000..87ce079052 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/ossimAffineProjection.cpp @@ -0,0 +1,287 @@ +//***************************************************************************** +// FILE: ossimAffineProjection.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// AUTHOR: Oscar Kramer (okramer@imagelinks.com) +// +// DESCRIPTION: +// Contains implementation of class ossimAffineModel. This is an +// implementation of a warping interpolation model. +// +//***************************************************************************** +// $Id: ossimAffineProjection.cpp,v 1.6 2005/09/09 19:23:58 gpotts Exp $ + +#include <projections/ossimAffineProjection.h> +RTTI_DEF1(ossimAffineProjection, "ossimAffineProjection", ossimProjection); + +#include <base/misc/ossimAffineTransform.h> +#include <base/context/ossimNotifyContext.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> + +//*** +// Define Trace flags for use within this file: +//*** +#include <base/common/ossimTrace.h> +static ossimTrace traceExec ("ossimAffineProjection:exec"); +static ossimTrace traceDebug ("ossimAffineProjection:debug"); + +//***************************************************************************** +// CONSTRUCTOR: Default +// +//***************************************************************************** +ossimAffineProjection::ossimAffineProjection() + : + ossimProjection(), + theClientProjection (NULL), + theAffineTransform (NULL) +{ +} + + +//***************************************************************************** +// CONSTRUCTOR: Primary constructor accepting pointer to the underlying +// client projection +// +//***************************************************************************** +ossimAffineProjection::ossimAffineProjection(ossimProjection* client) + : + ossimProjection(), + theClientProjection (client), + theAffineTransform (NULL) +{ +} + +//***************************************************************************** +// CONSTRUCTOR: Accepts geom keywordlist +//***************************************************************************** +ossimAffineProjection::ossimAffineProjection(const ossimKeywordlist& geom_kwl, + const char* prefix) + : + ossimProjection(), + theClientProjection (NULL), + theAffineTransform (NULL) +{ + theClientProjection = ossimProjectionFactoryRegistry::instance()-> + createProjection(geom_kwl, prefix); + + theAffineTransform = new ossimAffineTransform(); + bool rtn_stat = theAffineTransform->loadState(geom_kwl, prefix); + + if (!theClientProjection || + theClientProjection->getErrorStatus() || !rtn_stat) + setErrorStatus(ossimErrorCodes::OSSIM_ERROR); +} + +//***************************************************************************** +// DESTRUCTOR +//***************************************************************************** +ossimAffineProjection::~ossimAffineProjection() +{ + delete theClientProjection; + delete theAffineTransform; +} + +//***************************************************************************** +// METHOD: ossimAffineProjection::worldToLineSample() +//***************************************************************************** +void +ossimAffineProjection::worldToLineSample (const ossimGpt& worldPoint, + ossimDpt& lineSampPt) const +{ + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimAffineProjection::worldToLineSample: Entering..." << std::endl; + + if (theClientProjection && theAffineTransform) + { + theClientProjection->worldToLineSample(worldPoint, lineSampPt); + theAffineTransform->inverse(lineSampPt); + } + else + lineSampPt.makeNan(); + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimAffineProjection::worldToLineSample: Returning..." << std::endl; +} + +//***************************************************************************** +// METHOD: ossimAffineProjection::lineSampleToWorld() +//***************************************************************************** +void +ossimAffineProjection::lineSampleToWorld(const ossimDpt& lineSampPt, + ossimGpt& worldPt) const +{ + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimAffineProjection::lineSampleToWorld: Entering..." << std::endl; + + if (theClientProjection && theAffineTransform) + { + ossimDpt adjustedPt; + theAffineTransform->forward(lineSampPt, adjustedPt); + theClientProjection->lineSampleToWorld(adjustedPt, worldPt); + } + else + { + worldPt.makeNan(); + } + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimAffineProjection::lineSampleToWorld: Returning..." << std::endl; +} + +//***************************************************************************** +// METHOD: ossimAffineProjection::lineSampleToWorld() +//***************************************************************************** +void +ossimAffineProjection::lineSampleHeightToWorld(const ossimDpt& lineSampPt, + const double& hgt, + ossimGpt& worldPt) const +{ + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimAffineProjection::lineSampleHeightToWorld: Entering..." << std::endl; + + if (theClientProjection && theAffineTransform) + { + ossimDpt adjustedPt; + theAffineTransform->forward(lineSampPt, adjustedPt); + theClientProjection->lineSampleHeightToWorld(adjustedPt, hgt, worldPt); + } + else + { + worldPt.makeNan(); + } + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "dEBUG ossimAffineProjection::lineSampleHeightToWorld: Returning..." << std::endl; +} + +//***************************************************************************** +// METHOD: ossimAffineProjection::print() +//***************************************************************************** +std::ostream& ossimAffineProjection::print(std::ostream& out) const +{ + + if (theClientProjection && theAffineTransform) + { + out << + "ossimAffineProjection:\n" + " Member theClientProjection: "; + theClientProjection->print(out); + out << "\n Member theAffineTransform: " + << *theAffineTransform << endl; + } + else + { + out << "ossimAffineProjection -- Not initialized." << endl; + } + return out; +} + +std::ostream& operator<<(std::ostream& os, const ossimAffineProjection& m) +{ + return m.print(os); +} + +//***************************************************************************** +// METHOD: ossimAffineProjection::() +//***************************************************************************** +bool ossimAffineProjection::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimAffineProjection::saveState: entering..." << std::endl; + + if (theClientProjection && theAffineTransform) + { + theClientProjection->saveState(kwl, prefix); + theAffineTransform->saveState(kwl, prefix); + } + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimAffineProjection::saveState: returning..." << std::endl; + return true; +} + +//***************************************************************************** +// METHOD: ossimAffineProjection::() +//***************************************************************************** +bool ossimAffineProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimAffineProjection::loadState: entering..." << std::endl; + + bool good_load; + int err_stat; + + if (!theClientProjection) + { + theClientProjection = ossimProjectionFactoryRegistry::instance()-> + createProjection(kwl, prefix); + err_stat = theClientProjection->getErrorStatus(); + if (err_stat != ossimErrorCodes::OSSIM_OK) + { + return false; + } + } + else + { + good_load = theClientProjection->loadState(kwl, prefix); + if (!good_load) + { + return false; + } + } + + if (!theAffineTransform) + { + theAffineTransform = new ossimAffineTransform(); + } + good_load = theAffineTransform->loadState(kwl, prefix); + if (!good_load) + { + return false; + } + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimAffineProjection::loadState: returning..." << std::endl; + + return true; + +} + +//***************************************************************************** +// METHOD: ossimAffineProjection::() +//***************************************************************************** +ossimObject* ossimAffineProjection::dup() const +{ + ossimKeywordlist kwl; + saveState(kwl); + ossimProjection* duped = new ossimAffineProjection(kwl); + return duped; +} + +//***************************************************************************** +// METHOD: +//***************************************************************************** +ossimGpt ossimAffineProjection::origin() const +{ + if (theClientProjection) + return theClientProjection->origin(); + return ossimGpt(0.0, 0.0, 0.0); +} + +//***************************************************************************** +// METHOD: +//***************************************************************************** +ossimDpt ossimAffineProjection::getMetersPerPixel() const +{ + if (theClientProjection) + return theClientProjection->getMetersPerPixel(); + return ossimDpt(OSSIM_NAN, OSSIM_NAN); +} + diff --git a/Utilities/OSSIM/ossim_core/projections/ossimAffineProjection.h b/Utilities/OSSIM/ossim_core/projections/ossimAffineProjection.h new file mode 100644 index 0000000000..a7e162ef7f --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/ossimAffineProjection.h @@ -0,0 +1,130 @@ +//***************************************************************************** +// FILE: ossimAffineProjection.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// AUTHOR: Oscar Kramer (okramer@imagelinks.com) +// +// DESCRIPTION: +// Contains declaration of class ossimAffineProjection. This is an +// implementation of a warping interpolation model. +// +//***************************************************************************** +// $Id: ossimAffineProjection.h,v 1.3 2005/09/09 19:23:58 gpotts Exp $ + +#ifndef ossimAffineProjection_HEADER +#define ossimAffineProjection_HEADER + +#include "projections/ossimProjection.h" +#include "base/data_types/ossimIpt.h" + +class ossim2dTo2dTransform; + +/*!**************************************************************************** + * + * CLASS: ossimAffineProjection + * + *****************************************************************************/ +class ossimAffineProjection : public ossimProjection +{ +public: + /*! + * Default Contructor: + */ + ossimAffineProjection(); + + /*! + * Primary constructor accepting pointer to the underlying client projection. + */ + ossimAffineProjection(ossimProjection* client); + + /*! + * Constructor accepts OSSIM keywordlist geometry file. + */ + ossimAffineProjection(const ossimKeywordlist& geom_kwl, + const char* prefix=NULL); + + ~ossimAffineProjection(); + + /*! + * METHOD: worldToLineSample() + * Performs the forward projection from ground point to line, sample. + */ + virtual void worldToLineSample(const ossimGpt& worldPoint, + ossimDpt& lineSampPt) const; + + /*! + * METHOD: lineSampleToWorld() + * Performs the inverse projection from line, sample to ground (world): + */ + virtual void lineSampleToWorld(const ossimDpt& lineSampPt, + ossimGpt& worldPt) const; + + /*! + * Performs the inverse projection from line, sample to ground, bypassing + * reference to elevation surface: + */ + virtual void lineSampleHeightToWorld(const ossimDpt& lineSampPt, + const double& hgtEllipsoid, + ossimGpt& worldPt) const; + + /*! + * Extends base-class implementation. Dumps contents of object to ostream. + */ + virtual std::ostream& print(std::ostream& out) const; + friend std::ostream& operator<<(std::ostream& os, + const ossimAffineProjection& m); + + /*! + * Fulfills ossimObject base-class pure virtuals. Loads and saves geometry + * KWL files. Returns true if successful. + */ + virtual bool saveState(ossimKeywordlist& kwl, const char* prefix=0) const; + virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix=0); + + /*! + * Returns pointer to a new instance, copy of this. + */ + virtual ossimObject* dup() const; + + /*! + * Returns projection's ground point origin. That is the GP corresponding + * to line=0, sample=0. + */ + virtual ossimGpt origin() const; + + /*! + * Compares this instance with arg projection. NOT IMPLEMENTED. + */ + virtual bool operator==(const ossimProjection& projection) const + { return false; } + + virtual ossimDpt getMetersPerPixel() const; + +protected: + + /*! + * Data Members: + */ + ossimProjection* theClientProjection; + ossim2dTo2dTransform* theAffineTransform; + + TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/ossimBilinearProjection.cpp b/Utilities/OSSIM/ossim_core/projections/ossimBilinearProjection.cpp new file mode 100644 index 0000000000..27e4840646 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/ossimBilinearProjection.cpp @@ -0,0 +1,433 @@ +//******************************************************************* +// Copyright (C) 2004 Intelligence Data Systems, Inc. All rights reserved. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************** +// $Id: ossimBilinearProjection.cpp,v 1.6 2004/09/30 20:20:41 dburken Exp $ + +#include <sstream> +using namespace std; + +#include <projections/ossimBilinearProjection.h> +#include <base/factory/ossimDatumFactory.h> +#include <base/data_types/ossimGpt.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimEcefPoint.h> +#include <base/data_types/ossimEcefVector.h> +#include <base/data_types/ossimDrect.h> +#include <base/data_types/datum/ossimDatum.h> +#include <base/common/ossimKeywordNames.h> +#include <base/common/ossimTrace.h> +#include <base/context/ossimNotifyContext.h> +#include <elevation/ossimElevManager.h> + +#ifdef OSSIM_ID_ENABLED +static const char OSSIM_ID[] = "$Id: ossimBilinearProjection.cpp,v 1.6 2004/09/30 20:20:41 dburken Exp $"; +#endif + +// static const ossim_uint32 MINIMUM_NMBER_OF_POINTS = 4; + +static ossimTrace traceDebug("ossimBilinearProjection:debug"); + +RTTI_DEF1(ossimBilinearProjection, "ossimBilinearProjection", ossimProjection); + +ossimBilinearProjection::ossimBilinearProjection() + : + ossimProjection(), + theLineSamplePt(0), + theGeographicPt(0), + theLatFit(), + theLonFit() +{ +#ifdef OSSIM_ID_ENABLED + if (traceDebug()) ossimNotify(ossimNotifyLevel_DEBUG) << OSSIM_ID << endl; +#endif +} + +ossimBilinearProjection::ossimBilinearProjection(const ossimBilinearProjection& rhs) + : + ossimProjection(rhs), + theLineSamplePt(rhs.theLineSamplePt), + theGeographicPt(rhs.theGeographicPt), + theLonFit(rhs.theLonFit) +{ +} + +ossimBilinearProjection::ossimBilinearProjection(const ossimDpt& ul, + const ossimDpt& ur, + const ossimDpt& lr, + const ossimDpt& ll, + const ossimGpt& ulg, + const ossimGpt& urg, + const ossimGpt& lrg, + const ossimGpt& llg) + : + ossimProjection(), + theLineSamplePt(4), + theGeographicPt(4), + theLatFit(), + theLonFit() +{ + theLineSamplePt[0] = ul; + theLineSamplePt[1] = ur; + theLineSamplePt[2] = lr; + theLineSamplePt[3] = ll; + + theGeographicPt[0] = ulg; + theGeographicPt[1] = urg; + theGeographicPt[2] = lrg; + theGeographicPt[3] = llg; + + initializeBilinear(); +} + +ossimBilinearProjection::~ossimBilinearProjection() +{ +} + +ossimObject *ossimBilinearProjection::dup()const +{ + return new ossimBilinearProjection(*this); +} + +ossimGpt ossimBilinearProjection::origin()const +{ + ossimGpt result; + result.makeNan(); + if ( (theGeographicPt.size() == 0) || gPtsHaveNan() ) + { + return result; + } + + double lat = 0.0; + double lon = 0.0; + const double SIZE = theGeographicPt.size(); + + vector<ossimGpt>::const_iterator i = theGeographicPt.begin(); + while (i != theGeographicPt.end()) + { + lat += (*i).latd(); + lon += (*i).lond(); + ++i; + } + + result.latd(lat/SIZE); + result.lond(lon/SIZE); + result.height(0.0); + result.datum(theGeographicPt[0].datum()); + + return result; +} + +void ossimBilinearProjection::worldToLineSample(const ossimGpt& worldPoint, + ossimDpt& lineSampPt) const +{ + ossimProjection::worldToLineSample(worldPoint, lineSampPt); +} + +void ossimBilinearProjection::lineSampleToWorld(const ossimDpt& lineSampPt, + ossimGpt& worldPt) const +{ + lineSampleHeightToWorld(lineSampPt, + OSSIM_DBL_NAN, + worldPt); + +} + +void ossimBilinearProjection::lineSampleHeightToWorld(const ossimDpt& lineSampPt, + const double& heightAboveEllipsoid, + ossimGpt& worldPt) const +{ + worldPt.makeNan(); + + if (dPtsHaveNan() || gPtsHaveNan()) + { + return; + } + + + worldPt.lat = theLatFit.lsFitValue(lineSampPt.x, lineSampPt.y); + worldPt.lon = theLonFit.lsFitValue(lineSampPt.x, lineSampPt.y); + if (heightAboveEllipsoid != OSSIM_DBL_NAN) + { + worldPt.hgt = heightAboveEllipsoid; + } + else + { + worldPt.hgt = + ossimElevManager::instance()->getHeightAboveEllipsoid(worldPt); + } + if (theGeographicPt.size()) + { + worldPt.datum(theGeographicPt[0].datum()); + } +} + +bool ossimBilinearProjection::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + if (theLineSamplePt.size() != theGeographicPt.size()) + { + // Should never happen. + return false; + } + + ossimProjection::saveState(kwl, prefix); + + const ossim_uint32 SIZE = theLineSamplePt.size(); + + for (ossim_uint32 i = 0; i < SIZE; ++i) + { + ossimString index_string = ossimString::toString(i); + + // Add the geographic point. + ossimString kw = "gpt"; + kw += index_string; + ostringstream os1; + os1 << theGeographicPt[i]; + kwl.add(prefix, kw, os1.str().c_str()); + + // Add the sample line.. + kw = "dpt"; + kw += index_string; + ostringstream os2; + os2 << theLineSamplePt[i]; + kwl.add(prefix, kw, os2.str().c_str()); + } + + return true; +} + +bool ossimBilinearProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + // Load the base class. + ossimProjection::loadState(kwl, prefix); + + // Start with clear lists. + theLineSamplePt.clear(); + theGeographicPt.clear(); + + //--- + // Get the number of points. + // If 0 or gpt size not equal to dpt size get out. + //--- + const ossim_uint32 SIZE = kwl.numberOf(prefix, "gpt"); + if ( (SIZE == 0) || (SIZE != kwl.numberOf(prefix, "dpt")) ) + { + return false; + } + + for (ossim_uint32 i = 0; i < SIZE; ++i) + { + const char* lookup; + ossimString index_string = ossimString::toString(i); + + // Get the geographic point. + ossimString kw = "gpt"; + kw += index_string; + lookup = kwl.find(prefix, kw); + if (lookup) + { + ossimGpt gp; + istringstream is(lookup); + is >> gp; + + //--- + // Allow for "nan" height values by substituting with 0.0 so the + // hasNans() will work. "nan"s will get placed in the point if the + // user doesn't have the elevation manager preferences set up + // correctly. + //--- + if (gp.isHgtNan()) + { + gp.height(0.0); + } + theGeographicPt.push_back(gp); + } + + // Get the line sample point. + kw = "dpt"; + kw += index_string; + lookup = kwl.find(prefix, kw); + if (lookup) + { + ossimDpt dp; + istringstream is(lookup); + is >> dp; + theLineSamplePt.push_back(dp); + } + } + + if (traceDebug()) + { + print(ossimNotify(ossimNotifyLevel_DEBUG)); + } + + initializeBilinear(); + + return true; +} + +bool ossimBilinearProjection::operator==(const ossimProjection& projection) const +{ + return false; +} + +ossimDpt ossimBilinearProjection::getMetersPerPixel() const +{ + ossimGpt centerG; + ossimGpt rightG; + ossimGpt topG; + + ossimDpt midPoint = midLineSamplePt(); + + lineSampleToWorld(midPoint, centerG); + lineSampleToWorld(midPoint+ossimDpt(1,0), rightG); + lineSampleToWorld(midPoint+ossimDpt(0,-1), topG); + + ossimEcefPoint centerP = centerG; + ossimEcefPoint rightP = rightG; + ossimEcefPoint topP = topG; + + ossimEcefVector horizontal = rightP-centerP; + ossimEcefVector vertical = topP-centerP; + + ossimDpt result(horizontal.magnitude(), + vertical.magnitude()); + + result.x = (result.x + result.y)/2.0; + result.y = result.x; + + return result; +} + +void ossimBilinearProjection::initializeBilinear() +{ + theLatFit.clear(); + theLonFit.clear(); + + const ossim_uint32 SIZE = theLineSamplePt.size(); + if (SIZE != theGeographicPt.size()) + { + return; + } + + for (ossim_uint32 i = 0; i < SIZE; ++i) + { + theLatFit.addSample(theLineSamplePt[i].x, + theLineSamplePt[i].y, + theGeographicPt[i].latd()); + + theLonFit.addSample(theLineSamplePt[i].x, + theLineSamplePt[i].y, + theGeographicPt[i].lond()); + } + + theLatFit.solveLS(); + theLonFit.solveLS(); +} + +bool ossimBilinearProjection::dPtsHaveNan() const +{ + if (theLineSamplePt.size() == 0) + { + return false; + } + + vector<ossimDpt>::const_iterator i = theLineSamplePt.begin(); + while (i != theLineSamplePt.end()) + { + if ( (*i).hasNans() ) + { + return true; + } + ++i; + } + return false; +} + +bool ossimBilinearProjection::gPtsHaveNan() const +{ + //--- + // NOTE: This method ignores nans in the height field. + //--- + + if (theGeographicPt.size() == 0) + { + return false; + } + + vector<ossimGpt>::const_iterator i = theGeographicPt.begin(); + while (i != theGeographicPt.end()) + { + if ( (*i).isLatNan() || (*i).isLonNan() ) + { + return true; + } + ++i; + } + return false; +} + +ossimDpt ossimBilinearProjection::midLineSamplePt() const +{ + ossimDpt result; + + if ( (theLineSamplePt.size() == 0) || dPtsHaveNan()) + { + result.makeNan(); + return result; + } + + double x = 0.0; + double y = 0.0; + vector<ossimDpt>::const_iterator i = theLineSamplePt.begin(); + while (i != theLineSamplePt.end()) + { + x += (*i).x; + y += (*i).y; + ++i; + } + const double SIZE = theLineSamplePt.size(); + result.x = x / SIZE; + result.y = y / SIZE; + + return result; +} + +std::ostream& ossimBilinearProjection::print(std::ostream& out) const +{ + ossimNotify(ossimNotifyLevel_INFO) + << "ossimBilinearProjection::print\n"; + + ossim_uint32 index = 0; + vector<ossimDpt>::const_iterator di = theLineSamplePt.begin(); + while (di != theLineSamplePt.end()) + { + ossimNotify(ossimNotifyLevel_INFO) + << "theLineSamplePt[" << index << "]: " + << (*di) << endl; + ++di; + ++index; + } + + index = 0; + vector<ossimGpt>::const_iterator gi = theGeographicPt.begin(); + while (gi != theGeographicPt.end()) + { + ossimNotify(ossimNotifyLevel_INFO) + << "theGeographicPt[" << index << "]: " + << (*gi) << endl; + ++gi; + ++index; + } + + return ossimProjection::print(out); +} + diff --git a/Utilities/OSSIM/ossim_core/projections/ossimBilinearProjection.h b/Utilities/OSSIM/ossim_core/projections/ossimBilinearProjection.h new file mode 100644 index 0000000000..1af3e320e8 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/ossimBilinearProjection.h @@ -0,0 +1,108 @@ +//******************************************************************* +// Copyright (C) 2004 Intelligence Data Systems, Inc. All rights reserved. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts +// +//******************************************************************** +// $Id: ossimBilinearProjection.h,v 1.2 2004/07/01 21:02:30 dburken Exp $ +#ifndef ossimBilinearProjection_HEADER +#define ossimBilinearProjection_HEADER + +#include <vector> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimGpt.h> +#include <projections/ossimProjection.h> +#include <base/common/ossimLeastSquaresBilin.h> + +class ossimBilinearProjection : public ossimProjection +{ +public: + ossimBilinearProjection(); + ossimBilinearProjection(const ossimBilinearProjection& rhs); + ossimBilinearProjection(const ossimDpt& ul, + const ossimDpt& ur, + const ossimDpt& lr, + const ossimDpt& ll, + const ossimGpt& ulg, + const ossimGpt& urg, + const ossimGpt& lrg, + const ossimGpt& llg); + virtual ~ossimBilinearProjection(); + virtual ossimObject *dup()const; + virtual ossimGpt origin()const; + + virtual void worldToLineSample(const ossimGpt& worldPoint, + ossimDpt& lineSampPt) const; + /*! + * METHOD: lineSampleToWorld() + * Performs the inverse projection from line, sample to ground (world): + */ + virtual void lineSampleToWorld(const ossimDpt& lineSampPt, + ossimGpt& worldPt) const; + + /*! + * METHOD: lineSampleHeightToWorld + * This is the pure virtual that projects the image point to the given + * elevation above ellipsoid, thereby bypassing reference to a DEM. Useful + * for projections that are sensitive to elevation (such as sensor models). + */ + virtual void lineSampleHeightToWorld(const ossimDpt& lineSampPt, + const double& heightAboveEllipsoid, + ossimGpt& worldPt) const; + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual bool operator==(const ossimProjection& projection) const; + virtual ossimDpt getMetersPerPixel() const; + + virtual std::ostream& print(std::ostream& out) const; + +protected: + void initializeBilinear(); + + /** + * Checks theLineSamplePt for nans. + * @return true if any point has a nan. + * @note If theLineSamplePt size is 0 this returns false. + */ + bool dPtsHaveNan() const; + + /** + * Checks theGeographicPt for nans. + * @return true if any point has a nan. + * @note If theLineSamplePt size is 0 this returns false. + */ + bool gPtsHaveNan() const; + + /** + * @return The mid point of theLineSamplePts. + */ + ossimDpt midLineSamplePt() const; + + std::vector<ossimDpt> theLineSamplePt; + std::vector<ossimGpt> theGeographicPt; + ossimLeastSquaresBilin theLatFit; + ossimLeastSquaresBilin theLonFit; + +TYPE_DATA +}; + +#endif /* #ifndef ossimBilinearProjection_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/projections/ossimImageViewAffineTransform.cpp b/Utilities/OSSIM/ossim_core/projections/ossimImageViewAffineTransform.cpp new file mode 100644 index 0000000000..f91807f280 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/ossimImageViewAffineTransform.cpp @@ -0,0 +1,352 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimImageViewAffineTransform.cpp,v 1.9 2006/01/05 12:03:52 gpotts Exp $ +#include "ossimImageViewAffineTransform.h" +#include "base/data_types/ossimKeywordlist.h" +#include "base/data_types/ossimMatrix3x3.h" + +RTTI_DEF1(ossimImageViewAffineTransform, "ossimImageViewAffineTransform", ossimImageViewTransform) + +ossimImageViewAffineTransform::ossimImageViewAffineTransform(double rotateDegrees, + double scaleXValue, + double scaleYValue, + double translateXValue, + double translateYValue, + double translateOriginXValue, + double translateOriginYValue) + :theTransform(3,3), + theInverseTransform(3,3), + theRotation(rotateDegrees), + theScale(scaleXValue, scaleYValue), + theTranslate(translateXValue, translateYValue), + theTranslateOrigin(translateOriginXValue, translateOriginYValue) +{ + theTransform << 1 << 0 << 0 + << 0 << 1 << 0 + << 0 << 0 << 1; + + theInverseTransform << 1 << 0 << 0 + << 0 << 1 << 0 + << 0 << 0 << 1; + + + rotate(rotateDegrees); + scale(scaleXValue, scaleYValue); + translate(translateXValue, translateYValue); + translateOrigin(translateOriginXValue, translateOriginYValue); +} + +ossimImageViewAffineTransform::~ossimImageViewAffineTransform() +{ +} + +void ossimImageViewAffineTransform::imageToView(const ossimDpt& imagePoint, + ossimDpt& viewPoint)const +{ + +// viewPoint.x = theTransform[0][0]*(imagePoint.x - translateRotationOriginPoint.x) + theTransform[0][1]*(imagePoint.y - translateRotationOriginPoint.y) + theTransform[0][2]; +// viewPoint.y = theTransform[1][0]*(imagePoint.x - translateRotationOriginPoint.x) + theTransform[1][1]*(imagePoint.y - translateRotationOriginPoint.y) + theTransform[1][2]; + viewPoint.x = theTransform[0][0]*imagePoint.x + theTransform[0][1]*imagePoint.y + theTransform[0][2]; + viewPoint.y = theTransform[1][0]*imagePoint.x + theTransform[1][1]*imagePoint.y + theTransform[1][2]; +} + +void ossimImageViewAffineTransform::viewToImage(const ossimDpt& viewPoint, + ossimDpt& imagePoint)const +{ + +// imagePoint.x = theInverseTransform[0][0]*viewPoint.x + theInverseTransform[0][1]*viewPoint.y + theInverseTransform[0][2] + translateRotationOriginPoint.x; +// imagePoint.y = theInverseTransform[1][0]*viewPoint.x + theInverseTransform[1][1]*viewPoint.y + theInverseTransform[1][2] + translateRotationOriginPoint.y; + imagePoint.x = theInverseTransform[0][0]*viewPoint.x + theInverseTransform[0][1]*viewPoint.y + theInverseTransform[0][2]; + imagePoint.y = theInverseTransform[1][0]*viewPoint.x + theInverseTransform[1][1]*viewPoint.y + theInverseTransform[1][2]; + +} + +void ossimImageViewAffineTransform::setMatrix(NEWMAT::Matrix& matrix) +{ + theTransform = matrix; + theInverseTransform = theTransform.i(); +} + +const NEWMAT::Matrix& ossimImageViewAffineTransform::getMatrix()const +{ + return theTransform; +} + + + +void ossimImageViewAffineTransform::scale(double x, double y) +{ +// NEWMAT::Matrix m(3, 3); + +// m << x << 0 << 0 +// << 0 << y << 0 +// << 0 << 0 << 1; + + +// theTransform = (m*theTransform); + +// theInverseTransform = theTransform.i(); + + theScale = ossimDpt(x,y); + buildCompositeTransform(); +} + +void ossimImageViewAffineTransform::translate(double deltaX, + double deltaY) +{ + theTranslate = ossimDpt(deltaX, deltaY); + buildCompositeTransform(); +// NEWMAT::Matrix m(3,3); + +// m << 1 << 0 << deltaX +// << 0 << 1 << deltaY +// << 0 << 0 << 1; + + +// theTransform = m*theTransform; +// theInverseTransform = theTransform.i(); +} + +void ossimImageViewAffineTransform::translateX(double deltaX) +{ + translate(deltaX, theTranslate.y); +} + +void ossimImageViewAffineTransform::translateY(double deltaY) +{ + translate(theTranslate.x, deltaY); +} + +void ossimImageViewAffineTransform::scaleX(double x) +{ + scale(x, theScale.y); +} + +void ossimImageViewAffineTransform::scaleY(double y) +{ + scale(theScale.x, y); +} + +void ossimImageViewAffineTransform::translateOrigin(double originX, double originY) +{ + theTranslateOrigin.x = originX; + theTranslateOrigin.y = originY; + buildCompositeTransform(); +} + +void ossimImageViewAffineTransform::translateOriginX(double originX) +{ + translateOrigin(originX,theTranslateOrigin.y); +} + +void ossimImageViewAffineTransform::translateOriginY(double originY) +{ + translateOrigin(theTranslateOrigin.x, originY); +} + +void ossimImageViewAffineTransform::rotate(double degrees) +{ + theRotation = degrees; + buildCompositeTransform(); +// theTransform = (theTransform * ossimMatrix3x3::createRotationZMatrix(degrees)); +// theTransform = ossimMatrix3x3::createRotationZMatrix(degrees) * theTransform; + +// theInverseTransform = theTransform.i(); +} + +void ossimImageViewAffineTransform::buildCompositeTransform() +{ + NEWMAT::Matrix scaleM(3, 3); + NEWMAT::Matrix rotzM = ossimMatrix3x3::createRotationZMatrix(theRotation); + NEWMAT::Matrix transM(3,3); + NEWMAT::Matrix transOriginM(3,3); + NEWMAT::Matrix transOriginNegatedM(3,3); + + transM << 1 << 0 << theTranslate.x + << 0 << 1 << theTranslate.y + << 0 << 0 << 1; + + transOriginM << 1 << 0 << theTranslateOrigin.x + << 0 << 1 << theTranslateOrigin.y + << 0 << 0 << 1; + + transOriginNegatedM << 1 << 0 << -theTranslateOrigin.x + << 0 << 1 << -theTranslateOrigin.y + << 0 << 0 << 1; + + scaleM << theScale.x << 0 << 0 + << 0 << theScale.y << 0 + << 0 << 0 << 1; + + theTransform = transOriginM*transM*scaleM*rotzM*transOriginNegatedM; + theInverseTransform = theTransform.i(); + +} + + +bool ossimImageViewAffineTransform::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimString newPrefix = ossimString(prefix) + "transform."; + + const char* lookup = kwl.find(newPrefix.c_str(), + "m11"); + if(lookup) + { + theTransform[0][0] = ossimString(lookup).toDouble(); + } + + lookup = kwl.find(newPrefix.c_str(), + "m12"); + if(lookup) + { + theTransform[0][1] = ossimString(lookup).toDouble(); + } + + lookup = kwl.find(newPrefix.c_str(), + "m13"); + if(lookup) + { + theTransform[0][2] = ossimString(lookup).toDouble(); + } + + lookup = kwl.find(newPrefix.c_str(), + "m21"); + if(lookup) + { + theTransform[1][0] = ossimString(lookup).toDouble(); + } + + lookup = kwl.find(newPrefix.c_str(), + "m22"); + if(lookup) + { + theTransform[1][1] = ossimString(lookup).toDouble(); + } + + lookup = kwl.find(newPrefix.c_str(), + "m23"); + if(lookup) + { + theTransform[1][2] = ossimString(lookup).toDouble(); + } + + lookup = kwl.find(newPrefix.c_str(), + "m31"); + if(lookup) + { + theTransform[2][0] = ossimString(lookup).toDouble(); + } + + lookup = kwl.find(newPrefix.c_str(), + "m32"); + if(lookup) + { + theTransform[2][1] = ossimString(lookup).toDouble(); + } + + lookup = kwl.find(newPrefix.c_str(), + "m33"); + if(lookup) + { + theTransform[2][2] = ossimString(lookup).toDouble(); + } + + lookup = kwl.find(newPrefix.c_str(), + "rotate"); + if(lookup) + { + double degrees = ossimString(lookup).toDouble(); + theTransform *= ossimMatrix3x3::createRotationZMatrix(degrees); + } + theInverseTransform = theTransform.i(); + + return true; +} + +bool ossimImageViewAffineTransform::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + + kwl.add(prefix, + "transform.m11", + theTransform[0][0], + true); + kwl.add(prefix, + "transform.m12", + theTransform[0][1], + true); + kwl.add(prefix, + "transform.m13", + theTransform[0][2], + true); + kwl.add(prefix, + "transform.m21", + theTransform[1][0], + true); + kwl.add(prefix, + "transform.m22", + theTransform[1][1], + true); + kwl.add(prefix, + "transform.m23", + theTransform[1][2], + true); + kwl.add(prefix, + "transform.m31", + theTransform[2][0], + true); + kwl.add(prefix, + "transform.m32", + theTransform[2][1], + true); + kwl.add(prefix, + "transform.m33", + theTransform[2][2], + true); + + return true; +} + +bool ossimImageViewAffineTransform::isValid()const +{ + return true; +} + +bool ossimImageViewAffineTransform::setView(ossimObject* /* obj */, + bool /* ownsProjection*/ ) +{ + return false; +} + +ossimObject* ossimImageViewAffineTransform::getView() +{ + return NULL; +} + +const ossimObject* ossimImageViewAffineTransform::getView()const +{ + return NULL; +} + +ossimDpt ossimImageViewAffineTransform::getInputMetersPerPixel()const +{ + return ossimDpt(1,1); +} + +ossimDpt ossimImageViewAffineTransform::getOutputMetersPerPixel()const +{ + ossimDpt result; + + result.makeNan(); + + return result; +} diff --git a/Utilities/OSSIM/ossim_core/projections/ossimImageViewAffineTransform.h b/Utilities/OSSIM/ossim_core/projections/ossimImageViewAffineTransform.h new file mode 100644 index 0000000000..d724dfbbff --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/ossimImageViewAffineTransform.h @@ -0,0 +1,139 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +//******************************************************************* +// $Id: ossimImageViewAffineTransform.h,v 1.9 2005/08/30 11:50:05 gpotts Exp $ +#ifndef ossimImageViewAffineTransform_HEADER +#define ossimImageViewAffineTransform_HEADER +#include "ossimImageViewTransform.h" +#include "matrix/newmat.h" + +class OSSIMDLLEXPORT ossimImageViewAffineTransform: public ossimImageViewTransform +{ +public: + ossimImageViewAffineTransform(double rotateDegrees = 0, + double scaleXValue = 1, + double scaleYValue = 1, + double translateXValue = 0, + double translateYValue = 0, + double translateOriginXValue = 0, + double translateOriginYValue = 0); + virtual ~ossimImageViewAffineTransform(); + + virtual void imageToView(const ossimDpt& imagePoint, + ossimDpt& viewPoint)const; + virtual void viewToImage(const ossimDpt& viewPoint, + ossimDpt& imagePoint)const; + void setMatrix(NEWMAT::Matrix& matrix); + const NEWMAT::Matrix& getMatrix()const; + + virtual bool isIdentity()const + { + return ((theTransform[0][0] == 1.0)&& + (theTransform[0][1] == 0.0)&& + (theTransform[0][2] == 0.0)&& + (theTransform[1][0] == 0.0)&& + (theTransform[1][1] == 1.0)&& + (theTransform[1][2] == 0.0)&& + (theTransform[2][0] == 0.0)&& + (theTransform[2][1] == 0.0)&& + (theTransform[2][2] == 1.0)); + } + + virtual bool isValid()const; + virtual bool setView(ossimObject* obj, bool ownsProjection=false); + virtual ossimObject* getView(); + virtual const ossimObject* getView()const; + + /** @return (1, 1) ???????(drb) */ + virtual ossimDpt getInputMetersPerPixel()const; + + /** @return (nan, nan) ????????? (drb) */ + virtual ossimDpt getOutputMetersPerPixel()const; + + /*! + * Translate in the x and y direction. + */ + virtual void translate(double deltaX, double deltaY); + + /*! + * Translate in the x direction. + */ + virtual void translateX(double deltaX); + + /*! + * Translate in the Y direction. + */ + virtual void translateY(double deltaY); + + /*! + * Translate the origin for rotation in the x and y direction. + */ + virtual void translateOrigin(double originX, double originY); + + /*! + * Translate the origin for rotation in the x direction. + */ + virtual void translateOriginX(double originX); + + /*! + * Translate the origin for rotation in the y direction. + */ + virtual void translateOriginY(double originY); + + /*! + * will allow you to specify a scale + * for both the x and y direction. + */ + virtual void scale(double x, double y); + + /*! + * will alow you to specify a scale + * along the X direction. + */ + virtual void scaleX(double x); + + /*! + * Will allow you to scale along the Y + * direction. + */ + virtual void scaleY(double y); + + /*! + * Will apply a rotation + */ + virtual void rotate(double degrees); + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix =0); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix =0)const; + +protected: + void buildCompositeTransform(); + + /*! + * This is the transformation from image to + * viewing coordinates. If this matrix is + * changed it will perform an inverse to solve + * the inverse transform. + */ + NEWMAT::Matrix theTransform; + NEWMAT::Matrix theInverseTransform; + ossim_float64 theRotation; + ossimDpt theScale; + ossimDpt theTranslate; + ossimDpt theTranslateOrigin; +// ossimDpt theTranslateRotationOriginPoint; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/ossimImageViewProjectionTransform.cpp b/Utilities/OSSIM/ossim_core/projections/ossimImageViewProjectionTransform.cpp new file mode 100644 index 0000000000..d3fae95774 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/ossimImageViewProjectionTransform.cpp @@ -0,0 +1,476 @@ +//***************************************************************************** +// FILE: ossimImageViewProjectionTransform.cc +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// AUTHOR: Garrett Potts +// +// DESCRIPTION: Contains declaration of ossimImageViewProjectionTransform. +// This class provides an image to view transform that utilizes two +// independent 2D-to-3D projections. Intended for transforming view to +// geographic "world" space to input image space. +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimImageViewProjectionTransform.cpp,v 1.32 2005/09/28 19:23:17 gpotts Exp $ +// +#include <projections/ossimImageViewProjectionTransform.h> +#include <projections/ossimProjection.h> +#include <base/data_types/ossimKeywordlist.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <projections/map_projections/ossimEquDistCylProjection.h> +#include <projections/map_projections/ossimUtmProjection.h> +#include <base/data_types/ossimGeoPolygon.h> +#include <base/data_types/ossimPolyArea2d.h> + +RTTI_DEF1(ossimImageViewProjectionTransform, + "ossimImageViewProjectionTransform", + ossimImageViewTransform); + +//*** +// Define Trace flags for use within this file: +//*** +#include <base/common/ossimTrace.h> +static ossimTrace traceExec ("ossimImageViewProjectionTransform:exec"); +static ossimTrace traceDebug ("ossimImageViewProjectionTransform:debug"); + +//***************************************************************************** +// CONSTRUCTOR: ossimImageViewProjectionTransform +// +//***************************************************************************** +ossimImageViewProjectionTransform::ossimImageViewProjectionTransform +( ossimProjection* imageProjection, + ossimProjection* viewProjection, + bool ownsImageProjectionFlag, + bool ownsViewProjectionFlag) + : + ossimImageViewTransform(), + theImageProjection(imageProjection), + theViewProjection(viewProjection), + theOwnsImageProjFlag(ownsImageProjectionFlag), + theOwnsViewProjFlag(ownsViewProjectionFlag), + theSameProjection(false), + theInputMapProjectionFlag(false), + theOutputMapProjectionFlag(false) +{ + if(!theViewProjection) + { +// theViewProjection = new ossimEquDistCylProjection; + theOwnsViewProjFlag = true; + } + + if(!theImageProjection) + { + theImageProjection = new ossimEquDistCylProjection; + theOwnsImageProjFlag = true; + } +} + +//***************************************************************************** +// DESTRUCTOR: ~ossimImageViewProjectionTransform +// +//***************************************************************************** +ossimImageViewProjectionTransform::~ossimImageViewProjectionTransform() +{ + if(theImageProjection && theOwnsImageProjFlag) + { + delete theImageProjection; + theImageProjection = NULL; + } + if(theViewProjection && theOwnsViewProjFlag) + { + delete theViewProjection; + theViewProjection = NULL; + } +} + +//***************************************************************************** +// METHOD: ossimImageViewProjectionTransform::imageToView +// +//***************************************************************************** +void ossimImageViewProjectionTransform::imageToView +( const ossimDpt& imagePoint, + ossimDpt& viewPoint) const +{ + if(theImageProjection&&theViewProjection) + { + ossimGpt gpt; + +// if(theInputMapProjectionFlag) +// { +// ((ossimMapProjection*)theImageProjection)->lineSampleToWorldIterate(imagePoint, +// gpt); +// } +// else +// { + theImageProjection->lineSampleToWorld(imagePoint, gpt); +// } + + if(gpt.isLatNan()||gpt.isLonNan()) + { + viewPoint.makeNan(); + return; + } + theViewProjection->worldToLineSample(gpt, viewPoint); +#if 0 + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "DEBUG ossimImageViewProjectionTransform::imageToView:" + <<"\n viewPoint: "<<viewPoint + <<"\n gpt: "<<gpt + <<"\n imagePoint: "<<imagePoint<<std::endl; + + } +#endif + } +} + +//***************************************************************************** +// METHOD: ossimImageViewProjectionTransform::viewToImage +// +//***************************************************************************** +void ossimImageViewProjectionTransform::viewToImage +( const ossimDpt& viewPoint, + ossimDpt& imagePoint) const +{ + bool transformed = false; + if(theSameProjection) + { + ossimDpt en; + ossimMapProjection* mapIProj = (ossimMapProjection*)theImageProjection; + ossimMapProjection* mapVProj = (ossimMapProjection*)theViewProjection; + + if(mapIProj&&mapVProj) + { + mapVProj->lineSampleToEastingNorthing(viewPoint, en); + mapIProj->eastingNorthingToLineSample(en, imagePoint); + return; + } + } + + if(!transformed&&theImageProjection&&theViewProjection) + { + ossimGpt gpt; + theViewProjection->lineSampleToWorld(viewPoint, gpt); + if(gpt.isLatNan()||gpt.isLonNan()) + { + imagePoint.makeNan(); + return; + } + theImageProjection->worldToLineSample(gpt, imagePoint); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimImageViewProjectionTransform::viewToImage:" + <<"\n viewPoint: "<<viewPoint + <<"\n gpt: "<<gpt + <<"\n imagePoint: "<<imagePoint<<std::endl; + } +// if(removeError&&!imagePoint.hasNans()&&!viewPoint.hasNans()) +// { +// ossimDpt err; + +// getRoundTripErrorImage(err, ossimIpt(imagePoint)); +// imagePoint+=err; +// if( fabs(imagePoint.x - (int)imagePoint.x) <= FLT_EPSILON) +// { +// imagePoint.x = (int)imagePoint.x; +// } +// if( fabs(imagePoint.y - (int)imagePoint.y) <= FLT_EPSILON) +// { +// imagePoint.y = (int)imagePoint.y; +// } +// } + } +} + +//***************************************************************************** +// METHOD: ossimImageViewProjectionTransform::setViewProjection +// +//***************************************************************************** +void ossimImageViewProjectionTransform::setViewProjection(ossimProjection* viewProjection, bool ownsViewProjection) +{ + if(theViewProjection && + (theViewProjection!=viewProjection) && + theOwnsViewProjFlag) + { + delete theViewProjection; + theViewProjection = (ossimProjection*)NULL; + } + theOwnsViewProjFlag = ownsViewProjection; + theViewProjection = viewProjection; + if(PTR_CAST(ossimMapProjection, + theViewProjection)) + { + theOutputMapProjectionFlag = true; + } + else + { + theOutputMapProjectionFlag = false; + } + checkSameProjection(); +} + +bool ossimImageViewProjectionTransform::setView(ossimObject* baseObject, + bool ownsTheView) +{ + bool result = true; + if(baseObject) + { + // if not null then we will set it if it is of + // our type + ossimProjection* proj = PTR_CAST(ossimProjection, baseObject); + + if(proj) + { + setViewProjection(proj, ownsTheView); + } + else + { + result = false; + } + } + else + { + // if it's null we will just clear the view out + setViewProjection((ossimProjection*)NULL, true); + } + + checkSameProjection(); + return result; +} + +//***************************************************************************** +// METHOD: ossimImageViewProjectionTransform::setImageProjection +// +//***************************************************************************** +void ossimImageViewProjectionTransform::setImageProjection(ossimProjection* imageProjection, bool ownsImageProjection) +{ + if(theImageProjection && + (theImageProjection!=imageProjection) && + theOwnsImageProjFlag) + { + delete theImageProjection; + theImageProjection = (ossimProjection*)NULL; + } + theOwnsImageProjFlag = ownsImageProjection; + theImageProjection = imageProjection; + if(PTR_CAST(ossimMapProjection, + theImageProjection)) + { + theInputMapProjectionFlag = true; + } + else + { + theInputMapProjectionFlag = false; + } + + checkSameProjection(); +} + +//***************************************************************************** +// METHOD: ossimImageViewProjectionTransform::setViewProjection +// +//***************************************************************************** +void ossimImageViewProjectionTransform::setViewProjection(const ossimProjection& viewProjection) +{ + if(theViewProjection && theOwnsViewProjFlag) + { + delete theViewProjection; + theViewProjection = (ossimProjection*)NULL; + } + theViewProjection = (ossimProjection*)viewProjection.dup(); + theOwnsViewProjFlag = true; + if(PTR_CAST(ossimMapProjection, + theViewProjection)) + { + theOutputMapProjectionFlag = true; + } + else + { + theOutputMapProjectionFlag = false; + } + checkSameProjection(); +} + +//***************************************************************************** +// METHOD: ossimImageViewProjectionTransform::setImageProjection +// +//***************************************************************************** +void ossimImageViewProjectionTransform::setImageProjection(const ossimProjection& imageProjection) +{ + if(theImageProjection && theOwnsImageProjFlag) + { + delete theImageProjection; + } + + theImageProjection = (ossimProjection*)imageProjection.dup(); + if(PTR_CAST(ossimMapProjection, + theImageProjection)) + { + theInputMapProjectionFlag = true; + } + theOwnsImageProjFlag = true; + checkSameProjection(); +} + +//***************************************************************************** +// METHOD: ossimImageViewProjectionTransform::print +//***************************************************************************** +std::ostream& ossimImageViewProjectionTransform::print(std::ostream& out)const +{ + if(theImageProjection) + { + out << "image projection: " << endl; + theImageProjection->print(out); + } + if(theViewProjection) + { + out << "view projection: " << endl; + theViewProjection->print(out); + } + return out; +} + +//***************************************************************************** +// METHOD: ossimImageViewProjectionTransform::getImageProjection +//***************************************************************************** +ossimProjection* ossimImageViewProjectionTransform::getImageProjection() +{ + return theImageProjection; +} + +//***************************************************************************** +// METHOD: ossimImageViewProjectionTransform::getViewProjection +// +//***************************************************************************** +ossimProjection* ossimImageViewProjectionTransform::getViewProjection() +{ + return theViewProjection; +} + +ossimDrect ossimImageViewProjectionTransform::getImageToViewBounds(const ossimDrect& imageRect)const +{ + ossimDrect result = ossimImageViewTransform::getImageToViewBounds(imageRect); + + if(result.hasNans()&&theImageProjection&&theViewProjection) + { + ossimGeoPolygon viewClip; + theViewProjection->getGroundClipPoints(viewClip); + if(viewClip.size()) + { + std::vector<ossimPolygon> visiblePolygons; + + std::vector<ossimGpt> imageGpts(4); + const ossimDatum* viewDatum = theViewProjection->origin().datum(); + theImageProjection->lineSampleToWorld(imageRect.ul(), imageGpts[0]); + theImageProjection->lineSampleToWorld(imageRect.ur(), imageGpts[1]); + theImageProjection->lineSampleToWorld(imageRect.lr(), imageGpts[2]); + theImageProjection->lineSampleToWorld(imageRect.ll(), imageGpts[3]); + + imageGpts[0].changeDatum(viewDatum); + imageGpts[1].changeDatum(viewDatum); + imageGpts[2].changeDatum(viewDatum); + imageGpts[3].changeDatum(viewDatum); + + ossimPolyArea2d viewPolyArea(viewClip.getVertexList()); + ossimPolyArea2d imagePolyArea(imageGpts); + viewPolyArea &= imagePolyArea; + viewPolyArea.getAllVisiblePolygons(visiblePolygons); + if(visiblePolygons.size()) + { + + std::vector<ossimDpt> vpts; + ossim_uint32 idx = 0; + for(idx=0; idx<visiblePolygons[0].getNumberOfVertices();++idx) + { + ossimDpt tempPt; + ossimGpt gpt(visiblePolygons[0][idx].lat, + visiblePolygons[0][idx].lon, + 0.0, + viewDatum); + theViewProjection->worldToLineSample(gpt, + tempPt); + vpts.push_back(tempPt); + } + result = ossimDrect(vpts); + } + } + + } + + return result; +} + +//***************************************************************************** +// METHOD: ossimImageViewProjectionTransform::loadState +// +//***************************************************************************** +bool ossimImageViewProjectionTransform::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimString newPrefix = prefix; + + if(theImageProjection) + { + delete theImageProjection; + theImageProjection = NULL; + } + if(theViewProjection) + { + delete theViewProjection; + theViewProjection = NULL; + } + + newPrefix = ossimString(prefix) + "view_proj."; + theViewProjection + = ossimProjectionFactoryRegistry::instance()->createProjection(kwl, newPrefix.c_str()); + + theOwnsImageProjFlag = true; + theOwnsViewProjFlag = true; + if(PTR_CAST(ossimMapProjection, + theImageProjection)) + { + theInputMapProjectionFlag = true; + } + else + { + theInputMapProjectionFlag = false; + } + if(PTR_CAST(ossimMapProjection, + theViewProjection)) + { + theOutputMapProjectionFlag = true; + } + else + { + theOutputMapProjectionFlag = false; + } + + return ossimImageViewTransform::loadState(kwl, prefix); +} + +bool ossimImageViewProjectionTransform::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + if(theViewProjection) + { + theViewProjection->saveState(kwl, + (ossimString(prefix) + "view_proj.").c_str()); + } + kwl.add(prefix, + "type", + STATIC_TYPE_NAME(ossimImageViewProjectionTransform), + true); + + return ossimImageViewTransform::saveState(kwl, prefix); +} + +void ossimImageViewProjectionTransform::checkSameProjection() +{ + theSameProjection = false; +} diff --git a/Utilities/OSSIM/ossim_core/projections/ossimImageViewProjectionTransform.h b/Utilities/OSSIM/ossim_core/projections/ossimImageViewProjectionTransform.h new file mode 100644 index 0000000000..86e9c9058d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/ossimImageViewProjectionTransform.h @@ -0,0 +1,169 @@ +//***************************************************************************** +// FILE: ossimImageViewProjectionTransform.h +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// AUTHOR: Garrett Potts (gpotts@imagelinks.com) +// +// DESCRIPTION: Contains declaration of ossimImageViewProjectionTransform. +// This class provides an image to view transform that utilizes two +// independent 2D-to-3D projections. Intended for transforming view to +// geographic "world" space to input image space. +// +// LIMITATIONS: None. +// +//***************************************************************************** +// $Id: ossimImageViewProjectionTransform.h,v 1.14 2005/09/28 19:23:17 gpotts Exp $ + +#ifndef ossimImageViewProjectionTransform_HEADER +#define ossimImageViewProjectionTransform_HEADER + +#include <projections/ossimImageViewTransform.h> +#include <projections/ossimProjection.h> +#ifndef NULL +#include <stddef.h> +#endif + +class ossimProjection; +class ossimMapProjection; + +class OSSIMDLLEXPORT ossimImageViewProjectionTransform : public ossimImageViewTransform +{ +public: + ossimImageViewProjectionTransform(ossimProjection* imageProjection=NULL, + ossimProjection* viewProjection=NULL, + bool ownsImageProjectionFlag=true, + bool ownsViewProjectionFlag=true); + + virtual ~ossimImageViewProjectionTransform(); + + virtual bool isValid()const + { + return (theImageProjection&&theViewProjection); + } + virtual bool isIdentity()const + { + if(theImageProjection&&theViewProjection) + { + return (*theImageProjection)==(*theViewProjection); + } + + return true; + } + virtual void imageToView(const ossimDpt& imagePoint, + ossimDpt& viewPoint)const; + virtual void viewToImage(const ossimDpt& viewPoint, + ossimDpt& imagePoint)const; + +// virtual void getRoundTripErrorView(ossimDpt& result, +// const ossimDpt& viewPt)const; + +// virtual void getRoundTripErrorImage(ossimDpt& result, +// const ossimDpt& imagePt)const; + /*! + * Will not allocate a new projection. It will just copy + * the pointer and delete the one it owns if they addresses + * are different. It will own the passes in projection. + */ + void setViewProjection(ossimProjection* viewProjection, + bool ownsViewProjection=false); + + /*! + * Will allocate a new projection and copy it. + */ + void setViewProjection(const ossimProjection& viewProjection); + + /*! + * Will not allocate a new projection. It will just copy + * the pointer and delete the one it owns if they addresses + * are different. Flag indicates whether this becomes owner. + */ + void setImageProjection(ossimProjection* imageProjection, + bool ownsImageProjection=false); + + /*! + * Will allocate a new projection and copy it. + */ + void setImageProjection(const ossimProjection& imageProjection); + + virtual std::ostream& print(std::ostream& out) const; + + ossimProjection* getImageProjection(); + ossimProjection* getViewProjection(); + + virtual bool setView(ossimObject* baseObject, + bool ownsTheView = false); + virtual ossimObject* getView() + { + return theViewProjection; + } + virtual const ossimObject* getView()const + { + return theViewProjection; + } + + virtual ossimDpt getInputMetersPerPixel()const + { + ossimDpt result; + + result.makeNan(); + + if(theImageProjection) + { + result = theImageProjection->getMetersPerPixel(); + } + + return result; + } + virtual ossimDpt getOutputMetersPerPixel()const + { + ossimDpt result; + + result.makeNan(); + + if(theViewProjection) + { + result = theViewProjection->getMetersPerPixel(); + } + + return result; + } + virtual ossimDrect getImageToViewBounds(const ossimDrect& imageRect)const; + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix =0); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix = 0)const; +protected: + ossimProjection* theImageProjection; + ossimProjection* theViewProjection; + bool theOwnsImageProjFlag; + bool theOwnsViewProjFlag; + mutable bool theSameProjection; + mutable bool theInputMapProjectionFlag; + mutable bool theOutputMapProjectionFlag; + void checkSameProjection(); +// void findWorldPoint(const ossimDpt& imagePoint, +// ossimGpt& worldPt, +// ossimMapProjection* proj)const; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/ossimImageViewTransform.cpp b/Utilities/OSSIM/ossim_core/projections/ossimImageViewTransform.cpp new file mode 100644 index 0000000000..9d9ef3ebbe --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/ossimImageViewTransform.cpp @@ -0,0 +1,272 @@ +#include <math.h> +#include "base/common/ossimCommon.h" // this is going to be used for the ossimGetSign +#include "ossimImageViewTransform.h" +#include "base/data_types/ossimDrect.h" +#include "base/data_types/ossimIrect.h" + +RTTI_DEF2(ossimImageViewTransform, "ossimImageViewTransform", ossim2dTo2dTransform, ossimViewInterface) + +ossimImageViewTransform::ossimImageViewTransform() + : + ossim2dTo2dTransform(), + ossimViewInterface(NULL) +{ + ossimViewInterface::theObject = this; +} + +void ossimImageViewTransform::forward(const ossimDpt& input, + ossimDpt& output) const +{ + imageToView(input, output); +} + +void ossimImageViewTransform::imageToView(const ossimDpt& imagePoint, + ossimDpt& viewPoint)const +{ + viewPoint = imagePoint; +} + +void ossimImageViewTransform::viewToImage(const ossimDpt& viewPoint, + ossimDpt& imagePoint)const +{ + imagePoint = viewPoint; +} + +ossimDpt ossimImageViewTransform::imageToView(const ossimDpt& imagePoint)const +{ + ossimDpt tempPt; + + imageToView(imagePoint, tempPt); + + return tempPt; +} + +ossimDpt ossimImageViewTransform::viewToImage(const ossimDpt& viewPoint)const +{ + ossimDpt tempPt; + + viewToImage(viewPoint, tempPt); + + return tempPt; +} + +void ossimImageViewTransform::getRoundTripErrorView(ossimDpt& result, + const ossimDpt& /* viewPt */)const +{ + result = ossimDpt(0,0); +} + +ossimDpt ossimImageViewTransform::getRoundTripErrorView(const ossimDpt& viewPt)const +{ + ossimDpt result; + getRoundTripErrorView(result, viewPt); + return result; +} + +void ossimImageViewTransform::getRoundTripErrorImage(ossimDpt& result, + const ossimDpt& /* imagePt */)const +{ + result = ossimDpt(0,0); +} + +ossimDpt ossimImageViewTransform::getRoundTripErrorImage(const ossimDpt& imagePt)const +{ + ossimDpt result; + getRoundTripErrorView(result, imagePt); + return result; +} + +bool ossimImageViewTransform::loadState(const ossimKeywordlist& /* kwl */, + const char* /* prefix */) +{ + return true; +} + +bool ossimImageViewTransform::saveState(ossimKeywordlist& /* kwl */, + const char* /* prefix */)const +{ + return true; +} + +void ossimImageViewTransform::getScaleChangeImageToView(ossimDpt& result, + const ossimDrect& imageRect) +{ + result.makeNan(); + if(!imageRect.hasNans()) + { + ossimDpt vul; + ossimDpt vur; + ossimDpt vlr; + ossimDpt vll; + + imageToView(imageRect.ul(), + vul); + imageToView(imageRect.ur(), + vur); + imageToView(imageRect.lr(), + vlr); + imageToView(imageRect.ll(), + vll); + + if(!vul.hasNans()&& + !vur.hasNans()&& + !vlr.hasNans()&& + !vll.hasNans()) + { + + double deltaTop = (vul - vur).length(); + double deltaBottom = (vll - vlr).length(); + double deltaRight = (vur - vlr).length(); + + double w = imageRect.width(); + double h = imageRect.height(); + result.x = (deltaTop/w + deltaBottom/w)*.5; + result.y = (deltaRight/h + deltaRight/h)*.5; + } + } +} + +void ossimImageViewTransform::getScaleChangeViewToImage(ossimDpt& result, + const ossimDrect& viewRect) +{ + result.makeNan(); + if(!viewRect.hasNans()) + { + ossimDpt iul; + ossimDpt iur; + ossimDpt ilr; + ossimDpt ill; + + imageToView(viewRect.ul(), + iul); + imageToView(viewRect.ur(), + iur); + imageToView(viewRect.lr(), + ilr); + imageToView(viewRect.ll(), + ill); + + if(!iul.hasNans()&& + !iur.hasNans()&& + !ilr.hasNans()&& + !ill.hasNans()) + { + + double deltaTop = (iul - iur).length(); + double deltaBottom = (ill - ilr).length(); + double deltaRight = (iur - ilr).length(); + + double w = viewRect.width(); + double h = viewRect.height(); + result.x = (deltaTop/w + deltaBottom/w)*.5; + result.y = (deltaRight/h + deltaRight/h)*.5; + } + } +} + +void ossimImageViewTransform::getImageToViewScale(ossimDpt& resultScale, + const ossimDpt& imagePoint, + const ossimDpt& deltaImagePointXY)const +{ + ossimDpt p1 = imagePoint; + ossimDpt p2(imagePoint.x + deltaImagePointXY.x, + imagePoint.y); + ossimDpt p3(imagePoint.x, + imagePoint.y + deltaImagePointXY.y); + + ossimDpt transformedP1; + ossimDpt transformedP2; + ossimDpt transformedP3; + + imageToView(p1, transformedP1); + imageToView(p2, transformedP2); + imageToView(p3, transformedP3); + + ossimDpt deltaP1P2 = transformedP1 - transformedP2; + ossimDpt deltaP1P3 = transformedP1 - transformedP3; + + // now compute the distances. + double sumSquaredSqrtP1P2 = sqrt((deltaP1P2.x*deltaP1P2.x) + + (deltaP1P2.y*deltaP1P2.y)); + double sumSquaredSqrtP1P3 = sqrt((deltaP1P3.x*deltaP1P3.x) + + (deltaP1P3.y*deltaP1P3.y)); + + resultScale.x = 0; + resultScale.y = 0; + + if(sumSquaredSqrtP1P2 > FLT_EPSILON) + { + resultScale.x = sumSquaredSqrtP1P2/deltaImagePointXY.x; + } + if(sumSquaredSqrtP1P3 > FLT_EPSILON) + { + resultScale.y = sumSquaredSqrtP1P3/deltaImagePointXY.y; + } +} + +void ossimImageViewTransform::getViewToImageScale(ossimDpt& resultScale, + const ossimDpt& viewPoint, + const ossimDpt& deltaViewPointXY)const +{ + ossimDpt p1 = viewPoint; + ossimDpt p2(viewPoint.x + deltaViewPointXY.x, + viewPoint.y); + ossimDpt p3(viewPoint.x, + viewPoint.y + deltaViewPointXY.y); + + ossimDpt transformedP1; + ossimDpt transformedP2; + ossimDpt transformedP3; + + viewToImage(p1, transformedP1); + viewToImage(p2, transformedP2); + viewToImage(p3, transformedP3); + + ossimDpt deltaP1P2 = transformedP1 - transformedP2; + ossimDpt deltaP1P3 = transformedP1 - transformedP3; + + // now compute the distances. + double sumSquaredSqrtP1P2 = sqrt((deltaP1P2.x*deltaP1P2.x) + + (deltaP1P2.y*deltaP1P2.y)); + double sumSquaredSqrtP1P3 = sqrt((deltaP1P3.x*deltaP1P3.x) + + (deltaP1P3.y*deltaP1P3.y)); + + resultScale.x = 0; + resultScale.y = 0; + + if(sumSquaredSqrtP1P2 > FLT_EPSILON) + { + resultScale.x = sumSquaredSqrtP1P2/deltaViewPointXY.x; + } + if(sumSquaredSqrtP1P3 > FLT_EPSILON) + { + resultScale.y = sumSquaredSqrtP1P3/deltaViewPointXY.y; + } +} + +ossimDrect ossimImageViewTransform::getImageToViewBounds(const ossimDrect& imageRect)const +{ + ossimDpt p1; + ossimDpt p2; + ossimDpt p3; + ossimDpt p4; + + imageToView(imageRect.ul(), p1); + imageToView(imageRect.ur(), p2); + imageToView(imageRect.lr(), p3); + imageToView(imageRect.ll(), p4); + + return ossimDrect(p1, p2, p3, p4); +} + +std::ostream& ossimImageViewTransform::print(std::ostream& out) const +{ + return out; +} + +std::ostream& operator<<(std::ostream& out, + const ossimImageViewTransform& data) +{ + return data.print(out); +} + diff --git a/Utilities/OSSIM/ossim_core/projections/ossimImageViewTransform.h b/Utilities/OSSIM/ossim_core/projections/ossimImageViewTransform.h new file mode 100644 index 0000000000..0445a45a80 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/ossimImageViewTransform.h @@ -0,0 +1,134 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: This class hides the image view transformation process. +// We should be able to open up ay image within the system +// and be able to map it to the view space. Classes need to +// derive and override the methods within this class. This will +// mainly be used in the resampling process. +// +//******************************************************************* +// $Id: ossimImageViewTransform.h,v 1.16 2005/09/28 19:23:17 gpotts Exp $ +#ifndef ossimImageViewTransform_HEADER +#define ossimImageViewTransform_HEADER +#include <iostream> +using namespace std; +#include "base/common/ossimViewInterface.h" +#include "base/common/ossimObject.h" +#include "base/data_types/ossimDpt.h" +#include "base/data_types/ossimDrect.h" +#include "base/misc/ossim2dTo2dTransform.h" + +class OSSIMDLLEXPORT ossimImageViewTransform : public ossim2dTo2dTransform, + public ossimViewInterface +{ +public: + friend OSSIMDLLEXPORT ostream& operator<<(ostream& out, + const ossimImageViewTransform& data); + + ossimImageViewTransform(); + + virtual void forward(const ossimDpt& input, ossimDpt& output) const; + + /*! + * derived classes will specify if the imageViewTransform is an + * identity. + */ + virtual bool isIdentity()const=0; + + + virtual bool isValid()const=0; + virtual ossimDpt getInputMetersPerPixel()const=0; + virtual ossimDpt getOutputMetersPerPixel()const=0; + /*! + * If it needs to it will use the information passed in to get the + * scae factor by transforming the line point.x to point.x+deltaXY and + * point.y to point.y + deltaXY.y. It will comput new delta's and + * set the ratio of deltaXY/newDeltaXY to the result scale. + * + * Derived classes can overide this default implementation. Note: + * if the scale changes are only subpixel then it will return a scale + * of one. We have to see how this works before we actually keep this + * implementation. + */ + virtual void getImageToViewScale(ossimDpt& resultScale, + const ossimDpt& imagePoint, + const ossimDpt& deltaImagePointXY)const; + + /*! + * If it needs to it will use the information passed in to get the + * scae factor by transforming the line point.x to point.x+deltaXY and + * point.y to point.y + deltaXY.y. It will comput new delta's and + * set the ratio of deltaXY/newDeltaXY to the result scale. + * + * Derived classes can overide this default implementation. Note: + * if the scale changes are only subpixel then it will return a scale + * of one. We have to see how this works before we actually keep this + * implementation. + */ + virtual void getViewToImageScale(ossimDpt& resultScale, + const ossimDpt& imagePoint, + const ossimDpt& deltaImagePointXY)const; + + virtual void imageToView(const ossimDpt& imagePoint, + ossimDpt& viewPoint)const; + + virtual void viewToImage(const ossimDpt& viewPoint, + ossimDpt& imagePoint)const; + + virtual std::ostream& print(std::ostream& out) const; + + ossimDpt imageToView(const ossimDpt& imagePoint)const; + + ossimDpt viewToImage(const ossimDpt& viewPoint)const; + + /*! + * This should compute output/input. + */ + virtual void getScaleChangeImageToView(ossimDpt& result, + const ossimDrect& imageRect); + /*! + * This should compute output/input. + */ + virtual void getScaleChangeViewToImage(ossimDpt& result, + const ossimDrect& viewRect); + + virtual void getRoundTripErrorView(ossimDpt& result, + const ossimDpt& viewPt)const; + + virtual ossimDpt getRoundTripErrorView(const ossimDpt& viewPt)const; + + virtual void getRoundTripErrorImage(ossimDpt& result, + const ossimDpt& imagePt)const; + + virtual ossimDpt getRoundTripErrorImage(const ossimDpt& imagePt)const; + + virtual ossimDrect getImageToViewBounds(const ossimDrect& imageRect)const; + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix =0); + + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix = 0)const; + +TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/ossimMapViewController.cpp b/Utilities/OSSIM/ossim_core/projections/ossimMapViewController.cpp new file mode 100644 index 0000000000..34cc364c9d --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/ossimMapViewController.cpp @@ -0,0 +1,215 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossimMapViewController.cpp,v 1.21 2004/12/20 15:07:25 gpotts Exp $ +#include <projections/ossimMapViewController.h> +#include <projections/map_projections/ossimEquDistCylProjection.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <base/common/ossimKeywordNames.h> +#include <base/context/ossimNotifyContext.h> +#include <iostream> +#include <fstream> +using namespace std; + +RTTI_DEF1(ossimMapViewController, "ossimMapViewController", ossimViewController); + +ossimMapViewController::ossimMapViewController() + :ossimViewController() +{ +} + +ossimMapViewController::ossimMapViewController(ossimObject* owner, + ossim_uint32 inputListSize, + ossim_uint32 outputListSize, + bool inputListFixedFlag, + bool outputListFixedFlag) + :ossimViewController(owner, + inputListSize, + outputListSize, + inputListFixedFlag, + outputListFixedFlag) +{ + if(theOwner) + { + const ossimObject* obj = findFirstViewOfType(STATIC_TYPE_INFO(ossimMapProjection)); + ossimMapProjection* proj = PTR_CAST(ossimMapProjection, obj); + + if(proj) + { + // we are initialized to the first view. + theView = proj->dup(); + } + else + { + // initialize the controller to true geographic + theView = new ossimEquDistCylProjection; + } + } + else + { + // initialize the controller to true geographic + theView = new ossimEquDistCylProjection; + } +} + +ossimMapViewController::~ossimMapViewController() +{ +} + +bool ossimMapViewController::setView(ossimObject* object) +{ + if(PTR_CAST(ossimMapProjection, object)) + { + return ossimViewController::setView(object); + } + + return false; +} + +void ossimMapViewController::changeOwner(ossimObject* owner) +{ + ossimConnectableObject::changeOwner(owner); + + if(!theView) + { + // initialize the controller to geographic + const ossimObject* obj = findFirstViewOfType(STATIC_TYPE_INFO(ossimMapProjection)); + ossimMapProjection* proj = PTR_CAST(ossimMapProjection, obj); + + if(proj) + { + // we are initialized to the first view. + setView(proj->dup()); + propagateView(); + } + else + { + // initialize the controller to true geographic + setView(new ossimEquDistCylProjection); + propagateView(); + } + } + else + { + propagateView(); + } +} + +void ossimMapViewController::setFilename(const ossimFilename& file) +{ + if(file.exists()) + { + ossimKeywordlist kwl; + kwl.addFile(file.c_str()); + + ossimProjection* proj = ossimProjectionFactoryRegistry::instance()->createProjection(kwl); + if(PTR_CAST(ossimMapProjection, proj)) + { + setView(proj); + } + else + { + if(proj) + { + delete proj; + } + } + } + + theGeometryFile = file; +} + + +bool ossimMapViewController::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimSource::saveState(kwl, prefix); + ossimMapProjection* proj = PTR_CAST(ossimMapProjection, getView()); + + ossimString newPrefix = prefix; + newPrefix += "projection."; + + if(proj) + { + if(theGeometryFile == "") + { + proj->saveState(kwl, newPrefix.c_str()); + } + else + { + ofstream output(theGeometryFile.c_str()); + if(output) + { + kwl.add(prefix, + ossimKeywordNames::FILENAME_KW, + theGeometryFile); + ossimKeywordlist kwl2; + proj->saveState(kwl2); + kwl2.writeToStream(output); + } + else + { + ossimNotify(ossimNotifyLevel_WARN) << "WARNING ossimMapViewController::saveState can't open filename " << theGeometryFile + << "\nsaving inline to passed in keywordlist" << std::endl; + proj->saveState(kwl, newPrefix); + } + } + } + + return true; +} + +bool ossimMapViewController::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimSource::loadState(kwl, prefix); + + theGeometryFile = kwl.find(prefix, ossimKeywordNames::FILENAME_KW); + ossimProjection* proj=(ossimProjection*)NULL; + + if(theGeometryFile == "") + { + ossimString newPrefix = prefix; + newPrefix += "projection."; + proj = ossimProjectionFactoryRegistry::instance()->createProjection(kwl, newPrefix.c_str()); + } + else + { + ossimKeywordlist kwl2; + kwl2.addFile(theGeometryFile); + + proj = ossimProjectionFactoryRegistry::instance()->createProjection(kwl2); + } + + if(PTR_CAST(ossimMapProjection, proj)) + { + setView(proj); + } + else + { + if(proj) + { + delete proj; + } + } + + return true; +} diff --git a/Utilities/OSSIM/ossim_core/projections/ossimMapViewController.h b/Utilities/OSSIM/ossim_core/projections/ossimMapViewController.h new file mode 100644 index 0000000000..57531ade15 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/ossimMapViewController.h @@ -0,0 +1,72 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks) +// +//************************************************************************* +// $Id: ossimMapViewController.h,v 1.7 2003/05/13 11:31:10 dburken Exp $ +#ifndef ossimMapViewController_HEADER +#define ossimMapViewController_HEADER +#include "base/common/ossimViewController.h" +#include "base/data_types/ossimFilename.h" + +class ossimMapViewController : public ossimViewController +{ +public: + ossimMapViewController(); + ossimMapViewController(ossimObject* owner, + ossim_uint32 inputListSize, + ossim_uint32 outputListSize, + bool inputListFixedFlag=true, + bool outputListFixedFlag=false); + + virtual ~ossimMapViewController(); + virtual bool setView(ossimObject* object); + virtual void changeOwner(ossimObject* owner); + virtual void setFilename(const ossimFilename& file); + virtual const ossimFilename& getFilename()const + { + return theGeometryFile; + } + + virtual ossimString getShortName()const + { + return ossimString("Map View"); + } + + virtual ossimString getLongName()const + { + return ossimString("Map View controller"); + } + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); +protected: + + /*! + * If the file is not "" (empty) then it will + * use this filename to load and save the geometry + * projection. + */ + ossimFilename theGeometryFile; + +TYPE_DATA +}; +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/ossimProjection.cpp b/Utilities/OSSIM/ossim_core/projections/ossimProjection.cpp new file mode 100644 index 0000000000..7557c38807 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/ossimProjection.cpp @@ -0,0 +1,203 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +// Author: Garrett Potts +// +// Description: +// +// Base class for all projections. +//******************************************************************* +// $Id: ossimProjection.cpp,v 1.15 2005/09/28 19:23:17 gpotts Exp $ + +#include <iostream> +#include <iomanip> + +#include <projections/ossimProjection.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/data_types/datum/ossimDatum.h> +#include <base/common/ossimKeywordNames.h> +#include <elevation/ossimElevManager.h> +#include <base/context/ossimNotifyContext.h> +//*** +// Define Trace flags for use within this file: +//*** +#include <base/common/ossimTrace.h> +static ossimTrace traceExec ("ossimProjection:exec"); +static ossimTrace traceDebug ("ossimProjection:debug"); + +using namespace std; + +RTTI_DEF1(ossimProjection, "ossimProjection", ossimObject); + +//******************************************************************* +// Public constructor: +//******************************************************************* +ossimProjection::ossimProjection() +{ +} + +//***************************************************************************** +// METHOD: ossimProjection::saveState() +//***************************************************************************** +bool ossimProjection::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + ossimKeywordNames::TYPE_KW, + TYPE_NAME(this), + true); + + return true; +} + +//***************************************************************************** +// METHOD: ossimProjection::loadState() +//***************************************************************************** +bool ossimProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + return true; +} + +//***************************************************************************** +// METHOD: ossimProjection::worldToLineSample() +// +// Performs forward projection of ground point to image space via iterative +// calls to lineSampleHeightToWorld +// +//***************************************************************************** +void ossimProjection::worldToLineSample(const ossimGpt& worldPoint, + ossimDpt& ip) const +{ + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimProjection::worldToLineSample: entering..." << std::endl; + static const double PIXEL_THRESHOLD = 0.1; // acceptable pixel error + static const int MAX_NUM_ITERATIONS = 20; + + //*** + // First check if the world point is inside bounding rectangle: + //*** + int iters = 0; + double height = worldPoint.hgt; + if ((height == ossimElevSource::DEFAULT_NULL_HEIGHT)|| + (height == OSSIM_DBL_NAN)) + height = 0.0; + + //*** + // Utilize iterative scheme for arriving at image point. Begin with guess + // at image center: + //*** + ip.u = 0; + ip.v = 0; + + ossimDpt ip_du; + ossimDpt ip_dv; + + ossimGpt gp, gp_du, gp_dv; + double dlat_du, dlat_dv, dlon_du, dlon_dv; + double delta_lat, delta_lon, delta_u, delta_v; + double inverse_norm; + + //*** + // Begin iterations: + //*** + do + { + //*** + // establish perturbed image points about the guessed point: + //*** + ip_du.u = ip.u + 1.0; + ip_du.v = ip.v; + ip_dv.u = ip.u; + ip_dv.v = ip.v + 1.0; + + //*** + // Compute numerical partials at current guessed point: + //*** + lineSampleHeightToWorld(ip, height, gp); + lineSampleHeightToWorld(ip_du, height, gp_du); + lineSampleHeightToWorld(ip_dv, height, gp_dv); + + dlat_du = gp_du.lat - gp.lat; //e + dlon_du = gp_du.lon - gp.lon; //g + dlat_dv = gp_dv.lat - gp.lat; //f + dlon_dv = gp_dv.lon - gp.lon; //h + + //*** + // Test for convergence: + //*** + delta_lat = worldPoint.lat - gp.lat; + delta_lon = worldPoint.lon - gp.lon; + + //*** + // Compute linearized estimate of image point given gp delta: + //*** + inverse_norm = dlat_dv*dlon_du - dlat_du*dlon_dv; // fg-eh + if (inverse_norm != 0) + { + delta_u = (-dlon_dv*delta_lat + dlat_dv*delta_lon)/inverse_norm; + delta_v = ( dlon_du*delta_lat - dlat_du*delta_lon)/inverse_norm; + ip.u += delta_u; + ip.v += delta_v; + } + else + { + delta_u = 0; + delta_v = 0; + } + + iters++; + + } while (((fabs(delta_u) > PIXEL_THRESHOLD) || + (fabs(delta_v) > PIXEL_THRESHOLD)) && + (iters < MAX_NUM_ITERATIONS)); + + //*** + // Note that this error mesage appears only if max count was reached while + // iterating. A linear (no iteration) solution would finish with iters = + // MAX_NUM_ITERATIONS + 1: + //*** + if (iters == MAX_NUM_ITERATIONS) + { +// ossimNotify(ossimNotifyLevel_WARN) << "WARNING ossimProjection::worldToLineSample: Exceeded max number of iterations computing image \n" +// << "point for ground point: " << worldPoint +// << "\nCheck the geometry file for valid quantities." << endl; + } + +} + +void ossimProjection::getRoundTripError(const ossimDpt& imagePoint, + ossimDpt& errorResult)const +{ + ossimGpt world; + ossimDpt testPt; + + lineSampleToWorld(imagePoint, world); + worldToLineSample(world, testPt); + + errorResult = imagePoint - testPt; +} + +void ossimProjection::getRoundTripError(const ossimGpt& groundPoint, + ossimDpt& errorResult)const +{ + ossimDpt tempPt; + ossimGpt tempGround; + + worldToLineSample(groundPoint, tempPt); + lineSampleToWorld(tempPt, tempGround); + + errorResult = ossimDpt(groundPoint) - ossimDpt(tempGround); +} + +void ossimProjection::getGroundClipPoints(ossimGeoPolygon& gpts)const +{ +} + +std::ostream& ossimProjection::print(std::ostream& out) const +{ + return ossimErrorStatusInterface::print(out); +} diff --git a/Utilities/OSSIM/ossim_core/projections/ossimProjection.h b/Utilities/OSSIM/ossim_core/projections/ossimProjection.h new file mode 100644 index 0000000000..b1c405ad54 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/ossimProjection.h @@ -0,0 +1,148 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +// +// Description: Base class for all projections (2D-to-3D transform) +// +//******************************************************************* +// $Id: ossimProjection.h,v 1.20 2005/09/28 19:23:17 gpotts Exp $ +#ifndef ossimProjection_HEADER +#define ossimProjection_HEADER +#include <iostream> + +#include <base/common/ossimObject.h> +#include <base/common/ossimErrorStatusInterface.h> +#include <base/data_types/ossimString.h> +#include <base/data_types/ossimKeyword.h> +#include <base/data_types/ossimGpt.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimGeoPolygon.h> +#include <elevation/ossimElevManager.h> + +class OSSIMDLLEXPORT ossimProjection : public ossimObject, + public ossimErrorStatusInterface +{ +public: + /*! + * Constructors, Destructor: + */ + ossimProjection(); + virtual ~ossimProjection() {} + + virtual ossimObject *dup()const=0; + + /*! + * METHOD: origin() + * Returns projection's ground point origin. That is the GP corresponding + * to line=0, sample=0. + */ + virtual ossimGpt origin()const=0; + + /*! + * METHODS: forward(), reverse() + * OBSOLETE -- provided for existing GUI code only. Bogus return value. + */ + virtual ossimDpt forward(const ossimGpt &wp) const; //inline below + virtual ossimGpt inverse(const ossimDpt &pp) const; //inline below + + /*! + * METHOD: worldToLineSample() + * Performs the forward projection from ground point to line, sample. + */ + virtual void worldToLineSample(const ossimGpt& worldPoint, + ossimDpt& lineSampPt) const = 0; + + /*! + * METHOD: lineSampleToWorld() + * Performs the inverse projection from line, sample to ground (world): + */ + virtual void lineSampleToWorld(const ossimDpt& lineSampPt, + ossimGpt& worldPt) const = 0; + + /*! + * METHOD: lineSampleHeightToWorld + * This is the pure virtual that projects the image point to the given + * elevation above ellipsoid, thereby bypassing reference to a DEM. Useful + * for projections that are sensitive to elevation (such as sensor models). + */ + virtual void lineSampleHeightToWorld(const ossimDpt& lineSampPt, + const double& heightAboveEllipsoid, + ossimGpt& worldPt) const = 0; + + virtual void getRoundTripError(const ossimDpt& imagePoint, + ossimDpt& errorResult)const; + + virtual void getRoundTripError(const ossimGpt& groundPoint, + ossimDpt& errorResult)const; + + virtual std::ostream& print(std::ostream& out) const; + + virtual void getGroundClipPoints(ossimGeoPolygon& gpts)const; + /*! + * METHODS: saveState, loadState + * Fulfills ossimObject base-class pure virtuals. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + /*! + * OPERATOR: == + * Compares this instance with arg projection. NOT IMPLEMENTED. + */ + virtual bool operator==(const ossimProjection& projection) const=0; + + /*! + * ACCESS METHODS: + */ + virtual ossimDpt getMetersPerPixel() const=0; + +protected: + + + TYPE_DATA +}; + +//====================== BEGIN INLINE DEFINITIONS =========================== + +//***************************************************************************** +// INLINE METHOD: ossimProjection::forward() +// Projects ground point to 2D plane. +//***************************************************************************** +inline ossimDpt ossimProjection::forward(const ossimGpt &wp) const +{ + ossimDpt p; + worldToLineSample(wp, p); + return p; +} + +//***************************************************************************** +// INLINE METHOD: ossimProjection::inverse() +// Inverse projection from 2D plane to ground point. +//***************************************************************************** +inline ossimGpt ossimProjection::inverse(const ossimDpt &pp) const +{ + ossimGpt g; + lineSampleToWorld(pp, g); + return g; +} + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/ossimQuadProjection.cpp b/Utilities/OSSIM/ossim_core/projections/ossimQuadProjection.cpp new file mode 100644 index 0000000000..7d837f08fb --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/ossimQuadProjection.cpp @@ -0,0 +1,543 @@ +//******************************************************************* +// Copyright (C) 2004 Intelligence Data Systems, Inc. All rights reserved. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts +// +//******************************************************************** +// $Id: ossimQuadProjection.cpp,v 1.3 2004/06/17 14:13:36 dburken Exp $ + +#include <projections/ossimQuadProjection.h> +#include <base/factory/ossimDatumFactory.h> +#include <base/data_types/ossimGpt.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimEcefPoint.h> +#include <base/data_types/ossimEcefVector.h> +#include <base/data_types/ossimDrect.h> +#include <base/data_types/datum/ossimDatum.h> +#include <base/common/ossimKeywordNames.h> +#include <elevation/ossimElevManager.h> + +RTTI_DEF1(ossimQuadProjection, "ossimQuadProjection", ossimProjection); + +ossimQuadProjection::ossimQuadProjection() + :ossimProjection() +{ + theInputRect.makeNan(); + theUlg.makeNan(); + theUrg.makeNan(); + theLrg.makeNan(); + theLlg.makeNan(); +} + +ossimQuadProjection::ossimQuadProjection(const ossimQuadProjection& rhs) + :ossimProjection(rhs), + theInputRect(rhs.theInputRect), + theUlg(rhs.theUlg), + theUrg(rhs.theUrg), + theLrg(rhs.theLrg), + theLlg(rhs.theLlg), + theLatGrid(rhs.theLatGrid), + theLonGrid(rhs.theLonGrid) +{ +} + +ossimQuadProjection::ossimQuadProjection(const ossimIrect& rect, + const ossimGpt& ulg, + const ossimGpt& urg, + const ossimGpt& lrg, + const ossimGpt& llg) + :theInputRect(rect), + theUlg(ulg), + theUrg(urg), + theLrg(lrg), + theLlg(llg) +{ + initializeGrids(); +} + +ossimQuadProjection::~ossimQuadProjection() +{ +} + +ossimObject *ossimQuadProjection::dup()const +{ + return new ossimQuadProjection(*this); +} + +ossimGpt ossimQuadProjection::origin()const +{ + ossimGpt result; + result.makeNan(); + if(theUlg.isLatNan()|| + theUlg.isLonNan()|| + theUrg.isLatNan()|| + theUrg.isLonNan()|| + theLrg.isLatNan()|| + theLrg.isLonNan()|| + theLlg.isLatNan()|| + theLlg.isLonNan()) + { + return result; + } + + result.latd( (theUlg.latd() + theUrg.latd() + theLrg.latd() + theLlg.latd())*.25); + result.lond( (theUlg.lond() + theUrg.lond() + theLrg.lond() + theLlg.lond())*.25); + + result.datum(theUlg.datum()); + + return result; +} + +void ossimQuadProjection::worldToLineSample(const ossimGpt& worldPoint, + ossimDpt& lineSampPt) const +{ + ossimProjection::worldToLineSample(worldPoint, lineSampPt); +} + +void ossimQuadProjection::lineSampleToWorld(const ossimDpt& lineSampPt, + ossimGpt& worldPt) const +{ + lineSampleHeightToWorld(lineSampPt, + OSSIM_DBL_NAN, + worldPt); + +} + +void ossimQuadProjection::lineSampleHeightToWorld(const ossimDpt& lineSampPt, + const double& heightAboveEllipsoid, + ossimGpt& worldPt) const +{ + worldPt.makeNan(); + worldPt.datum(theUlg.datum()); + + if(theUlg.isLatNan()|| + theUlg.isLonNan()|| + theUrg.isLatNan()|| + theUrg.isLonNan()|| + theLrg.isLatNan()|| + theLrg.isLonNan()|| + theLlg.isLatNan()|| + theLlg.isLonNan()|| + theInputRect.hasNans()) + { + return; + } + + if(!theInputRect.pointWithin(lineSampPt)) + { + worldPt = extrapolate(lineSampPt, + heightAboveEllipsoid); + worldPt.hgt = ossimElevManager::instance()->getHeightAboveEllipsoid(worldPt); + return; + } + + worldPt.lat = theLatGrid(lineSampPt); + worldPt.lon = theLonGrid(lineSampPt); + worldPt.hgt = heightAboveEllipsoid; + worldPt.hgt = ossimElevManager::instance()->getHeightAboveEllipsoid(worldPt); +} + +bool ossimQuadProjection::saveState(ossimKeywordlist& kwl, + const char* prefix)const +{ + ossimProjection::saveState(kwl, prefix); + kwl.add(prefix, + ossimKeywordNames::DATUM_KW, + theUlg.datum()->code(), + true); + + if(theInputRect.hasNans()) + { + kwl.add(prefix, + ossimKeywordNames::UL_X_KW, + "nan", + true); + kwl.add(prefix, + ossimKeywordNames::UL_Y_KW, + "nan", + true); + kwl.add(prefix, + "width", + 0, + true); + kwl.add(prefix, + "height", + 0, + true); + } + else + { + kwl.add(prefix, + ossimKeywordNames::UL_X_KW, + theInputRect.ul().x, + true); + kwl.add(prefix, + ossimKeywordNames::UL_Y_KW, + theInputRect.ul().y, + true); + kwl.add(prefix, + "width", + theInputRect.width(), + true); + kwl.add(prefix, + "height", + theInputRect.height(), + true); + } + + if(theUlg.isLatNan()|| + theUlg.isLonNan()|| + theUrg.isLatNan()|| + theUrg.isLonNan()|| + theLrg.isLatNan()|| + theLrg.isLonNan()|| + theLlg.isLatNan()|| + theLlg.isLonNan()) + { + kwl.add(prefix, + ossimKeywordNames::UL_LAT_KW, + "nan", + true); + kwl.add(prefix, + ossimKeywordNames::UL_LON_KW, + "nan", + true); + kwl.add(prefix, + ossimKeywordNames::UR_LAT_KW, + "nan", + true); + kwl.add(prefix, + ossimKeywordNames::UR_LON_KW, + "nan", + true); + kwl.add(prefix, + ossimKeywordNames::LR_LAT_KW, + "nan", + true); + kwl.add(prefix, + ossimKeywordNames::LR_LON_KW, + "nan", + true); + kwl.add(prefix, + ossimKeywordNames::LL_LAT_KW, + "nan", + true); + kwl.add(prefix, + ossimKeywordNames::LL_LON_KW, + "nan", + true); + } + else + { + kwl.add(prefix, + ossimKeywordNames::UL_LAT_KW, + theUlg.latd(), + true); + kwl.add(prefix, + ossimKeywordNames::UL_LON_KW, + theUlg.lond(), + true); + kwl.add(prefix, + ossimKeywordNames::UR_LAT_KW, + theUrg.latd(), + true); + kwl.add(prefix, + ossimKeywordNames::UR_LON_KW, + theUrg.lond(), + true); + kwl.add(prefix, + ossimKeywordNames::LR_LAT_KW, + theLrg.latd(), + true); + kwl.add(prefix, + ossimKeywordNames::LR_LON_KW, + theLrg.lond(), + true); + kwl.add(prefix, + ossimKeywordNames::LL_LAT_KW, + theLlg.latd(), + true); + kwl.add(prefix, + ossimKeywordNames::LL_LON_KW, + theLlg.lond(), + true); + } + return true; +} + +bool ossimQuadProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + ossimProjection::loadState(kwl, prefix); + theUlg.makeNan(); + theUrg.makeNan(); + theLrg.makeNan(); + theLlg.makeNan(); + theInputRect.makeNan(); + + ossimString ulLat = kwl.find(prefix, ossimKeywordNames::UL_LAT_KW); + ossimString ulLon = kwl.find(prefix, ossimKeywordNames::UL_LON_KW); + ossimString urLat = kwl.find(prefix, ossimKeywordNames::UR_LAT_KW); + ossimString urLon = kwl.find(prefix, ossimKeywordNames::UR_LON_KW); + ossimString lrLat = kwl.find(prefix, ossimKeywordNames::LR_LAT_KW); + ossimString lrLon = kwl.find(prefix, ossimKeywordNames::LR_LON_KW); + ossimString llLat = kwl.find(prefix, ossimKeywordNames::LL_LAT_KW); + ossimString llLon = kwl.find(prefix, ossimKeywordNames::LL_LON_KW); + ossimString datum = kwl.find(prefix, ossimKeywordNames::DATUM_KW); + ossimString ulX = kwl.find(prefix, ossimKeywordNames::UL_X_KW); + ossimString ulY = kwl.find(prefix, ossimKeywordNames::UL_Y_KW); + ossimString width = kwl.find(prefix, "width"); + ossimString height = kwl.find(prefix, "height"); + + if(ulLat == "nan") + { + theUlg.latd(OSSIM_DBL_NAN); + } + else + { + theUlg.latd(ulLat.toDouble()); + } + if(ulLon == "nan") + { + theUlg.lond(OSSIM_DBL_NAN); + } + else + { + theUlg.lond(ulLon.toDouble()); + } + + if(urLat == "nan") + { + theUrg.latd(OSSIM_DBL_NAN); + } + else + { + theUrg.latd(urLat.toDouble()); + } + if(urLon == "nan") + { + theUrg.lond(OSSIM_DBL_NAN); + } + else + { + theUrg.lond(urLon.toDouble()); + } + + if(lrLat == "nan") + { + theLrg.latd(OSSIM_DBL_NAN); + } + else + { + theLrg.latd(lrLat.toDouble()); + } + if(lrLon == "nan") + { + theLrg.lond(OSSIM_DBL_NAN); + } + else + { + theLrg.lond(lrLon.toDouble()); + } + + if(llLat == "nan") + { + theLlg.latd(OSSIM_DBL_NAN); + } + else + { + theLlg.latd(llLat.toDouble()); + } + if(llLon == "nan") + { + theLlg.lond(OSSIM_DBL_NAN); + } + else + { + theLlg.lond(llLon.toDouble()); + } + + ossimIpt ul; + + ul.makeNan(); + + if((ulX != "nan") && + (ulY != "nan")) + { + ul.x = ulX.toInt32(); + ul.y = ulY.toInt32(); + } + ossim_uint32 w = width.toUInt32(); + ossim_uint32 h = height.toUInt32(); + if(datum == "") + { + datum = "WGE"; + } + const ossimDatum* datumPtr = ossimDatumFactory::instance()->create(datum); + theUlg.datum(datumPtr); + theUrg.datum(datumPtr); + theLrg.datum(datumPtr); + theLlg.datum(datumPtr); + + if(w&&h) + { + theInputRect = ossimIrect(ul.x, + ul.y, + ul.x + w - 1, + ul.y + h - 1); + } + else + { + theInputRect.makeNan(); + } + + initializeGrids(); + + return true; +} + +bool ossimQuadProjection::operator==(const ossimProjection& projection) const +{ + return false; +} + +ossimDpt ossimQuadProjection::getMetersPerPixel() const +{ + ossimGpt centerG; + ossimGpt rightG; + ossimGpt topG; + + lineSampleToWorld(theInputRect.midPoint(), centerG); + lineSampleToWorld(theInputRect.midPoint()+ossimDpt(1,0), rightG); + lineSampleToWorld(theInputRect.midPoint()+ossimDpt(0,-1), topG); + + ossimEcefPoint centerP = centerG; + ossimEcefPoint rightP = rightG; + ossimEcefPoint topP = topG; + + ossimEcefVector horizontal = rightP-centerP; + ossimEcefVector vertical = topP-centerP; + + ossimDpt result(horizontal.magnitude(), + vertical.magnitude()); + + result.x = (result.x + result.y)/2.0; + result.y = result.x; + + + return result; +} + +void ossimQuadProjection::initializeGrids() +{ + ossimIpt gridSize(2,2); + + ossimDpt spacing = ossimDpt((double)(theInputRect.width()-1)/(gridSize.x-1), + (double)(theInputRect.height()-1)/(gridSize.y-1)); + + theLatGrid.setNullValue(OSSIM_DBL_NAN); + theLonGrid.setNullValue(OSSIM_DBL_NAN); + theLatGrid.initialize(gridSize, theInputRect.ul(), spacing); + theLonGrid.initialize(gridSize, theInputRect.ul(), spacing); + + theLatGrid.setNode(0,0, theUlg.latd()); + theLatGrid.setNode(1,0, theUrg.latd()); + theLatGrid.setNode(1,1, theLrg.latd()); + theLatGrid.setNode(0,1, theLlg.latd()); + + theLonGrid.setNode(0,0, theUlg.lond()); + theLonGrid.setNode(1,0, theUrg.lond()); + theLonGrid.setNode(1,1, theLrg.lond()); + theLonGrid.setNode(0,1, theLlg.lond()); +} + +ossimGpt ossimQuadProjection::extrapolate(const ossimDpt& imagePoint, + const double& height) const +{ + //*** + // If image point supplied has NaN components, return now with a NaN point. + // This prevents an infinite recursion between model worldToLineSample + // and this method: + //*** + if ((imagePoint.line == OSSIM_DBL_NAN) || (imagePoint.samp == OSSIM_DBL_NAN)) + { + return ossimGpt(OSSIM_DBL_NAN, OSSIM_DBL_NAN, OSSIM_DBL_NAN); + } + + //*** + // Determine which edge is intersected by the radial, and establish + // intersection: + //*** + ossimGpt gpt; + ossimDpt edgePt (imagePoint); + ossimDpt image_center (theInputRect.midPoint()); + ossimDrect clipRect = theInputRect; + clipRect.clip(image_center, edgePt); + + //*** + // Need edgePt relative to image center. Compute an epsilon perturbation in + // the direction of edgePt for later computing directional derivative, + // and back out the offset to origin: + //*** + ossimDpt deltaPt (edgePt - image_center); + ossimDpt epsilon (deltaPt/deltaPt.length()); + edgePt -= epsilon; // insure that we are inside the image + ossimDpt edgePt_prime (edgePt - epsilon); // epsilon=1pixel + + //*** + // Establish ground point corresponding to edge point and edgePt+epsilon: + //*** + ossimGpt edgeGP; + ossimGpt edgeGP_prime; + + if (height == OSSIM_DBL_NAN) + { + lineSampleToWorld(edgePt, edgeGP); + lineSampleToWorld(edgePt_prime, edgeGP_prime); + } + else + { + lineSampleHeightToWorld(edgePt, height, edgeGP); + lineSampleHeightToWorld(edgePt_prime, height, edgeGP_prime); + } + + //*** + // Compute approximate directional derivatives of lat and lon along radial + // at the edge: + //*** + double dpixel = (edgePt-edgePt_prime).length(); + double dlat_drad = (edgeGP.lat - edgeGP_prime.lat)/dpixel; + double dlon_drad = (edgeGP.lon - edgeGP_prime.lon)/dpixel; + + //*** + // Now extrapolate to image point of interest: + //*** + double delta_pixel = (imagePoint - edgePt).length(); + + gpt.lat = edgeGP.lat + dlat_drad*delta_pixel; + gpt.lon = edgeGP.lon + dlon_drad*delta_pixel; +// if (height == OSSIM_DBL_NAN) +// { +// gpt.hgt = theElevation->getHeightAboveMSL(gpt); +// } +// else + gpt.hgt = height; + + return gpt; + +} diff --git a/Utilities/OSSIM/ossim_core/projections/ossimQuadProjection.h b/Utilities/OSSIM/ossim_core/projections/ossimQuadProjection.h new file mode 100644 index 0000000000..d99c49f252 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/ossimQuadProjection.h @@ -0,0 +1,88 @@ +//******************************************************************* +// Copyright (C) 2004 Intelligence Data Systems, Inc. All rights reserved. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts +// +//******************************************************************** +// $Id: ossimQuadProjection.h,v 1.3 2004/06/17 14:13:36 dburken Exp $ +#ifndef ossimQuadProjection_HEADER +#define ossimQuadProjection_HEADER + +#include <projections/ossimProjection.h> +#include <base/data_types/ossimIrect.h> +#include <base/data_types/ossimDblGrid.h> + +class ossimQuadProjection : public ossimProjection +{ + public: + ossimQuadProjection(); + ossimQuadProjection(const ossimQuadProjection& rhs); + ossimQuadProjection(const ossimIrect& rect, + const ossimGpt& ulg, + const ossimGpt& urg, + const ossimGpt& lrg, + const ossimGpt& llg); + + virtual ~ossimQuadProjection(); + virtual ossimObject *dup()const; + virtual ossimGpt origin()const; + + virtual void worldToLineSample(const ossimGpt& worldPoint, + ossimDpt& lineSampPt) const; + /*! + * METHOD: lineSampleToWorld() + * Performs the inverse projection from line, sample to ground (world): + */ + virtual void lineSampleToWorld(const ossimDpt& lineSampPt, + ossimGpt& worldPt) const; + + /*! + * METHOD: lineSampleHeightToWorld + * This is the pure virtual that projects the image point to the given + * elevation above ellipsoid, thereby bypassing reference to a DEM. Useful + * for projections that are sensitive to elevation (such as sensor models). + */ + virtual void lineSampleHeightToWorld(const ossimDpt& lineSampPt, + const double& heightAboveEllipsoid, + ossimGpt& worldPt) const; + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0)const; + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual bool operator==(const ossimProjection& projection) const; + virtual ossimDpt getMetersPerPixel() const; + + protected: + ossimIrect theInputRect; + ossimGpt theUlg; + ossimGpt theUrg; + ossimGpt theLrg; + ossimGpt theLlg; + + ossimDblGrid theLatGrid; + ossimDblGrid theLonGrid; + + void initializeGrids(); + ossimGpt extrapolate(const ossimDpt& imagePoint, + const double& height) const; +TYPE_DATA +}; + +#endif /* #ifndef ossimQuadProjection_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/projections/ossimRpcProjection.cpp b/Utilities/OSSIM/ossim_core/projections/ossimRpcProjection.cpp new file mode 100644 index 0000000000..b2d07f3c23 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/ossimRpcProjection.cpp @@ -0,0 +1,788 @@ +//***************************************************************************** +// FILE: ossimRpcModel.cc +// +// Copyright (C) 2004 Intelligence Data Systems. +// +// LGPL +// +// AUTHOR: Garrett Potts +// +//***************************************************************************** +//$Id: ossimRpcProjection.cpp,v 1.4 2005/09/22 11:58:12 gpotts Exp $ + +#include <projections/ossimRpcProjection.h> +#include <base/data_types/ossimEcefPoint.h> +#include <base/data_types/ossimEcefVector.h> + +RTTI_DEF1(ossimRpcProjection, "ossimRpcProjection", ossimProjection); + +#include <base/data_types/ossimGpt.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimKeywordlist.h> +#include <base/common/ossimKeywordNames.h> +#include <cstdio> +#include <fstream> +#include <iostream> +#include <algorithm> + +//*** +// Define Trace flags for use within this file: +//*** +#include <base/common/ossimTrace.h> +static ossimTrace traceExec ("ossimRpcProjection:exec"); +static ossimTrace traceDebug ("ossimRpcProjection:debug"); + +static const int MODEL_VERSION_NUMBER = 1; +static const int NUM_COEFFS = 20; +static const char* MODEL_TYPE = "ossimRpcModel"; +static const char* POLY_TYPE_KW = "polynomial_format"; +static const char* LINE_SCALE_KW = "line_scale"; +static const char* SAMP_SCALE_KW = "samp_scale"; +static const char* LAT_SCALE_KW = "lat_scale"; +static const char* LON_SCALE_KW = "long_scale"; +static const char* HGT_SCALE_KW = "height_scale"; +static const char* LINE_OFFSET_KW = "line_off"; +static const char* SAMP_OFFSET_KW = "samp_off"; +static const char* LAT_OFFSET_KW = "lat_off"; +static const char* LON_OFFSET_KW = "long_off"; +static const char* HGT_OFFSET_KW = "height_off"; +static const char* LINE_NUM_COEF_KW = "line_num_coeff_"; +static const char* LINE_DEN_COEF_KW = "line_den_coeff_"; +static const char* SAMP_NUM_COEF_KW = "samp_num_coeff_"; +static const char* SAMP_DEN_COEF_KW = "samp_den_coeff_"; + +//***************************************************************************** +// DEFAULT CONSTRUCTOR: ossimRpcModel() +// +//***************************************************************************** +ossimRpcProjection::ossimRpcProjection() + : ossimProjection() + { + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection Default Constructor: entering..." << std::endl; + + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection Default Constructor: returning..." << std::endl; +} + +//***************************************************************************** +// COPY CONSTRUCTOR: ossimRpcProjection(ossimRpcProjection) +// +//***************************************************************************** +ossimRpcProjection::ossimRpcProjection(const ossimRpcProjection& model) + : + ossimProjection(model), + thePolyType (model.thePolyType), + theLineScale (model.theLineScale), + theSampScale (model.theSampScale), + theLatScale (model.theLatScale), + theLonScale (model.theLonScale), + theHgtScale (model.theHgtScale), + theLineOffset (model.theLineOffset), + theSampOffset (model.theSampOffset), + theLatOffset (model.theLatOffset), + theLonOffset (model.theLonOffset), + theHgtOffset (model.theHgtOffset) +{ + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection Copy Constructor: entering..." << std::endl; + + for (int i=0; i<20; i++) + { + theLineNumCoef[i] = model.theLineNumCoef[i]; + theLineDenCoef[i] = model.theLineDenCoef[i]; + theSampNumCoef[i] = model.theSampNumCoef[i]; + theSampDenCoef[i] = model.theSampDenCoef[i]; + } + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection Copy Constructor: returning..." << std::endl; +} + +//***************************************************************************** +// DESTRUCTOR: ~ossimRpcProjection() +// +//***************************************************************************** +ossimRpcProjection::~ossimRpcProjection() +{ + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ~ossimRpcProjection() Destructor: entering..." << std::endl; + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimNotify(ossimNotifyLevel_DEBUG): returning..." << std::endl; +} + +void ossimRpcProjection::setAttributes(ossim_float64 sampleOffset, + ossim_float64 lineOffset, + ossim_float64 sampleScale, + ossim_float64 lineScale, + ossim_float64 latOffset, + ossim_float64 lonOffset, + ossim_float64 heightOffset, + ossim_float64 latScale, + ossim_float64 lonScale, + ossim_float64 heightScale, + const std::vector<double>& xNumeratorCoeffs, + const std::vector<double>& xDenominatorCoeffs, + const std::vector<double>& yNumeratorCoeffs, + const std::vector<double>& yDenominatorCoeffs, + PolynomialType polyType) +{ + thePolyType = polyType; + + theLineScale = lineScale; + theSampScale = sampleScale; + theLatScale = latScale; + theLonScale = lonScale; + theHgtScale = heightScale; + theLineOffset = lineOffset; + theSampOffset = sampleOffset; + theLatOffset = latOffset; + theLonOffset = lonOffset; + theHgtOffset = heightOffset; + + if(xNumeratorCoeffs.size() == 20) + { + std::copy(xNumeratorCoeffs.begin(), + xNumeratorCoeffs.end(), + theSampNumCoef); + } + if(xDenominatorCoeffs.size() == 20) + { + std::copy(xDenominatorCoeffs.begin(), + xDenominatorCoeffs.end(), + theSampDenCoef); + } + if(yNumeratorCoeffs.size() == 20) + { + std::copy(yNumeratorCoeffs.begin(), + yNumeratorCoeffs.end(), + theLineNumCoef); + } + if(yDenominatorCoeffs.size() == 20) + { + std::copy(yDenominatorCoeffs.begin(), + yDenominatorCoeffs.end(), + theLineDenCoef); + } +} + + +//***************************************************************************** +// METHOD: ossimRpcProjection::worldToLineSample() +// +// Overrides base class implementation. Directly computes line-sample from +// the polynomials. +//***************************************************************************** +void ossimRpcProjection::worldToLineSample(const ossimGpt& ground_point, + ossimDpt& imgPt) const +{ + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection::worldToLineSample(): entering..." << std::endl; + + if(ground_point.isLatNan() || + ground_point.isLonNan() ) + { + imgPt.makeNan(); + return; + } + //*** + // Normalize the lat, lon, hgt: + //*** + double nlat = (ground_point.lat - theLatOffset) / theLatScale; + double nlon = (ground_point.lon - theLonOffset) / theLonScale; + double nhgt; + + if(ground_point.hgt == OSSIM_DBL_NAN) + { + nhgt = (theHgtScale - theHgtOffset) / theHgtScale; + } + else + { + nhgt = (ground_point.hgt - theHgtOffset) / theHgtScale; + } + // + // Compute the adjusted, normalized line (U) and sample (V): + // + imgPt.x = (polynomial(nlat, nlon, nhgt, theSampNumCoef)/ + polynomial(nlat, nlon, nhgt, theSampDenCoef))*theSampScale + theSampOffset; + + imgPt.y = (polynomial(nlat, nlon, nhgt, theLineNumCoef)/ + polynomial(nlat, nlon, nhgt, theLineDenCoef))*theLineScale + theLineOffset ; + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection::worldToLineSample(): returning..." << std::endl; + + return; +} + +void ossimRpcProjection::lineSampleToWorld(const ossimDpt& imagePoint, + ossimGpt& worldPoint) const +{ + if(!imagePoint.hasNans()) + { + lineSampleHeightToWorld(imagePoint, + worldPoint.height(), + worldPoint); + } + else + { + worldPoint.makeNan(); + } +} + +//***************************************************************************** +// METHOD: ossimRpcProjection::lineSampleHeightToWorld() +// +// Performs reverse projection of image line/sample to ground point. +// The imaging ray is intersected with a level plane at height = elev. +// +// NOTE: U = line, V = sample -- this differs from the convention. +// +//***************************************************************************** +void ossimRpcProjection::lineSampleHeightToWorld(const ossimDpt& image_point, + const double& ellHeight, + ossimGpt& gpt) const +{ + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection::lineSampleHeightToWorld: entering..." << std::endl; + + // + // Constants for convergence tests: + // + static const int MAX_NUM_ITERATIONS = 10; + static const double CONVERGENCE_EPSILON = 0.1; // pixels + + // + // The image point must be adjusted by the adjustable parameters as well + // as the scale and offsets given as part of the RPC param normalization. + // + // NOTE: U = line, V = sample + // + double U = (image_point.y-theLineOffset)/(theLineScale); + double V = (image_point.x-theSampOffset)/(theSampScale); + + + // now apply adjust intrack and cross track + //*** + // Initialize quantities to be used in the iteration for ground point: + //*** + double nlat = 0.0; // normalized latitude + double nlon = 0.0; // normalized longitude + + double nhgt; + + if(ellHeight == OSSIM_DBL_NAN) + { + nhgt = (theHgtScale - theHgtOffset) / theHgtScale; // norm height + } + else + { + nhgt = (ellHeight - theHgtOffset) / theHgtScale; // norm height + } + + double epsilonU = CONVERGENCE_EPSILON/(theLineScale); + double epsilonV = CONVERGENCE_EPSILON/(theSampScale); + int iteration = 0; + + //*** + // Declare variables only once outside the loop. These include: + // * polynomials (numerators Pu, Pv, and denominators Qu, Qv), + // * partial derivatives of polynomials wrt X, Y, + // * computed normalized image point: Uc, Vc, + // * residuals of normalized image point: deltaU, deltaV, + // * partial derivatives of Uc and Vc wrt X, Y, + // * corrections to normalized lat, lon: deltaLat, deltaLon. + //*** + double Pu, Qu, Pv, Qv; + double dPu_dLat, dQu_dLat, dPv_dLat, dQv_dLat; + double dPu_dLon, dQu_dLon, dPv_dLon, dQv_dLon; + double Uc, Vc; + double deltaU, deltaV; + double dU_dLat, dU_dLon, dV_dLat, dV_dLon, W; + double deltaLat, deltaLon; + + //*** + // Now iterate until the computed Uc, Vc is within epsilon of the desired + // image point U, V: + //*** + do + { + //*** + // Calculate the normalized line and sample Uc, Vc as ratio of + // polynomials Pu, Qu and Pv, Qv: + //*** + Pu = polynomial(nlat, nlon, nhgt, theLineNumCoef); + Qu = polynomial(nlat, nlon, nhgt, theLineDenCoef); + Pv = polynomial(nlat, nlon, nhgt, theSampNumCoef); + Qv = polynomial(nlat, nlon, nhgt, theSampDenCoef); + Uc = Pu/Qu; + Vc = Pv/Qv; + + //*** + // Compute residuals between desired and computed line, sample: + //*** + deltaU = U - Uc; + deltaV = V - Vc; + + //*** + // Check for convergence and skip re-linearization if converged: + //*** + if ((fabs(deltaU) > epsilonU) || (fabs(deltaV) > epsilonV)) + { + //*** + // Analytically compute the partials of each polynomial wrt lat, lon: + //*** + dPu_dLat = dPoly_dLat(nlat, nlon, nhgt, theLineNumCoef); + dQu_dLat = dPoly_dLat(nlat, nlon, nhgt, theLineDenCoef); + dPv_dLat = dPoly_dLat(nlat, nlon, nhgt, theSampNumCoef); + dQv_dLat = dPoly_dLat(nlat, nlon, nhgt, theSampDenCoef); + dPu_dLon = dPoly_dLon(nlat, nlon, nhgt, theLineNumCoef); + dQu_dLon = dPoly_dLon(nlat, nlon, nhgt, theLineDenCoef); + dPv_dLon = dPoly_dLon(nlat, nlon, nhgt, theSampNumCoef); + dQv_dLon = dPoly_dLon(nlat, nlon, nhgt, theSampDenCoef); + + //*** + // Analytically compute partials of quotients U and V wrt lat, lon: + //*** + dU_dLat = (Qu*dPu_dLat - Pu*dQu_dLat)/(Qu*Qu); + dU_dLon = (Qu*dPu_dLon - Pu*dQu_dLon)/(Qu*Qu); + dV_dLat = (Qv*dPv_dLat - Pv*dQv_dLat)/(Qv*Qv); + dV_dLon = (Qv*dPv_dLon - Pv*dQv_dLon)/(Qv*Qv); + + W = dU_dLon*dV_dLat - dU_dLat*dV_dLon; + + //*** + // Now compute the corrections to normalized lat, lon: + //*** + deltaLat = (dU_dLon*deltaV - dV_dLon*deltaU) / W; + deltaLon = (dV_dLat*deltaU - dU_dLat*deltaV) / W; + nlat += deltaLat; + nlon += deltaLon; + } + + iteration++; + + } while (((fabs(deltaU)>epsilonU) || (fabs(deltaV)>epsilonV)) + && (iteration < MAX_NUM_ITERATIONS)); + + //*** + // Test for exceeding allowed number of iterations. Flag error if so: + //*** + if (iteration == MAX_NUM_ITERATIONS) + { + ossimNotify(ossimNotifyLevel_WARN) << "WARNING ossimRpcProjection::lineSampleHeightToWorld: \nMax number of iterations reached in ground point " + << "solution. Results are inaccurate." << endl; + } + + //*** + // Now un-normalize the ground point lat, lon and establish return quantity: + //*** + gpt.lat = nlat*theLatScale + theLatOffset; + gpt.lon = nlon*theLonScale + theLonOffset; + gpt.hgt = ellHeight; + +} + +ossimGpt ossimRpcProjection::origin()const +{ + return ossimGpt(theLatOffset, + theLonOffset, + theHgtOffset); +} + + +ossimDpt ossimRpcProjection::getMetersPerPixel() const +{ + ossimDpt left = ossimDpt(theSampOffset-1, + theLineOffset); + ossimDpt right = ossimDpt(theSampOffset+1, + theLineOffset); + ossimDpt top = ossimDpt(theSampOffset, + theLineOffset-1); + ossimDpt bottom = ossimDpt(theSampOffset, + theLineOffset+1); + ossimGpt leftG; + ossimGpt rightG; + ossimGpt topG; + ossimGpt bottomG; + + lineSampleToWorld(left, leftG); + lineSampleToWorld(right, rightG); + lineSampleToWorld(top, topG); + lineSampleToWorld(bottom, bottomG); + + ossimDpt result; + + result.x = (ossimEcefPoint(leftG) - ossimEcefPoint(rightG)).magnitude()/2.0; + result.y = (ossimEcefPoint(topG) - ossimEcefPoint(bottomG)).magnitude()/2.0; + + return result; +} + +bool ossimRpcProjection::operator==(const ossimProjection& projection) const +{ + if(&projection == this) return true; + + // not implemented yet + // + return false; +} + +//***************************************************************************** +// PRIVATE METHOD: ossimRpcProjection::polynomial +// +// Computes polynomial. +// +//***************************************************************************** +double ossimRpcProjection::polynomial(const double& P, const double& L, + const double& H, const double* c) const +{ + double r; + + if (thePolyType == A) + { + r = c[ 0] + c[ 1]*L + c[ 2]*P + c[ 3]*H + + c[ 4]*L*P + c[ 5]*L*H + c[ 6]*P*H + c[ 7]*L*P*H + + c[ 8]*L*L + c[ 9]*P*P + c[10]*H*H + c[11]*L*L*L + + c[12]*L*L*P + c[13]*L*L*H + c[14]*L*P*P + c[15]*P*P*P + + c[16]*P*P*H + c[17]*L*H*H + c[18]*P*H*H + c[19]*H*H*H; + } + else + { + r = c[ 0] + c[ 1]*L + c[ 2]*P + c[ 3]*H + + c[ 4]*L*P + c[ 5]*L*H + c[ 6]*P*H + c[ 7]*L*L + + c[ 8]*P*P + c[ 9]*H*H + c[10]*L*P*H + c[11]*L*L*L + + c[12]*L*P*P + c[13]*L*H*H + c[14]*L*L*P + c[15]*P*P*P + + c[16]*P*H*H + c[17]*L*L*H + c[18]*P*P*H + c[19]*H*H*H; + } + + return r; +} + +//***************************************************************************** +// PRIVATE METHOD: ossimRpcProjection::dPoly_dLat +// +// Computes derivative of polynomial wrt normalized Latitude P. +// +//***************************************************************************** +double ossimRpcProjection::dPoly_dLat(const double& P, const double& L, + const double& H, const double* c) const +{ + double dr; + + if (thePolyType == A) + { + dr = c[2] + c[4]*L + c[6]*H + c[7]*L*H + 2*c[9]*P + c[12]*L*L + + 2*c[14]*L*P + 3*c[15]*P*P +2*c[16]*P*H + c[18]*H*H; + } + else + { + dr = c[2] + c[4]*L + c[6]*H + 2*c[8]*P + c[10]*L*H + 2*c[12]*L*P + + c[14]*L*L + 3*c[15]*P*P + c[16]*H*H + 2*c[18]*P*H; + } + + return dr; +} + +//***************************************************************************** +// PRIVATE METHOD: ossimRpcProjection::dPoly_dLon +// +// Computes derivative of polynomial wrt normalized Longitude L. +// +//***************************************************************************** +double ossimRpcProjection::dPoly_dLon(const double& P, const double& L, + const double& H, const double* c) const +{ + double dr; + + if (thePolyType == A) + { + dr = c[1] + c[4]*P + c[5]*H + c[7]*P*H + 2*c[8]*L + 3*c[11]*L*L + + 2*c[12]*L*P + 2*c[13]*L*H + c[14]*P*P + c[17]*H*H; + } + else + { + dr = c[1] + c[4]*P + c[5]*H + 2*c[7]*L + c[10]*P*H + 3*c[11]*L*L + + c[12]*P*P + c[13]*H*H + 2*c[14]*P*L + 2*c[17]*L*H; + } + return dr; +} + +//***************************************************************************** +// METHOD: ossimRpcProjection::print() +// +// Formatted dump of data members. +// +//***************************************************************************** +std::ostream& ossimRpcProjection::print(std::ostream& out) const +{ + out << "\nDump of ossimRpcProjection object at " << hex << this << ":\n" + << POLY_TYPE_KW << ": " << thePolyType << "\n" + << LINE_SCALE_KW << ": " << theLineScale << "\n" + << SAMP_SCALE_KW << ": " << theSampScale << "\n" + << LAT_SCALE_KW << ": " << theLatScale << "\n" + << LON_SCALE_KW << ": " << theLonScale << "\n" + << HGT_SCALE_KW << ": " << theHgtScale << "\n" + << LINE_OFFSET_KW << ": " << theLineOffset << "\n" + << SAMP_OFFSET_KW << ": " << theSampOffset << "\n" + << LAT_OFFSET_KW << ": " << theLatOffset << "\n" + << LON_OFFSET_KW << ": " << theLonOffset << "\n" + << HGT_OFFSET_KW << ": " << theHgtOffset << endl; + + for (int i=0; i<NUM_COEFFS; i++) + out<<" "<<LINE_NUM_COEF_KW<<"["<<i<<"]: "<<theLineNumCoef[i]<<endl; + + out << endl; + for (int i=0; i<NUM_COEFFS; i++) + out<<" "<<LINE_DEN_COEF_KW<<"["<<i<<"]: "<<theLineDenCoef[i]<<endl; + + out << endl; + for (int i=0; i<NUM_COEFFS; i++) + out<<" "<<SAMP_NUM_COEF_KW<<"["<<i<<"]: "<<theSampNumCoef[i]<<endl; + + out << endl; + for (int i=0; i<NUM_COEFFS; i++) + out<<" "<<SAMP_DEN_COEF_KW<<"["<<i<<"]: "<<theSampDenCoef[i]<<endl; + + out << endl; + + return ossimProjection::print(out); +} + +//***************************************************************************** +// METHOD: ossimRpcProjection::saveState() +// +// Saves the model state to the KWL. This KWL also serves as a geometry file. +// +//***************************************************************************** +bool ossimRpcProjection::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection::saveState(): entering..." << std::endl; + + kwl.add(prefix, ossimKeywordNames::TYPE_KW, MODEL_TYPE); + + //*** + // Hand off to base class for common stuff: + //*** + ossimProjection::saveState(kwl, prefix); + + kwl.add(prefix, + POLY_TYPE_KW, + (char)thePolyType, + true); + + kwl.add(prefix, LINE_SCALE_KW, theLineScale); + kwl.add(prefix, SAMP_SCALE_KW, theSampScale); + kwl.add(prefix, LAT_SCALE_KW, theLatScale); + kwl.add(prefix, LON_SCALE_KW, theLonScale); + kwl.add(prefix, HGT_SCALE_KW, theHgtScale); + kwl.add(prefix, LINE_OFFSET_KW, theLineOffset); + kwl.add(prefix, SAMP_OFFSET_KW, theSampOffset); + kwl.add(prefix, LAT_OFFSET_KW, theLatOffset); + kwl.add(prefix, LON_OFFSET_KW, theLonOffset); + + kwl.add(prefix, HGT_OFFSET_KW, theHgtOffset); + + for (int i=0; i<NUM_COEFFS; i++) + { + kwl.add(prefix, (LINE_NUM_COEF_KW + ossimString::toString(i)).c_str(), theLineNumCoef[i]); + kwl.add(prefix, (LINE_DEN_COEF_KW + ossimString::toString(i)).c_str(), theLineDenCoef[i]); + kwl.add(prefix, (SAMP_NUM_COEF_KW + ossimString::toString(i)).c_str(), theSampNumCoef[i]); + kwl.add(prefix, (SAMP_DEN_COEF_KW + ossimString::toString(i)).c_str(), theSampDenCoef[i]); + } + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection::saveState(): returning..." << std::endl; + return true; +} + +//***************************************************************************** +// METHOD: ossimRpcProjection::loadState() +// +// Restores the model's state from the KWL. This KWL also serves as a +// geometry file. +// +//***************************************************************************** +bool ossimRpcProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection::loadState(): entering..." << std::endl; + + const char* value; + const char* keyword; + + //*** + // Pass on to the base-class for parsing first: + //*** + bool success = ossimProjection::loadState(kwl, prefix); + if (!success) + { + theErrorStatus++; + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection::loadState(): returning with error..." << std::endl; + return false; + } + + //*** + // Continue parsing for local members: + //*** + keyword = POLY_TYPE_KW; + value = kwl.find(prefix, keyword); + if (!value) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: " + << "<" << keyword << ">. Check the keywordlist for proper syntax." + << std::endl; + return false; + } + thePolyType = (PolynomialType) value[0]; + + keyword = LINE_SCALE_KW; + value = kwl.find(prefix, keyword); + if (!value) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: " + << "<" << keyword << ">. Check the keywordlist for proper syntax." + << std::endl; + return false; + } + theLineScale = ossimString(value).toDouble(); + + keyword = SAMP_SCALE_KW; + value = kwl.find(prefix, keyword); + if (!value) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: " + << "<" << keyword << ">. Check the keywordlist for proper syntax." + << std::endl; + return false; + } + theSampScale = ossimString(value).toDouble(); + + keyword = LAT_SCALE_KW; + value = kwl.find(prefix, keyword); + if (!value) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: " + << "<" << keyword << ">. Check the keywordlist for proper syntax." + << std::endl; + return false; + } + theLatScale = ossimString(value).toDouble(); + + keyword = LON_SCALE_KW; + value = kwl.find(prefix, keyword); + if (!value) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: " + << "<" << keyword << ">. Check the keywordlist for proper syntax." + << std::endl; + return false; + } + theLonScale = ossimString(value).toDouble(); + + keyword = HGT_SCALE_KW; + value = kwl.find(prefix, keyword); + if (!value) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: " + << "<" << keyword << ">. Check the keywordlist for proper syntax." + << std::endl; + return false; + } + theHgtScale = ossimString(value).toDouble(); + + keyword = LINE_OFFSET_KW; + value = kwl.find(prefix, keyword); + if (!value) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: " + << "<" << keyword << ">. Check the keywordlist for proper syntax." + << std::endl; + return false; + } + theLineOffset = ossimString(value).toDouble(); + + keyword = SAMP_OFFSET_KW; + value = kwl.find(prefix, keyword); + if (!value) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: " + << "<" << keyword << ">. Check the keywordlist for proper syntax." + << std::endl; + return false; + } + theSampOffset = ossimString(value).toDouble(); + + keyword = LAT_OFFSET_KW; + value = kwl.find(prefix, keyword); + if (!value) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: " + << "<" << keyword << ">. Check the keywordlist for proper syntax." + << std::endl; + return false; + } + theLatOffset = ossimString(value).toDouble(); + + keyword = LON_OFFSET_KW; + value = kwl.find(prefix, keyword); + if (!value) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: " + << "<" << keyword << ">. Check the keywordlist for proper syntax." + << std::endl; + return false; + } + theLonOffset = ossimString(value).toDouble(); + + keyword = HGT_OFFSET_KW; + value = kwl.find(prefix, keyword); + if (!value) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: " + << "<" << keyword << ">. Check the keywordlist for proper syntax." + << std::endl; + return false; + } + theHgtOffset = ossimString(value).toDouble(); + + for (int i=0; i<NUM_COEFFS; i++) + { + value = kwl.find(prefix, (LINE_NUM_COEF_KW+ossimString::toString(i)).c_str()); + if (!value) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: " + << "<" << keyword << ">. Check the keywordlist for proper syntax." + << std::endl; + return false; + } + theLineNumCoef[i] = ossimString(value).toDouble(); + + value = kwl.find(prefix, (LINE_DEN_COEF_KW+ossimString::toString(i)).c_str()); + if (!value) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: " + << "<" << keyword << ">. Check the keywordlist for proper syntax." + << std::endl; + return false; + } + theLineDenCoef[i] = ossimString(value).toDouble(); + + value = kwl.find(prefix, (SAMP_NUM_COEF_KW+ossimString::toString(i)).c_str()); + if (!value) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: " + << "<" << keyword << ">. Check the keywordlist for proper syntax." + << std::endl; + return false; + } + theSampNumCoef[i] = ossimString(value).toDouble(); + + value = kwl.find(prefix, (SAMP_DEN_COEF_KW+ossimString::toString(i)).c_str()); + if (!value) + { + ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: " + << "<" << keyword << ">. Check the keywordlist for proper syntax." + << std::endl; + return false; + } + theSampDenCoef[i] = ossimString(value).toDouble(); + } + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection::loadState(): returning..." << std::endl; + + return true; +} diff --git a/Utilities/OSSIM/ossim_core/projections/ossimRpcProjection.h b/Utilities/OSSIM/ossim_core/projections/ossimRpcProjection.h new file mode 100644 index 0000000000..589555b4c9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/ossimRpcProjection.h @@ -0,0 +1,151 @@ +//***************************************************************************** +// FILE: ossimRpcProjection.h +// +// Copyright (C) 2004 Intelligence Data Syatems +// +// LGPL +// +// DESCRIPTION: Contains declaration of class ossimRpcProjection. +// This is a replacement model utilizing the Rational Polynomial Coefficients +// (RPC), a.k.a. Rapid Positioning Capability, and Universal Sensor Model +// (USM). +// +//***************************************************************************** +// $Id: ossimRpcProjection.h,v 1.2 2005/09/09 19:23:58 gpotts Exp $ + +#ifndef ossimRpcProjection_HEADER +#define ossimRpcProjection_HEADER + +#include <projections/ossimProjection.h> +#include <base/data_types/ossimIpt.h> + +/*!**************************************************************************** + * + * CLASS: ossimRpcProjection + * + *****************************************************************************/ +class OSSIM_DLL ossimRpcProjection : public ossimProjection +{ +public: + //*** + // Enumeration of supported RPC polynomial formats: + //*** + enum PolynomialType + { + A='A', // corresponds to "RPC00A" + B='B' // corresponds to "RPC00B" + }; + + /*! + * CONSTRUCTORS: + */ + ossimRpcProjection(); + ossimRpcProjection(const ossimRpcProjection& copy_this); + ~ossimRpcProjection(); + + void setAttributes(ossim_float64 theSampleOffset, + ossim_float64 theLineOffset, + ossim_float64 theSampleScale, + ossim_float64 theLineScale, + ossim_float64 theLatOffset, + ossim_float64 theLonOffset, + ossim_float64 theHeightOffset, + ossim_float64 theLatScale, + ossim_float64 theLonScale, + ossim_float64 theHeightScale, + const std::vector<double>& xNumeratorCoeffs, + const std::vector<double>& xDenominatorCoeffs, + const std::vector<double>& yNumeratorCoeffs, + const std::vector<double>& yDenominatorCoeffs, + PolynomialType polyType = B); + + /*! + * METHOD: worldToLineSample() + * Overrides base class implementation. Directly computes line-sample from + * the polynomials. + */ + virtual void worldToLineSample(const ossimGpt& world_point, + ossimDpt& image_point) const; + /*! + * METHOD: print() + * Extends base-class implementation. Dumps contents of object to ostream. + */ + virtual std::ostream& print(std::ostream& out) const; + + /*! + * METHODS: saveState, loadState + * Fulfills ossimObject base-class pure virtuals. Loads and saves geometry + * KWL files. Returns true if successful. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0) const; + + virtual bool loadState(const ossimKeywordlist& kwl, + const char* prefix=0); + + virtual void lineSampleToWorld(const ossimDpt& image_point, + ossimGpt& world_point) const; + //*** + // METHOD: lineSampleHeightToWorld() + // Overrides base class pure virtual. Height understood to be relative to + // standard ellipsoid. + //*** + virtual void lineSampleHeightToWorld(const ossimDpt& image_point, + const double& heightEllipsoid, + ossimGpt& worldPoint) const; + + /*! + * METHOD: dup() + * Returns pointer to a new instance, copy of this. + */ + virtual ossimObject* dup() const { return new ossimRpcProjection(*this); } + + virtual ossimGpt origin()const; + virtual ossimDpt getMetersPerPixel() const; + virtual bool operator==(const ossimProjection& projection) const; + +protected: + //*** + // Methods for computing RPC polynomial and its derivatives: + //*** + double polynomial(const double& nlat, + const double& nlon, + const double& nhgt, + const double* coeffs) const; + double dPoly_dLat(const double& nlat, + const double& nlon, + const double& nhgt, + const double* coeffs) const; + double dPoly_dLon(const double& nlat, + const double& nlon, + const double& nhgt, + const double* coeffs) const; + + PolynomialType thePolyType; + //*** + // Quantities for zero-biasing and normalizing the image point and + // ground point coordinates referenced in the polynomials: + //*** + double theLineScale; + double theSampScale; + double theLatScale; + double theLonScale; + double theHgtScale; + double theLineOffset; + double theSampOffset; + double theLatOffset; + double theLonOffset; + double theHgtOffset; + + //*** + // Coefficients: + //*** + double theLineNumCoef[20]; + double theLineDenCoef[20]; + double theSampNumCoef[20]; + double theSampDenCoef[20]; + + TYPE_DATA +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/ossimRpcSolver.cpp b/Utilities/OSSIM/ossim_core/projections/ossimRpcSolver.cpp new file mode 100644 index 0000000000..05544db4f6 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/ossimRpcSolver.cpp @@ -0,0 +1,792 @@ +//***************************************************************************** +// FILE: ossimRpcModel.h +// +// Copyright (C) 2004 Intelligence Data Systems, Inc. +// +// LICENSE: LGPL +// +// see top level LICENSE.txt +// +// AUTHOR: Garrett Potts +// +//***************************************************************************** +// $Id: ossimRpcSolver.cpp,v 1.15 2005/10/12 10:48:44 dburken Exp $ +#include <projections/ossimRpcSolver.h> +#include <projections/sensor_modeling/rpc/ossimRpcModel.h> +#include <projections/ossimProjection.h> +#include <matrix/newmatap.h> +#include <matrix/newmatio.h> +#include <iomanip> +#include <iostream> +#include <iterator> +#include <time.h> +#include <matrix/newmatnl.h> +#include <matrix/newmatio.h> +#include <elevation/ossimElevManager.h> +#include <support_data/nitf/ossimNitfRpcBTag.h> + +ossimRpcSolver::ossimRpcSolver(bool useElevation, + bool heightAboveMSLFlag) +{ + theUseElevationFlag = useElevation; + theHeightAboveMSLFlag = heightAboveMSLFlag; + theXNumCoeffs.resize(20); + theXDenCoeffs.resize(20); + theYNumCoeffs.resize(20); + theYDenCoeffs.resize(20); + + std::fill(theXNumCoeffs.begin(), + theXNumCoeffs.end(), 0.0); + std::fill(theXDenCoeffs.begin(), + theXDenCoeffs.end(), 0.0); + std::fill(theYNumCoeffs.begin(), + theYNumCoeffs.end(), 0.0); + std::fill(theYDenCoeffs.begin(), + theYDenCoeffs.end(), 0.0); + theXNumCoeffs[0] = 1.0; + theXDenCoeffs[0] = 1.0; + theYNumCoeffs[0] = 1.0; + theYDenCoeffs[0] = 1.0; +} + +void ossimRpcSolver::solveCoefficients(const ossimDrect& imageBounds, + const ossimProjection& proj, + ossim_uint32 xSamples, + ossim_uint32 ySamples, + bool shiftTo0Flag) +{ + std::vector<ossimGpt> theGroundPoints; + std::vector<ossimDpt> theImagePoints; + ossim_uint32 x,y; + ossim_float64 w = imageBounds.width(); + ossim_float64 h = imageBounds.height(); + ossimGpt gpt; + ossimGpt defaultGround; + if(ySamples < 1) ySamples = 12; + if(xSamples < 1) xSamples = 12; + srand(time(0)); + double xnorm; + double ynorm; + ossimDpt ul = imageBounds.ul(); + ossimDpt shiftTo0(-ul.x, + -ul.y); + for(y = 0; y < ySamples; ++y) + { + for(x = 0; x < xSamples; ++x) + { + if(ySamples > 1) + { + ynorm = (double)y/(double)(ySamples-1.0); + } + else + { + ynorm = 0.0; + } + if(xSamples > 1) + { + xnorm = (double)x/(double)(xSamples-1.0); + } + else + { + xnorm = 0.0; + } + + ossimDpt dpt((.25 + .5*xnorm)*w + ul.x, + (.25 + .5*ynorm)*h + ul.y); + + proj.lineSampleToWorld(dpt, + gpt); + gpt.changeDatum(defaultGround.datum()); + + if(shiftTo0Flag) + { + theImagePoints.push_back(dpt+shiftTo0); + } + else + { + theImagePoints.push_back(dpt); + } + if(theHeightAboveMSLFlag) + { + double h = ossimElevManager::instance()->getHeightAboveMSL(gpt); + gpt.height(h); + } + theGroundPoints.push_back(gpt); + } + } + solveCoefficients(theImagePoints, + theGroundPoints); +} + +void ossimRpcSolver::solveCoefficients(const std::vector<ossimDpt>& imagePoints, + const std::vector<ossimGpt>& groundControlPoints, + const ossimDpt& imageShift) +{ + if((imagePoints.size() != groundControlPoints.size())) + { + return; + } + + // we will first create f which holds the result of f(x,y,z). + // This basically holds the cooresponding image point for each + // ground control point. One for x and a second array for y + // + std::vector<double> f[2]; + + // Holds the x, y, z vectors + // + std::vector<double> x; + std::vector<double> y; + std::vector<double> z; + ossim_uint32 c = 0; + f[0].resize(imagePoints.size()); + f[1].resize(imagePoints.size()); + x.resize(imagePoints.size()); + y.resize(imagePoints.size()); + z.resize(imagePoints.size()); + + // compute the image bounds for the given image points + // + ossimDrect rect(imagePoints); + + // get the widtha dn height that will be used + // in data normalization + // + ossim_float64 w = rect.width(); + ossim_float64 h = rect.width(); + + // setup scales for normalization +// ossim_float64 xScale = w/2.0; +// ossim_float64 yScale = h/2.0; + + // get the shift for the cneter of the data + ossimDpt centerImagePoint = rect.midPoint(); + + double latSum=0.0; + double lonSum=0.0; + double heightSum=0.0; + + // find the center ground Use elevation only if its enabled + // + for(c = 0; c < groundControlPoints.size();++c) + { + if(groundControlPoints[c].latd() != OSSIM_DBL_NAN) + { + latSum += groundControlPoints[c].latd(); + } + if(groundControlPoints[c].lond() != OSSIM_DBL_NAN) + { + lonSum += groundControlPoints[c].lond(); + } + if(!groundControlPoints[c].isHgtNan()) + { + if(theUseElevationFlag) + { + heightSum += groundControlPoints[c].height(); + } + } + } + + // set the center ground for the offset + // + ossimGpt centerGround(latSum/groundControlPoints.size(), + lonSum/groundControlPoints.size(), + heightSum/groundControlPoints.size()); + + // set up ground scales and deltas for normalization + // +// ossim_float64 latScale = 0.0; +// ossim_float64 lonScale = 0.0; +// ossim_float64 heightScale = 0.0; + ossim_float64 deltaLat = 0.0; + ossim_float64 deltaLon = 0.0; + ossim_float64 deltaHeight = 0.0; + ossim_float64 maxDeltaLat = 0.0; + ossim_float64 maxDeltaLon = 0.0; + ossim_float64 maxDeltaHeight = 0.0; + for(c = 0; c < groundControlPoints.size(); ++c) + { + deltaLat = (groundControlPoints[c].latd()-centerGround.latd()); + deltaLon = (groundControlPoints[c].lond()-centerGround.lond()); + if(!groundControlPoints[c].isHgtNan()) + { + if(theUseElevationFlag) + { + deltaHeight = groundControlPoints[c].height() - centerGround.height(); + } + else + { + deltaHeight = 0.0; + } + } + else + { + deltaHeight = 0.0; + } + f[0][c] = (imagePoints[c].x - centerImagePoint.x)/(w/2.0); + f[1][c] = (imagePoints[c].y - centerImagePoint.y)/(h/2.0); + + x[c] = deltaLon; + y[c] = deltaLat; + z[c] = deltaHeight; + + if(fabs(deltaLat) > maxDeltaLat) maxDeltaLat = fabs(deltaLat); + if(fabs(deltaLon) > maxDeltaLon) maxDeltaLon = fabs(deltaLon); + if(fabs(deltaHeight) > maxDeltaHeight) maxDeltaHeight = fabs(deltaHeight); + } + + // if the delta is already between -1 to 1 I guess its safe not to normalize + // so force the divisor to 1.0 + // + if(maxDeltaLat < 1) maxDeltaLat = 1.0; + if(maxDeltaLon < 1) maxDeltaLon = 1.0; + if(maxDeltaHeight < 1) maxDeltaHeight = 1.0; + + // normalize the ground points + for(c = 0; c < groundControlPoints.size(); ++c) + { + x[c] /= maxDeltaLon; + y[c] /= maxDeltaLat; + z[c] /= maxDeltaHeight; + } + + theLatScale = maxDeltaLat; + theLonScale = maxDeltaLon; + theHeightScale = maxDeltaHeight; + + + theImageOffset = centerImagePoint; + theImageScale = ossimDpt(w/2.0, + h/2.0); + theGroundOffset = centerGround; + + if(theGroundOffset.height() == OSSIM_DBL_NAN) + { + theGroundOffset.height(0.0); + } + + // now lets solve the coefficients + // + std::vector<double> coeffx; + std::vector<double> coeffy; + + NEWMAT::ColumnVector coeffxVec; + NEWMAT::ColumnVector coeffyVec; + // perform a least squares fit for sample values found in f + // given the world values with variables x, y, z + // + solveCoefficients(coeffxVec, + f[0], + x, + y, + z); + + + // perform a least squares fit for line values found in f + // given the world values with variables x, y, z + // + solveCoefficients(coeffyVec, + f[1], + x, + y, + z); + + coeffx.resize(coeffxVec.Nrows()); + coeffy.resize(coeffyVec.Nrows()); + + for(c = 0; c < coeffx.size();++c) + { + coeffx[c] = coeffxVec[c]; + coeffy[c] = coeffyVec[c]; + } + // there are 20 numerator coefficients + // and 19 denominator coefficients + // I believe that the very first one for the + // denominator coefficients is fixed at 1.0 + // + std::copy(coeffx.begin(), + coeffx.begin()+20, + theXNumCoeffs.begin()); + std::copy(coeffx.begin()+20, + coeffx.begin()+39, + theXDenCoeffs.begin()+1); + std::copy(coeffy.begin(), + coeffy.begin()+20, + theYNumCoeffs.begin()); + std::copy(coeffy.begin()+20, + coeffy.begin()+39, + theYDenCoeffs.begin()+1); + theXDenCoeffs[0] = 1.0; + theYDenCoeffs[0] = 1.0; + + + // now lets compute the RMSE for the given control points by feeding it + // back through the modeled RPC + // + ossim_float64 sumSquareError = 0.0; + ossim_uint32 idx = 0; + +// std::cout << "ground offset height = " << theGroundOffset.height() +// << "Height scale = " << theHeightScale << std::endl; + for (idx = 0; idx<imagePoints.size(); idx++) + { + ossim_float64 x = (groundControlPoints[idx].lond() - theGroundOffset.lond())/theLonScale; + ossim_float64 y = (groundControlPoints[idx].latd() - theGroundOffset.latd())/theLatScale; + ossim_float64 z = (groundControlPoints[idx].height() - theGroundOffset.height())/theHeightScale; + + if(z == OSSIM_DBL_NAN) + { + z = 0.0; + } + else + { + z = (z - theGroundOffset.height())/theHeightScale; + } + + ossim_float64 imageX = ((eval(theXNumCoeffs, x, y, z)/ + eval(theXDenCoeffs, x, y, z))*theImageScale.x) + theImageOffset.x; + + ossim_float64 imageY = ((eval(theYNumCoeffs, x, y, z)/ + eval(theYDenCoeffs, x, y, z))*theImageScale.y) + theImageOffset.y; + + ossimDpt evalPt(imageX, imageY); + ossim_float64 len = (evalPt - imagePoints[idx]).length(); + + sumSquareError += (len*len); + } + + // set the error + // + theError = sqrt(sumSquareError/imagePoints.size()); +} + +ossimRefPtr<ossimRpcModel> ossimRpcSolver::createRpcModel()const +{ + ossimRpcModel* model = new ossimRpcModel; + + model->setAttributes(theImageOffset.x, + theImageOffset.y, + theImageScale.x, + theImageScale.y, + theGroundOffset.latd(), + theGroundOffset.lond(), + theGroundOffset.height(), + theLatScale, + theLonScale, + theHeightScale, + theXNumCoeffs, + theXDenCoeffs, + theYNumCoeffs, + theYDenCoeffs); + return model; +} + +ossimRefPtr<ossimRpcProjection> ossimRpcSolver::createRpcProjection()const +{ + ossimRpcProjection* proj = new ossimRpcProjection; + + proj->setAttributes(theImageOffset.x, + theImageOffset.y, + theImageScale.x, + theImageScale.y, + theGroundOffset.latd(), + theGroundOffset.lond(), + theGroundOffset.height(), + theLatScale, + theLonScale, + theHeightScale, + theXNumCoeffs, + theXDenCoeffs, + theYNumCoeffs, + theYDenCoeffs); + return proj; +} + +const std::vector<double>& ossimRpcSolver::getImageXNumCoefficients()const +{ + return theXNumCoeffs; +} + +const std::vector<double>& ossimRpcSolver::getImageXDenCoefficients()const +{ + return theXDenCoeffs; +} + +const std::vector<double>& ossimRpcSolver::getImageYNumCoefficients()const +{ + return theYNumCoeffs; +} + +const std::vector<double>& ossimRpcSolver::getImageYDenCoefficients()const +{ + return theYDenCoeffs; +} + +double ossimRpcSolver::getImageXOffset()const +{ + return theImageOffset.x; +} + +double ossimRpcSolver::getImageYOffset()const +{ + return theImageOffset.y; +} + +double ossimRpcSolver::getLatOffset()const +{ + return theGroundOffset.latd(); +} + +double ossimRpcSolver::getLonOffset()const +{ + return theGroundOffset.lond(); +} + +double ossimRpcSolver::getHeightOffset()const +{ + return theGroundOffset.height(); +} + +double ossimRpcSolver::getImageXScale()const +{ + return theImageScale.x; +} + +double ossimRpcSolver::getImageYScale()const +{ + return theImageScale.y; +} + +double ossimRpcSolver::getLatScale()const +{ + return theLatScale; +} + +double ossimRpcSolver::getLonScale()const +{ + return theLonScale; +} + +double ossimRpcSolver::getHeightScale()const +{ + return theHeightScale; +} + +double ossimRpcSolver::getRmsError()const +{ + return theError; +} + +void ossimRpcSolver::solveInitialCoefficients(NEWMAT::ColumnVector& coeff, + const std::vector<double>& f, + const std::vector<double>& x, + const std::vector<double>& y, + const std::vector<double>& z)const +{ + ossim_uint32 idx = 0; + NEWMAT::Matrix m; + NEWMAT::ColumnVector r(f.size()); + for(idx = 0; idx < f.size(); ++idx) + { + r[idx] = f[idx]; + } + setupSystemOfEquations(m, + r, + x, + y, + z); + + coeff = invert(m.t()*m)*m.t()*r; +} + +void ossimRpcSolver::solveCoefficients(NEWMAT::ColumnVector& coeff, + const std::vector<double>& f, + const std::vector<double>& x, + const std::vector<double>& y, + const std::vector<double>& z)const +{ + // this is an iterative linear least square fit. We really pobably need + // a nonlinear fit instead + // + ossim_uint32 idx = 0; + NEWMAT::Matrix m; + + NEWMAT::ColumnVector r(f.size()); + + for(idx = 0; idx < f.size(); ++idx) + { + r[idx] = f[idx]; + } + + NEWMAT::ColumnVector tempCoeff; + NEWMAT::DiagonalMatrix weights(f.size()); + NEWMAT::ColumnVector denominator(20); + + // initialize the weight matrix to the identity + // + for(idx = 0; idx < f.size(); ++idx) + { + weights[idx] = 1.0; + } + + double residualValue = 1.0/FLT_EPSILON; + ossim_uint32 iterations = 0; + NEWMAT::Matrix w2; + do + { + w2 = weights*weights; + + // sets up the matrix to hold the system of + // equations + setupSystemOfEquations(m, + r, + x, + y, + z); + + // solve the least sqaures solution. Note: the invert is used + // to do a Singular Value Decomposition for the inverse since the + // matrix is more than likely singular. Slower but more robust + // + tempCoeff = invert(m.t()*w2*m)*m.t()*w2*r; + + // set up the weight matrix by using the denominator + // + for(idx = 0; idx < 19; ++idx) + { + denominator[idx+1] = tempCoeff[20+idx]; + } + denominator[0] = 1.0; + + setupWeightMatrix(weights, + denominator, + r, + x, + y, + z); + + // compute the residual + // + NEWMAT::ColumnVector residual = (m.t()*w2*m*tempCoeff-m.t()*w2*r); + + // now get the innerproduct + // + NEWMAT::Matrix tempRes = (residual.t()*residual); + residualValue = tempRes[0][0]; + + ++iterations; + + }while((residualValue >FLT_EPSILON)&& + (iterations < 10)); + coeff = tempCoeff; + +} + +NEWMAT::Matrix ossimRpcSolver::invert(const NEWMAT::Matrix& m)const +{ + ossim_uint32 idx = 0; + NEWMAT::DiagonalMatrix d; + NEWMAT::Matrix u; + NEWMAT::Matrix v; + + // decompose m.t*m which is stored in Temp into the singular values and vectors. + // + NEWMAT::SVD(m, d, u, v, true, true); + + // invert the diagonal + // this is just doing the reciprical fo all diagonal components and store back int + // d. ths compute d inverse. + // + for(idx=0; idx < (ossim_uint32)d.Ncols(); ++idx) + { + if(d[idx] > FLT_EPSILON) + { + d[idx] = 1.0/d[idx]; + } + else + { + d[idx] = 0.0; + } + } + + //compute inverse of decomposed m; + return v*d*u.t(); +} + + +void ossimRpcSolver::setupSystemOfEquations(NEWMAT::Matrix& equations, + const NEWMAT::ColumnVector& f, + const std::vector<double>& x, + const std::vector<double>& y, + const std::vector<double>& z)const +{ + ossim_uint32 idx; + equations.ReSize(f.Nrows(), + 39); + + for(idx = 0; idx < (ossim_uint32)f.Nrows();++idx) + { + equations[idx][0] = 1; + equations[idx][1] = x[idx]; + equations[idx][2] = y[idx]; + equations[idx][3] = z[idx]; + equations[idx][4] = x[idx]*y[idx]; + equations[idx][5] = x[idx]*z[idx]; + equations[idx][6] = y[idx]*z[idx]; + equations[idx][7] = x[idx]*x[idx]; + equations[idx][8] = y[idx]*y[idx]; + equations[idx][9] = z[idx]*z[idx]; + equations[idx][10] = x[idx]*y[idx]*z[idx]; + equations[idx][11] = x[idx]*x[idx]*x[idx]; + equations[idx][12] = x[idx]*y[idx]*y[idx]; + equations[idx][13] = x[idx]*z[idx]*z[idx]; + equations[idx][14] = x[idx]*x[idx]*y[idx]; + equations[idx][15] = y[idx]*y[idx]*y[idx]; + equations[idx][16] = y[idx]*z[idx]*z[idx]; + equations[idx][17] = z[idx]*x[idx]*z[idx]; + equations[idx][18] = y[idx]*y[idx]*z[idx]; + equations[idx][19] = z[idx]*z[idx]*z[idx]; + equations[idx][20] = -f[idx]*x[idx]; + equations[idx][21] = -f[idx]*y[idx]; + equations[idx][22] = -f[idx]*z[idx]; + equations[idx][23] = -f[idx]*x[idx]*y[idx]; + equations[idx][24] = -f[idx]*x[idx]*z[idx]; + equations[idx][25] = -f[idx]*y[idx]*z[idx]; + equations[idx][26] = -f[idx]*x[idx]*x[idx]; + equations[idx][27] = -f[idx]*y[idx]*y[idx]; + equations[idx][28] = -f[idx]*z[idx]*z[idx]; + equations[idx][29] = -f[idx]*x[idx]*y[idx]*z[idx]; + equations[idx][30] = -f[idx]*x[idx]*x[idx]*x[idx]; + equations[idx][31] = -f[idx]*x[idx]*y[idx]*y[idx]; + equations[idx][32] = -f[idx]*x[idx]*z[idx]*z[idx]; + equations[idx][33] = -f[idx]*x[idx]*x[idx]*y[idx]; + equations[idx][34] = -f[idx]*y[idx]*y[idx]*y[idx]; + equations[idx][35] = -f[idx]*y[idx]*z[idx]*z[idx]; + equations[idx][36] = -f[idx]*z[idx]*x[idx]*z[idx]; + equations[idx][37] = -f[idx]*y[idx]*y[idx]*z[idx]; + equations[idx][38] = -f[idx]*z[idx]*z[idx]*z[idx]; + } +} + +void ossimRpcSolver::setupWeightMatrix(NEWMAT::DiagonalMatrix& result, // holds the resulting weights + const NEWMAT::ColumnVector& coefficients, + const NEWMAT::ColumnVector& f, + const std::vector<double>& x, + const std::vector<double>& y, + const std::vector<double>& z)const +{ + result.ReSize(f.Nrows()); + ossim_uint32 idx = 0; + ossim_uint32 idx2 = 0; + NEWMAT::RowVector row(coefficients.Nrows()); + + for(idx = 0; idx < (ossim_uint32)f.Nrows(); ++idx) + { + row[0] = 1; + row[1] = x[idx]; + row[2] = y[idx]; + row[3] = z[idx]; + row[4] = x[idx]*y[idx]; + row[5] = x[idx]*z[idx]; + row[6] = y[idx]*z[idx]; + row[7] = x[idx]*x[idx]; + row[8] = y[idx]*y[idx]; + row[9] = z[idx]*z[idx]; + row[10] = x[idx]*y[idx]*z[idx]; + row[11] = x[idx]*x[idx]*x[idx]; + row[12] = x[idx]*y[idx]*y[idx]; + row[13] = x[idx]*z[idx]*z[idx]; + row[14] = x[idx]*x[idx]*y[idx]; + row[15] = y[idx]*y[idx]*y[idx]; + row[16] = y[idx]*z[idx]*z[idx]; + row[17] = z[idx]*x[idx]*z[idx]; + row[18] = y[idx]*y[idx]*z[idx]; + row[19] = z[idx]*z[idx]*z[idx]; + + result[idx] = 0.0; + for(idx2 = 0; idx2 < (ossim_uint32)row.Ncols(); ++idx2) + { + result[idx] += row[idx2]*coefficients[idx2]; + } + + if(result[idx] > FLT_EPSILON) + { + result[idx] = 1.0/result[idx]; + } + } +} + +double ossimRpcSolver::eval(const std::vector<double>& coeff, + double x, + double y, + double z)const +{ + return coeff[ 0] + coeff[ 1]*x + coeff[ 2]*y + coeff[ 3]*z + + coeff[ 4]*x*y + coeff[ 5]*x*z + coeff[ 6]*y*z + coeff[ 7]*x*x + + coeff[ 8]*y*y + coeff[ 9]*z*z + coeff[10]*x*y*z + coeff[11]*x*x*x + + coeff[12]*x*y*y + coeff[13]*x*z*z + coeff[14]*x*x*y + coeff[15]*y*y*y + + coeff[16]*y*z*z + coeff[17]*x*x*z + coeff[18]*y*y*z + coeff[19]*z*z*z; +} + + +ossimRefPtr<ossimNitfRegisteredTag> ossimRpcSolver::getNitfRpcBTag() const +{ + ossimNitfRpcBTag* rpcbTag = new ossimNitfRpcBTag(); + + // success always true + rpcbTag->setSuccess(true); + + // temp "0"... + rpcbTag->setErrorBias(0.0); + + // temp "0"... + rpcbTag->setErrorRand(0.0); + + // line offset + rpcbTag->setLineOffset(static_cast<ossim_uint32>(getImageYOffset())); + + // sample offset + rpcbTag->setSampleOffset(static_cast<ossim_uint32>(getImageXOffset())); + + // latitude offset + rpcbTag->setGeodeticLatOffset(getLatOffset()); + + // longitude offset + rpcbTag->setGeodeticLonOffset(getLonOffset()); + + // height offset + rpcbTag->setGeodeticHeightOffset( + static_cast<ossim_int32>(getHeightOffset())); + + // line scale + rpcbTag->setLineScale(static_cast<ossim_uint32>(getImageYScale())); + + // sample scale + rpcbTag->setSampleScale(static_cast<ossim_uint32>(getImageXScale())); + + // latitude scale + rpcbTag->setGeodeticLatScale(getLatScale()); + + // longitude scale + rpcbTag->setGeodeticLonScale(getLonScale()); + + // height scale + rpcbTag->setGeodeticHeightScale(static_cast<ossim_int32>(getHeightScale())); + + // line numerator coefficients + rpcbTag->setLineNumeratorCoeff(getImageYNumCoefficients()); + + // line denominator coefficients + rpcbTag->setLineDenominatorCoeff(getImageYDenCoefficients()); + + // sample numerator coefficients + rpcbTag->setSampleNumeratorCoeff(getImageXNumCoefficients()); + + // sample denominator coefficients + rpcbTag->setSampleDenominatorCoeff(getImageXDenCoefficients()); + + // Return it as an ossimRefPtr<ossimNitfRegisteredTag>... + ossimRefPtr<ossimNitfRegisteredTag> tag = rpcbTag; + + return tag; +} diff --git a/Utilities/OSSIM/ossim_core/projections/ossimRpcSolver.h b/Utilities/OSSIM/ossim_core/projections/ossimRpcSolver.h new file mode 100644 index 0000000000..2a8235320a --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/ossimRpcSolver.h @@ -0,0 +1,233 @@ +//***************************************************************************** +// FILE: ossimRpcModel.h +// +// Copyright (C) 2004 Intelligence Data Systems, Inc. +// +// LICENSE: LGPL +// +// see top level LICENSE.txt +// +// AUTHOR: Garrett Potts +// +//***************************************************************************** +// $Id: ossimRpcSolver.h,v 1.11 2005/10/06 16:02:45 gpotts Exp $ +#ifndef ossimRpcSolver_HEADER +#define ossimRpcSolver_HEADER + +#include <vector> +#include <base/common/ossimRefPtr.h> +#include <base/data_types/ossimDpt.h> +#include <base/data_types/ossimGpt.h> +#include <base/data_types/ossimDrect.h> +#include <matrix/newmat.h> +#include <projections/sensor_modeling/rpc/ossimRpcModel.h> +#include <projections/ossimRpcProjection.h> + +class ossimProjection; +class ossimNitfRegisteredTag; + + +/** + * This currently only support Rational poilynomial B format. This can be found in + * the NITF registered commercial tag document. + * + * <pre> + * Format is: + * coeff[ 0] + coeff[ 1]*x + coeff[ 2]*y + coeff[ 3]*z + + * coeff[ 4]*x*y + coeff[ 5]*x*z + coeff[ 6]*y*z + coeff[ 7]*x*x + + * coeff[ 8]*y*y + coeff[ 9]*z*z + coeff[10]*x*y*z + coeff[11]*x*x*x + + * coeff[12]*x*y*y + coeff[13]*x*z*z + coeff[14]*x*x*y + coeff[15]*y*y*y + + * coeff[16]*y*z*z + coeff[17]*x*x*z + coeff[18]*y*y*z + coeff[19]*z*z*z; + * + * where coeff is one of XNum, XDen, YNum, and YDen. So there are 80 + * coefficients all together. + * + * + * Currently we use a linear least squares fit to solve the coefficients. This is the simplest + * to implement. We probably relly need a nonlinear minimizer to fit the coefficients but I don't have + * time to experiment. Levenberg Marquardt might be a solution to look into. + * + * + * + * HOW TO USE: + * + * ossimRpcSolver solver; + * solver.solveCoefficients(rect, + * *proj.get()); + * + * We can also call solve coefficients with a list of ground control points. + * First is the list of image points followed by the ground points. + * NOTE: Thes must be equal in size. + * + * solver.solveCoefficients(imagePoints, + * groundPoints); + * + * + * Once you call solveCoefficients you can create the projector: + * + * ossimRefPtr<ossimRpcProjection> rpc = solver.createRpcProjection(); + * + * </pre> + * + */ +class OSSIM_DLL ossimRpcSolver +{ +public: + /** + * The use elvation flag will deterimne if we force the height t be 0. If the elevation + * is enabled then we use the height field of the control points to determine the + * coefficients of the RPC00 polynomial. If its false then we will ignore the height + * by setting the height field to 0.0. + * + * Note: even if the elevation is enabled all NAN heights are set to 0.0. + */ + ossimRpcSolver(bool useElevation=false, + bool heightAboveMSLFlag=true); + + virtual ~ossimRpcSolver(){} + /** + * This will convert any projector to an RPC model + */ + void solveCoefficients(const ossimDrect& imageBouunds, + const ossimProjection& imageProj, + ossim_uint32 xSamples=8, + ossim_uint32 ySamples=8, + bool shiftTo0Flag=true); + + /** + * takes associated image points and ground points + * and solves the coefficents for the rational polynomial for + * line and sample calculations from world points. + * + * Note: All data will be normalized between -1 and 1 for + * numerical robustness. + */ + void solveCoefficients(const std::vector<ossimDpt>& imagePoints, + const std::vector<ossimGpt>& groundControlPoints, + const ossimDpt& imageShift = ossimDpt(0.0,0.0)); + + /** + * Creates and Rpc model from the coefficients + */ + ossimRefPtr<ossimRpcModel> createRpcModel()const; + + /** + * Create a simple rpc projection which is a dumbed down + * rpc model. + */ + ossimRefPtr<ossimRpcProjection> createRpcProjection()const; + + + /** + * Gives access to the solved coefficients. For the image + * X numerator + */ + const std::vector<double>& getImageXNumCoefficients()const; + + /** + * Gives access to the solved coefficients. For the image + * X denominator + */ + const std::vector<double>& getImageXDenCoefficients()const; + + /** + * Gives access to the solved coefficients. For the image + * Y numerator + */ + const std::vector<double>& getImageYNumCoefficients()const; + + /** + * Gives access to the solved coefficients. For the image + * Y denominator + */ + const std::vector<double>& getImageYDenCoefficients()const; + + + double getImageXOffset()const; + double getImageYOffset()const; + double getLatOffset()const; + double getLonOffset()const; + double getHeightOffset()const; + double getImageXScale()const; + double getImageYScale()const; + double getLatScale()const; + double getLonScale()const; + double getHeightScale()const; + + double getRmsError()const; + + /** + * @return ossimRefPtr<ossimNitfRegisteredTag> + * + * @note one of the solve methods should have been called prior to this. + */ + ossimRefPtr<ossimNitfRegisteredTag> getNitfRpcBTag() const; + +protected: + virtual void solveInitialCoefficients(NEWMAT::ColumnVector& coeff, + const std::vector<double>& f, + const std::vector<double>& x, + const std::vector<double>& y, + const std::vector<double>& z)const; + + virtual void solveCoefficients(NEWMAT::ColumnVector& coeff, + const std::vector<double>& f, + const std::vector<double>& x, + const std::vector<double>& y, + const std::vector<double>& z)const; + + double eval(const std::vector<double>& coeff, + double x, + double y, + double z)const; + + /** + * Inverts using the SVD method + */ + NEWMAT::Matrix invert(const NEWMAT::Matrix& m)const; + + void setupSystemOfEquations(NEWMAT::Matrix& equations, + const NEWMAT::ColumnVector& f, + const std::vector<double>& x, + const std::vector<double>& y, + const std::vector<double>& z)const; + + void setupWeightMatrix(NEWMAT::DiagonalMatrix& result, // holds the resulting weights + const NEWMAT::ColumnVector& coefficients, + const NEWMAT::ColumnVector& f, + const std::vector<double>& x, + const std::vector<double>& y, + const std::vector<double>& z)const; + + bool theUseElevationFlag; + bool theHeightAboveMSLFlag; + ossimDpt theImageOffset; + ossimGpt theGroundOffset; + ossimDpt theImageScale; + ossim_float64 theLatScale; + ossim_float64 theLonScale; + ossim_float64 theHeightScale; + ossim_float64 theError; + /** + * there are 20 coefficients in the cubic RPC model + */ + std::vector<ossim_float64> theXNumCoeffs; + + /** + * there are 20 coefficients in the cubic RPC model + */ + std::vector<ossim_float64> theXDenCoeffs; + + /** + * there are 20 coefficients in the cubic RPC model + */ + std::vector<ossim_float64> theYNumCoeffs; + + /** + * there are 20 coefficients in the cubic RPC model + */ + std::vector<ossim_float64> theYDenCoeffs; + +}; + +#endif diff --git a/Utilities/OSSIM/ossim_core/projections/ossimStatePlaneProjectionInfo.cpp b/Utilities/OSSIM/ossim_core/projections/ossimStatePlaneProjectionInfo.cpp new file mode 100644 index 0000000000..acc182a827 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/ossimStatePlaneProjectionInfo.cpp @@ -0,0 +1,306 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +//******************************************************************* +// $Id: ossimStatePlaneProjectionInfo.cpp,v 1.9 2004/06/09 15:36:16 dburken Exp $ +#include "ossimStatePlaneProjectionInfo.h" +#include "map_projections/ossimTransMercatorProjection.h" +#include "map_projections/ossimLambertConformalConicProjection.h" +#include "base/common/ossimKeywordNames.h" +#include "base/factory/ossimDatumFactory.h" +#include "base/common/ossimConstants.h" + +ossimStatePlaneProjectionInfo::ossimStatePlaneProjectionInfo(char* name, + int pcsCode, + char* projName, + char* param1, + char* param2, + char* param3, + char* param4, + double falseEast, + double falseNorth, + char* units) + : + thePcsCode (pcsCode), + theName (name), + theProjectionName (projName), + theDatum (0), + theOriginLat (param1), + theOriginLon (param2), + theOrigin (), + theParameter3 (0.0), + theParameter4 (0.0), + theFalseEasting (falseEast), + theFalseNorthing (falseNorth), + theScaleFactor (0.0), + theUnits (units) + +{ + // Set the parameters + theParameter3 = ossimDms(param3).getDegrees(); + theParameter4 = ossimDms(param4).getDegrees(); + + if(theName.contains("NAD27")) + { + theDatum = ossimDatumFactory::instance()->create("NAS-C"); // NAD 1927 + } + else + { + theDatum = ossimDatumFactory::instance()->create("NAR-C"); // NAD 1983 + } + + theOrigin = ossimGpt(theOriginLat.getDegrees(), + theOriginLon.getDegrees(), + 0, + theDatum); +} + +ossimStatePlaneProjectionInfo::ossimStatePlaneProjectionInfo(char* name, + int pcsCode, + char* projName, + char* param1, + char* param2, + double param3, + double param4, + double falseEast, + double falseNorth, + char* units) + : + thePcsCode (pcsCode), + theName (name), + theProjectionName (projName), + theDatum (0), + theOriginLat (param1), + theOriginLon (param2), + theOrigin (), + theParameter3 (param3), + theParameter4 (param4), + theFalseEasting (falseEast), + theFalseNorthing (falseNorth), + theScaleFactor (0.0), + theUnits (units) +{ + if(theName.contains("NAD27")) + { + theDatum = ossimDatumFactory::instance()->create("NAS-C"); // NAD 1927 + } + else + { + theDatum = ossimDatumFactory::instance()->create("NAR-C"); // NAD 1983 + } + + theOrigin = ossimGpt(theOriginLat.getDegrees(), + theOriginLon.getDegrees(), + 0, + theDatum); + if(fabs(theParameter3) > FLT_EPSILON) + { + theScaleFactor = 1.0 - (1.0 / theParameter3); + } + else + { + theScaleFactor = 1.0; + } + +} + +int ossimStatePlaneProjectionInfo::code() const +{ + return thePcsCode; +} + +const ossimString& ossimStatePlaneProjectionInfo::name() const +{ + return theName; +} + +const ossimString& ossimStatePlaneProjectionInfo::projName() const +{ + return theProjectionName; +} + +double ossimStatePlaneProjectionInfo::originLat() const +{ + return theOriginLat.getDegrees(); +} + +double ossimStatePlaneProjectionInfo::originLon() const +{ + return theOriginLon.getDegrees(); +} + +const ossimDatum* ossimStatePlaneProjectionInfo::datum() const +{ + return theDatum; +} + +ossimGpt ossimStatePlaneProjectionInfo::origin() const +{ + return theOrigin; +} + +double ossimStatePlaneProjectionInfo::parallel1() const +{ + return theParameter3; +} + +double ossimStatePlaneProjectionInfo::parallel2() const +{ + return theParameter4; +} + +double ossimStatePlaneProjectionInfo::falseEasting() const +{ + return theFalseEasting; +} + +double ossimStatePlaneProjectionInfo::falseNorthing() const +{ + return theFalseNorthing; +} + +double ossimStatePlaneProjectionInfo::scaleFactor() const +{ + return theScaleFactor; +} + +const ossimString& ossimStatePlaneProjectionInfo::units() const +{ + return theUnits; +} + +bool ossimStatePlaneProjectionInfo::isSameCode(int pcsCode) const +{ + if(pcsCode == thePcsCode) + { + return true; + } + + return false; +} + +double ossimStatePlaneProjectionInfo::falseEastingInMeters() const +{ + if (units()=="m") + { + return theFalseEasting; + } + return theFalseEasting * US_METERS_PER_FT; +} + +double ossimStatePlaneProjectionInfo::falseNorthingInMeters() const +{ + if (units()=="m") + { + return theFalseNorthing; + } + + return theFalseNorthing * US_METERS_PER_FT; +} + +void ossimStatePlaneProjectionInfo::populateProjectionKeywords(ossimKeywordlist& kwl, + const char* prefix)const +{ + kwl.add(prefix, + ossimKeywordNames::PCS_CODE_KW, + thePcsCode, + true); + + kwl.add(prefix, + ossimKeywordNames::FALSE_EASTING_KW, + falseEastingInMeters(), + true); + kwl.add(prefix, + ossimKeywordNames::FALSE_NORTHING_KW, + falseNorthingInMeters(), + true); + kwl.add(prefix, + ossimKeywordNames::ORIGIN_LATITUDE_KW, + origin().latd(), + true); + kwl.add(prefix, + ossimKeywordNames::CENTRAL_MERIDIAN_KW, + origin().lond(), + true); + kwl.add(prefix, + ossimKeywordNames::TYPE_KW, + projName(), + true); + if(theDatum) + { + + kwl.add(prefix, + ossimKeywordNames::DATUM_KW, + theDatum->code(), + true); + } + + if (projName()== STATIC_TYPE_NAME(ossimLambertConformalConicProjection)) + { + kwl.add(prefix, + ossimKeywordNames::TYPE_KW, + STATIC_TYPE_NAME(ossimLambertConformalConicProjection), + true); + kwl.add(prefix, + ossimKeywordNames::STD_PARALLEL_1_KW, + parallel1(), + true); + kwl.add(prefix, + ossimKeywordNames::STD_PARALLEL_2_KW, + parallel2(), + true); + } + else + { + kwl.add(prefix, + ossimKeywordNames::SCALE_FACTOR_KW, + theScaleFactor, + true); + } +} + +ostream& operator<<(ostream& os, const ossimStatePlaneProjectionInfo& thePlane) +{ + if (thePlane.projName()== STATIC_TYPE_NAME(ossimTransMercatorProjection)) + { + return os << "ossimStatePlaneProjection: " + << "\nName: " << thePlane.name() + << "\nPcsCode: " << thePlane.code() + << "\norigin: " << thePlane.origin() + << "\nscale factor: " << setprecision(12) + << thePlane.scaleFactor() + << "\nfalseEasting: " << thePlane.falseEasting() + << "\nfalseNorthing: " << thePlane.falseNorthing() + << endl; + } + else // Lambert + { + return os << "ossimStatePlaneProjection: " + << "\nName: " << thePlane.name() + << "\nPcsCode: " << thePlane.code() + << "\norigin: " << thePlane.origin() + << "\nphi1: " + << setprecision(12) << thePlane.parallel1() + << "\nphi2: " + << setprecision(12) << thePlane.parallel2() + << "\nfalseEasting: " << thePlane.falseEasting() + << "\nfalseNorthing: " << thePlane.falseNorthing() + << endl; + } +} diff --git a/Utilities/OSSIM/ossim_core/projections/ossimStatePlaneProjectionInfo.h b/Utilities/OSSIM/ossim_core/projections/ossimStatePlaneProjectionInfo.h new file mode 100644 index 0000000000..a99f06fa54 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/ossimStatePlaneProjectionInfo.h @@ -0,0 +1,108 @@ +//******************************************************************* +// Copyright (C) 2000 ImageLinks Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// Author: Garrett Potts (gpotts@imagelinks.com) +//******************************************************************* +// $Id: ossimStatePlaneProjectionInfo.h,v 1.5 2004/06/09 15:35:33 dburken Exp $ +#ifndef ossimStatePlaneProjectionInfo_HEADER +#define ossimStatePlaneProjectionInfo_HEADER + +#include "base/data_types/ossimDms.h" +#include "base/data_types/ossimGpt.h" +#include "base/data_types/ossimString.h" +#include "base/data_types/ossimKeywordlist.h" + +class ossimDatum; + +class OSSIMDLLEXPORT ossimStatePlaneProjectionInfo +{ + + friend ostream& operator<<(ostream&, const ossimStatePlaneProjectionInfo&); + +public: + + ossimStatePlaneProjectionInfo(char* name, + int pcsCode, + char* projCode, + char* param1, + char* param2, + char* param3, + char* param4, + double falseEast, + double falseNorth, + char* units); + + ossimStatePlaneProjectionInfo(char* name, + int pcsCode, + char* projCode, + char* param1, + char* param2, + double param3, + double param4, + double falseEast, + double falseNorth, + char* units); + + int code() const; + const ossimString& name() const; + const ossimString& projName() const; + double originLat() const; + double originLon() const; + const ossimDatum* datum() const; + ossimGpt origin() const; + double parallel1() const; + double parallel2() const; + double falseEasting() const; + double falseNorthing() const; + double falseEastingInMeters() const; + double falseNorthingInMeters() const; + double scaleFactor() const; + const ossimString& units() const; + bool isSameCode( int Code ) const; + + void populateProjectionKeywords(ossimKeywordlist& kwl, + const char* prefix=NULL)const; +private: + + int thePcsCode; // The Geotiff code + ossimString theName; // Descriptive PCS name + + /*! + * ossimLambertConformalConicProjection or + * ossimTransMercatorProjection + */ + ossimString theProjectionName; + + const ossimDatum* theDatum; // Either NAD83 or NAD27 based on name + + ossimDms theOriginLat; + ossimDms theOriginLon; + ossimGpt theOrigin; + + double theParameter3; // parallel 1 or Scale factor + double theParameter4; // parallel 2 or 0 + + double theFalseEasting; + double theFalseNorthing; + + double theScaleFactor; + + ossimString theUnits; // "ft" or "m" +}; + +#endif /* #ifndef ossimStatePlaneProjectionInfo_HEADER */ diff --git a/Utilities/OSSIM/ossim_core/projections/ossimWarpProjection.cpp b/Utilities/OSSIM/ossim_core/projections/ossimWarpProjection.cpp new file mode 100644 index 0000000000..fb965b2cf3 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/ossimWarpProjection.cpp @@ -0,0 +1,343 @@ +//***************************************************************************** +// FILE: ossimWarpProjection.cc +// +// Copyright (C) 2001 ImageLinks, Inc. +// +// OSSIM 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. +// +// This software 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. +// +// You should have received a copy of the GNU General Public License +// along with this software. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- +// 1307, USA. +// +// See the GPL in the COPYING.GPL file for more details. +// +// AUTHOR: Oscar Kramer (okramer@imagelinks.com) +// +// DESCRIPTION: +// Contains implementation of class ossimWarpModel. This is an +// implementation of a warping interpolation model. +// +//***************************************************************************** +// $Id: ossimWarpProjection.cpp,v 1.11 2005/09/09 19:23:58 gpotts Exp $ + +#include <projections/ossimWarpProjection.h> +RTTI_DEF1(ossimWarpProjection, "ossimWarpProjection", ossimProjection); + +#include <base/misc/ossimQuadTreeWarp.h> +#include <base/misc/ossimAffineTransform.h> +#include <projections/factory/ossimProjectionFactoryRegistry.h> +#include <base/context/ossimNotifyContext.h> + +static const char* AFFINE_PREFIX = "affine."; +static const char* QUADWARP_PREFIX = "quadwarp."; +static const char* PROJECTION_PREFIX = "projection."; + +//*** +// Define Trace flags for use within this file: +//*** +#include <base/common/ossimTrace.h> +static ossimTrace traceExec ("ossimWarpProjection:exec"); +static ossimTrace traceDebug ("ossimWarpProjection:debug"); + +//***************************************************************************** +// CONSTRUCTOR: Default +// +//***************************************************************************** +ossimWarpProjection::ossimWarpProjection() + : + ossimProjection(), + theClientProjection (NULL), + theWarpTransform (NULL), + theAffineTransform (NULL) +{ + theWarpTransform = new ossimQuadTreeWarp; + theAffineTransform = new ossimAffineTransform; +} + + +//***************************************************************************** +// CONSTRUCTOR: Primary constructor accepting pointer to the underlying +// client projection +// +//***************************************************************************** +ossimWarpProjection::ossimWarpProjection(ossimProjection* client) + : + ossimProjection(), + theClientProjection (client), + theWarpTransform (NULL), + theAffineTransform (NULL) +{ + theWarpTransform = new ossimQuadTreeWarp; + theAffineTransform = new ossimAffineTransform; +} + +//***************************************************************************** +// CONSTRUCTOR: Accepts geom keywordlist +//***************************************************************************** +ossimWarpProjection::ossimWarpProjection(const ossimKeywordlist& geom_kwl, + const char* prefix) + : + ossimProjection(), + theClientProjection (NULL), + theWarpTransform (NULL), + theAffineTransform (NULL) +{ + theClientProjection = ossimProjectionFactoryRegistry::instance()-> + createProjection(geom_kwl, prefix); + + theWarpTransform = new ossimQuadTreeWarp(); + bool rtn_stat = theWarpTransform->loadState(geom_kwl, prefix); + + theAffineTransform = new ossimAffineTransform(); + rtn_stat &= theAffineTransform->loadState(geom_kwl, prefix); + + if ((!theClientProjection) || + (theClientProjection->getErrorStatus()) || + (!rtn_stat)) + setErrorStatus(ossimErrorCodes::OSSIM_ERROR); +} + +//***************************************************************************** +// DESTRUCTOR +//***************************************************************************** +ossimWarpProjection::~ossimWarpProjection() +{ + if(theClientProjection) + { + delete theClientProjection; + theClientProjection = NULL; + } + if(theWarpTransform) + { + delete theWarpTransform; + theWarpTransform = NULL; + } + if(theAffineTransform) + { + delete theAffineTransform; + theAffineTransform = NULL; + } +} + +//***************************************************************************** +// METHOD: ossimWarpProjection::worldToLineSample() +//***************************************************************************** +void ossimWarpProjection::worldToLineSample (const ossimGpt& worldPoint, + ossimDpt& lineSampPt) const +{ + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimWarpProjection::worldToLineSample: Entering..." << std::endl; + + if (theClientProjection && theWarpTransform && theAffineTransform) + { + theClientProjection->worldToLineSample(worldPoint, lineSampPt); + theAffineTransform->inverse(lineSampPt); + theWarpTransform->inverse(lineSampPt); + } + else + { + lineSampPt.makeNan(); + } + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimWarpProjection::worldToLineSample: Returning..." << std::endl; +} + +//***************************************************************************** +// METHOD: ossimWarpProjection::lineSampleToWorld() +//***************************************************************************** +void ossimWarpProjection::lineSampleToWorld(const ossimDpt& lineSampPt, + ossimGpt& worldPt) const +{ + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimWarpProjection::lineSampleToWorld: Entering..." << std::endl; + + if (theClientProjection && theWarpTransform && theAffineTransform) + { + ossimDpt adjustedPt; + theWarpTransform->forward(adjustedPt); + theAffineTransform->forward(lineSampPt, adjustedPt); + theClientProjection->lineSampleToWorld(adjustedPt, worldPt); + } + else + { + worldPt.makeNan(); + } + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimWarpProjection::lineSampleToWorld: Returning..." << std::endl; +} + +//***************************************************************************** +// METHOD: ossimWarpProjection::lineSampleToWorld() +//***************************************************************************** +void ossimWarpProjection::lineSampleHeightToWorld(const ossimDpt& lineSampPt, + const double& hgt, + ossimGpt& worldPt) const +{ + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimWarpProjection::lineSampleHeightToWorld: Entering..." << std::endl; + + if (theClientProjection && theWarpTransform && theAffineTransform) + { + ossimDpt adjustedPt; + theAffineTransform->forward(lineSampPt, adjustedPt); + theWarpTransform->forward(adjustedPt); + theClientProjection->lineSampleHeightToWorld(adjustedPt, hgt, worldPt); + } + else + { + worldPt.makeNan(); + } + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimWarpProjection::lineSampleHeightToWorld: Returning..." << std::endl; +} + +//***************************************************************************** +// METHOD: ossimWarpProjection::print() +//***************************************************************************** +std::ostream& ossimWarpProjection::print(std::ostream& out) const +{ + if (theClientProjection && theWarpTransform && theAffineTransform) + { + out << + "ossimWarpProjection:\n" + << " Member theClientProjection: "; + theClientProjection->print(out); + + out << " Member theAffineTransform: " << *theAffineTransform << "\n" + << " Member theWarpTransform: " << *theWarpTransform << endl; + } + else + { + out << "ossimWarpProjection -- Not inititialized." << endl; + } + return out; +} + +std::ostream& operator<<(std::ostream& os, const ossimWarpProjection& m) +{ + return m.print(os); +} + +//***************************************************************************** +// METHOD: ossimWarpProjection::saveState() +//***************************************************************************** +bool ossimWarpProjection::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimWarpProjection::saveState: entering..." << std::endl; + + ossimString projPrefix = ossimString(prefix) + PROJECTION_PREFIX; + ossimString affinePrefix = ossimString(prefix) + AFFINE_PREFIX; + ossimString quadwarpPrefix = ossimString(prefix) + QUADWARP_PREFIX; + + if (theClientProjection && theWarpTransform && theAffineTransform) + { + theClientProjection->saveState(kwl, projPrefix.c_str()); + theAffineTransform->saveState(kwl, affinePrefix.c_str()); + theWarpTransform->saveState(kwl, quadwarpPrefix.c_str()); + } + + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimWarpProjection::saveState: returning..." << std::endl; + return ossimProjection::saveState(kwl, prefix); +} + +//***************************************************************************** +// METHOD: ossimWarpProjection::loadState() +//***************************************************************************** +bool ossimWarpProjection::loadState(const ossimKeywordlist& kwl, + const char* prefix) +{ + if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimWarpProjection::loadState: entering..." << std::endl; + +// bool good_load; +// int err_stat; + bool result = true; + + ossimString projPrefix = ossimString(prefix) + PROJECTION_PREFIX; + ossimString affinePrefix = ossimString(prefix) + AFFINE_PREFIX; + ossimString quadwarpPrefix = ossimString(prefix) + QUADWARP_PREFIX; + + if(theClientProjection) delete theClientProjection; + theClientProjection = (ossimProjection*)NULL; + + if (!theWarpTransform) + theWarpTransform = new ossimQuadTreeWarp(); + + if (!theAffineTransform) + theAffineTransform = new ossimAffineTransform(); + + theClientProjection = ossimProjectionFactoryRegistry::instance()->createProjection(kwl, projPrefix.c_str()); + + if(!theClientProjection) + { + result = false; + } + else + { + theWarpTransform->loadState(kwl, quadwarpPrefix.c_str()); + theAffineTransform->loadState(kwl, affinePrefix.c_str()); + } + + return ossimProjection::loadState(kwl, prefix); +} + +//***************************************************************************** +// METHOD: ossimWarpProjection::dup() +//***************************************************************************** +ossimObject* ossimWarpProjection::dup() const +{ + ossimKeywordlist kwl; + saveState(kwl); + return new ossimWarpProjection(kwl); +} + +//***************************************************************************** +// METHOD: +//***************************************************************************** +ossimGpt ossimWarpProjection::origin() const +{ + if (theClientProjection) + return theClientProjection->origin(); + return ossimGpt(0.0, 0.0, 0.0); +} + +//***************************************************************************** +// METHOD: +//***************************************************************************** +ossimDpt ossimWarpProjection::getMetersPerPixel() const +{ + if (theClientProjection) + return theClientProjection->getMetersPerPixel(); + return ossimDpt(OSSIM_NAN, OSSIM_NAN); +} + + +void ossimWarpProjection::setNewWarpTransform(ossim2dTo2dTransform* warp) +{ + if(warp) + { + if(theWarpTransform) + { + delete theWarpTransform; + theWarpTransform = NULL; + } + theWarpTransform = warp; + } +} + +void ossimWarpProjection::setNewAffineTransform(ossim2dTo2dTransform* affine) +{ + if(affine) + { + if(theAffineTransform) + { + delete theAffineTransform; + theAffineTransform = NULL; + } + theAffineTransform = affine; + } +} diff --git a/Utilities/OSSIM/ossim_core/projections/ossimWarpProjection.h b/Utilities/OSSIM/ossim_core/projections/ossimWarpProjection.h new file mode 100644 index 0000000000..703ffd64c9 --- /dev/null +++ b/Utilities/OSSIM/ossim_core/projections/ossimWarpProjection.h @@ -0,0 +1,146 @@ +//***************************************************************************** +// FILE: ossimWarpProjection.